@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.
Files changed (227) hide show
  1. package/CHANGELOG.md +5 -905
  2. package/README.md +9 -7
  3. package/dist/src/actions/action.adapter.d.ts +36 -0
  4. package/dist/src/actions/action.adapter.js +183 -0
  5. package/dist/src/actions/action.adapter.js.map +1 -0
  6. package/dist/src/actions/action.attributes.d.ts +15 -0
  7. package/dist/src/actions/action.attributes.js +137 -0
  8. package/dist/src/actions/action.attributes.js.map +1 -0
  9. package/dist/src/actions/action.registry.d.ts +4 -0
  10. package/dist/src/actions/action.registry.js +119 -0
  11. package/dist/src/actions/action.registry.js.map +1 -0
  12. package/dist/src/actions/index.d.ts +3 -2
  13. package/dist/src/actions/index.js +3 -80
  14. package/dist/src/actions/index.js.map +1 -1
  15. package/dist/src/compute/compute.expand.d.ts +70 -0
  16. package/dist/src/compute/compute.expand.js +319 -0
  17. package/dist/src/compute/compute.expand.js.map +1 -0
  18. package/dist/src/compute/compute.scan.d.ts +54 -0
  19. package/dist/src/compute/compute.scan.js +160 -0
  20. package/dist/src/compute/compute.scan.js.map +1 -0
  21. package/dist/src/compute/option-resolver.d.ts +31 -0
  22. package/dist/src/compute/option-resolver.js +147 -0
  23. package/dist/src/compute/option-resolver.js.map +1 -0
  24. package/dist/src/contexts/context.compute.d.ts +12 -0
  25. package/dist/src/contexts/context.compute.js +4 -0
  26. package/dist/src/contexts/context.compute.js.map +1 -0
  27. package/dist/src/contexts/context.scope.d.ts +139 -0
  28. package/dist/src/contexts/context.scope.js +48 -0
  29. package/dist/src/contexts/context.scope.js.map +1 -0
  30. package/dist/src/controllers/controller.action-resolve.d.ts +110 -0
  31. package/dist/src/controllers/controller.action-resolve.js +203 -0
  32. package/dist/src/controllers/controller.action-resolve.js.map +1 -0
  33. package/dist/src/controllers/controller.action-topology.d.ts +59 -0
  34. package/dist/src/controllers/controller.action-topology.js +130 -0
  35. package/dist/src/controllers/controller.action-topology.js.map +1 -0
  36. package/dist/src/controllers/controller.compute.d.ts +72 -0
  37. package/dist/src/controllers/controller.compute.js +110 -0
  38. package/dist/src/controllers/controller.compute.js.map +1 -0
  39. package/dist/src/controllers/controller.resolve.d.ts +78 -0
  40. package/dist/src/controllers/controller.resolve.js +205 -0
  41. package/dist/src/controllers/controller.resolve.js.map +1 -0
  42. package/dist/src/core/action-topology.d.ts +62 -0
  43. package/dist/src/core/action-topology.js +67 -0
  44. package/dist/src/core/action-topology.js.map +1 -0
  45. package/dist/src/core/actions.d.ts +64 -0
  46. package/dist/src/core/actions.js +47 -0
  47. package/dist/src/core/actions.js.map +1 -0
  48. package/dist/src/core/node.element.d.ts +179 -0
  49. package/dist/src/core/node.element.js +573 -0
  50. package/dist/src/core/node.element.js.map +1 -0
  51. package/dist/src/core/node.scope.d.ts +374 -0
  52. package/dist/src/core/node.scope.js +558 -0
  53. package/dist/src/core/node.scope.js.map +1 -0
  54. package/dist/src/core/option-update.d.ts +11 -0
  55. package/dist/src/core/option-update.js +59 -0
  56. package/dist/src/core/option-update.js.map +1 -0
  57. package/dist/src/dsl/compilers/array/compiler.js +13 -14
  58. package/dist/src/dsl/compilers/array/compiler.js.map +1 -1
  59. package/dist/src/dsl/compilers/boolean/compiler.d.ts +1 -1
  60. package/dist/src/dsl/compilers/boolean/compiler.js +14 -27
  61. package/dist/src/dsl/compilers/boolean/compiler.js.map +1 -1
  62. package/dist/src/dsl/compilers/enum/compiler.js +7 -10
  63. package/dist/src/dsl/compilers/enum/compiler.js.map +1 -1
  64. package/dist/src/dsl/compilers/index.d.ts +1 -1
  65. package/dist/src/dsl/compilers/index.js +5 -5
  66. package/dist/src/dsl/compilers/index.js.map +1 -1
  67. package/dist/src/dsl/utilty.d.ts +0 -4
  68. package/dist/src/dsl/utilty.js +3 -30
  69. package/dist/src/dsl/utilty.js.map +1 -1
  70. package/dist/src/eta/batch.d.ts +123 -0
  71. package/dist/src/eta/batch.js +162 -0
  72. package/dist/src/eta/batch.js.map +1 -0
  73. package/dist/src/eta/batcher.d.ts +184 -0
  74. package/dist/src/eta/batcher.js +335 -0
  75. package/dist/src/eta/batcher.js.map +1 -0
  76. package/dist/src/eta/cache.d.ts +36 -0
  77. package/dist/src/eta/cache.js +56 -0
  78. package/dist/src/eta/cache.js.map +1 -0
  79. package/dist/src/eta/controller.d.ts +608 -0
  80. package/dist/src/eta/controller.js +1036 -0
  81. package/dist/src/eta/controller.js.map +1 -0
  82. package/dist/src/eta/factory.d.ts +74 -0
  83. package/dist/src/eta/factory.js +121 -0
  84. package/dist/src/eta/factory.js.map +1 -0
  85. package/dist/src/eta/idle.d.ts +39 -0
  86. package/dist/src/eta/idle.js +52 -0
  87. package/dist/src/eta/idle.js.map +1 -0
  88. package/dist/src/eta/index.d.ts +52 -0
  89. package/dist/src/eta/index.js +13 -0
  90. package/dist/src/eta/index.js.map +1 -0
  91. package/dist/src/eta/observer.d.ts +263 -0
  92. package/dist/src/eta/observer.js +263 -0
  93. package/dist/src/eta/observer.js.map +1 -0
  94. package/dist/src/eta/operations.d.ts +41 -0
  95. package/dist/src/eta/operations.js +59 -0
  96. package/dist/src/eta/operations.js.map +1 -0
  97. package/dist/src/eta/source-registry.d.ts +198 -0
  98. package/dist/src/eta/source-registry.js +267 -0
  99. package/dist/src/eta/source-registry.js.map +1 -0
  100. package/dist/src/eta/template-index.d.ts +285 -0
  101. package/dist/src/eta/template-index.js +642 -0
  102. package/dist/src/eta/template-index.js.map +1 -0
  103. package/dist/src/eta/types.d.ts +529 -0
  104. package/dist/src/eta/types.js +2 -0
  105. package/dist/src/eta/types.js.map +1 -0
  106. package/dist/src/index.d.ts +21 -9
  107. package/dist/src/index.js +22 -11
  108. package/dist/src/index.js.map +1 -1
  109. package/dist/src/nodes/node.context.d.ts +5 -3
  110. package/dist/src/nodes/node.context.js +48 -3
  111. package/dist/src/nodes/node.context.js.map +1 -1
  112. package/dist/src/nodes/node.option.d.ts +11 -31
  113. package/dist/src/nodes/node.option.js +158 -222
  114. package/dist/src/nodes/node.option.js.map +1 -1
  115. package/dist/src/nodes/node.product.d.ts +7 -11
  116. package/dist/src/nodes/node.product.js +85 -64
  117. package/dist/src/nodes/node.product.js.map +1 -1
  118. package/dist/src/renders/attributes/buyLink.d.ts +2 -2
  119. package/dist/src/renders/attributes/buyLink.js +14 -11
  120. package/dist/src/renders/attributes/buyLink.js.map +1 -1
  121. package/dist/src/renders/attributes/devices.d.ts +2 -2
  122. package/dist/src/renders/attributes/devices.js +9 -19
  123. package/dist/src/renders/attributes/devices.js.map +1 -1
  124. package/dist/src/renders/attributes/discount.d.ts +2 -2
  125. package/dist/src/renders/attributes/discount.js +56 -44
  126. package/dist/src/renders/attributes/discount.js.map +1 -1
  127. package/dist/src/renders/attributes/hide.d.ts +2 -2
  128. package/dist/src/renders/attributes/hide.js +49 -14
  129. package/dist/src/renders/attributes/hide.js.map +1 -1
  130. package/dist/src/renders/attributes/index.d.ts +3 -3
  131. package/dist/src/renders/attributes/index.js +2 -4
  132. package/dist/src/renders/attributes/index.js.map +1 -1
  133. package/dist/src/renders/attributes/price.d.ts +2 -2
  134. package/dist/src/renders/attributes/price.js +30 -44
  135. package/dist/src/renders/attributes/price.js.map +1 -1
  136. package/dist/src/renders/attributes/subscription.d.ts +2 -2
  137. package/dist/src/renders/attributes/subscription.js +14 -20
  138. package/dist/src/renders/attributes/subscription.js.map +1 -1
  139. package/dist/src/renders/attributes/utilty.d.ts +2 -0
  140. package/dist/src/renders/attributes/utilty.js +17 -4
  141. package/dist/src/renders/attributes/utilty.js.map +1 -1
  142. package/dist/src/renders/context.d.ts +122 -10
  143. package/dist/src/renders/context.js +140 -80
  144. package/dist/src/renders/context.js.map +1 -1
  145. package/dist/src/renders/format.js +2 -2
  146. package/dist/src/renders/format.js.map +1 -1
  147. package/dist/src/renders/index.d.ts +6 -2
  148. package/dist/src/renders/index.js +67 -29
  149. package/dist/src/renders/index.js.map +1 -1
  150. package/dist/src/renders/observe.d.ts +1 -4
  151. package/dist/src/renders/observe.js +10 -24
  152. package/dist/src/renders/observe.js.map +1 -1
  153. package/dist/src/renders/render.wrapper.d.ts +37 -0
  154. package/dist/src/renders/render.wrapper.js +147 -0
  155. package/dist/src/renders/render.wrapper.js.map +1 -0
  156. package/dist/src/templating/eta.js +1 -4
  157. package/dist/src/templating/eta.js.map +1 -1
  158. package/package.json +4 -5
  159. package/dist/src/actions/action.button.d.ts +0 -2
  160. package/dist/src/actions/action.button.js +0 -8
  161. package/dist/src/actions/action.button.js.map +0 -1
  162. package/dist/src/actions/action.input.d.ts +0 -2
  163. package/dist/src/actions/action.input.js +0 -43
  164. package/dist/src/actions/action.input.js.map +0 -1
  165. package/dist/src/actions/action.select.d.ts +0 -2
  166. package/dist/src/actions/action.select.js +0 -14
  167. package/dist/src/actions/action.select.js.map +0 -1
  168. package/dist/src/actions/utilty.d.ts +0 -16
  169. package/dist/src/actions/utilty.js +0 -149
  170. package/dist/src/actions/utilty.js.map +0 -1
  171. package/dist/src/contexts/context.datalayer.d.ts +0 -9
  172. package/dist/src/contexts/context.datalayer.js +0 -3
  173. package/dist/src/contexts/context.datalayer.js.map +0 -1
  174. package/dist/src/contexts/context.derived.d.ts +0 -12
  175. package/dist/src/contexts/context.derived.js +0 -3
  176. package/dist/src/contexts/context.derived.js.map +0 -1
  177. package/dist/src/contexts/context.option.d.ts +0 -5
  178. package/dist/src/contexts/context.option.js +0 -3
  179. package/dist/src/contexts/context.option.js.map +0 -1
  180. package/dist/src/contexts/context.product.d.ts +0 -5
  181. package/dist/src/contexts/context.product.js +0 -3
  182. package/dist/src/contexts/context.product.js.map +0 -1
  183. package/dist/src/contexts/context.state.d.ts +0 -28
  184. package/dist/src/contexts/context.state.js +0 -3
  185. package/dist/src/contexts/context.state.js.map +0 -1
  186. package/dist/src/contexts/context.store.d.ts +0 -5
  187. package/dist/src/contexts/context.store.js +0 -3
  188. package/dist/src/contexts/context.store.js.map +0 -1
  189. package/dist/src/controllers/collect-controller.d.ts +0 -39
  190. package/dist/src/controllers/collect-controller.js +0 -161
  191. package/dist/src/controllers/collect-controller.js.map +0 -1
  192. package/dist/src/controllers/compute-controller.d.ts +0 -55
  193. package/dist/src/controllers/compute-controller.js +0 -350
  194. package/dist/src/controllers/compute-controller.js.map +0 -1
  195. package/dist/src/controllers/eta-renderer/eta-dom-renderer.d.ts +0 -25
  196. package/dist/src/controllers/eta-renderer/eta-dom-renderer.js +0 -192
  197. package/dist/src/controllers/eta-renderer/eta-dom-renderer.js.map +0 -1
  198. package/dist/src/controllers/eta-renderer/eta-mutation-observer.d.ts +0 -28
  199. package/dist/src/controllers/eta-renderer/eta-mutation-observer.js +0 -206
  200. package/dist/src/controllers/eta-renderer/eta-mutation-observer.js.map +0 -1
  201. package/dist/src/controllers/eta-renderer/eta-renderer.d.ts +0 -21
  202. package/dist/src/controllers/eta-renderer/eta-renderer.js +0 -77
  203. package/dist/src/controllers/eta-renderer/eta-renderer.js.map +0 -1
  204. package/dist/src/controllers/eta-renderer/eta-template-cache.d.ts +0 -24
  205. package/dist/src/controllers/eta-renderer/eta-template-cache.js +0 -61
  206. package/dist/src/controllers/eta-renderer/eta-template-cache.js.map +0 -1
  207. package/dist/src/controllers/eta-renderer/eta-types.d.ts +0 -11
  208. package/dist/src/controllers/eta-renderer/eta-types.js +0 -1
  209. package/dist/src/controllers/eta-renderer/eta-types.js.map +0 -1
  210. package/dist/src/controllers/eta-renderer/index.d.ts +0 -2
  211. package/dist/src/controllers/eta-renderer/index.js +0 -2
  212. package/dist/src/controllers/eta-renderer/index.js.map +0 -1
  213. package/dist/src/controllers/event-pipeline-controller.d.ts +0 -28
  214. package/dist/src/controllers/event-pipeline-controller.js +0 -72
  215. package/dist/src/controllers/event-pipeline-controller.js.map +0 -1
  216. package/dist/src/events/events.d.ts +0 -75
  217. package/dist/src/events/events.js +0 -78
  218. package/dist/src/events/events.js.map +0 -1
  219. package/dist/src/nodes/node.root.d.ts +0 -16
  220. package/dist/src/nodes/node.root.js +0 -49
  221. package/dist/src/nodes/node.root.js.map +0 -1
  222. package/dist/src/nodes/node.state.d.ts +0 -88
  223. package/dist/src/nodes/node.state.js +0 -330
  224. package/dist/src/nodes/node.state.js.map +0 -1
  225. package/dist/src/renders/utility.d.ts +0 -32
  226. package/dist/src/renders/utility.js +0 -191
  227. package/dist/src/renders/utility.js.map +0 -1
