@repobit/dex-store-elements 1.7.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/CHANGELOG.md +5 -913
  2. package/README.md +9 -7
  3. package/dist/src/actions/action.adapter.d.ts +36 -0
  4. package/dist/src/actions/action.adapter.js +183 -0
  5. package/dist/src/actions/action.adapter.js.map +1 -0
  6. package/dist/src/actions/action.attributes.d.ts +15 -0
  7. package/dist/src/actions/action.attributes.js +137 -0
  8. package/dist/src/actions/action.attributes.js.map +1 -0
  9. package/dist/src/actions/action.registry.d.ts +4 -0
  10. package/dist/src/actions/action.registry.js +119 -0
  11. package/dist/src/actions/action.registry.js.map +1 -0
  12. package/dist/src/actions/index.d.ts +3 -2
  13. package/dist/src/actions/index.js +3 -80
  14. package/dist/src/actions/index.js.map +1 -1
  15. package/dist/src/compute/compute.expand.d.ts +70 -0
  16. package/dist/src/compute/compute.expand.js +319 -0
  17. package/dist/src/compute/compute.expand.js.map +1 -0
  18. package/dist/src/compute/compute.scan.d.ts +54 -0
  19. package/dist/src/compute/compute.scan.js +160 -0
  20. package/dist/src/compute/compute.scan.js.map +1 -0
  21. package/dist/src/compute/option-resolver.d.ts +31 -0
  22. package/dist/src/compute/option-resolver.js +147 -0
  23. package/dist/src/compute/option-resolver.js.map +1 -0
  24. package/dist/src/contexts/context.compute.d.ts +12 -0
  25. package/dist/src/contexts/context.compute.js +4 -0
  26. package/dist/src/contexts/context.compute.js.map +1 -0
  27. package/dist/src/contexts/context.scope.d.ts +139 -0
  28. package/dist/src/contexts/context.scope.js +48 -0
  29. package/dist/src/contexts/context.scope.js.map +1 -0
  30. package/dist/src/controllers/controller.action-resolve.d.ts +110 -0
  31. package/dist/src/controllers/controller.action-resolve.js +203 -0
  32. package/dist/src/controllers/controller.action-resolve.js.map +1 -0
  33. package/dist/src/controllers/controller.action-topology.d.ts +59 -0
  34. package/dist/src/controllers/controller.action-topology.js +130 -0
  35. package/dist/src/controllers/controller.action-topology.js.map +1 -0
  36. package/dist/src/controllers/controller.compute.d.ts +72 -0
  37. package/dist/src/controllers/controller.compute.js +110 -0
  38. package/dist/src/controllers/controller.compute.js.map +1 -0
  39. package/dist/src/controllers/controller.resolve.d.ts +78 -0
  40. package/dist/src/controllers/controller.resolve.js +205 -0
  41. package/dist/src/controllers/controller.resolve.js.map +1 -0
  42. package/dist/src/core/action-topology.d.ts +62 -0
  43. package/dist/src/core/action-topology.js +67 -0
  44. package/dist/src/core/action-topology.js.map +1 -0
  45. package/dist/src/core/actions.d.ts +64 -0
  46. package/dist/src/core/actions.js +47 -0
  47. package/dist/src/core/actions.js.map +1 -0
  48. package/dist/src/core/node.element.d.ts +179 -0
  49. package/dist/src/core/node.element.js +573 -0
  50. package/dist/src/core/node.element.js.map +1 -0
  51. package/dist/src/core/node.scope.d.ts +374 -0
  52. package/dist/src/core/node.scope.js +558 -0
  53. package/dist/src/core/node.scope.js.map +1 -0
  54. package/dist/src/core/option-update.d.ts +11 -0
  55. package/dist/src/core/option-update.js +59 -0
  56. package/dist/src/core/option-update.js.map +1 -0
  57. package/dist/src/dsl/compilers/array/compiler.js +13 -14
  58. package/dist/src/dsl/compilers/array/compiler.js.map +1 -1
  59. package/dist/src/dsl/compilers/boolean/compiler.d.ts +1 -1
  60. package/dist/src/dsl/compilers/boolean/compiler.js +14 -27
  61. package/dist/src/dsl/compilers/boolean/compiler.js.map +1 -1
  62. package/dist/src/dsl/compilers/enum/compiler.js +7 -10
  63. package/dist/src/dsl/compilers/enum/compiler.js.map +1 -1
  64. package/dist/src/dsl/compilers/index.d.ts +1 -1
  65. package/dist/src/dsl/compilers/index.js +5 -5
  66. package/dist/src/dsl/compilers/index.js.map +1 -1
  67. package/dist/src/dsl/utilty.d.ts +0 -4
  68. package/dist/src/dsl/utilty.js +3 -30
  69. package/dist/src/dsl/utilty.js.map +1 -1
  70. package/dist/src/eta/batch.d.ts +123 -0
  71. package/dist/src/eta/batch.js +162 -0
  72. package/dist/src/eta/batch.js.map +1 -0
  73. package/dist/src/eta/batcher.d.ts +184 -0
  74. package/dist/src/eta/batcher.js +335 -0
  75. package/dist/src/eta/batcher.js.map +1 -0
  76. package/dist/src/eta/cache.d.ts +36 -0
  77. package/dist/src/eta/cache.js +56 -0
  78. package/dist/src/eta/cache.js.map +1 -0
  79. package/dist/src/eta/controller.d.ts +608 -0
  80. package/dist/src/eta/controller.js +1036 -0
  81. package/dist/src/eta/controller.js.map +1 -0
  82. package/dist/src/eta/factory.d.ts +74 -0
  83. package/dist/src/eta/factory.js +121 -0
  84. package/dist/src/eta/factory.js.map +1 -0
  85. package/dist/src/eta/idle.d.ts +39 -0
  86. package/dist/src/eta/idle.js +52 -0
  87. package/dist/src/eta/idle.js.map +1 -0
  88. package/dist/src/eta/index.d.ts +52 -0
  89. package/dist/src/eta/index.js +13 -0
  90. package/dist/src/eta/index.js.map +1 -0
  91. package/dist/src/eta/observer.d.ts +263 -0
  92. package/dist/src/eta/observer.js +263 -0
  93. package/dist/src/eta/observer.js.map +1 -0
  94. package/dist/src/eta/operations.d.ts +41 -0
  95. package/dist/src/eta/operations.js +59 -0
  96. package/dist/src/eta/operations.js.map +1 -0
  97. package/dist/src/eta/source-registry.d.ts +198 -0
  98. package/dist/src/eta/source-registry.js +267 -0
  99. package/dist/src/eta/source-registry.js.map +1 -0
  100. package/dist/src/eta/template-index.d.ts +285 -0
  101. package/dist/src/eta/template-index.js +642 -0
  102. package/dist/src/eta/template-index.js.map +1 -0
  103. package/dist/src/eta/types.d.ts +529 -0
  104. package/dist/src/eta/types.js +2 -0
  105. package/dist/src/eta/types.js.map +1 -0
  106. package/dist/src/index.d.ts +21 -9
  107. package/dist/src/index.js +22 -11
  108. package/dist/src/index.js.map +1 -1
  109. package/dist/src/nodes/node.context.d.ts +5 -3
  110. package/dist/src/nodes/node.context.js +48 -3
  111. package/dist/src/nodes/node.context.js.map +1 -1
  112. package/dist/src/nodes/node.option.d.ts +11 -31
  113. package/dist/src/nodes/node.option.js +158 -222
  114. package/dist/src/nodes/node.option.js.map +1 -1
  115. package/dist/src/nodes/node.product.d.ts +7 -11
  116. package/dist/src/nodes/node.product.js +85 -64
  117. package/dist/src/nodes/node.product.js.map +1 -1
  118. package/dist/src/renders/attributes/buyLink.d.ts +2 -2
  119. package/dist/src/renders/attributes/buyLink.js +14 -11
  120. package/dist/src/renders/attributes/buyLink.js.map +1 -1
  121. package/dist/src/renders/attributes/devices.d.ts +2 -2
  122. package/dist/src/renders/attributes/devices.js +9 -19
  123. package/dist/src/renders/attributes/devices.js.map +1 -1
  124. package/dist/src/renders/attributes/discount.d.ts +2 -2
  125. package/dist/src/renders/attributes/discount.js +56 -44
  126. package/dist/src/renders/attributes/discount.js.map +1 -1
  127. package/dist/src/renders/attributes/hide.d.ts +2 -2
  128. package/dist/src/renders/attributes/hide.js +49 -14
  129. package/dist/src/renders/attributes/hide.js.map +1 -1
  130. package/dist/src/renders/attributes/index.d.ts +3 -3
  131. package/dist/src/renders/attributes/index.js +2 -4
  132. package/dist/src/renders/attributes/index.js.map +1 -1
  133. package/dist/src/renders/attributes/price.d.ts +2 -2
  134. package/dist/src/renders/attributes/price.js +30 -44
  135. package/dist/src/renders/attributes/price.js.map +1 -1
  136. package/dist/src/renders/attributes/subscription.d.ts +2 -2
  137. package/dist/src/renders/attributes/subscription.js +14 -20
  138. package/dist/src/renders/attributes/subscription.js.map +1 -1
  139. package/dist/src/renders/attributes/utilty.d.ts +2 -0
  140. package/dist/src/renders/attributes/utilty.js +17 -4
  141. package/dist/src/renders/attributes/utilty.js.map +1 -1
  142. package/dist/src/renders/context.d.ts +122 -10
  143. package/dist/src/renders/context.js +140 -80
  144. package/dist/src/renders/context.js.map +1 -1
  145. package/dist/src/renders/format.js +2 -2
  146. package/dist/src/renders/format.js.map +1 -1
  147. package/dist/src/renders/index.d.ts +6 -2
  148. package/dist/src/renders/index.js +67 -29
  149. package/dist/src/renders/index.js.map +1 -1
  150. package/dist/src/renders/observe.d.ts +1 -4
  151. package/dist/src/renders/observe.js +10 -24
  152. package/dist/src/renders/observe.js.map +1 -1
  153. package/dist/src/renders/render.wrapper.d.ts +37 -0
  154. package/dist/src/renders/render.wrapper.js +147 -0
  155. package/dist/src/renders/render.wrapper.js.map +1 -0
  156. package/dist/src/templating/eta.js +1 -4
  157. package/dist/src/templating/eta.js.map +1 -1
  158. package/package.json +4 -5
  159. package/dist/src/actions/action.button.d.ts +0 -2
  160. package/dist/src/actions/action.button.js +0 -8
  161. package/dist/src/actions/action.button.js.map +0 -1
  162. package/dist/src/actions/action.input.d.ts +0 -2
  163. package/dist/src/actions/action.input.js +0 -43
  164. package/dist/src/actions/action.input.js.map +0 -1
  165. package/dist/src/actions/action.select.d.ts +0 -2
  166. package/dist/src/actions/action.select.js +0 -14
  167. package/dist/src/actions/action.select.js.map +0 -1
  168. package/dist/src/actions/utilty.d.ts +0 -16
  169. package/dist/src/actions/utilty.js +0 -149
  170. package/dist/src/actions/utilty.js.map +0 -1
  171. package/dist/src/contexts/context.datalayer.d.ts +0 -9
  172. package/dist/src/contexts/context.datalayer.js +0 -3
  173. package/dist/src/contexts/context.datalayer.js.map +0 -1
  174. package/dist/src/contexts/context.derived.d.ts +0 -12
  175. package/dist/src/contexts/context.derived.js +0 -3
  176. package/dist/src/contexts/context.derived.js.map +0 -1
  177. package/dist/src/contexts/context.option.d.ts +0 -5
  178. package/dist/src/contexts/context.option.js +0 -3
  179. package/dist/src/contexts/context.option.js.map +0 -1
  180. package/dist/src/contexts/context.product.d.ts +0 -5
  181. package/dist/src/contexts/context.product.js +0 -3
  182. package/dist/src/contexts/context.product.js.map +0 -1
  183. package/dist/src/contexts/context.state.d.ts +0 -28
  184. package/dist/src/contexts/context.state.js +0 -3
  185. package/dist/src/contexts/context.state.js.map +0 -1
  186. package/dist/src/contexts/context.store.d.ts +0 -5
  187. package/dist/src/contexts/context.store.js +0 -3
  188. package/dist/src/contexts/context.store.js.map +0 -1
  189. package/dist/src/controllers/collect-controller.d.ts +0 -39
  190. package/dist/src/controllers/collect-controller.js +0 -161
  191. package/dist/src/controllers/collect-controller.js.map +0 -1
  192. package/dist/src/controllers/compute-controller.d.ts +0 -55
  193. package/dist/src/controllers/compute-controller.js +0 -350
  194. package/dist/src/controllers/compute-controller.js.map +0 -1
  195. package/dist/src/controllers/eta-renderer/eta-dom-renderer.d.ts +0 -25
  196. package/dist/src/controllers/eta-renderer/eta-dom-renderer.js +0 -192
  197. package/dist/src/controllers/eta-renderer/eta-dom-renderer.js.map +0 -1
  198. package/dist/src/controllers/eta-renderer/eta-mutation-observer.d.ts +0 -28
  199. package/dist/src/controllers/eta-renderer/eta-mutation-observer.js +0 -206
  200. package/dist/src/controllers/eta-renderer/eta-mutation-observer.js.map +0 -1
  201. package/dist/src/controllers/eta-renderer/eta-renderer.d.ts +0 -21
  202. package/dist/src/controllers/eta-renderer/eta-renderer.js +0 -77
  203. package/dist/src/controllers/eta-renderer/eta-renderer.js.map +0 -1
  204. package/dist/src/controllers/eta-renderer/eta-template-cache.d.ts +0 -24
  205. package/dist/src/controllers/eta-renderer/eta-template-cache.js +0 -61
  206. package/dist/src/controllers/eta-renderer/eta-template-cache.js.map +0 -1
  207. package/dist/src/controllers/eta-renderer/eta-types.d.ts +0 -11
  208. package/dist/src/controllers/eta-renderer/eta-types.js +0 -1
  209. package/dist/src/controllers/eta-renderer/eta-types.js.map +0 -1
  210. package/dist/src/controllers/eta-renderer/index.d.ts +0 -2
  211. package/dist/src/controllers/eta-renderer/index.js +0 -2
  212. package/dist/src/controllers/eta-renderer/index.js.map +0 -1
  213. package/dist/src/controllers/event-pipeline-controller.d.ts +0 -28
  214. package/dist/src/controllers/event-pipeline-controller.js +0 -72
  215. package/dist/src/controllers/event-pipeline-controller.js.map +0 -1
  216. package/dist/src/events/events.d.ts +0 -75
  217. package/dist/src/events/events.js +0 -78
  218. package/dist/src/events/events.js.map +0 -1
  219. package/dist/src/nodes/node.root.d.ts +0 -16
  220. package/dist/src/nodes/node.root.js +0 -49
  221. package/dist/src/nodes/node.root.js.map +0 -1
  222. package/dist/src/nodes/node.state.d.ts +0 -88
  223. package/dist/src/nodes/node.state.js +0 -330
  224. package/dist/src/nodes/node.state.js.map +0 -1
  225. package/dist/src/renders/utility.d.ts +0 -32
  226. package/dist/src/renders/utility.js +0 -191
  227. package/dist/src/renders/utility.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/eta/cache.ts"],"names":[],"mappings":"AAAA,mBAAmB;AAEnB,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAO/B;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,uBAAuB;IAOlC,YACE,OAAuD;QANxC,YAAO,GAAG,IAAI,GAAG,EAG/B,CAAC;QAKF,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC;YACjB,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;YAClB,GAAG,OAAO;SACX,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAExC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,oEAAoE;YACpE,6DAA6D;YAC7D,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CACtC,IAAI,CAAC,GAAG,CACc,CAAC;YAEzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAuD;IAEvD,OAAO,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAC9C,CAAC","sourcesContent":["// src/eta/cache.ts\n\nimport { Eta } from 'eta/core';\n\nimport type {\n EtaCompiledTemplate,\n EtaTemplateCache\n} from './types.js';\n\n/**\n * Default cache backed by a single Eta instance.\n *\n * The Eta class compiles templates lazily and stores the resulting function\n * strings. Wrapping it in a small cache gives us:\n *\n * - a stable `source -> compiled` map that survives across renders\n * - a single, well-defined place that knows about Eta tags / options\n * - a `clear` hook so tests and HMR can drop the cache when templates change\n *\n * Compilation happens on first access for a given source. The cache is keyed\n * by the raw source string, so two equivalent template strings share a single\n * compiled entry.\n */\nexport class DefaultEtaTemplateCache implements EtaTemplateCache {\n private readonly eta: Eta;\n private readonly entries = new Map<\n string,\n EtaCompiledTemplate\n >();\n\n constructor(\n options?: Partial<ConstructorParameters<typeof Eta>[0]>\n ) {\n this.eta = new Eta({\n tags: ['{{', '}}'],\n ...options\n });\n }\n\n get(source: string): EtaCompiledTemplate {\n let compiled = this.entries.get(source);\n\n if (compiled === undefined) {\n // Eta's compile() is bound to the instance. We bind once so callers\n // can invoke the cached function without an explicit `this`.\n compiled = this.eta.compile(source).bind(\n this.eta\n ) as EtaCompiledTemplate;\n\n this.entries.set(source, compiled);\n }\n\n return compiled;\n }\n\n clear(): void {\n this.entries.clear();\n }\n\n /**\n * Number of compiled templates currently held in the cache.\n *\n * Exposed for diagnostics and tests; not part of the public contract.\n */\n get size(): number {\n return this.entries.size;\n }\n}\n\n/**\n * Convenience constructor used by the default factory.\n *\n * Tests can swap in a custom cache via the factory constructor; the rest of\n * the subsystem talks only to the `EtaTemplateCache` interface.\n */\nexport function createEtaTemplateCache(\n options?: Partial<ConstructorParameters<typeof Eta>[0]>\n): EtaTemplateCache {\n return new DefaultEtaTemplateCache(options);\n}\n"]}
