@microsoft/fast-element 2.10.4 → 3.0.0-rc.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 (211) hide show
  1. package/CHANGELOG.md +52 -2
  2. package/README.md +244 -1
  3. package/dist/arrays/arrays.api.json +2621 -0
  4. package/dist/context/context.api.json +13 -13
  5. package/dist/declarative/declarative.api.json +8483 -0
  6. package/dist/di/di.api.json +16 -16
  7. package/dist/dts/__test__/helpers.d.ts +6 -0
  8. package/dist/dts/array-observer.d.ts +2 -0
  9. package/dist/dts/arrays.d.ts +2 -0
  10. package/dist/dts/attr.d.ts +1 -0
  11. package/dist/dts/binding/binding.d.ts +15 -5
  12. package/dist/dts/binding/one-time.d.ts +1 -1
  13. package/dist/dts/binding/one-way.d.ts +1 -1
  14. package/dist/dts/binding/signal.d.ts +6 -6
  15. package/dist/dts/binding/two-way.d.ts +2 -1
  16. package/dist/dts/binding.d.ts +7 -0
  17. package/dist/dts/components/attributes.d.ts +1 -4
  18. package/dist/dts/components/definition-schema-transforms.d.ts +9 -0
  19. package/dist/dts/components/element-controller.d.ts +80 -114
  20. package/dist/dts/components/element-hydration.d.ts +1 -1
  21. package/dist/dts/components/enable-hydration.d.ts +54 -0
  22. package/dist/dts/components/fast-definitions.d.ts +98 -46
  23. package/dist/dts/components/fast-element.d.ts +43 -16
  24. package/dist/dts/components/hydration-tracker.d.ts +83 -0
  25. package/dist/dts/components/hydration.d.ts +23 -53
  26. package/dist/dts/components/schema.d.ts +205 -0
  27. package/dist/dts/context.d.ts +13 -13
  28. package/dist/dts/css.d.ts +3 -0
  29. package/dist/dts/debug.d.ts +5 -1
  30. package/dist/dts/declarative/attribute-map.d.ts +58 -0
  31. package/dist/dts/declarative/debug.d.ts +4 -0
  32. package/dist/dts/declarative/index.d.ts +14 -0
  33. package/dist/dts/declarative/interfaces.d.ts +8 -0
  34. package/dist/dts/declarative/observer-map-utilities.d.ts +58 -0
  35. package/dist/dts/declarative/observer-map.d.ts +89 -0
  36. package/dist/dts/declarative/runtime.d.ts +5 -0
  37. package/dist/dts/declarative/syntax.d.ts +21 -0
  38. package/dist/dts/declarative/template-bridge.d.ts +33 -0
  39. package/dist/dts/declarative/template-parser.d.ts +98 -0
  40. package/dist/dts/declarative/template.d.ts +10 -0
  41. package/dist/dts/declarative/utilities.d.ts +358 -0
  42. package/dist/dts/di/di.d.ts +7 -7
  43. package/dist/dts/directives/children.d.ts +2 -0
  44. package/dist/dts/directives/node-observation.d.ts +2 -0
  45. package/dist/dts/directives/ref.d.ts +2 -0
  46. package/dist/dts/directives/repeat.d.ts +4 -0
  47. package/dist/dts/directives/slotted.d.ts +2 -0
  48. package/dist/dts/directives/when.d.ts +3 -0
  49. package/dist/dts/dom-policy.d.ts +23 -5
  50. package/dist/dts/dom.d.ts +4 -16
  51. package/dist/dts/html.d.ts +5 -0
  52. package/dist/dts/hydration/diagnostics.d.ts +93 -0
  53. package/dist/dts/hydration/hydration-debugger.d.ts +35 -0
  54. package/dist/dts/hydration/messages.d.ts +62 -0
  55. package/dist/dts/hydration/runtime.d.ts +7 -0
  56. package/dist/dts/hydration/target-builder.d.ts +40 -12
  57. package/dist/dts/hydration.d.ts +18 -0
  58. package/dist/dts/index.d.ts +42 -42
  59. package/dist/dts/index.debug.d.ts +0 -1
  60. package/dist/dts/index.rollup.debug.d.ts +0 -1
  61. package/dist/dts/interfaces.d.ts +2 -49
  62. package/dist/dts/observable.d.ts +3 -6
  63. package/dist/dts/observation/arrays.d.ts +1 -1
  64. package/dist/dts/observation/observable.d.ts +3 -3
  65. package/dist/dts/observation/update-queue.d.ts +1 -1
  66. package/dist/dts/platform.d.ts +45 -8
  67. package/dist/dts/registry.d.ts +1 -0
  68. package/dist/dts/render.d.ts +7 -0
  69. package/dist/dts/schema.d.ts +1 -0
  70. package/dist/dts/state/exports.d.ts +1 -1
  71. package/dist/dts/state/state.d.ts +2 -2
  72. package/dist/dts/styles/css-directive.d.ts +5 -12
  73. package/dist/dts/styles/css.d.ts +5 -7
  74. package/dist/dts/styles/element-styles.d.ts +0 -10
  75. package/dist/dts/styles.d.ts +6 -0
  76. package/dist/dts/templating/compiler.d.ts +1 -1
  77. package/dist/dts/templating/html-binding-directive.d.ts +10 -2
  78. package/dist/dts/templating/html-directive.d.ts +19 -1
  79. package/dist/dts/templating/hydration-view.d.ts +130 -0
  80. package/dist/dts/templating/render.d.ts +1 -1
  81. package/dist/dts/templating/repeat.d.ts +1 -1
  82. package/dist/dts/templating/template.d.ts +15 -7
  83. package/dist/dts/templating/view.d.ts +25 -102
  84. package/dist/dts/templating.d.ts +10 -0
  85. package/dist/dts/testing/exports.d.ts +2 -2
  86. package/dist/dts/testing/fakes.d.ts +4 -4
  87. package/dist/dts/updates.d.ts +1 -0
  88. package/dist/dts/volatile.d.ts +2 -0
  89. package/dist/esm/__test__/helpers.js +22 -0
  90. package/dist/esm/__test__/setup-node.js +18 -0
  91. package/dist/esm/array-observer.js +1 -0
  92. package/dist/esm/arrays.js +1 -0
  93. package/dist/esm/attr.js +1 -0
  94. package/dist/esm/binding/normalize.js +1 -1
  95. package/dist/esm/binding/signal.js +4 -4
  96. package/dist/esm/binding/two-way.js +3 -3
  97. package/dist/esm/binding.js +4 -0
  98. package/dist/esm/components/attributes.js +18 -11
  99. package/dist/esm/components/definition-schema-transforms.js +23 -0
  100. package/dist/esm/components/element-controller.js +206 -270
  101. package/dist/esm/components/element-hydration.js +1 -1
  102. package/dist/esm/components/enable-hydration.js +124 -0
  103. package/dist/esm/components/fast-definitions.js +219 -56
  104. package/dist/esm/components/fast-element.js +18 -27
  105. package/dist/esm/components/hydration-tracker.js +122 -0
  106. package/dist/esm/components/hydration.js +137 -140
  107. package/dist/esm/components/schema.js +253 -0
  108. package/dist/esm/context.js +6 -6
  109. package/dist/esm/css.js +3 -0
  110. package/dist/esm/debug.js +27 -26
  111. package/dist/esm/declarative/attribute-map.js +122 -0
  112. package/dist/esm/declarative/debug.js +4 -0
  113. package/dist/esm/declarative/index.js +4 -0
  114. package/dist/esm/declarative/interfaces.js +9 -0
  115. package/dist/esm/declarative/observer-map-utilities.js +565 -0
  116. package/dist/esm/declarative/observer-map.js +216 -0
  117. package/dist/esm/declarative/runtime.js +14 -0
  118. package/dist/esm/declarative/syntax.js +36 -0
  119. package/dist/esm/declarative/template-bridge.js +160 -0
  120. package/dist/esm/declarative/template-parser.js +306 -0
  121. package/dist/esm/declarative/template.js +143 -0
  122. package/dist/esm/declarative/utilities.js +1069 -0
  123. package/dist/esm/di/di.js +8 -9
  124. package/dist/esm/directives/children.js +1 -0
  125. package/dist/esm/directives/node-observation.js +1 -0
  126. package/dist/esm/directives/ref.js +1 -0
  127. package/dist/esm/directives/repeat.js +1 -0
  128. package/dist/esm/directives/slotted.js +1 -0
  129. package/dist/esm/directives/when.js +1 -0
  130. package/dist/esm/dom-policy.js +35 -6
  131. package/dist/esm/dom.js +1 -1
  132. package/dist/esm/html.js +2 -0
  133. package/dist/esm/hydration/diagnostics.js +50 -0
  134. package/dist/esm/hydration/hydration-debugger.js +112 -0
  135. package/dist/esm/hydration/messages.js +84 -0
  136. package/dist/esm/hydration/runtime.js +33 -0
  137. package/dist/esm/hydration/target-builder.js +144 -91
  138. package/dist/esm/hydration.js +6 -0
  139. package/dist/esm/index.debug.js +2 -1
  140. package/dist/esm/index.js +38 -29
  141. package/dist/esm/index.rollup.debug.js +3 -2
  142. package/dist/esm/index.rollup.js +1 -1
  143. package/dist/esm/interfaces.js +2 -45
  144. package/dist/esm/metadata.js +2 -8
  145. package/dist/esm/observable.js +1 -4
  146. package/dist/esm/observation/arrays.js +1 -1
  147. package/dist/esm/observation/notifier.js +2 -4
  148. package/dist/esm/observation/observable.js +5 -5
  149. package/dist/esm/observation/update-queue.js +47 -58
  150. package/dist/esm/platform.js +31 -30
  151. package/dist/esm/registry.js +1 -0
  152. package/dist/esm/render.js +1 -0
  153. package/dist/esm/schema.js +1 -0
  154. package/dist/esm/state/exports.js +1 -1
  155. package/dist/esm/styles/css-directive.js +1 -2
  156. package/dist/esm/styles/css.js +15 -56
  157. package/dist/esm/styles/element-styles.js +69 -15
  158. package/dist/esm/styles.js +2 -0
  159. package/dist/esm/templating/html-binding-directive.js +11 -9
  160. package/dist/esm/templating/hydration-view.js +228 -0
  161. package/dist/esm/templating/render.js +39 -18
  162. package/dist/esm/templating/repeat.js +69 -33
  163. package/dist/esm/templating/template.js +7 -7
  164. package/dist/esm/templating/view.js +25 -234
  165. package/dist/esm/templating.js +7 -0
  166. package/dist/esm/testing/exports.js +2 -2
  167. package/dist/esm/testing/fixture.js +2 -2
  168. package/dist/esm/testing/timeout.js +2 -2
  169. package/dist/esm/updates.js +1 -0
  170. package/dist/esm/volatile.js +1 -0
  171. package/dist/fast-element.api.json +14389 -11138
  172. package/dist/fast-element.d.ts +3651 -809
  173. package/dist/fast-element.debug.js +5666 -4722
  174. package/dist/fast-element.debug.min.js +2 -2
  175. package/dist/fast-element.js +5394 -4381
  176. package/dist/fast-element.min.js +2 -2
  177. package/dist/fast-element.untrimmed.d.ts +923 -472
  178. package/dist/hydration/hydration.api.json +6460 -0
  179. package/dist/styles/styles.api.json +2672 -0
  180. package/package.json +165 -45
  181. package/ARCHITECTURE_FASTELEMENT.md +0 -63
  182. package/ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md +0 -36
  183. package/ARCHITECTURE_INTRO.md +0 -10
  184. package/ARCHITECTURE_OVERVIEW.md +0 -52
  185. package/ARCHITECTURE_UPDATES.md +0 -11
  186. package/CHANGELOG.json +0 -2275
  187. package/DESIGN.md +0 -510
  188. package/api-extractor.context.json +0 -14
  189. package/api-extractor.di.json +0 -14
  190. package/biome.json +0 -4
  191. package/dist/dts/components/install-hydration.d.ts +0 -1
  192. package/dist/dts/pending-task.d.ts +0 -32
  193. package/dist/dts/styles/css-binding-directive.d.ts +0 -60
  194. package/dist/dts/templating/install-hydratable-view-templates.d.ts +0 -1
  195. package/dist/esm/components/install-hydration.js +0 -3
  196. package/dist/esm/pending-task.js +0 -28
  197. package/dist/esm/polyfills.js +0 -60
  198. package/dist/esm/styles/css-binding-directive.js +0 -76
  199. package/dist/esm/templating/install-hydratable-view-templates.js +0 -23
  200. package/docs/ACKNOWLEDGEMENTS.md +0 -12
  201. package/docs/api-report.api.md +0 -1122
  202. package/docs/context/api-report.api.md +0 -69
  203. package/docs/di/api-report.api.md +0 -315
  204. package/docs/fast-element-2-changes.md +0 -15
  205. package/playwright.config.ts +0 -26
  206. package/scripts/run-api-extractor.js +0 -51
  207. package/test/index.html +0 -11
  208. package/test/main.ts +0 -104
  209. package/test/vite.config.ts +0 -19
  210. package/tsconfig.api-extractor.json +0 -6
  211. /package/dist/dts/{polyfills.d.ts → __test__/setup-node.d.ts} +0 -0