package/README.md CHANGED
@@ -88,7 +88,7 @@ Peer dependencies are resolved automatically by npm; no extra install command is
88
88
  ```
89
89
 
90
90
  **Store Config**
91
- - `trialLinks` and `overrides` come from `@repobit/dex-store` and work transparently with these elements. You pass them when creating the `Store` and render trial links via `data-store-buy-link="30 days"` (trial duration as the attribute value) or rely on overridden option fields.
91
+ - `trialLinks` and `overrides` come from `@repobit/dex-store` and work transparently with these elements. You pass them when creating the `Store` and render them via attributes like `data-store-trial-link` or by relying on overridden option fields.
92
92
 
93
93
  Example advanced config when constructing the store:
94
94
 
@@ -105,12 +105,12 @@ const store = new Store({
105
105
  trialLinks: {
106
106
  'com.bitdefender.tsmd.v2': {
107
107
  default: {
108
- '5-12' : { '30 days': 'https://trial.example.com/default/5-12' },
109
- '10-12': { '30 days': 'https://trial.example.com/default/10-12' }
108
+ '5-12' : 'https://trial.example.com/default/5-12',
109
+ '10-12': 'https://trial.example.com/default/10-12'
110
110
  },
111
111
  PromoX: {
112
- '5-12' : { '30 days': 'https://trial.example.com/promox/5-12' },
113
- '10-12': { '30 days': 'https://trial.example.com/promox/10-12' }
112
+ '5-12' : 'https://trial.example.com/promox/5-12',
113
+ '10-12': 'https://trial.example.com/promox/10-12'
114
114
  }
115
115
  }
116
116
  },
@@ -137,8 +137,9 @@ const store = new Store({
137
137
  ```