@@ -0,0 +1,608 @@
1
+ import { type TaskStatus } from '@lit/task';
2
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
3
+ import type { EtaMutationBatchSchedule, EtaTemplateControllerOptions, EtaTemplateHost, EtaTemplateIndexLike } from './types.js';
4
+ /**
5
+ * Default context type for the Eta template subsystem.
6
+ *
7
+ * **This is a recommended context shape, NOT something the controller
8
+ * builds automatically.** The controller used to spread a default
9
+ * `$scope` / `$compute` context internally; the current `args` /
10
+ * `context` API delegates that to the host. Hosts that want the
11
+ * documented shape should construct the context themselves:
12
+ *
13
+ * ```ts
14
+ * context: ([scope]) => ({
15
+ * ...(scope ?? {}),
16
+ * $scope : scope,
17
+ * $compute: this.compute
18
+ * })
19
+ * ```
20
+ *
21
+ * Templates may reference any property of the scope as a top-level
22
+ * binding.
23
+ */
24
+ export type DefaultEtaContext = {
25
+ readonly $scope?: object;
26
+ readonly $compute?: object;
27
+ } & Record<string, unknown>;
28
+ /**
29
+ * Status of the underlying `@lit/task`. Re-exported so consumers do
30
+ * not need a direct `@lit/task` dependency to read it.
31
+ */
32
+ export type EtaTemplateStatus = TaskStatus;
33
+ /**
34
+ * Reactive controller that owns the lifecycle of the Eta template
35
+ * subsystem for a single scoped boundary.
36
+ *
37
+ * Responsibilities:
38
+ *
39
+ * - Owns the `@lit/task` that drives rendering.
40
+ * - Builds the rendering context from the host-supplied `args` /
41
+ * `context` callbacks.
42
+ * - Owns the `MutationObserver` that feeds the index.
43
+ * - Owns a single `EtaTemplateIndex`.
44
+ * - Iterates operations and calls `execute(context)` on each.
45
+ * - Participates in `host.trackLocalWork` so render passes count
46
+ * toward `BdNodeElement.updateComplete`.
47
+ *
48
+ * It does NOT:
49
+ *
50
+ * - Walk the DOM during render (the index is the source of truth).
51
+ * - Discover templates during render (the factory runs once on
52
+ * `add`).
53
+ * - Know about products, options, prices, or transitions.
54
+ *
55
+ * **Skip-render semantics.** When `enabled(args)` returns `false`
56
+ * or `context(args)` returns `undefined`, the controller skips the
57
+ * render pass and returns `undefined`. Previously rendered DOM
58
+ * output stays as-is — the controller does not blank the DOM or
59
+ * remove rendered nodes. Hosts that want blank/fallback output
60
+ * should either return a context that causes templates to render
61
+ * blank values, or publish a fallback scope (e.g. an empty object
62
+ * or a sentinel value) before requesting a render. This behaviour
63
+ * is intentional: it lets the controller be safely driven from
64
+ * the host's reactive state without flickering on intermediate
65
+ * states where the scope is temporarily absent.
66
+ */
67
+ export declare class EtaTemplateController<TArgs extends readonly unknown[] = readonly unknown[], TContext extends object = DefaultEtaContext> implements ReactiveController {
68
+ #private;
69
+ readonly index: EtaTemplateIndexLike<TContext>;
70
+ private readonly host;
71
+ private readonly argsFn;
72
+ private readonly enabledFn;
73
+ private readonly contextFn;
74
+ private readonly onRenderError;
75
+ private readonly mutationBatchScheduleOption;
76
+ /**
77
+ * Cached boundary-element predicate, captured once in the
78
+ * constructor and forwarded to every shadow-root index through
79
+ * `_shadowBoundaryPredicate`. The controller is the single
80
+ * source of truth for the predicate — the host supplies it via
81
+ * `options.isBoundaryElement` and the controller threads the
82
+ * SAME predicate to every observed root (light + shadow).
83
+ *
84
+ * Captured up-front so `_shadowBoundaryPredicate` does not need
85
+ * to reach back into `this.options` at every shadow-binding
86
+ * creation. `undefined` when the host did not supply a
87
+ * predicate — preserves the pre-fix behaviour for those hosts.
88
+ */
89
+ private readonly _boundaryElementPredicate;
90
+ /**
91
+ * Set of every shadow root that has already been wired into a
92
+ * shadow binding.
93
+ *
94
+ * `WeakSet` because shadow roots can be GC'd when their host
95
+ * disconnects — we never want to keep them alive through this
96
+ * field. `_addShadowBinding` is the single writer; both
97
+ * `_connectShadowRoots` (initial discovery) and
98
+ * `_discoverShadowRootsFor` (light-DOM mutation-driven
99
+ * discovery) gate registration through this set so the same
100
+ * shadow root is never wired twice.
101
+ */
102
+ private readonly _seenShadows;
103
+ private readonly observer;
104
+ private readonly batcher;
105
+ private readonly task;
106
+ private readonly factory;
107
+ /**
108
+ * Per-shadow-root observer + batcher + index triples. Empty
109
+ * when the host does not enumerate any shadow roots. Each
110
+ * triple is wired in `hostConnected` and torn down in
111
+ * `hostDisconnected` alongside the light-DOM observer.
112
+ */
113
+ private shadowBindings;
114
+ constructor(host: EtaTemplateHost & ReactiveControllerHost, options: EtaTemplateControllerOptions<TArgs, TContext>);
115
+ /**
116
+ * Invalidates every compiled template this controller owns.
117
+ *
118
+ * Drops all entries from the controller's internal cache. The
119
+ * next render that touches a previously-compiled template will
120
+ * re-compile it through the cache.
121
+ *
122
+ * **Per-controller scope.** `clearCache()` only clears this
123
+ * controller's own cache. There is no public cache injection
124
+ * option; hosts that want shared templates across controllers
125
+ * should compile and store those templates at the application
126
+ * layer instead of sharing the controller's internal Eta cache.
127
+ *
128
+ * Safe to call at any time, including between renders.
129
+ */
130
+ clearCache(): void;
131
+ /**
132
+ * Status of the underlying Task.
133
+ *
134
+ * Exposed so consumers (e.g. tests) can assert progress without
135
+ * reaching into the `@lit/task` surface.
136
+ */
137
+ get status(): EtaTemplateStatus;
138
+ /**
139
+ * Latest context produced by a successful render pass.
140
+ */
141
+ get value(): TContext | undefined;
142
+ /**
143
+ * Most recent render error, or `undefined` when the last render
144
+ * succeeded.
145
+ *
146
+ * Mirrors `@lit/task`'s `Task.error` getter. When a host passes
147
+ * `onRenderError`, the controller swallows render errors and
148
+ * records them here — read this getter to surface them in UI
149
+ * state (e.g. an error banner). When `onRenderError` is omitted,
150
+ * render errors reject `updateComplete`; both this getter and
151
+ * the rejected promise expose the same error value.
152
+ */
153
+ get error(): unknown;
154
+ /**
155
+ * Promise that resolves when the current render pass completes.
156
+ *
157
+ * Mirrors `BdNodeElement.updateComplete`'s promise semantics for
158
+ * the Eta subsystem. When the host supplies `trackLocalWork`,
159
+ * this promise is tracked under the controller's instance so the
160
+ * host's `updateComplete` waits for the render to settle before
161
+ * resolving.
162
+ *
163
+ * Useful for tests and for downstream consumers that need to
164
+ * observe render completion without poking at `@lit/task`.
165
+ */
166
+ get updateComplete(): Promise<TContext | undefined>;
167
+ /**
168
+ * Requests a fresh render pass through the underlying `@lit/task`.
169
+ *
170
+ * Most consumers never need to call this: the controller re-runs
171
+ * whenever the host signals an update, the index mutates, or the
172
+ * Task args change. The hook is provided for tests and for
173
+ * consumers that want to force a re-render after an external cache
174
+ * invalidation, scope mutation outside the normal reactive flow,
175
+ * or other event that the Task's `argsEqual` check might miss.
176
+ *
177
+ * The name reflects what actually happens: `Task.run()` schedules
178
+ * the task through Task's own scheduling semantics (which may
179
+ * batch, dedupe, or abort against the current run id) rather than
180
+ * synchronously executing the render loop.
181
+ *
182
+ * **Returns a promise.** The promise resolves to the latest
183
+ * context (`TContext | undefined`) produced by the render pass
184
+ * that `Task.run()` scheduled. Awaiting it lets tests and
185
+ * downstream consumers observe render completion without
186
+ * reaching into `@lit/task`. The promise resolves with the
187
+ * controller's `value`, which is `undefined` when the render was
188
+ * skipped (because `enabled()` returned `false` or `context()`
189
+ * returned `undefined`).
190
+ *
191
+ * Because `Task.run()` returns `Promise<void>` in the installed
192
+ * `@lit/task` version, this method kicks the run and then waits
193
+ * on `taskComplete` (the same promise exposed as
194
+ * `controller.updateComplete`) before reading `this.value`.
195
+ * `Task.run()` resolves when the run is *scheduled*, not when it
196
+ * *completes*; waiting on `taskComplete` is the only way to
197
+ * guarantee the returned context reflects the render that this
198
+ * call kicked off. The same `taskComplete` is also what the host
199
+ * `updateComplete` waits on (through `trackLocalWork`), so
200
+ * awaiting this method aligns the caller with the host's
201
+ * subtree-completion promise.
202
+ */
203
+ requestRender(): Promise<TContext | undefined>;
204
+ /**
205
+ * Flushes the mutation batcher synchronously.
206
+ *
207
+ * Forwards any pending `MutationRecord`s to the index through
208
+ * the batcher's compaction pass and returns whether the flush
209
+ * made the index dirty. Returns `false` when there was nothing
210
+ * to flush — an empty batch is a no-op.
211
+ *
212
+ * **Use cases:**
213
+ *
214
+ * - Hosts that drive the controller with
215
+ * `mutationBatchSchedule: 'manual'` and want to apply a
216
+ * known decoration phase's mutations before reading the
217
+ * index. Pair with `flushAndRender()` when a render is
218
+ * needed afterwards.
219
+ * - Tests that want a deterministic, intent-revealing way to
220
+ * drain the batcher without going through the observer's
221
+ * scheduled tick. This is the recommended way to assert on
222
+ * the post-flush index state from test bodies.
223
+ * - Hot-path code that knows a render is about to be requested
224
+ * via `requestRender()` and wants to guarantee the render
225
+ * sees the latest mutations (the render task body already
226
+ * calls `batcher.flush()` before executing, so this is
227
+ * rarely needed in practice — but useful when callers want
228
+ * the flush to happen synchronously at the call site rather
229
+ * than inside the Task).
230
+ *
231
+ * Does NOT call `onFlush` on the batcher, so the flush never
232
+ * re-enters `task.run()` on its own. Call `flushAndRender()`
233
+ * when a render should follow the flush.
234
+ *
235
+ * Returns the batcher's `flush()` return value — `true` when
236
+ * at least one compacted mutation made the index dirty,
237
+ * `false` otherwise. The dirty flag mirrors the batcher's
238
+ * dirty semantics (OR-accumulated across the four compaction
239
+ * passes — see `EtaMutationBatcher.flush`).
240
+ */
241
+ /**
242
+ * Flushes every observer queue into its matching batcher, then
243
+ * flushes every batcher into its matching index.
244
+ *
245
+ * Forwards any pending `MutationRecord`s to the index through
246
+ * the batcher's compaction pass and returns whether the flush
247
+ * made the index dirty. Returns `false` when there was nothing
248
+ * to flush — an empty batch is a no-op.
249
+ *
250
+ * **Manual schedule mode.** When `mutationBatchSchedule` is
251
+ * `'manual'`, the batcher never auto-flushes; the host must
252
+ * drain the queue itself. This method honours that contract
253
+ * across every observed root (light + every shadow binding).
254
+ *
255
+ * **Drain order:**
256
+ *
257
+ * 1. Light observer → light batcher
258
+ * (`observer.flushPendingRecords({ notify: false })`).
259
+ * 2. Every shadow observer → its shadow batcher
260
+ * (`binding.observer.flushPendingRecords({ notify: false })`).
261
+ * Drain the observer BEFORE the batcher so records the
262
+ * browser has produced but not yet delivered reach the
263
+ * batcher before the synchronous flush.
264
+ * 3. Light batcher → light index (`batcher.flush()`).
265
+ * 4. Every shadow batcher → its shadow index
266
+ * (`binding.batcher.flush()`), OR-accumulated into the
267
+ * combined dirty flag.
268
+ *
269
+ * **Use cases:**
270
+ *
271
+ * - Hosts that drive the controller with
272
+ * `mutationBatchSchedule: 'manual'` and want to apply a
273
+ * known decoration phase's mutations before reading the
274
+ * index. Pair with `flushAndRender()` when a render is
275
+ * needed afterwards.
276
+ * - Tests that want a deterministic, intent-revealing way to
277
+ * drain the batcher without going through the observer's
278
+ * scheduled tick. This is the recommended way to assert on
279
+ * the post-flush index state from test bodies.
280
+ * - Hot-path code that knows a render is about to be requested
281
+ * via `requestRender()` and wants to guarantee the render
282
+ * sees the latest mutations (the render task body already
283
+ * calls `batcher.flush()` before executing, so this is
284
+ * rarely needed in practice — but useful when callers want
285
+ * the flush to happen synchronously at the call site rather
286
+ * than inside the Task).
287
+ *
288
+ * Does NOT call `onFlush` on any batcher, so the flush never
289
+ * re-enters `task.run()` on its own. Call `flushAndRender()`
290
+ * when a render should follow the flush.
291
+ *
292
+ * Returns the combined dirty flag — `true` when at least one
293
+ * batcher (light or shadow) made its index dirty, `false`
294
+ * otherwise. The dirty flag mirrors each batcher's dirty
295
+ * semantics (OR-accumulated across the four compaction passes
296
+ * — see `EtaMutationBatcher.flush`).
297
+ *
298
+ * Idempotent — calling on an empty queue/batch still returns
299
+ * `false` and never triggers a render. The `notify: false` flag
300
+ * on every `flushPendingRecords` call keeps the observer's
301
+ * own `onChange` callback dormant during a manual flush so a
302
+ * host that drains and then calls `requestRender()` does not
303
+ * double-schedule.
304
+ */
305
+ flushMutations(): boolean;
306
+ /**
307
+ * Flushes the mutation batcher and requests a fresh render
308
+ * pass when the flush was dirty.
309
+ *
310
+ * Convenience wrapper for the "manual" schedule mode — hosts
311
+ * that opt into `mutationBatchSchedule: 'manual'` must drain
312
+ * the batcher themselves and then trigger a render. This
313
+ * method collapses both steps into one call:
314
+ *
315
+ * ```ts
316
+ * decorateBlock(block);
317
+ * await decorateIcons(block);
318
+ * eta.flushAndRender();
319
+ * ```
320
+ *
321
+ * When the flush was a no-op (`false` return from the
322
+ * batcher) the render is skipped — there is no point re-running
323
+ * the Task against an unchanged index. When the flush was
324
+ * dirty, the call forwards to `requestRender()` so the Task
325
+ * runs with the same scheduling semantics as any other
326
+ * render-triggering path.
327
+ *
328
+ * Does NOT wait for the render to complete; callers that need
329
+ * to await the resulting context can follow up with
330
+ * `await controller.updateComplete` (or
331
+ * `await controller.requestRender()`). The return value of
332
+ * the underlying `requestRender()` is intentionally discarded
333
+ * to keep the API synchronous and easy to call from
334
+ * imperative decoration flows.
335
+ */
336
+ flushAndRender(): void;
337
+ /**
338
+ * Reads the current batch schedule as resolved by the
339
+ * controller. Useful for diagnostics and for tests that want
340
+ * to assert on the controller's effective schedule without
341
+ * reaching into the private `batcher` field.
342
+ */
343
+ get mutationBatchSchedule(): EtaMutationBatchSchedule;
344
+ private _currentMutationBatchSchedule;
345
+ /**
346
+ * Runs a single render pass.
347
+ *
348
+ * The pass is gated by `enabled(args)` and `context(args)`:
349
+ *
350
+ * - `enabled` returning `false` skips the loop and returns
351
+ * `undefined` (no context, no render).
352
+ * - `context` returning `undefined` does the same.
353
+ *
354
+ * When both gates pass, the render loop runs in two phases:
355
+ *
356
+ * 1. **Pre-flush.** The mutation batcher applies any pending
357
+ * `MutationRecord` batches to the index via
358
+ * `observer.flushPendingRecords({ notify: false })` drains
359
+ * records the browser has produced but not delivered yet into
360
+ * the batcher, then `batcher.flush()` applies the compacted
361
+ * batch so the index and source registry are accurate before
362
+ * the render reads operations. Without this step, a render
363
+ * triggered by a Task args change or a manual `requestRender()`
364
+ * call could run against a stale index whenever the observer or
365
+ * batcher had not yet flushed a pending burst of DOM changes.
366
+ *
367
+ * `batcher.flush()` cancels any pending scheduled flush
368
+ * AND applies the current batch synchronously; it does NOT
369
+ * call `onFlush`. That detail is important — calling
370
+ * `onFlush` from inside an in-flight render pass would
371
+ * re-enter `task.run()` and create an infinite render
372
+ * loop. The Task's auto-run and the batcher's onFlush
373
+ * callback are kept on separate scheduling paths for this
374
+ * reason.
375
+ *
376
+ * The round-6 batcher sits between the observer and the index,
377
+ * so both layers participate in the pre-flush: the observer
378
+ * drains queued records into the batcher, and the batcher
379
+ * drains its compacted mutations into the index.
380
+ * 2. **Render.** The render loop runs in two phases so each
381
+ * phase can suspend only the observer that would otherwise
382
+ * treat the phase's self-induced mutations as fresh external
383
+ * mutations:
384
+ *
385
+ * a. **Light-DOM phase.** Iterates `this.index` inside
386
+ * `observer.suspendSync(...)` so DOM writes performed by
387
+ * light-DOM operations are not fed back as fresh
388
+ * mutations. The `finally` block drains whatever's queued
389
+ * after the loop — at this point only self-induced
390
+ * records should remain.
391
+ * b. **Shadow phase.** Iterates each binding's `index`
392
+ * inside `binding.observer.suspendSync(...)`. Wrapping
393
+ * the shadow phase in `this.observer.suspendSync` would
394
+ * discard legitimate external light-DOM mutations queued
395
+ * in the meantime via `takeRecords`, and would not
396
+ * actually suppress shadow observer feedback (the light
397
+ * observer cannot see shadow-tree writes anyway). Each
398
+ * binding therefore suspends its OWN observer so writes
399
+ * inside its shadow root are not fed back as fresh
400
+ * mutations.
401
+ *
402
+ * The pre-flush step above drained every shadow observer
403
+ * BEFORE either phase, so the only records the shadow
404
+ * observer will see during the shadow phase are writes from
405
+ * the shadow operations themselves — exactly what each
406
+ * shadow observer's `suspendSync` is there to suppress.
407
+ *
408
+ * Per-operation errors are routed to `onRenderError` when
409
+ * supplied; otherwise they propagate to the Task and abort the
410
+ * render pass.
411
+ */
412
+ private _runRenderPass;
413
+ /**
414
+ * Returns the effective attribute-name list that both the
415
+ * observer and the factory must agree on.
416
+ *
417
+ * The single source of truth avoids contradictory
418
+ * configurations where the observer is told to watch every
419
+ * attribute while the factory is told to filter to a specific
420
+ * list (or vice versa). The previous behaviour dropped records
421
+ * on the floor silently when `observeAllAttributes: true` was
422
+ * combined with a non-empty `attributeNames`.
423
+ *
424
+ * Resolution order:
425
+ *
426
+ * 1. `observeAllAttributes: true` → `undefined` (watch
427
+ * everything).
428
+ * 2. Non-empty `attributeNames` → that exact list.
429
+ * 3. Anything else → `undefined` (watch everything).
430
+ */
431
+ private _observerAttributeNames;
432
+ /**
433
+ * Builds the per-factory option object passed to the default
434
+ * factory constructor.
435
+ *
436
+ * `observeAllAttributes: true` (or no allowlist supplied) means
437
+ * the factory should observe every attribute, so we omit
438
+ * `attributeNames` entirely and let the factory default to
439
+ * "observe all".
440
+ *
441
+ * When the controller was constructed with an explicit
442
+ * `attributeNames` allowlist, we forward the **normalized** list
443
+ * (computed by `_observerAttributeNames`) so the factory and the
444
+ * observer agree on the same allowlist. Using the raw
445
+ * `options.attributeNames` here would let `observeAllAttributes:
446
+ * true` coexist with a non-empty list, contradicting the
447
+ * observer's "watch everything" mode.
448
+ */
449
+ private _factoryOptions;
450
+ hostConnected(): void;
451
+ /**
452
+ * Discovers every open shadow root attached to a descendant of
453
+ * the host's light subtree and wires one observer + batcher +
454
+ * index triple per root.
455
+ *
456
+ * `MutationObserver` is scoped to a single root: an observer
457
+ * attached to the host's light root does NOT see mutations
458
+ * inside any nested shadow root. To render templates into
459
+ * shadow trees the controller must therefore attach a separate
460
+ * observer per shadow root. The controller discovers those roots
461
+ * itself — walking the host's light subtree and reading
462
+ * `element.shadowRoot` — so hosts do not have to plumb the
463
+ * list through.
464
+ *
465
+ * Closed shadow roots are unreachable from outside (the
466
+ * `shadowRoot` getter returns `null` for closed mode), so they
467
+ * are silently skipped. Hosts that want to render into a
468
+ * closed root should attach a controller from inside that root
469
+ * instead.
470
+ *
471
+ * Idempotent — re-running on a second `hostConnected()` first
472
+ * tears down any existing bindings, then rebuilds them.
473
+ */
474
+ private _connectShadowRoots;
475
+ /**
476
+ * Registers a single shadow root with the controller — builds
477
+ * one observer + batcher + index triple per root and wires it
478
+ * into the light-DOM observer's discovery callback.
479
+ *
480
+ * Gates registration through `_seenShadows` so the same shadow
481
+ * root is never wired twice. Closed roots are skipped
482
+ * silently (their `shadowRoot` getter returns `null` so the
483
+ * caller should not pass them in).
484
+ */
485
+ private _addShadowBinding;
486
+ /**
487
+ * Reacts to a light-DOM `MutationRecord` batch by registering
488
+ * any newly-discovered open shadow roots.
489
+ *
490
+ * Lit `until` directives, `repeat` expansions, and custom
491
+ * element upgrades can attach shadow roots after the
492
+ * controller's `hostConnected()` pass has already walked the
493
+ * subtree. The light-DOM observer's callback fires for every
494
+ * mutation batch — we hook it here so a newly-inserted element
495
+ * that carries an open shadow root gets wired into the
496
+ * controller on the next batcher tick.
497
+ *
498
+ * Idempotent — `_addShadowBinding` gates against
499
+ * `_seenShadows`, so re-running the discovery walk on the same
500
+ * records (or running it during a `suspendSync` of the light
501
+ * observer) is harmless.
502
+ *
503
+ * Only `childList` records matter: an `add` of an element is
504
+ * what can carry a fresh shadow root, and skipping text /
505
+ * attribute records keeps the discovery walk cheap.
506
+ */
507
+ private _discoverShadowRootsFor;
508
+ /**
509
+ * Iterative DFS over `node`'s subtree (light children + open
510
+ * shadow roots) that registers every shadow root it encounters
511
+ * via `_addShadowBinding`.
512
+ *
513
+ * Mirrors the discovery shape used inside `_connectShadowRoots`
514
+ * but operates on a single subtree rooted at `node` rather
515
+ * than the full host subtree. Skips detached roots and any
516
+ * element/shadow already known to the controller — the
517
+ * `_seenShadows` gate inside `_addShadowBinding` short-circuits
518
+ * the second registration.
519
+ */
520
+ private _walkForShadows;
521
+ /**
522
+ * Tears down every per-shadow-root observer, batcher, and index.
523
+ * Mirrors the light-DOM teardown order in `hostDisconnected()`
524
+ * so source-registry preservation behaves the same way on
525
+ * shadow roots as it does on the light tree.
526
+ *
527
+ * Clears `_seenShadows` so a subsequent `hostConnected()` can
528
+ * re-discover every shadow root from scratch — observers do
529
+ * not survive disconnect, so previously-seen shadow roots are
530
+ * no longer wired and should be re-discovered.
531
+ */
532
+ private _disconnectShadowRoots;
533
+ /**
534
+ * Returns the boundary predicate for a shadow-root index. The
535
+ * controller currently reuses the host's
536
+ * `isBoundaryElement` rule for every observed root — the host
537
+ * option is the single source of truth. This helper exists so
538
+ * per-root overrides can be added later without churning the
539
+ * `_connectShadowRoots` call site.
540
+ *
541
+ * Returns `undefined` when the host did not supply an
542
+ * `isBoundaryElement` predicate — preserves the pre-fix
543
+ * behaviour for those hosts (the shadow index then has no
544
+ * boundary rule and falls back to its own ownership checks).
545
+ */
546
+ private _shadowBoundaryPredicate;
547
+ /**
548
+ * Cached normalized attribute name list. The controller
549
+ * computes this once in the constructor and reuses it for both
550
+ * the light-DOM observer and every shadow observer so a single
551
+ * allowlist applies across every observed root.
552
+ */
553
+ private readonly _normalizedAttributeNames;
554
+ hostDisconnected(): void;
555
+ /**
556
+ * Explicit-disposal alias for `hostDisconnected()`.
557
+ *
558
+ * Lit `ReactiveController`s are torn down automatically when
559
+ * the host is disconnected, so most consumers never need this
560
+ * method. It exists for two cases:
561
+ *
562
+ * - Tests that want a deterministic, intent-revealing way to
563
+ * tear down the controller from the test body, without
564
+ * reaching into the Lit host's `hostDisconnected()` hook
565
+ * manually. This makes the teardown intent obvious in
566
+ * tests that exercise the observer / index wiring in
567
+ * isolation.
568
+ * - Application code that owns a controller instance and wants
569
+ * to mirror the Lit `hostConnected` / `hostDisconnected`
570
+ * pair with a single, intent-revealing `dispose()` call —
571
+ * for example, when a controller's lifetime is decoupled
572
+ * from the host element (a controller that should be
573
+ * disposed when a feature is unmounted, even if the host
574
+ * stays connected for other reasons).
575
+ *
576
+ * The controller still requires a Lit `ReactiveControllerHost`
577
+ * because the constructor calls `host.addController(this)` —
578
+ * `dispose()` does not enable non-Lit integrations on its own,
579
+ * it only offers a more direct teardown path for the
580
+ * already-Lit-managed controller. If you need a true non-Lit
581
+ * integration, wrap the controller in a minimal
582
+ * `ReactiveControllerHost` adapter.
583
+ *
584
+ * The behaviour is identical to `hostDisconnected()`: the
585
+ * observer is drained into the batcher via
586
+ * `flushPendingRecords({ notify: false })`, the batcher is
587
+ * flushed synchronously, the observer is disconnected, and the
588
+ * index runs `disposeAll()`. Safe to call multiple times — the
589
+ * underlying `MutationObserver.disconnect()` is idempotent and
590
+ * the observer is one-shot, so a second call is a no-op.
591
+ */
592
+ dispose(): void;
593
+ }
594
+ /**
595
+ * Convenience constructor used by `BdScopedElement` (in a follow-up
596
+ * task) and by tests that want a one-line setup.
597
+ *
598
+ * The controller owns its own cache and factory — neither is a
599
+ * public option. This constructor simply forwards to
600
+ * `new EtaTemplateController(host, options)` with no
601
+ * transformations. It exists as a named export so callers do not
602
+ * have to import the class directly.
603
+ *
604
+ * `args` and `context` are required by `EtaTemplateController` and
605
+ * must be supplied by the caller. The convenience constructor does
606
+ * not synthesise defaults for them.
607
+ */
608
+ export declare function createEtaTemplateController<TArgs extends readonly unknown[] = readonly unknown[], TContext extends object = DefaultEtaContext>(host: EtaTemplateHost & ReactiveControllerHost, options: EtaTemplateControllerOptions<TArgs, TContext>): EtaTemplateController<TArgs, TContext>;