@microsoft/fast-element 2.10.3 → 3.0.0-rc.1

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 (351) hide show
  1. package/ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md +1 -1
  2. package/ARCHITECTURE_OVERVIEW.md +2 -2
  3. package/CHANGELOG.json +31 -1
  4. package/CHANGELOG.md +10 -2
  5. package/DECLARATIVE_DESIGN.md +806 -0
  6. package/DECLARATIVE_HTML.md +470 -0
  7. package/DECLARATIVE_MIGRATION.md +215 -0
  8. package/DECLARATIVE_RENDERING.md +530 -0
  9. package/DECLARATIVE_RENDERING_LIFECYCLE.md +288 -0
  10. package/DECLARATIVE_SCHEMA_OBSERVER_MAP.md +489 -0
  11. package/DESIGN.md +143 -34
  12. package/MIGRATION.md +387 -0
  13. package/README.md +208 -1
  14. package/SIZES.md +25 -0
  15. package/api-extractor.arrays.json +15 -0
  16. package/api-extractor.context.json +1 -0
  17. package/api-extractor.declarative.json +15 -0
  18. package/api-extractor.di.json +1 -0
  19. package/api-extractor.hydration.json +15 -0
  20. package/api-extractor.styles.json +15 -0
  21. package/dist/arrays/arrays.api.json +2621 -0
  22. package/dist/context/context.api.json +1 -1
  23. package/dist/declarative/declarative.api.json +7844 -0
  24. package/dist/di/di.api.json +2 -2
  25. package/dist/dts/array-observer.d.ts +2 -0
  26. package/dist/dts/arrays.d.ts +2 -0
  27. package/dist/dts/attr.d.ts +1 -0
  28. package/dist/dts/binding/signal.d.ts +6 -6
  29. package/dist/dts/binding/two-way.d.ts +1 -0
  30. package/dist/dts/binding.d.ts +7 -0
  31. package/dist/dts/components/attributes.d.ts +2 -5
  32. package/dist/dts/components/definition-schema-transforms.d.ts +9 -0
  33. package/dist/dts/components/element-controller.d.ts +80 -114
  34. package/dist/dts/components/element-hydration.d.ts +1 -1
  35. package/dist/dts/components/enable-hydration.d.ts +34 -0
  36. package/dist/dts/components/fast-definitions.d.ts +91 -42
  37. package/dist/dts/components/fast-element.d.ts +5 -8
  38. package/dist/dts/components/hydration-tracker.d.ts +40 -0
  39. package/dist/dts/components/hydration.d.ts +18 -53
  40. package/dist/dts/components/schema.d.ts +205 -0
  41. package/dist/dts/context.d.ts +6 -6
  42. package/dist/dts/css.d.ts +3 -0
  43. package/dist/dts/debug.d.ts +5 -1
  44. package/dist/dts/declarative/attribute-map.d.ts +58 -0
  45. package/dist/dts/declarative/debug.d.ts +5 -0
  46. package/dist/dts/declarative/index.d.ts +13 -0
  47. package/dist/dts/declarative/interfaces.d.ts +9 -0
  48. package/dist/dts/declarative/observer-map-utilities.d.ts +58 -0
  49. package/dist/dts/declarative/observer-map.d.ts +89 -0
  50. package/dist/dts/declarative/runtime.d.ts +5 -0
  51. package/dist/dts/declarative/syntax.d.ts +21 -0
  52. package/dist/dts/declarative/template-bridge.d.ts +33 -0
  53. package/dist/dts/declarative/template-parser.d.ts +98 -0
  54. package/dist/dts/declarative/template.d.ts +9 -0
  55. package/dist/dts/declarative/utilities.d.ts +312 -0
  56. package/dist/dts/di/di.d.ts +1 -1
  57. package/dist/dts/directives/children.d.ts +2 -0
  58. package/dist/dts/directives/node-observation.d.ts +2 -0
  59. package/dist/dts/directives/ref.d.ts +2 -0
  60. package/dist/dts/directives/repeat.d.ts +4 -0
  61. package/dist/dts/directives/slotted.d.ts +2 -0
  62. package/dist/dts/directives/when.d.ts +3 -0
  63. package/dist/dts/dom-policy.d.ts +1 -1
  64. package/dist/dts/html.d.ts +5 -0
  65. package/dist/dts/hydration/runtime.d.ts +7 -0
  66. package/dist/dts/hydration/target-builder.d.ts +15 -12
  67. package/dist/dts/hydration.d.ts +14 -0
  68. package/dist/dts/index.d.ts +38 -42
  69. package/dist/dts/index.debug.d.ts +0 -1
  70. package/dist/dts/index.rollup.debug.d.ts +0 -1
  71. package/dist/dts/interfaces.d.ts +1 -49
  72. package/dist/dts/observable.d.ts +3 -6
  73. package/dist/dts/observation/arrays.d.ts +1 -1
  74. package/dist/dts/observation/update-queue.d.ts +1 -1
  75. package/dist/dts/platform.d.ts +25 -4
  76. package/dist/dts/render.d.ts +7 -0
  77. package/dist/dts/schema.d.ts +1 -0
  78. package/dist/dts/state/exports.d.ts +1 -1
  79. package/dist/dts/state/state.d.ts +2 -2
  80. package/dist/dts/styles/css-directive.d.ts +5 -12
  81. package/dist/dts/styles/css.d.ts +5 -7
  82. package/dist/dts/styles/element-styles.d.ts +0 -10
  83. package/dist/dts/styles.d.ts +6 -0
  84. package/dist/dts/templating/children.d.ts +1 -1
  85. package/dist/dts/templating/html-binding-directive.d.ts +10 -0
  86. package/dist/dts/templating/html-directive.d.ts +17 -0
  87. package/dist/dts/templating/hydration-view.d.ts +109 -0
  88. package/dist/dts/templating/ref.d.ts +1 -1
  89. package/dist/dts/templating/render.d.ts +8 -2
  90. package/dist/dts/templating/repeat.d.ts +2 -2
  91. package/dist/dts/templating/slotted.d.ts +1 -1
  92. package/dist/dts/templating/template.d.ts +17 -9
  93. package/dist/dts/templating/view.d.ts +25 -102
  94. package/dist/dts/templating/when.d.ts +1 -1
  95. package/dist/dts/templating.d.ts +10 -0
  96. package/dist/dts/testing/exports.d.ts +2 -2
  97. package/dist/dts/tsdoc-metadata.json +1 -1
  98. package/dist/dts/updates.d.ts +1 -0
  99. package/dist/dts/volatile.d.ts +2 -0
  100. package/dist/esm/array-observer.js +1 -0
  101. package/dist/esm/arrays.js +1 -0
  102. package/dist/esm/attr.js +1 -0
  103. package/dist/esm/binding/normalize.js +1 -1
  104. package/dist/esm/binding/signal.js +4 -4
  105. package/dist/esm/binding/two-way.js +2 -1
  106. package/dist/esm/binding.js +4 -0
  107. package/dist/esm/components/attributes.js +8 -5
  108. package/dist/esm/components/definition-schema-transforms.js +23 -0
  109. package/dist/esm/components/element-controller.js +200 -269
  110. package/dist/esm/components/element-hydration.js +1 -1
  111. package/dist/esm/components/enable-hydration.js +100 -0
  112. package/dist/esm/components/fast-definitions.js +211 -49
  113. package/dist/esm/components/fast-element.js +18 -27
  114. package/dist/esm/components/hydration-tracker.js +93 -0
  115. package/dist/esm/components/hydration.js +62 -144
  116. package/dist/esm/components/schema.js +253 -0
  117. package/dist/esm/context.js +6 -6
  118. package/dist/esm/css.js +3 -0
  119. package/dist/esm/debug.js +26 -26
  120. package/dist/esm/declarative/attribute-map.js +121 -0
  121. package/dist/esm/declarative/debug.js +5 -0
  122. package/dist/esm/declarative/index.js +3 -0
  123. package/dist/esm/declarative/interfaces.js +10 -0
  124. package/dist/esm/declarative/observer-map-utilities.js +562 -0
  125. package/dist/esm/declarative/observer-map.js +216 -0
  126. package/dist/esm/declarative/runtime.js +14 -0
  127. package/dist/esm/declarative/syntax.js +36 -0
  128. package/dist/esm/declarative/template-bridge.js +170 -0
  129. package/dist/esm/declarative/template-parser.js +306 -0
  130. package/dist/esm/declarative/template.js +142 -0
  131. package/dist/esm/declarative/utilities.js +834 -0
  132. package/dist/esm/di/di.js +6 -8
  133. package/dist/esm/directives/children.js +1 -0
  134. package/dist/esm/directives/node-observation.js +1 -0
  135. package/dist/esm/directives/ref.js +1 -0
  136. package/dist/esm/directives/repeat.js +1 -0
  137. package/dist/esm/directives/slotted.js +1 -0
  138. package/dist/esm/directives/when.js +1 -0
  139. package/dist/esm/dom-policy.js +2 -2
  140. package/dist/esm/dom.js +1 -1
  141. package/dist/esm/html.js +2 -0
  142. package/dist/esm/hydration/runtime.js +33 -0
  143. package/dist/esm/hydration/target-builder.js +97 -90
  144. package/dist/esm/hydration.js +4 -0
  145. package/dist/esm/index.debug.js +2 -1
  146. package/dist/esm/index.js +34 -29
  147. package/dist/esm/index.rollup.debug.js +3 -2
  148. package/dist/esm/index.rollup.js +1 -1
  149. package/dist/esm/interfaces.js +1 -45
  150. package/dist/esm/observable.js +1 -4
  151. package/dist/esm/observation/arrays.js +1 -1
  152. package/dist/esm/observation/observable.js +5 -5
  153. package/dist/esm/observation/update-queue.js +47 -58
  154. package/dist/esm/platform.js +31 -30
  155. package/dist/esm/render.js +1 -0
  156. package/dist/esm/schema.js +1 -0
  157. package/dist/esm/state/exports.js +1 -1
  158. package/dist/esm/styles/css-directive.js +1 -2
  159. package/dist/esm/styles/css.js +15 -56
  160. package/dist/esm/styles/element-styles.js +69 -15
  161. package/dist/esm/styles.js +2 -0
  162. package/dist/esm/templating/html-binding-directive.js +24 -10
  163. package/dist/esm/templating/hydration-view.js +235 -0
  164. package/dist/esm/templating/render.js +13 -2
  165. package/dist/esm/templating/repeat.js +36 -34
  166. package/dist/esm/templating/template.js +7 -7
  167. package/dist/esm/templating/view.js +24 -233
  168. package/dist/esm/templating.js +7 -0
  169. package/dist/esm/testing/exports.js +2 -2
  170. package/dist/esm/updates.js +1 -0
  171. package/dist/esm/volatile.js +1 -0
  172. package/dist/fast-element.api.json +9017 -6996
  173. package/dist/fast-element.d.ts +3557 -796
  174. package/dist/fast-element.debug.js +5093 -4419
  175. package/dist/fast-element.debug.min.js +2 -2
  176. package/dist/fast-element.js +5398 -4655
  177. package/dist/fast-element.min.js +2 -2
  178. package/dist/fast-element.untrimmed.d.ts +881 -481
  179. package/dist/hydration/hydration.api.json +5237 -0
  180. package/dist/styles/styles.api.json +2672 -0
  181. package/docs/api-report.api.md +344 -167
  182. package/docs/arrays/api-report.api.md +114 -0
  183. package/docs/declarative/api-report.api.md +397 -0
  184. package/docs/hydration/api-report.api.md +285 -0
  185. package/docs/styles/api-report.api.md +135 -0
  186. package/package.json +149 -40
  187. package/playwright.declarative.config.ts +26 -0
  188. package/playwright.declarative.webui.config.ts +20 -0
  189. package/scripts/declarative/build-fixtures-with-webui.js +135 -0
  190. package/scripts/declarative/build-fixtures.js +49 -0
  191. package/scripts/declarative/build-fixtures.utilities.js +101 -0
  192. package/scripts/measure-sizes.js +219 -0
  193. package/scripts/run-api-extractor.js +39 -20
  194. package/test/declarative/fixtures/README.md +72 -0
  195. package/test/declarative/fixtures/WRITING_FIXTURES.md +330 -0
  196. package/test/declarative/fixtures/bindings/README.md +12 -0
  197. package/test/declarative/fixtures/bindings/attribute/entry.html +13 -0
  198. package/test/declarative/fixtures/bindings/attribute/fast-build.config.json +6 -0
  199. package/test/declarative/fixtures/bindings/attribute/index.html +25 -0
  200. package/test/declarative/fixtures/bindings/attribute/main.ts +41 -0
  201. package/test/declarative/fixtures/bindings/attribute/state.json +8 -0
  202. package/test/declarative/fixtures/bindings/attribute/templates.html +11 -0
  203. package/test/declarative/fixtures/bindings/content/entry.html +12 -0
  204. package/test/declarative/fixtures/bindings/content/fast-build.config.json +6 -0
  205. package/test/declarative/fixtures/bindings/content/index.html +19 -0
  206. package/test/declarative/fixtures/bindings/content/main.ts +27 -0
  207. package/test/declarative/fixtures/bindings/content/state.json +4 -0
  208. package/test/declarative/fixtures/bindings/content/templates.html +6 -0
  209. package/test/declarative/fixtures/bindings/dot-syntax/entry.html +11 -0
  210. package/test/declarative/fixtures/bindings/dot-syntax/fast-build.config.json +6 -0
  211. package/test/declarative/fixtures/bindings/dot-syntax/index.html +47 -0
  212. package/test/declarative/fixtures/bindings/dot-syntax/main.ts +59 -0
  213. package/test/declarative/fixtures/bindings/dot-syntax/state.json +16 -0
  214. package/test/declarative/fixtures/bindings/dot-syntax/templates.html +17 -0
  215. package/test/declarative/fixtures/bindings/event/entry.html +11 -0
  216. package/test/declarative/fixtures/bindings/event/fast-build.config.json +6 -0
  217. package/test/declarative/fixtures/bindings/event/index.html +43 -0
  218. package/test/declarative/fixtures/bindings/event/main.ts +43 -0
  219. package/test/declarative/fixtures/bindings/event/state.json +3 -0
  220. package/test/declarative/fixtures/bindings/event/templates.html +18 -0
  221. package/test/declarative/fixtures/bindings/host/entry.html +40 -0
  222. package/test/declarative/fixtures/bindings/host/fast-build.config.json +6 -0
  223. package/test/declarative/fixtures/bindings/host/index.html +96 -0
  224. package/test/declarative/fixtures/bindings/host/main.ts +222 -0
  225. package/test/declarative/fixtures/bindings/host/state.json +9 -0
  226. package/test/declarative/fixtures/bindings/host/templates.html +55 -0
  227. package/test/declarative/fixtures/directives/README.md +12 -0
  228. package/test/declarative/fixtures/directives/children/entry.html +11 -0
  229. package/test/declarative/fixtures/directives/children/fast-build.config.json +6 -0
  230. package/test/declarative/fixtures/directives/children/index.html +15 -0
  231. package/test/declarative/fixtures/directives/children/main.ts +22 -0
  232. package/test/declarative/fixtures/directives/children/state.json +3 -0
  233. package/test/declarative/fixtures/directives/children/templates.html +3 -0
  234. package/test/declarative/fixtures/directives/ref/entry.html +11 -0
  235. package/test/declarative/fixtures/directives/ref/fast-build.config.json +6 -0
  236. package/test/declarative/fixtures/directives/ref/index.html +15 -0
  237. package/test/declarative/fixtures/directives/ref/main.ts +17 -0
  238. package/test/declarative/fixtures/directives/ref/state.json +1 -0
  239. package/test/declarative/fixtures/directives/ref/templates.html +3 -0
  240. package/test/declarative/fixtures/directives/repeat/entry.html +21 -0
  241. package/test/declarative/fixtures/directives/repeat/fast-build.config.json +6 -0
  242. package/test/declarative/fixtures/directives/repeat/index.html +133 -0
  243. package/test/declarative/fixtures/directives/repeat/main.ts +110 -0
  244. package/test/declarative/fixtures/directives/repeat/sprites.svg +8 -0
  245. package/test/declarative/fixtures/directives/repeat/state.json +10 -0
  246. package/test/declarative/fixtures/directives/repeat/templates.html +75 -0
  247. package/test/declarative/fixtures/directives/slotted/entry.html +17 -0
  248. package/test/declarative/fixtures/directives/slotted/fast-build.config.json +6 -0
  249. package/test/declarative/fixtures/directives/slotted/index.html +27 -0
  250. package/test/declarative/fixtures/directives/slotted/main.ts +29 -0
  251. package/test/declarative/fixtures/directives/slotted/state.json +1 -0
  252. package/test/declarative/fixtures/directives/slotted/templates.html +7 -0
  253. package/test/declarative/fixtures/directives/when/entry.html +51 -0
  254. package/test/declarative/fixtures/directives/when/fast-build.config.json +6 -0
  255. package/test/declarative/fixtures/directives/when/index.html +136 -0
  256. package/test/declarative/fixtures/directives/when/main.ts +172 -0
  257. package/test/declarative/fixtures/directives/when/state.json +12 -0
  258. package/test/declarative/fixtures/directives/when/templates.html +75 -0
  259. package/test/declarative/fixtures/ecosystem/README.md +11 -0
  260. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/entry.html +12 -0
  261. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/fast-build.config.json +6 -0
  262. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/index.html +20 -0
  263. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/main.ts +68 -0
  264. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/state.json +4 -0
  265. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/templates.html +7 -0
  266. package/test/declarative/fixtures/ecosystem/errors/entry.html +12 -0
  267. package/test/declarative/fixtures/ecosystem/errors/fast-build.config.json +6 -0
  268. package/test/declarative/fixtures/ecosystem/errors/index.html +20 -0
  269. package/test/declarative/fixtures/ecosystem/errors/main.ts +17 -0
  270. package/test/declarative/fixtures/ecosystem/errors/state.json +1 -0
  271. package/test/declarative/fixtures/ecosystem/errors/templates.html +7 -0
  272. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/entry.html +17 -0
  273. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/fast-build.config.json +6 -0
  274. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/index.html +56 -0
  275. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/main.ts +134 -0
  276. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/state.json +12 -0
  277. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/templates.html +34 -0
  278. package/test/declarative/fixtures/ecosystem/performance-metrics/entry.html +25 -0
  279. package/test/declarative/fixtures/ecosystem/performance-metrics/fast-build.config.json +6 -0
  280. package/test/declarative/fixtures/ecosystem/performance-metrics/fast-card.css +10 -0
  281. package/test/declarative/fixtures/ecosystem/performance-metrics/index.html +181 -0
  282. package/test/declarative/fixtures/ecosystem/performance-metrics/main.ts +58 -0
  283. package/test/declarative/fixtures/ecosystem/performance-metrics/state.json +6 -0
  284. package/test/declarative/fixtures/ecosystem/performance-metrics/templates.html +15 -0
  285. package/test/declarative/fixtures/extensions/README.md +15 -0
  286. package/test/declarative/fixtures/extensions/attribute-map/entry.html +14 -0
  287. package/test/declarative/fixtures/extensions/attribute-map/fast-build.config.json +6 -0
  288. package/test/declarative/fixtures/extensions/attribute-map/index.html +31 -0
  289. package/test/declarative/fixtures/extensions/attribute-map/main.ts +40 -0
  290. package/test/declarative/fixtures/extensions/attribute-map/state.json +4 -0
  291. package/test/declarative/fixtures/extensions/attribute-map/templates.html +14 -0
  292. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/entry.html +12 -0
  293. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/fast-build.config.json +7 -0
  294. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/index.html +25 -0
  295. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/main.ts +31 -0
  296. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/state.json +5 -0
  297. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/templates.html +11 -0
  298. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/entry.html +13 -0
  299. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/fast-build.config.json +7 -0
  300. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/index.html +23 -0
  301. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/main.ts +37 -0
  302. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/state.json +1 -0
  303. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/templates.html +9 -0
  304. package/test/declarative/fixtures/extensions/observer-map/entry.html +15 -0
  305. package/test/declarative/fixtures/extensions/observer-map/fast-build.config.json +6 -0
  306. package/test/declarative/fixtures/extensions/observer-map/index.html +442 -0
  307. package/test/declarative/fixtures/extensions/observer-map/main.ts +482 -0
  308. package/test/declarative/fixtures/extensions/observer-map/state.json +158 -0
  309. package/test/declarative/fixtures/extensions/observer-map/templates.html +172 -0
  310. package/test/declarative/fixtures/extensions/observer-map-config-object/entry.html +16 -0
  311. package/test/declarative/fixtures/extensions/observer-map-config-object/fast-build.config.json +6 -0
  312. package/test/declarative/fixtures/extensions/observer-map-config-object/index.html +27 -0
  313. package/test/declarative/fixtures/extensions/observer-map-config-object/main.ts +53 -0
  314. package/test/declarative/fixtures/extensions/observer-map-config-object/state.json +9 -0
  315. package/test/declarative/fixtures/extensions/observer-map-config-object/templates.html +12 -0
  316. package/test/declarative/fixtures/extensions/observer-map-deep-merge/README.md +98 -0
  317. package/test/declarative/fixtures/extensions/observer-map-deep-merge/entry.html +156 -0
  318. package/test/declarative/fixtures/extensions/observer-map-deep-merge/fast-build.config.json +6 -0
  319. package/test/declarative/fixtures/extensions/observer-map-deep-merge/index.html +376 -0
  320. package/test/declarative/fixtures/extensions/observer-map-deep-merge/main.ts +366 -0
  321. package/test/declarative/fixtures/extensions/observer-map-deep-merge/state.json +69 -0
  322. package/test/declarative/fixtures/extensions/observer-map-deep-merge/templates.html +91 -0
  323. package/test/declarative/fixtures/extensions/observer-map-properties/entry.html +14 -0
  324. package/test/declarative/fixtures/extensions/observer-map-properties/fast-build.config.json +6 -0
  325. package/test/declarative/fixtures/extensions/observer-map-properties/index.html +110 -0
  326. package/test/declarative/fixtures/extensions/observer-map-properties/main.ts +175 -0
  327. package/test/declarative/fixtures/extensions/observer-map-properties/state.json +29 -0
  328. package/test/declarative/fixtures/extensions/observer-map-properties/templates.html +55 -0
  329. package/test/declarative/fixtures/scenarios/README.md +7 -0
  330. package/test/declarative/fixtures/scenarios/nested-elements/entry.html +16 -0
  331. package/test/declarative/fixtures/scenarios/nested-elements/fast-build.config.json +6 -0
  332. package/test/declarative/fixtures/scenarios/nested-elements/index.html +126 -0
  333. package/test/declarative/fixtures/scenarios/nested-elements/main.ts +214 -0
  334. package/test/declarative/fixtures/scenarios/nested-elements/state.json +10 -0
  335. package/test/declarative/fixtures/scenarios/nested-elements/templates.html +54 -0
  336. package/test/declarative/index.html +12 -0
  337. package/test/declarative/vite.config.ts +55 -0
  338. package/test/declarative-main.ts +6 -0
  339. package/test/extension-subpaths-main.ts +9 -0
  340. package/test/main.ts +38 -33
  341. package/test/pure-declarative-main.ts +1 -0
  342. package/dist/dts/components/install-hydration.d.ts +0 -1
  343. package/dist/dts/pending-task.d.ts +0 -32
  344. package/dist/dts/polyfills.d.ts +0 -0
  345. package/dist/dts/styles/css-binding-directive.d.ts +0 -60
  346. package/dist/dts/templating/install-hydratable-view-templates.d.ts +0 -1
  347. package/dist/esm/components/install-hydration.js +0 -3
  348. package/dist/esm/pending-task.js +0 -28
  349. package/dist/esm/polyfills.js +0 -60
  350. package/dist/esm/styles/css-binding-directive.js +0 -76
  351. package/dist/esm/templating/install-hydratable-view-templates.js +0 -23
