@twobirds/microcomponents 0.0.21 → 0.0.22

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/.gitlab-ci.yml +1 -0
  2. package/README.md +31 -12
  3. package/assets/documentation/MicroComponents.md +228 -0
  4. package/assets/my-tag.css +4 -0
  5. package/assets/test.html +5 -1
  6. package/dist/MC.d.ts +32 -0
  7. package/dist/MC.d.ts.map +1 -0
  8. package/dist/MC.min.js +414 -0
  9. package/dist/MC.ts +350 -0
  10. package/dist/MCbundle.d.ts +8 -0
  11. package/dist/MCbundle.d.ts.map +1 -0
  12. package/dist/MCbundle.min.js +1 -0
  13. package/dist/MCbundle.ts +8 -0
  14. package/dist/McEvent.d.ts +15 -0
  15. package/dist/McEvent.d.ts.map +1 -0
  16. package/dist/McEvent.ts +96 -0
  17. package/dist/autoloader.d.ts +2 -0
  18. package/dist/autoloader.d.ts.map +1 -0
  19. package/dist/autoloader.ts +98 -0
  20. package/dist/customElements.d.ts +5 -0
  21. package/dist/customElements.d.ts.map +1 -0
  22. package/dist/customElements.min.js +1 -0
  23. package/dist/customElements.ts +67 -0
  24. package/dist/customObservables.d.ts +3 -0
  25. package/dist/customObservables.d.ts.map +1 -0
  26. package/dist/customObservables.min.js +1 -0
  27. package/dist/customObservables.ts +340 -0
  28. package/dist/customSelectors.d.ts +108 -0
  29. package/dist/customSelectors.d.ts.map +1 -0
  30. package/dist/customSelectors.min.js +1 -0
  31. package/dist/customSelectors.ts +1634 -0
  32. package/dist/formValues.d.ts +4 -0
  33. package/dist/formValues.d.ts.map +1 -0
  34. package/dist/formValues.ts +275 -0
  35. package/dist/formvValues.min.js +1 -0
  36. package/dist/helpers.d.ts +11 -0
  37. package/dist/helpers.d.ts.map +1 -0
  38. package/dist/helpers.ts +173 -0
  39. package/dist/microcomponents.es3.d.ts +1 -20
  40. package/dist/microcomponents.es3.d.ts.map +1 -1
  41. package/dist/test.d.ts +2 -0
  42. package/dist/test.d.ts.map +1 -0
  43. package/package.json +11 -7
  44. package/public/MC.js +273 -0
  45. package/public/MC.min.js +414 -0
  46. package/public/MCbundle.js +8 -0
  47. package/public/MCbundle.min.js +1 -0
  48. package/public/McEvent.js +74 -0
  49. package/public/MicroComponents.svg +15 -0
  50. package/public/assets/search.js +1 -1
  51. package/public/autoloader.js +57 -0
  52. package/public/classes/MC.DC.html +247 -0
  53. package/public/classes/MC.MC.html +150 -0
  54. package/public/classes/MC.McBase.html +123 -0
  55. package/public/classes/MCbundle.McEvent.html +184 -0
  56. package/public/customElements.js +48 -0
  57. package/public/customElements.min.js +1 -0
  58. package/public/customObservables.js +255 -0
  59. package/public/customObservables.min.js +1 -0
  60. package/public/customSelectors.js +1088 -0
  61. package/public/customSelectors.min.js +1 -0
  62. package/public/documentation/MicroComponents.md +228 -0
  63. package/public/formValues.js +211 -0
  64. package/public/formvValues.min.js +1 -0
  65. package/public/functions/MC.addListener.html +73 -0
  66. package/public/functions/MC.removeListener.html +69 -0
  67. package/public/functions/MCbundle._d.html +85 -0
  68. package/public/functions/MCbundle._t.html +85 -0
  69. package/public/functions/MCbundle.debounce.html +85 -0
  70. package/public/functions/MCbundle.deepEqual.html +85 -0
  71. package/public/functions/MCbundle.defineCE.html +98 -0
  72. package/public/functions/MCbundle.formValues.html +89 -0
  73. package/public/functions/MCbundle.getCE.html +83 -0
  74. package/public/functions/MCbundle.htmlToElements.html +83 -0
  75. package/public/functions/MCbundle.isObject.html +83 -0
  76. package/public/functions/MCbundle.kebabToPascal.html +83 -0
  77. package/public/functions/MCbundle.makeCO.html +85 -0
  78. package/public/functions/MCbundle.nameSpace.html +89 -0
  79. package/public/functions/MCbundle.parse.html +85 -0
  80. package/public/helpers.js +128 -0
  81. package/public/index.html +22 -13
  82. package/public/interfaces/MC.HTMLMcElement.html +3605 -0
  83. package/public/interfaces/MCbundle.DSelector.html +1010 -0
  84. package/public/interfaces/MCbundle.LooseObject.html +80 -0
  85. package/public/interfaces/MCbundle.TSelector.html +709 -0
  86. package/public/microcomponents.es3.js +348 -0
  87. package/public/modules/MC.html +84 -0
  88. package/public/modules/MCbundle.html +133 -0
  89. package/public/modules.html +4 -4
  90. package/public/my-tag.css +4 -0
  91. package/public/test.html +5 -1
  92. package/public/test.js +100 -202
  93. package/public/types/MCbundle.selection.html +74 -0
  94. package/public/types/MCbundle.singleSelector.html +74 -0
  95. package/src/MC.ts +350 -0
  96. package/src/MCbundle.ts +8 -0
  97. package/src/McEvent.ts +96 -0
  98. package/src/autoloader.ts +98 -0
  99. package/src/customElements.ts +67 -0
  100. package/src/customObservables.ts +340 -0
  101. package/src/customSelectors.ts +1634 -0
  102. package/src/formValues.ts +275 -0
  103. package/src/helpers.ts +173 -0
  104. package/src/microcomponents.es3.js +353 -82
  105. package/src/test.js +137 -218
  106. package/tsconfig.json +2 -2
  107. package/typedoc.json +1 -1
  108. package/webpack.config.js +233 -0
  109. package/dist/microcomponents.d.ts +0 -26
  110. package/dist/microcomponents.d.ts.map +0 -1
  111. package/dist/microcomponents.es3.js +0 -96
  112. package/dist/microcomponents.es3.min.js +0 -15
  113. package/dist/microcomponents.js +0 -176
  114. package/dist/microcomponents.min.js +0 -38
  115. package/dist/microcomponents.ts +0 -216
  116. package/public/classes/microcomponents.MC.html +0 -313
  117. package/public/classes/microcomponents_es3.MC.html +0 -336
  118. package/public/functions/microcomponents_es3.__isEmpty.html +0 -60
  119. package/public/microcomponents.js +0 -176
  120. package/public/modules/microcomponents.html +0 -57
  121. package/public/modules/microcomponents_es3.html +0 -60
  122. package/src/microcomponents.ts +0 -216
