vaderjs 1.3.3-alpha-41 → 1.3.3-alpha-43

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/runtime/vader.js CHANGED
@@ -1,152 +1,29 @@
1
-
2
- window.params = {};
3
1
  window.Vader = {
4
2
  version: "1.3.3",
5
3
  };
6
-
4
+ window.componentRegistry = {};
7
5
  let errors = {
8
6
  "SyntaxError: Unexpected token '<'": "You forgot to enclose tags in a fragment <></>",
9
- }
7
+ }
10
8
 
11
- const path = {
12
- basename: (path) => {
13
- return path.split("/").pop();
14
- },
15
-
16
- }
17
-
18
- window.queryRef = (ref) => {
19
- return document.querySelector(`[data-ref="${ref}"]`)
20
- }
21
- window.reinvoke = (eventtype, element) => {
22
- const eventListener = (e) => {
23
- return e
24
- };
25
-
26
- // Check if the event listener has not been added before adding it
27
- if (!element._eventListenerAdded) {
28
- element.addEventListener(eventtype, eventListener);
29
-
30
- // Set the flag to indicate that the event listener has been added
31
- element._eventListenerAdded = true;
32
-
33
- // Trigger the event without overwriting existing data or listeners
34
- element.dispatchEvent(new Event(eventtype));
35
- }
36
- };
37
-
38
-
39
-
40
-
41
- let invokes = []
42
- let hasran = [];
43
- let states = {};
44
9
  let mounts = [];