@@ -0,0 +1,330 @@
1
+ # Writing Fixtures
2
+
3
+ This guide explains how to create and maintain Playwright test fixtures for the
4
+ declarative runtime in `@microsoft/fast-element`. Each fixture is a
5
+ self-contained test case that exercises a specific feature through a live Vite
6
+ dev server.
7
+
8
+ ## Fixture structure
9
+
10
+ Every fixture lives in a category subdirectory under
11
+ `test/declarative/fixtures/`:
12
+
13
+ ```
14
+ test/declarative/fixtures/<category>/<feature>/
15
+ ├── <feature>.spec.ts # Playwright test
16
+ ├── entry.html # Entry template — input to the build step
17
+ ├── fast-build.config.json # Build configuration for @microsoft/fast-build
18
+ ├── index.html # Pre-rendered page — GENERATED, do not edit
19
+ ├── main.ts # Component definitions and setup
20
+ ├── state.json # Initial state for server-side rendering
21
+ └── templates.html # Declarative <f-template> definitions
22
+ ```
23
+
24
+ Fixtures are organized into five categories:
25
+
26
+ | Category | Description | Details |
27
+ |---|---|---|
28
+ | `bindings/` | Various binding types (attribute, content, event, etc.) | [README](./bindings/README.md) |
29
+ | `scenarios/` | Complex scenarios with edge cases involving multiple features | [README](./scenarios/README.md) |
30
+ | `directives/` | Attribute and element directives (`f-repeat`, `f-when`, `f-ref`, etc.) | [README](./directives/README.md) |
31
+ | `extensions/` | Additional functionality beyond direct configuration (attribute maps, observer maps) | [README](./extensions/README.md) |
32
+ | `ecosystem/` | Other ecosystem APIs (errors, lifecycle, performance) | [README](./ecosystem/README.md) |
33
+
34
+ > **Important:** `index.html` is generated by `npm run build:fixtures`. Never edit it by hand — your changes will be overwritten on the next build. If something looks wrong in `index.html`, fix the source files (`entry.html`, `state.json`, `templates.html`) and rebuild.
35
+
36
+ ---
37
+
38
+ ## Creating a new fixture
39
+
40
+ 1. Create a new directory under `test/declarative/fixtures/<category>/` with a
41
+ descriptive kebab-case name (e.g., `bindings/my-feature/`).
42
+ 2. Add the required files described below.
43
+ 3. Run `npm run build:fixtures -w @microsoft/fast-element` to generate
44
+ `index.html`.
45
+ 4. Write your Playwright tests in `<feature>.spec.ts`.
46
+ 5. Run `npm run test:chromium:declarative -w @microsoft/fast-element` to verify
47
+ everything works.
48
+
49
+ Fixtures are auto-discovered by scanning category directories for subdirectories that contain `entry.html`, `templates.html`, `state.json`, and `fast-build.config.json`. Both the build script and the Vite config pick up new fixtures automatically — no registration step is needed.
50
+
51
+ ---
52
+
53
+ ## fast-build.config.json
54
+
55
+ Each fixture must include a `fast-build.config.json` file that tells the `@microsoft/fast-build` CLI where to find the fixture's source files and how to build them. The build script passes `--config=<path>` to the CLI for each fixture.
56
+
57
+ ### Standard config
58
+
59
+ Most fixtures use the same standard configuration:
60
+
61
+ ```json
62
+ {
63
+ "entry": "entry.html",
64
+ "state": "state.json",
65
+ "output": "index.html",
66
+ "templates": "templates.html"
67
+ }
68
+ ```
69
+
70
+ ### Fixture-specific options
71
+
72
+ If a fixture needs custom build options (e.g., an attribute name strategy), add them to the config:
73
+
74
+ ```json
75
+ {
76
+ "entry": "entry.html",
77
+ "state": "state.json",
78
+ "output": "index.html",
79
+ "templates": "templates.html",
80
+ "attribute-name-strategy": "camelCase"
81
+ }
82
+ ```
83
+
84
+ Allowed keys: `entry`, `state`, `output`, `templates`, `attribute-name-strategy`. All values must be strings. File paths are resolved relative to the config file's directory.
85
+
86
+ > **Note:** Fixture configs must use the standard file names (`entry.html`, `state.json`, `index.html`, `templates.html`) because the build scripts and WebUI integration rely on these conventions for template injection and cross-renderer testing.
87
+
88
+ ---
89
+
90
+ ## entry.html
91
+
92
+ The entry file is a minimal HTML document that places your custom elements on the page. It serves as the input to the server-side renderer.
93
+
94
+ ```html
95
+ <!DOCTYPE html>
96
+ <html lang="en-US">
97
+ <head>
98
+ <meta charset="utf-8">
99
+ <title></title>
100
+ </head>
101
+ <body>
102
+ <my-element greeting="{{greeting}}"></my-element>
103
+ <script type="module" src="./main.ts"></script>
104
+ </body>
105
+ </html>
106
+ ```
107
+
108
+ ### Attribute binding guidelines
109
+
110
+ When writing attribute bindings on root elements in `entry.html`:
111
+
112
+ | Pattern | Guidance |
113
+ |---|---|
114
+ | `type="{{type}}"` (primitive same-name) | ✅ Fine — rendered onto the opening tag for `@attr` initialization. |
115
+ | `list="{{list}}"` (complex same-name) | ❌ Unnecessary — non-primitive values are stripped from the rendered tag; state propagation provides them automatically. |
116
+ | `foo="{{bar}}"` (rename) | ❌ Avoid — rename `bar` to `foo` in `state.json` instead. |
117
+ | `:items="{{emptyItems}}"` (property binding) | ✅ Acceptable when multiple instances of the same element need different values for the same property. |
118
+
119
+ ---
120
+
121
+ ## state.json
122
+
123
+ A JSON object containing the initial state that the server-side renderer uses to evaluate bindings. Property names should match what the templates and entry HTML reference.
124
+
125
+ ```json
126
+ {
127
+ "greeting": "Hello",
128
+ "isEnabled": true,
129
+ "items": ["A", "B", "C"]
130
+ }
131
+ ```
132
+
133
+ Keep `state.json` minimal — only include values that affect the pre-rendered output. Complex objects (arrays, nested data) are supported.
134
+
135
+ ---
136
+
137
+ ## templates.html
138
+
139
+ This file defines the declarative `<f-template>` elements that describe each custom element's shadow DOM. Each `<f-template>` has a `name` attribute matching the custom element tag name and contains a `<template>` child with the component's markup.
140
+
141
+ ```html
142
+ <f-template name="my-element">
143
+ <template>
144
+ <span>{{greeting}}</span>
145
+ </template>
146
+ </f-template>
147
+ ```
148
+
149
+ ### Template syntax
150
+
151
+ For a full reference of binding syntax, event bindings, directives (`f-when`,
152
+ `f-repeat`), and execution context access, see the [Syntax section of the
153
+ declarative docs](../../../DECLARATIVE_HTML.md#syntax).
154
+
155
+ Multiple `<f-template>` elements can be defined in a single `templates.html` — one per custom element used in the fixture.
156
+
157
+ ---
158
+
159
+ ## main.ts
160
+
161
+ The component definition file registers custom elements and configures the template system. Every fixture must:
162
+
163
+ 1. Define element classes extending `FASTElement`.
164
+ 2. Call `define()` on the element class with `template: declarativeTemplate()`.
165
+ 3. Use `declarativeTemplate(callbacks)` for per-element lifecycle callbacks,
166
+ `enableHydration()` for hydration callbacks, and define extensions such as
167
+ `attributeMap()` / `observerMap()` for schema behavior.
168
+ `declarativeTemplate()` registers FAST's internal `<f-template>` publisher
169
+ automatically.
170
+
171
+ ### Import paths
172
+
173
+ > **Important:** All imports in `main.ts` must use package names (for example
174
+ > `@microsoft/fast-element`), **not** relative paths.
175
+ > Relative imports will break the WebUI integration tests because fixtures are
176
+ > copied to a different directory structure during the integration build. The
177
+ > same applies to any other paths referenced in `main.ts`.
178
+
179
+ ### Basic pattern
180
+
181
+ ```typescript
182
+ import {
183
+ FASTElement,
184
+ attr,
185
+ observable,
186
+ } from "@microsoft/fast-element";
187
+ import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";
188
+
189
+ class MyElement extends FASTElement {
190
+ @attr
191
+ greeting: string = "Hello";
192
+ }
193
+ MyElement.define({
194
+ name: "my-element",
195
+ template: declarativeTemplate(),
196
+ });
197
+ ```
198
+
199
+ ### When to use `@attr` vs `@observable`
200
+
201
+ - Use `@attr` for values reflected as HTML attributes (strings, booleans) — these can be set in `entry.html`.
202
+ - Use `@observable` for internal state or complex values (arrays, objects) — these are provided via `state.json`.
203
+
204
+ ### Exporting types
205
+
206
+ If your spec file needs to reference element types (e.g., for `page.evaluate` calls), export the classes:
207
+
208
+ ```typescript
209
+ export class TestElement extends FASTElement {
210
+ @observable
211
+ list: Array<string> = [];
212
+ }
213
+ ```
214
+
215
+ Then import in the spec:
216
+
217
+ ```typescript
218
+ import type { TestElement } from "./main.js";
219
+
220
+ await customElement.evaluate((node: TestElement) => {
221
+ node.list = ["A", "B", "C"];
222
+ });
223
+ ```
224
+
225
+ ### Using ObserverMap
226
+
227
+ For fixtures that test deeply nested property reactivity, prefer the
228
+ definition-scoped `observerMap()` extension:
229
+
230
+ ```typescript
231
+ import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";
232
+ import { observerMap } from "@microsoft/fast-element/observer-map.js";
233
+
234
+ MyElement.define(
235
+ {
236
+ name: "my-element",
237
+ template: declarativeTemplate(),
238
+ },
239
+ [observerMap()],
240
+ );
241
+ ```
242
+
243
+ This enables the `ObserverMap` proxy system to track nested property changes without requiring `@observable` decorators on every property.
244
+
245
+ ---
246
+
247
+ ## Writing the spec file
248
+
249
+ Spec files use Playwright's test runner. Each fixture's tests navigate to the fixture page and interact with the rendered components.
250
+
251
+ ### Basic structure
252
+
253
+ ```typescript
254
+ import { expect, test } from "@playwright/test";
255
+
256
+ test.describe("my-feature", async () => {
257
+ test("initial render is correct", async ({ page }) => {
258
+ await page.goto("/fixtures/bindings/my-feature/");
259
+
260
+ const element = page.locator("my-element");
261
+ await expect(element).toHaveText("Hello");
262
+ });
263
+
264
+ test("responds to attribute changes", async ({ page }) => {
265
+ await page.goto("/fixtures/bindings/my-feature/");
266
+
267
+ const element = page.locator("my-element");
268
+
269
+ await page.evaluate(() => {
270
+ document
271
+ .querySelector("my-element")!
272
+ .setAttribute("greeting", "World");
273
+ });
274
+
275
+ await expect(element).toHaveText("World");
276
+ });
277
+ });
278
+ ```
279
+
280
+ ### Common patterns
281
+
282
+ - **Navigate to the fixture:** `await page.goto("/fixtures/<category>/<feature>/");`
283
+ - **Locate elements:** `page.locator("my-element")` or `page.locator("#specific-id")`
284
+ - **Modify attributes:** `await page.evaluate(() => { element.setAttribute(...) })`
285
+ - **Modify properties:** `await element.evaluate((node: MyElement) => { node.prop = value })`
286
+ - **Assert text:** `await expect(element).toHaveText("expected")`
287
+ - **Assert attributes:** `await expect(element).toHaveAttribute("attr", "value")`
288
+ - **Assert child count:** `await expect(element.locator("li")).toHaveCount(3)`
289
+
290
+ ---
291
+
292
+ ## Rebuilding fixtures
293
+
294
+ After editing `entry.html`, `templates.html`, `state.json`, or `fast-build.config.json`, you **must** regenerate `index.html`:
295
+
296
+ ```bash
297
+ npm run build:fixtures -w @microsoft/fast-element
298
+ ```
299
+
300
+ This invokes `@microsoft/fast-build` for each auto-discovered fixture with `--config` pointing to the fixture's `fast-build.config.json`. The CLI reads the config file to locate the entry template, state, template definitions, and output path, then renders the output. The build script then injects the `<f-template>` declarations from `templates.html` before the `<script>` tag in the generated output. Fixtures are discovered automatically by scanning category subdirectories for directories that contain `entry.html`, `templates.html`, `state.json`, and `fast-build.config.json`.
301
+
302
+ > **Tip:** If you're iterating on a fixture, use
303
+ > `npm run dev:declarative -w @microsoft/fast-element` to start the Vite dev
304
+ > server with file watching. But remember to run `build:fixtures` before
305
+ > committing — the Vite dev server uses the generated `index.html`.
306
+
307
+ ### WebUI integration
308
+
309
+ The same fixtures are also validated against `@microsoft/webui` to ensure cross-renderer compatibility. To build and test fixtures with webui:
310
+
311
+ ```bash
312
+ # Build fixtures with webui and run Playwright tests
313
+ npm run test:webui-integration -w @microsoft/fast-element
314
+
315
+ # Or run the steps separately
316
+ npm run build:fixtures:webui -w @microsoft/fast-element
317
+ npm exec -w @microsoft/fast-element -- playwright test --config=playwright.declarative.webui.config.ts
318
+ ```
319
+
320
+ The webui build step (`scripts/build-fixtures-with-webui.js`) extracts `<f-template>` elements, builds each fixture with `webui build --plugin=fast`, renders the output with `state.json`, and writes the result to `temp/integrations/webui/fixtures/`. The existing Playwright specs then run against this output.
321
+
322
+ ---
323
+
324
+ ## Checklist for new fixtures
325
+
326
+ - [ ] Created fixture directory within the appropriate category with all required files (including `fast-build.config.json`)
327
+ - [ ] Ran `npm run build:fixtures -w @microsoft/fast-element` to generate `index.html`
328
+ - [ ] Wrote Playwright tests in `<feature>.spec.ts`
329
+ - [ ] Tests pass locally with `npm run test:chromium:declarative -w @microsoft/fast-element`
330
+ - [ ] Committed all files **including** the generated `index.html`
@@ -0,0 +1,12 @@
1
+ # Bindings
2
+
3
+ Fixtures for testing the various binding types supported by FAST Element's
4
+ declarative templates.
5
+
6
+ | Fixture | Description |
7
+ |---|---|
8
+ | `attribute` | Attribute binding via `@attr` and `@observable` decorators on custom elements. |
9
+ | `content` | Content binding with `{{text}}` for escaped HTML and `{{{html}}}` for unescaped HTML injection. |
10
+ | `dot-syntax` | Dot-notation path access in bindings (e.g., `{{user.name}}`, `{{user.address.city}}`). |
11
+ | `event` | Event binding syntax with `@click="{handleClick()}"`, DOM event access via `$e`, and context access via `$c`. |
12
+ | `host` | Host element bindings for applying styles and attributes to the host element. |
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title></title>
6
+ </head>
7
+ <body>
8
+ <test-element type="{{type}}"></test-element>
9
+ <test-element-property></test-element-property>
10
+ <test-element-expression></test-element-expression>
11
+ <script type="module" src="./main.ts"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,6 @@
1
+ {
2
+ "entry": "entry.html",
3
+ "state": "state.json",
4
+ "output": "index.html",
5
+ "templates": "templates.html"
6
+ }
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title></title>
6
+ </head>
7
+ <body>
8
+ <test-element type="checkbox"><template shadowrootmode="open" shadowroot="open"><input type="checkbox" disabled data-fe="1"></template></test-element>
9
+ <test-element-property><template shadowrootmode="open" shadowroot="open"><input type="checkbox" disabled data-fe="1"></template></test-element-property>
10
+ <test-element-expression><template shadowrootmode="open" shadowroot="open"><input disabled type="button" data-fe="1"></template></test-element-expression>
11
+ <f-template name="test-element">
12
+ <template> <input type="{{type}}" disabled> </template>
13
+ </f-template>
14
+ <f-template name="test-element-property">
15
+ <template> <input type="checkbox" ?disabled="{{!isEnabled}}"> </template>
16
+ </f-template>
17
+ <f-template name="test-element-expression">
18
+ <template>
19
+ <input ?disabled="{{activeGroup == currentGroup}}" type="button">
20
+ </template>
21
+ </f-template>
22
+
23
+ <script type="module" src="./main.ts"></script>
24
+ </body>
25
+ </html>
@@ -0,0 +1,41 @@
1
+ import { attr } from "@microsoft/fast-element/attr.js";
2
+ import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";
3
+ import { FASTElement } from "@microsoft/fast-element/fast-element.js";
4
+ import { enableHydration } from "@microsoft/fast-element/hydration.js";
5
+ import { observable } from "@microsoft/fast-element/observable.js";
6
+
7
+ class TestElement extends FASTElement {
8
+ @attr
9
+ type: string = "radio";
10
+ }
11
+ TestElement.define({
12
+ name: "test-element",
13
+ template: declarativeTemplate(),
14
+ });
15
+
16
+ class TestElementProperty extends FASTElement {
17
+ @observable
18
+ isEnabled: boolean = false;
19
+ }
20
+ TestElementProperty.define({
21
+ name: "test-element-property",
22
+ template: declarativeTemplate(),
23
+ });
24
+
25
+ class TestElementExpression extends FASTElement {
26
+ @attr({ attribute: "active-group" })
27
+ activeGroup: string = "";
28
+
29
+ @attr({ attribute: "current-group" })
30
+ currentGroup: string = "";
31
+ }
32
+ TestElementExpression.define({
33
+ name: "test-element-expression",
34
+ template: declarativeTemplate(),
35
+ });
36
+
37
+ enableHydration({
38
+ hydrationComplete() {
39
+ (window as any).hydrationCompleted = true;
40
+ },
41
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "type": "checkbox",
3
+ "active-group": "work",
4
+ "current-group": "work",
5
+ "activeGroup": "work",
6
+ "currentGroup": "work",
7
+ "isEnabled": false
8
+ }
@@ -0,0 +1,11 @@
1
+ <f-template name="test-element">
2
+ <template> <input type="{{type}}" disabled> </template>
3
+ </f-template>
4
+ <f-template name="test-element-property">
5
+ <template> <input type="checkbox" ?disabled="{{!isEnabled}}"> </template>
6
+ </f-template>
7
+ <f-template name="test-element-expression">
8
+ <template>
9
+ <input ?disabled="{{activeGroup == currentGroup}}" type="button">
10
+ </template>
11
+ </f-template>
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title></title>
6
+ </head>
7
+ <body>
8
+ <test-element text="{{text}}"></test-element>
9
+ <test-element-unescaped html="{{html}}"></test-element-unescaped>
10
+ <script type="module" src="./main.ts"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,6 @@
1
+ {
2
+ "entry": "entry.html",
3
+ "state": "state.json",
4
+ "output": "index.html",
5
+ "templates": "templates.html"
6
+ }
@@ -0,0 +1,19 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title></title>
6
+ </head>
7
+ <body>
8
+ <test-element text="Hello world"><template shadowrootmode="open" shadowroot="open"><!--fe:b-->Hello world<!--fe:/b--></template></test-element>
9
+ <test-element-unescaped html="&lt;p&gt;Hello world&lt;/p&gt;"><template shadowrootmode="open" shadowroot="open"><!--fe:b--><p>Hello world</p><!--fe:/b--></template></test-element-unescaped>
10
+ <f-template name="test-element">
11
+ <template>{{text}}</template>
12
+ </f-template>
13
+ <f-template name="test-element-unescaped">
14
+ <template>{{{html}}}</template>
15
+ </f-template>
16
+
17
+ <script type="module" src="./main.ts"></script>
18
+ </body>
19
+ </html>
@@ -0,0 +1,27 @@
1
+ import { attr } from "@microsoft/fast-element/attr.js";
2
+ import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";
3
+ import { FASTElement } from "@microsoft/fast-element/fast-element.js";
4
+ import { enableHydration } from "@microsoft/fast-element/hydration.js";
5
+
6
+ class TestElement extends FASTElement {
7
+ @attr
8
+ text: string = "Hello";
9
+ }
10
+ TestElement.define({
11
+ name: "test-element",
12
+ template: declarativeTemplate(),
13
+ });
14
+
15
+ class TestElementUnescaped extends FASTElement {
16
+ public html = `<p>Hello world</p>`;
17
+ }
18
+ TestElementUnescaped.define({
19
+ name: "test-element-unescaped",
20
+ template: declarativeTemplate(),
21
+ });
22
+
23
+ enableHydration({
24
+ hydrationComplete() {
25
+ (window as any).hydrationCompleted = true;
26
+ },
27
+ });
@@ -0,0 +1,4 @@
1
+ {
2
+ "text": "Hello world",
3
+ "html": "<p>Hello world</p>"
4
+ }
@@ -0,0 +1,6 @@
1
+ <f-template name="test-element">
2
+ <template>{{text}}</template>
3
+ </f-template>
4
+ <f-template name="test-element-unescaped">
5
+ <template>{{{html}}}</template>
6
+ </f-template>
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title></title>
6
+ </head>
7
+ <body>
8
+ <test-element></test-element>
9
+ <script type="module" src="./main.ts"></script>
10
+ </body>
11
+ </html>
@@ -0,0 +1,6 @@
1
+ {
2
+ "entry": "entry.html",
3
+ "state": "state.json",
4
+ "output": "index.html",
5
+ "templates": "templates.html"
6
+ }
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title></title>
6
+ </head>
7
+ <body>
8
+ <test-element><template shadowrootmode="open" shadowroot="open"><span><!--fe:b-->bar<!--fe:/b--></span>
9
+ <span><!--fe:b--><!--fe:/b--></span>
10
+ <span><!--fe:b-->FOO<!--fe:/b--></span>
11
+ <button data-fe="1">Set b</button>
12
+ <button data-fe="1">Set a.b1</button>
13
+ <button data-fe="1">Set a.b2.c</button>
14
+ <!--fe:b-->
15
+ <!--fe:b--><!--fe:r-->
16
+ <!--fe:b-->
17
+ <div><!--fe:b-->Item 1<!--fe:/b--></div>
18
+ <!--fe:/b-->
19
+ <!--fe:/r--><!--fe:r-->
20
+ <!--fe:b-->
21
+ <div><!--fe:b-->Item 2<!--fe:/b--></div>
22
+ <!--fe:/b-->
23
+ <!--fe:/r--><!--fe:r-->
24
+ <!--fe:b--><!--fe:/b-->
25
+ <!--fe:/r--><!--fe:/b-->
26
+ <!--fe:/b--></template></test-element>
27
+ <f-template name="test-element">
28
+ <template>
29
+ <span>{{object.b}}</span>
30
+ <span>{{object.a.b1}}</span>
31
+ <span>{{object.a.b2.c}}</span>
32
+ <button @click="{handleBClick()}">Set b</button>
33
+ <button @click="{handleAB1Click()}">Set a.b1</button>
34
+ <button @click="{handleAB2CClick()}">Set a.b2.c</button>
35
+ <f-when value="{{object.c}}">
36
+ <f-repeat value="{{item in object.c}}">
37
+ <f-when value="{{item.name && item.status == 'active'}}">
38
+ <div>{{item.name}}</div>
39
+ </f-when>
40
+ </f-repeat>
41
+ </f-when>
42
+ </template>
43
+ </f-template>
44
+
45
+ <script type="module" src="./main.ts"></script>
46
+ </body>
47
+ </html>
@@ -0,0 +1,59 @@
1
+ import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";
2
+ import { FASTElement } from "@microsoft/fast-element/fast-element.js";
3
+ import { enableHydration } from "@microsoft/fast-element/hydration.js";
4
+ import { observerMap } from "@microsoft/fast-element/observer-map.js";
5
+
6
+ class TestElement extends FASTElement {
7
+ public object: any = {
8
+ a: {
9
+ b2: {
10
+ c: "FOO",
11
+ },
12
+ },
13
+ b: "bar",
14
+ c: [
15
+ {
16
+ name: "Item 1",
17
+ status: "active",
18
+ },
19
+ {
20
+ name: "Item 2",
21
+ status: "active",
22
+ },
23
+ {
24
+ status: "active",
25
+ },
26
+ ],
27
+ };
28
+
29
+ public handleBClick = () => {
30
+ this.object.b = "Hello";
31
+ };
32
+
33
+ public handleAB1Click = () => {
34
+ if (this.object.a) {
35
+ this.object.a.b1 = "World";
36
+ } else {
37
+ this.object.a = {
38
+ b1: "World",
39
+ };
40
+ }
41
+ };
42
+
43
+ public handleAB2CClick = () => {
44
+ this.object.a.b2.c = "Pluto";
45
+ };
46
+ }
47
+ TestElement.define(
48
+ {
49
+ name: "test-element",
50
+ template: declarativeTemplate(),
51
+ },
52
+ [observerMap()],
53
+ );
54
+
55
+ enableHydration({
56
+ hydrationComplete() {
57
+ (window as any).hydrationCompleted = true;
58
+ },
59
+ });