138
138
 
139
139
  Notes
140
+ - `data-store-trial-link` uses `trialLinks` to set the anchor `href`. If no mapping exists, the attribute is left untouched.
140
141
  - `overrides.options` merges into each option; you can update `buyLink`, `discountedPrice`, etc., or delete an entire variation with `null`.
141
- - Keys are resolved against the product alias returned by the provider. If you don't use id mappings, it's the id you pass in `<bd-product product-id="...">`.
142
+ - Keys are resolved against the product id returned by the provider (after adaptor mapping). If you dont use mappings, its the id you pass in `<bd-product product-id="...">`.
142
143
 
143
144
  ## Rendering model
144
145
  - Add `data-store-render` to any element you want updated by the pipeline.
@@ -169,7 +170,8 @@ Notes
169
170
  - `data-store-context-discount` tokens: `min-value`, `max-value`, `min-value-monthly`, `max-value-monthly`, `min-percentage`, `max-percentage`, `min-percentage-monthly`, `max-percentage-monthly`
170
171
 
171
172
  - Links
172
- - `data-store-buy-link` sets anchor `href` and useful `data-*` attributes. Accepts an optional trial-duration value (e.g. `data-store-buy-link="30 days"`): when provided, the trial link for that duration is used if one is configured for the current variation, otherwise falls back to the regular buy link.
173
+ - `data-store-buy-link` sets anchor `href` and useful `data-*` attributes
174
+ - `data-store-trial-link` sets anchor `href` to the trial link (if configured in `@repobit/dex-store` store config)
173
175
 
174
176
  - Hide DSL
175
177
  - `data-store-hide="<boolean expression>"` with an optional `data-store-hide-type="display|opacity|visibility"`
