@microsoft/fast-element 1.10.5 → 2.0.0-beta.10

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 (122) hide show
  1. package/.eslintrc.json +1 -12
  2. package/CHANGELOG.json +629 -6
  3. package/CHANGELOG.md +152 -5
  4. package/dist/dts/components/attributes.d.ts +14 -1
  5. package/dist/dts/components/{controller.d.ts → element-controller.d.ts} +32 -32
  6. package/dist/dts/components/fast-definitions.d.ts +51 -11
  7. package/dist/dts/components/fast-element.d.ts +18 -23
  8. package/dist/dts/context.d.ts +157 -0
  9. package/dist/{esm/observation/behavior.js → dts/debug.d.ts} +0 -0
  10. package/dist/dts/di/di.d.ts +899 -0
  11. package/dist/dts/index.d.ts +17 -16
  12. package/dist/dts/index.debug.d.ts +2 -0
  13. package/dist/dts/index.rollup.d.ts +2 -0
  14. package/dist/dts/index.rollup.debug.d.ts +3 -0
  15. package/dist/dts/interfaces.d.ts +176 -0
  16. package/dist/dts/metadata.d.ts +25 -0
  17. package/dist/dts/observation/arrays.d.ts +207 -0
  18. package/dist/dts/observation/notifier.d.ts +18 -18
  19. package/dist/dts/observation/observable.d.ts +117 -34
  20. package/dist/dts/observation/update-queue.d.ts +40 -0
  21. package/dist/dts/pending-task.d.ts +20 -0
  22. package/dist/dts/platform.d.ts +23 -66
  23. package/dist/dts/polyfills.d.ts +8 -0
  24. package/dist/dts/state/exports.d.ts +3 -0
  25. package/dist/dts/state/reactive.d.ts +8 -0
  26. package/dist/dts/state/state.d.ts +141 -0
  27. package/dist/dts/state/visitor.d.ts +6 -0
  28. package/dist/dts/state/watch.d.ts +10 -0
  29. package/dist/dts/styles/css-directive.d.ts +44 -6
  30. package/dist/dts/styles/css.d.ts +19 -3
  31. package/dist/dts/styles/element-styles.d.ts +49 -63
  32. package/dist/dts/styles/host.d.ts +68 -0
  33. package/dist/dts/templating/binding-signal.d.ts +21 -0
  34. package/dist/dts/templating/binding-two-way.d.ts +39 -0
  35. package/dist/dts/templating/binding.d.ts +101 -70
  36. package/dist/dts/templating/children.d.ts +18 -15
  37. package/dist/dts/templating/compiler.d.ts +46 -28
  38. package/dist/dts/templating/dom.d.ts +41 -0
  39. package/dist/dts/templating/html-directive.d.ts +239 -45
  40. package/dist/dts/templating/markup.d.ts +48 -0
  41. package/dist/dts/templating/node-observation.d.ts +45 -30
  42. package/dist/dts/templating/ref.d.ts +6 -20
  43. package/dist/dts/templating/render.d.ts +272 -0
  44. package/dist/dts/templating/repeat.d.ts +36 -33
  45. package/dist/dts/templating/slotted.d.ts +13 -14
  46. package/dist/dts/templating/template.d.ts +28 -22
  47. package/dist/dts/templating/view.d.ts +82 -24
  48. package/dist/dts/templating/when.d.ts +3 -3
  49. package/dist/dts/testing/exports.d.ts +3 -0
  50. package/dist/dts/testing/fakes.d.ts +4 -0
  51. package/dist/dts/testing/fixture.d.ts +84 -0
  52. package/dist/dts/testing/timeout.d.ts +7 -0
  53. package/dist/{tsdoc-metadata.json → dts/tsdoc-metadata.json} +1 -1
  54. package/dist/dts/utilities.d.ts +22 -0
  55. package/dist/esm/components/attributes.js +38 -28
  56. package/dist/esm/components/{controller.js → element-controller.js} +150 -140
  57. package/dist/esm/components/fast-definitions.js +48 -46
  58. package/dist/esm/components/fast-element.js +31 -12
  59. package/dist/esm/context.js +163 -0
  60. package/dist/esm/debug.js +61 -0
  61. package/dist/esm/di/di.js +1435 -0
  62. package/dist/esm/index.debug.js +2 -0
  63. package/dist/esm/index.js +20 -14
  64. package/dist/esm/index.rollup.debug.js +3 -0
  65. package/dist/esm/index.rollup.js +2 -0
  66. package/dist/esm/interfaces.js +12 -1
  67. package/dist/esm/metadata.js +60 -0
  68. package/dist/esm/observation/arrays.js +570 -0
  69. package/dist/esm/observation/notifier.js +27 -35
  70. package/dist/esm/observation/observable.js +116 -149
  71. package/dist/esm/observation/update-queue.js +67 -0
  72. package/dist/esm/pending-task.js +16 -0
  73. package/dist/esm/platform.js +60 -42
  74. package/dist/esm/polyfills.js +85 -0
  75. package/dist/esm/state/exports.js +3 -0
  76. package/dist/esm/state/reactive.js +34 -0
  77. package/dist/esm/state/state.js +148 -0
  78. package/dist/esm/state/visitor.js +28 -0
  79. package/dist/esm/state/watch.js +36 -0
  80. package/dist/esm/styles/css-directive.js +29 -13
  81. package/dist/esm/styles/css.js +29 -42
  82. package/dist/esm/styles/element-styles.js +79 -104
  83. package/dist/esm/styles/host.js +1 -0
  84. package/dist/esm/templating/binding-signal.js +83 -0
  85. package/dist/esm/templating/binding-two-way.js +103 -0
  86. package/dist/esm/templating/binding.js +189 -159
  87. package/dist/esm/templating/children.js +33 -23
  88. package/dist/esm/templating/compiler.js +258 -152
  89. package/dist/esm/templating/dom.js +49 -0
  90. package/dist/esm/templating/html-directive.js +193 -36
  91. package/dist/esm/templating/markup.js +75 -0
  92. package/dist/esm/templating/node-observation.js +51 -45
  93. package/dist/esm/templating/ref.js +8 -25
  94. package/dist/esm/templating/render.js +391 -0
  95. package/dist/esm/templating/repeat.js +83 -79
  96. package/dist/esm/templating/slotted.js +23 -20
  97. package/dist/esm/templating/template.js +51 -93
  98. package/dist/esm/templating/view.js +125 -46
  99. package/dist/esm/templating/when.js +6 -4
  100. package/dist/esm/testing/exports.js +3 -0
  101. package/dist/esm/testing/fakes.js +76 -0
  102. package/dist/esm/testing/fixture.js +86 -0
  103. package/dist/esm/testing/timeout.js +24 -0
  104. package/dist/esm/utilities.js +44 -0
  105. package/dist/fast-element.api.json +12153 -5373
  106. package/dist/fast-element.d.ts +1448 -696
  107. package/dist/fast-element.debug.js +4107 -0
  108. package/dist/fast-element.debug.min.js +1 -0
  109. package/dist/fast-element.js +3817 -4029
  110. package/dist/fast-element.min.js +1 -1
  111. package/dist/fast-element.untrimmed.d.ts +2814 -0
  112. package/docs/api-report.md +567 -254
  113. package/docs/fast-element-2-changes.md +15 -0
  114. package/karma.conf.cjs +6 -17
  115. package/package.json +76 -15
  116. package/dist/dts/dom.d.ts +0 -112
  117. package/dist/dts/observation/array-change-records.d.ts +0 -48
  118. package/dist/dts/observation/array-observer.d.ts +0 -9
  119. package/dist/dts/observation/behavior.d.ts +0 -19
  120. package/dist/esm/dom.js +0 -207
  121. package/dist/esm/observation/array-change-records.js +0 -326
  122. package/dist/esm/observation/array-observer.js +0 -177
