@repobit/dex-store-elements 1.7.3 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -906
- package/README.md +308 -283
- 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,558 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { bdComputeContext } from '../contexts/context.compute.js';
|
|
8
|
+
import { bdScopeContext, createBdStoreScope, runBdScopeDerived } from '../contexts/context.scope.js';
|
|
9
|
+
import { BdComputeController } from '../controllers/controller.compute.js';
|
|
10
|
+
import { getTransitionEventId } from '../core/actions.js';
|
|
11
|
+
import { createEtaTemplateController } from '../eta/controller.js';
|
|
12
|
+
import { buildTemplateDslContext } from '../renders/context.js';
|
|
13
|
+
import { consume, provide } from '@lit/context';
|
|
14
|
+
import { property, state } from 'lit/decorators.js';
|
|
15
|
+
import { BdNodeElement } from './node.element.js';
|
|
16
|
+
function hasOwn(object, key) {
|
|
17
|
+
return Object.prototype.hasOwnProperty.call(object, key);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Sparse flag application.
|
|
21
|
+
*
|
|
22
|
+
* `applyScopedFlags` is the single pass that merges per-node
|
|
23
|
+
* overlays into the published scope:
|
|
24
|
+
*
|
|
25
|
+
* - **sparse boolean flags** — `computeDisabled` and
|
|
26
|
+
* `etaDisabled`. Represented by presence, not by `true` /
|
|
27
|
+
* `false`: missing means enabled, present and `true` means
|
|
28
|
+
* disabled. Setting `enabled=false` deletes the flag rather
|
|
29
|
+
* than storing `false`.
|
|
30
|
+
*
|
|
31
|
+
* - **value overlays** — `derived` and
|
|
32
|
+
* `mutationBatchSchedule`. Caller-supplied values win; the
|
|
33
|
+
* node's own property fills in when the caller did not supply
|
|
34
|
+
* one. Missing on both sides means the field is absent from
|
|
35
|
+
* the published scope.
|
|
36
|
+
*
|
|
37
|
+
* The function preserves the original `object` reference when
|
|
38
|
+
* nothing actually changes. The `nextObject` slot is only
|
|
39
|
+
* allocated the first time a write happens, so a scope with
|
|
40
|
+
* nothing to merge returns the same reference it was given —
|
|
41
|
+
* important because `publishScope` uses `Object.is` to short-
|
|
42
|
+
* circuit downstream `@provide` notifications.
|
|
43
|
+
*/
|
|
44
|
+
function applyScopedFlags(scope, overlays) {
|
|
45
|
+
let nextObject;
|
|
46
|
+
const getNextObject = () => {
|
|
47
|
+
if (nextObject !== undefined) {
|
|
48
|
+
return nextObject;
|
|
49
|
+
}
|
|
50
|
+
nextObject = {
|
|
51
|
+
...scope
|
|
52
|
+
};
|
|
53
|
+
return nextObject;
|
|
54
|
+
};
|
|
55
|
+
for (const [key, enabled] of Object.entries(overlays.flags)) {
|
|
56
|
+
const currentValue = scope[key];
|
|
57
|
+
if (enabled) {
|
|
58
|
+
if (currentValue !== true) {
|
|
59
|
+
getNextObject()[key] = true;
|
|
60
|
+
}
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (hasOwn(scope, key)) {
|
|
64
|
+
delete getNextObject()[key];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
for (const [key, value] of Object.entries(overlays.values)) {
|
|
68
|
+
if (value === undefined) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (Object.is(scope[key], value)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
getNextObject()[key] = value;
|
|
75
|
+
}
|
|
76
|
+
return nextObject ?? scope;
|
|
77
|
+
}
|
|
78
|
+
export class BdScopedElement extends BdNodeElement {
|
|
79
|
+
constructor() {
|
|
80
|
+
super(...arguments);
|
|
81
|
+
this.scopedValueKeys = new Set();
|
|
82
|
+
this.compute = new BdComputeController(this, {
|
|
83
|
+
store: () => this.currentScope?.store,
|
|
84
|
+
enabled: () => this.isComputeEnabled,
|
|
85
|
+
onResult: (result) => {
|
|
86
|
+
const previous = this.computeResult;
|
|
87
|
+
this.computeResult = result;
|
|
88
|
+
if (Object.is(previous, result)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this._fireOnScopeChangeForCompute();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
/**
|
|
95
|
+
* Eta template controller that renders the subtree against the
|
|
96
|
+
* current scope and compute result.
|
|
97
|
+
*
|
|
98
|
+
* Args trigger a re-render when the scope, the compute result,
|
|
99
|
+
* or the eta-enabled flag change. The render is gated on
|
|
100
|
+
* `isEtaEnabled` so a disabled scope does not flicker
|
|
101
|
+
* intermediate state.
|
|
102
|
+
*
|
|
103
|
+
* The context exposes **only** `store`, `product`, `option`,
|
|
104
|
+
* and `state` — exactly the fields templates are expected to
|
|
105
|
+
* reference. We do not spread the full scope, do not surface
|
|
106
|
+
* `$scope` / `$state` handles, and do not leak the transition
|
|
107
|
+
* object. New fields belong on `BdScope` plus an explicit
|
|
108
|
+
* binding here so the public template surface stays auditable.
|
|
109
|
+
*
|
|
110
|
+
* The boundary predicate uses raw tag names so nested
|
|
111
|
+
* `bd-context` / `bd-product` / `bd-option` nodes
|
|
112
|
+
* keep their own controllers and templates do not leak across
|
|
113
|
+
* scope boundaries. Tag-name checks are stable before custom
|
|
114
|
+
* element upgrade — `EtaTemplateControllerOptions.isBoundaryElement`
|
|
115
|
+
* MUST work on raw DOM shape.
|
|
116
|
+
*/
|
|
117
|
+
this.eta = createEtaTemplateController(this, {
|
|
118
|
+
args: () => [
|
|
119
|
+
this.currentScope,
|
|
120
|
+
this.computeResult
|
|
121
|
+
],
|
|
122
|
+
enabled: () => this.isEtaEnabled,
|
|
123
|
+
context: ([scope, compute]) => {
|
|
124
|
+
const dsl = buildTemplateDslContext({
|
|
125
|
+
store: scope?.store,
|
|
126
|
+
product: scope?.product,
|
|
127
|
+
option: scope?.option,
|
|
128
|
+
state: compute
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
store: dsl.store,
|
|
132
|
+
product: dsl.product,
|
|
133
|
+
option: dsl.option,
|
|
134
|
+
state: dsl.state,
|
|
135
|
+
ctx: dsl.ctx,
|
|
136
|
+
derived: runBdScopeDerived(scope)
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
/**
|
|
140
|
+
* Mutation batch schedule is resolved from the current
|
|
141
|
+
* published scope whenever the batcher schedules a future
|
|
142
|
+
* flush. The value flows through `BdScope` like `derived`
|
|
143
|
+
* does, so a parent that republishes a new
|
|
144
|
+
* `mutationBatchSchedule` is observed by already-constructed
|
|
145
|
+
* descendants on subsequent mutation bursts.
|
|
146
|
+
*
|
|
147
|
+
* Resolution order at scheduling time:
|
|
148
|
+
*
|
|
149
|
+
* 1. `this.currentScope?.mutationBatchSchedule` — this
|
|
150
|
+
* element's normalized published scope, when it has one.
|
|
151
|
+
* It already includes inherited values plus this node's
|
|
152
|
+
* own override.
|
|
153
|
+
* 2. `this.parentScope?.mutationBatchSchedule` — inherited
|
|
154
|
+
* schedule for scoped consumers that do not publish a
|
|
155
|
+
* scope of their own.
|
|
156
|
+
* 3. The Eta controller's own default
|
|
157
|
+
* (`'animation-frame'`).
|
|
158
|
+
*
|
|
159
|
+
* The cascade mirrors `derived`, but the Eta controller gets
|
|
160
|
+
* a resolver callback rather than the current value so the
|
|
161
|
+
* batcher can read the latest published scope.
|
|
162
|
+
*/
|
|
163
|
+
mutationBatchSchedule: () => this.currentScope?.mutationBatchSchedule ??
|
|
164
|
+
this.parentScope?.mutationBatchSchedule,
|
|
165
|
+
isBoundaryElement: (element) => {
|
|
166
|
+
const name = element.localName;
|
|
167
|
+
return (name === 'bd-context' ||
|
|
168
|
+
name === 'bd-product' ||
|
|
169
|
+
name === 'bd-option');
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
this.etaDisabled = false;
|
|
173
|
+
this.computeDisabled = false;
|
|
174
|
+
/**
|
|
175
|
+
* When set, this node only reacts to events originating inside its own
|
|
176
|
+
* subtree. Cascading transitions from `parentScope.transition` are
|
|
177
|
+
* dropped, mirroring v1's `<bd-state ignore-events-parent>` semantics.
|
|
178
|
+
*
|
|
179
|
+
* `<bd-context>` enables this by default (it is a hard event boundary).
|
|
180
|
+
*/
|
|
181
|
+
this.ignoreEventsParent = false;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Owning boundary for the Eta template index.
|
|
185
|
+
*
|
|
186
|
+
* `BdScopedElement` IS the index root — every nested template
|
|
187
|
+
* is owned by the closest enclosing bd-* node, and that node
|
|
188
|
+
* in turn owns the controller that renders its subtree.
|
|
189
|
+
*/
|
|
190
|
+
get root() {
|
|
191
|
+
return this;
|
|
192
|
+
}
|
|
193
|
+
get isEtaEnabled() {
|
|
194
|
+
return (this.etaDisabled !== true &&
|
|
195
|
+
this.parentScope?.etaDisabled !== true);
|
|
196
|
+
}
|
|
197
|
+
get currentScope() {
|
|
198
|
+
return this.providedScope;
|
|
199
|
+
}
|
|
200
|
+
get isComputeEnabled() {
|
|
201
|
+
return (this.computeDisabled !== true &&
|
|
202
|
+
this.parentScope?.computeDisabled !== true);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Lazy cache of the parsed `ignore-events` attribute.
|
|
206
|
+
*
|
|
207
|
+
* Re-parsed whenever the attribute changes; consumers should access
|
|
208
|
+
* `this.ignoredEventIds` rather than calling `parseIgnoreEvents` themselves.
|
|
209
|
+
*/
|
|
210
|
+
#ignoredEventIds;
|
|
211
|
+
get ignoredEventIds() {
|
|
212
|
+
if (this.#ignoredEventIds !== undefined) {
|
|
213
|
+
return this.#ignoredEventIds;
|
|
214
|
+
}
|
|
215
|
+
this.#ignoredEventIds = parseIgnoreEvents(this.ignoreEvents);
|
|
216
|
+
return this.#ignoredEventIds;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Filter callback handed to each node's `BdActionResolveController`.
|
|
220
|
+
*
|
|
221
|
+
* Drops transitions whose `eventId` matches an entry in `ignore-events`,
|
|
222
|
+
* and — when `ignore-events-parent` is set — drops any cascade from a
|
|
223
|
+
* parent scope. Concrete nodes pass `filterTransition: (c) =>
|
|
224
|
+
* this._filterTransition(c)` into their controller config; the
|
|
225
|
+
* controller invokes this for both local `bd-action-request` events
|
|
226
|
+
* and inherited transitions.
|
|
227
|
+
*/
|
|
228
|
+
_filterTransition(candidate) {
|
|
229
|
+
if (this.ignoreEventsParent &&
|
|
230
|
+
candidate.source === 'parent') {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
const ignored = this.ignoredEventIds;
|
|
234
|
+
if (ignored.size === 0) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
const eventId = getTransitionEventId(candidate.transition);
|
|
238
|
+
if (eventId === undefined) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
return !ignored.has(eventId);
|
|
242
|
+
}
|
|
243
|
+
publishScope(nextScope) {
|
|
244
|
+
const sourceScope = Object.is(nextScope, this.providedScope)
|
|
245
|
+
? this.scopeWithoutOwnedValues(nextScope)
|
|
246
|
+
: nextScope;
|
|
247
|
+
const normalizedScope = this.applyScopedFlags(sourceScope);
|
|
248
|
+
this.updateScopedValueKeys(sourceScope, normalizedScope);
|
|
249
|
+
if (Object.is(this.providedScope, normalizedScope)) {
|
|
250
|
+
return normalizedScope;
|
|
251
|
+
}
|
|
252
|
+
const previousScope = this.providedScope;
|
|
253
|
+
const hadPreviousScope = previousScope !== undefined;
|
|
254
|
+
const previousSnapshot = this.buildScopeChangeSnapshot(previousScope);
|
|
255
|
+
const nextSnapshot = this.buildScopeChangeSnapshot(normalizedScope);
|
|
256
|
+
this.providedScope = normalizedScope;
|
|
257
|
+
// Fire the hook when the observable snapshot changed OR
|
|
258
|
+
// when the scope transitioned in or out of existence. The
|
|
259
|
+
// latter covers the "first publish" and "clear" lifecycle
|
|
260
|
+
// events even when the snapshot itself is all-undefined.
|
|
261
|
+
const existenceChanged = !hadPreviousScope;
|
|
262
|
+
const observableChanged = !this.snapshotsEqual(previousSnapshot, nextSnapshot);
|
|
263
|
+
if (existenceChanged || observableChanged) {
|
|
264
|
+
const onScopeChange = normalizedScope.onScopeChange ??
|
|
265
|
+
previousScope?.onScopeChange;
|
|
266
|
+
onScopeChange?.(nextSnapshot);
|
|
267
|
+
}
|
|
268
|
+
return normalizedScope;
|
|
269
|
+
}
|
|
270
|
+
buildScopeChangeSnapshot(scope) {
|
|
271
|
+
return {
|
|
272
|
+
store: scope?.store,
|
|
273
|
+
product: scope?.product,
|
|
274
|
+
option: scope?.option,
|
|
275
|
+
state: this.computeResult
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Fires `onScopeChange` for compute-result-only transitions.
|
|
280
|
+
*
|
|
281
|
+
* `BdComputeController.onResult` writes `computeResult`, which
|
|
282
|
+
* is part of the published snapshot's `state`. Without this
|
|
283
|
+
* trigger, consumers watching the snapshot would miss compute
|
|
284
|
+
* state changes that are not accompanied by a scope publish
|
|
285
|
+
* or clear. Targeted invocation keeps the contract in one
|
|
286
|
+
* place: `publishScope()` and `clearScope()` keep their own
|
|
287
|
+
* paths; this helper handles the compute-only path.
|
|
288
|
+
*
|
|
289
|
+
* Idempotent: no-op when no scope has been published yet
|
|
290
|
+
* (the hook is not on any scope) or when the snapshot's
|
|
291
|
+
* `state` did not actually change (caller short-circuits via
|
|
292
|
+
* `Object.is` before calling).
|
|
293
|
+
*/
|
|
294
|
+
_fireOnScopeChangeForCompute() {
|
|
295
|
+
if (!this.providedScope) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const snapshot = this.buildScopeChangeSnapshot(this.providedScope);
|
|
299
|
+
const onScopeChange = this.providedScope.onScopeChange;
|
|
300
|
+
onScopeChange?.(snapshot);
|
|
301
|
+
}
|
|
302
|
+
snapshotsEqual(a, b) {
|
|
303
|
+
return (a.store === b.store &&
|
|
304
|
+
a.product === b.product &&
|
|
305
|
+
a.option === b.option &&
|
|
306
|
+
a.state === b.state);
|
|
307
|
+
}
|
|
308
|
+
scopeWithoutOwnedValues(scope) {
|
|
309
|
+
let nextScope;
|
|
310
|
+
for (const key of this.scopedValueKeys) {
|
|
311
|
+
if (!hasOwn(scope, key)) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
if (nextScope === undefined) {
|
|
315
|
+
nextScope = { ...scope };
|
|
316
|
+
}
|
|
317
|
+
delete nextScope[key];
|
|
318
|
+
}
|
|
319
|
+
return nextScope ?? scope;
|
|
320
|
+
}
|
|
321
|
+
updateScopedValueKeys(sourceScope, normalizedScope) {
|
|
322
|
+
this.updateScopedValueKey('derived', sourceScope, normalizedScope, this.derived);
|
|
323
|
+
this.updateScopedValueKey('mutationBatchSchedule', sourceScope, normalizedScope, this.mutationBatchSchedule);
|
|
324
|
+
this.updateScopedValueKey('onScopeChange', sourceScope, normalizedScope, this.onScopeChange);
|
|
325
|
+
this.updateScopedValueKey('dataLayer', sourceScope, normalizedScope, this.dataLayer);
|
|
326
|
+
}
|
|
327
|
+
updateScopedValueKey(key, sourceScope, normalizedScope, ownValue) {
|
|
328
|
+
if (ownValue !== undefined &&
|
|
329
|
+
sourceScope[key] === undefined &&
|
|
330
|
+
Object.is(normalizedScope[key], ownValue)) {
|
|
331
|
+
this.scopedValueKeys.add(key);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
this.scopedValueKeys.delete(key);
|
|
335
|
+
}
|
|
336
|
+
clearScope() {
|
|
337
|
+
if (this.store !== undefined) {
|
|
338
|
+
this.publishScope(createBdStoreScope(this.store));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const previousScope = this.providedScope;
|
|
342
|
+
if (previousScope === undefined) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
const onScopeChange = previousScope.onScopeChange;
|
|
346
|
+
this.providedScope = undefined;
|
|
347
|
+
if (onScopeChange) {
|
|
348
|
+
onScopeChange({
|
|
349
|
+
store: undefined,
|
|
350
|
+
product: undefined,
|
|
351
|
+
option: undefined,
|
|
352
|
+
state: undefined
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
requireParentScope() {
|
|
357
|
+
if (!this.parentScope) {
|
|
358
|
+
throw new Error(`${this.localName} requires a parent BdScope.`);
|
|
359
|
+
}
|
|
360
|
+
return this.parentScope;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Single-pass overlay applied to every published scope.
|
|
364
|
+
*
|
|
365
|
+
* The pass runs in two phases:
|
|
366
|
+
*
|
|
367
|
+
* 1. **Sparse boolean flags** — `computeDisabled` and
|
|
368
|
+
* `etaDisabled`. Reflected from `isComputeEnabled` /
|
|
369
|
+
* `isEtaEnabled` (the inverse of "is enabled").
|
|
370
|
+
* 2. **Value overlays** — `derived` and
|
|
371
|
+
* `mutationBatchSchedule`. Caller-supplied values win; the
|
|
372
|
+
* per-instance property fills in when the caller did not
|
|
373
|
+
* supply one.
|
|
374
|
+
*
|
|
375
|
+
* Both phases share the same lazy-allocation strategy: a new
|
|
376
|
+
* scope object is only created when at least one phase has a
|
|
377
|
+
* write to perform. A scope with nothing to merge is returned
|
|
378
|
+
* by reference, which lets `publishScope`'s `Object.is` check
|
|
379
|
+
* short-circuit the downstream `@provide` notification.
|
|
380
|
+
*/
|
|
381
|
+
applyScopedFlags(scope) {
|
|
382
|
+
const overlay = {
|
|
383
|
+
flags: {
|
|
384
|
+
computeDisabled: !this.isComputeEnabled,
|
|
385
|
+
etaDisabled: !this.isEtaEnabled
|
|
386
|
+
},
|
|
387
|
+
values: {}
|
|
388
|
+
};
|
|
389
|
+
if (scope.derived === undefined && this.derived !== undefined) {
|
|
390
|
+
overlay.values.derived = this.derived;
|
|
391
|
+
}
|
|
392
|
+
if (scope.mutationBatchSchedule === undefined &&
|
|
393
|
+
this.mutationBatchSchedule !== undefined) {
|
|
394
|
+
overlay.values.mutationBatchSchedule =
|
|
395
|
+
this.mutationBatchSchedule;
|
|
396
|
+
}
|
|
397
|
+
if (scope.onScopeChange === undefined &&
|
|
398
|
+
this.onScopeChange !== undefined) {
|
|
399
|
+
overlay.values.onScopeChange = this.onScopeChange;
|
|
400
|
+
}
|
|
401
|
+
if (scope.dataLayer === undefined &&
|
|
402
|
+
this.dataLayer !== undefined) {
|
|
403
|
+
overlay.values.dataLayer = this.dataLayer;
|
|
404
|
+
}
|
|
405
|
+
return applyScopedFlags(scope, overlay);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Publishes or clears the scope for a `store` property change.
|
|
409
|
+
*
|
|
410
|
+
* Single entry point for the three transitions `store` can drive:
|
|
411
|
+
*
|
|
412
|
+
* 1. `store` is `undefined` → `clearScope()` removes the published
|
|
413
|
+
* scope and fires the `onScopeChange` hook with all-undefined
|
|
414
|
+
* fields.
|
|
415
|
+
* 2. `store` is defined and a scope is already published →
|
|
416
|
+
* re-publishes the existing scope with the new store reference
|
|
417
|
+
* (the rest of the scope — `derived`, `mutationBatchSchedule`,
|
|
418
|
+
* `onScopeChange`, flags — is preserved).
|
|
419
|
+
* 3. `store` is defined and no scope is published yet → publishes a
|
|
420
|
+
* fresh `createBdStoreScope(this.store)` so the first descendant
|
|
421
|
+
* read sees a non-undefined `parentScope.store`.
|
|
422
|
+
*
|
|
423
|
+
* Called from `willUpdate` whenever `changedProperties.has('store')`.
|
|
424
|
+
* Idempotent: re-publishing the same scope reference is a no-op for
|
|
425
|
+
* the `@provide` notification because `publishScope` already short-
|
|
426
|
+
* circuits on `Object.is(this.providedScope, normalizedScope)`.
|
|
427
|
+
*/
|
|
428
|
+
publishStoreScope() {
|
|
429
|
+
if (this.store === undefined) {
|
|
430
|
+
this.clearScope();
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
if (this.providedScope) {
|
|
434
|
+
this.publishScope({
|
|
435
|
+
...this.providedScope,
|
|
436
|
+
store: this.store
|
|
437
|
+
});
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
this.publishScope(createBdStoreScope(this.store));
|
|
441
|
+
}
|
|
442
|
+
willUpdate(changedProperties) {
|
|
443
|
+
super.willUpdate(changedProperties);
|
|
444
|
+
const overlayPropsChanged = changedProperties.has('computeDisabled') ||
|
|
445
|
+
changedProperties.has('etaDisabled') ||
|
|
446
|
+
changedProperties.has('derived') ||
|
|
447
|
+
changedProperties.has('mutationBatchSchedule') ||
|
|
448
|
+
changedProperties.has('onScopeChange') ||
|
|
449
|
+
changedProperties.has('dataLayer');
|
|
450
|
+
const storeChanged = changedProperties.has('store');
|
|
451
|
+
if (changedProperties.has('ignoreEvents')) {
|
|
452
|
+
this.#ignoredEventIds = undefined;
|
|
453
|
+
}
|
|
454
|
+
if (!overlayPropsChanged && !storeChanged) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
if (storeChanged) {
|
|
458
|
+
this.publishStoreScope();
|
|
459
|
+
}
|
|
460
|
+
if (overlayPropsChanged && this.providedScope) {
|
|
461
|
+
this.publishScope(this.providedScope);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
__decorate([
|
|
466
|
+
provide({
|
|
467
|
+
context: bdComputeContext
|
|
468
|
+
}),
|
|
469
|
+
state()
|
|
470
|
+
], BdScopedElement.prototype, "computeResult", void 0);
|
|
471
|
+
__decorate([
|
|
472
|
+
property({
|
|
473
|
+
attribute: 'eta-disabled',
|
|
474
|
+
type: Boolean,
|
|
475
|
+
reflect: true
|
|
476
|
+
})
|
|
477
|
+
], BdScopedElement.prototype, "etaDisabled", void 0);
|
|
478
|
+
__decorate([
|
|
479
|
+
property({
|
|
480
|
+
attribute: 'compute-disabled',
|
|
481
|
+
type: Boolean,
|
|
482
|
+
reflect: true
|
|
483
|
+
})
|
|
484
|
+
], BdScopedElement.prototype, "computeDisabled", void 0);
|
|
485
|
+
__decorate([
|
|
486
|
+
consume({
|
|
487
|
+
context: bdScopeContext,
|
|
488
|
+
subscribe: true
|
|
489
|
+
}),
|
|
490
|
+
property({
|
|
491
|
+
attribute: false
|
|
492
|
+
})
|
|
493
|
+
], BdScopedElement.prototype, "parentScope", void 0);
|
|
494
|
+
__decorate([
|
|
495
|
+
provide({
|
|
496
|
+
context: bdScopeContext
|
|
497
|
+
}),
|
|
498
|
+
state()
|
|
499
|
+
], BdScopedElement.prototype, "providedScope", void 0);
|
|
500
|
+
__decorate([
|
|
501
|
+
property({
|
|
502
|
+
attribute: 'ignore-events'
|
|
503
|
+
})
|
|
504
|
+
], BdScopedElement.prototype, "ignoreEvents", void 0);
|
|
505
|
+
__decorate([
|
|
506
|
+
property({
|
|
507
|
+
attribute: 'ignore-events-parent',
|
|
508
|
+
type: Boolean,
|
|
509
|
+
reflect: true
|
|
510
|
+
})
|
|
511
|
+
], BdScopedElement.prototype, "ignoreEventsParent", void 0);
|
|
512
|
+
__decorate([
|
|
513
|
+
property({
|
|
514
|
+
attribute: false
|
|
515
|
+
})
|
|
516
|
+
], BdScopedElement.prototype, "derived", void 0);
|
|
517
|
+
__decorate([
|
|
518
|
+
property({
|
|
519
|
+
attribute: false
|
|
520
|
+
})
|
|
521
|
+
], BdScopedElement.prototype, "mutationBatchSchedule", void 0);
|
|
522
|
+
__decorate([
|
|
523
|
+
property({
|
|
524
|
+
attribute: false
|
|
525
|
+
})
|
|
526
|
+
], BdScopedElement.prototype, "onScopeChange", void 0);
|
|
527
|
+
__decorate([
|
|
528
|
+
property({
|
|
529
|
+
attribute: false
|
|
530
|
+
})
|
|
531
|
+
], BdScopedElement.prototype, "dataLayer", void 0);
|
|
532
|
+
__decorate([
|
|
533
|
+
property({
|
|
534
|
+
attribute: false
|
|
535
|
+
})
|
|
536
|
+
], BdScopedElement.prototype, "store", void 0);
|
|
537
|
+
/**
|
|
538
|
+
* Parses the comma-separated `ignore-events` attribute into a set of ids.
|
|
539
|
+
*
|
|
540
|
+
* Empty entries are skipped so `"foo, ,bar"` produces `{ foo, bar }`.
|
|
541
|
+
* The function is exported so test code can compare against the same
|
|
542
|
+
* parsing rules the runtime uses.
|
|
543
|
+
*/
|
|
544
|
+
export function parseIgnoreEvents(value) {
|
|
545
|
+
if (value === undefined || value === '') {
|
|
546
|
+
return EMPTY_EVENT_IDS;
|
|
547
|
+
}
|
|
548
|
+
const ids = new Set();
|
|
549
|
+
for (const part of value.split(',')) {
|
|
550
|
+
const trimmed = part.trim();
|
|
551
|
+
if (trimmed !== '') {
|
|
552
|
+
ids.add(trimmed);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return ids.size === 0 ? EMPTY_EVENT_IDS : ids;
|
|
556
|
+
}
|
|
557
|
+
const EMPTY_EVENT_IDS = new Set();
|
|
558
|
+
//# sourceMappingURL=node.scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.scope.js","sourceRoot":"","sources":["../../../src/core/node.scope.ts"],"names":[],"mappings":";;;;;;AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAEL,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EAKlB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EACL,oBAAoB,EAErB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,uBAAuB,EAIxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAKhD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAuBlD,SAAS,MAAM,CACb,MAAc,EACd,GAAgB;IAEhB,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CACzC,MAAM,EACN,GAAG,CACJ,CAAC;AACJ,CAAC;AAyCD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAS,gBAAgB,CACvB,KAAc,EACd,QAWE;IAEF,IAAI,UAA+B,CAAC;IAEpC,MAAM,aAAa,GAAG,GAAY,EAAE;QAClC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,UAAU,GAAG;YACX,GAAG,KAAK;SACT,CAAC;QAEF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IAEF,KACE,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAGlD,EACH,CAAC;QACD,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAEhC,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;gBACzB,aAAa,EAA8B,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YAC3D,CAAC;YAED,SAAS;QACX,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;YACvB,OAAQ,aAAa,EAA8B,CAAC,GAAG,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,KACE,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAMjD,EACH,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,SAAS;QACX,CAAC;QAED,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;YACjC,SAAS;QACX,CAAC;QAEA,aAAa,EAA8B,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC5D,CAAC;IAED,OAAO,UAAU,IAAI,KAAK,CAAC;AAC7B,CAAC;AAED,MAAM,OAAgB,eAAgB,SAAQ,aAAa;IAA3D;;QACmB,oBAAe,GAAG,IAAI,GAAG,EAAmB,CAAC;QAQrD,YAAO,GACd,IAAI,mBAAmB,CAAC,IAAI,EAAE;YAC5B,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK;YAErC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB;YAEpC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;gBACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC;gBAEpC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;gBAE5B,IAAI,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;oBAChC,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,4BAA4B,EAAE,CAAC;YACtC,CAAC;SACF,CAAC,CAAC;QAaL;;;;;;;;;;;;;;;;;;;;;;WAsBG;QACM,QAAG,GACV,2BAA2B,CAMzB,IAAI,EAAE;YACN,IAAI,EAAE,GAAG,EAAE,CAAC;gBACV,IAAI,CAAC,YAAY;gBACjB,IAAI,CAAC,aAAa;aACV;YAEV,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY;YAEhC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE;gBAC5B,MAAM,GAAG,GAAG,uBAAuB,CAAC;oBAClC,KAAK,EAAI,KAAK,EAAE,KAAK;oBACrB,OAAO,EAAE,KAAK,EAAE,OAAO;oBACvB,MAAM,EAAG,KAAK,EAAE,MAAM;oBACtB,KAAK,EAAI,OAAO;iBACjB,CAAC,CAAC;gBAEH,OAAO;oBACL,KAAK,EAAI,GAAG,CAAC,KAAK;oBAClB,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,MAAM,EAAG,GAAG,CAAC,MAAM;oBACnB,KAAK,EAAI,GAAG,CAAC,KAAK;oBAClB,GAAG,EAAM,GAAG,CAAC,GAAG;oBAChB,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC;iBAClC,CAAC;YACJ,CAAC;YAED;;;;;;;;;;;;;;;;;;;;;;;eAuBG;YACH,qBAAqB,EAAE,GAAG,EAAE,CAC1B,IAAI,CAAC,YAAY,EAAE,qBAAqB;gBACxC,IAAI,CAAC,WAAW,EAAE,qBAAqB;YAEzC,iBAAiB,EAAE,CAAC,OAAO,EAAE,EAAE;gBAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC;gBAE/B,OAAO,CACL,IAAI,KAAK,YAAY;oBACrB,IAAI,KAAK,YAAY;oBACrB,IAAI,KAAK,WAAW,CACrB,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;QAOL,gBAAW,GAAG,KAAK,CAAC;QAcpB,oBAAe,GAAG,KAAK,CAAC;QAoDxB;;;;;;WAMG;QAMH,uBAAkB,GAAG,KAAK,CAAC;IAojB7B,CAAC;IAjvBC;;;;;;OAMG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC;IACd,CAAC;IAwGD,IAAc,YAAY;QACxB,OAAO,CACL,IAAI,CAAC,WAAW,KAAK,IAAI;YACzB,IAAI,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CACvC,CAAC;IACJ,CAAC;IAwBD,IAAc,YAAY;QACxB,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,IAAc,gBAAgB;QAC5B,OAAO,CACL,IAAI,CAAC,eAAe,KAAK,IAAI;YAC7B,IAAI,CAAC,WAAW,EAAE,eAAe,KAAK,IAAI,CAC3C,CAAC;IACJ,CAAC;IAwCD;;;;;OAKG;IACH,gBAAgB,CAAuB;IAEvC,IAAc,eAAe;QAC3B,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC,gBAAgB,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,gBAAgB,GAAG,iBAAiB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAE7D,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED;;;;;;;;;OASG;IACO,iBAAiB,CAAC,SAG3B;QACC,IACE,IAAI,CAAC,kBAAkB;YACvB,SAAS,CAAC,MAAM,KAAK,QAAQ,EAC7B,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC;QAErC,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,oBAAoB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAE3D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAES,YAAY,CAAC,SAAkB;QACvC,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC;YAC1D,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC;YACzC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAE3D,IAAI,CAAC,qBAAqB,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QAEzD,IAAI,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,EAAE,CAAC;YACnD,OAAO,eAAe,CAAC;QACzB,CAAC;QAED,MAAM,aAAa,GAAM,IAAI,CAAC,aAAa,CAAC;QAC5C,MAAM,gBAAgB,GAAG,aAAa,KAAK,SAAS,CAAC;QACrD,MAAM,gBAAgB,GAAG,IAAI,CAAC,wBAAwB,CACpD,aAAa,CACd,CAAC;QACF,MAAM,YAAY,GAAG,IAAI,CAAC,wBAAwB,CAChD,eAAe,CAChB,CAAC;QAEF,IAAI,CAAC,aAAa,GAAG,eAAe,CAAC;QAErC,wDAAwD;QACxD,0DAA0D;QAC1D,0DAA0D;QAC1D,yDAAyD;QACzD,MAAM,gBAAgB,GAAG,CAAC,gBAAgB,CAAC;QAC3C,MAAM,iBAAiB,GAAG,CAAC,IAAI,CAAC,cAAc,CAC5C,gBAAgB,EAChB,YAAY,CACb,CAAC;QAEF,IAAI,gBAAgB,IAAI,iBAAiB,EAAE,CAAC;YAC1C,MAAM,aAAa,GACjB,eAAe,CAAC,aAAa;gBAC7B,aAAa,EAAE,aAAa,CAAC;YAE/B,aAAa,EAAE,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,eAAe,CAAC;IACzB,CAAC;IAEO,wBAAwB,CAC9B,KAA0B;QAE1B,OAAO;YACL,KAAK,EAAI,KAAK,EAAE,KAAK;YACrB,OAAO,EAAE,KAAK,EAAE,OAAO;YACvB,MAAM,EAAG,KAAK,EAAE,MAAM;YACtB,KAAK,EAAI,IAAI,CAAC,aAAa;SAC5B,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACK,4BAA4B;QAClC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,wBAAwB,CAC5C,IAAI,CAAC,aAAa,CACnB,CAAC;QAEF,MAAM,aAAa,GACjB,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC;QAEnC,aAAa,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAEO,cAAc,CACpB,CAAwB,EACxB,CAAwB;QAExB,OAAO,CACL,CAAC,CAAC,KAAK,KAAO,CAAC,CAAC,KAAK;YACrB,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO;YACvB,CAAC,CAAC,MAAM,KAAM,CAAC,CAAC,MAAM;YACtB,CAAC,CAAC,KAAK,KAAO,CAAC,CAAC,KAAK,CACtB,CAAC;IACJ,CAAC;IAEO,uBAAuB,CAAC,KAAc;QAC5C,IAAI,SAA8B,CAAC;QAEnC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;gBACxB,SAAS;YACX,CAAC;YAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,SAAS,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;YAC3B,CAAC;YAED,OAAQ,SAAqC,CAAC,GAAG,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,SAAS,IAAI,KAAK,CAAC;IAC5B,CAAC;IAEO,qBAAqB,CAC3B,WAAoB,EACpB,eAAwB;QAExB,IAAI,CAAC,oBAAoB,CACvB,SAAS,EACT,WAAW,EACX,eAAe,EACf,IAAI,CAAC,OAAO,CACb,CAAC;QACF,IAAI,CAAC,oBAAoB,CACvB,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,IAAI,CAAC,qBAAqB,CAC3B,CAAC;QACF,IAAI,CAAC,oBAAoB,CACvB,eAAe,EACf,WAAW,EACX,eAAe,EACf,IAAI,CAAC,aAAa,CACnB,CAAC;QACF,IAAI,CAAC,oBAAoB,CACvB,WAAW,EACX,WAAW,EACX,eAAe,EACf,IAAI,CAAC,SAAS,CACf,CAAC;IACJ,CAAC;IAEO,oBAAoB,CAC1B,GAAoB,EACpB,WAAoB,EACpB,eAAwB,EACxB,QAAuB;QAEvB,IACE,QAAQ,KAAK,SAAS;YACtB,WAAW,CAAC,GAAG,CAAC,KAAK,SAAS;YAC9B,MAAM,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,EACzC,CAAC;YACD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAES,UAAU;QAClB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAElD,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QAEzC,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,aAAa,CAAC,aAAa,CAAC;QAElD,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAE/B,IAAI,aAAa,EAAE,CAAC;YAClB,aAAa,CAAC;gBACZ,KAAK,EAAI,SAAS;gBAClB,OAAO,EAAE,SAAS;gBAClB,MAAM,EAAG,SAAS;gBAClB,KAAK,EAAI,SAAS;aACnB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAES,kBAAkB;QAC1B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,CAAC,SAAS,6BAA6B,CAC/C,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACK,gBAAgB,CAAC,KAAc;QACrC,MAAM,OAAO,GAAmB;YAC9B,KAAK,EAAE;gBACL,eAAe,EAAE,CAAC,IAAI,CAAC,gBAAgB;gBACvC,WAAW,EAAM,CAAC,IAAI,CAAC,YAAY;aACpC;YACD,MAAM,EAAE,EAAE;SACX,CAAC;QAEF,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9D,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QACxC,CAAC;QAED,IACE,KAAK,CAAC,qBAAqB,KAAK,SAAS;YACzC,IAAI,CAAC,qBAAqB,KAAK,SAAS,EACxC,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,qBAAqB;gBAClC,IAAI,CAAC,qBAAqB,CAAC;QAC/B,CAAC;QAED,IACE,KAAK,CAAC,aAAa,KAAK,SAAS;YACjC,IAAI,CAAC,aAAa,KAAK,SAAS,EAChC,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QACpD,CAAC;QAED,IACE,KAAK,CAAC,SAAS,KAAK,SAAS;YAC7B,IAAI,CAAC,SAAS,KAAK,SAAS,EAC5B,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAC5C,CAAC;QAED,OAAO,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAsLD;;;;;;;;;;;;;;;;;;;;OAoBG;IACO,iBAAiB;QACzB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;YAElB,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,IAAI,CAAC,YAAY,CAAC;gBAChB,GAAG,IAAI,CAAC,aAAa;gBACrB,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC,CAAC;YAEH,OAAO;QACT,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACpD,CAAC;IAEkB,UAAU,CAC3B,iBAAuC;QAEvC,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QAEpC,MAAM,mBAAmB,GACvB,iBAAiB,CAAC,GAAG,CAAC,iBAAiB,CAAC;YACxC,iBAAiB,CAAC,GAAG,CAAC,aAAa,CAAC;YACpC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC;YAChC,iBAAiB,CAAC,GAAG,CAAC,uBAAuB,CAAC;YAC9C,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC;YACtC,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACrC,MAAM,YAAY,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEpD,IAAI,iBAAiB,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,mBAAmB,IAAI,CAAC,YAAY,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,mBAAmB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC9C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;CACF;AAtwBW;IAJT,OAAO,CAAC;QACP,OAAO,EAAE,gBAAgB;KAC1B,CAAC;IACD,KAAK,EAAE;sDACkC;AAoI1C;IALC,QAAQ,CAAC;QACR,SAAS,EAAE,cAAc;QACzB,IAAI,EAAO,OAAO;QAClB,OAAO,EAAI,IAAI;KAChB,CAAC;oDACkB;AAcpB;IALC,QAAQ,CAAC;QACR,SAAS,EAAE,kBAAkB;QAC7B,IAAI,EAAO,OAAO;QAClB,OAAO,EAAI,IAAI;KAChB,CAAC;wDACsB;AASd;IAPT,OAAO,CAAC;QACP,OAAO,EAAI,cAAc;QACzB,SAAS,EAAE,IAAI;KAChB,CAAC;IACD,QAAQ,CAAC;QACR,SAAS,EAAE,KAAK;KACjB,CAAC;oDAC8B;AAMtB;IAJT,OAAO,CAAC;QACP,OAAO,EAAE,cAAc;KACxB,CAAC;IACD,KAAK,EAAE;sDAC0B;AAmClC;IAHC,QAAQ,CAAC;QACR,SAAS,EAAE,eAAe;KAC3B,CAAC;qDACoB;AActB;IALC,QAAQ,CAAC;QACR,SAAS,EAAE,sBAAsB;QACjC,IAAI,EAAO,OAAO;QAClB,OAAO,EAAI,IAAI;KAChB,CAAC;2DACyB;AAsX3B;IAHC,QAAQ,CAAC;QACR,SAAS,EAAE,KAAK;KACjB,CAAC;gDACwB;AA+B1B;IAHC,QAAQ,CAAC;QACR,SAAS,EAAE,KAAK;KACjB,CAAC;8DAC+C;AAsCjD;IAHC,QAAQ,CAAC;QACR,SAAS,EAAE,KAAK;KACjB,CAAC;sDAC8B;AAUhC;IAHC,QAAQ,CAAC;QACR,SAAS,EAAE,KAAK;KACjB,CAAC;kDACwB;AAuC1B;IAHC,QAAQ,CAAC;QACR,SAAS,EAAE,KAAK;KACjB,CAAC;8CACY;AA0EhB;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAyB;IAEzB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAE5B,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC;AAChD,CAAC;AAED,MAAM,eAAe,GAAwB,IAAI,GAAG,EAAU,CAAC","sourcesContent":["import type { BdComputeResult } from '@/compute/compute.expand.js';\nimport { bdComputeContext } from '@/contexts/context.compute.js';\nimport {\n BdScope,\n bdScopeContext,\n createBdStoreScope,\n runBdScopeDerived,\n type BdDataLayerFn,\n type BdScopeChangeFn,\n type BdScopeChangeSnapshot,\n type BdScopeDeriveFn\n} from '@/contexts/context.scope.js';\nimport { BdComputeController } from '@/controllers/controller.compute.js';\nimport {\n getTransitionEventId,\n type BdTransition\n} from '@/core/actions.js';\nimport {\n createEtaTemplateController\n} from '@/eta/controller.js';\nimport type { EtaMutationBatchSchedule } from '@/eta/types.js';\nimport {\n buildTemplateDslContext,\n type TemplateOptionContext,\n type TemplateProductContext,\n type TemplateStateContext\n} from '@/renders/context.js';\nimport { consume, provide } from '@lit/context';\nimport type {\n Store\n} from '@repobit/dex-store';\nimport type { PropertyValues } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { BdNodeElement } from './node.element.js';\n/**\n * The shape templates see under a `BdScopedElement`.\n *\n * Mirrors the v1 `it.*` layout: `option` / `product` / `state` are flattened\n * DTOs with pre-formatted strings, and `ctx` is an alias of `state`. Adding\n * a new field here is a public surface change (every consumer can read it),\n * so prefer extending `TemplateDslContext` and rebinding this snapshot\n * rather than spreading the raw `BdScope` object.\n *\n * `derived` carries whatever object `scope.derived({...})` returned for the\n * current scope — templates read derived properties as `<%= it.derived.foo\n * %>`. `undefined` when the scope has no `derived` factory.\n */\nexport type BdScopedTemplateContext = {\n store : Store | undefined;\n product: TemplateProductContext | undefined;\n option : TemplateOptionContext | undefined;\n state : TemplateStateContext | undefined;\n ctx : TemplateStateContext | undefined;\n derived: Readonly<Record<string, unknown>> | undefined;\n};\n\nfunction hasOwn(\n object: object,\n key: PropertyKey\n): boolean {\n return Object.prototype.hasOwnProperty.call(\n object,\n key\n );\n}\n\n/**\n * Applies sparse boolean flags to a scope object.\n *\n * Flags are represented by presence, not by true/false values:\n * - `computeDisabled: true` means compute is disabled;\n * - missing `computeDisabled` means compute is enabled.\n *\n * The function preserves the original scope reference when the flags already\n * match the requested state. Otherwise, it returns a shallow clone with the\n * required flags added or removed.\n */\n/**\n * Overlay shape consumed by `applyScopedFlags`.\n *\n * `flags` is the sparse-boolean phase (`computeDisabled`,\n * `etaDisabled`). `values` is the value-merge phase (`derived`,\n * `mutationBatchSchedule`). Both phases run in the same lazy\n * allocation slot, so any write in either phase causes the\n * scope to be cloned exactly once.\n */\ntype BdScopeOverlay = Readonly<{\n flags : Partial<Record<\n 'computeDisabled' | 'etaDisabled',\n boolean\n >>;\n values: Partial<{\n derived : BdScopeDeriveFn;\n mutationBatchSchedule: EtaMutationBatchSchedule;\n onScopeChange : BdScopeChangeFn;\n dataLayer : BdDataLayerFn;\n }>;\n}>;\n\ntype BdScopeValueKey =\n | 'derived'\n | 'mutationBatchSchedule'\n | 'onScopeChange'\n | 'dataLayer';\n\n/**\n * Sparse flag application.\n *\n * `applyScopedFlags` is the single pass that merges per-node\n * overlays into the published scope:\n *\n * - **sparse boolean flags** — `computeDisabled` and\n * `etaDisabled`. Represented by presence, not by `true` /\n * `false`: missing means enabled, present and `true` means\n * disabled. Setting `enabled=false` deletes the flag rather\n * than storing `false`.\n *\n * - **value overlays** — `derived` and\n * `mutationBatchSchedule`. Caller-supplied values win; the\n * node's own property fills in when the caller did not supply\n * one. Missing on both sides means the field is absent from\n * the published scope.\n *\n * The function preserves the original `object` reference when\n * nothing actually changes. The `nextObject` slot is only\n * allocated the first time a write happens, so a scope with\n * nothing to merge returns the same reference it was given —\n * important because `publishScope` uses `Object.is` to short-\n * circuit downstream `@provide` notifications.\n */\nfunction applyScopedFlags(\n scope: BdScope,\n overlays: Readonly<{\n flags: Partial<Record<\n 'computeDisabled' | 'etaDisabled',\n boolean\n >>;\n values: Partial<{\n derived : BdScopeDeriveFn;\n mutationBatchSchedule: EtaMutationBatchSchedule;\n onScopeChange : BdScopeChangeFn;\n dataLayer : BdDataLayerFn;\n }>;\n }>\n): BdScope {\n let nextObject: BdScope | undefined;\n\n const getNextObject = (): BdScope => {\n if (nextObject !== undefined) {\n return nextObject;\n }\n\n nextObject = {\n ...scope\n };\n\n return nextObject;\n };\n\n for (\n const [key, enabled] of Object.entries(overlays.flags) as [\n 'computeDisabled' | 'etaDisabled',\n boolean\n ][]\n ) {\n const currentValue = scope[key];\n\n if (enabled) {\n if (currentValue !== true) {\n (getNextObject() as Record<string, unknown>)[key] = true;\n }\n\n continue;\n }\n\n if (hasOwn(scope, key)) {\n delete (getNextObject() as Record<string, unknown>)[key];\n }\n }\n\n for (\n const [key, value] of Object.entries(overlays.values) as [\n 'derived' | 'mutationBatchSchedule' | 'onScopeChange' | 'dataLayer',\n BdScopeDeriveFn |\n EtaMutationBatchSchedule |\n BdScopeChangeFn |\n BdDataLayerFn\n ][]\n ) {\n if (value === undefined) {\n continue;\n }\n\n if (Object.is(scope[key], value)) {\n continue;\n }\n\n (getNextObject() as Record<string, unknown>)[key] = value;\n }\n\n return nextObject ?? scope;\n}\n\nexport abstract class BdScopedElement extends BdNodeElement {\n private readonly scopedValueKeys = new Set<BdScopeValueKey>();\n\n @provide({\n context: bdComputeContext\n })\n @state()\n protected computeResult?: BdComputeResult;\n\n readonly compute =\n new BdComputeController(this, {\n store: () => this.currentScope?.store,\n\n enabled: () => this.isComputeEnabled,\n\n onResult: (result) => {\n const previous = this.computeResult;\n\n this.computeResult = result;\n\n if (Object.is(previous, result)) {\n return;\n }\n\n this._fireOnScopeChangeForCompute();\n }\n });\n\n /**\n * Owning boundary for the Eta template index.\n *\n * `BdScopedElement` IS the index root — every nested template\n * is owned by the closest enclosing bd-* node, and that node\n * in turn owns the controller that renders its subtree.\n */\n get root(): Element {\n return this;\n }\n\n /**\n * Eta template controller that renders the subtree against the\n * current scope and compute result.\n *\n * Args trigger a re-render when the scope, the compute result,\n * or the eta-enabled flag change. The render is gated on\n * `isEtaEnabled` so a disabled scope does not flicker\n * intermediate state.\n *\n * The context exposes **only** `store`, `product`, `option`,\n * and `state` — exactly the fields templates are expected to\n * reference. We do not spread the full scope, do not surface\n * `$scope` / `$state` handles, and do not leak the transition\n * object. New fields belong on `BdScope` plus an explicit\n * binding here so the public template surface stays auditable.\n *\n * The boundary predicate uses raw tag names so nested\n * `bd-context` / `bd-product` / `bd-option` nodes\n * keep their own controllers and templates do not leak across\n * scope boundaries. Tag-name checks are stable before custom\n * element upgrade — `EtaTemplateControllerOptions.isBoundaryElement`\n * MUST work on raw DOM shape.\n */\n readonly eta =\n createEtaTemplateController<\n readonly [\n scope : BdScope | undefined,\n compute: BdComputeResult | undefined\n ],\n BdScopedTemplateContext\n >(this, {\n args: () => [\n this.currentScope,\n this.computeResult\n ] as const,\n\n enabled: () => this.isEtaEnabled,\n\n context: ([scope, compute]) => {\n const dsl = buildTemplateDslContext({\n store : scope?.store,\n product: scope?.product,\n option : scope?.option,\n state : compute\n });\n\n return {\n store : dsl.store,\n product: dsl.product,\n option : dsl.option,\n state : dsl.state,\n ctx : dsl.ctx,\n derived: runBdScopeDerived(scope)\n };\n },\n\n /**\n * Mutation batch schedule is resolved from the current\n * published scope whenever the batcher schedules a future\n * flush. The value flows through `BdScope` like `derived`\n * does, so a parent that republishes a new\n * `mutationBatchSchedule` is observed by already-constructed\n * descendants on subsequent mutation bursts.\n *\n * Resolution order at scheduling time:\n *\n * 1. `this.currentScope?.mutationBatchSchedule` — this\n * element's normalized published scope, when it has one.\n * It already includes inherited values plus this node's\n * own override.\n * 2. `this.parentScope?.mutationBatchSchedule` — inherited\n * schedule for scoped consumers that do not publish a\n * scope of their own.\n * 3. The Eta controller's own default\n * (`'animation-frame'`).\n *\n * The cascade mirrors `derived`, but the Eta controller gets\n * a resolver callback rather than the current value so the\n * batcher can read the latest published scope.\n */\n mutationBatchSchedule: () =>\n this.currentScope?.mutationBatchSchedule ??\n this.parentScope?.mutationBatchSchedule,\n\n isBoundaryElement: (element) => {\n const name = element.localName;\n\n return (\n name === 'bd-context' ||\n name === 'bd-product' ||\n name === 'bd-option'\n );\n }\n });\n\n @property({\n attribute: 'eta-disabled',\n type : Boolean,\n reflect : true\n })\n etaDisabled = false;\n\n protected get isEtaEnabled(): boolean {\n return (\n this.etaDisabled !== true &&\n this.parentScope?.etaDisabled !== true\n );\n }\n\n @property({\n attribute: 'compute-disabled',\n type : Boolean,\n reflect : true\n })\n computeDisabled = false;\n\n @consume({\n context : bdScopeContext,\n subscribe: true\n })\n @property({\n attribute: false\n })\n protected parentScope?: BdScope;\n\n @provide({\n context: bdScopeContext\n })\n @state()\n protected providedScope?: BdScope;\n\n protected get currentScope(): BdScope | undefined {\n return this.providedScope;\n }\n\n protected get isComputeEnabled(): boolean {\n return (\n this.computeDisabled !== true &&\n this.parentScope?.computeDisabled !== true\n );\n }\n\n /**\n * Comma-separated list of event ids to ignore.\n *\n * Pair with `data-store-event-id` on action elements: any transition\n * whose command carries a matching `eventId` is dropped before it can\n * drive this node (or any of its descendants, since the cascade is\n * gated here).\n *\n * Example:\n * ```html\n * <button data-store-action\n * data-store-event-id=\"devicesBtn\"\n * data-store-set-devices=\"25\">25</button>\n *\n * <bd-option ignore-events=\"devicesBtn, subscriptionBtn\">\n * ...\n * </bd-option>\n * ```\n */\n @property({\n attribute: 'ignore-events'\n })\n ignoreEvents?: string;\n\n /**\n * When set, this node only reacts to events originating inside its own\n * subtree. Cascading transitions from `parentScope.transition` are\n * dropped, mirroring v1's `<bd-state ignore-events-parent>` semantics.\n *\n * `<bd-context>` enables this by default (it is a hard event boundary).\n */\n @property({\n attribute: 'ignore-events-parent',\n type : Boolean,\n reflect : true\n })\n ignoreEventsParent = false;\n\n /**\n * Lazy cache of the parsed `ignore-events` attribute.\n *\n * Re-parsed whenever the attribute changes; consumers should access\n * `this.ignoredEventIds` rather than calling `parseIgnoreEvents` themselves.\n */\n #ignoredEventIds?: ReadonlySet<string>;\n\n protected get ignoredEventIds(): ReadonlySet<string> {\n if (this.#ignoredEventIds !== undefined) {\n return this.#ignoredEventIds;\n }\n\n this.#ignoredEventIds = parseIgnoreEvents(this.ignoreEvents);\n\n return this.#ignoredEventIds;\n }\n\n /**\n * Filter callback handed to each node's `BdActionResolveController`.\n *\n * Drops transitions whose `eventId` matches an entry in `ignore-events`,\n * and — when `ignore-events-parent` is set — drops any cascade from a\n * parent scope. Concrete nodes pass `filterTransition: (c) =>\n * this._filterTransition(c)` into their controller config; the\n * controller invokes this for both local `bd-action-request` events\n * and inherited transitions.\n */\n protected _filterTransition(candidate: {\n transition: BdTransition;\n source : 'local' | 'parent';\n }): boolean {\n if (\n this.ignoreEventsParent &&\n candidate.source === 'parent'\n ) {\n return false;\n }\n\n const ignored = this.ignoredEventIds;\n\n if (ignored.size === 0) {\n return true;\n }\n\n const eventId = getTransitionEventId(candidate.transition);\n\n if (eventId === undefined) {\n return true;\n }\n\n return !ignored.has(eventId);\n }\n\n protected publishScope(nextScope: BdScope): BdScope {\n const sourceScope = Object.is(nextScope, this.providedScope)\n ? this.scopeWithoutOwnedValues(nextScope)\n : nextScope;\n const normalizedScope = this.applyScopedFlags(sourceScope);\n\n this.updateScopedValueKeys(sourceScope, normalizedScope);\n\n if (Object.is(this.providedScope, normalizedScope)) {\n return normalizedScope;\n }\n\n const previousScope = this.providedScope;\n const hadPreviousScope = previousScope !== undefined;\n const previousSnapshot = this.buildScopeChangeSnapshot(\n previousScope\n );\n const nextSnapshot = this.buildScopeChangeSnapshot(\n normalizedScope\n );\n\n this.providedScope = normalizedScope;\n\n // Fire the hook when the observable snapshot changed OR\n // when the scope transitioned in or out of existence. The\n // latter covers the \"first publish\" and \"clear\" lifecycle\n // events even when the snapshot itself is all-undefined.\n const existenceChanged = !hadPreviousScope;\n const observableChanged = !this.snapshotsEqual(\n previousSnapshot,\n nextSnapshot\n );\n\n if (existenceChanged || observableChanged) {\n const onScopeChange =\n normalizedScope.onScopeChange ??\n previousScope?.onScopeChange;\n\n onScopeChange?.(nextSnapshot);\n }\n\n return normalizedScope;\n }\n\n private buildScopeChangeSnapshot(\n scope: BdScope | undefined\n ): BdScopeChangeSnapshot {\n return {\n store : scope?.store,\n product: scope?.product,\n option : scope?.option,\n state : this.computeResult\n };\n }\n\n /**\n * Fires `onScopeChange` for compute-result-only transitions.\n *\n * `BdComputeController.onResult` writes `computeResult`, which\n * is part of the published snapshot's `state`. Without this\n * trigger, consumers watching the snapshot would miss compute\n * state changes that are not accompanied by a scope publish\n * or clear. Targeted invocation keeps the contract in one\n * place: `publishScope()` and `clearScope()` keep their own\n * paths; this helper handles the compute-only path.\n *\n * Idempotent: no-op when no scope has been published yet\n * (the hook is not on any scope) or when the snapshot's\n * `state` did not actually change (caller short-circuits via\n * `Object.is` before calling).\n */\n private _fireOnScopeChangeForCompute(): void {\n if (!this.providedScope) {\n return;\n }\n\n const snapshot = this.buildScopeChangeSnapshot(\n this.providedScope\n );\n\n const onScopeChange =\n this.providedScope.onScopeChange;\n\n onScopeChange?.(snapshot);\n }\n\n private snapshotsEqual(\n a: BdScopeChangeSnapshot,\n b: BdScopeChangeSnapshot\n ): boolean {\n return (\n a.store === b.store &&\n a.product === b.product &&\n a.option === b.option &&\n a.state === b.state\n );\n }\n\n private scopeWithoutOwnedValues(scope: BdScope): BdScope {\n let nextScope: BdScope | undefined;\n\n for (const key of this.scopedValueKeys) {\n if (!hasOwn(scope, key)) {\n continue;\n }\n\n if (nextScope === undefined) {\n nextScope = { ...scope };\n }\n\n delete (nextScope as Record<string, unknown>)[key];\n }\n\n return nextScope ?? scope;\n }\n\n private updateScopedValueKeys(\n sourceScope: BdScope,\n normalizedScope: BdScope\n ): void {\n this.updateScopedValueKey(\n 'derived',\n sourceScope,\n normalizedScope,\n this.derived\n );\n this.updateScopedValueKey(\n 'mutationBatchSchedule',\n sourceScope,\n normalizedScope,\n this.mutationBatchSchedule\n );\n this.updateScopedValueKey(\n 'onScopeChange',\n sourceScope,\n normalizedScope,\n this.onScopeChange\n );\n this.updateScopedValueKey(\n 'dataLayer',\n sourceScope,\n normalizedScope,\n this.dataLayer\n );\n }\n\n private updateScopedValueKey<T>(\n key: BdScopeValueKey,\n sourceScope: BdScope,\n normalizedScope: BdScope,\n ownValue: T | undefined\n ): void {\n if (\n ownValue !== undefined &&\n sourceScope[key] === undefined &&\n Object.is(normalizedScope[key], ownValue)\n ) {\n this.scopedValueKeys.add(key);\n return;\n }\n\n this.scopedValueKeys.delete(key);\n }\n\n protected clearScope(): void {\n if (this.store !== undefined) {\n this.publishScope(createBdStoreScope(this.store));\n\n return;\n }\n\n const previousScope = this.providedScope;\n\n if (previousScope === undefined) {\n return;\n }\n\n const onScopeChange = previousScope.onScopeChange;\n\n this.providedScope = undefined;\n\n if (onScopeChange) {\n onScopeChange({\n store : undefined,\n product: undefined,\n option : undefined,\n state : undefined\n });\n }\n }\n\n protected requireParentScope(): BdScope {\n if (!this.parentScope) {\n throw new Error(\n `${this.localName} requires a parent BdScope.`\n );\n }\n\n return this.parentScope;\n }\n\n /**\n * Single-pass overlay applied to every published scope.\n *\n * The pass runs in two phases:\n *\n * 1. **Sparse boolean flags** — `computeDisabled` and\n * `etaDisabled`. Reflected from `isComputeEnabled` /\n * `isEtaEnabled` (the inverse of \"is enabled\").\n * 2. **Value overlays** — `derived` and\n * `mutationBatchSchedule`. Caller-supplied values win; the\n * per-instance property fills in when the caller did not\n * supply one.\n *\n * Both phases share the same lazy-allocation strategy: a new\n * scope object is only created when at least one phase has a\n * write to perform. A scope with nothing to merge is returned\n * by reference, which lets `publishScope`'s `Object.is` check\n * short-circuit the downstream `@provide` notification.\n */\n private applyScopedFlags(scope: BdScope): BdScope {\n const overlay: BdScopeOverlay = {\n flags: {\n computeDisabled: !this.isComputeEnabled,\n etaDisabled : !this.isEtaEnabled\n },\n values: {}\n };\n\n if (scope.derived === undefined && this.derived !== undefined) {\n overlay.values.derived = this.derived;\n }\n\n if (\n scope.mutationBatchSchedule === undefined &&\n this.mutationBatchSchedule !== undefined\n ) {\n overlay.values.mutationBatchSchedule =\n this.mutationBatchSchedule;\n }\n\n if (\n scope.onScopeChange === undefined &&\n this.onScopeChange !== undefined\n ) {\n overlay.values.onScopeChange = this.onScopeChange;\n }\n\n if (\n scope.dataLayer === undefined &&\n this.dataLayer !== undefined\n ) {\n overlay.values.dataLayer = this.dataLayer;\n }\n\n return applyScopedFlags(scope, overlay);\n }\n\n /**\n * Per-instance derived Eta context factory.\n *\n * Users supply this on any bd-* node (via constructor,\n * attribute, or `instance.derived = fn`) to expose additional\n * template bindings under the `derived` key. The factory\n * receives `{ store, product, option }` and returns an object\n * whose properties become available to templates as\n * `<%= it.derived.<key> %>`.\n *\n * `publishScope` merges this property into the published scope\n * automatically when the caller did not supply an explicit\n * `derived` of its own — so a user just needs to assign\n * `node.derived = fn` (or set the `derived` attribute) and\n * the factory becomes part of the scope for free.\n *\n * Reactivity: the field is a Lit `@property`, so reassigning\n * `this.derived = newFactory` triggers `requestUpdate()` and a\n * re-publish via `willUpdate`. Method references declared\n * once per instance are stable, so the `@lit/task` args\n * comparison short-circuits re-renders for unrelated changes.\n *\n * `derived` is intended to be supplied by users at the call\n * site, not declared on concrete node subclasses. Subclasses\n * that need a static default can still assign it in their\n * constructor; the merge step lets callers override.\n *\n * @example\n *\n * ```ts\n * const product = document.createElement('bd-product');\n * product.productId = 'acrobat-pro';\n * product.derived = ({ product, option }) => ({\n * canBuy : Boolean(product && option),\n * hasDiscount: Boolean(option?.discounted)\n * });\n * ```\n *\n * Or via plain JS (recommended — functions cannot be authored\n * as attribute strings):\n *\n * ```ts\n * const product = document.createElement('bd-product');\n * product.productId = 'acrobat-pro';\n * product.derived = ({ product, option }) => ({\n * canBuy : Boolean(product && option),\n * hasDiscount: Boolean(option?.discounted)\n * });\n * ```\n *\n * The attribute mapping is intentionally omitted — Lit's\n * default converter cannot turn a string into a typed\n * function, so the property is JS-only. Hosts that want\n * attribute-driven configuration should expose a wrapper\n * attribute on their own subclass and assign `derived` from\n * the wrapper's converter.\n */\n @property({\n attribute: false\n })\n derived?: BdScopeDeriveFn;\n\n /**\n * Per-instance mutation batch schedule.\n *\n * Wired through the scope so descendants can read the same\n * value via `parentScope.mutationBatchSchedule`. Existing Eta\n * controllers receive a resolver callback, so flipping the\n * schedule after connection affects future mutation flushes\n * once the parent republishes its scope.\n *\n * Accepted via constructor / `instance.mutationBatchSchedule =\n * 'idle'`. The attribute mapping is intentionally omitted\n * because Lit's default converter is happy with the string\n * union, but exposing it as an attribute would invite the\n * same authoring pitfalls we deliberately avoid for\n * `derived` (callers writing `schedule=\"animation-frame\"`\n * without realising the value is scope-driven rather than an\n * imperative one-shot switch).\n *\n * @example\n *\n * ```ts\n * const product = document.createElement('bd-product');\n * product.productId = 'acrobat-pro';\n * product.mutationBatchSchedule = 'microtask';\n * ```\n */\n @property({\n attribute: false\n })\n mutationBatchSchedule?: EtaMutationBatchSchedule;\n\n /**\n * Per-instance scope-change hook.\n *\n * Fired whenever this node's effective published scope changes\n * — both when `publishScope(...)` produces a new normalized\n * scope reference, and when `clearScope()` removes the\n * scope. The hook receives a narrow snapshot exposing only\n * `store`, `product`, `option`, and `state` — the four fields\n * that drive template rendering. It does NOT receive the\n * transition, the disabled flags, the derived factory, or the\n * mutation batch schedule.\n *\n * Wired through `BdScope.onScopeChange` like `derived` and\n * `mutationBatchSchedule`, so descendants can read the\n * inherited hook from `parentScope.onScopeChange` and a child\n * can override its ancestor's hook by assigning its own.\n *\n * Attribute mapping is intentionally omitted — functions\n * cannot be represented as attribute strings, and a stale or\n * stale-shaped `on-scope-change=\"...\"` attribute would invite\n * the same authoring pitfalls we deliberately avoid for\n * `derived`. Configure via JS instead:\n *\n * @example\n *\n * ```ts\n * const product = document.createElement('bd-product');\n * product.productId = 'acrobat-pro';\n * product.onScopeChange = ({ store, product, option, state }) => {\n * console.log('scope changed', { store, product, option, state });\n * };\n * ```\n */\n @property({\n attribute: false\n })\n onScopeChange?: BdScopeChangeFn;\n\n /**\n * Inherited callback for option-load data-layer events.\n * Configure it as a JavaScript property; functions are not\n * represented as attributes.\n */\n @property({\n attribute: false\n })\n dataLayer?: BdDataLayerFn;\n\n /**\n * Per-instance store reference.\n *\n * When set on any `BdScopedElement` subclass, the value is published\n * into the scope context via `createBdStoreScope(this.store)` so\n * descendants can consume it from `parentScope.store`. Setting it back\n * to `undefined` calls `clearScope()` to remove the published scope;\n * flipping from one store to another re-publishes the existing scope\n * with the new reference.\n *\n * The store-property publish is intentionally additive — it does not\n * replace the existing `BdActionResolveController` flow used by\n * `bd-context`, `bd-product`, and `bd-option`. Those controllers\n * capture their own transition for the action-request path; the store\n * scope is purely a value-publish surface.\n *\n * @example\n *\n * ```ts\n * const root = document.createElement('bd-context');\n * root.store = myStore;\n * // descendants under <bd-context> now see { store: myStore }\n * // via parentScope.store.\n *\n * // Clear the published scope\n * root.store = undefined;\n * ```\n *\n * The attribute mapping is intentionally omitted — Lit's default\n * converter cannot turn a string into a `Store` instance, and\n * serializing a store to an attribute would defeat the point of\n * holding it as a typed reference. Configure via JS instead, the\n * same way `derived` and `onScopeChange` are configured.\n */\n @property({\n attribute: false\n })\n store?: Store;\n\n /**\n * Publishes or clears the scope for a `store` property change.\n *\n * Single entry point for the three transitions `store` can drive:\n *\n * 1. `store` is `undefined` → `clearScope()` removes the published\n * scope and fires the `onScopeChange` hook with all-undefined\n * fields.\n * 2. `store` is defined and a scope is already published →\n * re-publishes the existing scope with the new store reference\n * (the rest of the scope — `derived`, `mutationBatchSchedule`,\n * `onScopeChange`, flags — is preserved).\n * 3. `store` is defined and no scope is published yet → publishes a\n * fresh `createBdStoreScope(this.store)` so the first descendant\n * read sees a non-undefined `parentScope.store`.\n *\n * Called from `willUpdate` whenever `changedProperties.has('store')`.\n * Idempotent: re-publishing the same scope reference is a no-op for\n * the `@provide` notification because `publishScope` already short-\n * circuits on `Object.is(this.providedScope, normalizedScope)`.\n */\n protected publishStoreScope(): void {\n if (this.store === undefined) {\n this.clearScope();\n\n return;\n }\n\n if (this.providedScope) {\n this.publishScope({\n ...this.providedScope,\n store: this.store\n });\n\n return;\n }\n\n this.publishScope(createBdStoreScope(this.store));\n }\n\n protected override willUpdate(\n changedProperties: PropertyValues<this>\n ): void {\n super.willUpdate(changedProperties);\n\n const overlayPropsChanged =\n changedProperties.has('computeDisabled') ||\n changedProperties.has('etaDisabled') ||\n changedProperties.has('derived') ||\n changedProperties.has('mutationBatchSchedule') ||\n changedProperties.has('onScopeChange') ||\n changedProperties.has('dataLayer');\n const storeChanged = changedProperties.has('store');\n\n if (changedProperties.has('ignoreEvents')) {\n this.#ignoredEventIds = undefined;\n }\n\n if (!overlayPropsChanged && !storeChanged) {\n return;\n }\n\n if (storeChanged) {\n this.publishStoreScope();\n }\n\n if (overlayPropsChanged && this.providedScope) {\n this.publishScope(this.providedScope);\n }\n }\n}\n\n/**\n * Parses the comma-separated `ignore-events` attribute into a set of ids.\n *\n * Empty entries are skipped so `\"foo, ,bar\"` produces `{ foo, bar }`.\n * The function is exported so test code can compare against the same\n * parsing rules the runtime uses.\n */\nexport function parseIgnoreEvents(\n value: string | undefined\n): ReadonlySet<string> {\n if (value === undefined || value === '') {\n return EMPTY_EVENT_IDS;\n }\n\n const ids = new Set<string>();\n\n for (const part of value.split(',')) {\n const trimmed = part.trim();\n\n if (trimmed !== '') {\n ids.add(trimmed);\n }\n }\n\n return ids.size === 0 ? EMPTY_EVENT_IDS : ids;\n}\n\nconst EMPTY_EVENT_IDS: ReadonlySet<string> = new Set<string>();\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { UpdateByDelta } from '../core/actions.js';
|
|
2
|
+
import type { Product } from '@repobit/dex-store';
|
|
3
|
+
/**
|
|
4
|
+
* Pure devices/subscription update semantics shared by the runtime OptionNode
|
|
5
|
+
* and the dry-run compute layer.
|
|
6
|
+
*
|
|
7
|
+
* Given a current numeric value and an UpdateByDelta command, this returns the
|
|
8
|
+
* next value. `next` / `prev` walk the product's declared dimension values, so
|
|
9
|
+
* sequential stepping respects what the product actually offers.
|
|
10
|
+
*/
|
|
11
|
+
export declare function applyOptionUpdate(field: UpdateByDelta['type'], currentValue: number | undefined, update: UpdateByDelta | undefined, product: Product | undefined): number | undefined;
|