package/src/McEvent.ts ADDED
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ var isBrowser=new Function("try {return this===window;}catch(e){ return false;}");
4
+
5
+ let nativeEventNames: Set<string> = new Set();
6
+
7
+ // HTMLElement native event names
8
+ if ( isBrowser() ){
9
+ Object.keys( HTMLElement.prototype ).filter( key => /^on/.test(key) ).forEach( eventName => nativeEventNames.add( eventName ) );
10
+ }
11
+
12
+ function isDOM(element: { [key:string]: any } ) {
13
+ return element && element instanceof HTMLElement;
14
+ }
15
+
16
+ interface McEvent {
17
+ data: any;
18
+ bubble: string;
19
+ }
20
+
21
+ class McEvent{
22
+
23
+ #type: string;
24
+ #stopped: boolean = false;
25
+ #immediateStopped: boolean = false;
26
+
27
+ constructor( type: string, data: any = {}, bubble: string = 'l' ){
28
+ // bubble standard = local only, options = any combination of'uld' characters: up to root, local, down
29
+ this.#type = type;
30
+ this.data = data;
31
+ this.bubble = bubble;
32
+ }
33
+
34
+ get type(): string {
35
+ return this.#type;
36
+ }
37
+
38
+ get stopped(): boolean {
39
+ return this.#stopped;
40
+ }
41
+
42
+ get immediateStopped(): boolean {
43
+ return this.#immediateStopped;
44
+ }
45
+
46
+ stopPropagation(){
47
+ this.#stopped = true;
48
+ }
49
+
50
+ stopImmediatePropagation(){
51
+ this.stopPropagation();
52
+ this.#immediateStopped = true;
53
+ }
54
+
55
+ }
56
+
57
+ // get all microcomponents from a list of HTMLElements
58
+ function getMicroComponents( elements: any[], search: string): any[] {
59
+ let mcValues: any[] = [];
60
+
61
+ elements.forEach( e => {
62
+ if (e) {
63
+ if (e instanceof HTMLElement) {
64
+ const _mc = ( e as any )?._mc;
65
+ if ( !search && _mc ) {
66
+ mcValues = mcValues.concat(Object.values(( e as any )._mc));
67
+ }
68
+ else if ( search && _mc && _mc[search] ) {
69
+ mcValues.push( _mc[search] );
70
+ }
71
+ }
72
+ }
73
+ });
74
+ return mcValues;
75
+ }
76
+
77
+ // get all ancestor DOM nodes up to the document root
78
+ function traverseNodes(node: { [key:string]: any }, search: string, firstonly = true): any[] {
79
+ let mcValues: any[] = [];
80
+ while (node) {
81
+ if (node._mc) {
82
+ if (!search) {
83
+ mcValues = mcValues.concat(Object.values(node._mc));
84
+ }
85
+ else if (search && node._mc[search]) {
86
+ mcValues.push(node._mc[search]);
87
+ }
88
+ if (firstonly)
89
+ return mcValues;
90
+ }
91
+ node = node.parentNode;
92
+ }
93
+ return mcValues;
94
+ }
95
+
96
+ export { McEvent };
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ import { getCE } from './customElements.js'
4
+
5
+ // set of currently loading scripts
6
+ const loadingScripts: Set<string> = new Set();
7
+
8
+ const _makeLoadData = ( e: HTMLElement ): Array<any> | false => {
9
+
10
+ let
11
+ tagName = e?.localName ?? '',
12
+ isAttribute = e.getAttribute?.('is') || '',
13
+ isUBE = isAttribute ? true : false,
14
+ isCE = tagName.indexOf('-') !== -1 ? true : false,
15
+ ubeSelector = isUBE ? `${tagName}[is=\"${isAttribute}\"]:defined` : '',
16
+ ceSelector = isCE ? tagName + ':defined' : '',
17
+ fileBaseName = isUBE
18
+ ? isAttribute
19
+ : isCE
20
+ ? tagName
21
+ : '',
22
+ fileName = fileBaseName.length ? '/' + fileBaseName.split('-').join('/') + '.js' : '',
23
+ selector = isUBE
24
+ ? ubeSelector
25
+ : isCE
26
+ ? ceSelector
27
+ : ''
28
+ ;
29
+
30
+ //console.log( 'makeLoadData()', tagName, isUBE, isCE, ubeSelector, ceSelector, fileBaseName, ' => ', (isUBE || isCE) ? [ e, selector, fileName ] : false );
31
+ return (isUBE || isCE) ? [ e, selector, fileName, fileBaseName ] : false;
32
+ }
33
+
34
+ const _loadRequirements = ( node: HTMLTemplateElement | HTMLElement ): Promise<any> => {
35
+
36
+ let
37
+ undefinedSet: Set<any> = new Set(),
38
+ element: any = node instanceof HTMLTemplateElement ? (node as HTMLTemplateElement).content : node,
39
+ head = document.head,
40
+ allPromises: Array<any> = [],
41
+ e: HTMLElement;
42
+ ;
43
+
44
+ if ( element instanceof HTMLTemplateElement === false ){
45
+ // if node itself is undefined
46
+ let data: any = _makeLoadData(element);
47
+
48
+ if ( data && !data[0].matches( data[1] ) ){
49
+ undefinedSet.add( data );
50
+ }
51
+ }
52
+
53
+ // if some of the childNodes are undefined
54
+ Array.from( element.childNodes ).forEach(( node )=>{
55
+ let data: any = _makeLoadData(node as HTMLElement);
56
+
57
+ if ( data && !data[0].matches( data[1] ) ){
58
+ undefinedSet.add( data );
59
+ }
60
+ });
61
+
62
+ if ( !!undefinedSet.size ){ // there are requirements
63
+
64
+ undefinedSet.forEach( (data) => {
65
+ if ( !getCE( data[3] ) && !loadingScripts.has( data[2]) ){
66
+
67
+ loadingScripts.add( data[2] );
68
+
69
+ const se: HTMLScriptElement = document.createElement('script');
70
+
71
+ se.setAttribute( 'src', data[2] );
72
+ se.setAttribute( 'blocking', 'render' );
73
+ se.setAttribute( 'type', 'module' );
74
+ let s = (data as any)[2];
75
+ se.onload = () => {
76
+ // console.info('loaded', s);
77
+ loadingScripts.delete( s );
78
+ };
79
+
80
+ head.append( se );
81
+
82
+ let e = (data as Array<any>)[0];
83
+ } else {
84
+ return ;
85
+ }
86
+ });
87
+
88
+ }
89
+
90
+ return Promise.all( allPromises );
91
+ }
92
+
93
+ /*
94
+ TBD
95
+ if ( template.content.childNodes.length ){
96
+ _loadRequirements(template);
97
+ }
98
+ */
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ import { DC } from './MC.js';
4
+ import { kebabToPascal } from './helpers.js';
5
+
6
+ class CeBaseClass extends HTMLElement {
7
+ constructor() {
8
+ super();
9
+ }
10
+
11
+ connectedCallback() {
12
+ (DC as any).trigger(this, 'Connected');
13
+ }
14
+
15
+ disconnectedCallback() {
16
+ (DC as any).trigger(this, 'Disconnected');
17
+ }
18
+
19
+ adoptedCallback() {
20
+ (DC as any).trigger(this, 'Adopted');
21
+ }
22
+
23
+ attributeChangedCallback(name: string, oldValue: any, newValue: any) {
24
+ (DC as any).trigger(this, 'AttributeChanged', { name, oldValue, newValue });
25
+ }
26
+ }
27
+
28
+ function createNamedClass(name: string, ClassBody: { new (...args: any[]): any } ) {
29
+ return Object.defineProperty( ClassBody, 'name', { value: name });
30
+ }
31
+
32
+ export function defineCE( tagName: string, DefinitionClass: { new (...args: any[]): any }, observedAttributes: string[] = []){
33
+ if (customElements.get(tagName)) {
34
+ console.warn(`IGNORED: Custom element "${tagName}" is already defined!`);
35
+ return;
36
+ }
37
+
38
+ if (!tagName.includes('-')) {
39
+ throw new Error('createCustomElement: tagName must contain at least one hyphen ("-").');
40
+ }
41
+
42
+ let name = kebabToPascal(tagName);
43
+
44
+ customElements.define(
45
+ tagName,
46
+ createNamedClass(
47
+ name,
48
+ class extends CeBaseClass {
49
+ instance: any;
50
+
51
+ constructor( data?: any ) {
52
+ super();
53
+ let instance = new DefinitionClass(this, data);
54
+ ( DC as any ).add(this, name, instance );
55
+ }
56
+
57
+ static get observedAttributes() {
58
+ return observedAttributes;
59
+ }
60
+ }
61
+ )
62
+ );
63
+ };
64
+
65
+ export function getCE(tagName: string): CustomElementConstructor | undefined {
66
+ return customElements.get(tagName);
67
+ }
@@ -0,0 +1,340 @@
1
+ "use strict";
2
+
3
+ import { LooseObject } from './helpers.js';
4
+ import { isObject, parse, debounce, deepEqual } from './helpers.js';
5
+
6
+ export const makeCO = ( target: LooseObject, propertyName?: string ) => {
7
+
8
+ let keys = !propertyName ? [ ...Object.getOwnPropertyNames(target) ] : [ propertyName ];
9
+
10
+ keys.forEach( (key) => {
11
+ // console.log( 'co propname', key, typeof target[key], target[key] );
12
+ if ( key[0] === '_' || target?.[key] === undefined ) return;
13
+ let
14
+ val: any = target[key],
15
+ Constructor: any
16
+ ;
17
+
18
+ if ( !val.prototype ){
19
+ switch ( typeof val ){
20
+ case "string":
21
+ Constructor = String;
22
+ break;
23
+ case "number":
24
+ Constructor = Number;
25
+ break;
26
+ case "boolean":
27
+ Constructor = Boolean;
28
+ break;
29
+ case "object":
30
+ if ( val instanceof Array){
31
+ Constructor = Array;
32
+ } else {
33
+ Constructor = Object;
34
+ }
35
+ break;
36
+ default:
37
+ return;
38
+ }
39
+
40
+ }
41
+
42
+ let Observable = class extends Constructor{
43
+
44
+ constructor( val: any ){
45
+ super( val );
46
+ (this.constructor as LooseObject).callbacks = [];
47
+ if ( isObject(val) ){ // you cannot bind native values to the dom
48
+ (this.constructor as LooseObject).bound = [];
49
+ Object.getOwnPropertyNames( val ).forEach( (key) => {
50
+ this[key] = val[key];
51
+ });
52
+ }
53
+ }
54
+
55
+ observe( f: Function ){
56
+ //console.log('observe');
57
+ (this.constructor as any).callbacks.push( f );
58
+ return this;
59
+ }
60
+
61
+ bind( target: HTMLElement | ShadowRoot ){
62
+
63
+ const
64
+ that = this,
65
+ iso = isObject( that.valueOf() ),
66
+ bound = (that.constructor as any).bound
67
+ ;
68
+
69
+ //console.log('bind', iso, target);
70
+
71
+ if ( iso ){
72
+ // console.log('bind...', that.valueOf(), target );
73
+
74
+ function walk( element: Node ){
75
+ //console.log('-walk:', element, element.childNodes );
76
+
77
+ if ( !!element['nodeType'] && element.nodeType === 3 ){ // text node
78
+ //console.log('--type: textNode(3)');
79
+
80
+ var placeholders = Array.from( element.nodeValue && element.nodeValue.match( /\{[^\{\}]*\}/g ) || []);
81
+
82
+ if ( placeholders.length > 0 ){
83
+ //console.log('--placeholders:', placeholders);
84
+ var f=(function( template: string ){
85
+ //console.log('template', template);
86
+ return function( values: any ){
87
+ var t,
88
+ changed = false;
89
+
90
+ //console.log( 'placeholders:', placeholders, 'values:', values);
91
+ if ( placeholders ){
92
+ if ( iso ){
93
+ placeholders.forEach(function(placeholder){
94
+ if ( ( f as LooseObject).values[placeholder] !== values[placeholder] ){
95
+ (f as LooseObject).values[placeholder] = values[placeholder];
96
+ changed = true;
97
+ }
98
+ });
99
+ } else { // it is a simple value
100
+ (f as LooseObject).values = values;
101
+ changed = true;
102
+ };
103
+ }
104
+ if (changed){ // only reflow if changed
105
+ t = template;
106
+ //console.log('--template parse', t, (f as LooseObject).values );
107
+ if ( iso ){
108
+ element.nodeValue = parse(
109
+ t,
110
+ (f as LooseObject).values
111
+ );
112
+ } else { // it is a simple value -> replace every placeholder whatever the name wi
113
+ element.nodeValue = t.replace( /\{.*\}/g ,(f as LooseObject).values );
114
+ };
115
+ }
116
+ return values;
117
+ };
118
+ })( element.nodeValue || '' );
119
+
120
+ (f as LooseObject).values = iso ? {} : undefined;
121
+ placeholders = Array.from( placeholders ).map((pKey) => pKey.replace(/[\{\}]/g, '').trim());
122
+
123
+ let initial: any = iso ? {} : undefined;
124
+ placeholders.forEach(function(pKey){
125
+ if ( iso ){
126
+ initial[pKey] = "";
127
+ }
128
+ });
129
+
130
+ bound.push(f);
131
+ // console.log( `--bound textNode`, placeholders, f );
132
+ //(observableFunction as Function)(initial);
133
+ }
134
+
135
+ //console.log('--childNodes:', element.childNodes );
136
+ Array.from( element.childNodes )
137
+ .forEach(function( childNode ){
138
+ walk( childNode );
139
+ });
140
+
141
+ that.notify();
142
+ }
143
+
144
+ if ( !!element['nodeType'] && element.nodeType === 1 ){ // HTML element
145
+ //console.log('--type: HTMLElement(1)');
146
+ Array.from( (element as HTMLElement).attributes )
147
+ .forEach(
148
+ function( attributeNode ){
149
+ var placeholders = Array.from( attributeNode.value && attributeNode.value.match( /\{[^\{\}]*\}/g ) || []);
150
+
151
+ if ( placeholders.length > 0 ){
152
+ //console.log( `--[${attributeNode.value}] placeholders:`, placeholders );
153
+
154
+ var f=(function( template: string ){
155
+ return function( values: any ){
156
+ var t,
157
+ changed = false;
158
+
159
+ //console.log( 'placeholders:', placeholders, 'values:', values);
160
+ if ( placeholders ){
161
+ placeholders.forEach(function(pKey){
162
+ if ( ( f as LooseObject).values[pKey] !== values[pKey] ){
163
+ (f as LooseObject).values[pKey] = values[pKey];
164
+ changed = true;
165
+ }
166
+ });
167
+ }
168
+ if (changed){ // only reflow if changed
169
+ t = template;
170
+ element.nodeValue = parse(
171
+ t,
172
+ (f as LooseObject).values
173
+ );
174
+ }
175
+ return values;
176
+ };
177
+ })( attributeNode.value || '' );
178
+
179
+ (f as LooseObject).values = {};
180
+ placeholders = Array.from( placeholders ).map((pKey) => pKey.replace(/[\{\}]/g, '').trim());
181
+ let initial: LooseObject = {};
182
+ placeholders.forEach(function(pKey){
183
+ initial[pKey] = "";
184
+ });
185
+
186
+ bound.push(f);
187
+ // console.log( `--bound element attribute`, placeholders, f );
188
+ // console.log( `--bound`, observableFunction.bound );
189
+ //(observableFunction as Function)(initial);
190
+ }
191
+ }
192
+ );
193
+
194
+ //console.log('--childNodes:', element.childNodes );
195
+ Array.from( element.childNodes )
196
+ .forEach(function( childNode ){
197
+ walk( childNode );
198
+ });
199
+
200
+ that.notify();
201
+
202
+ }
203
+
204
+ if ( !!element['nodeType'] && element.nodeType === 11 ){ // shadowRoot node
205
+ // console.log( element, element.childNodes );
206
+ Array.from( element.childNodes )
207
+ .forEach(function( childNode ){
208
+ walk( childNode );
209
+ });
210
+ }
211
+ }
212
+
213
+ walk( target );
214
+
215
+ if ( bound.length > 0 ){
216
+ that.notify();
217
+ }
218
+ } else {
219
+ console.warn( 'IGNORED - cannot bind a non-Object to the dom, IS:', typeof that.valueOf() );
220
+ }
221
+
222
+ return this;
223
+ }
224
+
225
+ notify(){
226
+ let
227
+ that = this,
228
+ data = isObject( that.valueOf() ) && ( that.valueOf() instanceof Array ) === false
229
+ ? structuredClone( Object.assign({}, that) )
230
+ : that.valueOf()
231
+ ;
232
+
233
+ // console.log('notify', that.constructor, (that.constructor as any).callbacks.length, (that.constructor as any)?.bound?.length, data );
234
+ (that.constructor as any).callbacks.forEach( (f: Function) => {
235
+ // console.log( 'callback', f, data);
236
+ f( data );
237
+ });
238
+ if ( isObject( that.valueOf() ) ){
239
+ // console.log('bound', this.constructor);
240
+ (that.constructor as any).bound.forEach( (f: Function) => {
241
+ // console.log( 'bound', f, data);
242
+ f( data );
243
+ });
244
+ }
245
+ return this;
246
+ }
247
+ }
248
+
249
+ //(Observable.constructor as LooseObject).callbacks = [];
250
+ let o = new Observable( val );
251
+
252
+ Object.defineProperty(
253
+ target,
254
+ key,
255
+ {
256
+ enumerable: true,
257
+ get(){
258
+ if ( isObject( o.valueOf() ) ){
259
+ let check = structuredClone( Object.assign( {}, o ) );
260
+ setTimeout(
261
+ debounce(
262
+ function checkChanges(){
263
+ let state = structuredClone( Object.assign( {}, o ) );
264
+ //console.log( 'check changes', state, check );
265
+ if ( !deepEqual( state, check ) ){
266
+ //console.log( '-> not equal!' );
267
+ o.notify();
268
+ }
269
+ },
270
+ 0
271
+ ),
272
+ 0
273
+ );
274
+ }
275
+ return o;
276
+ },
277
+ set( val: any ){
278
+ //console.log( 'SET:', isObject( val.valueOf() ), 'set:', val, 'to', isObject( o.valueOf() ), o, );
279
+ if ( typeof val === typeof o.valueOf() ){
280
+
281
+ let iso = isObject( o.valueOf() ) && ( o.valueOf() instanceof Array ) === false;
282
+ //let iso = o.constructor.prototype.__proto__.constructor === Object;
283
+ //console.log('target iso:', iso);
284
+ if ( iso ){
285
+ let
286
+ old = structuredClone( Object.assign( {}, o ) )
287
+ ;
288
+
289
+ val = structuredClone( Object.assign( {}, val ) );
290
+
291
+ let
292
+ hasFormHandler = (o.constructor as LooseObject)?.hasFormHandler ?? false,
293
+ callbacks = (o.constructor as LooseObject).callbacks,
294
+ bound = (o.constructor as LooseObject).bound
295
+ ;
296
+
297
+ o = new Observable( structuredClone( Object.assign( {}, val ) ) );
298
+
299
+ //console.log('after set o=', o, 'check', old);
300
+ (o.constructor as LooseObject).callbacks = hasFormHandler;
301
+ (o.constructor as LooseObject).callbacks = callbacks;
302
+ (o.constructor as LooseObject).bound = bound;
303
+
304
+ setTimeout( // check for changes
305
+ debounce(
306
+ function checkChanges(){
307
+ let state = structuredClone( Object.assign( {}, o ) );
308
+ //console.log( 'check changes', state, check );
309
+ if ( !deepEqual( state, old ) ){
310
+ //console.log( '-> not equal!' );
311
+ o.notify();
312
+ }
313
+ },
314
+ 0
315
+ ),
316
+ 0
317
+ );
318
+ } else { // simple native var
319
+ let
320
+ old = o.valueOf(),
321
+ callbacks = (o.constructor as LooseObject).callbacks
322
+ ;
323
+ o = new Observable( val );
324
+ (o.constructor as LooseObject).callbacks = callbacks;
325
+ if ( val !== old ){
326
+ o.notify();
327
+ }
328
+ }
329
+ } else {
330
+ console.warn( 'IGNORED - cannot change observable types, IS:', typeof o.valueOf(), '- CANNOT BECOME:', typeof val );
331
+ }
332
+ }
333
+ }
334
+ );
335
+
336
+ target[key] = val;
337
+
338
+ });
339
+
340
+ }