@@ -1,55 +1,41 @@
1
- import { DOM } from "../dom.js";
1
+ import { isFunction } from "../interfaces.js";
2
2
  import { ExecutionContext, Observable, } from "../observation/observable.js";
3
- import { TargetedHTMLDirective } from "./html-directive.js";
4
- function normalBind(source, context) {
5
- this.source = source;
6
- this.context = context;
7
- if (this.bindingObserver === null) {
8
- this.bindingObserver = Observable.binding(this.binding, this, this.isBindingVolatile);
9
- }
10
- this.updateTarget(this.bindingObserver.observe(source, context));
11
- }
12
- function triggerBind(source, context) {
13
- this.source = source;
14
- this.context = context;
15
- this.target.addEventListener(this.targetName, this);
16
- }
17
- function normalUnbind() {
18
- this.bindingObserver.disconnect();
19
- this.source = null;
20
- this.context = null;
21
- }
22
- function contentUnbind() {
23
- this.bindingObserver.disconnect();
24
- this.source = null;
25
- this.context = null;
26
- const view = this.target.$fastView;
27
- if (view !== void 0 && view.isComposed) {
28
- view.unbind();
29
- view.needsBindOnly = true;
3
+ import { FAST } from "../platform.js";
4
+ import { DOM } from "./dom.js";
5
+ import { Aspect, Binding, HTMLDirective, } from "./html-directive.js";
6
+ import { Markup, nextId } from "./markup.js";
7
+ const createInnerHTMLBinding = globalThis.TrustedHTML
8
+ ? (binding) => (s, c) => {
9
+ const value = binding(s, c);
10
+ if (value instanceof TrustedHTML) {
11
+ return value;
12
+ }
13
+ throw FAST.error(1202 /* Message.bindingInnerHTMLRequiresTrustedTypes */);
14
+ }
15
+ : (binding) => binding;
16
+ class OnChangeBinding extends Binding {
17
+ createObserver(_, subscriber) {
18
+ return Observable.binding(this.evaluate, subscriber, this.isVolatile);
30
19
  }
31
20
  }
32
- function triggerUnbind() {
33
- this.target.removeEventListener(this.targetName, this);
34
- this.source = null;
35
- this.context = null;
36
- }
37
- function updateAttributeTarget(value) {
38
- DOM.setAttribute(this.target, this.targetName, value);
39
- }
40
- function updateBooleanAttributeTarget(value) {
41
- DOM.setBooleanAttribute(this.target, this.targetName, value);
21
+ class OneTimeBinding extends Binding {
22
+ createObserver() {
23
+ return this;
24
+ }
25
+ bind(controller) {
26
+ return this.evaluate(controller.source, controller.context);
27
+ }
42
28
  }
43
- function updateContentTarget(value) {
29
+ function updateContent(target, aspect, value, controller) {
44
30
  // If there's no actual value, then this equates to the
45
31
  // empty string for the purposes of content bindings.
46
32
  if (value === null || value === undefined) {
47
33
  value = "";
48
34
  }
49
- // If the value has a "create" method, then it's a template-like.
35
+ // If the value has a "create" method, then it's a ContentTemplate.
50
36
  if (value.create) {
51
- this.target.textContent = "";
52
- let view = this.target.$fastView;
37
+ target.textContent = "";
38
+ let view = target.$fastView;
53
39
  // If there's no previous view that we might be able to
54
40
  // reuse then create a new view from the template.
55
41
  if (view === void 0) {
@@ -60,7 +46,7 @@ function updateContentTarget(value) {
60
46
  // from the same template as the new value, then we
61
47
  // need to remove the old view if it's still in the DOM
62
48
  // and create a new view from the template.
63
- if (this.target.$fastTemplate !== value) {
49
+ if (target.$fastTemplate !== value) {
64
50
  if (view.isComposed) {
65
51
  view.remove();
66
52
  view.unbind();
@@ -72,18 +58,18 @@ function updateContentTarget(value) {
72
58
  // and that there's actually no need to compose it.
73
59
  if (!view.isComposed) {
74
60
  view.isComposed = true;
75
- view.bind(this.source, this.context);
76
- view.insertBefore(this.target);
77
- this.target.$fastView = view;
78
- this.target.$fastTemplate = value;
61
+ view.bind(controller.source, controller.context);
62
+ view.insertBefore(target);
63
+ target.$fastView = view;
64
+ target.$fastTemplate = value;
79
65
  }
80
66
  else if (view.needsBindOnly) {
81
67
  view.needsBindOnly = false;
82
- view.bind(this.source, this.context);
68
+ view.bind(controller.source, controller.context);
83
69
  }
84
70
  }
85
71
  else {
86
- const view = this.target.$fastView;
72
+ const view = target.$fastView;
87
73
  // If there is a view and it's currently composed into
88
74
  // the DOM, then we need to remove it.
89
75
  if (view !== void 0 && view.isComposed) {
@@ -96,16 +82,16 @@ function updateContentTarget(value) {
96
82
  view.unbind();
97
83
  }
98
84
  }
99
- this.target.textContent = value;
85
+ target.textContent = value;
100
86
  }
101
87
  }
102
- function updatePropertyTarget(value) {
103
- this.target[this.targetName] = value;
104
- }
105
- function updateClassTarget(value) {
106
- const classVersions = this.classVersions || Object.create(null);
107
- const target = this.target;
108
- let version = this.version || 0;
88
+ function updateTokenList(target, aspect, value) {
89
+ var _a;
90
+ const lookup = `${this.id}-t`;
91
+ const state = (_a = target[lookup]) !== null && _a !== void 0 ? _a : (target[lookup] = { c: 0, v: Object.create(null) });
92
+ const versions = state.v;
93
+ let currentVersion = state.c;
94
+ const tokenList = target[aspect];
109
95
  // Add the classes, tracking the version at which they were added.
110
96
  if (value !== null && value !== undefined && value.length) {
111
97
  const names = value.split(/\s+/);
@@ -114,139 +100,183 @@ function updateClassTarget(value) {
114
100
  if (currentName === "") {
115
101
  continue;
116
102
  }
117
- classVersions[currentName] = version;
118
- target.classList.add(currentName);
103
+ versions[currentName] = currentVersion;
104
+ tokenList.add(currentName);
119
105
  }
120
106
  }
121
- this.classVersions = classVersions;
122
- this.version = version + 1;
107
+ state.v = currentVersion + 1;
123
108
  // If this is the first call to add classes, there's no need to remove old ones.
124
- if (version === 0) {
109
+ if (currentVersion === 0) {
125
110
  return;
126
111
  }
127
112
  // Remove classes from the previous version.
128
- version -= 1;
129
- for (const name in classVersions) {
130
- if (classVersions[name] === version) {
131
- target.classList.remove(name);
113
+ currentVersion -= 1;
114
+ for (const name in versions) {
115
+ if (versions[name] === currentVersion) {
116
+ tokenList.remove(name);
132
117
  }
133
118
  }
134
119
  }
120
+ const setProperty = (t, a, v) => (t[a] = v);
121
+ const eventTarget = () => void 0;
135
122
  /**
136
- * A directive that configures data binding to element content and attributes.
123
+ * A directive that applies bindings.
137
124
  * @public
138
125
  */
139
- export class HTMLBindingDirective extends TargetedHTMLDirective {
126
+ export class HTMLBindingDirective {
140
127
  /**
141
- * Creates an instance of BindingDirective.
142
- * @param binding - A binding that returns the data used to update the DOM.
128
+ * Creates an instance of HTMLBindingDirective.
129
+ * @param dataBinding - The binding configuration to apply.
143
130
  */
144
- constructor(binding) {
145
- super();
146
- this.binding = binding;
147
- this.bind = normalBind;
148
- this.unbind = normalUnbind;
149
- this.updateTarget = updateAttributeTarget;
150
- this.isBindingVolatile = Observable.isVolatileBinding(this.binding);
131
+ constructor(dataBinding) {
132
+ this.dataBinding = dataBinding;
133
+ this.updateTarget = null;
134
+ /**
135
+ * The unique id of the factory.
136
+ */
137
+ this.id = nextId();
138
+ /**
139
+ * The type of aspect to target.
140
+ */
141
+ this.aspectType = Aspect.content;
142
+ /** @internal */
143
+ this.bind = this.bindDefault;
144
+ this.data = `${this.id}-d`;
151
145
  }
152
146
  /**
153
- * Gets/sets the name of the attribute or property that this
154
- * binding is targeting.
147
+ * Creates HTML to be used within a template.
148
+ * @param add - Can be used to add behavior factories to a template.
155
149
  */
156
- get targetName() {
157
- return this.originalTargetName;
158
- }
159
- set targetName(value) {
160
- this.originalTargetName = value;
161
- if (value === void 0) {
162
- return;
163
- }
164
- switch (value[0]) {
165
- case ":":
166
- this.cleanedTargetName = value.substr(1);
167
- this.updateTarget = updatePropertyTarget;
168
- if (this.cleanedTargetName === "innerHTML") {
169
- const binding = this.binding;
170
- this.binding = (s, c) => DOM.createHTML(binding(s, c));
171
- }
172
- break;
173
- case "?":
174
- this.cleanedTargetName = value.substr(1);
175
- this.updateTarget = updateBooleanAttributeTarget;
176
- break;
177
- case "@":
178
- this.cleanedTargetName = value.substr(1);
179
- this.bind = triggerBind;
180
- this.unbind = triggerUnbind;
181
- break;
182
- default:
183
- this.cleanedTargetName = value;
184
- if (value === "class") {
185
- this.updateTarget = updateClassTarget;
186
- }
187
- break;
188
- }
150
+ createHTML(add) {
151
+ return Markup.interpolation(add(this));
189
152
  }
190
153
  /**
191
- * Makes this binding target the content of an element rather than
192
- * a particular attribute or property.
154
+ * Creates a behavior.
193
155
  */
194
- targetAtContent() {
195
- this.updateTarget = updateContentTarget;
196
- this.unbind = contentUnbind;
156
+ createBehavior() {
157
+ if (this.updateTarget === null) {
158
+ if (this.targetAspect === "innerHTML") {
159
+ this.dataBinding.evaluate = createInnerHTMLBinding(this.dataBinding.evaluate);
160
+ }
161
+ switch (this.aspectType) {
162
+ case 1:
163
+ this.updateTarget = DOM.setAttribute;
164
+ break;
165
+ case 2:
166
+ this.updateTarget = DOM.setBooleanAttribute;
167
+ break;
168
+ case 3:
169
+ this.updateTarget = setProperty;
170
+ break;
171
+ case 4:
172
+ this.bind = this.bindContent;
173
+ this.updateTarget = updateContent;
174
+ break;
175
+ case 5:
176
+ this.updateTarget = updateTokenList;
177
+ break;
178
+ case 6:
179
+ this.bind = this.bindEvent;
180
+ this.updateTarget = eventTarget;
181
+ break;
182
+ default:
183
+ throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
184
+ }
185
+ }
186
+ return this;
197
187
  }
198
- /**
199
- * Creates the runtime BindingBehavior instance based on the configuration
200
- * information stored in the BindingDirective.
201
- * @param target - The target node that the binding behavior should attach to.
202
- */
203
- createBehavior(target) {
204
- /* eslint-disable-next-line @typescript-eslint/no-use-before-define */
205
- return new BindingBehavior(target, this.binding, this.isBindingVolatile, this.bind, this.unbind, this.updateTarget, this.cleanedTargetName);
188
+ /** @internal */
189
+ bindDefault(controller) {
190
+ var _a;
191
+ const target = controller.targets[this.nodeId];
192
+ const observer = (_a = target[this.data]) !== null && _a !== void 0 ? _a : (target[this.data] = this.dataBinding.createObserver(this, this));
193
+ observer.target = target;
194
+ observer.controller = controller;
195
+ this.updateTarget(target, this.targetAspect, observer.bind(controller), controller);
196
+ if (this.updateTarget === updateContent) {
197
+ controller.onUnbind(this);
198
+ }
206
199
  }
207
- }
208
- /**
209
- * A behavior that updates content and attributes based on a configured
210
- * BindingDirective.
211
- * @public
212
- */
213
- export class BindingBehavior {
214
- /**
215
- * Creates an instance of BindingBehavior.
216
- * @param target - The target of the data updates.
217
- * @param binding - The binding that returns the latest value for an update.
218
- * @param isBindingVolatile - Indicates whether the binding has volatile dependencies.
219
- * @param bind - The operation to perform during binding.
220
- * @param unbind - The operation to perform during unbinding.
221
- * @param updateTarget - The operation to perform when updating.
222
- * @param targetName - The name of the target attribute or property to update.
223
- */
224
- constructor(target, binding, isBindingVolatile, bind, unbind, updateTarget, targetName) {
225
- /** @internal */
226
- this.source = null;
227
- /** @internal */
228
- this.context = null;
229
- /** @internal */
230
- this.bindingObserver = null;
231
- this.target = target;
232
- this.binding = binding;
233
- this.isBindingVolatile = isBindingVolatile;
234
- this.bind = bind;
235
- this.unbind = unbind;
236
- this.updateTarget = updateTarget;
237
- this.targetName = targetName;
200
+ /** @internal */
201
+ bindContent(controller) {
202
+ this.bindDefault(controller);
203
+ controller.onUnbind(this);
204
+ }
205
+ /** @internal */
206
+ bindEvent(controller) {
207
+ const target = controller.targets[this.nodeId];
208
+ target[this.data] = controller;
209
+ target.addEventListener(this.targetAspect, this, this.dataBinding.options);
238
210
  }
239
211
  /** @internal */
240
- handleChange() {
241
- this.updateTarget(this.bindingObserver.observe(this.source, this.context));
212
+ unbind(controller) {
213
+ const target = controller.targets[this.nodeId];
214
+ const view = target.$fastView;
215
+ if (view !== void 0 && view.isComposed) {
216
+ view.unbind();
217
+ view.needsBindOnly = true;
218
+ }
242
219
  }
243
220
  /** @internal */
244
221
  handleEvent(event) {
222
+ const target = event.currentTarget;
245
223
  ExecutionContext.setEvent(event);
246
- const result = this.binding(this.source, this.context);
224
+ const controller = target[this.data];
225
+ const result = this.dataBinding.evaluate(controller.source, controller.context);
247
226
  ExecutionContext.setEvent(null);
248
227
  if (result !== true) {
249
228
  event.preventDefault();
250
229
  }
251
230
  }
231
+ /** @internal */
232
+ handleChange(binding, observer) {
233
+ const target = observer.target;
234
+ const controller = observer.controller;
235
+ this.updateTarget(target, this.targetAspect, observer.bind(controller), controller);
236
+ }
237
+ }
238
+ HTMLDirective.define(HTMLBindingDirective, { aspected: true });
239
+ /**
240
+ * Creates an standard binding.
241
+ * @param binding - The binding to refresh when changed.
242
+ * @param isVolatile - Indicates whether the binding is volatile or not.
243
+ * @returns A binding configuration.
244
+ * @public
245
+ */
246
+ export function bind(binding, isVolatile = Observable.isVolatileBinding(binding)) {
247
+ return new OnChangeBinding(binding, isVolatile);
248
+ }
249
+ /**
250
+ * Creates a one time binding
251
+ * @param binding - The binding to refresh when signaled.
252
+ * @returns A binding configuration.
253
+ * @public
254
+ */
255
+ export function oneTime(binding) {
256
+ return new OneTimeBinding(binding);
257
+ }
258
+ /**
259
+ * Creates an event listener binding.
260
+ * @param binding - The binding to invoke when the event is raised.
261
+ * @param options - Event listener options.
262
+ * @returns A binding configuration.
263
+ * @public
264
+ */
265
+ export function listener(binding, options) {
266
+ const config = new OnChangeBinding(binding, false);
267
+ config.options = options;
268
+ return config;
269
+ }
270
+ /**
271
+ * Normalizes the input value into a binding.
272
+ * @param value - The value to create the default binding for.
273
+ * @returns A binding configuration for the provided value.
274
+ * @public
275
+ */
276
+ export function normalizeBinding(value) {
277
+ return isFunction(value)
278
+ ? bind(value)
279
+ : value instanceof Binding
280
+ ? value
281
+ : oneTime(() => value);
252
282
  }
@@ -1,45 +1,55 @@
1
- import { AttachedBehaviorHTMLDirective } from "./html-directive.js";
2
- import { NodeObservationBehavior } from "./node-observation.js";
1
+ import { isString } from "../interfaces.js";
2
+ import { HTMLDirective } from "./html-directive.js";
3
+ import { NodeObservationDirective } from "./node-observation.js";
3
4
  /**
4
5
  * The runtime behavior for child node observation.
5
6
  * @public
6
7
  */
7
- export class ChildrenBehavior extends NodeObservationBehavior {
8
+ export class ChildrenDirective extends NodeObservationDirective {
8
9
  /**
9
- * Creates an instance of ChildrenBehavior.
10
- * @param target - The element target to observe children on.
11
- * @param options - The options to use when observing the element children.
10
+ * Creates an instance of ChildrenDirective.
11
+ * @param options - The options to use in configuring the child observation behavior.
12
12
  */
13
- constructor(target, options) {
14
- super(target, options);
15
- this.observer = null;
13
+ constructor(options) {
14
+ super(options);
15
+ this.observerProperty = `${this.id}-o`;
16
+ this.handleEvent = (mutations, observer) => {
17
+ const target = observer.target;
18
+ this.updateTarget(this.getSource(target), this.computeNodes(target));
19
+ };
16
20
  options.childList = true;
17
21
  }
18
22
  /**
19
23
  * Begins observation of the nodes.
24
+ * @param target - The target to observe.
20
25
  */
21
- observe() {
22
- if (this.observer === null) {
23
- this.observer = new MutationObserver(this.handleEvent.bind(this));
24
- }
25
- this.observer.observe(this.target, this.options);
26
+ observe(target) {
27
+ var _a;
28
+ const observer = (_a = target[this.observerProperty]) !== null && _a !== void 0 ? _a : (target[this.observerProperty] = new MutationObserver(this.handleEvent));
29
+ observer.target = target;
30
+ observer.observe(target, this.options);
26
31
  }
27
32
  /**
28
33
  * Disconnects observation of the nodes.
34
+ * @param target - The target to unobserve.
29
35
  */
30
- disconnect() {
31
- this.observer.disconnect();
36
+ disconnect(target) {
37
+ const observer = target[this.observerProperty];
38
+ observer.target = null;
39
+ observer.disconnect();
32
40
  }
33
41
  /**
34
- * Retrieves the nodes that should be assigned to the target.
42
+ * Retrieves the raw nodes that should be assigned to the source property.
43
+ * @param target - The target to get the node to.
35
44
  */
36
- getNodes() {
37
- if ("subtree" in this.options) {
38
- return Array.from(this.target.querySelectorAll(this.options.selector));
45
+ getNodes(target) {
46
+ if ("selector" in this.options) {
47
+ return Array.from(target.querySelectorAll(this.options.selector));
39
48
  }
40
- return Array.from(this.target.childNodes);
49
+ return Array.from(target.childNodes);
41
50
  }
42
51
  }
52
+ HTMLDirective.define(ChildrenDirective);
43
53
  /**
44
54
  * A directive that observes the `childNodes` of an element and updates a property
45
55
  * whenever they change.
@@ -47,10 +57,10 @@ export class ChildrenBehavior extends NodeObservationBehavior {
47
57
  * @public
48
58
  */
49
59
  export function children(propertyOrOptions) {
50
- if (typeof propertyOrOptions === "string") {
60
+ if (isString(propertyOrOptions)) {
51
61
  propertyOrOptions = {
52
62
  property: propertyOrOptions,
53
63
  };
54
64
  }
55
- return new AttachedBehaviorHTMLDirective("fast-children", ChildrenBehavior, propertyOrOptions);
65
+ return new ChildrenDirective(propertyOrOptions);
56
66
  }