@repobit/dex-store-elements 1.7.2 → 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.
- package/CHANGELOG.md +5 -905
- package/README.md +9 -7
- package/dist/src/actions/action.adapter.d.ts +36 -0
- package/dist/src/actions/action.adapter.js +183 -0
- package/dist/src/actions/action.adapter.js.map +1 -0
- package/dist/src/actions/action.attributes.d.ts +15 -0
- package/dist/src/actions/action.attributes.js +137 -0
- package/dist/src/actions/action.attributes.js.map +1 -0
- package/dist/src/actions/action.registry.d.ts +4 -0
- package/dist/src/actions/action.registry.js +119 -0
- package/dist/src/actions/action.registry.js.map +1 -0
- package/dist/src/actions/index.d.ts +3 -2
- package/dist/src/actions/index.js +3 -80
- package/dist/src/actions/index.js.map +1 -1
- package/dist/src/compute/compute.expand.d.ts +70 -0
- package/dist/src/compute/compute.expand.js +319 -0
- package/dist/src/compute/compute.expand.js.map +1 -0
- package/dist/src/compute/compute.scan.d.ts +54 -0
- package/dist/src/compute/compute.scan.js +160 -0
- package/dist/src/compute/compute.scan.js.map +1 -0
- package/dist/src/compute/option-resolver.d.ts +31 -0
- package/dist/src/compute/option-resolver.js +147 -0
- package/dist/src/compute/option-resolver.js.map +1 -0
- package/dist/src/contexts/context.compute.d.ts +12 -0
- package/dist/src/contexts/context.compute.js +4 -0
- package/dist/src/contexts/context.compute.js.map +1 -0
- package/dist/src/contexts/context.scope.d.ts +139 -0
- package/dist/src/contexts/context.scope.js +48 -0
- package/dist/src/contexts/context.scope.js.map +1 -0
- package/dist/src/controllers/controller.action-resolve.d.ts +110 -0
- package/dist/src/controllers/controller.action-resolve.js +203 -0
- package/dist/src/controllers/controller.action-resolve.js.map +1 -0
- package/dist/src/controllers/controller.action-topology.d.ts +59 -0
- package/dist/src/controllers/controller.action-topology.js +130 -0
- package/dist/src/controllers/controller.action-topology.js.map +1 -0
- package/dist/src/controllers/controller.compute.d.ts +72 -0
- package/dist/src/controllers/controller.compute.js +110 -0
- package/dist/src/controllers/controller.compute.js.map +1 -0
- package/dist/src/controllers/controller.resolve.d.ts +78 -0
- package/dist/src/controllers/controller.resolve.js +205 -0
- package/dist/src/controllers/controller.resolve.js.map +1 -0
- package/dist/src/core/action-topology.d.ts +62 -0
- package/dist/src/core/action-topology.js +67 -0
- package/dist/src/core/action-topology.js.map +1 -0
- package/dist/src/core/actions.d.ts +64 -0
- package/dist/src/core/actions.js +47 -0
- package/dist/src/core/actions.js.map +1 -0
- package/dist/src/core/node.element.d.ts +179 -0
- package/dist/src/core/node.element.js +573 -0
- package/dist/src/core/node.element.js.map +1 -0
- package/dist/src/core/node.scope.d.ts +374 -0
- package/dist/src/core/node.scope.js +558 -0
- package/dist/src/core/node.scope.js.map +1 -0
- package/dist/src/core/option-update.d.ts +11 -0
- package/dist/src/core/option-update.js +59 -0
- package/dist/src/core/option-update.js.map +1 -0
- package/dist/src/dsl/compilers/array/compiler.js +13 -14
- package/dist/src/dsl/compilers/array/compiler.js.map +1 -1
- package/dist/src/dsl/compilers/boolean/compiler.d.ts +1 -1
- package/dist/src/dsl/compilers/boolean/compiler.js +14 -27
- package/dist/src/dsl/compilers/boolean/compiler.js.map +1 -1
- package/dist/src/dsl/compilers/enum/compiler.js +7 -10
- package/dist/src/dsl/compilers/enum/compiler.js.map +1 -1
- package/dist/src/dsl/compilers/index.d.ts +1 -1
- package/dist/src/dsl/compilers/index.js +5 -5
- package/dist/src/dsl/compilers/index.js.map +1 -1
- package/dist/src/dsl/utilty.d.ts +0 -4
- package/dist/src/dsl/utilty.js +3 -30
- package/dist/src/dsl/utilty.js.map +1 -1
- package/dist/src/eta/batch.d.ts +123 -0
- package/dist/src/eta/batch.js +162 -0
- package/dist/src/eta/batch.js.map +1 -0
- package/dist/src/eta/batcher.d.ts +184 -0
- package/dist/src/eta/batcher.js +335 -0
- package/dist/src/eta/batcher.js.map +1 -0
- package/dist/src/eta/cache.d.ts +36 -0
- package/dist/src/eta/cache.js +56 -0
- package/dist/src/eta/cache.js.map +1 -0
- package/dist/src/eta/controller.d.ts +608 -0
- package/dist/src/eta/controller.js +1036 -0
- package/dist/src/eta/controller.js.map +1 -0
- package/dist/src/eta/factory.d.ts +74 -0
- package/dist/src/eta/factory.js +121 -0
- package/dist/src/eta/factory.js.map +1 -0
- package/dist/src/eta/idle.d.ts +39 -0
- package/dist/src/eta/idle.js +52 -0
- package/dist/src/eta/idle.js.map +1 -0
- package/dist/src/eta/index.d.ts +52 -0
- package/dist/src/eta/index.js +13 -0
- package/dist/src/eta/index.js.map +1 -0
- package/dist/src/eta/observer.d.ts +263 -0
- package/dist/src/eta/observer.js +263 -0
- package/dist/src/eta/observer.js.map +1 -0
- package/dist/src/eta/operations.d.ts +41 -0
- package/dist/src/eta/operations.js +59 -0
- package/dist/src/eta/operations.js.map +1 -0
- package/dist/src/eta/source-registry.d.ts +198 -0
- package/dist/src/eta/source-registry.js +267 -0
- package/dist/src/eta/source-registry.js.map +1 -0
- package/dist/src/eta/template-index.d.ts +285 -0
- package/dist/src/eta/template-index.js +642 -0
- package/dist/src/eta/template-index.js.map +1 -0
- package/dist/src/eta/types.d.ts +529 -0
- package/dist/src/eta/types.js +2 -0
- package/dist/src/eta/types.js.map +1 -0
- package/dist/src/index.d.ts +21 -9
- package/dist/src/index.js +22 -11
- package/dist/src/index.js.map +1 -1
- package/dist/src/nodes/node.context.d.ts +5 -3
- package/dist/src/nodes/node.context.js +48 -3
- package/dist/src/nodes/node.context.js.map +1 -1
- package/dist/src/nodes/node.option.d.ts +11 -31
- package/dist/src/nodes/node.option.js +158 -222
- package/dist/src/nodes/node.option.js.map +1 -1
- package/dist/src/nodes/node.product.d.ts +7 -11
- package/dist/src/nodes/node.product.js +85 -64
- package/dist/src/nodes/node.product.js.map +1 -1
- package/dist/src/renders/attributes/buyLink.d.ts +2 -2
- package/dist/src/renders/attributes/buyLink.js +14 -11
- package/dist/src/renders/attributes/buyLink.js.map +1 -1
- package/dist/src/renders/attributes/devices.d.ts +2 -2
- package/dist/src/renders/attributes/devices.js +9 -19
- package/dist/src/renders/attributes/devices.js.map +1 -1
- package/dist/src/renders/attributes/discount.d.ts +2 -2
- package/dist/src/renders/attributes/discount.js +56 -44
- package/dist/src/renders/attributes/discount.js.map +1 -1
- package/dist/src/renders/attributes/hide.d.ts +2 -2
- package/dist/src/renders/attributes/hide.js +49 -14
- package/dist/src/renders/attributes/hide.js.map +1 -1
- package/dist/src/renders/attributes/index.d.ts +3 -3
- package/dist/src/renders/attributes/index.js +2 -4
- package/dist/src/renders/attributes/index.js.map +1 -1
- package/dist/src/renders/attributes/price.d.ts +2 -2
- package/dist/src/renders/attributes/price.js +30 -44
- package/dist/src/renders/attributes/price.js.map +1 -1
- package/dist/src/renders/attributes/subscription.d.ts +2 -2
- package/dist/src/renders/attributes/subscription.js +14 -20
- package/dist/src/renders/attributes/subscription.js.map +1 -1
- package/dist/src/renders/attributes/utilty.d.ts +2 -0
- package/dist/src/renders/attributes/utilty.js +17 -4
- package/dist/src/renders/attributes/utilty.js.map +1 -1
- package/dist/src/renders/context.d.ts +122 -10
- package/dist/src/renders/context.js +140 -80
- package/dist/src/renders/context.js.map +1 -1
- package/dist/src/renders/format.js +2 -2
- package/dist/src/renders/format.js.map +1 -1
- package/dist/src/renders/index.d.ts +6 -2
- package/dist/src/renders/index.js +67 -29
- package/dist/src/renders/index.js.map +1 -1
- package/dist/src/renders/observe.d.ts +1 -4
- package/dist/src/renders/observe.js +10 -24
- package/dist/src/renders/observe.js.map +1 -1
- package/dist/src/renders/render.wrapper.d.ts +37 -0
- package/dist/src/renders/render.wrapper.js +147 -0
- package/dist/src/renders/render.wrapper.js.map +1 -0
- package/dist/src/templating/eta.js +1 -4
- package/dist/src/templating/eta.js.map +1 -1
- package/package.json +4 -5
- package/dist/src/actions/action.button.d.ts +0 -2
- package/dist/src/actions/action.button.js +0 -8
- package/dist/src/actions/action.button.js.map +0 -1
- package/dist/src/actions/action.input.d.ts +0 -2
- package/dist/src/actions/action.input.js +0 -43
- package/dist/src/actions/action.input.js.map +0 -1
- package/dist/src/actions/action.select.d.ts +0 -2
- package/dist/src/actions/action.select.js +0 -14
- package/dist/src/actions/action.select.js.map +0 -1
- package/dist/src/actions/utilty.d.ts +0 -16
- package/dist/src/actions/utilty.js +0 -149
- package/dist/src/actions/utilty.js.map +0 -1
- package/dist/src/contexts/context.datalayer.d.ts +0 -9
- package/dist/src/contexts/context.datalayer.js +0 -3
- package/dist/src/contexts/context.datalayer.js.map +0 -1
- package/dist/src/contexts/context.derived.d.ts +0 -12
- package/dist/src/contexts/context.derived.js +0 -3
- package/dist/src/contexts/context.derived.js.map +0 -1
- package/dist/src/contexts/context.option.d.ts +0 -5
- package/dist/src/contexts/context.option.js +0 -3
- package/dist/src/contexts/context.option.js.map +0 -1
- package/dist/src/contexts/context.product.d.ts +0 -5
- package/dist/src/contexts/context.product.js +0 -3
- package/dist/src/contexts/context.product.js.map +0 -1
- package/dist/src/contexts/context.state.d.ts +0 -28
- package/dist/src/contexts/context.state.js +0 -3
- package/dist/src/contexts/context.state.js.map +0 -1
- package/dist/src/contexts/context.store.d.ts +0 -5
- package/dist/src/contexts/context.store.js +0 -3
- package/dist/src/contexts/context.store.js.map +0 -1
- package/dist/src/controllers/collect-controller.d.ts +0 -39
- package/dist/src/controllers/collect-controller.js +0 -161
- package/dist/src/controllers/collect-controller.js.map +0 -1
- package/dist/src/controllers/compute-controller.d.ts +0 -55
- package/dist/src/controllers/compute-controller.js +0 -350
- package/dist/src/controllers/compute-controller.js.map +0 -1
- package/dist/src/controllers/eta-renderer/eta-dom-renderer.d.ts +0 -25
- package/dist/src/controllers/eta-renderer/eta-dom-renderer.js +0 -192
- package/dist/src/controllers/eta-renderer/eta-dom-renderer.js.map +0 -1
- package/dist/src/controllers/eta-renderer/eta-mutation-observer.d.ts +0 -28
- package/dist/src/controllers/eta-renderer/eta-mutation-observer.js +0 -206
- package/dist/src/controllers/eta-renderer/eta-mutation-observer.js.map +0 -1
- package/dist/src/controllers/eta-renderer/eta-renderer.d.ts +0 -21
- package/dist/src/controllers/eta-renderer/eta-renderer.js +0 -77
- package/dist/src/controllers/eta-renderer/eta-renderer.js.map +0 -1
- package/dist/src/controllers/eta-renderer/eta-template-cache.d.ts +0 -24
- package/dist/src/controllers/eta-renderer/eta-template-cache.js +0 -61
- package/dist/src/controllers/eta-renderer/eta-template-cache.js.map +0 -1
- package/dist/src/controllers/eta-renderer/eta-types.d.ts +0 -11
- package/dist/src/controllers/eta-renderer/eta-types.js +0 -1
- package/dist/src/controllers/eta-renderer/eta-types.js.map +0 -1
- package/dist/src/controllers/eta-renderer/index.d.ts +0 -2
- package/dist/src/controllers/eta-renderer/index.js +0 -2
- package/dist/src/controllers/eta-renderer/index.js.map +0 -1
- package/dist/src/controllers/event-pipeline-controller.d.ts +0 -28
- package/dist/src/controllers/event-pipeline-controller.js +0 -72
- package/dist/src/controllers/event-pipeline-controller.js.map +0 -1
- package/dist/src/events/events.d.ts +0 -75
- package/dist/src/events/events.js +0 -78
- package/dist/src/events/events.js.map +0 -1
- package/dist/src/nodes/node.root.d.ts +0 -16
- package/dist/src/nodes/node.root.js +0 -49
- package/dist/src/nodes/node.root.js.map +0 -1
- package/dist/src/nodes/node.state.d.ts +0 -88
- package/dist/src/nodes/node.state.js +0 -330
- package/dist/src/nodes/node.state.js.map +0 -1
- package/dist/src/renders/utility.d.ts +0 -32
- package/dist/src/renders/utility.js +0 -191
- 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>;
|