@twobirds/microcomponents 0.0.34 → 0.0.39

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 (120) 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/assets/my-tag.css +6 -2
  7. package/dist/MC.d.ts +3 -4
  8. package/dist/MC.d.ts.map +1 -1
  9. package/dist/MC.min.js +89 -66
  10. package/dist/MC.ts +213 -178
  11. package/dist/autoloader.ts +1 -1
  12. package/dist/{customElements.d.ts → elements.d.ts} +1 -1
  13. package/dist/elements.d.ts.map +1 -0
  14. package/dist/elements.min.js +1 -0
  15. package/dist/{customElements.ts → elements.ts} +23 -14
  16. package/dist/helpers.d.ts +6 -4
  17. package/dist/helpers.d.ts.map +1 -1
  18. package/dist/helpers.ts +95 -128
  19. package/dist/microcomponents.d.ts +3 -3
  20. package/dist/microcomponents.d.ts.map +1 -1
  21. package/dist/microcomponents.min.js +1 -1
  22. package/dist/microcomponents.ts +3 -3
  23. package/dist/{customObservables.d.ts → observables.d.ts} +3 -3
  24. package/dist/observables.d.ts.map +1 -0
  25. package/dist/observables.min.js +1 -0
  26. package/dist/observables.ts +353 -0
  27. package/dist/{customSelectors.d.ts → selectors.d.ts} +1 -1
  28. package/dist/selectors.d.ts.map +1 -0
  29. package/dist/selectors.min.js +1 -0
  30. package/dist/test.ts +135 -156
  31. package/klemmstein.png +0 -0
  32. package/package.json +52 -52
  33. package/public/MC.js +90 -67
  34. package/public/MC.js.map +1 -1
  35. package/public/MC.min.js +89 -66
  36. package/public/assets/search.js +1 -1
  37. package/public/autoloader.js +1 -1
  38. package/public/autoloader.js.map +1 -1
  39. package/public/classes/{DC.html → MC.DC.html} +60 -59
  40. package/public/classes/{MC.html → MC.MC.html} +41 -35
  41. package/public/classes/{McBase.html → MC.McBase.html} +28 -20
  42. package/public/classes/{McEvent.html → MC.McEvent.html} +48 -42
  43. package/public/documentation/{MicroComponents.md → MC.md} +17 -17
  44. package/public/documentation/comparision.md +0 -0
  45. package/public/documentation/elements.md +276 -0
  46. package/public/documentation/magic.md +10 -68
  47. package/public/{customElements.js → elements.js} +9 -10
  48. package/public/elements.js.map +1 -0
  49. package/public/elements.min.js +1 -0
  50. package/public/functions/{addListener.html → MC.addListener.html} +18 -12
  51. package/public/functions/{removeListener.html → MC.removeListener.html} +18 -12
  52. package/public/functions/elements.defineCE.html +78 -0
  53. package/public/functions/elements.getCE.html +63 -0
  54. package/public/functions/formValues.formValues.html +68 -0
  55. package/public/functions/observables.observe.html +65 -0
  56. package/public/functions/selectors._d.html +69 -0
  57. package/public/functions/selectors._t.html +69 -0
  58. package/public/helpers.js +66 -89
  59. package/public/helpers.js.map +1 -1
  60. package/public/index.html +48 -33
  61. package/public/interfaces/{HTMLMcElement.html → MC.HTMLMcElement.html} +601 -595
  62. package/public/interfaces/selectors.DSelector.html +1013 -0
  63. package/public/interfaces/selectors.TSelector.html +712 -0
  64. package/public/microcomponents.js +3 -3
  65. package/public/microcomponents.js.map +1 -1
  66. package/public/microcomponents.min.js +1 -1
  67. package/public/modules/MC.html +78 -0
  68. package/public/modules/elements.html +62 -0
  69. package/public/modules/formValues.html +60 -0
  70. package/public/modules/observables.html +65 -0
  71. package/public/modules/selectors.html +76 -0
  72. package/public/modules.html +11 -23
  73. package/public/my-tag.css +6 -2
  74. package/public/observables.js +259 -0
  75. package/public/observables.js.map +1 -0
  76. package/public/observables.min.js +1 -0
  77. package/public/{customSelectors.js → selectors.js} +1 -1
  78. package/public/selectors.js.map +1 -0
  79. package/public/selectors.min.js +1 -0
  80. package/public/src/MC.ts +413 -0
  81. package/public/src/McEvent.ts +96 -0
  82. package/public/src/autoloader.ts +98 -0
  83. package/{src/customElements.ts → public/src/elements.ts} +23 -14
  84. package/public/src/formValues.ts +275 -0
  85. package/public/src/helpers.ts +140 -0
  86. package/public/src/microcomponents.ts +8 -0
  87. package/public/src/observables.ts +353 -0
  88. package/public/src/test.ts +190 -0
  89. package/public/test.js +93 -118
  90. package/public/test.js.map +1 -1
  91. package/public/types/observables.Observable.html +91 -0
  92. package/public/types/selectors.selection.html +58 -0
  93. package/public/types/selectors.singleSelector.html +58 -0
  94. package/src/MC.ts +213 -178
  95. package/src/autoloader.ts +1 -1
  96. package/src/elements.ts +76 -0
  97. package/src/helpers.ts +95 -128
  98. package/src/microcomponents.ts +3 -3
  99. package/src/observables.ts +353 -0
  100. package/src/selectors.ts +1634 -0
  101. package/src/test.ts +135 -156
  102. package/typedoc.json +1 -1
  103. package/webpack.config.js +9 -9
  104. package/dist/customElements.d.ts.map +0 -1
  105. package/dist/customElements.min.js +0 -1
  106. package/dist/customObservables.d.ts.map +0 -1
  107. package/dist/customObservables.min.js +0 -1
  108. package/dist/customObservables.ts +0 -348
  109. package/dist/customSelectors.d.ts.map +0 -1
  110. package/dist/customSelectors.min.js +0 -1
  111. package/public/customElements.js.map +0 -1
  112. package/public/customElements.min.js +0 -1
  113. package/public/customObservables.js +0 -256
  114. package/public/customObservables.js.map +0 -1
  115. package/public/customObservables.min.js +0 -1
  116. package/public/customSelectors.js.map +0 -1
  117. package/public/customSelectors.min.js +0 -1
  118. package/src/customObservables.ts +0 -348
  119. /package/dist/{customSelectors.ts → selectors.ts} +0 -0
  120. /package/{src/customSelectors.ts → public/src/selectors.ts} +0 -0
