@twobirds/microcomponents 0.0.33 → 0.0.37

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 (118) hide show
  1. package/README.md +40 -27
  2. package/assets/documentation/{MicroComponents.md → MC.md} +17 -17
  3. package/assets/documentation/comparision.md +0 -0
  4. package/assets/documentation/elements.md +276 -0
  5. package/assets/documentation/magic.md +10 -68
  6. package/dist/MC.d.ts +2 -3
  7. package/dist/MC.d.ts.map +1 -1
  8. package/dist/MC.min.js +45 -43
  9. package/dist/MC.ts +173 -175
  10. package/dist/autoloader.ts +1 -1
  11. package/dist/{customElements.d.ts → elements.d.ts} +1 -1
  12. package/dist/elements.d.ts.map +1 -0
  13. package/dist/elements.min.js +1 -0
  14. package/dist/{customElements.ts → elements.ts} +23 -14
  15. package/dist/helpers.d.ts +6 -4
  16. package/dist/helpers.d.ts.map +1 -1
  17. package/dist/helpers.ts +95 -128
  18. package/dist/microcomponents.d.ts +3 -3
  19. package/dist/microcomponents.d.ts.map +1 -1
  20. package/dist/microcomponents.min.js +1 -1
  21. package/dist/microcomponents.ts +3 -3
  22. package/dist/{customObservables.d.ts → observables.d.ts} +3 -3
  23. package/dist/observables.d.ts.map +1 -0
  24. package/dist/observables.min.js +1 -0
  25. package/dist/observables.ts +354 -0
  26. package/dist/{customSelectors.d.ts → selectors.d.ts} +1 -1
  27. package/dist/selectors.d.ts.map +1 -0
  28. package/dist/selectors.min.js +1 -0
  29. package/dist/test.ts +133 -157
  30. package/klemmstein.png +0 -0
  31. package/package.json +52 -52
  32. package/public/MC.js +46 -44
  33. package/public/MC.js.map +1 -1
  34. package/public/MC.min.js +45 -43
  35. package/public/assets/search.js +1 -1
  36. package/public/autoloader.js +1 -1
  37. package/public/autoloader.js.map +1 -1
  38. package/public/classes/{DC.html → MC.DC.html} +60 -59
  39. package/public/classes/{MC.html → MC.MC.html} +41 -35
  40. package/public/classes/{McBase.html → MC.McBase.html} +28 -20
  41. package/public/classes/{McEvent.html → MC.McEvent.html} +48 -42
  42. package/public/documentation/{MicroComponents.md → MC.md} +17 -17
  43. package/public/documentation/comparision.md +0 -0
  44. package/public/documentation/elements.md +276 -0
  45. package/public/documentation/magic.md +10 -68
  46. package/public/{customElements.js → elements.js} +9 -10
  47. package/public/elements.js.map +1 -0
  48. package/public/elements.min.js +1 -0
  49. package/public/functions/{addListener.html → MC.addListener.html} +18 -12
  50. package/public/functions/{removeListener.html → MC.removeListener.html} +18 -12
  51. package/public/functions/elements.defineCE.html +78 -0
  52. package/public/functions/elements.getCE.html +63 -0
  53. package/public/functions/formValues.formValues.html +68 -0
  54. package/public/functions/observables.observe.html +65 -0
  55. package/public/functions/selectors._d.html +69 -0
  56. package/public/functions/selectors._t.html +69 -0
  57. package/public/helpers.js +66 -89
  58. package/public/helpers.js.map +1 -1
  59. package/public/index.html +48 -33
  60. package/public/interfaces/{HTMLMcElement.html → MC.HTMLMcElement.html} +601 -595
  61. package/public/interfaces/selectors.DSelector.html +1013 -0
  62. package/public/interfaces/selectors.TSelector.html +712 -0
  63. package/public/microcomponents.js +3 -3
  64. package/public/microcomponents.js.map +1 -1
  65. package/public/microcomponents.min.js +1 -1
  66. package/public/modules/MC.html +78 -0
  67. package/public/modules/elements.html +62 -0
  68. package/public/modules/formValues.html +60 -0
  69. package/public/modules/observables.html +65 -0
  70. package/public/modules/selectors.html +76 -0
  71. package/public/modules.html +11 -23
  72. package/public/observables.js +255 -0
  73. package/public/observables.js.map +1 -0
  74. package/public/observables.min.js +1 -0
  75. package/public/{customSelectors.js → selectors.js} +1 -1
  76. package/public/selectors.js.map +1 -0
  77. package/public/selectors.min.js +1 -0
  78. package/public/src/MC.ts +376 -0
  79. package/public/src/McEvent.ts +96 -0
  80. package/public/src/autoloader.ts +98 -0
  81. package/{src/customElements.ts → public/src/elements.ts} +23 -14
  82. package/public/src/formValues.ts +275 -0
  83. package/public/src/helpers.ts +140 -0
  84. package/public/src/microcomponents.ts +8 -0
  85. package/public/src/observables.ts +354 -0
  86. package/public/src/test.ts +187 -0
  87. package/public/test.js +99 -115
  88. package/public/test.js.map +1 -1
  89. package/public/types/observables.Observable.html +91 -0
  90. package/public/types/selectors.selection.html +58 -0
  91. package/public/types/selectors.singleSelector.html +58 -0
  92. package/src/MC.ts +173 -175
  93. package/src/autoloader.ts +1 -1
  94. package/src/elements.ts +76 -0
  95. package/src/helpers.ts +95 -128
  96. package/src/microcomponents.ts +3 -3
  97. package/src/observables.ts +354 -0
  98. package/src/selectors.ts +1634 -0
  99. package/src/test.ts +133 -157
  100. package/typedoc.json +1 -1
  101. package/webpack.config.js +9 -9
  102. package/dist/customElements.d.ts.map +0 -1
  103. package/dist/customElements.min.js +0 -1
  104. package/dist/customObservables.d.ts.map +0 -1
  105. package/dist/customObservables.min.js +0 -1
  106. package/dist/customObservables.ts +0 -348
  107. package/dist/customSelectors.d.ts.map +0 -1
  108. package/dist/customSelectors.min.js +0 -1
  109. package/public/customElements.js.map +0 -1
  110. package/public/customElements.min.js +0 -1
  111. package/public/customObservables.js +0 -256
  112. package/public/customObservables.js.map +0 -1
  113. package/public/customObservables.min.js +0 -1
  114. package/public/customSelectors.js.map +0 -1
  115. package/public/customSelectors.min.js +0 -1
  116. package/src/customObservables.ts +0 -348
  117. /package/dist/{customSelectors.ts → selectors.ts} +0 -0
  118. /package/{src/customSelectors.ts → public/src/selectors.ts} +0 -0
