@microsoft/fast-element 3.0.0-rc.1 → 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 (286) hide show
  1. package/CHANGELOG.md +51 -1
  2. package/README.md +50 -14
  3. package/dist/context/context.api.json +13 -13
  4. package/dist/declarative/declarative.api.json +654 -15
  5. package/dist/di/di.api.json +15 -15
  6. package/dist/dts/__test__/helpers.d.ts +6 -0
  7. package/dist/dts/__test__/setup-node.d.ts +0 -0
  8. package/dist/dts/binding/binding.d.ts +15 -5
  9. package/dist/dts/binding/one-time.d.ts +1 -1
  10. package/dist/dts/binding/one-way.d.ts +1 -1
  11. package/dist/dts/binding/signal.d.ts +1 -1
  12. package/dist/dts/binding/two-way.d.ts +1 -1
  13. package/dist/dts/components/attributes.d.ts +1 -1
  14. package/dist/dts/components/enable-hydration.d.ts +22 -2
  15. package/dist/dts/components/fast-definitions.d.ts +7 -4
  16. package/dist/dts/components/fast-element.d.ts +42 -12
  17. package/dist/dts/components/hydration-tracker.d.ts +47 -4
  18. package/dist/dts/components/hydration.d.ts +5 -0
  19. package/dist/dts/context.d.ts +7 -7
  20. package/dist/dts/declarative/debug.d.ts +2 -3
  21. package/dist/dts/declarative/index.d.ts +3 -2
  22. package/dist/dts/declarative/interfaces.d.ts +1 -2
  23. package/dist/dts/declarative/template.d.ts +2 -1
  24. package/dist/dts/declarative/utilities.d.ts +50 -4
  25. package/dist/dts/di/di.d.ts +6 -6
  26. package/dist/dts/dom-policy.d.ts +22 -4
  27. package/dist/dts/dom.d.ts +4 -16
  28. package/dist/dts/hydration/diagnostics.d.ts +93 -0
  29. package/dist/dts/hydration/hydration-debugger.d.ts +35 -0
  30. package/dist/dts/hydration/messages.d.ts +62 -0
  31. package/dist/dts/hydration/target-builder.d.ts +26 -1
  32. package/dist/dts/hydration.d.ts +7 -3
  33. package/dist/dts/index.d.ts +7 -3
  34. package/dist/dts/interfaces.d.ts +1 -0
  35. package/dist/dts/observation/observable.d.ts +3 -3
  36. package/dist/dts/platform.d.ts +20 -4
  37. package/dist/dts/registry.d.ts +1 -0
  38. package/dist/dts/templating/children.d.ts +1 -1
  39. package/dist/dts/templating/compiler.d.ts +1 -1
  40. package/dist/dts/templating/html-binding-directive.d.ts +6 -2
  41. package/dist/dts/templating/html-directive.d.ts +2 -1
  42. package/dist/dts/templating/hydration-view.d.ts +24 -3
  43. package/dist/dts/templating/ref.d.ts +1 -1
  44. package/dist/dts/templating/render.d.ts +2 -2
  45. package/dist/dts/templating/repeat.d.ts +1 -1
  46. package/dist/dts/templating/slotted.d.ts +1 -1
  47. package/dist/dts/templating/template.d.ts +5 -5
  48. package/dist/dts/templating/when.d.ts +1 -1
  49. package/dist/dts/testing/fakes.d.ts +4 -4
  50. package/dist/esm/__test__/helpers.js +22 -0
  51. package/dist/esm/__test__/setup-node.js +18 -0
  52. package/dist/esm/binding/two-way.js +1 -2
  53. package/dist/esm/components/attributes.js +12 -8
  54. package/dist/esm/components/element-controller.js +11 -6
  55. package/dist/esm/components/enable-hydration.js +27 -3
  56. package/dist/esm/components/fast-definitions.js +19 -18
  57. package/dist/esm/components/hydration-tracker.js +34 -5
  58. package/dist/esm/components/hydration.js +85 -6
  59. package/dist/esm/debug.js +1 -0
  60. package/dist/esm/declarative/attribute-map.js +2 -1
  61. package/dist/esm/declarative/debug.js +0 -1
  62. package/dist/esm/declarative/index.js +1 -0
  63. package/dist/esm/declarative/interfaces.js +0 -1
  64. package/dist/esm/declarative/observer-map-utilities.js +58 -55
  65. package/dist/esm/declarative/template-bridge.js +4 -14
  66. package/dist/esm/declarative/template.js +4 -3
  67. package/dist/esm/declarative/utilities.js +236 -1
  68. package/dist/esm/di/di.js +2 -1
  69. package/dist/esm/dom-policy.js +33 -4
  70. package/dist/esm/hydration/diagnostics.js +50 -0
  71. package/dist/esm/hydration/hydration-debugger.js +112 -0
  72. package/dist/esm/hydration/messages.js +84 -0
  73. package/dist/esm/hydration/target-builder.js +65 -19
  74. package/dist/esm/hydration.js +3 -1
  75. package/dist/esm/index.js +6 -2
  76. package/dist/esm/interfaces.js +1 -0
  77. package/dist/esm/metadata.js +2 -8
  78. package/dist/esm/observation/notifier.js +2 -4
  79. package/dist/esm/registry.js +1 -0
  80. package/dist/esm/templating/html-binding-directive.js +1 -1
  81. package/dist/esm/templating/hydration-view.js +20 -27
  82. package/dist/esm/templating/render.js +39 -18
  83. package/dist/esm/templating/repeat.js +51 -17
  84. package/dist/esm/templating/view.js +1 -1
  85. package/dist/esm/testing/fixture.js +2 -2
  86. package/dist/esm/testing/timeout.js +2 -2
  87. package/dist/fast-element.api.json +1329 -99
  88. package/dist/fast-element.d.ts +147 -66
  89. package/dist/fast-element.debug.js +392 -99
  90. package/dist/fast-element.debug.min.js +2 -2
  91. package/dist/fast-element.js +392 -99
  92. package/dist/fast-element.min.js +2 -2
  93. package/dist/fast-element.untrimmed.d.ts +133 -70
  94. package/dist/hydration/hydration.api.json +1280 -57
  95. package/dist/styles/styles.api.json +1 -1
  96. package/package.json +21 -9
  97. package/ARCHITECTURE_FASTELEMENT.md +0 -63
  98. package/ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md +0 -36
  99. package/ARCHITECTURE_INTRO.md +0 -10
  100. package/ARCHITECTURE_OVERVIEW.md +0 -52
  101. package/ARCHITECTURE_UPDATES.md +0 -11
  102. package/CHANGELOG.json +0 -2275
  103. package/DECLARATIVE_DESIGN.md +0 -806
  104. package/DECLARATIVE_HTML.md +0 -470
  105. package/DECLARATIVE_MIGRATION.md +0 -215
  106. package/DECLARATIVE_RENDERING.md +0 -530
  107. package/DECLARATIVE_RENDERING_LIFECYCLE.md +0 -288
  108. package/DECLARATIVE_SCHEMA_OBSERVER_MAP.md +0 -489
  109. package/DESIGN.md +0 -615
  110. package/MIGRATION.md +0 -387
  111. package/SIZES.md +0 -25
  112. package/api-extractor.arrays.json +0 -15
  113. package/api-extractor.context.json +0 -15
  114. package/api-extractor.declarative.json +0 -15
  115. package/api-extractor.di.json +0 -15
  116. package/api-extractor.hydration.json +0 -15
  117. package/api-extractor.styles.json +0 -15
  118. package/biome.json +0 -4
  119. package/docs/ACKNOWLEDGEMENTS.md +0 -12
  120. package/docs/api-report.api.md +0 -1299
  121. package/docs/arrays/api-report.api.md +0 -114
  122. package/docs/context/api-report.api.md +0 -69
  123. package/docs/declarative/api-report.api.md +0 -397
  124. package/docs/di/api-report.api.md +0 -315
  125. package/docs/fast-element-2-changes.md +0 -15
  126. package/docs/hydration/api-report.api.md +0 -285
  127. package/docs/styles/api-report.api.md +0 -135
  128. package/playwright.config.ts +0 -26
  129. package/playwright.declarative.config.ts +0 -26
  130. package/playwright.declarative.webui.config.ts +0 -20
  131. package/scripts/declarative/build-fixtures-with-webui.js +0 -135
  132. package/scripts/declarative/build-fixtures.js +0 -49
  133. package/scripts/declarative/build-fixtures.utilities.js +0 -101
  134. package/scripts/measure-sizes.js +0 -219
  135. package/scripts/run-api-extractor.js +0 -70
  136. package/test/declarative/fixtures/README.md +0 -72
  137. package/test/declarative/fixtures/WRITING_FIXTURES.md +0 -330
  138. package/test/declarative/fixtures/bindings/README.md +0 -12
  139. package/test/declarative/fixtures/bindings/attribute/entry.html +0 -13
  140. package/test/declarative/fixtures/bindings/attribute/fast-build.config.json +0 -6
  141. package/test/declarative/fixtures/bindings/attribute/index.html +0 -25
  142. package/test/declarative/fixtures/bindings/attribute/main.ts +0 -41
  143. package/test/declarative/fixtures/bindings/attribute/state.json +0 -8
  144. package/test/declarative/fixtures/bindings/attribute/templates.html +0 -11
  145. package/test/declarative/fixtures/bindings/content/entry.html +0 -12
  146. package/test/declarative/fixtures/bindings/content/fast-build.config.json +0 -6
  147. package/test/declarative/fixtures/bindings/content/index.html +0 -19
  148. package/test/declarative/fixtures/bindings/content/main.ts +0 -27
  149. package/test/declarative/fixtures/bindings/content/state.json +0 -4
  150. package/test/declarative/fixtures/bindings/content/templates.html +0 -6
  151. package/test/declarative/fixtures/bindings/dot-syntax/entry.html +0 -11
  152. package/test/declarative/fixtures/bindings/dot-syntax/fast-build.config.json +0 -6
  153. package/test/declarative/fixtures/bindings/dot-syntax/index.html +0 -47
  154. package/test/declarative/fixtures/bindings/dot-syntax/main.ts +0 -59
  155. package/test/declarative/fixtures/bindings/dot-syntax/state.json +0 -16
  156. package/test/declarative/fixtures/bindings/dot-syntax/templates.html +0 -17
  157. package/test/declarative/fixtures/bindings/event/entry.html +0 -11
  158. package/test/declarative/fixtures/bindings/event/fast-build.config.json +0 -6
  159. package/test/declarative/fixtures/bindings/event/index.html +0 -43
  160. package/test/declarative/fixtures/bindings/event/main.ts +0 -43
  161. package/test/declarative/fixtures/bindings/event/state.json +0 -3
  162. package/test/declarative/fixtures/bindings/event/templates.html +0 -18
  163. package/test/declarative/fixtures/bindings/host/entry.html +0 -40
  164. package/test/declarative/fixtures/bindings/host/fast-build.config.json +0 -6
  165. package/test/declarative/fixtures/bindings/host/index.html +0 -96
  166. package/test/declarative/fixtures/bindings/host/main.ts +0 -222
  167. package/test/declarative/fixtures/bindings/host/state.json +0 -9
  168. package/test/declarative/fixtures/bindings/host/templates.html +0 -55
  169. package/test/declarative/fixtures/directives/README.md +0 -12
  170. package/test/declarative/fixtures/directives/children/entry.html +0 -11
  171. package/test/declarative/fixtures/directives/children/fast-build.config.json +0 -6
  172. package/test/declarative/fixtures/directives/children/index.html +0 -15
  173. package/test/declarative/fixtures/directives/children/main.ts +0 -22
  174. package/test/declarative/fixtures/directives/children/state.json +0 -3
  175. package/test/declarative/fixtures/directives/children/templates.html +0 -3
  176. package/test/declarative/fixtures/directives/ref/entry.html +0 -11
  177. package/test/declarative/fixtures/directives/ref/fast-build.config.json +0 -6
  178. package/test/declarative/fixtures/directives/ref/index.html +0 -15
  179. package/test/declarative/fixtures/directives/ref/main.ts +0 -17
  180. package/test/declarative/fixtures/directives/ref/state.json +0 -1
  181. package/test/declarative/fixtures/directives/ref/templates.html +0 -3
  182. package/test/declarative/fixtures/directives/repeat/entry.html +0 -21
  183. package/test/declarative/fixtures/directives/repeat/fast-build.config.json +0 -6
  184. package/test/declarative/fixtures/directives/repeat/index.html +0 -133
  185. package/test/declarative/fixtures/directives/repeat/main.ts +0 -110
  186. package/test/declarative/fixtures/directives/repeat/sprites.svg +0 -8
  187. package/test/declarative/fixtures/directives/repeat/state.json +0 -10
  188. package/test/declarative/fixtures/directives/repeat/templates.html +0 -75
  189. package/test/declarative/fixtures/directives/slotted/entry.html +0 -17
  190. package/test/declarative/fixtures/directives/slotted/fast-build.config.json +0 -6
  191. package/test/declarative/fixtures/directives/slotted/index.html +0 -27
  192. package/test/declarative/fixtures/directives/slotted/main.ts +0 -29
  193. package/test/declarative/fixtures/directives/slotted/state.json +0 -1
  194. package/test/declarative/fixtures/directives/slotted/templates.html +0 -7
  195. package/test/declarative/fixtures/directives/when/entry.html +0 -51
  196. package/test/declarative/fixtures/directives/when/fast-build.config.json +0 -6
  197. package/test/declarative/fixtures/directives/when/index.html +0 -136
  198. package/test/declarative/fixtures/directives/when/main.ts +0 -172
  199. package/test/declarative/fixtures/directives/when/state.json +0 -12
  200. package/test/declarative/fixtures/directives/when/templates.html +0 -75
  201. package/test/declarative/fixtures/ecosystem/README.md +0 -11
  202. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/entry.html +0 -12
  203. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/fast-build.config.json +0 -6
  204. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/index.html +0 -20
  205. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/main.ts +0 -68
  206. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/state.json +0 -4
  207. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/templates.html +0 -7
  208. package/test/declarative/fixtures/ecosystem/errors/entry.html +0 -12
  209. package/test/declarative/fixtures/ecosystem/errors/fast-build.config.json +0 -6
  210. package/test/declarative/fixtures/ecosystem/errors/index.html +0 -20
  211. package/test/declarative/fixtures/ecosystem/errors/main.ts +0 -17
  212. package/test/declarative/fixtures/ecosystem/errors/state.json +0 -1
  213. package/test/declarative/fixtures/ecosystem/errors/templates.html +0 -7
  214. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/entry.html +0 -17
  215. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/fast-build.config.json +0 -6
  216. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/index.html +0 -56
  217. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/main.ts +0 -134
  218. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/state.json +0 -12
  219. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/templates.html +0 -34
  220. package/test/declarative/fixtures/ecosystem/performance-metrics/entry.html +0 -25
  221. package/test/declarative/fixtures/ecosystem/performance-metrics/fast-build.config.json +0 -6
  222. package/test/declarative/fixtures/ecosystem/performance-metrics/fast-card.css +0 -10
  223. package/test/declarative/fixtures/ecosystem/performance-metrics/index.html +0 -181
  224. package/test/declarative/fixtures/ecosystem/performance-metrics/main.ts +0 -58
  225. package/test/declarative/fixtures/ecosystem/performance-metrics/state.json +0 -6
  226. package/test/declarative/fixtures/ecosystem/performance-metrics/templates.html +0 -15
  227. package/test/declarative/fixtures/extensions/README.md +0 -15
  228. package/test/declarative/fixtures/extensions/attribute-map/entry.html +0 -14
  229. package/test/declarative/fixtures/extensions/attribute-map/fast-build.config.json +0 -6
  230. package/test/declarative/fixtures/extensions/attribute-map/index.html +0 -31
  231. package/test/declarative/fixtures/extensions/attribute-map/main.ts +0 -40
  232. package/test/declarative/fixtures/extensions/attribute-map/state.json +0 -4
  233. package/test/declarative/fixtures/extensions/attribute-map/templates.html +0 -14
  234. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/entry.html +0 -12
  235. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/fast-build.config.json +0 -7
  236. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/index.html +0 -25
  237. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/main.ts +0 -31
  238. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/state.json +0 -5
  239. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/templates.html +0 -11
  240. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/entry.html +0 -13
  241. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/fast-build.config.json +0 -7
  242. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/index.html +0 -23
  243. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/main.ts +0 -37
  244. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/state.json +0 -1
  245. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/templates.html +0 -9
  246. package/test/declarative/fixtures/extensions/observer-map/entry.html +0 -15
  247. package/test/declarative/fixtures/extensions/observer-map/fast-build.config.json +0 -6
  248. package/test/declarative/fixtures/extensions/observer-map/index.html +0 -442
  249. package/test/declarative/fixtures/extensions/observer-map/main.ts +0 -482
  250. package/test/declarative/fixtures/extensions/observer-map/state.json +0 -158
  251. package/test/declarative/fixtures/extensions/observer-map/templates.html +0 -172
  252. package/test/declarative/fixtures/extensions/observer-map-config-object/entry.html +0 -16
  253. package/test/declarative/fixtures/extensions/observer-map-config-object/fast-build.config.json +0 -6
  254. package/test/declarative/fixtures/extensions/observer-map-config-object/index.html +0 -27
  255. package/test/declarative/fixtures/extensions/observer-map-config-object/main.ts +0 -53
  256. package/test/declarative/fixtures/extensions/observer-map-config-object/state.json +0 -9
  257. package/test/declarative/fixtures/extensions/observer-map-config-object/templates.html +0 -12
  258. package/test/declarative/fixtures/extensions/observer-map-deep-merge/README.md +0 -98
  259. package/test/declarative/fixtures/extensions/observer-map-deep-merge/entry.html +0 -156
  260. package/test/declarative/fixtures/extensions/observer-map-deep-merge/fast-build.config.json +0 -6
  261. package/test/declarative/fixtures/extensions/observer-map-deep-merge/index.html +0 -376
  262. package/test/declarative/fixtures/extensions/observer-map-deep-merge/main.ts +0 -366
  263. package/test/declarative/fixtures/extensions/observer-map-deep-merge/state.json +0 -69
  264. package/test/declarative/fixtures/extensions/observer-map-deep-merge/templates.html +0 -91
  265. package/test/declarative/fixtures/extensions/observer-map-properties/entry.html +0 -14
  266. package/test/declarative/fixtures/extensions/observer-map-properties/fast-build.config.json +0 -6
  267. package/test/declarative/fixtures/extensions/observer-map-properties/index.html +0 -110
  268. package/test/declarative/fixtures/extensions/observer-map-properties/main.ts +0 -175
  269. package/test/declarative/fixtures/extensions/observer-map-properties/state.json +0 -29
  270. package/test/declarative/fixtures/extensions/observer-map-properties/templates.html +0 -55
  271. package/test/declarative/fixtures/scenarios/README.md +0 -7
  272. package/test/declarative/fixtures/scenarios/nested-elements/entry.html +0 -16
  273. package/test/declarative/fixtures/scenarios/nested-elements/fast-build.config.json +0 -6
  274. package/test/declarative/fixtures/scenarios/nested-elements/index.html +0 -126
  275. package/test/declarative/fixtures/scenarios/nested-elements/main.ts +0 -214
  276. package/test/declarative/fixtures/scenarios/nested-elements/state.json +0 -10
  277. package/test/declarative/fixtures/scenarios/nested-elements/templates.html +0 -54
  278. package/test/declarative/index.html +0 -12
  279. package/test/declarative/vite.config.ts +0 -55
  280. package/test/declarative-main.ts +0 -6
  281. package/test/extension-subpaths-main.ts +0 -9
  282. package/test/index.html +0 -11
  283. package/test/main.ts +0 -109
  284. package/test/pure-declarative-main.ts +0 -1
  285. package/test/vite.config.ts +0 -19
  286. package/tsconfig.api-extractor.json +0 -6