@@ -0,0 +1,36 @@
1
+ export declare class BdActionElementAdapter {
2
+ readonly element: HTMLElement;
3
+ readonly updateComplete: Promise<boolean>;
4
+ private readonly _listenerDisposers;
5
+ private _scan;
6
+ private _observer?;
7
+ private _connected;
8
+ /**
9
+ * The nearest bd node that claimed this element on connect.
10
+ *
11
+ * Retained so the disconnect can be announced directly to the owner even
12
+ * after the element is detached from the DOM. A bubbling event dispatched on
13
+ * a detached element would never reach the still-connected owner node.
14
+ */
15
+ private _owner?;
16
+ constructor(element: HTMLElement);
17
+ get isConnected(): boolean;
18
+ connectedCallback(): void;
19
+ disconnectedCallback(): void;
20
+ connect(): void;
21
+ disconnect(): void;
22
+ private _announceConnect;
23
+ private _announceDisconnect;
24
+ private _announceUpdate;
25
+ dispatchAction(): boolean;
26
+ private _connectElementBehavior;
27
+ private _connectInputElement;
28
+ private _connectSelectElement;
29
+ private _dispatchInputValueAction;
30
+ private _dispatchSelectAction;
31
+ private _addEventListener;
32
+ private _clearListeners;
33
+ private _connectElementObserver;
34
+ private _disconnectElementObserver;
35
+ private _refreshScan;
36
+ }
@@ -0,0 +1,183 @@
1
+ import { collectActionElementCompute, EMPTY_COMPUTE_SCAN } from '../compute/compute.scan.js';
2
+ import { dispatchBdActionConnect, dispatchBdActionDisconnect, dispatchBdActionUpdate } from '../core/action-topology.js';
3
+ import { dispatchBdActionRequest } from '../core/actions.js';
4
+ import { readBdActionCommand, readInputValueCommand } from './action.attributes.js';
5
+ const ACTION_ADAPTER_OBSERVED_ATTRIBUTES = [
6
+ 'data-store-action',
7
+ 'data-store-devices',
8
+ 'data-store-set-bundle',
9
+ 'data-store-set-campaign',
10
+ 'data-store-set-delta',
11
+ 'data-store-set-devices',
12
+ 'data-store-set-id',
13
+ 'data-store-set-max',
14
+ 'data-store-set-min',
15
+ 'data-store-set-subscription',
16
+ 'data-store-set-type',
17
+ 'data-store-set-use-as-value',
18
+ 'data-store-subscription',
19
+ 'max',
20
+ 'min',
21
+ 'type',
22
+ 'value'
23
+ ];
24
+ export class BdActionElementAdapter {
25
+ constructor(element) {
26
+ this.updateComplete = Promise.resolve(true);
27
+ this._listenerDisposers = new Set();
28
+ this._scan = EMPTY_COMPUTE_SCAN;
29
+ this._connected = false;
30
+ this.element = element;
31
+ }
32
+ get isConnected() {
33
+ return this._connected && this.element.isConnected;
34
+ }
35
+ connectedCallback() {
36
+ if (this._connected) {
37
+ return;
38
+ }
39
+ this._connected = true;
40
+ this._scan = collectActionElementCompute(this.element);
41
+ this._connectElementBehavior();
42
+ this._connectElementObserver();
43
+ }
44
+ disconnectedCallback() {
45
+ if (!this._connected) {
46
+ return;
47
+ }
48
+ this._connected = false;
49
+ this._clearListeners();
50
+ this._disconnectElementObserver();
51
+ }
52
+ connect() {
53
+ if (this._connected) {
54
+ return;
55
+ }
56
+ this.connectedCallback();
57
+ this._announceConnect();
58
+ }
59
+ disconnect() {
60
+ if (!this._connected) {
61
+ return;
62
+ }
63
+ this._announceDisconnect();
64
+ this.disconnectedCallback();
65
+ }
66
+ _announceConnect() {
67
+ dispatchBdActionConnect(this.element, this._scan, (owner) => {
68
+ this._owner = owner;
69
+ });
70
+ }
71
+ _announceDisconnect() {
72
+ dispatchBdActionDisconnect(this._owner ?? this.element, this.element);
73
+ this._owner = undefined;
74
+ }
75
+ _announceUpdate() {
76
+ if (!this._owner) {
77
+ return;
78
+ }
79
+ dispatchBdActionUpdate(this._owner, this.element, this._scan);
80
+ }
81
+ dispatchAction() {
82
+ const command = readBdActionCommand(this.element);
83
+ if (!command) {
84
+ return false;
85
+ }
86
+ return dispatchBdActionRequest(this.element, { command });
87
+ }
88
+ _connectElementBehavior() {
89
+ if (this.element instanceof HTMLInputElement) {
90
+ this._connectInputElement(this.element);
91
+ return;
92
+ }
93
+ if (this.element instanceof HTMLSelectElement) {
94
+ this._connectSelectElement(this.element);
95
+ return;
96
+ }
97
+ this._addEventListener(this.element, 'click', () => this.dispatchAction());
98
+ }
99
+ _connectInputElement(input) {
100
+ switch (input.type) {
101
+ case 'checkbox':
102
+ case 'radio':
103
+ if (input.checked) {
104
+ this.dispatchAction();
105
+ }
106
+ this._addEventListener(input, 'click', () => {
107
+ if (input.checked) {
108
+ this.dispatchAction();
109
+ }
110
+ });
111
+ break;
112
+ case 'number':
113
+ case 'text':
114
+ this._addEventListener(input, 'change', () => this._dispatchInputValueAction(input));
115
+ break;
116
+ default:
117
+ this._addEventListener(input, 'change', () => this.dispatchAction());
118
+ break;
119
+ }
120
+ }
121
+ _connectSelectElement(select) {
122
+ this._addEventListener(select, 'change', () => this._dispatchSelectAction(select));
123
+ }
124
+ _dispatchInputValueAction(input) {
125
+ const command = readInputValueCommand(input);
126
+ if (!command) {
127
+ return false;
128
+ }
129
+ return dispatchBdActionRequest(input, { command });
130
+ }
131
+ _dispatchSelectAction(select) {
132
+ const selected = select.selectedOptions[0];
133
+ const command = selected
134
+ ? readBdActionCommand(selected)
135
+ : readBdActionCommand(select);
136
+ if (!command ||
137
+ command.kind === 'update-by-delta') {
138
+ return false;
139
+ }
140
+ return dispatchBdActionRequest(select, { command });
141
+ }
142
+ _addEventListener(target, type, listener) {
143
+ target.addEventListener(type, listener);
144
+ this._listenerDisposers.add(() => {
145
+ target.removeEventListener(type, listener);
146
+ });
147
+ }
148
+ _clearListeners() {
149
+ for (const dispose of this._listenerDisposers) {
150
+ dispose();
151
+ }
152
+ this._listenerDisposers.clear();
153
+ }
154
+ _connectElementObserver() {
155
+ if (typeof MutationObserver === 'undefined') {
156
+ return;
157
+ }
158
+ this._observer = new MutationObserver(() => {
159
+ this._refreshScan();
160
+ });
161
+ this._observer.observe(this.element, {
162
+ attributeFilter: [...ACTION_ADAPTER_OBSERVED_ATTRIBUTES],
163
+ attributes: true
164
+ });
165
+ }
166
+ _disconnectElementObserver() {
167
+ this._observer?.disconnect();
168
+ this._observer = undefined;
169
+ }
170
+ _refreshScan() {
171
+ const scan = collectActionElementCompute(this.element);
172
+ if (sameComputeScan(this._scan, scan)) {
173
+ return;
174
+ }
175
+ this._scan = scan;
176
+ this._announceUpdate();
177
+ }
178
+ }
179
+ function sameComputeScan(a, b) {
180
+ return (JSON.stringify(a.staticCommands) === JSON.stringify(b.staticCommands) &&
181
+ JSON.stringify(a.domains) === JSON.stringify(b.domains));
182
+ }
183
+ //# sourceMappingURL=action.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.adapter.js","sourceRoot":"","sources":["../../../src/actions/action.adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n collectActionElementCompute,\n EMPTY_COMPUTE_SCAN,\n type BdComputeScan\n} from '@/compute/compute.scan.js';\nimport {\n dispatchBdActionConnect,\n dispatchBdActionDisconnect,\n dispatchBdActionUpdate\n} from '@/core/action-topology.js';\nimport { dispatchBdActionRequest } from '@/core/actions.js';\nimport {\n readBdActionCommand,\n readInputValueCommand\n} from './action.attributes.js';\n\nconst ACTION_ADAPTER_OBSERVED_ATTRIBUTES = [\n 'data-store-action',\n 'data-store-devices',\n 'data-store-set-bundle',\n 'data-store-set-campaign',\n 'data-store-set-delta',\n 'data-store-set-devices',\n 'data-store-set-id',\n 'data-store-set-max',\n 'data-store-set-min',\n 'data-store-set-subscription',\n 'data-store-set-type',\n 'data-store-set-use-as-value',\n 'data-store-subscription',\n 'max',\n 'min',\n 'type',\n 'value'\n] as const;\n\nexport class BdActionElementAdapter {\n readonly element : HTMLElement;\n readonly updateComplete: Promise<boolean> = Promise.resolve(true);\n\n private readonly _listenerDisposers = new Set<() => void>();\n private _scan : BdComputeScan = EMPTY_COMPUTE_SCAN;\n private _observer?: MutationObserver;\n private _connected = false;\n\n /**\n * The nearest bd node that claimed this element on connect.\n *\n * Retained so the disconnect can be announced directly to the owner even\n * after the element is detached from the DOM. A bubbling event dispatched on\n * a detached element would never reach the still-connected owner node.\n */\n private _owner?: EventTarget;\n\n constructor(\n element: HTMLElement\n ) {\n this.element = element;\n }\n\n get isConnected(): boolean {\n return this._connected && this.element.isConnected;\n }\n\n connectedCallback(): void {\n if (this._connected) {\n return;\n }\n\n this._connected = true;\n this._scan = collectActionElementCompute(this.element);\n this._connectElementBehavior();\n this._connectElementObserver();\n }\n\n disconnectedCallback(): void {\n if (!this._connected) {\n return;\n }\n\n this._connected = false;\n this._clearListeners();\n this._disconnectElementObserver();\n }\n\n connect(): void {\n if (this._connected) {\n return;\n }\n\n this.connectedCallback();\n this._announceConnect();\n }\n\n disconnect(): void {\n if (!this._connected) {\n return;\n }\n\n this._announceDisconnect();\n this.disconnectedCallback();\n }\n\n private _announceConnect(): void {\n dispatchBdActionConnect(\n this.element,\n this._scan,\n (owner) => {\n this._owner = owner;\n }\n );\n }\n\n private _announceDisconnect(): void {\n dispatchBdActionDisconnect(\n this._owner ?? this.element,\n this.element\n );\n\n this._owner = undefined;\n }\n\n private _announceUpdate(): void {\n if (!this._owner) {\n return;\n }\n\n dispatchBdActionUpdate(\n this._owner,\n this.element,\n this._scan\n );\n }\n\n dispatchAction(): boolean {\n const command = readBdActionCommand(this.element);\n\n if (!command) {\n return false;\n }\n\n return dispatchBdActionRequest(\n this.element,\n { command }\n );\n }\n\n private _connectElementBehavior(): void {\n if (this.element instanceof HTMLInputElement) {\n this._connectInputElement(this.element);\n return;\n }\n\n if (this.element instanceof HTMLSelectElement) {\n this._connectSelectElement(this.element);\n return;\n }\n\n this._addEventListener(\n this.element,\n 'click',\n () => this.dispatchAction()\n );\n }\n\n private _connectInputElement(\n input: HTMLInputElement\n ): void {\n switch (input.type) {\n case 'checkbox':\n case 'radio':\n if (input.checked) {\n this.dispatchAction();\n }\n\n this._addEventListener(\n input,\n 'click',\n () => {\n if (input.checked) {\n this.dispatchAction();\n }\n }\n );\n break;\n\n case 'number':\n case 'text':\n this._addEventListener(\n input,\n 'change',\n () => this._dispatchInputValueAction(input)\n );\n break;\n\n default:\n this._addEventListener(\n input,\n 'change',\n () => this.dispatchAction()\n );\n break;\n }\n }\n\n private _connectSelectElement(\n select: HTMLSelectElement\n ): void {\n this._addEventListener(\n select,\n 'change',\n () => this._dispatchSelectAction(select)\n );\n }\n\n private _dispatchInputValueAction(\n input: HTMLInputElement\n ): boolean {\n const command = readInputValueCommand(input);\n\n if (!command) {\n return false;\n }\n\n return dispatchBdActionRequest(\n input,\n { command }\n );\n }\n\n private _dispatchSelectAction(\n select: HTMLSelectElement\n ): boolean {\n const selected = select.selectedOptions[0];\n const command = selected\n ? readBdActionCommand(selected)\n : readBdActionCommand(select);\n\n if (\n !command ||\n command.kind === 'update-by-delta'\n ) {\n return false;\n }\n\n return dispatchBdActionRequest(\n select,\n { command }\n );\n }\n\n private _addEventListener<K extends keyof HTMLElementEventMap>(\n target: HTMLElement,\n type: K,\n listener: (event: HTMLElementEventMap[K]) => void\n ): void {\n target.addEventListener(\n type,\n listener as EventListener\n );\n\n this._listenerDisposers.add(() => {\n target.removeEventListener(\n type,\n listener as EventListener\n );\n });\n }\n\n private _clearListeners(): void {\n for (const dispose of this._listenerDisposers) {\n dispose();\n }\n\n this._listenerDisposers.clear();\n }\n\n private _connectElementObserver(): void {\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n this._observer = new MutationObserver(() => {\n this._refreshScan();\n });\n\n this._observer.observe(\n this.element,\n {\n attributeFilter: [...ACTION_ADAPTER_OBSERVED_ATTRIBUTES],\n attributes : true\n }\n );\n }\n\n private _disconnectElementObserver(): void {\n this._observer?.disconnect();\n this._observer = undefined;\n }\n\n private _refreshScan(): void {\n const scan = collectActionElementCompute(this.element);\n\n if (sameComputeScan(\n this._scan,\n scan\n )) {\n return;\n }\n\n this._scan = scan;\n this._announceUpdate();\n }\n}\n\nfunction sameComputeScan(\n a: BdComputeScan,\n b: BdComputeScan\n): boolean {\n return (\n JSON.stringify(a.staticCommands) === JSON.stringify(b.staticCommands) &&\n JSON.stringify(a.domains) === JSON.stringify(b.domains)\n );\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import type { BdActionCommand } from '../core/actions.js';
2
+ export declare const DATA_ACTION_NODE: "[data-store-action]";
3
+ export declare const DATA_EVENT_ID_ATTR = "data-store-event-id";
4
+ /**
5
+ * Reads the optional `data-store-event-id` attribute from an element.
6
+ *
7
+ * The value pairs with the `ignore-events` attribute on `bd-*` provider
8
+ * elements, so a node can opt out of reacting to events whose source
9
+ * element carries this id. Returns `undefined` when the attribute is
10
+ * absent.
11
+ */
12
+ export declare function readEventId(element: HTMLElement): string | undefined;
13
+ export declare function isActionElement(element: HTMLElement): boolean;
14
+ export declare function readBdActionCommand(element: HTMLElement): BdActionCommand | undefined;
15
+ export declare function readInputValueCommand(input: HTMLInputElement): BdActionCommand | undefined;
@@ -0,0 +1,137 @@
1
+ export const DATA_ACTION_NODE = '[data-store-action]';
2
+ export const DATA_EVENT_ID_ATTR = 'data-store-event-id';
3
+ /**
4
+ * Reads the optional `data-store-event-id` attribute from an element.
5
+ *
6
+ * The value pairs with the `ignore-events` attribute on `bd-*` provider
7
+ * elements, so a node can opt out of reacting to events whose source
8
+ * element carries this id. Returns `undefined` when the attribute is
9
+ * absent.
10
+ */
11
+ export function readEventId(element) {
12
+ const value = element.dataset.storeEventId;
13
+ if (value === undefined || value === '') {
14
+ return undefined;
15
+ }
16
+ return value;
17
+ }
18
+ export function isActionElement(element) {
19
+ return element.matches(DATA_ACTION_NODE);
20
+ }
21
+ export function readBdActionCommand(element) {
22
+ const dataset = element.dataset;
23
+ if ('storeSetType' in dataset) {
24
+ const update = readUpdateByDelta(element);
25
+ if (!update) {
26
+ return undefined;
27
+ }
28
+ return {
29
+ kind: 'update-by-delta',
30
+ update
31
+ };
32
+ }
33
+ if (!isActionElement(element) &&
34
+ !hasSetActionData(dataset)) {
35
+ return undefined;
36
+ }
37
+ return {
38
+ kind: 'set-action',
39
+ action: readSetAction(element)
40
+ };
41
+ }
42
+ export function readInputValueCommand(input) {
43
+ const command = readBdActionCommand(input);
44
+ if (command?.kind !== 'update-by-delta') {
45
+ return command;
46
+ }
47
+ const delta = toOptionalNumber(input.value);
48
+ if (delta === undefined) {
49
+ return undefined;
50
+ }
51
+ return {
52
+ kind: 'update-by-delta',
53
+ update: {
54
+ ...command.update,
55
+ delta,
56
+ min: toOptionalNumber(input.min) ?? command.update.min,
57
+ max: toOptionalNumber(input.max) ?? command.update.max,
58
+ useAsValue: true
59
+ }
60
+ };
61
+ }
62
+ function readUpdateByDelta(element) {
63
+ const dataset = element.dataset;
64
+ const type = dataset.storeSetType;
65
+ if (type !== 'devices' &&
66
+ type !== 'subscription') {
67
+ return undefined;
68
+ }
69
+ const delta = readDelta(dataset.storeSetDelta);
70
+ if (delta === undefined) {
71
+ return undefined;
72
+ }
73
+ return {
74
+ type,
75
+ delta,
76
+ min: toOptionalNumber(dataset.storeSetMin),
77
+ max: toOptionalNumber(dataset.storeSetMax),
78
+ useAsValue: readBooleanAttribute(dataset, 'storeSetUseAsValue'),
79
+ eventId: readEventId(element)
80
+ };
81
+ }
82
+ function readSetAction(element) {
83
+ const dataset = element.dataset;
84
+ return {
85
+ id: dataset.storeSetId,
86
+ campaign: dataset.storeSetCampaign,
87
+ bundle: readBooleanAttribute(dataset, 'storeSetBundle'),
88
+ devices: toOptionDimension(dataset.storeSetDevices),
89
+ subscription: toOptionDimension(dataset.storeSetSubscription),
90
+ eventId: readEventId(element)
91
+ };
92
+ }
93
+ function hasSetActionData(dataset) {
94
+ return ('storeSetId' in dataset ||
95
+ 'storeSetCampaign' in dataset ||
96
+ 'storeSetBundle' in dataset ||
97
+ 'storeSetDevices' in dataset ||
98
+ 'storeSetSubscription' in dataset);
99
+ }
100
+ function readDelta(value) {
101
+ if (value === 'next' ||
102
+ value === 'prev') {
103
+ return value;
104
+ }
105
+ return toOptionalNumber(value);
106
+ }
107
+ function readBooleanAttribute(dataset, key) {
108
+ if (!(key in dataset)) {
109
+ return false;
110
+ }
111
+ const value = dataset[key];
112
+ return value === '' || value === 'true';
113
+ }
114
+ function toOptionalNumber(value) {
115
+ if (value === undefined) {
116
+ return undefined;
117
+ }
118
+ const trimmed = value.trim();
119
+ if (!trimmed) {
120
+ return undefined;
121
+ }
122
+ const parsed = Number(trimmed);
123
+ return Number.isNaN(parsed)
124
+ ? undefined
125
+ : parsed;
126
+ }
127
+ function toOptionDimension(value) {
128
+ const parsed = toOptionalNumber(value);
129
+ if (parsed === undefined ||
130
+ !Number.isFinite(parsed) ||
131
+ parsed < 0 ||
132
+ !Number.isInteger(parsed)) {
133
+ return undefined;
134
+ }
135
+ return parsed;
136
+ }
137
+ //# sourceMappingURL=action.attributes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.attributes.js","sourceRoot":"","sources":["../../../src/actions/action.attributes.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n Action,\n BdActionCommand,\n UpdateByDelta\n} from '@/core/actions.js';\n\nexport const DATA_ACTION_NODE = '[data-store-action]' as const;\nexport const DATA_EVENT_ID_ATTR = 'data-store-event-id';\n\n/**\n * Reads the optional `data-store-event-id` attribute from an element.\n *\n * The value pairs with the `ignore-events` attribute on `bd-*` provider\n * elements, so a node can opt out of reacting to events whose source\n * element carries this id. Returns `undefined` when the attribute is\n * absent.\n */\nexport function readEventId(\n element: HTMLElement\n): string | undefined {\n const value = element.dataset.storeEventId;\n\n if (value === undefined || value === '') {\n return undefined;\n }\n\n return value;\n}\n\nexport function isActionElement(\n element: HTMLElement\n): boolean {\n return element.matches(DATA_ACTION_NODE);\n}\n\nexport function readBdActionCommand(\n element: HTMLElement\n): BdActionCommand | undefined {\n const dataset = element.dataset;\n\n if ('storeSetType' in dataset) {\n const update = readUpdateByDelta(element);\n\n if (!update) {\n return undefined;\n }\n\n return {\n kind: 'update-by-delta',\n update\n };\n }\n\n if (\n !isActionElement(element) &&\n !hasSetActionData(dataset)\n ) {\n return undefined;\n }\n\n return {\n kind : 'set-action',\n action: readSetAction(element)\n };\n}\n\nexport function readInputValueCommand(\n input: HTMLInputElement\n): BdActionCommand | undefined {\n const command = readBdActionCommand(input);\n\n if (command?.kind !== 'update-by-delta') {\n return command;\n }\n\n const delta = toOptionalNumber(input.value);\n\n if (delta === undefined) {\n return undefined;\n }\n\n return {\n kind : 'update-by-delta',\n update: {\n ...command.update,\n delta,\n min : toOptionalNumber(input.min) ?? command.update.min,\n max : toOptionalNumber(input.max) ?? command.update.max,\n useAsValue: true\n }\n };\n}\n\nfunction readUpdateByDelta(\n element: HTMLElement\n): UpdateByDelta | undefined {\n const dataset = element.dataset;\n const type = dataset.storeSetType;\n\n if (\n type !== 'devices' &&\n type !== 'subscription'\n ) {\n return undefined;\n }\n\n const delta = readDelta(dataset.storeSetDelta);\n\n if (delta === undefined) {\n return undefined;\n }\n\n return {\n type,\n delta,\n min : toOptionalNumber(dataset.storeSetMin),\n max : toOptionalNumber(dataset.storeSetMax),\n useAsValue: readBooleanAttribute(\n dataset,\n 'storeSetUseAsValue'\n ),\n eventId: readEventId(element)\n };\n}\n\nfunction readSetAction(\n element: HTMLElement\n): Action {\n const dataset = element.dataset;\n\n return {\n id : dataset.storeSetId,\n campaign: dataset.storeSetCampaign,\n bundle : readBooleanAttribute(\n dataset,\n 'storeSetBundle'\n ),\n devices : toOptionDimension(dataset.storeSetDevices),\n subscription: toOptionDimension(dataset.storeSetSubscription),\n eventId : readEventId(element)\n };\n}\n\nfunction hasSetActionData(\n dataset: DOMStringMap\n): boolean {\n return (\n 'storeSetId' in dataset ||\n 'storeSetCampaign' in dataset ||\n 'storeSetBundle' in dataset ||\n 'storeSetDevices' in dataset ||\n 'storeSetSubscription' in dataset\n );\n}\n\nfunction readDelta(\n value: string | undefined\n): UpdateByDelta['delta'] | undefined {\n if (\n value === 'next' ||\n value === 'prev'\n ) {\n return value;\n }\n\n return toOptionalNumber(value);\n}\n\nfunction readBooleanAttribute(\n dataset: DOMStringMap,\n key: string\n): boolean {\n if (!(key in dataset)) {\n return false;\n }\n\n const value = dataset[key];\n\n return value === '' || value === 'true';\n}\n\nfunction toOptionalNumber(\n value: string | undefined\n): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n const trimmed = value.trim();\n\n if (!trimmed) {\n return undefined;\n }\n\n const parsed = Number(trimmed);\n\n return Number.isNaN(parsed)\n ? undefined\n : parsed;\n}\n\nfunction toOptionDimension(\n value: string | undefined\n): number | undefined {\n const parsed = toOptionalNumber(value);\n\n if (\n parsed === undefined ||\n !Number.isFinite(parsed) ||\n parsed < 0 ||\n !Number.isInteger(parsed)\n ) {\n return undefined;\n }\n\n return parsed;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { BdActionElementAdapter } from './action.adapter.js';
2
+ export type BdActionRegistryCleanup = () => void;
3
+ export declare function getActionElementAdapter(element: HTMLElement): BdActionElementAdapter | undefined;
4
+ export declare function registerActionNodes(root: HTMLElement | ShadowRoot): BdActionRegistryCleanup;
@@ -0,0 +1,119 @@
1
+ import { BdActionElementAdapter } from './action.adapter.js';
2
+ import { DATA_ACTION_NODE, isActionElement } from './action.attributes.js';
3
+ const SHADOW_HOST_SELECTOR = '[shadow], [data-bd-watch-shadow]';
4
+ const ACTION_ADAPTERS = new WeakMap();
5
+ export function getActionElementAdapter(element) {
6
+ return ACTION_ADAPTERS.get(element);
7
+ }
8
+ export function registerActionNodes(root) {
9
+ const observed = new WeakSet();
10
+ const observers = new WeakMap();
11
+ const activeObservers = new Set();
12
+ const activeAdapters = new Set();
13
+ const connectActionElement = (element) => {
14
+ let adapter = ACTION_ADAPTERS.get(element);
15
+ if (!adapter) {
16
+ adapter = new BdActionElementAdapter(element);
17
+ ACTION_ADAPTERS.set(element, adapter);
18
+ }
19
+ activeAdapters.add(adapter);
20
+ adapter.connect();
21
+ };
22
+ const disconnectActionElement = (element) => {
23
+ const adapter = ACTION_ADAPTERS.get(element);
24
+ if (!adapter) {
25
+ return;
26
+ }
27
+ adapter.disconnect();
28
+ activeAdapters.delete(adapter);
29
+ };
30
+ const disconnectObserver = (node) => {
31
+ observed.delete(node);
32
+ const observer = observers.get(node);
33
+ if (!observer) {
34
+ return;
35
+ }
36
+ observer.disconnect();
37
+ observers.delete(node);
38
+ activeObservers.delete(observer);
39
+ };
40
+ const forEachActionElement = (searchRoot, callback) => {
41
+ if (searchRoot instanceof HTMLElement &&
42
+ isActionElement(searchRoot)) {
43
+ callback(searchRoot);
44
+ }
45
+ searchRoot
46
+ .querySelectorAll(DATA_ACTION_NODE)
47
+ .forEach(callback);
48
+ };
49
+ const forEachShadowRoot = (searchRoot, callback) => {
50
+ if (searchRoot instanceof HTMLElement &&
51
+ matchesShadowHost(searchRoot)) {
52
+ callback(searchRoot.shadowRoot);
53
+ }
54
+ searchRoot
55
+ .querySelectorAll(SHADOW_HOST_SELECTOR)
56
+ .forEach((host) => {
57
+ if (host.shadowRoot) {
58
+ callback(host.shadowRoot);
59
+ }
60
+ });
61
+ };
62
+ const cleanupShadowTree = (shadowRoot) => {
63
+ forEachActionElement(shadowRoot, disconnectActionElement);
64
+ forEachShadowRoot(shadowRoot, cleanupShadowTree);
65
+ disconnectObserver(shadowRoot);
66
+ };
67
+ const handleAdded = (node) => {
68
+ forEachActionElement(node, connectActionElement);
69
+ forEachShadowRoot(node, watch);
70
+ };
71
+ const handleRemoved = (node) => {
72
+ forEachActionElement(node, disconnectActionElement);
73
+ forEachShadowRoot(node, cleanupShadowTree);
74
+ };
75
+ const watch = (node) => {
76
+ if (observed.has(node)) {
77
+ return;
78
+ }
79
+ observed.add(node);
80
+ forEachActionElement(node, connectActionElement);
81
+ forEachShadowRoot(node, watch);
82
+ const observer = new MutationObserver((mutations) => {
83
+ for (const mutation of mutations) {
84
+ for (const added of mutation.addedNodes) {
85
+ if (added instanceof HTMLElement) {
86
+ handleAdded(added);
87
+ }
88
+ }
89
+ for (const removed of mutation.removedNodes) {
90
+ if (removed instanceof HTMLElement) {
91
+ handleRemoved(removed);
92
+ }
93
+ }
94
+ }
95
+ });
96
+ observer.observe(node, {
97
+ childList: true,
98
+ subtree: true
99
+ });
100
+ observers.set(node, observer);
101
+ activeObservers.add(observer);
102
+ };
103
+ watch(root);
104
+ return () => {
105
+ for (const observer of activeObservers) {
106
+ observer.disconnect();
107
+ }
108
+ activeObservers.clear();
109
+ for (const adapter of activeAdapters) {
110
+ adapter.disconnect();
111
+ }
112
+ activeAdapters.clear();
113
+ };
114
+ }
115
+ function matchesShadowHost(element) {
116
+ return Boolean(element.shadowRoot &&
117
+ element.matches(SHADOW_HOST_SELECTOR));
118
+ }
119
+ //# sourceMappingURL=action.registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.registry.js","sourceRoot":"","sources":["../../../src/actions/action.registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { BdActionElementAdapter } from './action.adapter.js';\nimport {\n DATA_ACTION_NODE,\n isActionElement\n} from './action.attributes.js';\n\nconst SHADOW_HOST_SELECTOR = '[shadow], [data-bd-watch-shadow]';\n\nconst ACTION_ADAPTERS = new WeakMap<HTMLElement, BdActionElementAdapter>();\n\nexport type BdActionRegistryCleanup = () => void;\n\nexport function getActionElementAdapter(\n element: HTMLElement\n): BdActionElementAdapter | undefined {\n return ACTION_ADAPTERS.get(element);\n}\n\nexport function registerActionNodes(\n root: HTMLElement | ShadowRoot\n): BdActionRegistryCleanup {\n const observed = new WeakSet<Node>();\n const observers = new WeakMap<Node, MutationObserver>();\n const activeObservers = new Set<MutationObserver>();\n const activeAdapters = new Set<BdActionElementAdapter>();\n\n const connectActionElement = (element: HTMLElement): void => {\n let adapter = ACTION_ADAPTERS.get(element);\n\n if (!adapter) {\n adapter = new BdActionElementAdapter(element);\n ACTION_ADAPTERS.set(\n element,\n adapter\n );\n }\n\n activeAdapters.add(adapter);\n adapter.connect();\n };\n\n const disconnectActionElement = (element: HTMLElement): void => {\n const adapter = ACTION_ADAPTERS.get(element);\n\n if (!adapter) {\n return;\n }\n\n adapter.disconnect();\n activeAdapters.delete(adapter);\n };\n\n const disconnectObserver = (node: Node): void => {\n observed.delete(node);\n\n const observer = observers.get(node);\n\n if (!observer) {\n return;\n }\n\n observer.disconnect();\n observers.delete(node);\n activeObservers.delete(observer);\n };\n\n const forEachActionElement = (\n searchRoot: HTMLElement | ShadowRoot,\n callback: (element: HTMLElement) => void\n ): void => {\n if (\n searchRoot instanceof HTMLElement &&\n isActionElement(searchRoot)\n ) {\n callback(searchRoot);\n }\n\n searchRoot\n .querySelectorAll<HTMLElement>(DATA_ACTION_NODE)\n .forEach(callback);\n };\n\n const forEachShadowRoot = (\n searchRoot: HTMLElement | ShadowRoot,\n callback: (shadowRoot: ShadowRoot) => void\n ): void => {\n if (\n searchRoot instanceof HTMLElement &&\n matchesShadowHost(searchRoot)\n ) {\n callback(searchRoot.shadowRoot);\n }\n\n searchRoot\n .querySelectorAll<HTMLElement>(SHADOW_HOST_SELECTOR)\n .forEach((host) => {\n if (host.shadowRoot) {\n callback(host.shadowRoot);\n }\n });\n };\n\n const cleanupShadowTree = (shadowRoot: ShadowRoot): void => {\n forEachActionElement(\n shadowRoot,\n disconnectActionElement\n );\n\n forEachShadowRoot(\n shadowRoot,\n cleanupShadowTree\n );\n\n disconnectObserver(shadowRoot);\n };\n\n const handleAdded = (node: HTMLElement): void => {\n forEachActionElement(\n node,\n connectActionElement\n );\n\n forEachShadowRoot(\n node,\n watch\n );\n };\n\n const handleRemoved = (node: HTMLElement): void => {\n forEachActionElement(\n node,\n disconnectActionElement\n );\n\n forEachShadowRoot(\n node,\n cleanupShadowTree\n );\n };\n\n const watch = (node: HTMLElement | ShadowRoot): void => {\n if (observed.has(node)) {\n return;\n }\n\n observed.add(node);\n\n forEachActionElement(\n node,\n connectActionElement\n );\n\n forEachShadowRoot(\n node,\n watch\n );\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const added of mutation.addedNodes) {\n if (added instanceof HTMLElement) {\n handleAdded(added);\n }\n }\n\n for (const removed of mutation.removedNodes) {\n if (removed instanceof HTMLElement) {\n handleRemoved(removed);\n }\n }\n }\n });\n\n observer.observe(\n node,\n {\n childList: true,\n subtree : true\n }\n );\n\n observers.set(\n node,\n observer\n );\n\n activeObservers.add(observer);\n };\n\n watch(root);\n\n return () => {\n for (const observer of activeObservers) {\n observer.disconnect();\n }\n\n activeObservers.clear();\n\n for (const adapter of activeAdapters) {\n adapter.disconnect();\n }\n\n activeAdapters.clear();\n };\n}\n\nfunction matchesShadowHost(\n element: HTMLElement\n): element is HTMLElement & { shadowRoot: ShadowRoot } {\n return Boolean(\n element.shadowRoot &&\n element.matches(SHADOW_HOST_SELECTOR)\n );\n}\n"]}
@@ -1,2 +1,3 @@
1
- declare const registerActionNodes: (root: HTMLElement | ShadowRoot) => () => void;
2
- export { registerActionNodes };
1
+ export * from './action.adapter.js';
2
+ export * from './action.attributes.js';
3
+ export * from './action.registry.js';