@aurelia-mdc-web/all 9.3.0-au2 → 9.3.1-au2

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 (27) hide show
  1. package/dist/chips/mdc-chip/mdc-chip.js.map +1 -1
  2. package/dist/data-table/mdc-data-table.js.map +1 -1
  3. package/dist/dialog/mdc-dialog-service.js.map +1 -1
  4. package/dist/expandable/mdc-expandable.js.map +1 -1
  5. package/dist/form-field/mdc-form-field.js.map +1 -1
  6. package/dist/list/mdc-deprecated-list/mdc-deprecated-list-item/mdc-deprecated-list-item.js.map +1 -1
  7. package/dist/list/mdc-list-item/mdc-list-item.js.map +1 -1
  8. package/dist/menu/mdc-menu.js.map +1 -1
  9. package/dist/segmented-button/mdc-segmented-button-segment/mdc-segmented-button-segment.js.map +1 -1
  10. package/dist/select/mdc-select-value-observer.js.map +1 -1
  11. package/dist/select/mdc-select.js.map +1 -1
  12. package/dist/text-field/mdc-text-field.js.map +1 -1
  13. package/dist/tree-view/mdc-tree-view.js.map +1 -1
  14. package/package.json +2 -2
  15. package/src/chips/mdc-chip/mdc-chip.ts +290 -290
  16. package/src/data-table/mdc-data-table.ts +432 -432
  17. package/src/dialog/mdc-dialog-service.ts +80 -80
  18. package/src/expandable/mdc-expandable.ts +104 -104
  19. package/src/form-field/mdc-form-field.ts +60 -60
  20. package/src/list/mdc-deprecated-list/mdc-deprecated-list-item/mdc-deprecated-list-item.ts +108 -108
  21. package/src/list/mdc-list-item/mdc-list-item.ts +136 -136
  22. package/src/menu/mdc-menu.ts +340 -340
  23. package/src/segmented-button/mdc-segmented-button-segment/mdc-segmented-button-segment.ts +170 -170
  24. package/src/select/mdc-select-value-observer.ts +346 -346
  25. package/src/select/mdc-select.ts +480 -480
  26. package/src/text-field/mdc-text-field.ts +535 -535
  27. package/src/tree-view/mdc-tree-view.ts +147 -147