package/DESIGN.md DELETED
@@ -1,615 +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 Object](#fast-object)
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
- | Declarative HTML runtime | `@microsoft/fast-element/declarative.js` → `declarativeTemplate()`, `TemplateParser`; `@microsoft/fast-element/schema.js` → `Schema` |
46
- | Schema-driven extensions | `@microsoft/fast-element/attribute-map.js` and `@microsoft/fast-element/observer-map.js` → map helpers usable with declarative or manually supplied schemas |
47
- | Async DOM updates | `Updates` queue (batched, `requestAnimationFrame`-aligned) |
48
- | Scoped styles | `css` tagged template literal → `ElementStyles` → `adoptedStylesheets` / `<style>` |
49
- | Dependency injection | `DI` container, `@inject`, `@singleton`, `@transient`, resolvers |
50
- | Context protocol | W3C community Context protocol (`Context.create`, `Context.for`) |
51
- | Reactive state helpers | `state()`, `watch()` (beta) |
52
-
53
- The library's kernel is module-scoped rather than stored on `globalThis`: import `FAST` from `@microsoft/fast-element`, `Updates` from `@microsoft/fast-element`, and `Observable` from `@microsoft/fast-element`.
54
-
55
- The root entrypoint exports the FAST Element implementation APIs. Focused package
56
- path exports remain available when a consumer wants a narrower entrypoint.
57
-
58
- ---
59
-
60
- ## Core Concepts
61
-
62
- ### FAST Object
63
-
64
- **File**: `src/platform.ts`, `src/interfaces.ts`
65
-
66
- `FAST` is a module-scoped singleton exported from `@microsoft/fast-element`. It is **not** attached to `globalThis`. It provides:
67
-
68
- - `FAST.warn(code, values)` / `FAST.error(code, values)` – structured diagnostic messages
69
- - `FAST.addMessages(dict)` – registers human-readable debug messages used by `enableDebug()` and declarative runtime diagnostics
70
-
71
- The previous `FAST.getById()` slot registry, `FASTGlobal` type, and `KernelServiceId` enum have been removed. Kernel services (update queue, observable system, etc.) are resolved through standard ES module imports rather than a shared global registry.
72
-
73
- ---
74
-
75
- ### FASTElement & ElementController
76
-
77
- **Files**: `src/components/fast-element.ts`, `src/components/element-controller.ts`, `src/components/fast-definitions.ts`
78
-
79
- `FASTElement` is a thin mixin applied on top of `HTMLElement`. It:
80
-
81
- 1. Calls `ElementController.forCustomElement(this)` in its `constructor` to create or locate the element's controller.
82
- 2. Delegates all lifecycle hooks to the controller:
83
- - `connectedCallback` → `$fastController.connect()`
84
- - `disconnectedCallback` → `$fastController.disconnect()`
85
- - `attributeChangedCallback` → `$fastController.onAttributeChangedCallback()`
86
-
87
- `ElementController` is the real workhorse. It:
88
-
89
- - Uses composition with an internal `_notifier` field (rather than extending `PropertyChangeNotifier`) and implements the `Notifier` interface directly, so the element still participates in the observable system.
90
- - Holds the element's `FASTElementDefinition` (name, template, styles, observed attributes).
91
- - Manages a `Stages` state machine: `disconnected → connecting → connected → disconnecting → disconnected`.
92
- - Exposes `isPrerendered: Promise<boolean>` which resolves to `true` when the element had a declarative shadow root (DSD) at connect time, regardless of whether hydration ran. Exposes `isHydrated: Promise<boolean>` which resolves to `true` only when hydration actually ran successfully. The `ViewController` interface also exposes both `isPrerendered` and `isHydrated` as `Promise<boolean>` for custom directives. Attribute-skip logic during the hydration bind uses an internal `_skipAttrUpdates` flag that is never exposed as a public boolean.
93
- - On `connect()`: restores pre-upgrade observable values, calls `connectedCallback` on all `HostBehavior`s, renders the current template into the shadow root when one is available, and applies styles.
94
- - Rendering is split into two modular paths. Hydration is pluggable: `enableHydration()` from `@microsoft/fast-element/hydration.js` installs a hook via `ElementController.installHydrationHook()`, keeping zero hydration imports in the core controller:
95
- - **Prerendered**: The hydration hook (installed by `enableHydration()`) registers the element in the static hydration tracker, fires the definition's `elementWillHydrate` callback, swaps `onAttributeChangedCallback` to a no-op so the upgrade-time burst of callbacks is discarded, hydrates the existing DOM via `template.hydrate()`, fires `elementDidHydrate`, then restores the standard handler and removes the element from the tracker. The entire method is wrapped in `try/finally` to guarantee cleanup even if an error occurs during hydration. After this point, all future attribute changes flow through the real handler with zero overhead.
96
- - **Client-side**: `renderClientSide()` clones the compiled fragment, binds, and appends to the host — the standard path with no prerender logic.
97
- - **Static hydration tracking**: Hydration is opt-in via `enableHydration()` from `@microsoft/fast-element/hydration.js`, which creates a `HydrationTracker` and installs a pluggable hydration hook on `ElementController` via `ElementController.installHydrationHook()`. Until this is called, `renderTemplate()` always uses the client-side path — even if the element has a pre-existing shadow root. `HydrationTracker` manages a `Set<HTMLElement>` of pending elements, fires global callbacks (`hydrationStarted`, `hydrationComplete`), and fires `hydrationComplete` via a debounced `setTimeout(0)` after the last element finishes binding — ensuring all async template batches settle first. Per-element hydration callbacks (`elementWillHydrate`, `elementDidHydrate`) are stored on the `FASTElementDefinition.lifecycleCallbacks` and fired directly by the hydration hook.
98
- - On `disconnect()`: calls `disconnectedCallback` on behaviors, unbinds the view.
99
- - `onAttributeChangedCallback()` is the standard handler that processes attribute changes. During the prerendered bind, it is temporarily swapped to a no-op (see above) to avoid redundant processing of server-rendered attribute values.
100
- - Exposes `addBehavior` / `removeBehavior` for dynamic `HostBehavior` management (used by `ElementStyles`).
101
-
102
- `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()` (which returns `Promise<FASTElementDefinition>`, always resolving immediately) and registered globally via `fastElementRegistry`. `PartialFASTElementDefinition.template` may be either a concrete `ElementViewTemplate<InstanceType<TType>>` or a `FASTElementTemplateResolver<TType>` function that receives the composed definition and returns the concrete template (sync or async). `FASTElementDefinition.template` always stores the concrete `ElementViewTemplate<InstanceType<TType>>` after composition or resolver settlement. `FASTElement.define()` returns `Promise<TType>` — resolving immediately for complete definitions or definitions without an initial template, and resolving async template resolver functions only after extensions have had a chance to update the definition. `FASTElementDefinition.register()` returns `Promise<Function>` — resolving when a definition with the given name has been registered.
103
-
104
- #### Extensions
105
-
106
- `FASTElement.define()` and `FASTElementDefinition.define()` accept an optional array of **extension callbacks** (`FASTElementExtension`). Each extension is a function that receives the resolved `FASTElementDefinition` and is invoked **before** the element is registered with the platform via `customElements.define()`. `FASTElement.define()` also invokes extensions before any template resolver function is asked to produce a concrete `ElementViewTemplate`, so plugins can attach state that affects template resolution without leaving non-template values on `definition.template`.
107
-
108
- ```typescript
109
- type FASTElementExtension = (definition: FASTElementDefinition) => void;
110
- ```
111
-
112
- Extensions are typically produced by factory functions:
113
-
114
- ```typescript
115
- function myPlugin() {
116
- return (definition: FASTElementDefinition) => {
117
- console.log(`Registering: ${definition.name}`);
118
- };
119
- }
120
-
121
- MyComponent.define({ name: "my-component" }, [myPlugin()]);
122
- ```
123
-
124
- ---
125
-
126
- ### Observables & Notifiers
127
-
128
- **Files**: `src/observation/observable.ts`, `src/observation/notifier.ts`, `src/observation/arrays.ts`
129
-
130
- #### Property observability
131
-
132
- `Observable.defineProperty(target, name)` (or the `@observable` decorator) replaces a plain property with a getter/setter pair via `Reflect.defineProperty`. The setter:
133
-
134
- 1. Stores the new value in a backing slot.
135
- 2. Calls `Observable.getNotifier(this).notify(name)` to fan out to subscribers.
136
-
137
- `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.
138
-
139
- #### SubscriberSet / PropertyChangeNotifier
140
-
141
- `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.
142
-
143
- #### ExpressionNotifier (binding observer)
144
-
145
- `Observable.binding(expression, subscriber)` creates an `ExpressionNotifier`. When `observe(source, context)` is called it:
146
-
147
- 1. Pushes itself as the _current watcher_ onto a thread-local stack.
148
- 2. Evaluates the expression (e.g., `x => x.name`).
149
- 3. Any `Observable`-tracked property get encountered during evaluation subscribes the notifier to that property's notifier automatically.
150
- 4. Pops itself. Future changes to any accessed property trigger `handleChange` on the subscriber.
151
-
152
- This gives FAST automatic, fine-grained dependency tracking without explicit declarations.
153
-
154
- ---
155
-
156
- ### Bindings
157
-
158
- **Files**: `src/binding/binding.ts`, `src/binding/one-way.ts`, `src/binding/one-time.ts`, `src/binding/normalize.ts`
159
-
160
- `Binding` is an abstract class that pairs an `Expression` (arrow function) with a `DOMPolicy` and a volatility flag. Concrete subclasses implement `createObserver(subscriber, directive)`:
161
-
162
- | Binding | Observer behaviour |
163
- |---|---|
164
- | `oneWay` | Creates an `ExpressionNotifier`; tracks dependencies; re-evaluates on change |
165
- | `oneTime` | Evaluates once during `bind()`, returns immediately |
166
- | `listener` | Same as `oneWay` but attaches as a DOM event handler |
167
-
168
- `normalizeBinding(value)` converts raw arrow functions or static values into a `Binding` object.
169
-
170
- ---
171
-
172
- ### html Tagged Template Literal
173
-
174
- **File**: `src/templating/template.ts`
175
-
176
- The `html` tag is the primary authoring API:
177
-
178
- ```typescript
179
- const template = html<MyElement>`
180
- <div>${x => x.label}</div>
181
- <button @click="${x => x.handleClick}">OK</button>
182
- `;
183
- ```
184
-
185
- When the tag function is called it invokes `ViewTemplate.create(strings, values)` (static method) which:
186
-
187
- 1. Iterates the template string fragments (`strings`) paired with interpolated values.
188
- 2. For each value:
189
- - A plain function → wrapped in `HTMLBindingDirective(oneWay(fn))`
190
- - A `Binding` instance → wrapped in `HTMLBindingDirective(binding)`
191
- - A registered `HTMLDirective` instance → used directly
192
- - Anything else → wrapped as a `oneTime` static binding
193
- 3. Calls `directive.createHTML(add)` which returns a **placeholder string** (a special attribute or marker containing the factory's unique ID).
194
- 4. Concatenates all static strings and placeholders into a single HTML string.
195
- 5. Returns a `ViewTemplate(html, factories)` – the factories dictionary maps IDs to `ViewBehaviorFactory` instances.
196
-
197
- No DOM nodes are created at this point; compilation is deferred.
198
-
199
- See [ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md](./ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md) for more detail on directives and the `Markup`/`Parser` helpers.
200
-
201
- ---
202
-
203
- ### ViewTemplate & Compiler
204
-
205
- **Files**: `src/templating/template.ts`, `src/templating/compiler.ts`, `src/templating/markup.ts`
206
-
207
- `ViewTemplate.compile()` is called lazily the first time the template is rendered. It delegates to `Compiler.compile(html, factories, policy)`:
208
-
209
- 1. Sets the HTML string as the `innerHTML` of a `<template>` element (letting the browser parse the DOM once).
210
- 2. Traverses the resulting `DocumentFragment` depth-first.
211
- 3. For each node, calls `compileAttributes()` which scans attributes for factory placeholder IDs.
212
- 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").
213
- 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.
214
- 6. Returns a `CompilationContext` that implements `HTMLTemplateCompilationResult`.
215
-
216
- `CompilationContext.createView(hostBindingTarget?)` clones the compiled `DocumentFragment`, instantiates behaviors from factories, and returns an `HTMLView`.
217
-
218
- ---
219
-
220
- ### Views & Behaviors
221
-
222
- **Files**: `src/templating/view.ts`, `src/templating/html-directive.ts`
223
-
224
- `HTMLView` implements `ElementView` / `SyntheticView`. It:
225
-
226
- - Holds the cloned `DocumentFragment` nodes.
227
- - Has a `targets` map (resolved lazily) from structural node IDs to live `Node` references.
228
- - `bind(source, context)` iterates all `ViewBehavior` instances and calls `behavior.bind(controller)`.
229
- - `unbind()` calls `behavior.unbind()` on each behavior and clears the source.
230
- - `appendTo(node)` / `insertBefore(node)` / `remove()` move its DOM nodes in the tree.
231
-
232
- `ViewBehavior` is the runtime unit of work attached to a specific DOM node. Examples:
233
-
234
- | Directive | Created `ViewBehavior` | Effect |
235
- |---|---|---|
236
- | `HTMLBindingDirective` | `BindingBehavior` | Evaluates the binding; updates the DOM aspect (attribute / property / event / content / tokenList) |
237
- | `when` | `WhenBehavior` | Conditionally inserts a child view |
238
- | `repeat` | `RepeatBehavior` | Renders a list of child views |
239
- | `ref` | `RefDirective` | Writes the element reference onto the source |
240
- | `children` / `slotted` | `ChildrenDirective` / `SlottedDirective` | Observes DOM mutations |
241
-
242
- `ViewBehaviorFactory` (created at template-authoring time) is the blueprint; `ViewBehavior` (created per `HTMLView` instance) is the live runtime object.
243
-
244
- See [src/templating/TEMPLATE-BINDINGS.md](./src/templating/TEMPLATE-BINDINGS.md) for the full binding pipeline including `DOMAspect` routing and two-way binding.
245
-
246
- ---
247
-
248
- ### Updates Queue
249
-
250
- **File**: `src/observation/update-queue.ts`
251
-
252
- **Exported as**: `Updates`
253
-
254
- `Updates` is a shared, batched task queue used to synchronise writes to the DOM. It is resolved through standard ES module imports so multiple parts of the application share a single flush cycle.
255
-
256
- - `Updates.enqueue(callable)` – schedules a task for the next batch.
257
- - `Updates.process()` – forces immediate synchronous flush (useful in tests).
258
- - `Updates.next()` – returns a `Promise` that resolves after the next flush.
259
- - `Updates.setMode(isAsync)` – toggle async (default) vs. synchronous mode.
260
-
261
- 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.
262
-
263
- Observable setters and `attributeChangedCallback` enqueue their DOM mutations through `Updates`, ensuring that multiple synchronous property changes result in only one DOM update per frame.
264
-
265
- See [ARCHITECTURE_UPDATES.md](./ARCHITECTURE_UPDATES.md) for more detail.
266
-
267
- ---
268
-
269
- ### Styles
270
-
271
- **Files**: `src/styles/css.ts`, `src/styles/element-styles.ts`, `src/styles/css-directive.ts`
272
-
273
- **Exported from**: `@microsoft/fast-element`
274
-
275
- The `css` tag, `ElementStyles`, `CSSDirective`, `cssDirective`,
276
- `ComposableStyles`, `HostBehavior`, `HostController`, `StyleStrategy`, and
277
- `StyleTarget` are imported from `@microsoft/fast-element`. The `css` tag
278
- (analogous to `html`) builds `ElementStyles` objects. During
279
- `ElementController.connect()`, styles are applied to the element's shadow root
280
- either via `adoptedStylesheets` (preferred) or an appended `<style>` node,
281
- depending on platform support. `CSSDirective`s can contribute additional static
282
- CSS during template composition, but runtime CSS bindings and style-attached
283
- `HostBehavior`s are not supported. Arbitrary runtime style toggling is handled
284
- through `ElementController.addStyles()` / `removeStyles()`; `ElementStyles`
285
- itself is a static container.
286
-
287
- ---
288
-
289
- ### Dependency Injection (DI)
290
-
291
- **File**: `src/di/di.ts`
292
-
293
- FAST ships a full hierarchical DI container inspired by Aurelia. Key types:
294
-
295
- | Type | Role |
296
- |---|---|
297
- | `Container` | Resolves dependencies; parent containers are queried if a key is not found locally |
298
- | `Resolver` | Maps a key to a creation strategy (singleton, transient, callback, …) |
299
- | `Registration` | Produces a `Resolver` when registered in a container |
300
- | `Factory` | Constructs instances; supports `Transformer`s for post-construction mutation |
301
-
302
- 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).
303
-
304
- See `docs/di/api-report.api.md` for the full public API surface.
305
-
306
- ---
307
-
308
- ### Context Protocol
309
-
310
- **File**: `src/context.ts`
311
-
312
- `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:
313
-
314
- - `Context.create<T>(name, initialValue?)` – creates a named context token.
315
- - `Context.for<T>(name)` – gets or creates a globally-registered context token.
316
- - `context.provide(target, value)` – registers a provider on a DOM element.
317
- - `context.get(target)` – dispatches a `context-request` event and returns the synchronously provided value (or `initialValue`).
318
- - `context.request(target, callback, multiple?)` – async / multi-provider variant.
319
- - Used as a `@decorator` on class properties or constructor parameters to declare a context dependency.
320
-
321
- ---
322
-
323
- ### State Helpers
324
-
325
- **Files**: `src/state/state.ts`, `src/state/watch.ts`
326
-
327
- > **Status**: beta
328
-
329
- `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.
330
-
331
- `watch(object, subscriber)` deeply subscribes to all observable properties and array mutations on an object graph, returning a `Disposable`.
332
-
333
- ---
334
-
335
- ### Declarative HTML
336
-
337
- **Files**: `src/declarative/index.ts`, `src/declarative/*`
338
-
339
- FAST Element also owns the declarative HTML runtime that previously lived in a
340
- separate package. `@microsoft/fast-element` exports the declarative runtime API:
341
- `declarativeTemplate()`, `TemplateParser`, `Schema`, `schemaRegistry`, and
342
- related parser/schema types. Map helpers are also exported from the root so they
343
- can be used with declarative templates or manually supplied schemas. The
344
- `<f-template>` element is an internal native `HTMLElement` publisher that
345
- `declarativeTemplate()` defines in the target registry; it is not part of the
346
- public API.
347
-
348
- The declarative runtime intentionally reuses the same FAST Element primitives as
349
- the imperative `html` API:
350
-
351
- - The internal `<f-template>` publisher parses HTML and returns concrete
352
- `ViewTemplate` instances through the registry-aware declarative template
353
- bridge.
354
- - `TemplateParser` lowers declarative syntax to the same `strings` / `values`
355
- shape used by `ViewTemplate.create()`.
356
- - `attributeMap()` and `observerMap()` are `FASTElementExtension` factories
357
- exported from `@microsoft/fast-element/attribute-map.js` and
358
- `@microsoft/fast-element/observer-map.js`. With `declarativeTemplate()` they
359
- register schema transforms on the element definition, and those transforms run
360
- after parsing in deterministic order (`attributeMap()` before
361
- `observerMap()`). Outside declarative templates, `attributeMap()` uses
362
- `definition.schema`, while `observerMap()` can use either `definition.schema`
363
- or `observerMap({ schema })`.
364
-
365
- The `src/declarative/index.ts` entrypoint is pure at module evaluation time. Running a
366
- declarative API lazily installs declarative debug messages only. Hydration hooks
367
- and hydratable `ViewTemplate` support are installed exclusively by
368
- `enableHydration()` from `@microsoft/fast-element/hydration.js`. See
369
- [`DECLARATIVE_DESIGN.md`](./DECLARATIVE_DESIGN.md) for the detailed
370
- architecture.
371
-
372
- ---
373
-
374
- ## Data Flow Diagrams
375
-
376
- ### Module Load & Registration
377
-
378
- ```mermaid
379
- flowchart TD
380
- A([Browser loads script]) --> B[FAST module initialises singleton]
381
- B --> C[FASTElement subclass executes FASTElement.compose]
382
- C --> D[Observable decorators register accessors on the prototype]
383
- C --> E[Attribute decorators push AttributeDefinition to the class]
384
- C --> F[html tag is evaluated – ViewTemplate created with factories]
385
- D & E & F --> G[FASTElement.define registers with the Custom Element Registry]
386
- G --> H[Browser detects element in DOM]
387
- H --> I([FASTElement lifecycle begins])
388
- ```
389
-
390
- ### FASTElement Lifecycle
391
-
392
- ```mermaid
393
- flowchart TD
394
- CTOR[constructor] --> EC[ElementController.forCustomElement creates or locates the controller]
395
- EC --> ATTACH[Controller captures element + definition, sets $fastController]
396
-
397
- CONN[connectedCallback] --> STAGE[stage = connecting]
398
- STAGE --> PRERENDER{Existing shadow root\nfrom SSR/DSD?}
399
- PRERENDER -->|yes| SETFLAG[isPrerendered = true\nisHydrated = pending]
400
- PRERENDER -->|no| NORMAL[isPrerendered = false\nisHydrated = false]
401
- SETFLAG --> OBS[Restore pre-upgrade observable values]
402
- NORMAL --> OBS
403
- OBS --> BEHAV[Connect HostBehaviors]
404
- BEHAV --> RENDER{isPrerendered AND\ntemplate is hydratable?}
405
- RENDER -->|yes| HYDRATE[template.hydrate → HydrationView\nmaps existing DOM to binding targets\nisHydrated = true]
406
- RENDER -->|no| CLONE[ViewTemplate.render → HTMLView.appendTo shadow root]
407
- HYDRATE --> STYLES[Apply ElementStyles to shadow root]
408
- CLONE --> STYLES
409
- STYLES --> DONE[stage = connected]
410
-
411
- ATTR[attributeChangedCallback] --> ATTRGUARD{isPrerendered AND\nneedsInitialization?}
412
- ATTRGUARD -->|yes| SKIP[Skip — server-rendered values already correct]
413
- ATTRGUARD -->|no| ACD[AttributeDefinition.onAttributeChangedCallback]
414
- ACD --> ENQ[Updates.enqueue – reflect new value via Observable accessor]
415
-
416
- DISC[disconnectedCallback] --> DBEHAV[Disconnect HostBehaviors]
417
- DBEHAV --> UNBIND[HTMLView.unbind]
418
- UNBIND --> DSTAGE[stage = disconnected]
419
- ```
420
-
421
- ### Template Pipeline
422
-
423
- ```mermaid
424
- flowchart LR
425
- TAG["html\`...\` tag call"]
426
- CREATE["ViewTemplate.create() (static)\nBuilds HTML string with\nfactory placeholder IDs\nand factories dictionary"]
427
- LAZY["First render call\nViewTemplate.create() / render()"]
428
- COMPILE["ViewTemplate.compile()\n→ Compiler.compile()\nParses <template> innerHTML\nBuilds CompilationContext\nwith node ID descriptors"]
429
- CLONE["CompilationContext.createView()\nClones DocumentFragment\nInstantiates ViewBehaviors"]
430
- VIEW["HTMLView\nDOM nodes + behaviors"]
431
- BIND["HTMLView.bind(source, context)\nEach ViewBehavior.bind(controller)\nEvaluates expressions\nWrites to DOM"]
432
-
433
- TAG --> CREATE
434
- CREATE --> LAZY
435
- LAZY --> COMPILE
436
- COMPILE --> CLONE
437
- CLONE --> VIEW
438
- VIEW --> BIND
439
- ```
440
-
441
- ### Observable Change Propagation
442
-
443
- ```mermaid
444
- flowchart TD
445
- SET["element.property = newValue\n(Observable setter)"]
446
- NOTIFY["PropertyChangeNotifier.notify(propertyName)"]
447
- SUBS["For each Subscriber in SubscriberSet\nsubscriber.handleChange(subject, propertyName)"]
448
- ENQ["Updates.enqueue(binding task)"]
449
- RAF["requestAnimationFrame fires\nUpdates.process()"]
450
- EVAL["ExpressionNotifier re-evaluates expression"]
451
- DOM["DOM aspect updated\n(attribute / property / content / event)"]
452
-
453
- SET --> NOTIFY
454
- NOTIFY --> SUBS
455
- SUBS --> ENQ
456
- ENQ --> RAF
457
- RAF --> EVAL
458
- EVAL --> GUARD{"Controller still bound?"}
459
- GUARD -->|yes| DOM
460
- GUARD -->|no| DROP["Notification dropped\n(stale observer)"]
461
- ```
462
-
463
- > **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.
464
-
465
- ---
466
-
467
- ## How the Pieces Fit Together
468
-
469
- Below is a conceptual map of the major subsystems and their relationships:
470
-
471
- ```
472
- ┌──────────────────────────────────────────────────────────────────────────────┐
473
- │ FAST (module-scoped singleton) │
474
- │ warn / error / addMessages — diagnostic messaging │
475
- └────────────────────┬─────────────────────────────────────────────────────────┘
476
- │ ES module imports
477
- ┌───────────┴───────────┐
478
- │ │
479
- ┌────────▼──────────┐ ┌────────▼────────────────────┐
480
- │ Observable / │ │ Updates queue │
481
- │ ExpressionNotifier│ │ (rAF-batched task runner) │
482
- │ SubscriberSet │ └────────────────────────────-─┘
483
- └────────┬──────────┘ ▲
484
- │ dependency tracking │ enqueue
485
- ▼ │
486
- ┌────────────────────────────────┴──────────────────────────────┐
487
- │ Binding system │
488
- │ oneWay / oneTime / listener → Binding → ExpressionObserver │
489
- └────────────────────────┬──────────────────────────────────────┘
490
- │ drives
491
- ┌────────────────────────▼──────────────────────────────────────┐
492
- │ Templating pipeline │
493
- │ html tag → ViewTemplate → Compiler → CompilationContext │
494
- │ createView → HTMLView → ViewBehaviors (bind/update DOM) │
495
- └────────────────────────┬──────────────────────────────────────┘
496
- │ owned by
497
- ┌────────────────────────▼──────────────────────────────────────┐
498
- │ ElementController │
499
- │ Lifecycle (connect/disconnect/attr) • Styles • Behaviors │
500
- └────────────────────────┬──────────────────────────────────────┘
501
- │ wraps
502
- ┌────────────────────────▼──────────────────────────────────────┐
503
- │ FASTElement (HTMLElement subclass) │
504
- │ + FASTElementDefinition (metadata: name, template, styles) │
505
- └───────────────────────────────────────────────────────────────┘
506
- │ optional higher-level services
507
- ├──────────────────────────────────────────────┐
508
- ┌────────▼──────────┐ ┌──────────▼──────────┐
509
- │ DI container │ │ Context protocol │
510
- │ (di/di.ts) │ │ (context.ts) │
511
- └───────────────────┘ └─────────────────────┘
512
- ```
513
-
514
- **Authoring flow summary**:
515
-
516
- 1. Developer writes a class extending `FASTElement`, decorates properties with `@observable` / `@attr`, and calls `FASTElement.define({ name, template, styles })`.
517
- 2. `FASTElement.define` → `FASTElementDefinition.compose(...).define()` registers the element with the Custom Element Registry.
518
- 3. When the browser upgrades the element, `ElementController.forCustomElement(element)` is called in the constructor.
519
- 4. On `connectedCallback`, the controller renders the template into the shadow root. If the element already has a shadow root from SSR (prerendered content) and hydration has been enabled via `enableHydration()`, the installed hydration hook uses `template.hydrate()` to map existing DOM nodes to binding targets instead of cloning new DOM. If no template is available yet, the element connects without rendering until a later `definition.template` update recreates the controller. Compilation is lazy: the first render call triggers `Compiler.compile()`, subsequent calls clone the already-compiled `DocumentFragment`.
520
- 5. `HTMLView.bind(source)` wires up each `ViewBehavior`. `oneWay` bindings create `ExpressionNotifier`s that track observable dependencies automatically.
521
- 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.
522
- 7. On `disconnectedCallback`, `HTMLView.unbind()` tears down all bindings; behaviors disconnect; styles are removed.
523
-
524
- ---
525
-
526
- ## Package Layout
527
-
528
- ```
529
- src/
530
- ├── interfaces.ts # Core types: Callable, Constructable, Message codes
531
- ├── platform.ts # FAST module-scoped singleton, TypeRegistry
532
- ├── declarative/ # Pure declarative entrypoint and map helpers
533
- ├── dom.ts # DOMAspect enum, DOMPolicy, DOMSink
534
- ├── dom-policy.ts # Default DOM security policy (TrustedTypes integration)
535
- ├── metadata.ts # Reflect-based metadata helpers
536
- ├── utilities.ts # UnobservableMutationObserver and other helpers
537
- ├── debug.ts # Exports enableDebug() for human-readable FAST errors
538
- ├── observation/
539
- │ ├── observable.ts # Observable, @observable, ExpressionNotifier, ExecutionContext
540
- │ ├── notifier.ts # Subscriber, Notifier, SubscriberSet, PropertyChangeNotifier
541
- │ ├── arrays.ts # ArrayObserver, Splice, SpliceStrategy
542
- │ └── update-queue.ts # Updates (UpdateQueue)
543
- ├── binding/
544
- │ ├── binding.ts # Binding abstract base class, BindingDirective
545
- │ ├── one-way.ts # oneWay, listener
546
- │ ├── one-time.ts # oneTime
547
- │ └── normalize.ts # normalizeBinding helper
548
- ├── templating/
549
- │ ├── template.ts # ViewTemplate, html tag, InlineTemplateDirective
550
- │ ├── compiler.ts # Compiler, CompilationContext
551
- │ ├── view.ts # HTMLView, ElementView, SyntheticView
552
- │ ├── html-directive.ts # HTMLDirective, ViewBehavior, ViewBehaviorFactory
553
- │ ├── html-binding-directive.ts # HTMLBindingDirective
554
- │ ├── markup.ts # Markup placeholders, Parser
555
- │ ├── when.ts # when directive
556
- │ ├── repeat.ts # repeat directive
557
- │ ├── ref.ts # ref directive
558
- │ ├── render.ts # render directive
559
- │ ├── children.ts # children directive
560
- │ ├── slotted.ts # slotted directive
561
- │ └── TEMPLATE-BINDINGS.md
562
- ├── styles/
563
- │ ├── css.ts # css tag
564
- │ ├── element-styles.ts # ElementStyles
565
- │ ├── css-directive.ts # CSSDirective, @cssDirective
566
- │ └── host.ts # HostBehavior, HostController
567
- ├── components/
568
- │ ├── fast-element.ts # FASTElement, @customElement
569
- │ ├── element-controller.ts # ElementController, Stages
570
- │ ├── fast-definitions.ts # FASTElementDefinition, optional definition schema
571
- │ ├── schema.ts # Schema class and schemaRegistry
572
- │ ├── definition-schema-transforms.ts # Definition-scoped schema transform storage
573
- │ └── attributes.ts # AttributeDefinition, @attr, converters
574
- ├── extensions/
575
- │ ├── observer-map.ts # observerMap() extension and proxy-backed observation helpers
576
- │ └── attribute-map.ts # attributeMap() extension and automatic @attr helpers
577
- ├── di/
578
- │ └── di.ts # DI container, decorators, resolvers, Registration
579
- ├── context.ts # Context, FASTContext, Context protocol
580
- ├── declarative/
581
- │ ├── template.ts # declarativeTemplate() and internal f-template publisher
582
- │ ├── template-parser.ts # Declarative HTML parser → ViewTemplate strings/values
583
- │ ├── schema.ts # Compatibility re-export for Schema
584
- │ ├── definition-options.ts # Compatibility re-export for schema transforms
585
- │ ├── observer-map.ts # Internal observer-map extension alias (not a package export)
586
- │ ├── attribute-map.ts # Internal attribute-map extension alias (not a package export)
587
- │ ├── utilities.ts # Declarative parsing utilities
588
- │ └── syntax.ts # Declarative syntax constants
589
- ├── state/
590
- │ ├── state.ts # state() helper (beta)
591
- │ └── watch.ts # watch() helper (beta)
592
- └── hydration/
593
- └── target-builder.ts # Hydration target resolution
594
- ```
595
-
596
- ---
597
-
598
- ## Detailed Architecture Documents
599
-
600
- | Document | What it covers |
601
- |---|---|
602
- | [ARCHITECTURE_INTRO.md](./ARCHITECTURE_INTRO.md) | Glossary / index for all architecture docs |
603
- | [ARCHITECTURE_OVERVIEW.md](./ARCHITECTURE_OVERVIEW.md) | General FAST usage, compose/define flow, module load sequence |
604
- | [ARCHITECTURE_FASTELEMENT.md](./ARCHITECTURE_FASTELEMENT.md) | FASTElement & ElementController lifecycle in detail |
605
- | [ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md](./ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md) | `html` tag, directives, binding pre-processing |
606
- | [ARCHITECTURE_UPDATES.md](./ARCHITECTURE_UPDATES.md) | Updates queue, attribute and observable change batching |
607
- | [DECLARATIVE_DESIGN.md](./DECLARATIVE_DESIGN.md) | Declarative HTML runtime, parser, schema, maps, and fixture architecture |
608
- | [src/templating/TEMPLATE-BINDINGS.md](./src/templating/TEMPLATE-BINDINGS.md) | Full template binding pipeline: authoring → compilation → binding → DOM updates |
609
- | [docs/fast-element-2-changes.md](./docs/fast-element-2-changes.md) | Breaking changes from v1 to v2 |
610
-
611
- ---
612
-
613
- ## Bundle Size Reporting
614
-
615
- The build generates a `SIZES.md` file that records minified, gzip, and brotli sizes for the CDN rollup bundle and each individually tree-shaken export. Sizes are measured using `esbuild` for per-export bundles and from the Rollup minified output for the CDN rollup bundle. Compression sizes use Node.js `node:zlib`. The documentation site copies this file into the resources section during its prebuild step.