@@ -0,0 +1,413 @@
1
+ 'use strict';
2
+
3
+ import { LooseObject } from './helpers.js';
4
+ import { McEvent } from './McEvent.js';
5
+
6
+ var isBrowser = new Function(
7
+ 'try {return this===window;}catch(e){ return false;}'
8
+ );
9
+
10
+ let nativeEventNames: Set<string> = new Set();
11
+
12
+ // HTMLElement native event names
13
+ if (isBrowser()) {
14
+ Object.keys(HTMLElement.prototype)
15
+ .filter((key) => /^on/.test(key))
16
+ .forEach((eventName) => nativeEventNames.add(eventName));
17
+ }
18
+
19
+ export interface HTMLMcElement extends HTMLElement {
20
+ _mc: LooseObject;
21
+ }
22
+
23
+ // get all microcomponents from a list of HTMLElements
24
+ function getMicroComponents(elements: any[], search: string): any[] {
25
+ let mcValues: any[] = [];
26
+
27
+ elements.forEach((e) => {
28
+ if (e) {
29
+ if (e instanceof HTMLElement) {
30
+ const _mc = (e as any)?._mc;
31
+ if (!search && _mc) {
32
+ mcValues = mcValues.concat(Object.values((e as any)._mc));
33
+ } else if (search && _mc && _mc[search]) {
34
+ mcValues.push(_mc[search]);
35
+ }
36
+ }
37
+ }
38
+ });
39
+ return mcValues;
40
+ }
41
+
42
+ // get all ancestor DOM nodes up to the document root
43
+ function traverseNodes(
44
+ node: { [key: string]: any },
45
+ search: string,
46
+ firstonly = true
47
+ ): any[] {
48
+ let mcValues: any[] = [];
49
+ while (node) {
50
+ if (node._mc) {
51
+ if (!search) {
52
+ mcValues = mcValues.concat(Object.values(node._mc));
53
+ } else if (search && node._mc[search]) {
54
+ mcValues.push(node._mc[search]);
55
+ }
56
+ if (firstonly) return mcValues;
57
+ }
58
+ node = node.parentNode;
59
+ }
60
+ return mcValues;
61
+ }
62
+
63
+ function isDOM(element: { [key: string]: any }) {
64
+ return element && element instanceof HTMLElement;
65
+ }
66
+
67
+ function addListener(
68
+ domNode: Node,
69
+ eventName: string,
70
+ handler: EventListenerOrEventListenerObject | null,
71
+ capture: boolean = false,
72
+ once: boolean = false
73
+ ) {
74
+ let options: EventListenerOptions & { once: boolean } = { once: false };
75
+ if (capture) {
76
+ options.capture = capture;
77
+ }
78
+
79
+ if (once) {
80
+ options.once = once;
81
+ }
82
+
83
+ //console.log( 'addEventListener', eventName, ( handler as Function ).name, options );
84
+ domNode.addEventListener(eventName, handler, options);
85
+ }
86
+
87
+ function removeListener(
88
+ domNode: Node,
89
+ eventName: string,
90
+ handler: EventListenerOrEventListenerObject | null
91
+ ) {
92
+ domNode.removeEventListener(eventName, handler);
93
+ }
94
+
95
+ // add a microcomponent to a target DOM node
96
+ function add(target: HTMLElement, key: string, element = {}): any {
97
+ let node = target as HTMLMcElement;
98
+
99
+ // create the _mc property if necessary
100
+ if (!node._mc) {
101
+ let debug = (DC as any)?.debug;
102
+ (DC as any).debug = false;
103
+ node._mc = new (DC as any)(target);
104
+ (DC as any).debug = debug;
105
+ delete node._mc._mc; // NOT NEEDED on the top level _mc property of a DOM HTMLElement
106
+ }
107
+
108
+ const _mc = node._mc;
109
+
110
+ // add the element with the given property key to the _mc property
111
+ if (key.length && !_mc[key]) {
112
+ _mc[key] = element;
113
+ // add attribute if HTMLElement
114
+ if (target instanceof HTMLElement) {
115
+ target.setAttribute('_mc', '');
116
+ }
117
+ }
118
+ return element;
119
+ }
120
+
121
+ // remove a micro component from the DOM
122
+ function remove(target: HTMLMcElement, key: string) {
123
+ if (!key) return; // silent fail
124
+
125
+ const _mc = target?._mc || {};
126
+
127
+ // delete the property from the HTMLElement _mc collection
128
+ if (_mc && _mc[key]) {
129
+ delete _mc[key];
130
+ }
131
+
132
+ // remove the _mc attribute if the DOM collection is empty
133
+ if (
134
+ !Object.keys(_mc).length &&
135
+ target instanceof HTMLElement &&
136
+ target.hasAttribute('_mc')
137
+ ) {
138
+ target.removeAttribute('_mc');
139
+ }
140
+ return;
141
+ }
142
+
143
+ // trigger an event
144
+ function trigger(
145
+ target: HTMLElement,
146
+ ev: McEvent | string,
147
+ data: any = {},
148
+ bubble: string = 'l'
149
+ ) {
150
+ let _mc = (target as any)?._mc;
151
+ if (!_mc) return;
152
+
153
+ let event =
154
+ ev instanceof McEvent
155
+ ? new McEvent(ev.type, ev.data, 'l')
156
+ : new McEvent(ev, data, 'l'),
157
+ mcEvent: McEvent =
158
+ typeof ev !== 'string' ? (ev as McEvent) : new McEvent(ev, data, bubble);
159
+
160
+ [...Object.values(_mc)].forEach((mc: any) => {
161
+ //console.log( 'mc [', mc.constructor.name, ']', mc.constructor.prototype?.oneInit );
162
+ if ((mc as any)?.trigger && typeof (mc as any)?.trigger === 'function') {
163
+ (mc as any)?.trigger(event);
164
+ }
165
+ });
166
+
167
+ if (/[ud]/.test(mcEvent.bubble)) {
168
+ bubbleEvent(target, mcEvent);
169
+ }
170
+
171
+ return;
172
+ }
173
+
174
+ // run the "init" lifecycle event on the complete _mc structure
175
+ function init(element: MC | DC) {
176
+ if (element.constructor === DC) return;
177
+
178
+ setTimeout(() => {
179
+ element.trigger('Init');
180
+ /*
181
+ let keys = Object.keys( ( element as any)?._mc );
182
+ if ( keys.length ){
183
+ //console.log( 'inner Inits on [', mc.constructor.name, ']', keys );
184
+ keys?.forEach( (key: string) => {
185
+ let mc = ( element as any)?._mc?.[key];
186
+ //console.log( key, typeof mc?.oneInit, mc );
187
+ if ( ( mc as any )['oneInit'] && typeof ( mc as any ).oneInit == 'function' ){
188
+ ( mc as any ).oneInit( new McEvent('Init') );
189
+ }
190
+ });
191
+ };
192
+ */
193
+ }, 0);
194
+ }
195
+
196
+ function autoAttachListeners(element: MC | DC) {
197
+ if (!isBrowser() || element.constructor === DC) return;
198
+
199
+ const target = element.target;
200
+
201
+ if (target instanceof HTMLElement) {
202
+ let that: LooseObject = element;
203
+ Object.getOwnPropertyNames(that.constructor.prototype)
204
+ .filter(
205
+ (key) =>
206
+ /^on[A-Z]|one[A-Z]/.test(key) &&
207
+ typeof that.constructor.prototype[key] === 'function'
208
+ )
209
+ .forEach((key) => {
210
+ let once = /^one/.test(key),
211
+ withoutOnOne = key.replace(/^on[e]{0,1}/, ''), // preserves upper/lowercase for non-native events
212
+ nativeEventName = withoutOnOne.toLowerCase(),
213
+ listener = (ev: McEvent | Event | CustomEvent) => {
214
+ that.trigger(withoutOnOne, ev);
215
+ };
216
+ if (once) {
217
+ // console.log( '...is only called once', that.constructor.prototype[key] );
218
+ Object.defineProperty(element, 'on' + withoutOnOne, {
219
+ configurable: true,
220
+ enumerable: false,
221
+ writable: true,
222
+ value: (ev: any) => {
223
+ // console.log( 'onceHandler execute:', that.constructor.prototype[key] );
224
+ that.constructor.prototype[key].bind(that)(ev);
225
+ },
226
+ });
227
+ }
228
+
229
+ if (nativeEventNames.has('on' + nativeEventName)) {
230
+ // native event defined in HTMLElement
231
+ // console.log('added as native listener', target, nativeEventName );
232
+ addListener(target, nativeEventName, listener, false, once);
233
+ }
234
+ });
235
+ }
236
+ }
237
+
238
+ function bubbleEvent(target: HTMLElement, ev: McEvent) {
239
+ // at this point, either 'u' or 'd' bubbling should be indicated
240
+ // mcEvent bubbling is asynchronous, and the order of target MC execution in case of multiple matches is not guaranteed!
241
+ if (/[ud]/.test(ev.bubble)) {
242
+ setTimeout(() => {
243
+ // bubbling must include 'l' for local, or else no handlers are executed'
244
+ if (ev.bubble.indexOf('l') === -1) {
245
+ ev.bubble += 'l';
246
+ }
247
+
248
+ // bubble up towards root
249
+ if (ev.bubble.indexOf('u') > -1) {
250
+ let parent = traverseNodes(target, '', true)?.[0].target;
251
+ if (parent) DC.trigger(parent, ev);
252
+ }
253
+
254
+ // bubble down
255
+ if (ev.bubble.indexOf('d') > -1) {
256
+ let targets = new Set<HTMLMcElement>(
257
+ (target as HTMLMcElement)._mc
258
+ .children()
259
+ .map((c: unknown) => (c as any)?.target)
260
+ );
261
+ targets.forEach((target: HTMLMcElement) => {
262
+ if (target) DC.trigger(target, ev);
263
+ });
264
+ }
265
+ }, 0);
266
+ }
267
+ }
268
+
269
+ class McBase {
270
+ #target: WeakRef<any>; // avoid circular reference
271
+
272
+ constructor(target?: { [key: string]: any }, debug: boolean = false) {
273
+ let that: unknown = this,
274
+ element = that as MC | DC;
275
+
276
+ this.#target = new WeakRef(target || {});
277
+
278
+ init(element); // async lifecycle event
279
+
280
+ autoAttachListeners(element);
281
+ }
282
+
283
+ get target(): any {
284
+ return this.#target.deref();
285
+ }
286
+ }
287
+
288
+ class MC extends McBase {
289
+ _mc: { [key: string]: any } = {};
290
+
291
+ constructor(target?: any) {
292
+ super(target);
293
+ }
294
+
295
+ static trigger = trigger;
296
+
297
+ trigger(ev: McEvent | string, data: any = {}, bubble: string = 'l') {
298
+ let that = this;
299
+
300
+ //console.log( that, '.trigger(', ev, data, bubble, ')' );
301
+
302
+ // run all triggers
303
+ if (that.constructor === MC || that.constructor === DC) {
304
+ let event =
305
+ ev instanceof McEvent
306
+ ? new McEvent(ev.type, ev.data, 'l')
307
+ : new McEvent(ev, data, 'l'),
308
+ mcEvent: McEvent =
309
+ typeof ev !== 'string'
310
+ ? (ev as McEvent)
311
+ : new McEvent(ev, data, bubble);
312
+ [...Object.getOwnPropertyNames(that)].forEach((mc) => {
313
+ if (
314
+ (that as any)[mc]?.trigger &&
315
+ typeof (that as any)[mc]?.trigger === 'function'
316
+ ) {
317
+ (that as any)[mc]?.trigger(event);
318
+ }
319
+ });
320
+
321
+ if (/[ud]/.test(mcEvent.bubble)) {
322
+ bubbleEvent(that.target, mcEvent);
323
+ }
324
+
325
+ return; // must return here!
326
+ }
327
+
328
+ // only this instance
329
+ if ((that as any) instanceof MC || (that as any) instanceof DC) {
330
+ const that = this,
331
+ mcEvent: McEvent =
332
+ typeof ev !== 'string'
333
+ ? (ev as McEvent)
334
+ : new McEvent(ev, data, bubble),
335
+ handlerName =
336
+ 'on' + mcEvent.type[0].toUpperCase() + mcEvent.type.slice(1);
337
+ // console.log('trigger', handlerName, mcEvent, data, bubble );
338
+
339
+ if (mcEvent.bubble.indexOf('l') > -1) {
340
+ if (
341
+ !mcEvent.immediateStopped &&
342
+ typeof (that as any)[handlerName] === 'function'
343
+ ) {
344
+ // console.log( 'execute handler:', handlerName );
345
+ (that as any)[handlerName](mcEvent);
346
+ if ((that as any).hasOwnProperty(handlerName)) {
347
+ // it is a once handler
348
+ delete (that as any)[handlerName]; // remove after first execution
349
+ }
350
+ }
351
+ }
352
+
353
+ // if event stopped or local only, handling is cancelled
354
+ if (mcEvent.stopped || mcEvent.bubble === 'l') {
355
+ return that;
356
+ }
357
+
358
+ //console.log('bubble', mcEvent);
359
+ if (/[ud]/.test(mcEvent.bubble)) {
360
+ bubbleEvent(that.target, mcEvent);
361
+ }
362
+ }
363
+ }
364
+ }
365
+
366
+ class DC extends McBase {
367
+ _mc: { [key: string]: any } = {};
368
+
369
+ constructor(target: HTMLElement, debug: boolean = false) {
370
+ super(target);
371
+ }
372
+
373
+ static add: Function = add;
374
+ static remove: Function = remove;
375
+ static trigger: Function = trigger;
376
+
377
+ trigger(ev: McEvent | string, data: any = {}, bubble?: string) {
378
+ MC.prototype.trigger.call(this, ev, data, bubble);
379
+ }
380
+
381
+ parent(search: string = ''): any[] {
382
+ let target: HTMLElement = (this as any).target;
383
+ if (!isDOM(target)) return [];
384
+ return traverseNodes((target as any).parentNode, search, true);
385
+ }
386
+
387
+ ancestors(search: string = ''): any[] {
388
+ let target: any = (this as any)?.target;
389
+ if (!isDOM(target)) return [];
390
+ return traverseNodes((this as any).target.parentNode, search, false);
391
+ }
392
+
393
+ children(search: string = ''): any[] {
394
+ let target: any = (this as any)?.target;
395
+ if (!isDOM(target)) return [];
396
+ const id = Math.random().toString().replace('.', '');
397
+ const selector = '[_mc]:not([temp_id="' + id + '"] [_mc] [_mc])';
398
+ target.setAttribute('temp_id', id);
399
+ const myDomElements = target.querySelectorAll(selector);
400
+ const mcValues = getMicroComponents([...myDomElements], search);
401
+ target.removeAttribute('temp_id');
402
+ return mcValues;
403
+ }
404
+
405
+ descendants(search: string = ''): any[] {
406
+ let target: any = (this as any)?.target;
407
+ if (!isDOM(target)) return [];
408
+ const myDomElements = target.querySelectorAll('*[_mc]');
409
+ return getMicroComponents([...myDomElements], search);
410
+ }
411
+ }
412
+
413
+ export { addListener, removeListener, McBase, MC, DC, McEvent };
@@ -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 './elements.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
+ */
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
- import { DC } from './MC.js';
4
- import { kebabToPascal } from './helpers.js';
3
+ import { DC } from "./MC.js";
4
+ import { kebabToPascal } from "./helpers.js";
5
5
 