package/DESIGN.md DELETED
@@ -1,510 +0,0 @@
1
- # FAST Element – Design Overview
2
-
3
- This document is a contributor-oriented guide to the architecture of `@microsoft/fast-element`. It synthesises the individual architecture documents into a single entry point and explains how all the pieces fit together.
4
-
5
- For deep dives into specific areas, see the linked detailed documents.
6
-
7
- ---
8
-
9
- ## Table of Contents
10
-
11
- 1. [High-Level Overview](#high-level-overview)
12
- 2. [Core Concepts](#core-concepts)
13
- - [FAST Global](#fast-global)
14
- - [FASTElement & ElementController](#fastelement--elementcontroller)
15
- - [Observables & Notifiers](#observables--notifiers)
16
- - [Bindings](#bindings)
17
- - [html Tagged Template Literal](#html-tagged-template-literal)
18
- - [ViewTemplate & Compiler](#viewtemplate--compiler)
19
- - [Views & Behaviors](#views--behaviors)
20
- - [Updates Queue](#updates-queue)
21
- - [Styles](#styles)
22
- - [Dependency Injection (DI)](#dependency-injection-di)
23
- - [Context Protocol](#context-protocol)
24
- - [State Helpers](#state-helpers)
25
- 3. [Data Flow Diagrams](#data-flow-diagrams)
26
- - [Module Load & Registration](#module-load--registration)
27
- - [FASTElement Lifecycle](#fastelement-lifecycle)
28
- - [Template Pipeline](#template-pipeline)
29
- - [Observable Change Propagation](#observable-change-propagation)
30
- 4. [How the Pieces Fit Together](#how-the-pieces-fit-together)
31
- 5. [Package Layout](#package-layout)
32
- 6. [Detailed Architecture Documents](#detailed-architecture-documents)
33
-
34
- ---
35
-
36
- ## High-Level Overview
37
-
38
- `@microsoft/fast-element` is a lightweight library for building standards-based Custom Elements (Web Components). Its key responsibilities are:
39
-
40
- | Concern | What FAST provides |
41
- |---|---|
42
- | Element authoring | `FASTElement` base class + `@customElement`, `@attr`, `@observable` decorators |
43
- | Reactive data binding | `Observable`, `ExpressionNotifier`, `oneWay`/`oneTime`/`listener` bindings |
44
- | Declarative templating | `html` tagged template literal → `ViewTemplate` → compiled `HTMLView` |
45
- | Async DOM updates | `Updates` queue (batched, `requestAnimationFrame`-aligned) |
46
- | Scoped styles | `css` tagged template literal → `ElementStyles` → `adoptedStylesheets` / `<style>` |
47
- | Dependency injection | `DI` container, `@inject`, `@singleton`, `@transient`, resolvers |
48
- | Context protocol | W3C community Context protocol (`Context.create`, `Context.for`) |
49
- | Reactive state helpers | `state()`, `watch()` (beta) |
50
-
51
- The library's kernel (the `FAST` global, the `Updates` queue, and the `Observable` system) is stored on `globalThis.FAST` and can be shared across multiple versions of the library loaded on the same page.
52
-
53
- ---
54
-
55
- ## Core Concepts
56
-
57
- ### FAST Global
58
-
59
- **File**: `src/platform.ts`, `src/interfaces.ts`
60
-
61
- `FAST` is a singleton object attached to `globalThis`. It provides:
62
-
63
- - `FAST.getById(id, initializer)` – shared kernel slot registry (used to share the update queue and observable system across FAST instances)
64
- - `FAST.warn(code, values)` / `FAST.error(code, values)` – structured diagnostic messages
65
- - `FAST.addMessages(dict)` – registers human-readable debug messages (imported by `src/debug.ts`)
66
-
67
- The `KernelServiceId` object controls which numeric/string keys are used for shared services. Three modes are supported via a `fast-kernel` attribute on the current `<script>` tag:
68
-
69
- | Mode | Behaviour |
70
- |---|---|
71
- | `share` | Share the kernel across any FAST version |
72
- | `share-v2` | Share only with other v2 instances |
73
- | *(default)* | Fully isolated instance with a random postfix |
74
-
75
- ---
76
-
77
- ### FASTElement & ElementController
78
-
79
- **Files**: `src/components/fast-element.ts`, `src/components/element-controller.ts`, `src/components/fast-definitions.ts`
80
-
81
- `FASTElement` is a thin mixin applied on top of `HTMLElement`. It:
82
-
83
- 1. Calls `ElementController.forCustomElement(this)` in its `constructor` to create or locate the element's controller.
84
- 2. Delegates all lifecycle hooks to the controller:
85
- - `connectedCallback` → `$fastController.connect()`
86
- - `disconnectedCallback` → `$fastController.disconnect()`
87
- - `attributeChangedCallback` → `$fastController.onAttributeChangedCallback()`
88
-
89
- `ElementController` is the real workhorse. It:
90
-
91
- - Extends `PropertyChangeNotifier` so the element itself participates in the observable system.
92
- - Holds the element's `FASTElementDefinition` (name, template, styles, observed attributes).
93
- - Manages a `Stages` state machine: `disconnected → connecting → connected → disconnecting → disconnected`.
94
- - On `connect()`: restores pre-upgrade observable values, calls `connectedCallback` on all `HostBehavior`s, renders the template into the shadow root, and applies styles.
95
- - On `disconnect()`: calls `disconnectedCallback` on behaviors, unbinds the view.
96
- - Exposes `addBehavior` / `removeBehavior` for dynamic `HostBehavior` management (used by `ElementStyles`).
97
-
98
- `FASTElementDefinition` wraps all the metadata for a custom element class: its tag name, template, styles, and observed attribute list. It is created by `FASTElement.compose()` and registered globally via `fastElementRegistry`.
99
-
100
- ---
101
-
102
- ### Observables & Notifiers
103
-
104
- **Files**: `src/observation/observable.ts`, `src/observation/notifier.ts`, `src/observation/arrays.ts`
105
-
106
- #### Property observability
107
-
108
- `Observable.defineProperty(target, name)` (or the `@observable` decorator) replaces a plain property with a getter/setter pair via `Reflect.defineProperty`. The setter:
109
-
110
- 1. Stores the new value in a backing slot.
111
- 2. Calls `Observable.getNotifier(this).notify(name)` to fan out to subscribers.
112
-
113
- `Observable.getNotifier(object)` returns the `PropertyChangeNotifier` for an object, creating one on demand. Notifiers are stored in a `WeakMap` so they don't prevent GC.
114
-
115
- #### SubscriberSet / PropertyChangeNotifier
116
-
117
- `SubscriberSet` is an optimised set that stores the first two subscribers inline (avoiding heap allocations for the common 1–2 subscriber case) and falls back to an array. `PropertyChangeNotifier` extends `SubscriberSet` to support per-property subscriptions.
118
-
119
- #### ExpressionNotifier (binding observer)
120
-
121
- `Observable.binding(expression, subscriber)` creates an `ExpressionNotifier`. When `observe(source, context)` is called it:
122
-
123
- 1. Pushes itself as the _current watcher_ onto a thread-local stack.
124
- 2. Evaluates the expression (e.g., `x => x.name`).
125
- 3. Any `Observable`-tracked property get encountered during evaluation subscribes the notifier to that property's notifier automatically.
126
- 4. Pops itself. Future changes to any accessed property trigger `handleChange` on the subscriber.
127
-
128
- This gives FAST automatic, fine-grained dependency tracking without explicit declarations.
129
-
130
- ---
131
-
132
- ### Bindings
133
-
134
- **Files**: `src/binding/binding.ts`, `src/binding/one-way.ts`, `src/binding/one-time.ts`, `src/binding/normalize.ts`
135
-
136
- `Binding` is an abstract class that pairs an `Expression` (arrow function) with a `DOMPolicy` and a volatility flag. Concrete subclasses implement `createObserver(subscriber, directive)`:
137
-
138
- | Binding | Observer behaviour |
139
- |---|---|
140
- | `oneWay` | Creates an `ExpressionNotifier`; tracks dependencies; re-evaluates on change |
141
- | `oneTime` | Evaluates once during `bind()`, returns immediately |
142
- | `listener` | Same as `oneWay` but attaches as a DOM event handler |
143
-
144
- `normalizeBinding(value)` converts raw arrow functions or static values into a `Binding` object.
145
-
146
- ---
147
-
148
- ### html Tagged Template Literal
149
-
150
- **File**: `src/templating/template.ts`
151
-
152
- The `html` tag is the primary authoring API:
153
-
154
- ```typescript
155
- const template = html<MyElement>`
156
- <div>${x => x.label}</div>
157
- <button @click="${x => x.handleClick}">OK</button>
158
- `;
159
- ```
160
-
161
- When the tag function is called it invokes `ViewTemplate.create(strings, values)` (static method) which:
162
-
163
- 1. Iterates the template string fragments (`strings`) paired with interpolated values.
164
- 2. For each value:
165
- - A plain function → wrapped in `HTMLBindingDirective(oneWay(fn))`
166
- - A `Binding` instance → wrapped in `HTMLBindingDirective(binding)`
167
- - A registered `HTMLDirective` instance → used directly
168
- - Anything else → wrapped as a `oneTime` static binding
169
- 3. Calls `directive.createHTML(add)` which returns a **placeholder string** (a special attribute or marker containing the factory's unique ID).
170
- 4. Concatenates all static strings and placeholders into a single HTML string.
171
- 5. Returns a `ViewTemplate(html, factories)` – the factories dictionary maps IDs to `ViewBehaviorFactory` instances.
172
-
173
- No DOM nodes are created at this point; compilation is deferred.
174
-
175
- See [ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md](./ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md) for more detail on directives and the `Markup`/`Parser` helpers.
176
-
177
- ---
178
-
179
- ### ViewTemplate & Compiler
180
-
181
- **Files**: `src/templating/template.ts`, `src/templating/compiler.ts`, `src/templating/markup.ts`
182
-
183
- `ViewTemplate.compile()` is called lazily the first time the template is rendered. It delegates to `Compiler.compile(html, factories, policy)`:
184
-
185
- 1. Sets the HTML string as the `innerHTML` of a `<template>` element (letting the browser parse the DOM once).
186
- 2. Traverses the resulting `DocumentFragment` depth-first.
187
- 3. For each node, calls `compileAttributes()` which scans attributes for factory placeholder IDs.
188
- 4. When a placeholder is found, it associates the matching `ViewBehaviorFactory` with the node's structural ID (a dot-separated path like `"r.2.0"` meaning "third child of the root's second child").
189
- 5. Lazily-resolved descriptors (using `Object.defineProperty` on a prototype) allow `HTMLView` to look up any target node via a chain of `childNodes` accesses without pre-walking the tree for every view instance.
190
- 6. Returns a `CompilationContext` that implements `HTMLTemplateCompilationResult`.
191
-
192
- `CompilationContext.createView(hostBindingTarget?)` clones the compiled `DocumentFragment`, instantiates behaviors from factories, and returns an `HTMLView`.
193
-
194
- ---
195
-
196
- ### Views & Behaviors
197
-
198
- **Files**: `src/templating/view.ts`, `src/templating/html-directive.ts`
199
-
200
- `HTMLView` implements `ElementView` / `SyntheticView`. It:
201
-
202
- - Holds the cloned `DocumentFragment` nodes.
203
- - Has a `targets` map (resolved lazily) from structural node IDs to live `Node` references.
204
- - `bind(source, context)` iterates all `ViewBehavior` instances and calls `behavior.bind(controller)`.
205
- - `unbind()` calls `behavior.unbind()` on each behavior and clears the source.
206
- - `appendTo(node)` / `insertBefore(node)` / `remove()` move its DOM nodes in the tree.
207
-
208
- `ViewBehavior` is the runtime unit of work attached to a specific DOM node. Examples:
209
-
210
- | Directive | Created `ViewBehavior` | Effect |
211
- |---|---|---|
212
- | `HTMLBindingDirective` | `BindingBehavior` | Evaluates the binding; updates the DOM aspect (attribute / property / event / content / tokenList) |
213
- | `when` | `WhenBehavior` | Conditionally inserts a child view |
214
- | `repeat` | `RepeatBehavior` | Renders a list of child views |
215
- | `ref` | `RefDirective` | Writes the element reference onto the source |
216
- | `children` / `slotted` | `ChildrenDirective` / `SlottedDirective` | Observes DOM mutations |
217
-
218
- `ViewBehaviorFactory` (created at template-authoring time) is the blueprint; `ViewBehavior` (created per `HTMLView` instance) is the live runtime object.
219
-
220
- See [src/templating/TEMPLATE-BINDINGS.md](./src/templating/TEMPLATE-BINDINGS.md) for the full binding pipeline including `DOMAspect` routing and two-way binding.
221
-
222
- ---
223
-
224
- ### Updates Queue
225
-
226
- **File**: `src/observation/update-queue.ts`
227
-
228
- **Exported as**: `Updates`
229
-
230
- `Updates` is a shared, batched task queue used to synchronise writes to the DOM. It is stored on the `FAST` global (under `KernelServiceId.updateQueue`) so multiple FAST instances on the same page share a single flush cycle.
231
-
232
- - `Updates.enqueue(callable)` – schedules a task for the next batch.
233
- - `Updates.process()` – forces immediate synchronous flush (useful in tests).
234
- - `Updates.next()` – returns a `Promise` that resolves after the next flush.
235
- - `Updates.setMode(isAsync)` – toggle async (default) vs. synchronous mode.
236
-
237
- In async mode, the first `enqueue` call schedules a `requestAnimationFrame` callback that drains up to 1024 tasks per frame. Errors in tasks are deferred via `setTimeout` so they don't abort the remaining tasks.
238
-
239
- Observable setters and `attributeChangedCallback` enqueue their DOM mutations through `Updates`, ensuring that multiple synchronous property changes result in only one DOM update per frame.
240
-
241
- See [ARCHITECTURE_UPDATES.md](./ARCHITECTURE_UPDATES.md) for more detail.
242
-
243
- ---
244
-
245
- ### Styles
246
-
247
- **Files**: `src/styles/css.ts`, `src/styles/element-styles.ts`, `src/styles/css-directive.ts`
248
-
249
- The `css` tag (analogous to `html`) builds `ElementStyles` objects. During `ElementController.connect()`, styles are applied to the element's shadow root either via `adoptedStylesheets` (preferred) or an appended `<style>` node, depending on platform support. Styles can also contain dynamic `CSSDirective`s (e.g., CSS custom property bindings) that register as `HostBehavior`s and connect/disconnect alongside the element.
250
-
251
- ---
252
-
253
- ### Dependency Injection (DI)
254
-
255
- **File**: `src/di/di.ts`
256
-
257
- FAST ships a full hierarchical DI container inspired by Aurelia. Key types:
258
-
259
- | Type | Role |
260
- |---|---|
261
- | `Container` | Resolves dependencies; parent containers are queried if a key is not found locally |
262
- | `Resolver` | Maps a key to a creation strategy (singleton, transient, callback, …) |
263
- | `Registration` | Produces a `Resolver` when registered in a container |
264
- | `Factory` | Constructs instances; supports `Transformer`s for post-construction mutation |
265
-
266
- Containers are typically attached to DOM elements and walk the DOM hierarchy. DI keys are classes, interfaces, or `Context`-like tokens. Constructor parameters are annotated with the `@inject(key)` decorator (or use `@singleton` / `@transient` to declare the class's own registration).
267
-
268
- See `docs/di/api-report.api.md` for the full public API surface.
269
-
270
- ---
271
-
272
- ### Context Protocol
273
-
274
- **File**: `src/context.ts`
275
-
276
- `Context` implements the [W3C Community Context Protocol](https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md). A `FASTContext<T>` object is both a DI key and a decorator:
277
-
278
- - `Context.create<T>(name, initialValue?)` – creates a named context token.
279
- - `Context.for<T>(name)` – gets or creates a globally-registered context token.
280
- - `context.provide(target, value)` – registers a provider on a DOM element.
281
- - `context.get(target)` – dispatches a `context-request` event and returns the synchronously provided value (or `initialValue`).
282
- - `context.request(target, callback, multiple?)` – async / multi-provider variant.
283
- - Used as a `@decorator` on class properties or constructor parameters to declare a context dependency.
284
-
285
- ---
286
-
287
- ### State Helpers
288
-
289
- **Files**: `src/state/state.ts`, `src/state/watch.ts`
290
-
291
- > **Status**: beta
292
-
293
- `state<T>(initialValue, options?)` creates a reactive `State<T>` object – a callable that returns the current value. The state's `.current` property is a FAST observable, so templates or `ExpressionNotifier`s that read it will automatically re-evaluate when it changes.
294
-
295
- `watch(object, subscriber)` deeply subscribes to all observable properties and array mutations on an object graph, returning a `Disposable`.
296
-
297
- ---
298
-
299
- ## Data Flow Diagrams
300
-
301
- ### Module Load & Registration
302
-
303
- ```mermaid
304
- flowchart TD
305
- A([Browser loads script]) --> B[FAST global created on globalThis]
306
- B --> C[FASTElement subclass executes FASTElement.compose]
307
- C --> D[Observable decorators register accessors on the prototype]
308
- C --> E[Attribute decorators push AttributeDefinition to the class]
309
- C --> F[html tag is evaluated – ViewTemplate created with factories]
310
- D & E & F --> G[FASTElement.define registers with the Custom Element Registry]
311
- G --> H[Browser detects element in DOM]
312
- H --> I([FASTElement lifecycle begins])
313
- ```
314
-
315
- ### FASTElement Lifecycle
316
-
317
- ```mermaid
318
- flowchart TD
319
- CTOR[constructor] --> EC[ElementController.forCustomElement creates or locates the controller]
320
- EC --> ATTACH[Controller captures element + definition, sets $fastController]
321
-
322
- CONN[connectedCallback] --> STAGE[stage = connecting]
323
- STAGE --> OBS[Restore pre-upgrade observable values]
324
- OBS --> BEHAV[Connect HostBehaviors]
325
- BEHAV --> RENDER[renderTemplate → ViewTemplate.render → HTMLView.appendTo shadow root]
326
- RENDER --> STYLES[Apply ElementStyles to shadow root]
327
- STYLES --> DONE[stage = connected]
328
-
329
- ATTR[attributeChangedCallback] --> ACD[AttributeDefinition.onAttributeChangedCallback]
330
- ACD --> ENQ[Updates.enqueue – reflect new value via Observable accessor]
331
-
332
- DISC[disconnectedCallback] --> DBEHAV[Disconnect HostBehaviors]
333
- DBEHAV --> UNBIND[HTMLView.unbind]
334
- UNBIND --> DSTAGE[stage = disconnected]
335
- ```
336
-
337
- ### Template Pipeline
338
-
339
- ```mermaid
340
- flowchart LR
341
- TAG["html\`...\` tag call"]
342
- CREATE["ViewTemplate.create() (static)\nBuilds HTML string with\nfactory placeholder IDs\nand factories dictionary"]
343
- LAZY["First render call\nViewTemplate.create() / render()"]
344
- COMPILE["ViewTemplate.compile()\n→ Compiler.compile()\nParses <template> innerHTML\nBuilds CompilationContext\nwith node ID descriptors"]
345
- CLONE["CompilationContext.createView()\nClones DocumentFragment\nInstantiates ViewBehaviors"]
346
- VIEW["HTMLView\nDOM nodes + behaviors"]
347
- BIND["HTMLView.bind(source, context)\nEach ViewBehavior.bind(controller)\nEvaluates expressions\nWrites to DOM"]
348
-
349
- TAG --> CREATE
350
- CREATE --> LAZY
351
- LAZY --> COMPILE
352
- COMPILE --> CLONE
353
- CLONE --> VIEW
354
- VIEW --> BIND
355
- ```
356
-
357
- ### Observable Change Propagation
358
-
359
- ```mermaid
360
- flowchart TD
361
- SET["element.property = newValue\n(Observable setter)"]
362
- NOTIFY["PropertyChangeNotifier.notify(propertyName)"]
363
- SUBS["For each Subscriber in SubscriberSet\nsubscriber.handleChange(subject, propertyName)"]
364
- ENQ["Updates.enqueue(binding task)"]
365
- RAF["requestAnimationFrame fires\nUpdates.process()"]
366
- EVAL["ExpressionNotifier re-evaluates expression"]
367
- DOM["DOM aspect updated\n(attribute / property / content / event)"]
368
-
369
- SET --> NOTIFY
370
- NOTIFY --> SUBS
371
- SUBS --> ENQ
372
- ENQ --> RAF
373
- RAF --> EVAL
374
- EVAL --> GUARD{"Controller still bound?"}
375
- GUARD -->|yes| DOM
376
- GUARD -->|no| DROP["Notification dropped\n(stale observer)"]
377
- ```
378
-
379
- > **Stale notification guard**: When a view is unbound (e.g., after a parent `when` directive tears down a child element), the coupled source lifetime optimisation may leave expression observers subscribed to the child element's properties. If a property change fires while the view is inactive, `HTMLBindingDirective.handleChange` and `RenderBehavior.handleChange` check `controller.isBound` and skip the update to prevent evaluating expressions against a null source.
380
-
381
- ---
382
-
383
- ## How the Pieces Fit Together
384
-
385
- Below is a conceptual map of the major subsystems and their relationships:
386
-
387
- ```
388
- ┌──────────────────────────────────────────────────────────────────────────────┐
389
- │ FAST Global (globalThis.FAST) │
390
- │ KernelServiceIds → Updates queue, Observable system, Element registry │
391
- └────────────────────┬─────────────────────────────────────────────────────────┘
392
- │ shared kernel slots
393
- ┌───────────┴───────────┐
394
- │ │
395
- ┌────────▼──────────┐ ┌────────▼────────────────────┐
396
- │ Observable / │ │ Updates queue │
397
- │ ExpressionNotifier│ │ (rAF-batched task runner) │
398
- │ SubscriberSet │ └────────────────────────────-─┘
399
- └────────┬──────────┘ ▲
400
- │ dependency tracking │ enqueue
401
- ▼ │
402
- ┌────────────────────────────────┴──────────────────────────────┐
403
- │ Binding system │
404
- │ oneWay / oneTime / listener → Binding → ExpressionObserver │
405
- └────────────────────────┬──────────────────────────────────────┘
406
- │ drives
407
- ┌────────────────────────▼──────────────────────────────────────┐
408
- │ Templating pipeline │
409
- │ html tag → ViewTemplate → Compiler → CompilationContext │
410
- │ createView → HTMLView → ViewBehaviors (bind/update DOM) │
411
- └────────────────────────┬──────────────────────────────────────┘
412
- │ owned by
413
- ┌────────────────────────▼──────────────────────────────────────┐
414
- │ ElementController │
415
- │ Lifecycle (connect/disconnect/attr) • Styles • Behaviors │
416
- └────────────────────────┬──────────────────────────────────────┘
417
- │ wraps
418
- ┌────────────────────────▼──────────────────────────────────────┐
419
- │ FASTElement (HTMLElement subclass) │
420
- │ + FASTElementDefinition (metadata: name, template, styles) │
421
- └───────────────────────────────────────────────────────────────┘
422
- │ optional higher-level services
423
- ├──────────────────────────────────────────────┐
424
- ┌────────▼──────────┐ ┌──────────▼──────────┐
425
- │ DI container │ │ Context protocol │
426
- │ (di/di.ts) │ │ (context.ts) │
427
- └───────────────────┘ └─────────────────────┘
428
- ```
429
-
430
- **Authoring flow summary**:
431
-
432
- 1. Developer writes a class extending `FASTElement`, decorates properties with `@observable` / `@attr`, and calls `FASTElement.define({ name, template, styles })`.
433
- 2. `FASTElement.define` → `FASTElementDefinition.compose(...).define()` registers the element with the Custom Element Registry.
434
- 3. When the browser upgrades the element, `ElementController.forCustomElement(element)` is called in the constructor.
435
- 4. On `connectedCallback`, the controller renders the template (`ViewTemplate.render`) into the shadow root. Compilation is lazy: the first render call triggers `Compiler.compile()`, subsequent calls clone the already-compiled `DocumentFragment`.
436
- 5. `HTMLView.bind(source)` wires up each `ViewBehavior`. `oneWay` bindings create `ExpressionNotifier`s that track observable dependencies automatically.
437
- 6. When an observed property changes, its notifier fans out to all subscribers. Each binding enqueues a DOM update via `Updates`. The next animation frame drains the queue and applies the mutations.
438
- 7. On `disconnectedCallback`, `HTMLView.unbind()` tears down all bindings; behaviors disconnect; styles are removed.
439
-
440
- ---
441
-
442
- ## Package Layout
443
-
444
- ```
445
- src/
446
- ├── interfaces.ts # Core types: Callable, Constructable, FASTGlobal, Message codes
447
- ├── platform.ts # FAST global initialisation, KernelServiceId, TypeRegistry
448
- ├── dom.ts # DOMAspect enum, DOMPolicy, DOMSink
449
- ├── dom-policy.ts # Default DOM security policy (TrustedTypes integration)
450
- ├── metadata.ts # Reflect-based metadata helpers
451
- ├── utilities.ts # UnobservableMutationObserver and other helpers
452
- ├── debug.ts # Adds human-readable error messages to FAST global
453
- ├── observation/
454
- │ ├── observable.ts # Observable, @observable, ExpressionNotifier, ExecutionContext
455
- │ ├── notifier.ts # Subscriber, Notifier, SubscriberSet, PropertyChangeNotifier
456
- │ ├── arrays.ts # ArrayObserver, Splice, SpliceStrategy
457
- │ └── update-queue.ts # Updates (UpdateQueue)
458
- ├── binding/
459
- │ ├── binding.ts # Binding abstract base class, BindingDirective
460
- │ ├── one-way.ts # oneWay, listener
461
- │ ├── one-time.ts # oneTime
462
- │ └── normalize.ts # normalizeBinding helper
463
- ├── templating/
464
- │ ├── template.ts # ViewTemplate, html tag, InlineTemplateDirective
465
- │ ├── compiler.ts # Compiler, CompilationContext
466
- │ ├── view.ts # HTMLView, ElementView, SyntheticView
467
- │ ├── html-directive.ts # HTMLDirective, ViewBehavior, ViewBehaviorFactory
468
- │ ├── html-binding-directive.ts # HTMLBindingDirective
469
- │ ├── markup.ts # Markup placeholders, Parser
470
- │ ├── when.ts # when directive
471
- │ ├── repeat.ts # repeat directive
472
- │ ├── ref.ts # ref directive
473
- │ ├── render.ts # render directive
474
- │ ├── children.ts # children directive
475
- │ ├── slotted.ts # slotted directive
476
- │ └── TEMPLATE-BINDINGS.md
477
- ├── styles/
478
- │ ├── css.ts # css tag
479
- │ ├── element-styles.ts # ElementStyles
480
- │ ├── css-directive.ts # CSSDirective, @cssDirective
481
- │ └── host.ts # HostBehavior, HostController
482
- ├── components/
483
- │ ├── fast-element.ts # FASTElement, @customElement
484
- │ ├── element-controller.ts # ElementController, Stages
485
- │ ├── fast-definitions.ts # FASTElementDefinition, TemplateOptions
486
- │ ├── attributes.ts # AttributeDefinition, @attr, converters
487
- │ └── hydration.ts # SSR hydration helpers
488
- ├── di/
489
- │ └── di.ts # DI container, decorators, resolvers, Registration
490
- ├── context.ts # Context, FASTContext, Context protocol
491
- ├── state/
492
- │ ├── state.ts # state() helper (beta)
493
- │ └── watch.ts # watch() helper (beta)
494
- └── hydration/
495
- └── target-builder.ts # Hydration target resolution
496
- ```
497
-
498
- ---
499
-
500
- ## Detailed Architecture Documents
501
-
502
- | Document | What it covers |
503
- |---|---|
504
- | [ARCHITECTURE_INTRO.md](./ARCHITECTURE_INTRO.md) | Glossary / index for all architecture docs |
505
- | [ARCHITECTURE_OVERVIEW.md](./ARCHITECTURE_OVERVIEW.md) | General FAST usage, compose/define flow, module load sequence |
506
- | [ARCHITECTURE_FASTELEMENT.md](./ARCHITECTURE_FASTELEMENT.md) | FASTElement & ElementController lifecycle in detail |
507
- | [ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md](./ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md) | `html` tag, directives, binding pre-processing |
508
- | [ARCHITECTURE_UPDATES.md](./ARCHITECTURE_UPDATES.md) | Updates queue, attribute and observable change batching |
509
- | [src/templating/TEMPLATE-BINDINGS.md](./src/templating/TEMPLATE-BINDINGS.md) | Full template binding pipeline: authoring → compilation → binding → DOM updates |
510
- | [docs/fast-element-2-changes.md](./docs/fast-element-2-changes.md) | Breaking changes from v1 to v2 |
@@ -1,14 +0,0 @@
1
- {
2
- "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3
- "extends": "../../api-extractor.json",
4
- "mainEntryPointFilePath": "./dist/dts/context.d.ts",
5
- "apiReport": {
6
- "enabled": true,
7
- "reportFolder": "<projectFolder>/docs/context",
8
- "reportFileName": "api-report"
9
- },
10
- "docModel": {
11
- "enabled": true,
12
- "apiJsonFilePath": "<projectFolder>/dist/context/context.api.json"
13
- }
14
- }
@@ -1,14 +0,0 @@
1
- {
2
- "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3
- "extends": "../../api-extractor.json",
4
- "mainEntryPointFilePath": "./dist/dts/di/di.d.ts",
5
- "apiReport": {
6
- "enabled": true,
7
- "reportFolder": "<projectFolder>/docs/di",
8
- "reportFileName": "api-report"
9
- },
10
- "docModel": {
11
- "enabled": true,
12
- "apiJsonFilePath": "<projectFolder>/dist/di/di.api.json"
13
- }
14
- }
package/biome.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "root": false,
3
- "extends": "//"
4
- }
@@ -1 +0,0 @@
1
- import "../templating/install-hydratable-view-templates.js";
@@ -1,32 +0,0 @@
1
- /**
2
- * An implementation of the https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/pending-task.md proposal.
3
- * @public
4
- */
5
- export interface PendingTask extends Event {
6
- /**
7
- * A promise that resolves when the pending task is complete.
8
- */
9
- readonly complete: Promise<void>;
10
- }
11
- /**
12
- * A concrete implementation of {@link PendingTask}
13
- * @public
14
- */
15
- export declare class PendingTaskEvent extends Event implements PendingTask {
16
- readonly complete: Promise<void>;
17
- /**
18
- * The type of the pending task event.
19
- */
20
- static readonly type = "pending-task";
21
- /**
22
- * Creates an instance of PendingTaskEvent.
23
- * @param complete - A promise that resolves when the pending task is complete.
24
- */
25
- constructor(complete: Promise<void>);
26
- /**
27
- * Determines whether a value is a PendingTaskEvent.
28
- * @param value - The value to check.
29
- * @returns True if the value is a PendingTaskEvent; false otherwise.
30
- */
31
- static isPendingTask<T extends Event>(value: T | PendingTask): value is PendingTask;
32
- }
@@ -1,60 +0,0 @@
1
- import type { Binding, BindingDirective } from "../binding/binding.js";
2
- import type { Subscriber } from "../observation/notifier.js";
3
- import type { ExpressionObserver } from "../observation/observable.js";
4
- import { type AddBehavior, CSSDirective } from "./css-directive.js";
5
- import type { ComposableStyles } from "./element-styles.js";
6
- import type { HostBehavior, HostController } from "./host.js";
7
- type CSSBindingEntry = {
8
- observer: ExpressionObserver;
9
- controller: HostController;
10
- };
11
- /**
12
- * Enables bindings in CSS.
13
- *
14
- * @public
15
- */
16
- export declare class CSSBindingDirective implements HostBehavior, Subscriber, CSSDirective, BindingDirective {
17
- readonly dataBinding: Binding;
18
- readonly targetAspect: string;
19
- /**
20
- * Creates an instance of CSSBindingDirective.
21
- * @param dataBinding - The binding to use in CSS.
22
- * @param targetAspect - The CSS property to target.
23
- */
24
- constructor(dataBinding: Binding, targetAspect: string);
25
- /**
26
- * Creates a CSS fragment to interpolate into the CSS document.
27
- * @returns - the string to interpolate into CSS
28
- */
29
- createCSS(add: AddBehavior): ComposableStyles;
30
- /**
31
- * Executed when this behavior is attached to a controller.
32
- * @param controller - Controls the behavior lifecycle.
33
- */
34
- addedCallback(controller: HostController<HTMLElement & {
35
- $cssBindings: Map<CSSBindingDirective, CSSBindingEntry>;
36
- }>): void;
37
- /**
38
- * Executed when this behavior's host is connected.
39
- * @param controller - Controls the behavior lifecycle.
40
- */
41
- connectedCallback(controller: HostController<HTMLElement & {
42
- $cssBindings: Map<CSSBindingDirective, CSSBindingEntry>;
43
- }>): void;
44
- /**
45
- * Executed when this behavior is detached from a controller.
46
- * @param controller - Controls the behavior lifecycle.
47
- */
48
- removedCallback(controller: HostController<HTMLElement & {
49
- $cssBindings: Map<CSSBindingDirective, CSSBindingEntry>;
50
- }>): void;
51
- /**
52
- * Called when a subject this instance has subscribed to changes.
53
- * @param subject - The subject of the change.
54
- * @param args - The event args detailing the change that occurred.
55
- *
56
- * @internal
57
- */
58
- handleChange(_: any, observer: ExpressionObserver): void;
59
- }
60
- export {};
@@ -1,3 +0,0 @@
1
- import "../templating/install-hydratable-view-templates.js";
2
- import { HydratableElementController } from "./element-controller.js";
3
- HydratableElementController.install();