package/src/helpers.ts CHANGED
@@ -1,173 +1,140 @@
1
- "use strict";
2
-
3
- export function isObject( value: any ): boolean {
4
- return value != null && typeof value === 'object';
5
- }
1
+ 'use strict';
6
2
 
7
3
  export interface LooseObject {
8
4
  [key: string | symbol]: any;
9
5
  }
10
6
 
11
- export function kebabToPascal(str: string) {
12
- return str
13
- .split('-') // Split by hyphens
14
- .map(word => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize each part
15
- .join(''); // Join without spaces
7
+ export function isNativeObject(value: any): boolean {
8
+ return value && value['constructor'] && value.constructor === Object;
16
9
  }
17
10
 
18
- export function debounce( func: Function, milliseconds: number ): Function {
19
- let timeout: any;
20
- return () => {
11
+ export function sortObject(o: LooseObject): LooseObject {
12
+ let result: LooseObject = {},
13
+ keys = [...Object.keys(o)].sort();
21
14
 
22
- clearTimeout( timeout );
15
+ keys.forEach((key) => {
16
+ if (isNativeObject(o[key])) {
17
+ result[key] = sortObject(o[key]);
18
+ } else {
19
+ result[key] = o[key];
20
+ }
21
+ });
23
22
 
24
- timeout = setTimeout(
25
- function(){
26
- func( ...arguments );
27
- },
28
- milliseconds
29
- );
30
- };
31
- };
23
+ return result;
24
+ }
32
25
 
33
- export function deepEqual( o1: any, o2:any): boolean {
34
- const k1 = Object.keys(o1);
35
- const k2 = Object.keys(o2);
36
- if (k1.length !== k2.length) {
37
- return false;
38
- }
39
- for (const key of k1) {
40
- const
41
- v1 = o1[key],
42
- v2 = o2[key],
43
- recurse = isObject(v1) && isObject(v2);
44
- ;
26
+ export function flattenObject(
27
+ o: LooseObject,
28
+ doSort: boolean = true
29
+ ): LooseObject {
30
+ let result: LooseObject = {};
31
+
32
+ [...Object.getOwnPropertyNames(o)].forEach((propName) => {
45
33
  if (
46
- ( recurse && !deepEqual(v1, v2) )
47
- || (!recurse && v1 !== v2)
34
+ o[propName] &&
35
+ o[propName]['constructor'] &&
36
+ o[propName].constructor === Object
48
37
  ) {
49
- return false;
38
+ const temp = flattenObject(o[propName], false);
39
+ for (const j in temp) {
40
+ result[propName + '.' + j] = temp[j];
41
+ }
42
+ } else {
43
+ result[propName] = o[propName];
50
44
  }
51
- }
52
- return true;
53
- }
54
-
55
- export function nameSpace( ns: string, obj: LooseObject, val: any = null, orig?: any ): any {
56
- let leftOver: Array<any> = ns.split('.');
57
-
58
- if ( !orig ){
59
- orig = obj;
60
- }
61
-
62
- // console.log( 'start', ns, obj, val, leftOver );
45
+ });
63
46
 
64
- let
65
- last: string = leftOver.shift(), // this property name
66
- lns: string = leftOver.join('.') // the leftover namespace
67
- ;
68
-
69
- if ( val !== null && last.length && obj[last] === undefined ){ // extend if val given and ns leftover...
70
- // console.log( 'add prop', last );
71
- obj[last] = {};
72
- }
47
+ return doSort ? sortObject(result) : result;
48
+ }
73
49
 
74
- let
75
- lob: any = obj[last] // the leftover value or obj
76
- ;
50
+ export function deepEqual(o1: LooseObject, o2: LooseObject): boolean {
51
+ return (
52
+ JSON.stringify(flattenObject(o1)) === JSON.stringify(flattenObject(o2))
53
+ );
54
+ }
77
55
 
78
- // console.log( 'lob', lob, 'last:', last, 'lns:', lns, 'obj:', obj );
56
+ export function nameSpace(ns: string | string[], obj: LooseObject = {}): any {
57
+ let nsa = ns.constructor === String ? ns.split('.') : ns;
79
58
 
80
- if ( lns.length === 0 ){ // this should be the value to set or get
81
- if ( val !== null ){
82
- obj[last] = val;
83
- return orig;
84
- }
85
- return obj[last];
59
+ if (!obj || !nsa[0] || !obj[nsa[0]]) {
60
+ console.warn('ns', nsa[0], 'not in', obj);
61
+ return;
86
62
  }
87
-
88
- if ( isObject( obj[last] ) ){
89
- return nameSpace( lns, obj[last], val, orig );
90
- } else {
91
- if (val){
92
- return orig;
93
- }
94
-
95
- return lob[last];
63
+ if (obj[nsa[0]].constructor === Object && nsa.length > 1) {
64
+ return nameSpace((nsa as string[]).splice(1), obj[nsa[0]]);
96
65
  }
97
-
66
+ return obj[nsa[0]];
98
67
  }
99
68
 
100
- export function parse( what: string | Object | any[], parseThis: Object ){
69
+ export function parse(what: string | Object | any[], parseThis: Object) {
101
70
  var args = Array.from(arguments);
102
71
 
103
- if (!args.length){
104
- console.error('no arguments give to parse');
105
- return;
106
- }
107
-
108
- if (args.length === 1){
109
- return args[1];
110
- } else if (args.length > 2) {
111
- while (args.length > 1){
112
- args[0] = parse( args[0], args[1]);
72
+ if (args.length > 2) {
73
+ while (args.length > 1) {
74
+ args[0] = parse(args[0], args[1]);
113
75
  args.splice(1, 1);
114
76
  }
115
77
  return args[0];
116
78
  }
117
79
 
118
- // implicit else: exactly 2 arguments
119
- if ( typeof what === 'string' ){
120
- var vars = what.match( /\{[^\{\}]*\}/g );
121
-
122
- if ( !!vars ) {
123
- vars
124
- .forEach(
125
- function (pPropname) {
126
- var propname = pPropname.substr(1, pPropname.length - 2),
127
- value = nameSpace( propname, parseThis );
128
-
129
- if ( typeof value !== 'undefined' ){
130
- what = (what as string).replace( pPropname, value );
131
- }
132
- }
133
- );
134
- }
135
- } else if ( isObject(what) ){
136
- switch ( what.constructor ){
80
+ if (typeof what === 'string') {
81
+ what.match(/\{[^\{\}]*\}/g)?.forEach(function (pPropname) {
82
+ var propname = pPropname.substring(1, pPropname.length - 1),
83
+ value = nameSpace(propname, parseThis);
84
+ //console.log(propname, value);
85
+ if (typeof value !== 'undefined') {
86
+ what = (what as string).replace(pPropname, value);
87
+ }
88
+ });
89
+ } else if (isNativeObject(what)) {
90
+ switch (what.constructor) {
137
91
  case Object:
138
- Object
139
- .keys( what )
140
- .forEach(
141
- function( pKey ){
142
- if ( what.hasOwnProperty( pKey ) ){
143
- ( what as LooseObject )[ pKey ] = parse( ( what as LooseObject )[ pKey ], parseThis );
144
- }
145
- }
146
- );
92
+ Object.keys(what).forEach(function (pKey) {
93
+ if (what.hasOwnProperty(pKey)) {
94
+ (what as LooseObject)[pKey] = parse(
95
+ (what as LooseObject)[pKey],
96
+ parseThis
97
+ );
98
+ }
99
+ });
147
100
  break;
148
101
  case Array:
149
- ( what as Array<any> )
150
- .forEach(
151
- function( pValue, pKey, original ){
152
- original[ pKey ] = parse( (what as any)[ pKey ], parseThis );
153
- }
154
- );
102
+ (what as Array<any>).forEach(function (pValue, pKey, original) {
103
+ original[pKey] = parse((what as any)[pKey], parseThis);
104
+ });
155
105
  break;
156
106
  }
157
107
  }
158
108
 
159
109
  return what;
160
- };
110
+ }
111
+
112
+ export function kebabToPascal(str: string) {
113
+ return str
114
+ .split('-') // Split by hyphens
115
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize each part
116
+ .join(''); // Join without spaces
117
+ }
118
+
119
+ export function debounce(func: Function, milliseconds: number): Function {
120
+ let timeout: any;
121
+ return () => {
122
+ clearTimeout(timeout);
123
+
124
+ timeout = setTimeout(function () {
125
+ func(...arguments);
126
+ }, milliseconds);
127
+ };
128
+ }
161
129
 
162
- export function htmlToElements( html: string ): HTMLElement[]{
130
+ export function htmlToElements(html: string): HTMLElement[] {
163
131
  let template = document.createElement('template');
164
132
 
165
- html = html
166
- .replace( /<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi, "<$1$2></$1>"); // replace XHTML closing tags by full closing tags
133
+ html = html.replace(/<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi, '<$1$2></$1>'); // replace XHTML closing tags by full closing tags
167
134
 
168
135
  template.innerHTML = html;
169
136
 
170
137
  template.content.normalize();
171
138
 
172
- return ( Array.from(template.content.childNodes) as HTMLElement[] );
139
+ return Array.from(template.content.childNodes) as HTMLElement[];
173
140
  }
@@ -2,7 +2,7 @@
2
2
  export * from './helpers.js';
3
3
  export * from './MC.js';
4
4
  export * from './McEvent.js';
5
- export * from './customElements.js';
6
- export * from './customObservables.js';
7
- export * from './customSelectors.js';
5
+ export * from './elements.js';
6
+ export * from './observables.js';
7
+ export * from './selectors.js';
8
8
  export * from './formValues.js';
@@ -0,0 +1,354 @@
1
+ 'use strict';
2
+
3
+ import {
4
+ LooseObject,
5
+ parse,
6
+ debounce,
7
+ deepEqual,
8
+ nameSpace,
9
+ flattenObject,
10
+ } from './helpers.js';
11
+
12
+ import { DC, HTMLMcElement, McEvent } from './MC.js';
13
+
14
+ function isObservableObject(value: any): boolean {
15
+ return value != null && typeof value === 'object';
16
+ }
17
+
18
+ type Callback = (value: any) => void;
19
+
20
+ function getPlaceholders(target: HTMLElement): string[] {
21
+ let placeholders: Set<string> = new Set();
22
+
23
+ // scan attributes
24
+ target
25
+ .getAttributeNames()
26
+ .filter((attr) => target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)) // extract placeholder(s)
27
+ .forEach((attr) => {
28
+ let phs: Set<string> = new Set(
29
+ target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)
30
+ );
31
+ phs.forEach((placeholder) =>
32
+ placeholders.add(placeholder.replace(/[\{\}]/g, ''))
33
+ );
34
+ });
35
+
36
+ // scan children text nodes
37
+ [...target.childNodes]
38
+ .filter((childNode) => {
39
+ return (
40
+ // is text node and has placeholders
41
+ childNode.nodeType === 3 &&
42
+ ((childNode as any).nodeValue || '').match(/\{[^\{\}]*\}/g)
43
+ );
44
+ })
45
+ .forEach((childNode) => {
46
+ ((childNode as any).nodeValue || '')
47
+ .match(/\{[^\{\}]*\}/g)
48
+ .forEach((placeholder: string) => {
49
+ placeholders.add(placeholder.replace(/[\{\}]/g, ''));
50
+ });
51
+ });
52
+
53
+ // extract {}
54
+ let result: string[] = [...placeholders].map((placeholder) =>
55
+ placeholder.replace(/[\{\}]/g, '')
56
+ );
57
+
58
+ //console.log('getPlaceholders()', target, result);
59
+
60
+ return [...placeholders];
61
+ }
62
+
63
+ class Placeholders extends DC {
64
+ data: LooseObject = {};
65
+ placeholders: string[] = [];
66
+
67
+ constructor(target: HTMLElement) {
68
+ super(target);
69
+ let that = this;
70
+ getPlaceholders(target).forEach((property) => (that.data[property] = ''));
71
+ observe(that);
72
+ that.#attachCallbacks();
73
+ }
74
+
75
+ #attachCallbacks() {
76
+ let that = this,
77
+ target = that.target;
78
+
79
+ // console.log('attachCallbacks', that.target);
80
+
81
+ // scan attributes
82
+ target
83
+ .getAttributeNames()
84
+ .filter((attr: string) =>
85
+ target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)
86
+ ) // extract placeholder(s)
87
+ .forEach((attr: string) => {
88
+ let phs: Set<string> = new Set(
89
+ target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)
90
+ );
91
+ // attach callback
92
+ that.data.observe(
93
+ ((template: string) => (data: LooseObject) => {
94
+ let result: string = template;
95
+ phs.forEach((placeholder) => {
96
+ result = result.replace(
97
+ placeholder,
98
+ data[placeholder.replace(/[\{\}]/g, '')]
99
+ );
100
+ });
101
+ target.setAttribute(attr, result);
102
+ //console.log('cb setAttribute()', data, template, attr, result);
103
+ })(target.getAttribute(attr))
104
+ );
105
+ });
106
+
107
+ // scan children text nodes
108
+ [...target.childNodes]
109
+ .filter((childNode) => {
110
+ return (
111
+ // is text node and has placeholders
112
+ childNode.nodeType === 3 &&
113
+ ((childNode as any).nodeValue || '').match(/\{[^\{\}]*\}/g)
114
+ );
115
+ })
116
+ .forEach((childNode) => {
117
+ let phs: Set<string> = new Set(
118
+ childNode.nodeValue.match(/\{[^\{\}]*\}/g)
119
+ );
120
+
121
+ // attach callback
122
+ that.data.observe(
123
+ ((template: string) => (data: LooseObject) => {
124
+ let result: string = template;
125
+ phs.forEach((placeholder) => {
126
+ result = result.replace(
127
+ placeholder,
128
+ data[placeholder.replace(/[\{\}]/g, '')]
129
+ );
130
+ });
131
+ //console.log('cb nodeValue', phs, data, template, childNode, result);
132
+ childNode.nodeValue = result;
133
+ })(childNode.nodeValue)
134
+ );
135
+ });
136
+ }
137
+
138
+ onData(ev: McEvent) {
139
+ let that = this,
140
+ data: LooseObject = {};
141
+ Object.keys(ev.data).forEach((key) => {
142
+ if (that.data.hasOwnProperty(key)) data[key] = ev.data[key];
143
+ });
144
+ // console.log('onData()', ev, data, that.data);
145
+ if (JSON.stringify(data) !== JSON.stringify(that.data))
146
+ Object.assign(that.data, data); // will trigger callbacks
147
+ }
148
+ }
149
+
150
+ function getPlaceholderElements(
151
+ target: HTMLElement | DocumentFragment | ShadowRoot
152
+ ): HTMLElement[] {
153
+ let elements: Array<HTMLElement | DocumentFragment | ShadowRoot> = [target]
154
+ .concat([...(target.querySelectorAll('*') as unknown as HTMLElement[])])
155
+ .filter((e) => !!getPlaceholders(e as HTMLElement).length);
156
+ return elements as HTMLElement[];
157
+ }
158
+
159
+ function makePlaceHolders(
160
+ element: HTMLElement | DocumentFragment | ShadowRoot
161
+ ): void {
162
+ getPlaceholderElements(element).forEach((e) =>
163
+ DC.add(e, '_placeholders', new Placeholders(e))
164
+ );
165
+ }
166
+
167
+ export type Observable = {
168
+ observe: (cb: Callback) => void;
169
+ notify: () => void;
170
+ bind: (target: HTMLElement | DocumentFragment | ShadowRoot) => void;
171
+ };
172
+
173
+ export const observe = (target: LooseObject, propertyName?: string) => {
174
+ let keys = !propertyName
175
+ ? [...Object.getOwnPropertyNames(target)]
176
+ : [propertyName];
177
+
178
+ keys.forEach((key) => {
179
+ // console.log( 'co propname', key, typeof target[key], target[key] );
180
+ if (key[0] === '_' || target?.[key] === undefined) return;
181
+ let val: any = target[key],
182
+ Constructor: any;
183
+
184
+ if (!val.prototype) {
185
+ switch (typeof val) {
186
+ case 'string':
187
+ Constructor = String;
188
+ break;
189
+ case 'number':
190
+ Constructor = Number;
191
+ break;
192
+ case 'boolean':
193
+ Constructor = Boolean;
194
+ break;
195
+ case 'object':
196
+ if (val instanceof Array) {
197
+ Constructor = Array;
198
+ } else {
199
+ Constructor = Object;
200
+ }
201
+ break;
202
+ default:
203
+ return;
204
+ }
205
+ }
206
+
207
+ let Observable = class extends Constructor {
208
+ constructor(val: any) {
209
+ super(val);
210
+ (this.constructor as LooseObject).callbacks = [];
211
+ if (isObservableObject(val)) {
212
+ // you cannot bind native values to the dom
213
+ (this.constructor as LooseObject).bound = [];
214
+ Object.getOwnPropertyNames(val).forEach((key) => {
215
+ this[key] = val[key];
216
+ });
217
+ }
218
+ }
219
+
220
+ observe(f: Function) {
221
+ //console.log('observe');
222
+ (this.constructor as any).callbacks.push(f);
223
+ return this;
224
+ }
225
+
226
+ bind(target: HTMLElement | DocumentFragment | ShadowRoot) {
227
+ const that = this,
228
+ iso = isObservableObject(that.valueOf()),
229
+ bound = (that.constructor as any).bound;
230
+ //console.log('bind', iso, target);
231
+
232
+ if (iso) {
233
+ makePlaceHolders(target);
234
+ (this.constructor as any).callbacks.push((data: LooseObject) => {
235
+ DC.trigger(target, 'data', flattenObject(data), 'ld');
236
+ });
237
+ that.notify();
238
+ } else {
239
+ console.warn(
240
+ 'IGNORED - cannot bind a non-Object to the dom, IS:',
241
+ typeof that.valueOf(),
242
+ that
243
+ );
244
+ }
245
+
246
+ return this;
247
+ }
248
+
249
+ notify() {
250
+ let that = this,
251
+ data =
252
+ isObservableObject(that.valueOf()) &&
253
+ that.valueOf() instanceof Array === false
254
+ ? structuredClone(Object.assign({}, that))
255
+ : that.valueOf();
256
+ // console.log('notify', that.constructor, (that.constructor as any).callbacks.length, (that.constructor as any)?.bound?.length, data );
257
+ (that.constructor as any).callbacks.forEach((f: Function) => {
258
+ // console.log( 'callback', f, data);
259
+ f(data);
260
+ });
261
+ if (isObservableObject(that.valueOf())) {
262
+ // console.log('bound', this.constructor);
263
+ (that.constructor as any).bound.forEach((f: Function) => {
264
+ // console.log( 'bound', f, data);
265
+ f(data);
266
+ });
267
+ }
268
+ return this;
269
+ }
270
+ };
271
+
272
+ //(Observable.constructor as LooseObject).callbacks = [];
273
+ let o = new Observable(val);
274
+
275
+ Object.defineProperty(target, key, {
276
+ enumerable: true,
277
+ get() {
278
+ if (isObservableObject(o.valueOf())) {
279
+ let check = structuredClone(Object.assign({}, o));
280
+ setTimeout(
281
+ debounce(function checkChanges() {
282
+ let state = structuredClone(Object.assign({}, o));
283
+ //console.log( 'check changes', state, check );
284
+ if (!deepEqual(state, check)) {
285
+ //console.log( '-> not equal!' );
286
+ o.notify();
287
+ }
288
+ }, 0),
289
+ 0
290
+ );
291
+ }
292
+ return o;
293
+ },
294
+ set(val: any) {
295
+ //console.log( 'SET:', isObservableObject( val.valueOf() ), 'set:', val, 'to', isObservableObject( o.valueOf() ), o, );
296
+ if (typeof val === typeof o.valueOf()) {
297
+ let iso =
298
+ isObservableObject(o.valueOf()) &&
299
+ o.valueOf() instanceof Array === false;
300
+ //let iso = o.constructor.prototype.__proto__.constructor === Object;
301
+ //console.log('target iso:', iso);
302
+ if (iso) {
303
+ let old = structuredClone(Object.assign({}, o));
304
+ val = structuredClone(Object.assign({}, val));
305
+
306
+ let hasFormHandler =
307
+ (o.constructor as LooseObject)?.hasFormHandler ?? false,
308
+ callbacks = (o.constructor as LooseObject).callbacks,
309
+ bound = (o.constructor as LooseObject).bound;
310
+ o = new Observable(structuredClone(Object.assign({}, val)));
311
+
312
+ //console.log('after set o=', o, 'check', old);
313
+ (o.constructor as LooseObject).callbacks = hasFormHandler;
314
+ (o.constructor as LooseObject).callbacks = callbacks;
315
+ (o.constructor as LooseObject).bound = bound;
316
+
317
+ setTimeout(
318
+ // check for changes
319
+ debounce(function checkChanges() {
320
+ let state = structuredClone(Object.assign({}, o));
321
+ //console.log( 'check changes', state, check );
322
+ if (!deepEqual(state, old)) {
323
+ //console.log( '-> not equal!' );
324
+ o.notify();
325
+ }
326
+ }, 0),
327
+ 0
328
+ );
329
+ } else {
330
+ // simple native var
331
+ let old = o.valueOf(),
332
+ callbacks = (o.constructor as LooseObject).callbacks;
333
+ o = new Observable(val);
334
+ (o.constructor as LooseObject).callbacks = callbacks;
335
+ if (val !== old) {
336
+ o.notify();
337
+ }
338
+ }
339
+ } else {
340
+ console.warn(
341
+ 'IGNORED - cannot change observable types, IS:',
342
+ typeof o.valueOf(),
343
+ o,
344
+ '- CANNOT BECOME:',
345
+ typeof val
346
+ );
347
+ }
348
+ },
349
+ });
350
+
351
+ // replace old property with proxy (observable)
352
+ target[key] = val;
353
+ });
354
+ };