6
6
  class CeBaseClass extends HTMLElement {
7
7
  constructor() {
@@ -9,34 +9,43 @@ class CeBaseClass extends HTMLElement {
9
9
  }
10
10
 
11
11
  connectedCallback() {
12
- (DC as any).trigger(this, 'Connected');
12
+ (DC as any).trigger(this, "Connected");
13
13
  }
14
14
 
15
15
  disconnectedCallback() {
16
- (DC as any).trigger(this, 'Disconnected');
16
+ (DC as any).trigger(this, "Disconnected");
17
17
  }
18
18
 
19
19
  adoptedCallback() {
20
- (DC as any).trigger(this, 'Adopted');
20
+ (DC as any).trigger(this, "Adopted");
21
21
  }
22
22
 
23
23
  attributeChangedCallback(name: string, oldValue: any, newValue: any) {
24
- (DC as any).trigger(this, 'AttributeChanged', { name, oldValue, newValue });
24
+ (DC as any).trigger(this, "AttributeChanged", { name, oldValue, newValue });
25
25
  }
26
26
  }
27
27
 
28
- function createNamedClass(name: string, ClassBody: { new (...args: any[]): any } ) {
29
- return Object.defineProperty( ClassBody, 'name', { value: name });
28
+ function createNamedClass(
29
+ name: string,
30
+ ClassBody: { new (...args: any[]): any }
31
+ ) {
32
+ return Object.defineProperty(ClassBody, "name", { value: name });
30
33
  }
31
34
 
32
- export function defineCE( tagName: string, DefinitionClass: { new (...args: any[]): any }, observedAttributes: string[] = []){
35
+ export function defineCE(
36
+ tagName: string,
37
+ DefinitionClass: { new (...args: any[]): any },
38
+ observedAttributes: string[] = []
39
+ ) {
33
40
  if (customElements.get(tagName)) {
34
41
  console.warn(`IGNORED: Custom element "${tagName}" is already defined!`);
35
42
  return;
36
43
  }
37
44
 
38
- if (!tagName.includes('-')) {
39
- throw new Error('createCustomElement: tagName must contain at least one hyphen ("-").');
45
+ if (!tagName.includes("-")) {
46
+ throw new Error(
47
+ 'createCustomElement: tagName must contain at least one hyphen ("-").'
48
+ );
40
49
  }
41
50
 
42
51
  let name = kebabToPascal(tagName);
@@ -48,10 +57,10 @@ export function defineCE( tagName: string, DefinitionClass: { new (...args: any[
48
57
  class extends CeBaseClass {
49
58
  instance: any;
50
59
 
51
- constructor( data?: any ) {
60
+ constructor(data?: any) {
52
61
  super();
53
62
  let instance = new DefinitionClass(this, data);
54
- ( DC as any ).add(this, name, instance );
63
+ (DC as any).add(this, name, instance);
55
64
  }
56
65
 
57
66
  static get observedAttributes() {
@@ -60,7 +69,7 @@ export function defineCE( tagName: string, DefinitionClass: { new (...args: any[
60
69
  }
61
70
  )
62
71
  );
63
- };
72
+ }
64
73
 
65
74
  export function getCE(tagName: string): CustomElementConstructor | undefined {
66
75
  return customElements.get(tagName);