10
+ /**
11
+ * @method strictMount
12
+ * @description This method allows you to await until the component is mounted before running a callback
13
+ * @param {*} key
14
+ * @param {*} callback
15
+ */
45
16
  export const strictMount = (key, callback) => {
46
17
  let timer = setInterval(() => {
47
- if (document.querySelector('[key="' + key + '"]')) {
18
+ if (mounts.find((m) => m.key === key)) {
48
19
  clearInterval(timer);
49
20
  callback();
50
21
  }
51
22
  }, 120);
52
23
  };
53
-
54
- window.delegate = (event) => {
55
- return event.detail.target
56
- }
57
-
58
- let components = {};
59
24
 
60
- let style = document.createElement("style");
61
- document.head.appendChild(style);
62
-
63
- const parseStyles = async (styles, className = '') => {
64
- let css = await fetch(styles).then((res) => res.text());
65
- let classes = css.split("}");
66
- let parsedClasses = {};
67
- classes.forEach((cls) => {
68
-
69
- let name = cls.split(".")[1];
70
- let value = cls.split("{")[1]
71
- let keys = value.split(";");
72
- let newKeys = [];
73
- keys.forEach((key) => {
74
- if (key.includes(":")) {
75
- let newKey = key.split(":")[0].trim();
76
- let newValue = key.split(":")[1].trim();
77
- newKeys.push(`${newKey}: "${newValue}"`);
78
- }
79
- });
80
- value = `{${newKeys.join(",")}}`;
81
-
82
-
83
- parsedClasses[name] = JSON.stringify(value);
84
- });
85
- return parsedClasses;
86
- };
87
-
88
-
89
- export const stylis = {
90
- /**
91
- * @method create
92
- * @param {*} styles
93
- * @returns {Object} classes
94
- * @description This method allows you to create css classes from an object
95
- */
96
- create: async (/**@type {string} */ styles) => {
97
-
98
- return await parseStyles(styles);
99
- },
100
- };
101
-
102
- /**
103
- * @method mem
104
- * @param {Component} component
105
- * @returns {Component} Stateless Component
106
- * @description This method allows you to memoize a component - this means it will be intialized only once and can be reused multiple times baased on a static key
107
- */
108
- export const mem = (/**@type {Component}**/ component) => {
109
- // ensure component is instance of Component
110
- switch (true) {
111
- case !(component instanceof Component):
112
- throw new Error("component must be an instance of Component");
113
- case !component.key:
114
- throw new Error("component must have a static key");
115
- // check if key was randomly generated
116
- }
117
- let key = component.key;
118
- if (!components[key]) {
119
- components[key] = component;
120
- }
121
-
122
- return components[key];
123
- };
124
-
125
- /**
126
- * @method invoke
127
- * @description This method allows you to invoke a function from its id
128
- * @param {*} name
129
- * @param {*} params
130
- * @returns
131
- * @example
132
- * invoke(this.functions['test'], 'hello') // this will invoke the function test with the params hello
133
- */
134
25
 
135
- let functions = {};
136
26
 
137
- export const invoke = (func, params) => {
138
- let name = func.name;
139
-
140
- window[name] = function (params) {
141
- return func(params);
142
- }
143
- window[name] = window[name].bind(this);
144
-
145
-
146
- return `${name}(${params})`;
147
-
148
- };
149
-
150
27
  /**
151
28
  * Represents a component in the Vader framework.
152
29
  */
@@ -158,20 +35,10 @@ export class Component {
158
35
  this.state = {};
159
36
  this.key = null;
160
37
  this.components = {};
161
- this.mounted = false;
162
- this.currenthtml = null;
163
- window.listeners = [];
164
- this.functionMap = new Map();
165
- this.freeMemoryFromFunctions();
38
+ this.mounted = false;
166
39
  this.checkIFMounted();
167
40
  this.memoizes = []
168
- /**
169
- * @type {boolean}
170
- * @description Indicates if the component is a child component
171
- */
172
- this.isChild = false;
173
- this.vdom = []
174
-
41
+ this.functions = []
175
42
  this.children = []
176
43
 
177
44
 
@@ -285,23 +152,21 @@ export class Component {
285
152
  comp.parentNode = this;
286
153
  comp.request = this.request;
287
154
  comp.response = this.response;
288
- comp.isChild = true;
289
- delete comp.router
290
155
  comp.key = props.key || null;
291
156
 
292
157
  if(!this.components[props.key]){
293
- states[props.key] = {}
294
- }
295
- this.components[props.key] = comp
158
+ this.components[props.key] = comp;
159
+ }
296
160
  this.children.push(comp)
297
161
  return this.components[props.key]
298
162
  }
299
163
  reset(){
164
+ console.log('reset')
300
165
  Object.keys(this.components).forEach((key) => {
301
- states[key] = {}
166
+ this.components[key].onUnmount()
167
+ delete this.components[key]
302
168
  })
303
- states[this.key] = {}
304
- this.components = {}
169
+ this.state = {}
305
170
  this.children = []
306
171
  }
307
172
  memoize(/**@type {Component}**/component){
@@ -316,7 +181,11 @@ export class Component {
316
181
  }
317
182
 
318
183
  let comp = this.components[component.key];
319
- comp.props = component.props;
184
+ comp.bindMount();
185
+ comp.parentNode = this;
186
+ comp.props = component.props;
187
+ comp.request = this.request;
188
+ comp.response = this.response;
320
189
  let h = comp.render()
321
190
 
322
191
  if(h && h.split('>,').length > 1){
@@ -427,19 +296,7 @@ export class Component {
427
296
  return eval(obj);
428
297
  }
429
298
 
430
- /**
431
- * Frees memory from functions that have not been used for a certain period of time.c
432
- * @private
433
- */
434
- freeMemoryFromFunctions() {
435
- setInterval(() => {
436
- for (var [key, value] in this.functionMap) {
437
- if (Date.now() - value.lastUsed > 1000) {
438
- this.functionMap.delete(key);
439
- }
440
- }
441
- }, 1000);
442
- }
299
+
443
300
 
444
301
  /**
445
302
  * Binds a function to the component.
@@ -448,134 +305,58 @@ export class Component {
448
305
  * @param {string} ref - The reference.
449
306
  * @returns {string} - A valid inline JS function call.
450
307
  */
451
- bind(funcData,jsx,ref, paramNames, ...params) {
308
+ bind(funcTion,isTerny, jsx,ref, paramNames, ...params) {
309
+ ref = ref + this.key;
310
+
311
+ let paramObject = {};
452
312
 
453
-
454
- const name = `func_${crypto ? crypto.getRandomValues(new Uint32Array(1))[0] : Math.random()}`;
455
-
456
- var dynamicFunction = async (...params) => {
457
-
458
- // Replace double commas with a single comma
313
+
314
+ paramNames = paramNames.replace(/,,/g, ',');
315
+ let newparamnames = paramNames.replaceAll(',,', ',')
459
316
 
460
-
461
- // Turn params into a destructured object
462
- let paramObject = {};
463
- params = params[0]
317
+ for(var i in params){
318
+ let param = params[i]
319
+ let paramname = newparamnames.split(',')[i]
320
+ paramObject[paramname] = param
321
+ }
322
+
464
323
 
465
- paramNames = paramNames.replace(/,,/g, ',');
466
- let newparamnames = paramNames.replaceAll(',,', ',')
467
-
468
-
469
- for(var i in params){
470
- paramObject[newparamnames.split(',')[i]] = params[i]
471
- }
472
-
473
-
474
-
324
+
475
325
  paramNames = paramNames.replace(',,', ',');
476
326
  let func = new Function(`${paramNames}`, `
477
- return (async (${paramNames}) => {
478
- ${funcData}
479
- })(${Object.keys(paramObject).join(',')})
480
- `);
481
- await func.bind(this)(...Object.values(paramObject));
482
-
483
- };
327
+ return (async (${paramNames}) => {
328
+ ${funcTion.toString()}
329
+ })(${Object.keys(paramObject).join(',')})
330
+ `);
331
+ func = func.bind(this)
332
+
333
+ if(!this.functions.find((f) => f.ref === ref)){
334
+ document.addEventListener(`$dispatch_#id=${ref}`, (e) => {
335
+ let { name, event } = e.detail;
336
+ if (name === ref) {
337
+ let params = this.functions.find((f) => f.ref === ref).params
338
+ Object.keys(params).forEach((key) => {
339
+ if(params[key] instanceof CustomEvent){
340
+ delete params[key]
341
+ }
342
+ params[key] === undefined ? delete params[key] : params[key]
343
+ })
344
+ isTerny ? funcTion(event, ...Object.values(params)) : func(...Object.values(params))
345
+ }
346
+ });
347
+
348
+ }
484
349
 
485
-
486
- dynamicFunction = dynamicFunction.bind(this);
487
- if (!this.functionMap.has(name)) {
488
- document.addEventListener(`call_${name}`, (e) => {
489
-
490
- dynamicFunction(params)
491
- this.functionMap.set(e.detail.name, {
492
- lastUsed: Date.now(),
493
- });
494
- });
495
- }
496
-
497
- this.functionMap.set(name, {
498
- lastUsed: Date.now(),
499
- });
500
-
501
- window.call = (name, eventdata, params) => {
502
- document.dispatchEvent(
503
- new CustomEvent(`call_${name}`, {
504
- detail: { name: `call_${name}`, target: eventdata },
505
- })
506
- );
507
- };
508
-
509
- // Return a valid inline js function call
510
- function jsxCall(){
511
- document.dispatchEvent(
512
- new CustomEvent(`call_${name}`, {
513
- detail: { name: `call_${name}` },
514
- })
515
- );
516
- }
517
- return jsx ? jsxCall: `
518
- ((event) => {
519
- event.target.setAttribute('data-ref', '${ref}');
520
- let reference = event.target.getAttribute('data-ref');
521
- event.target.eventData = event;
522
- event.target.data = event
523
- call('${name}', {event:event.target.data}, '${paramNames}')
524
- })(event)
525
- `;
526
- }
527
-
528
- /**
529
- * Calls a function with the specified parameters. and dispatches an event.
530
- * @param {string} func - The function name.
531
- * @param {...*} params - The function parameters.
532
- */
533
- callFunction(func, isInlineJsx, ...params) {
534
- if(!isInlineJsx && params[0] && params[0].detail){
535
- let el = params[0].detail.target.event.target
536
- params[0].data = el.value;
537
- params[0] = params[0].detail.target.event
538
- }
539
- func = func.replace(/'/g, '');
540
- document.dispatchEvent(new CustomEvent(func, { detail: { name: func, params: params } }));
541
- }
542
-
543
- /**
544
- * Uses a function with the specified parameters.
545
- * @param {Function} func - The function to use.
546
- * @param {string} params - The function parameters.
547
- * @param {boolean} [isInlineJsx=false] - Indicates if the function is an inline JSX.
548
- * @returns {string} - The function call.
549
- */
550
- useFunction(func, params, isInlineJsx = false) {
551
- const sanitizedFuncName = func.name.trim().replace(/\s+/g, '_');
552
-
553
- if (!invokes.includes(`'${sanitizedFuncName}'${this.key}`)) {
554
- invokes.push(`'${sanitizedFuncName}'${this.key}`);
555
- document.addEventListener(`call_${sanitizedFuncName}_${this.key}`, (e) => {
556
- let { name, params } = e.detail;
557
- if (name === `call_${sanitizedFuncName}_${this.key}`) {
558
- let isarray = Array.isArray(params);
559
-
560
- func(...(isarray ? params : [params]));
561
- }
562
- });
563
-
564
- func = func.bind(this);
565
- }
566
-
567
- try {
568
- params = JSON.parse(params);
569
- } catch (error) {
570
- // Handle JSON parsing error if needed
571
- }
572
-
573
- const returnString = isInlineJsx
574
- ? `'call_${sanitizedFuncName}_${this.key}'`
575
- : `document.dispatchEvent(new CustomEvent('call_${sanitizedFuncName}_${this.key}', { detail: { name: 'call_${sanitizedFuncName}_${this.key}', params: ${JSON.stringify(params)} } }))`;
576
-
577
- return returnString;
350
+ window.callFunction = (name, event) => {
351
+ document.dispatchEvent(new CustomEvent(`$dispatch_#id=${name}`, { detail: { name: name, params: null, event: event } }));
352
+ }
353
+ !this.functions.find((f) => f.ref === ref) ? this.functions.push({ref: ref, params: paramObject}) : !isTerny ? this.functions.find((f) => f.ref === ref).params = paramObject : null
354
+
355
+
356
+ return jsx ? funcTion : `((event)=>{event.target.ev = event; callFunction('${ref}', event.target.ev)})(event)`;
578
357
  }
358
+
359
+
579
360
 
580
361
  /**
581
362
  * useState hook.
@@ -586,8 +367,8 @@ export class Component {
586
367
  * @returns {[() => T, (newValue: T, hook: Function) => void]} - A tuple with getter and setter functions.
587
368
  */
588
369
  useState(key, initialState) {
589
- if (!states[this.key][key]) {
590
- states[this.key][key] = initialState;
370
+ if (!this.state[key]) {
371
+ this.state[key] = initialState;
591
372
  }
592
373
 
593
374
  /**
@@ -595,7 +376,7 @@ export class Component {
595
376
  *
596
377
  * @returns {T} The current state value.
597
378
  */
598
- let updatedValue = () => states[this.key][key];
379
+ let updatedValue = () => this.state[key];
599
380
 
600
381
  const getValue = updatedValue();
601
382
 
@@ -606,7 +387,7 @@ export class Component {
606
387
  * @param {Function} hook - The hook to hydrate after setting the value.
607
388
  */
608
389
  const set = (newValue, hook) => {
609
- states[this.key][key] = newValue;
390
+ this.state[key] = newValue;
610
391
  this.hydrate(hook);
611
392
  };
612
393
 
@@ -634,14 +415,16 @@ export class Component {
634
415
  }
635
416
  }
636
417
 
637
- useReducer(key = null, initialState, func = null) {
418
+ useReducer(key = null, initialState, func = null) {
638
419
  const getValue = () => this.state[key];
420
+ const value = getValue();
639
421
  const set = (newValue) => {
640
-
641
- this.hydrate();
422
+ const nextState = func ? func(this.state[key], newValue) : newValue;
423
+ this.state[key] = nextState;
642
424
  };
643
- return [getValue, set];
425
+ return [value, set];
644
426
  }
427
+
645
428
 
646
429
  /**
647
430
  * Placeholder for content to be rendered.
@@ -654,14 +437,24 @@ export class Component {
654
437
  * @private
655
438
  */
656
439
  checkIFMounted() {
657
- if (this.mounted || !this.key) return;
658
- let timer = setInterval(() => {
659
- if (document.querySelector('[key="' + this.key + '"]')) {
660
- clearInterval(timer);
661
- this.mounted = true;
662
- this.onMount();
663
- }
664
- }, 120);
440
+ let observer = new MutationObserver((mutations) => {
441
+ mutations.forEach((mutation) => {
442
+
443
+ if (mutation.target.querySelector(`[key="${this.key}"]`) && !this.mounted) {
444
+ this.onMount();
445
+ this.mounted = true;
446
+ }
447
+
448
+ if(Array.from(mutation.removedNodes).find((node) => node.attributes && node.attributes.key && node.attributes.key.value === this.key)){
449
+ this.onUnmount();
450
+ this.reset();
451
+ }
452
+ })
453
+ })
454
+ observer.observe(document.body, {
455
+ childList: true,
456
+ subtree: true,
457
+ });
665
458
  }
666
459
 
667
460
  /**
@@ -669,69 +462,15 @@ export class Component {
669
462
  * @method onMount
670
463
  */
671
464
  onMount() {}
465
+ /**
466
+ * Method that is called when the component is unmounted.
467
+ * @method onUnmount
468
+ */
469
+ onUnmount() {}
672
470
  }
673
471
 
674
-
675
-
676
-
677
-
678
- let cache = {};
679
- /**
680
- * @method require
681
- * @description Import CommonJS modules like Node.js for the browser
682
- * @param {string} path
683
- * @param {Boolean} noresolve - used to tell if the path should be automatically handled or manually handled - this is false by default
684
- * @returns
685
- */
686
- export const require = async (path, options) => {
687
-
688
- if (cache[path]) {
689
- return cache[path];
690
- }
691
- let file = ''
692
- try {
693
- file = await fetch(path).then((res) => options && options.type === 'json' ? res.json() : res.text());
694
-
695
- } catch (error) {
696
- console.error(error)
697
- }
698
-
699
-
700
-
701
- let filetype = path.split(".").pop();
702
- filetype !== "json" ? file = file + `\n//# sourceURL=${path}\n` : null;
703
- switch (true) {
704
- case filetype === "js":
705
- let exports = file.match(/module.exports\s*=\s*{.*}/gs) || file.match(/exports\s*=\s*{.*}/gs);
706
- exports = exports ? exports[0] : null;
707
-
708
- if (exports) {
709
- let keys = exports.split("{")[1].split("}")[0].split(",");
710
- let returnstring = "";
711
- keys.forEach((key) => {
712
- key = key.trim();
713
- returnstring += `${key},`;
714
- });
715
- returnstring = `return {${returnstring}}`;
716
- file = file += returnstring;
717
- file = file.replaceAll(exports, "");
718
- }
719
-
720
- cache[path] = new Function(`return (async () => { ${file} })()`)();
721
- return cache[path]
722
- case filetype === "json":
723
- cache[path] = file
724
- return cache[path]
725
-
726
- case filetype === "jsx":
727
- cache[path] = new Function(`return (async () => { ${file} })()`)();
728
- return cache[path]
729
-
730
- }
731
- };
732
-
733
-
734
- window.require = require;
472
+
473
+
735
474
  /**
736
475
  * useState hook.
737
476
  *
@@ -776,17 +515,7 @@ export const useState = (key, initialState) => {
776
515
  export const useReducer = (/**@type {*}**/initialState, /**@type {function}**/reducer) => {
777
516
  return [initialState, (newValue) => {}];
778
517
  };
779
-
780
- const constants = {};
781
- let constantCounter = 0;
782
-
783
- export const constant = (value) => {
784
- const key = `constant_${constantCounter++}`;
785
- if (!constants[key]) {
786
- constants[key] = value;
787
- }
788
- return constants[key];
789
- };
518
+
790
519
 
791
520
  /**
792
521
  * useRef hook.
@@ -810,14 +539,9 @@ export const useRef = (initialState) => {
810
539
  };
811
540
 
812
541
  export default {
813
- Component,
814
- require,
815
- invoke,
816
- mem,
817
- constant,
542
+ Component,
818
543
  useRef,
819
544
  useReducer,
820
545
  useState,
821
- strictMount,
822
- stylis,
546
+ strictMount,
823
547
  }