@twobirds/microcomponents 0.1.16 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MC.ts +345 -346
- package/dist/elements.ts +80 -96
- package/dist/formValues.ts +165 -171
- package/dist/helpers.ts +100 -100
- package/dist/observables.ts +295 -325
- package/package.json +4 -3
- package/dist/MC.d.ts +0 -39
- package/dist/MC.d.ts.map +0 -1
- package/dist/MC.js +0 -302
- package/dist/MC.min.js +0 -345
- package/dist/elements.d.ts +0 -5
- package/dist/elements.d.ts.map +0 -1
- package/dist/elements.js +0 -67
- package/dist/elements.min.js +0 -1
- package/dist/formValues.d.ts +0 -3
- package/dist/formValues.d.ts.map +0 -1
- package/dist/formValues.js +0 -159
- package/dist/formValues.min.js +0 -1
- package/dist/helpers.d.ts +0 -14
- package/dist/helpers.d.ts.map +0 -1
- package/dist/helpers.js +0 -111
- package/dist/microcomponents.d.ts +0 -6
- package/dist/microcomponents.d.ts.map +0 -1
- package/dist/microcomponents.js +0 -6
- package/dist/microcomponents.min.js +0 -1
- package/dist/observables.d.ts +0 -11
- package/dist/observables.d.ts.map +0 -1
- package/dist/observables.js +0 -234
- package/dist/observables.min.js +0 -1
package/dist/observables.ts
CHANGED
|
@@ -5,169 +5,159 @@ import { LooseObject, debounce, deepEqual, flattenObject, copyGettersSetters } f
|
|
|
5
5
|
import { DC, HTMLMcElement, trigger } from './MC.js';
|
|
6
6
|
|
|
7
7
|
function isObservableObject(value: any): boolean {
|
|
8
|
-
|
|
8
|
+
return value != null && typeof value === 'object';
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
type Callback = (value: any) => void;
|
|
12
12
|
|
|
13
13
|
function getPlaceholders(target: HTMLElement): string[] {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// extract {} and return result
|
|
42
|
-
return [...placeholders].map((placeholder) => placeholder.replace(/[\{\}]/g, ''));
|
|
14
|
+
let placeholders: Set<string> = new Set(),
|
|
15
|
+
regEx = /\{[^\{\}]*\}/g;
|
|
16
|
+
|
|
17
|
+
// scan attributes
|
|
18
|
+
(target.getAttributeNames ? target.getAttributeNames() : [])
|
|
19
|
+
.filter((attr) => target.getAttribute(attr)?.match(regEx)) // extract placeholder(s)
|
|
20
|
+
.forEach((attr) => {
|
|
21
|
+
let placeholders: Set<string> = new Set(target.getAttribute(attr)?.match(regEx));
|
|
22
|
+
placeholders.forEach((placeholder) => placeholders.add(placeholder.replace(/[\{\}]/g, '')));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// scan children text nodes
|
|
26
|
+
[...target.childNodes]
|
|
27
|
+
.filter((childNode) => {
|
|
28
|
+
return (
|
|
29
|
+
// is text node and has placeholders
|
|
30
|
+
childNode.nodeType === 3 && ((childNode as any).nodeValue || '').match(regEx)
|
|
31
|
+
);
|
|
32
|
+
})
|
|
33
|
+
.forEach((childNode) => {
|
|
34
|
+
((childNode as any).nodeValue || '').match(regEx).forEach((placeholder: string) => {
|
|
35
|
+
placeholders.add(placeholder.replace(/[\{\}]/g, ''));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// extract {} and return result
|
|
40
|
+
return [...placeholders].map((placeholder) => placeholder.replace(/[\{\}]/g, ''));
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
const inputs = [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement];
|
|
46
44
|
|
|
47
45
|
class Placeholders extends DC {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
Object.keys(ev.detail.data).forEach((key) => {
|
|
139
|
-
if (this.data.hasOwnProperty(key)) data[key] = ev.detail.data[key];
|
|
140
|
-
});
|
|
141
|
-
//console.log( 'Placeholder onData', ev, data );
|
|
142
|
-
if (JSON.stringify(data) !== JSON.stringify(this.data)) Object.assign(this.data, data); // will trigger callbacks
|
|
143
|
-
}
|
|
46
|
+
data: LooseObject = {};
|
|
47
|
+
oldDisplay?: string = '';
|
|
48
|
+
|
|
49
|
+
constructor(target: HTMLElement) {
|
|
50
|
+
super(target);
|
|
51
|
+
getPlaceholders(target).forEach((property) => (this.data[property] = ''));
|
|
52
|
+
observe(this);
|
|
53
|
+
this.#attachCallbacks();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#attachCallbacks() {
|
|
57
|
+
let target = this.target,
|
|
58
|
+
hide: boolean = false;
|
|
59
|
+
|
|
60
|
+
// scan attributes
|
|
61
|
+
(target.getAttributeNames ? target.getAttributeNames() : [])
|
|
62
|
+
.filter((attr: string) => target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)) // extract placeholder(s)
|
|
63
|
+
.forEach((attr: string) => {
|
|
64
|
+
let placeholders: Set<string> = new Set(target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g));
|
|
65
|
+
// attach callback
|
|
66
|
+
this.data.observe(
|
|
67
|
+
((template: string) => (data: LooseObject) => {
|
|
68
|
+
let result: string = template;
|
|
69
|
+
placeholders.forEach((placeholder) => {
|
|
70
|
+
result = result.replace(
|
|
71
|
+
placeholder,
|
|
72
|
+
// JSON.stringify(data[placeholder.replace(/[\{\}]/g, '')])
|
|
73
|
+
data[placeholder.replace(/[\{\}]/g, '')]
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
target.setAttribute(attr, result);
|
|
77
|
+
})(target.getAttribute(attr))
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// scan children text nodes
|
|
82
|
+
[...target.childNodes]
|
|
83
|
+
.filter((childNode) => {
|
|
84
|
+
return (
|
|
85
|
+
// is text node and has placeholders
|
|
86
|
+
childNode.nodeType === 3 && ((childNode as Node).nodeValue || '').match(/\{[^\{\}]*\}/g)
|
|
87
|
+
);
|
|
88
|
+
})
|
|
89
|
+
.forEach((childNode) => {
|
|
90
|
+
hide = true;
|
|
91
|
+
let placeholders: Set<string> = new Set(childNode.nodeValue.match(/\{[^\{\}]*\}/g));
|
|
92
|
+
|
|
93
|
+
// attach callback
|
|
94
|
+
this.data.observe(
|
|
95
|
+
((template: string) => (data: LooseObject) => {
|
|
96
|
+
let result: string = template;
|
|
97
|
+
placeholders.forEach((placeholder) => {
|
|
98
|
+
result = result.replace(
|
|
99
|
+
placeholder,
|
|
100
|
+
// JSON.stringify(data[placeholder.replace(/[\{\}]/g, '')])
|
|
101
|
+
data[placeholder.replace(/[\{\}]/g, '')]
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (this.oldDisplay) {
|
|
106
|
+
target.style = this.oldDisplay;
|
|
107
|
+
} else {
|
|
108
|
+
target.removeAttribute('style');
|
|
109
|
+
}
|
|
110
|
+
delete this.oldDisplay;
|
|
111
|
+
|
|
112
|
+
childNode.nodeValue = result;
|
|
113
|
+
})(childNode.nodeValue)
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
// hide for now
|
|
117
|
+
this.oldDisplay = target.getAttribute('style') || ''; // TBD allow null to indicate there was no old style attribute
|
|
118
|
+
|
|
119
|
+
if (
|
|
120
|
+
hide &&
|
|
121
|
+
!inputs.includes((target as any).constructor) &&
|
|
122
|
+
target.tagName !== 'FIELDSET'
|
|
123
|
+
) {
|
|
124
|
+
target.style.display = 'none';
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
onData(ev: CustomEvent) {
|
|
130
|
+
let data: LooseObject = {};
|
|
131
|
+
Object.keys(ev.detail.data).forEach((key) => {
|
|
132
|
+
if (this.data.hasOwnProperty(key)) data[key] = ev.detail.data[key];
|
|
133
|
+
});
|
|
134
|
+
if (JSON.stringify(data) !== JSON.stringify(this.data)) Object.assign(this.data, data); // will trigger callbacks
|
|
135
|
+
}
|
|
144
136
|
}
|
|
145
137
|
|
|
146
138
|
function getPlaceholderElements(
|
|
147
|
-
|
|
139
|
+
target: HTMLElement | DocumentFragment | ShadowRoot
|
|
148
140
|
): HTMLElement[] {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return elements as HTMLElement[];
|
|
141
|
+
let elements: Array<Node> = [target]
|
|
142
|
+
.concat([...(target.querySelectorAll('*') as unknown as HTMLElement[])])
|
|
143
|
+
.filter((e) => !!getPlaceholders(e as HTMLElement).length)
|
|
144
|
+
.filter((e) => (e as HTMLElement)?.tagName !== 'STYLE')
|
|
145
|
+
.reverse(); // to start with inner elements
|
|
146
|
+
return elements as HTMLElement[];
|
|
156
147
|
}
|
|
157
148
|
|
|
158
149
|
function makePlaceholders(element: HTMLElement | DocumentFragment | ShadowRoot): void {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
});
|
|
150
|
+
getPlaceholderElements(element).forEach((e: HTMLElement) => {
|
|
151
|
+
if ((e as HTMLMcElement)?._mc?._placeholders) return;
|
|
152
|
+
DC.add(e, '_placeholders', new Placeholders(e));
|
|
153
|
+
});
|
|
164
154
|
}
|
|
165
155
|
|
|
166
156
|
export type Observable = {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
157
|
+
observe: (cb: Callback) => void;
|
|
158
|
+
notify: () => void;
|
|
159
|
+
bind: (target: HTMLElement | DocumentFragment | ShadowRoot) => void;
|
|
160
|
+
callbacks: Array<Function>;
|
|
171
161
|
};
|
|
172
162
|
|
|
173
163
|
type Class<T> = new (...args: any[]) => T;
|
|
@@ -177,192 +167,172 @@ const classRepo: LooseObject = {};
|
|
|
177
167
|
|
|
178
168
|
// creates a new observable class wrapper
|
|
179
169
|
function makeObservable(val: any): Class<typeof val> {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
(classRepo as any)[ConstructorName] = ObservableClass;
|
|
270
|
-
|
|
271
|
-
// console.log( 'classRepo:', classRepo );
|
|
272
|
-
|
|
273
|
-
return ObservableClass;
|
|
170
|
+
const Constructor = val.constructor,
|
|
171
|
+
ConstructorName: string = Constructor.name;
|
|
172
|
+
|
|
173
|
+
let ObservableClass = class extends Constructor {
|
|
174
|
+
#notify: boolean = true;
|
|
175
|
+
#callbacks: Array<Function> = [];
|
|
176
|
+
|
|
177
|
+
constructor(val: any) {
|
|
178
|
+
super(val);
|
|
179
|
+
(this.constructor as LooseObject).callbacks = [];
|
|
180
|
+
if (isObservableObject(val)) {
|
|
181
|
+
// you cannot bind native values to the dom
|
|
182
|
+
Object.getOwnPropertyNames(val).forEach((key) => {
|
|
183
|
+
this[key] = val[key];
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
get callbacks(): Array<Function> {
|
|
189
|
+
return this.#callbacks;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
set callbacks(callbacks: Array<Function>) {
|
|
193
|
+
this.#callbacks = callbacks;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
observe(callback: Function) {
|
|
197
|
+
this.#callbacks.push(callback);
|
|
198
|
+
return this;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
bind(target: HTMLElement | DocumentFragment | ShadowRoot) {
|
|
202
|
+
const iso = isObservableObject(this.valueOf());
|
|
203
|
+
|
|
204
|
+
if (iso) {
|
|
205
|
+
makePlaceholders(target);
|
|
206
|
+
const placeholders: unknown = [target, ...target.querySelectorAll('[data-mc]')].filter(
|
|
207
|
+
(e) => !!(e as LooseObject)?._mc?._placeholders
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
const func = function callback(data: LooseObject) {
|
|
211
|
+
// avoid bubbling for speed
|
|
212
|
+
let flattenedData = flattenObject(data);
|
|
213
|
+
(placeholders as Node[]).forEach((node) => {
|
|
214
|
+
// console.log('trigger callback', e);
|
|
215
|
+
if (!node) return;
|
|
216
|
+
trigger(node as HTMLMcElement, 'data', flattenedData);
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
(this as any).#callbacks.push(func);
|
|
220
|
+
this.notify();
|
|
221
|
+
} else {
|
|
222
|
+
console.warn(
|
|
223
|
+
'IGNORED - cannot bind a non-Object to the dom, IS:',
|
|
224
|
+
typeof this.valueOf(),
|
|
225
|
+
this
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return this;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
notify(notify?: boolean) {
|
|
233
|
+
let data =
|
|
234
|
+
isObservableObject(this.valueOf()) && this.valueOf() instanceof Array === false
|
|
235
|
+
? structuredClone(Object.assign({}, this))
|
|
236
|
+
: this.valueOf();
|
|
237
|
+
|
|
238
|
+
if (notify !== undefined) {
|
|
239
|
+
this.#notify = notify;
|
|
240
|
+
// return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (this.#notify) {
|
|
244
|
+
(this as any).#callbacks.forEach((f: Function) => {
|
|
245
|
+
f(data);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return this;
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
(classRepo as any)[ConstructorName] = ObservableClass;
|
|
254
|
+
|
|
255
|
+
return ObservableClass;
|
|
274
256
|
}
|
|
275
257
|
|
|
276
258
|
function getConstructor(val: any): Class<typeof val> {
|
|
277
|
-
|
|
278
|
-
|
|
259
|
+
let key: string = val.constructor.name;
|
|
260
|
+
return classRepo[key] || makeObservable(val);
|
|
279
261
|
}
|
|
280
262
|
|
|
281
263
|
export const observe = (target: LooseObject, propertyName?: string): LooseObject => {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
o,
|
|
357
|
-
'- CANNOT BECOME:',
|
|
358
|
-
typeof val
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
},
|
|
362
|
-
});
|
|
363
|
-
target[key] = val; // replace old property with proxy (observable)
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
return target;
|
|
264
|
+
let keys = !propertyName ? [...Object.getOwnPropertyNames(target)] : [propertyName];
|
|
265
|
+
|
|
266
|
+
keys.forEach((key) => {
|
|
267
|
+
if (
|
|
268
|
+
target.hasOwnProperty(key) &&
|
|
269
|
+
typeof target[key] !== 'function' &&
|
|
270
|
+
!target?.[key]?.constructor?.prototype?.observe
|
|
271
|
+
) {
|
|
272
|
+
if (key[0] === '_' || target?.[key] === undefined) return target;
|
|
273
|
+
let val: any = target[key];
|
|
274
|
+
|
|
275
|
+
let o = new (getConstructor(val) as Class<typeof val>)(val);
|
|
276
|
+
|
|
277
|
+
let debouncedNotify: Function = debounce(function debouncedNotify() {
|
|
278
|
+
o.notify();
|
|
279
|
+
}, 0);
|
|
280
|
+
|
|
281
|
+
Object.defineProperty(target, key, {
|
|
282
|
+
enumerable: true,
|
|
283
|
+
get() {
|
|
284
|
+
if (isObservableObject(o.valueOf())) {
|
|
285
|
+
let check = structuredClone(Object.assign({}, o));
|
|
286
|
+
setTimeout(function checkChanges() {
|
|
287
|
+
let state = structuredClone(Object.assign({}, o));
|
|
288
|
+
if (!deepEqual(state, check)) {
|
|
289
|
+
debouncedNotify();
|
|
290
|
+
}
|
|
291
|
+
}, 0);
|
|
292
|
+
}
|
|
293
|
+
return o;
|
|
294
|
+
},
|
|
295
|
+
set(val: any) {
|
|
296
|
+
if (typeof val === typeof o.valueOf()) {
|
|
297
|
+
let iso = isObservableObject(o.valueOf()) && o.valueOf() instanceof Array === false;
|
|
298
|
+
if (iso) {
|
|
299
|
+
// is observable object
|
|
300
|
+
if (o?.constructor?.prototype?.observe === undefined) {
|
|
301
|
+
// not observed yet
|
|
302
|
+
o = new (getConstructor(val) as Class<typeof val>)(
|
|
303
|
+
structuredClone(Object.assign({}, val))
|
|
304
|
+
);
|
|
305
|
+
copyGettersSetters(val, o);
|
|
306
|
+
//o.seal();
|
|
307
|
+
}
|
|
308
|
+
Object.assign(o, val); // mixin set object into observable object
|
|
309
|
+
o.notify(); // dont test, just assume "changed" status
|
|
310
|
+
} else {
|
|
311
|
+
// simple native var
|
|
312
|
+
let old = o.valueOf(),
|
|
313
|
+
callbacks = (o as Observable).callbacks;
|
|
314
|
+
|
|
315
|
+
if (val !== old) {
|
|
316
|
+
o = new (getConstructor(val) as Class<typeof val>)(val);
|
|
317
|
+
(o as Observable).callbacks = callbacks;
|
|
318
|
+
debouncedNotify();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
// set type is not stored type
|
|
323
|
+
console.warn(
|
|
324
|
+
'IGNORED - cannot change observable types, IS:',
|
|
325
|
+
typeof o.valueOf(),
|
|
326
|
+
o,
|
|
327
|
+
'- CANNOT BECOME:',
|
|
328
|
+
typeof val
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
target[key] = val; // replace old property with proxy (observable)
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
return target;
|
|
368
338
|
};
|