@@ -1,346 +1,346 @@
1
- import {
2
- subscriberCollection,
3
- AccessorType,
4
- } from '@aurelia/runtime';
5
-
6
- import type {
7
- ICollectionObserver,
8
- IndexMap,
9
- IObserver,
10
- IObserverLocator,
11
- ISubscriber,
12
- ISubscriberCollection,
13
- } from '@aurelia/runtime';
14
-
15
- import { INode, CustomElement } from '@aurelia/runtime-html';
16
- import { IMdcSelectElement, MdcSelect } from './mdc-select';
17
-
18
- // const hasOwn = Object.prototype.hasOwnProperty;
19
- const childObserverOptions = {
20
- childList: true,
21
- subtree: true,
22
- characterData: true
23
- };
24
-
25
- // function defaultMatcher(a: unknown, b: unknown): boolean {
26
- // return a === b;
27
- // }
28
-
29
- export interface IOptionElement extends HTMLOptionElement {
30
- model?: unknown;
31
- }
32
-
33
- export interface MdcSelectValueObserver extends
34
- ISubscriberCollection { }
35
-
36
- export interface INodeObserverConfigBase {
37
- /**
38
- * Indicates the list of events can be used to observe a particular property
39
- */
40
- readonly events: string[];
41
- /**
42
- * Indicates whether this property is readonly, so observer wont attempt to assign value
43
- * example: input.files
44
- */
45
- readonly readonly?: boolean;
46
- /**
47
- * A default value to assign to the corresponding property if the incoming value is null/undefined
48
- */
49
- readonly default?: unknown;
50
- }
51
-
52
-
53
- export interface INodeObserver extends IObserver {
54
- /**
55
- * Instruct this node observer event observation behavior
56
- */
57
- useConfig(config: INodeObserverConfigBase): void;
58
- }
59
-
60
- @subscriberCollection()
61
- export class MdcSelectValueObserver implements INodeObserver {
62
- public currentValue: unknown = void 0;
63
- public oldValue: unknown = void 0;
64
-
65
- public readonly obj: IMdcSelectElement;
66
- public config: INodeObserverConfigBase;
67
-
68
- public hasChanges: boolean = false;
69
- // ObserverType.Layout is not always true
70
- // but for simplicity, always treat as such
71
- public type: AccessorType = (AccessorType.Node | AccessorType.Observer | AccessorType.Layout) as AccessorType;
72
-
73
- public arrayObserver?: ICollectionObserver<'array'> = void 0;
74
- public nodeObserver?: MutationObserver = void 0;
75
-
76
- private observing: boolean = false;
77
- private listened: boolean = false;
78
-
79
- public constructor(
80
- obj: INode,
81
- // deepscan-disable-next-line
82
- _key: PropertyKey,
83
- config: INodeObserverConfigBase,
84
- _: IObserverLocator
85
- ) {
86
- this.obj = obj as unknown as IMdcSelectElement;
87
- this.config = config;
88
- }
89
-
90
- optionsWereSet: boolean;
91
-
92
- setElementValue(skipNotify: boolean) {
93
- // do not pass the value to the element if options has never been set
94
- // the value will be passed on when options do arrive
95
- if (this.optionsWereSet) {
96
- CustomElement.for<MdcSelect>(this.obj).viewModel.setValue(this.currentValue, skipNotify);
97
- }
98
- }
99
-
100
- public getValue(): unknown {
101
- // is it safe to assume the observer has the latest value?
102
- // todo: ability to turn on/off cache based on type
103
- return this.observing
104
- ? this.currentValue
105
- // : this.obj.multiple
106
- // ? Array.from(this.obj.options).map(o => o.value)
107
- : this.obj.value;
108
- }
109
-
110
- public setValue(newValue: unknown): void {
111
- this.currentValue = newValue;
112
- this.hasChanges = newValue !== this.oldValue;
113
- // this.observeArray(newValue instanceof Array ? newValue : null);
114
- if (this.optionsWereSet) {
115
- this.flushChanges();
116
- }
117
- }
118
-
119
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
120
- public flushChanges(): void {
121
- if (this.hasChanges) {
122
- this.hasChanges = false;
123
- this.synchronizeOptions();
124
- }
125
- }
126
-
127
- public handleCollectionChange(): void {
128
- // always sync "selected" property of <options/>
129
- // immediately whenever the array notifies its mutation
130
- this.synchronizeOptions();
131
- }
132
-
133
- public notify(): void {
134
- const oldValue = this.oldValue;
135
- const newValue = this.currentValue;
136
- if (newValue === oldValue) {
137
- return;
138
- }
139
- this.subs.notify(newValue, oldValue);
140
- }
141
-
142
- public handleEvent(): void {
143
- const shouldNotify = this.synchronizeValue();
144
- if (shouldNotify) {
145
- this.subs.notify(this.currentValue, this.oldValue);
146
- }
147
- }
148
-
149
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
150
- public synchronizeOptions(_indexMap?: IndexMap): void {
151
- this.setElementValue(true);
152
- // const { currentValue, obj } = this;
153
- // // const isArray = Array.isArray(currentValue);
154
- // // const matcher = obj.matcher !== void 0 ? obj.matcher : defaultMatcher;
155
- // // const matcher = defaultMatcher;
156
- // const options = CustomElement.for<MdcSelect>(obj).viewModel.items;
157
- // let i = options.length;
158
-
159
- // while (i-- > 0) {
160
- // // const option = options[i];
161
- // // const optionValue = hasOwn.call(option, 'model') ? option.model : option.value;
162
- // // const optionValue = option.value;
163
- // // if (isArray) {
164
- // // option.selected = (currentValue as unknown[]).findIndex(item => !!matcher(optionValue, item)) !== -1;
165
- // // continue;
166
- // // }
167
- // if (!this.optionsWereSet) {
168
- // this.optionsWereSet = true;
169
- // this.setElementValue(true);
170
- // }
171
- // // option.selected = !!matcher(optionValue, currentValue);
172
- // }
173
- }
174
-
175
- public synchronizeValue(): boolean {
176
- // Spec for synchronizing value from `<select/>` to `SelectObserver`
177
- // When synchronizing value to observed <select/> element, do the following steps:
178
- // A. If `<select/>` is multiple
179
- // 1. Check if current value, called `currentValue` is an array
180
- // a. If not an array, return true to signal value has changed
181
- // b. If is an array:
182
- // i. gather all current selected <option/>, in to array called `values`
183
- // ii. loop through the `currentValue` array and remove items that are nolonger selected based on matcher
184
- // iii. loop through the `values` array and add items that are selected based on matcher
185
- // iv. Return false to signal value hasn't changed
186
- // B. If the select is single
187
- // 1. Let `value` equal the first selected option, if no option selected, then `value` is `null`
188
- // 2. assign `this.currentValue` to `this.oldValue`
189
- // 3. assign `value` to `this.currentValue`
190
- // 4. return `true` to signal value has changed
191
- const obj = this.obj;
192
- const options = CustomElement.for<MdcSelect>(obj).viewModel.items ?? [];
193
- const len = options.length;
194
- // const currentValue = this.currentValue;
195
- let i = 0;
196
-
197
- /*
198
- if (obj.multiple) {
199
- // A.
200
- if (!(currentValue instanceof Array)) {
201
- // A.1.a
202
- return true;
203
- }
204
- // A.1.b
205
- // multi select
206
- let option: IOptionElement;
207
- const matcher = obj.matcher ?? defaultMatcher;
208
- // A.1.b.i
209
- const values: unknown[] = [];
210
- while (i < len) {
211
- option = options[i];
212
- if (option.selected) {
213
- values.push(hasOwn.call(option, 'model')
214
- ? option.model
215
- : option.value
216
- );
217
- }
218
- ++i;
219
- }
220
- // A.1.b.ii
221
- i = 0;
222
- while (i < currentValue.length) {
223
- const a = currentValue[i];
224
- // Todo: remove arrow fn
225
- if (values.findIndex(b => !!matcher(a, b)) === -1) {
226
- currentValue.splice(i, 1);
227
- } else {
228
- ++i;
229
- }
230
- }
231
- // A.1.b.iii
232
- i = 0;
233
- while (i < values.length) {
234
- const a = values[i];
235
- // Todo: remove arrow fn
236
- if (currentValue.findIndex(b => !!matcher(a, b)) === -1) {
237
- currentValue.push(a);
238
- }
239
- ++i;
240
- }
241
- // A.1.b.iv
242
- return false;
243
- }
244
- */
245
- // B. single select
246
- // B.1
247
- let value: unknown = null;
248
- while (i < len) {
249
- const option = options[i];
250
- if (option.value === this.obj.value) {
251
- // value = hasOwn.call(option, 'model') ? option.model : option.value;
252
- value = option.value;
253
- break;
254
- }
255
- ++i;
256
- }
257
- // B.2
258
- this.oldValue = this.currentValue;
259
- // B.3
260
- this.currentValue = value;
261
- // B.4
262
- return true;
263
- }
264
-
265
- private start(): void {
266
- const vm = CustomElement.for<MdcSelect>(this.obj).viewModel;
267
- vm.initialised.then(() => {
268
- (this.nodeObserver = new this.obj.ownerDocument.defaultView!.MutationObserver(records => this.handleNodeChange(records)))
269
- .observe(vm.menu.root, childObserverOptions);
270
- // this.observeArray(this.currentValue instanceof Array ? this.currentValue : null);
271
- this.observing = true;
272
- if (vm.items?.length) {
273
- this.optionsWereSet = true;
274
- this.synchronizeOptions();
275
- }
276
- });
277
- }
278
-
279
- private stop(): void {
280
- this.optionsWereSet = false;
281
- this.nodeObserver?.disconnect();
282
- this.arrayObserver?.unsubscribe(this);
283
- this.nodeObserver
284
- = this.arrayObserver
285
- = void 0;
286
- this.observing = false;
287
- }
288
-
289
- // todo: observe all kind of collection
290
- // private observeArray(array: unknown[] | null): void {
291
- // this.arrayObserver?.unsubscribe(this);
292
- // this.arrayObserver = void 0;
293
- // if (array !== null) {
294
- // if (!this.obj.multiple) {
295
- // throw new Error('Only null or Array instances can be bound to a multi-select.');
296
- // }
297
- // (this.arrayObserver = this.observerLocator.getArrayObserver(array)).subscribe(this);
298
- // }
299
- // }
300
-
301
- public handleNodeChange(records: MutationRecord[]): void {
302
- if (records.find(x => x.type === 'childList'
303
- && (Array.from(x.addedNodes).find(y => (y as HTMLElement).tagName === 'MDC-LIST-ITEM')
304
- || Array.from(x.removedNodes).find(y => (y as HTMLElement).tagName === 'MDC-LIST-ITEM'))
305
- )) {
306
- this.optionsWereSet = true;
307
- this.synchronizeOptions();
308
- const shouldNotify = this.synchronizeValue();
309
- if (shouldNotify) {
310
- this.notify();
311
- }
312
- }
313
- }
314
-
315
- public subscribe(subscriber: ISubscriber): void {
316
- if (this.subs.add(subscriber) && this.subs.count === 1) {
317
- for (const e of this.config.events) {
318
- this.obj.addEventListener(e, this);
319
- }
320
- this.listened = true;
321
- this.start();
322
- }
323
- }
324
-
325
- public unsubscribe(subscriber: ISubscriber): void {
326
- if (this.subs.remove(subscriber) && this.subs.count === 0) {
327
- for (const e of this.config.events) {
328
- this.obj.removeEventListener(e, this);
329
- }
330
- this.listened = false;
331
- this.stop();
332
- }
333
- }
334
-
335
- useConfig(config: INodeObserverConfigBase): void {
336
- this.config = config;
337
- if (this.listened) {
338
- for (const e of this.config.events) {
339
- this.obj.removeEventListener(e, this);
340
- }
341
- for (const e of this.config.events) {
342
- this.obj.addEventListener(e, this);
343
- }
344
- }
345
- }
346
- }
1
+ import {
2
+ subscriberCollection,
3
+ AccessorType,
4
+ } from '@aurelia/runtime';
5
+
6
+ import type {
7
+ ICollectionObserver,
8
+ IndexMap,
9
+ IObserver,
10
+ IObserverLocator,
11
+ ISubscriber,
12
+ ISubscriberCollection,
13
+ } from '@aurelia/runtime';
14
+
15
+ import { INode, CustomElement } from '@aurelia/runtime-html';
16
+ import { IMdcSelectElement, MdcSelect } from './mdc-select';
17
+
18
+ // const hasOwn = Object.prototype.hasOwnProperty;
19
+ const childObserverOptions = {
20
+ childList: true,
21
+ subtree: true,
22
+ characterData: true
23
+ };
24
+
25
+ // function defaultMatcher(a: unknown, b: unknown): boolean {
26
+ // return a === b;
27
+ // }
28
+
29
+ export interface IOptionElement extends HTMLOptionElement {
30
+ model?: unknown;
31
+ }
32
+
33
+ export interface MdcSelectValueObserver extends
34
+ ISubscriberCollection { }
35
+
36
+ export interface INodeObserverConfigBase {
37
+ /**
38
+ * Indicates the list of events can be used to observe a particular property
39
+ */
40
+ readonly events: string[];
41
+ /**
42
+ * Indicates whether this property is readonly, so observer wont attempt to assign value
43
+ * example: input.files
44
+ */
45
+ readonly readonly?: boolean;
46
+ /**
47
+ * A default value to assign to the corresponding property if the incoming value is null/undefined
48
+ */
49
+ readonly default?: unknown;
50
+ }
51
+
52
+
53
+ export interface INodeObserver extends IObserver {
54
+ /**
55
+ * Instruct this node observer event observation behavior
56
+ */
57
+ useConfig(config: INodeObserverConfigBase): void;
58
+ }
59
+
60
+ @subscriberCollection()
61
+ export class MdcSelectValueObserver implements INodeObserver {
62
+ public currentValue: unknown = void 0;
63
+ public oldValue: unknown = void 0;
64
+
65
+ public readonly obj: IMdcSelectElement;
66
+ public config: INodeObserverConfigBase;
67
+
68
+ public hasChanges: boolean = false;
69
+ // ObserverType.Layout is not always true
70
+ // but for simplicity, always treat as such
71
+ public type: AccessorType = (AccessorType.Node | AccessorType.Observer | AccessorType.Layout) as AccessorType;
72
+
73
+ public arrayObserver?: ICollectionObserver<'array'> = void 0;
74
+ public nodeObserver?: MutationObserver = void 0;
75
+
76
+ private observing: boolean = false;
77
+ private listened: boolean = false;
78
+
79
+ public constructor(
80
+ obj: INode,
81
+ // deepscan-disable-next-line
82
+ _key: PropertyKey,
83
+ config: INodeObserverConfigBase,
84
+ _: IObserverLocator
85
+ ) {
86
+ this.obj = obj as unknown as IMdcSelectElement;
87
+ this.config = config;
88
+ }
89
+
90
+ optionsWereSet: boolean;
91
+
92
+ setElementValue(skipNotify: boolean) {
93
+ // do not pass the value to the element if options has never been set
94
+ // the value will be passed on when options do arrive
95
+ if (this.optionsWereSet) {
96
+ CustomElement.for<MdcSelect>(this.obj).viewModel.setValue(this.currentValue, skipNotify);
97
+ }
98
+ }
99
+
100
+ public getValue(): unknown {
101
+ // is it safe to assume the observer has the latest value?
102
+ // todo: ability to turn on/off cache based on type
103
+ return this.observing
104
+ ? this.currentValue
105
+ // : this.obj.multiple
106
+ // ? Array.from(this.obj.options).map(o => o.value)
107
+ : this.obj.value;
108
+ }
109
+
110
+ public setValue(newValue: unknown): void {
111
+ this.currentValue = newValue;
112
+ this.hasChanges = newValue !== this.oldValue;
113
+ // this.observeArray(newValue instanceof Array ? newValue : null);
114
+ if (this.optionsWereSet) {
115
+ this.flushChanges();
116
+ }
117
+ }
118
+
119
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
120
+ public flushChanges(): void {
121
+ if (this.hasChanges) {
122
+ this.hasChanges = false;
123
+ this.synchronizeOptions();
124
+ }
125
+ }
126
+
127
+ public handleCollectionChange(): void {
128
+ // always sync "selected" property of <options/>
129
+ // immediately whenever the array notifies its mutation
130
+ this.synchronizeOptions();
131
+ }
132
+
133
+ public notify(): void {
134
+ const oldValue = this.oldValue;
135
+ const newValue = this.currentValue;
136
+ if (newValue === oldValue) {
137
+ return;
138
+ }
139
+ this.subs.notify(newValue, oldValue);
140
+ }
141
+
142
+ public handleEvent(): void {
143
+ const shouldNotify = this.synchronizeValue();
144
+ if (shouldNotify) {
145
+ this.subs.notify(this.currentValue, this.oldValue);
146
+ }
147
+ }
148
+
149
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
150
+ public synchronizeOptions(_indexMap?: IndexMap): void {
151
+ this.setElementValue(true);
152
+ // const { currentValue, obj } = this;
153
+ // // const isArray = Array.isArray(currentValue);
154
+ // // const matcher = obj.matcher !== void 0 ? obj.matcher : defaultMatcher;
155
+ // // const matcher = defaultMatcher;
156
+ // const options = CustomElement.for<MdcSelect>(obj).viewModel.items;
157
+ // let i = options.length;
158
+
159
+ // while (i-- > 0) {
160
+ // // const option = options[i];
161
+ // // const optionValue = hasOwn.call(option, 'model') ? option.model : option.value;
162
+ // // const optionValue = option.value;
163
+ // // if (isArray) {
164
+ // // option.selected = (currentValue as unknown[]).findIndex(item => !!matcher(optionValue, item)) !== -1;
165
+ // // continue;
166
+ // // }
167
+ // if (!this.optionsWereSet) {
168
+ // this.optionsWereSet = true;
169
+ // this.setElementValue(true);
170
+ // }
171
+ // // option.selected = !!matcher(optionValue, currentValue);
172
+ // }
173
+ }
174
+
175
+ public synchronizeValue(): boolean {
176
+ // Spec for synchronizing value from `<select/>` to `SelectObserver`
177
+ // When synchronizing value to observed <select/> element, do the following steps:
178
+ // A. If `<select/>` is multiple
179
+ // 1. Check if current value, called `currentValue` is an array
180
+ // a. If not an array, return true to signal value has changed
181
+ // b. If is an array:
182
+ // i. gather all current selected <option/>, in to array called `values`
183
+ // ii. loop through the `currentValue` array and remove items that are nolonger selected based on matcher
184
+ // iii. loop through the `values` array and add items that are selected based on matcher
185
+ // iv. Return false to signal value hasn't changed
186
+ // B. If the select is single
187
+ // 1. Let `value` equal the first selected option, if no option selected, then `value` is `null`
188
+ // 2. assign `this.currentValue` to `this.oldValue`
189
+ // 3. assign `value` to `this.currentValue`
190
+ // 4. return `true` to signal value has changed
191
+ const obj = this.obj;
192
+ const options = CustomElement.for<MdcSelect>(obj).viewModel.items ?? [];
193
+ const len = options.length;
194
+ // const currentValue = this.currentValue;
195
+ let i = 0;
196
+
197
+ /*
198
+ if (obj.multiple) {
199
+ // A.
200
+ if (!(currentValue instanceof Array)) {
201
+ // A.1.a
202
+ return true;
203
+ }
204
+ // A.1.b
205
+ // multi select
206
+ let option: IOptionElement;
207
+ const matcher = obj.matcher ?? defaultMatcher;
208
+ // A.1.b.i
209
+ const values: unknown[] = [];
210
+ while (i < len) {
211
+ option = options[i];
212
+ if (option.selected) {
213
+ values.push(hasOwn.call(option, 'model')
214
+ ? option.model
215
+ : option.value
216
+ );
217
+ }
218
+ ++i;
219
+ }
220
+ // A.1.b.ii
221
+ i = 0;
222
+ while (i < currentValue.length) {
223
+ const a = currentValue[i];
224
+ // Todo: remove arrow fn
225
+ if (values.findIndex(b => !!matcher(a, b)) === -1) {
226
+ currentValue.splice(i, 1);
227
+ } else {
228
+ ++i;
229
+ }
230
+ }
231
+ // A.1.b.iii
232
+ i = 0;
233
+ while (i < values.length) {
234
+ const a = values[i];
235
+ // Todo: remove arrow fn
236
+ if (currentValue.findIndex(b => !!matcher(a, b)) === -1) {
237
+ currentValue.push(a);
238
+ }
239
+ ++i;
240
+ }
241
+ // A.1.b.iv
242
+ return false;
243
+ }
244
+ */
245
+ // B. single select
246
+ // B.1
247
+ let value: unknown = null;
248
+ while (i < len) {
249
+ const option = options[i];
250
+ if (option.value === this.obj.value) {
251
+ // value = hasOwn.call(option, 'model') ? option.model : option.value;
252
+ value = option.value;
253
+ break;
254
+ }
255
+ ++i;
256
+ }
257
+ // B.2
258
+ this.oldValue = this.currentValue;
259
+ // B.3
260
+ this.currentValue = value;
261
+ // B.4
262
+ return true;
263
+ }
264
+
265
+ private start(): void {
266
+ const vm = CustomElement.for<MdcSelect>(this.obj).viewModel;
267
+ vm.initialised.then(() => {
268
+ (this.nodeObserver = new this.obj.ownerDocument.defaultView!.MutationObserver(records => this.handleNodeChange(records)))
269
+ .observe(vm.menu.root, childObserverOptions);
270
+ // this.observeArray(this.currentValue instanceof Array ? this.currentValue : null);
271
+ this.observing = true;
272
+ if (vm.items?.length) {
273
+ this.optionsWereSet = true;
274
+ this.synchronizeOptions();
275
+ }
276
+ });
277
+ }
278
+
279
+ private stop(): void {
280
+ this.optionsWereSet = false;
281
+ this.nodeObserver?.disconnect();
282
+ this.arrayObserver?.unsubscribe(this);
283
+ this.nodeObserver
284
+ = this.arrayObserver
285
+ = void 0;
286
+ this.observing = false;
287
+ }
288
+
289
+ // todo: observe all kind of collection
290
+ // private observeArray(array: unknown[] | null): void {
291
+ // this.arrayObserver?.unsubscribe(this);
292
+ // this.arrayObserver = void 0;
293
+ // if (array !== null) {
294
+ // if (!this.obj.multiple) {
295
+ // throw new Error('Only null or Array instances can be bound to a multi-select.');
296
+ // }
297
+ // (this.arrayObserver = this.observerLocator.getArrayObserver(array)).subscribe(this);
298
+ // }
299
+ // }
300
+
301
+ public handleNodeChange(records: MutationRecord[]): void {
302
+ if (records.find(x => x.type === 'childList'
303
+ && (Array.from(x.addedNodes).find(y => (y as HTMLElement).tagName === 'MDC-LIST-ITEM')
304
+ || Array.from(x.removedNodes).find(y => (y as HTMLElement).tagName === 'MDC-LIST-ITEM'))
305
+ )) {
306
+ this.optionsWereSet = true;
307
+ this.synchronizeOptions();
308
+ const shouldNotify = this.synchronizeValue();
309
+ if (shouldNotify) {
310
+ this.notify();
311
+ }
312
+ }
313
+ }
314
+
315
+ public subscribe(subscriber: ISubscriber): void {
316
+ if (this.subs.add(subscriber) && this.subs.count === 1) {
317
+ for (const e of this.config.events) {
318
+ this.obj.addEventListener(e, this);
319
+ }
320
+ this.listened = true;
321
+ this.start();
322
+ }
323
+ }
324
+
325
+ public unsubscribe(subscriber: ISubscriber): void {
326
+ if (this.subs.remove(subscriber) && this.subs.count === 0) {
327
+ for (const e of this.config.events) {
328
+ this.obj.removeEventListener(e, this);
329
+ }
330
+ this.listened = false;
331
+ this.stop();
332
+ }
333
+ }
334
+
335
+ useConfig(config: INodeObserverConfigBase): void {
336
+ this.config = config;
337
+ if (this.listened) {
338
+ for (const e of this.config.events) {
339
+ this.obj.removeEventListener(e, this);
340
+ }
341
+ for (const e of this.config.events) {
342
+ this.obj.addEventListener(e, this);
343
+ }
344
+ }
345
+ }
346
+ }