vaderjs 1.3.3-alpha-45 → 1.3.3-alpha-47

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,547 +1 @@
1
- window.Vader = {
2
- version: "1.3.3",
3
- };
4
- window.componentRegistry = {};
5
- let errors = {
6
- "SyntaxError: Unexpected token '<'": "You forgot to enclose tags in a fragment <></>",
7
- }
8
-
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
- */
16
- export const strictMount = (key, callback) => {
17
- let timer = setInterval(() => {
18
- if (mounts.find((m) => m.key === key)) {
19
- clearInterval(timer);
20
- callback();
21
- }
22
- }, 120);
23
- };
24
-
25
-
26
-
27
- /**
28
- * Represents a component in the Vader framework.
29
- */
30
- export class Component {
31
- /**
32
- * Creates an instance of Component.
33
- */
34
- constructor() {
35
- this.state = {};
36
- this.key = null;
37
- this.components = {};
38
- this.mounted = false;
39
- this.checkIFMounted();
40
- this.memoizes = []
41
- this.functions = []
42
- this.children = []
43
-
44
-
45
- /**
46
- * Parent of the current component.
47
- * @type {Component}
48
- */
49
- this.parentNode = {}
50
-
51
- /**
52
- * Request object.
53
- */
54
- this.request = {
55
- /**
56
- * @type {string}
57
- * @description The headers for the current route
58
- */
59
- headers:{},
60
- /**
61
- * @type {string}
62
- * @description The method for the current route
63
- */
64
- method: "GET",
65
- /**
66
- * @type {string}
67
- * @description params for the given route /:id/:name etc
68
- */
69
- params: {},
70
- /**
71
- * @type {string}
72
- * @description path: current route path
73
- */
74
- path: "",
75
- /**
76
- * @type {string}
77
- * @description query: query object for the current route ?name=hello -> {name: 'hello'}
78
- */
79
- query: {},
80
- },
81
- /**
82
- * @type {string}
83
- * @description The response object for the current route
84
- */
85
- this.response = {
86
- /**
87
- * @method json
88
- * @description This method allows you to send json data to the client
89
- * @param {*} data
90
- */
91
- json: (data) => {},
92
- /**
93
- * @method send
94
- * @description This method allows you to send text data to the client
95
- * @param {*} data
96
- */
97
- send: (data) => {},
98
- /**
99
- * @method redirect
100
- * @description This method allows you to redirect the client to a new route
101
- * @param {*} path
102
- */
103
- redirect: (path) => {},
104
- /**
105
- * @method render
106
- * @description render a new component to the client
107
- * @param {*} Component
108
- */
109
- render: async (Component) => {},
110
- /**
111
- * @method log
112
- * @description This method is used to log the request and response
113
- * @param {String} type
114
- */
115
- log: (type) => {},
116
- /**
117
- * @method setQuery
118
- * @description This method is used to set the query object for the current route
119
- */
120
- setQuery: (query) => {},
121
-
122
- }
123
- /**
124
- * @method router
125
- * @description use router methods directly from the parent component
126
- */
127
-
128
- this.router = {
129
- /**
130
- * @method use
131
- * @description add a middleware to the current route
132
- * @param {Function} middleware
133
- * @returns {void}
134
- */
135
- use: (/**@type {Function} */ middleware) => {},
136
- }
137
- }
138
-
139
- createComponent(/**@type {Component}**/component, props, children) {
140
-
141
- if (!component) {
142
- throw new Error("Component must be defined");
143
- }
144
- if(!props.key){
145
- throw new Error('new components must have a key')
146
- }
147
- let comp = new component(props);
148
-
149
- comp['props'] = props;
150
- comp.children = children;
151
- comp.props.children = children.join('')
152
- comp.parentNode = this;
153
- comp.request = this.request;
154
- comp.response = this.response;
155
- comp.key = props.key || null;
156
-
157
- if(!this.components[props.key]){
158
- this.components[props.key] = comp;
159
- }
160
- this.children.push(comp)
161
- return this.components[props.key]
162
- }
163
- reset(){
164
- console.log('reset')
165
- Object.keys(this.components).forEach((key) => {
166
- this.components[key].onUnmount()
167
- delete this.components[key]
168
- })
169
- this.state = {}
170
- this.children = []
171
- }
172
- memoize(/**@type {Component}**/component){
173
- if(!component.key){
174
- throw new Error('Component must have a static key')
175
- }
176
- switch(true){
177
- case !this.memoizes.includes(component.key):
178
- this.memoizes.push(component.key)
179
- this.components[component.key] = component;
180
- break;
181
- }
182
-
183
- let comp = this.components[component.key];
184
- comp.bindMount();
185
- comp.parentNode = this;
186
- comp.props = component.props;
187
- comp.request = this.request;
188
- comp.response = this.response;
189
- let h = comp.render()
190
-
191
- if(h && h.split('>,').length > 1){
192
- h = h.replaceAll('>,', '>')
193
- }
194
-
195
- return `<div key="${component.key}">${h}</div>`
196
- }
197
- parseStyle(styles){
198
- let css = ''
199
- Object.keys(styles).forEach((key) => {
200
- let value = styles[key]
201
- key = key.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase()
202
- css += `${key}:${value};`
203
- })
204
- return css
205
- }
206
- bindMount(){
207
- mounts.push(this)
208
- }
209
-
210
- /**
211
- * Hydrates the component by updating the HTML content if it has changed.
212
- * @private
213
- */
214
-
215
- domDifference(oldDom, newDom) {
216
- let diff = [];
217
-
218
- for (let i = 0; i < oldDom.length; i++) {
219
- let oldEl = oldDom[i];
220
- let newEl = newDom[i];
221
-
222
- if (oldEl && newEl && !oldEl.isEqualNode(newEl)) {
223
- diff.push({
224
- type: 'replace',
225
- old: oldEl,
226
- new: newEl.cloneNode(true),
227
- });
228
- }
229
- }
230
-
231
- return diff;
232
- }
233
-
234
- updateChangedElements(diff) {
235
- diff.forEach((change) => {
236
- switch (change.type) {
237
- case 'replace':
238
- change.old.parentNode.replaceChild(change.new, change.old);
239
- break;
240
- case 'remove':
241
- change.old.remove();
242
- break;
243
- case 'add':
244
- change.old.appendChild(change.new.cloneNode(true));
245
- break;
246
- default:
247
- break;
248
- }
249
- });
250
- }
251
-
252
- hydrate(hook) {
253
- if (this.key) {
254
- if (hook) {
255
- let newDom = new DOMParser().parseFromString(this.render(), 'text/html').body.firstChild;
256
-
257
- let oldElements = document.body.querySelectorAll(`[ref="${hook}"]`);
258
- let newElements = newDom.querySelectorAll(`[ref="${hook}"]`);
259
- let diff = this.domDifference(oldElements, newElements);
260
- this.updateChangedElements(diff);
261
- } else {
262
- const targetElement = document.querySelector(`[key="${this.key}"]`);
263
- if (targetElement) {
264
- targetElement.outerHTML = this.render();
265
- } else {
266
- console.error('Target element not found.');
267
- }
268
- }
269
- }
270
- }
271
-
272
-
273
-
274
- patch(oldElements, newElements) {
275
- const diff = this.domDifference(oldElements, newElements);
276
-
277
- this.updateChangedElements(diff);
278
- }
279
-
280
-
281
-
282
-
283
-
284
- /**
285
- * Handles an object by parsing it as JSON and evaluating it.
286
- * @param {string} obj - The object to handle.
287
- * @returns {*} - The evaluated object.
288
- * @prvate
289
- */
290
- handleObject(obj) {
291
- try {
292
- obj = JSON.parse(obj);
293
- } catch (error) {
294
- // Handle JSON parsing error if needed
295
- }
296
- return eval(obj);
297
- }
298
-
299
-
300
-
301
- /**
302
- * Binds a function to the component.
303
- * @param {string} funcData - The function data.
304
- * @param {string} p - The parameter.
305
- * @param {string} ref - The reference.
306
- * @returns {string} - A valid inline JS function call.
307
- */
308
- bind(funcTion,isTerny, jsx,ref, paramNames, ...params) {
309
- ref = ref + this.key;
310
-
311
- let paramObject = {};
312
-
313
-
314
- paramNames = paramNames.replace(/,,/g, ',');
315
- let newparamnames = paramNames.replaceAll(',,', ',')
316
-
317
- for(var i in params){
318
- let param = params[i]
319
- let paramname = newparamnames.split(',')[i]
320
- paramObject[paramname] = param
321
- }
322
-
323
-
324
-
325
- paramNames = paramNames.replace(',,', ',');
326
- let func = new Function(`${paramNames}`, `
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
- }
349
-
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)`;
357
- }
358
-
359
-
360
-
361
- /**
362
- * useState hook.
363
- *
364
- * @template T
365
- * @param {string} key - The key for the state property.
366
- * @param {T} initialState - The initial state value.
367
- * @returns {[() => T, (newValue: T, hook: Function) => void]} - A tuple with getter and setter functions.
368
- */
369
- useState(key, initialState) {
370
- if (!this.state[key]) {
371
- this.state[key] = initialState;
372
- }
373
-
374
- /**
375
- * Get the current state value.
376
- *
377
- * @returns {T} The current state value.
378
- */
379
- let updatedValue = () => this.state[key];
380
-
381
- const getValue = updatedValue();
382
-
383
- /**
384
- * Set a new value for the state.
385
- *
386
- * @param {T} newValue - The new value to set.
387
- * @param {Function} hook - The hook to hydrate after setting the value.
388
- */
389
- const set = (newValue, hook) => {
390
- this.state[key] = newValue;
391
- this.hydrate(hook);
392
- };
393
-
394
-
395
-
396
- return [getValue, set];
397
- }
398
-
399
-
400
-
401
- useRef(key = null, initialState) {
402
- if (!this.state[key]) {
403
- this.state[key] = initialState;
404
- }
405
- const getValue = () => document.querySelector(`[ref="${key + this.key}"]`) || initialState;
406
- const set = (newValue) => {
407
- this.state[key] = newValue;
408
- this.hydrate();
409
- };
410
-
411
-
412
- return {
413
- bind: key + this.key,
414
- current: getValue(),
415
- }
416
- }
417
-
418
- useReducer(key = null, initialState, func = null) {
419
- const getValue = () => this.state[key];
420
- const value = getValue();
421
- const set = (newValue) => {
422
- const nextState = func ? func(this.state[key], newValue) : newValue;
423
- this.state[key] = nextState;
424
- };
425
- return [value, set];
426
- }
427
-
428
-
429
- /**
430
- * Placeholder for content to be rendered.
431
- * @method render
432
- */
433
- render() {}
434
-
435
- /**
436
- * Checks if the component is mounted and triggers the onMount method.
437
- * @private
438
- */
439
- checkIFMounted() {
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
- });
458
- }
459
-
460
- /**
461
- * Method that is called when the component is mounted.
462
- * @method onMount
463
- */
464
- onMount() {}
465
- /**
466
- * Method that is called when the component is unmounted.
467
- * @method onUnmount
468
- */
469
- onUnmount() {}
470
- }
471
-
472
-
473
-
474
- /**
475
- * useState hook.
476
- *
477
- * @param {string} key - The key for the state property.
478
- * @param {*} initialState - The initial state value.
479
- * @returns {[*]} - A tuple with the current state value and a setter function.
480
- */
481
- export const useState = (key, initialState) => {
482
- if (!states[key]) {
483
- states[key] = initialState;
484
- }
485
-
486
- /**
487
- * Get the current state value.
488
- *
489
- * @returns {*} The current state value.
490
- */
491
- let updatedValue = () => states[key];
492
-
493
- /**
494
- * Set a new value for the state.
495
- *
496
- * @param {*} newValue - The new value to set.
497
- * @param {Function} hook - The hook to hydrate after setting the value.
498
- */
499
- const set = (newValue, hook) => {
500
- states[key] = newValue;
501
- this.hydrate(hook);
502
- };
503
-
504
- return [states[key], set];
505
- };
506
-
507
-
508
-
509
- /**
510
- * @method useReducer
511
- * @param {*} initialState
512
- * @param {*} reducer
513
- * @returns {Array} [value, set]
514
- */
515
- export const useReducer = (/**@type {*}**/initialState, /**@type {function}**/reducer) => {
516
- return [initialState, (newValue) => {}];
517
- };
518
-
519
-
520
- /**
521
- * useRef hook.
522
- *
523
- * @param {*} initialState - The initial state value for the ref.
524
- * @returns {{ current: *, bind: string }} - An object containing the current value and a bind string.
525
- */
526
- export const useRef = (initialState) => {
527
- return {
528
- /**
529
- * @description The current value of the ref.
530
- @type {*}
531
- */
532
- current: initialState,
533
- /**
534
- * @description A unique string that can be used to bind the ref to an element.
535
- * @type {HTMLElement|string}
536
- */
537
- bind: '',
538
- };
539
- };
540
-
541
- export default {
542
- Component,
543
- useRef,
544
- useReducer,
545
- useState,
546
- strictMount,
547
- }
1
+ window.Vader={version:"1.3.3"},window.componentRegistry={};let errors={"SyntaxError: Unexpected token '<'":"You forgot to enclose tags in a fragment <></>"},mounts=[];export const strictMount=(e,t)=>{let n=setInterval((()=>{mounts.find((t=>t.key===e))&&(clearInterval(n),t())}),120)};export class Component{constructor(){this.state={},this.key=null,this.components={},this.mounted=!1,this.checkIFMounted(),this.memoizes=[],this.functions=[],this.children=[],this.parentNode={},this.request={headers:{},method:"GET",params:{},path:"",query:{}},this.response={json:e=>{},send:e=>{},redirect:e=>{},render:async e=>{},log:e=>{},setQuery:e=>{}},this.router={use:e=>{}}}createComponent(e,t,n){function s(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}let o=s(e)?new e(t):null;if(!e)throw new Error("Component must be defined");if(!t.key)throw new Error("new components must have a key");if(s(e.default?e.default:e))o.props=t,o.children=n,o.props.children=n.join(""),o.parentNode=this,o.request=this.request,o.response=this.response,o.key=t.key||null;else{e.default&&(e=e.default);let s=new Component(t),r=e.toString(),i=r.includes("this.key")?r.split("this.key")[1].split("=")[1].split('"')[1]:null,u=(r.match(/return\s*`([\s\S]*)`/),r.split("return")[1].split("`")[0]);u=u.replace(/,\s*$/,""),t.children=n.join("");let a=e.apply(this,[t]);s.key=i,t.key=i,o={key:t.key?t.key:i,render:()=>a,request:this.request,response:this.response,reset:s.reset.bind(s),onMount:s.onMount.bind(s),parentNode:this,useState:s.useState.bind(s),useReducer:s.useReducer.bind(s),useRef:s.useRef.bind(s),router:{use:s.router.use.bind(s)},bindMount:s.bindMount.bind(s),memoize:s.memoize.bind(s),createComponent:s.createComponent.bind(s),isChild:!0,parseStyle:s.parseStyle.bind(s),components:{},onUnmount:s.onUnmount.bind(s),onMount:s.onMount.bind(s),functions:[],memoizes:[]}}return this.components[t.key]||(this.components[t.key]=o),this.children.push(o),this.components[t.key]}reset(){console.log("reset"),Object.keys(this.components).forEach((e=>{this.components[e].onUnmount(),delete this.components[e]})),this.state={},this.children=[]}memoize(e){if(!e.key)throw new Error("Component must have a static key");if(!0==!this.memoizes.includes(e.key))this.memoizes.push(e.key),this.components[e.key]=e;let t=this.components[e.key];t.bindMount(),t.parentNode=this,t.props=e.props,t.request=this.request,t.response=this.response;let n=t.render();return n&&n.split(">,").length>1&&(n=n.replaceAll(">,",">")),`<div key="${e.key}">${n}</div>`}parseStyle(e){let t="";return Object.keys(e).forEach((n=>{let s=e[n];n=n.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),t+=`${n}:${s};`})),t}bindMount(){mounts.push(this)}domDifference(e,t){let n=[];for(let s=0;s<e.length;s++){let o=e[s],r=t[s];o&&r&&!o.isEqualNode(r)&&n.push({type:"replace",old:o,new:r.cloneNode(!0)})}return n}updateChangedElements(e){e.forEach((e=>{switch(e.type){case"replace":e.old.parentNode.replaceChild(e.new,e.old);break;case"remove":e.old.remove();break;case"add":e.old.appendChild(e.new.cloneNode(!0))}}))}hydrate(e){if(this.key)if(e){let t=(new DOMParser).parseFromString(this.render(),"text/html").body.firstChild,n=document.body.querySelectorAll(`[ref="${e}"]`),s=t.querySelectorAll(`[ref="${e}"]`),o=this.domDifference(n,s);this.updateChangedElements(o)}else{const e=document.querySelector(`[key="${this.key}"]`);e?e.outerHTML=this.render():console.error("Target element not found.")}}patch(e,t){const n=this.domDifference(e,t);this.updateChangedElements(n)}handleObject(obj){try{obj=JSON.parse(obj)}catch(e){}return eval(obj)}bind(e,t,n,s,o,...r){s+=this.key;let i={},u=(o=o.replace(/,,/g,",")).replaceAll(",,",",");for(var a in r){let e=r[a];i[u.split(",")[a]]=e}o=o.replace(",,",",");let d=new Function(`${o}`,`\n return (async (${o}) => { \n ${e.toString()}\n })(${Object.keys(i).join(",")}) \n `);return d=d.bind(this),this.functions.find((e=>e.ref===s))||document.addEventListener(`$dispatch_#id=${s}`,(n=>{let{name:o,event:r}=n.detail;if(o===s){let n=this.functions.find((e=>e.ref===s)).params;Object.keys(n).forEach((e=>{n[e]instanceof CustomEvent&&delete n[e],void 0===n[e]?delete n[e]:n[e]})),t?e(r,...Object.values(n)):d(...Object.values(n))}})),window.callFunction=(e,t)=>{document.dispatchEvent(new CustomEvent(`$dispatch_#id=${e}`,{detail:{name:e,params:null,event:t}}))},this.functions.find((e=>e.ref===s))?!t&&(this.functions.find((e=>e.ref===s)).params=i):this.functions.push({ref:s,params:i}),n?e:`((event)=>{event.target.ev = event; callFunction('${s}', event.target.ev)})(event)`}useState(e,t){this.state[e]||(this.state[e]=t);return[(()=>this.state[e])(),(t,n)=>{this.state[e]=t,this.hydrate(n)}]}useRef(e=null,t){this.state[e]||(this.state[e]=t);return{bind:e+this.key,current:(()=>document.querySelector(`[ref="${e+this.key}"]`)||t)()}}useReducer(e=null,t,n=null){return[(()=>this.state[e])(),t=>{const s=n?n(this.state[e],t):t;this.state[e]=s}]}render(){}checkIFMounted(){new MutationObserver((e=>{e.forEach((e=>{e.target.querySelector(`[key="${this.key}"]`)&&!this.mounted&&(this.onMount(),this.mounted=!0),Array.from(e.removedNodes).find((e=>e.attributes&&e.attributes.key&&e.attributes.key.value===this.key))&&(this.onUnmount(),this.reset())}))})).observe(document.body,{childList:!0,subtree:!0})}onMount(){}onUnmount(){}}export const useState=(e,t)=>{states[e]||(states[e]=t);return[states[e],(t,n)=>{states[e]=t,this.hydrate(n)}]};export const useReducer=(e,t)=>[e,e=>{}];export const useRef=e=>({current:e,bind:""});export default{Component:Component,useRef:useRef,useReducer:useReducer,useState:useState,strictMount:strictMount};