cradova 1.0.1 → 1.0.2

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 (66) hide show
  1. package/README.md +53 -19
  2. package/dist/index.d.ts +26 -0
  3. package/dist/index.js +468 -0
  4. package/dist/rolled-cradova.js +2366 -0
  5. package/dist/scripts/JsonDB.d.ts +287 -0
  6. package/dist/scripts/JsonDB.js +633 -0
  7. package/dist/scripts/Router.d.ts +5 -0
  8. package/dist/scripts/Router.js +170 -0
  9. package/dist/scripts/Screen.d.ts +51 -0
  10. package/dist/scripts/Screen.js +107 -0
  11. package/dist/scripts/ajax.d.ts +28 -0
  12. package/dist/scripts/ajax.js +63 -0
  13. package/dist/scripts/fns.d.ts +84 -0
  14. package/dist/scripts/fns.js +307 -0
  15. package/dist/scripts/init.d.ts +1 -0
  16. package/dist/scripts/init.js +25 -0
  17. package/dist/scripts/loadCss.d.ts +1 -0
  18. package/dist/scripts/loadCss.js +194 -0
  19. package/dist/scripts/memory.d.ts +12 -0
  20. package/dist/scripts/memory.js +46 -0
  21. package/dist/scripts/store.d.ts +12 -0
  22. package/dist/scripts/store.js +64 -0
  23. package/dist/scripts/swipe.d.ts +1 -0
  24. package/dist/scripts/swipe.js +114 -0
  25. package/dist/scripts/track.d.ts +12 -0
  26. package/dist/scripts/track.js +150 -0
  27. package/dist/scripts/widget.d.ts +8 -0
  28. package/dist/scripts/widget.js +21 -0
  29. package/dist/types.d.ts +12 -0
  30. package/dist/types.js +1 -0
  31. package/index.ts +336 -147
  32. package/package.json +18 -11
  33. package/scripts/JsonDB.ts +134 -130
  34. package/scripts/Router.ts +94 -24
  35. package/scripts/Screen.ts +99 -39
  36. package/scripts/{littleAxios.ts → ajax.ts} +44 -6
  37. package/scripts/fns.ts +341 -0
  38. package/scripts/init.ts +11 -4
  39. package/scripts/loadCss.ts +194 -0
  40. package/scripts/memory.ts +44 -0
  41. package/scripts/store.ts +32 -21
  42. package/scripts/style.css +189 -0
  43. package/scripts/swipe.ts +4 -4
  44. package/scripts/track.ts +171 -0
  45. package/scripts/widget.ts +17 -15
  46. package/tsconfig.json +18 -98
  47. package/types.ts +15 -1
  48. package/{online-only-after-initial-cache.ts → workers/online-only-after-initial-cache.ts} +14 -11
  49. package/{service-worker.ts → workers/service-worker.ts} +17 -10
  50. package/docs/README.md +0 -0
  51. package/manifest.json +0 -38
  52. package/scripts/Metrics.ts +0 -66
  53. package/scripts/animate.ts +0 -55
  54. package/scripts/createState.ts +0 -27
  55. package/scripts/css.ts +0 -47
  56. package/scripts/dispatcher.ts +0 -158
  57. package/scripts/fetcher.ts +0 -31
  58. package/scripts/file-system.ts +0 -173
  59. package/scripts/fullscreen.ts +0 -21
  60. package/scripts/localStorage.ts +0 -19
  61. package/scripts/media.ts +0 -51
  62. package/scripts/promptbeforeleave.ts +0 -10
  63. package/scripts/reuse.ts +0 -79
  64. package/scripts/speaker.ts +0 -25
  65. package/scripts/uuid.ts +0 -10
  66. package/types.d.ts +0 -0
@@ -0,0 +1,2366 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
+ typeof define === 'function' && define.amd ? define(factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.cradova = factory());
5
+ })(this, (function () { 'use strict';
6
+
7
+ /**
8
+ * Document fragment
9
+ * @param childrens
10
+ * @returns
11
+ */
12
+ const fragment = function (...childrens) {
13
+ const par = document.createDocumentFragment();
14
+ // building it's children tree.
15
+ for (let i = 0; i < childrens.length; i++) {
16
+ const ch = childrens[i];
17
+ if (typeof ch === "function") {
18
+ par.append(ch());
19
+ }
20
+ else {
21
+ if (ch instanceof HTMLElement) {
22
+ par.append(ch);
23
+ }
24
+ }
25
+ }
26
+ return () => par;
27
+ };
28
+
29
+ function swipe(item) {
30
+ let caller;
31
+ let startX = 0, startY = 0;
32
+ if (typeof item === "object") {
33
+ caller = item;
34
+ }
35
+ else {
36
+ throw new Error("no call given for the swipe handler");
37
+ }
38
+ function handleTouchStart(e) {
39
+ startX = e.changedTouches[0].screenX;
40
+ startY = e.changedTouches[0].screenY;
41
+ }
42
+ function handleTouchEnd(e) {
43
+ const diffX = e.changedTouches[0].screenX - startX;
44
+ const diffY = e.changedTouches[0].screenY - startY;
45
+ const ratioX = Math.abs(diffX / diffY);
46
+ const ratioY = Math.abs(diffY / diffX);
47
+ const absDiff = Math.abs(ratioX > ratioY ? diffX : diffY);
48
+ if (absDiff < 10) {
49
+ if (caller.touch) {
50
+ callback.touch(caller.touch);
51
+ }
52
+ }
53
+ if (ratioX > ratioY) {
54
+ // left and right
55
+ if (diffX >= 0) {
56
+ if (caller.right) {
57
+ callback.right(caller.right);
58
+ }
59
+ }
60
+ else {
61
+ if (caller.left) {
62
+ callback.left(caller.left);
63
+ }
64
+ }
65
+ // up and down
66
+ }
67
+ else {
68
+ if (diffY >= 0) {
69
+ if (caller.down) {
70
+ callback.down(caller.down);
71
+ }
72
+ }
73
+ else {
74
+ if (caller.up) {
75
+ callback.up(caller.up);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ const escapeTSError = document.body;
81
+ escapeTSError.addEventListener("touchstart", handleTouchStart);
82
+ escapeTSError.addEventListener("touchend", handleTouchEnd);
83
+ const callback = {
84
+ touch(callback) {
85
+ return callback();
86
+ },
87
+ right(callback) {
88
+ return callback();
89
+ },
90
+ left(callback) {
91
+ return callback();
92
+ },
93
+ down(callback) {
94
+ return callback();
95
+ },
96
+ up(callback) {
97
+ return callback();
98
+ },
99
+ };
100
+ }
101
+ /*
102
+ *** HOW TO USE ***
103
+
104
+ function touch(){
105
+ console.log("touching")
106
+ }
107
+
108
+
109
+
110
+ function up(){
111
+ console.log("swipe up")
112
+ }
113
+
114
+
115
+ function down(){
116
+ console.log("swipe down")
117
+ }
118
+
119
+
120
+ function right(){
121
+ console.log("swipe right")
122
+ }
123
+
124
+
125
+ function left(){
126
+ console.log("swipe left")
127
+ }
128
+
129
+
130
+
131
+ let obj = {down: down,
132
+ touch: touch,
133
+ up: up,
134
+ right: right,
135
+ left: left
136
+ }
137
+
138
+ swipe(obj)
139
+
140
+
141
+
142
+ */
143
+
144
+ class store {
145
+ constructor(initial, useHistory) {
146
+ this.#index = 0;
147
+ this.#history = [];
148
+ this.#value = null;
149
+ this.#useHistory = false;
150
+ this.#value = initial;
151
+ if (useHistory) {
152
+ this.#useHistory = useHistory;
153
+ this.#history.push(initial);
154
+ }
155
+ }
156
+ #index;
157
+ #history;
158
+ #value;
159
+ #useHistory;
160
+ #callabck;
161
+ get() {
162
+ return this.#value;
163
+ }
164
+ set(value) {
165
+ this.#value = value;
166
+ if (!this.#useHistory)
167
+ return;
168
+ this.#index += 1;
169
+ this.#history.push(value);
170
+ if (this.#callabck) {
171
+ this.#callabck(this.#value);
172
+ }
173
+ }
174
+ setKey(name, value) {
175
+ if (typeof this.#value === "object") {
176
+ this.#value[name] = value;
177
+ if (!this.#useHistory)
178
+ return;
179
+ this.#history.push(this.#value);
180
+ this.#index += 1;
181
+ }
182
+ if (this.#callabck) {
183
+ this.#callabck(this.#value);
184
+ }
185
+ }
186
+ forward() {
187
+ if (this.#history.length > this.#index + 1) {
188
+ if (!this.#useHistory)
189
+ return;
190
+ this.#value = this.#history[this.#index + 1];
191
+ }
192
+ }
193
+ backward() {
194
+ if (this.#history.length > 0 && this.#index > 0) {
195
+ if (!this.#useHistory)
196
+ return;
197
+ this.#value = this.#history[this.#index - 1];
198
+ this.#index -= 1;
199
+ }
200
+ }
201
+ listen(callabck) {
202
+ this.#callabck = callabck;
203
+ }
204
+ }
205
+ const Store = function (initial, useHistory = false) {
206
+ return new store(initial, useHistory);
207
+ };
208
+
209
+ /**
210
+ * Facilitates navigation within the application and initializes
211
+ * page views based on the matched routes.
212
+ */
213
+ const Router = {};
214
+ Router["routes"] = {};
215
+ Router["params"] = {};
216
+ /**
217
+ *
218
+ * @param url
219
+ * @returns
220
+ */
221
+ const checker = (url) => {
222
+ // first strict check
223
+ if (Router.routes[url]) {
224
+ return [Router.routes[url], null];
225
+ }
226
+ // place holder check
227
+ for (const path in Router.routes) {
228
+ if (!path.includes("$")) {
229
+ continue;
230
+ }
231
+ //
232
+ const urlFixtures = url.split("/");
233
+ const pathFixtures = path.split("/");
234
+ // length check
235
+ if (pathFixtures.length === urlFixtures.length) {
236
+ urlFixtures.shift();
237
+ pathFixtures.shift();
238
+ let isIt = true;
239
+ let routesParams = {};
240
+ for (let i = 0; i < pathFixtures.length; i++) {
241
+ // loosely item checking by N indexes & includes
242
+ // FIXME: may be problematic but works faster than any other solutions
243
+ // NO regex :)
244
+ // this is faster and better
245
+ if (!pathFixtures[i].includes("$") && path.includes(urlFixtures[i] + "/") && (pathFixtures.indexOf(urlFixtures[i]) === pathFixtures.lastIndexOf(urlFixtures[i]))) {
246
+ if (!isIt)
247
+ isIt = true;
248
+ }
249
+ else {
250
+ if (pathFixtures[i].includes("$")) {
251
+ continue;
252
+ }
253
+ isIt = false;
254
+ }
255
+ if (!(pathFixtures.indexOf(urlFixtures[i]) === pathFixtures.lastIndexOf(urlFixtures[i]))) {
256
+ throw new Error("cradova router doesn't allow paths with multiple names");
257
+ }
258
+ }
259
+ if (isIt) {
260
+ for (let i = 0; i < pathFixtures.length; i++) {
261
+ if (pathFixtures[i].includes("$")) {
262
+ routesParams[pathFixtures[i].split("$")[1]] = urlFixtures[i];
263
+ }
264
+ }
265
+ return [Router.routes[path], routesParams];
266
+ }
267
+ }
268
+ }
269
+ return [];
270
+ };
271
+ /**
272
+ * Registers a route.
273
+ *
274
+ * @param {string} path Route path.
275
+ * @param {Function} controller the cradova document tree for the route.
276
+ */
277
+ Router.route = function (path = "/", controller) {
278
+ Router.routes[path] = {
279
+ controller: controller,
280
+ };
281
+ };
282
+ Router.navigate = function (href, data = {}) {
283
+ if (typeof href !== "string") {
284
+ throw new TypeError("cradova err href must be a defined path but got " + href + " instaed");
285
+ }
286
+ let route = null, params, link = null;
287
+ if (href.includes(".")) {
288
+ try {
289
+ if (new URL(href).pathname === window.location.pathname) {
290
+ return;
291
+ }
292
+ route = Router.routes[new URL(href).pathname];
293
+ link = new URL(href).pathname;
294
+ }
295
+ catch (error) {
296
+ throw new Error("cradova: invlaid route " + href);
297
+ }
298
+ }
299
+ else {
300
+ if (href === window.location.pathname) {
301
+ return;
302
+ }
303
+ [route, params] = checker(href);
304
+ if (route) {
305
+ Router.params.params = params || null;
306
+ Router.params.data = data || null;
307
+ link = href;
308
+ window.history.pushState({}, "", link);
309
+ document.body.click();
310
+ }
311
+ }
312
+ return;
313
+ };
314
+ Router.goTo = (path) => {
315
+ window.location.pathname = path;
316
+ };
317
+ Router.router = function (e) {
318
+ if (e.target.tagName === "INPUT") {
319
+ return;
320
+ }
321
+ //
322
+ let Alink;
323
+ if (e.target.tagName === "A") {
324
+ Alink = e.target;
325
+ if (Alink && Alink.href.includes("#")) {
326
+ return;
327
+ }
328
+ }
329
+ if (e.target.parentElement && e.target.parentElement.tagName === "A") {
330
+ Alink = e.target.parentElement;
331
+ }
332
+ if (Alink && Alink.href.includes("#")) {
333
+ return;
334
+ }
335
+ if (Alink && Alink.href.includes("javascript")) {
336
+ return;
337
+ }
338
+ e.preventDefault();
339
+ if (Alink) {
340
+ if (Alink.href === "" ||
341
+ new URL(Alink.href).pathname === window.location.pathname) {
342
+ return;
343
+ }
344
+ const [route, params] = checker(new URL(Alink.href).pathname);
345
+ if (route) {
346
+ Router.params.event = e;
347
+ Router.params.params = params || null;
348
+ Router.params.data = Router.params.data || null;
349
+ route.controller(Router.params);
350
+ }
351
+ else {
352
+ throw new Error("cradova err route doesn't exist " + Alink.href);
353
+ }
354
+ window.history.pushState({}, "", new URL(Alink.href).pathname);
355
+ return;
356
+ }
357
+ const url = window.location.pathname;
358
+ const [route, params] = checker(url);
359
+ if (route) {
360
+ Router.params.event = e;
361
+ Router.params.params = params || null;
362
+ Router.params.data = Router.params.data || null;
363
+ route.controller(Router.params);
364
+ }
365
+ };
366
+ /**
367
+ * Responds to click events anywhere in the document and when
368
+ * the click happens on a link that is supposed to be handled
369
+ * by the router, loads and displays the target page.
370
+ *
371
+ * @param {Event} e Click event.
372
+ */
373
+ document.addEventListener("click", Router.router);
374
+ window.addEventListener("load", Router.router);
375
+ window.addEventListener("popstate", (e) => {
376
+ e.preventDefault();
377
+ Router.router(e);
378
+ });
379
+
380
+ /**
381
+ *
382
+ * @param name
383
+ * @param template
384
+ * @param transitions
385
+ */
386
+ class Screen {
387
+ constructor(cradova_screen_initials) {
388
+ this.secondaryChildren = [];
389
+ /**
390
+ * this tells cradova to persist state on the screen or not
391
+ * persiting is better
392
+ */
393
+ this.persist = true;
394
+ const { template, name, callBack, transition, persist } = cradova_screen_initials;
395
+ if (typeof template !== "function") {
396
+ throw new Error("Cradova err: only functions that returns a cradova element is valid as screen");
397
+ }
398
+ this.html = template;
399
+ this.name = name;
400
+ this.template = document.createElement("div");
401
+ this.template.style.width = "100%";
402
+ this.template.style.display = "flex";
403
+ this.template.style.flexDirection = "column";
404
+ this.template.id = "cradova-screen-set";
405
+ this.callBack = callBack;
406
+ this.transition = transition;
407
+ if (!persist) {
408
+ this.persist = false;
409
+ }
410
+ }
411
+ async package(data) {
412
+ this.template.innerHTML = '';
413
+ if (typeof this.html === "function") {
414
+ let fuc = await this.html(data);
415
+ if (typeof fuc === "function") {
416
+ fuc = fuc();
417
+ if (!(fuc instanceof HTMLElement)) {
418
+ throw new Error("Cradova err only parent with descendants is valid");
419
+ }
420
+ else {
421
+ this.template.append(fuc);
422
+ }
423
+ }
424
+ }
425
+ this.template.append(...this.secondaryChildren);
426
+ }
427
+ onActivate(cb) {
428
+ this.callBack = cb;
429
+ }
430
+ addChild(...addOns) {
431
+ for (let i = 0; i < addOns.length; i++) {
432
+ if (addOns[i] && addOns[i] instanceof HTMLElement) {
433
+ this.secondaryChildren.push(addOns[i]);
434
+ }
435
+ if (addOns[i] && typeof addOns[i] === "function") {
436
+ this.secondaryChildren.push(addOns[i]());
437
+ }
438
+ }
439
+ }
440
+ detach() {
441
+ // crearing the dom
442
+ const screens = document.querySelectorAll("#cradova-screen-set");
443
+ for (let i = 0; i < screens.length; i++) {
444
+ const screen = screens[i];
445
+ if (this.transition) {
446
+ screen.classList.remove("CRADOVA-UI-" + this.transition);
447
+ }
448
+ screen.parentElement?.removeChild(screen);
449
+ }
450
+ }
451
+ async Activate(data) {
452
+ let packed = false;
453
+ if (document.title === this.name) {
454
+ return;
455
+ }
456
+ if (!this.template.firstChild) {
457
+ packed = true;
458
+ await this.package(data);
459
+ }
460
+ if (!this.persist && !packed) {
461
+ await this.package(data);
462
+ }
463
+ document.title = this.name;
464
+ this.detach();
465
+ document.querySelector("#app-wrapper").append(this.template);
466
+ if (this.transition) {
467
+ this.template?.classList.add("CRADOVA-UI-" + this.transition);
468
+ // console.log(this.template.className);
469
+ }
470
+ if (this.callBack) {
471
+ this.callBack(this.template.firstChild, data);
472
+ }
473
+ window.scrollTo(0, 0);
474
+ }
475
+ }
476
+ // SCREEN ANIMATION CLASSES
477
+ Screen.SCALE_IN = "SCALE-IN";
478
+ Screen.SCALE_OUT = "SCALE-OUT";
479
+ Screen.CIRCLE_IN = "CIRCLE-IN";
480
+ Screen.CIRCLE_OUT = "CIRCLE-OUT";
481
+ Screen.FADE_OUT = "FADE-OUT";
482
+ Screen.FADE_IN = "FADE-IN";
483
+ Screen.SLIDE_UP = "SLIDE-UP";
484
+ Screen.SLIDE_DOWN = "SLIDE-DOWN";
485
+ Screen.SLIDE_LEFT = "SLIDE-LEFT";
486
+ Screen.SLIDE_RIGHT = "SLIDE-RIGHT";
487
+
488
+ /**
489
+ * JSON DB DataBase MIT Licence © 2022
490
+ * ************************************
491
+ * Created by Friday Candour @uiedbooker
492
+ * email > fridaymaxtour@gmail.com
493
+ * github > www.github.com/FridayCandour
494
+ * telegram > @uiedbooker
495
+ * JSONDB @version 1.0.0
496
+ * */
497
+ const JSONDBversion = "1.0.0";
498
+ let fs, isNode = false, _dirname;
499
+ (async function () {
500
+ if (!globalThis.localStorage) {
501
+ isNode = true;
502
+ }
503
+ })();
504
+ const schema = class {
505
+ constructor(schema_configuration_object, validators) {
506
+ // validations
507
+ if (!schema_configuration_object.columns) {
508
+ throw new Error("JSONDB: can't create an empty table should have some columns");
509
+ }
510
+ validators.validateColumns(schema_configuration_object.columns);
511
+ const isEmptyObject = function (obj) {
512
+ // for checking for empty objects
513
+ for (const _name in obj) {
514
+ return false;
515
+ }
516
+ return true;
517
+ };
518
+ if (schema_configuration_object.relations &&
519
+ !isEmptyObject(schema_configuration_object.relations)) {
520
+ validators.validateRelations(schema_configuration_object.relations);
521
+ }
522
+ // assignment
523
+ this.base_name = "";
524
+ this.name = schema_configuration_object.name;
525
+ this.last_index = -1;
526
+ this.columns = schema_configuration_object.columns;
527
+ this.relations = schema_configuration_object.relations || null;
528
+ }
529
+ };
530
+ class JSONDBTableWrapper {
531
+ constructor(self, keys) {
532
+ this.put = async (name, value) => {
533
+ if (isNode) {
534
+ await fs.writeFile(name + ".json", JSON.stringify(value), "utf-8");
535
+ }
536
+ else {
537
+ localStorage.setItem(name, JSON.stringify(value));
538
+ }
539
+ };
540
+ this.get = async (name) => {
541
+ if (!isNode) {
542
+ return JSON.parse(localStorage.getItem(name));
543
+ }
544
+ const data = await fs.readFile(_dirname + "/" + name + ".json", {
545
+ encoding: "utf-8",
546
+ });
547
+ if (data) {
548
+ return JSON.parse(data);
549
+ }
550
+ else {
551
+ throw new Error("JSONDB: error failed to retrieve entities from database ");
552
+ }
553
+ };
554
+ this.validator = (incoming, tables) => {
555
+ // works for type, nulllable and unique validations.
556
+ const outgoing = {};
557
+ for (const prop in this.self.columns) {
558
+ if (this.self.columns[prop].nullable !== true &&
559
+ !Object.hasOwnProperty.call(incoming, prop)) {
560
+ throw new Error("JSONDB: error failed to validate incoming data because " +
561
+ prop +
562
+ " is required for " +
563
+ this.self.name +
564
+ " Schema");
565
+ }
566
+ if (!this.self.columns[prop].nullable &&
567
+ typeof incoming[prop] !== this.self.columns[prop].type) {
568
+ throw new Error("JSONDB: error failed to validate incoming data because " +
569
+ prop +
570
+ "'s value " +
571
+ incoming[prop] +
572
+ " has got a wrong data type of " +
573
+ typeof incoming[prop] +
574
+ " for " +
575
+ this.self.name +
576
+ " should be " +
577
+ this.self.columns[prop].type +
578
+ " type instead");
579
+ }
580
+ if (this.self.columns[prop].unique === true) {
581
+ for (let i = 0; i < tables.length; i++) {
582
+ const element = tables[i];
583
+ if (element[prop] === incoming[prop]) {
584
+ throw new Error("JSONDB: error failed to validate incoming data because " +
585
+ prop +
586
+ " is unique for " +
587
+ this.self.name +
588
+ " Schema can't have more than one instance");
589
+ }
590
+ }
591
+ }
592
+ // cleaning time
593
+ outgoing[prop] = incoming[prop];
594
+ }
595
+ return outgoing;
596
+ };
597
+ this.self = self;
598
+ this.keys = keys;
599
+ }
600
+ /**
601
+ * Save with relations
602
+ * ---------------------
603
+ * @type .saveWithRelations(target table, schema, schema | schema[]) => Promise(object)
604
+ * @example
605
+ * // single relation
606
+ await PollTable.saveWithRelations(MessageTable, Poll, message);
607
+ // arrays of relations
608
+ await PollTable.saveWithRelations(MessageTable, Poll, allMessages);
609
+ */
610
+ async saveWithRelations(table, incoming, relations) {
611
+ if (!relations || !table) {
612
+ throw new TypeError("JsonDB: error saving with relations table name or relation cannot be null " +
613
+ JSON.stringify(relations) +
614
+ " " +
615
+ JSON.stringify(table));
616
+ }
617
+ if (!table.self || !table.self.name) {
618
+ throw new TypeError("JsonDB: error saving with relations table is invalid " +
619
+ JSON.stringify(table));
620
+ }
621
+ const db = await this.get(this.self.base_name);
622
+ db.last_access_time = Date();
623
+ if (incoming && typeof incoming.index !== "number") {
624
+ throw new Error("JsonDB: save before saving with relations");
625
+ }
626
+ db.tables[this.self.name][incoming.index] = incoming;
627
+ if (relations && Array.isArray(relations)) {
628
+ for (let i = 0; i < relations.length; i++) {
629
+ if (db.Entities[this.self.name].relations[table.self.name]) {
630
+ if (db.Entities[this.self.name].relations[table.self.name].type ===
631
+ "many") {
632
+ db.tables[this.self.name][incoming.index].relations[table.self.name] = !db.tables[this.self.name][incoming.index].relations[table.self.name]
633
+ ? [relations[i]]
634
+ : [
635
+ ...db.tables[this.self.name][incoming.index].relations[table.self.name],
636
+ relations[i],
637
+ ];
638
+ }
639
+ else {
640
+ db.tables[this.self.name][incoming.index].relations[table.self.name] = relations[i];
641
+ }
642
+ }
643
+ }
644
+ }
645
+ else {
646
+ if (relations) {
647
+ if (db.Entities[this.self.name].relations[table.self.name]) {
648
+ if (db.Entities[this.self.name].relations[table.self.name].type ===
649
+ "many") {
650
+ db.tables[this.self.name][incoming.index].relations[table.self.name] = !db.tables[this.self.name][incoming.index].relations[table.self.name]
651
+ ? [relations]
652
+ : [
653
+ ...db.tables[this.self.name][incoming.index].relations[table.self.name],
654
+ relations,
655
+ ];
656
+ }
657
+ else {
658
+ db.tables[this.self.name][incoming.index].relations[table.self.name] = relations;
659
+ }
660
+ }
661
+ }
662
+ }
663
+ await this.put(this.self.base_name, db);
664
+ return db.tables[this.self.name][incoming.index];
665
+ }
666
+ /**
667
+ * Save table into a Jsondb instance
668
+ * -----------------------------
669
+ * @type .save(schema)=> Promise(object)
670
+ * @example
671
+ await PollTable.save(poll)
672
+ */
673
+ async save(incoming) {
674
+ // db.tables[this.self.name] = db.tables[this.self.name].sort(
675
+ // (a, b) => a.index - b.index
676
+ // );
677
+ const db = await this.get(this.self.base_name);
678
+ db.last_access_time = Date();
679
+ if (typeof incoming.index !== "number") {
680
+ incoming = this.validator(incoming, db.tables[this.self.name]);
681
+ if (this.self.relations && !incoming.relations) {
682
+ incoming.relations = {};
683
+ }
684
+ db.Entities[this.self.name].last_index += 1;
685
+ incoming.index = db.Entities[this.self.name].last_index;
686
+ db.tables[this.self.name].push(incoming);
687
+ }
688
+ else {
689
+ db.tables[this.self.name][incoming.index] = incoming;
690
+ }
691
+ await this.put(this.self.base_name, db);
692
+ return incoming;
693
+ }
694
+ /**
695
+ * Save table into a Jsondb instance
696
+ * -----------------------------
697
+ * @type .remove(schema)=> Promise(object)
698
+ * @example
699
+ await PollTable.remove(poll)
700
+ */
701
+ async remove(entity) {
702
+ const db = await this.get(this.self.base_name);
703
+ db.last_access_time = Date();
704
+ // db.tables[this.self.name].splice(entity.index, 1);
705
+ db.tables[this.self.name][entity.index] = null;
706
+ await this.put(this.self.base_name, db);
707
+ return true;
708
+ }
709
+ /**
710
+ * Save table into a Jsondb instance
711
+ * -----------------------------
712
+ * @type .count(schema)=> Promise(number)
713
+ * @example
714
+ await PollTable.count(poll)
715
+ */
716
+ async count() {
717
+ const db = await this.get(this.self.base_name);
718
+ db.last_access_time = Date();
719
+ return db.tables[this.self.name].length;
720
+ }
721
+ /**
722
+ * Save table into a Jsondb instance
723
+ * -----------------------------
724
+ * @type .getAll()=> Promise(object[])
725
+ * @example
726
+ await PollTable.getAll()
727
+ */
728
+ async getAll() {
729
+ const db = await this.get(this.self.base_name);
730
+ db.last_access_time = Date();
731
+ return db.tables[this.self.name];
732
+ }
733
+ /**
734
+ * get entities with any of the values specifiled from a Jsondb instance
735
+ * -----------------------------
736
+ * @type .getWhereAny({prop: value}, number | undefind)=> Promise(object)
737
+ * @example
738
+ await PollTable.getWhereAny({name: "friday", age: 121, class: "senior"}) // gets all
739
+ await PollTable.getWhereAny({email: "fridaymaxtour@gmail.com"}, 2) // gets 2 if they are up to two
740
+ */
741
+ async getWhereAny(props, number) {
742
+ const results = [];
743
+ let all;
744
+ const db = await this.get(this.self.base_name);
745
+ db.last_access_time = Date();
746
+ all = db.tables[this.self.name];
747
+ for (let i = 0; i < all.length; i++) {
748
+ const element = all[i];
749
+ for (const [k, v] of Object.entries(props)) {
750
+ if (element[k] && element[k] === v) {
751
+ results.push(element);
752
+ if (typeof number === "number" && results.length === number) {
753
+ return results;
754
+ }
755
+ }
756
+ }
757
+ }
758
+ return results;
759
+ }
760
+ /**
761
+ * get entities with the given prop of type "string" where the values specifiled is included
762
+ * -----------------------------
763
+ * @type .getWhereAnyPropsIncludes({prop: value}, number | undefind)=> Promise(object)
764
+ *
765
+ * @example prop must be type string!
766
+ *
767
+ await PollTable.getWhereAnyPropsIncludes({name: "fri"}) // gets all
768
+ await PollTable.getWhereAnyPropsIncludes({name: "fri"}, 2) // gets 2 if they are up to two
769
+ */
770
+ async getWhereAnyPropsIncludes(props, number) {
771
+ const results = [];
772
+ const db = await this.get(this.self.base_name);
773
+ db.last_access_time = Date();
774
+ const all = db.tables[this.self.name];
775
+ for (let i = 0; i < all.length; i++) {
776
+ const element = all[i];
777
+ for (const [k, v] of Object.entries(props)) {
778
+ if (element[k] && typeof v === "string" && element[k].includes(v)) {
779
+ results.push(element);
780
+ if (typeof number === "number" && results.length === number) {
781
+ return results;
782
+ }
783
+ }
784
+ }
785
+ }
786
+ return results;
787
+ }
788
+ /**
789
+ * get an entity with the values specifiled from a Jsondb instance
790
+ * -----------------------------
791
+ * @type .getOne({prop: value})=> Promise(object)
792
+ * @example
793
+
794
+ await PollTable.getOne({email: "fridaymaxtour@gamail.com"}) // gets one
795
+
796
+ */
797
+ async getOne(props) {
798
+ let results = null;
799
+ const db = await this.get(this.self.base_name);
800
+ db.last_access_time = Date();
801
+ const all = db.tables[this.self.name];
802
+ for (let i = 0; i < all.length; i++) {
803
+ const element = all[i];
804
+ for (const [k, v] of Object.entries(props)) {
805
+ if (element[k] && element[k] === v) {
806
+ results = element;
807
+ break;
808
+ }
809
+ }
810
+ }
811
+ return results;
812
+ }
813
+ }
814
+ const JSONDBConnection = class {
815
+ constructor(Entities, keys) {
816
+ this.Entities = Entities;
817
+ this.keys = keys;
818
+ }
819
+ /**
820
+ * Get a table from JSONDB
821
+ *------------------------
822
+ * @example
823
+ *
824
+ *
825
+ const details = {
826
+ password: "password",
827
+ username: "jsondb_username",
828
+ };
829
+ // getting connection instance into JSONDB
830
+ const connection = await database.createJSONDBConnection(details);
831
+ // getting a table
832
+ const MessageTable = connection.getTable("Message");
833
+ * */
834
+ getTable(table_name) {
835
+ for (const [tableName, table] of Object.entries(this.Entities)) {
836
+ if (table_name === tableName) {
837
+ return new JSONDBTableWrapper(table, this.keys);
838
+ }
839
+ }
840
+ return undefined;
841
+ }
842
+ };
843
+ /**
844
+ * Create a new JSONDB object
845
+ *------------------------
846
+ * @class
847
+
848
+ * const database = new JSONDB()
849
+ *
850
+ * Creates a new JSONDB object
851
+ *
852
+ * .
853
+ * */
854
+ class JSONDB {
855
+ constructor() {
856
+ this.DB_NAME = "";
857
+ this.username = "";
858
+ this.encrypted = false;
859
+ this.initialised = false;
860
+ this.time_created = Date();
861
+ this.version = JSONDBversion;
862
+ this.last_access_time = "";
863
+ this.visuality = "";
864
+ this.Entities = {};
865
+ this.tables = {};
866
+ }
867
+ async getDB(name) {
868
+ if (!isNode) {
869
+ return JSON.parse(localStorage.getItem(name));
870
+ }
871
+ const data = await fs.readFile(_dirname + "/" + name + ".json", {
872
+ encoding: "utf-8",
873
+ });
874
+ if (data) {
875
+ return JSON.parse(data);
876
+ }
877
+ else {
878
+ throw new Error("JSONDB: error failed to retrieve entities from database ");
879
+ }
880
+ }
881
+ /**
882
+ * Schema constructor for Jsondb
883
+ * -----------------------------
884
+ *
885
+ * name @type string
886
+ *
887
+ * columns @type object {
888
+ *
889
+ * type > @type any of number > string > boolean > blob and must be specified
890
+ *
891
+ * nullable @type bolean true > false default false
892
+ *
893
+ * unique @type bolean true > false default false
894
+ *
895
+ * }
896
+ *
897
+ * relations @type object {
898
+ *
899
+ * target: entity schema @type object,
900
+ *
901
+ * attachment_name: @type string,
902
+ *
903
+ * type : @type string should be "many" or "one"
904
+ *
905
+ * }
906
+ *
907
+ *
908
+ *
909
+ * @example
910
+ *
911
+ * const MessageSchema = database.schema({
912
+ name: "Message",
913
+ columns: {
914
+ vote: {
915
+ type: "number",
916
+ },
917
+ time: {
918
+ type: "string",
919
+ nullable: true,
920
+ },
921
+ value: {
922
+ type: "string",
923
+ },
924
+ },
925
+ });
926
+ *
927
+ * const PollSchema = new JSONDB.schema({
928
+ name: "Poll",
929
+ columns: {
930
+ value: {
931
+ type: "varchar",
932
+ },
933
+ },
934
+ relations: {
935
+ Message: {
936
+ target: Message,
937
+ type: "many-to-one",
938
+ },
939
+ },
940
+ });
941
+ */
942
+ schema(schema_configuration_object) {
943
+ return new schema(schema_configuration_object, {
944
+ validateColumns: this.validateColumns,
945
+ validateRelations: this.validateRelations,
946
+ });
947
+ }
948
+ /**
949
+ * Create a new JSONDB instance
950
+ *------------------------
951
+ * @example
952
+ * // creates a JSONDB object
953
+ * const Database = new JSONDB()
954
+ * // database configuration object
955
+ * const config = {
956
+ DB_NAME: "my db",
957
+ password: "password",
958
+ username: "jsondb_username",
959
+ encrypted: false,
960
+ }
961
+ // Creates a new JSONDB instance
962
+ * Database.init(config)
963
+ * */
964
+ async init(config) {
965
+ console.log(`\x1B[32m JSONDB version ${JSONDBversion} \x1B[39m`);
966
+ this.initialised = true;
967
+ this.DB_NAME = config.name;
968
+ this.password = config.password || "";
969
+ this.username = config.username || "";
970
+ this.encrypted = config.encrypted || false;
971
+ this.time_created = Date();
972
+ this.tables = {};
973
+ try {
974
+ let wasThere;
975
+ if (isNode) {
976
+ wasThere = this.getDB(config.name);
977
+ }
978
+ else {
979
+ wasThere = localStorage.getItem(config.name);
980
+ }
981
+ if (wasThere) {
982
+ return;
983
+ }
984
+ }
985
+ catch (error) { }
986
+ if (!config.password) {
987
+ throw new Error("JSONDB: error password is empty ");
988
+ }
989
+ if (!config.username) {
990
+ throw new Error("JSONDB: error username is empty ");
991
+ }
992
+ if (isNode) {
993
+ await fs.writeFile(config.name + ".json", JSON.stringify(this), "utf-8");
994
+ }
995
+ else {
996
+ let db = JSON.stringify(this);
997
+ localStorage.setItem(config.name, db);
998
+ }
999
+ }
1000
+ /**
1001
+ * Create secure connection a Jsondb instance
1002
+ * -----------------------------
1003
+ * @example
1004
+ *
1005
+ * const details = {
1006
+ password: "password",
1007
+ username: "jsondb_username",
1008
+ };
1009
+ const connection = await database.createJSONDBConnection(details);
1010
+ */
1011
+ async createJSONDBConnection(details) {
1012
+ if (!this.initialised) {
1013
+ throw new Error("JSONDB: you haven't create a JSONDB instance yet");
1014
+ }
1015
+ if (details.username !== this.username ||
1016
+ details.password !== this.password) {
1017
+ throw new Error("JSONDB: Access Denied");
1018
+ }
1019
+ const connection = await this.getDB(this.DB_NAME);
1020
+ connection.last_access_time = Date();
1021
+ return new JSONDBConnection(connection.Entities);
1022
+ }
1023
+ validateRelations(relations) {
1024
+ const types = ["many", "one"];
1025
+ for (const relation in relations) {
1026
+ const value = relations[relation];
1027
+ if (typeof value.target !== "object") {
1028
+ throw new Error("JSONDB: wrong relationship target type given " +
1029
+ value.target +
1030
+ " should be object only");
1031
+ }
1032
+ if (!types.includes(value.type)) {
1033
+ throw new Error("JSONDB: wrong relationship type given " +
1034
+ value.type +
1035
+ " should be many or one");
1036
+ }
1037
+ if (value.cascade && typeof value.cascade !== "boolean") {
1038
+ throw new Error("JSONDB: wrong cascade value given " +
1039
+ value.cascade +
1040
+ " should be true or false");
1041
+ }
1042
+ }
1043
+ }
1044
+ validateColumns(columns) {
1045
+ const types = ["number", "string", "boolean", "blob"];
1046
+ for (const column in columns) {
1047
+ const value = columns[column];
1048
+ if (column) {
1049
+ if (!types.includes(value.type)) {
1050
+ throw new Error("JSONDB: wrong data type given " +
1051
+ value.type +
1052
+ " only number, string, boolean and blob are accepted");
1053
+ }
1054
+ if (value.unique && typeof value.unique !== "boolean") {
1055
+ throw new Error("JSONDB: wrong unique value given " +
1056
+ value.unique +
1057
+ " should be true or false");
1058
+ }
1059
+ if (value.nullable && typeof value.nullable !== "boolean") {
1060
+ throw new Error("JSONDB: wrong nullable value given " +
1061
+ value.nullable +
1062
+ " should be true or false");
1063
+ }
1064
+ }
1065
+ }
1066
+ }
1067
+ /**
1068
+ * Assemble Entities into Jsondb
1069
+ * -----------------------------
1070
+ * @example
1071
+ *
1072
+ * const MessageSchema = database.schema({
1073
+ name: "Message",
1074
+ columns: {
1075
+ vote: {
1076
+ type: "number",
1077
+ },
1078
+ time: {
1079
+ type: "string",
1080
+ nullable: true,
1081
+ },
1082
+ value: {
1083
+ type: "string",
1084
+ },
1085
+ },
1086
+ });
1087
+
1088
+ database.assemble([MessageSchema]);
1089
+ *
1090
+ */
1091
+ async assemble(allEntities) {
1092
+ if (!this.initialised) {
1093
+ throw new Error("JSONDB: you haven't create a JSONDB instance yet");
1094
+ }
1095
+ try {
1096
+ const wasThere = await this.getDB(this.DB_NAME);
1097
+ if (wasThere) {
1098
+ return;
1099
+ }
1100
+ }
1101
+ catch (error) { }
1102
+ if (!Array.isArray(allEntities) || typeof allEntities[0] !== "object") {
1103
+ throw new Error("JSONDB: invalid entity array list, can't be assembled");
1104
+ }
1105
+ for (let i = 0; i < allEntities.length; i++) {
1106
+ this.Entities[allEntities[i].name] = allEntities[i];
1107
+ this.Entities[allEntities[i].name].base_name = this.DB_NAME;
1108
+ this.tables[allEntities[i].name] = [];
1109
+ }
1110
+ if (isNode) {
1111
+ await fs.writeFile(this.DB_NAME + ".json", JSON.stringify(this), "utf-8");
1112
+ }
1113
+ else {
1114
+ localStorage.setItem(this.DB_NAME, JSON.stringify(this));
1115
+ }
1116
+ }
1117
+ }
1118
+ /**
1119
+ * @exports
1120
+ */
1121
+
1122
+ /**
1123
+ *
1124
+ * little Axios request handler
1125
+ * ----------------------
1126
+ * supports files upload
1127
+ * ----------------------
1128
+ * @param {string} url
1129
+ * @param {object?} data?
1130
+ * @param {(object | function) ?} header or callback?
1131
+ * @param {function?} callback only?
1132
+ * @return void
1133
+ */
1134
+ async function littleAxios(url, callback, data, header) {
1135
+ if (!callback && typeof header === "function") {
1136
+ callback = header;
1137
+ }
1138
+ if (typeof url !== "string") {
1139
+ throw new Error("Cradova err : little Axios invalid url " + url);
1140
+ }
1141
+ const ajax = new XMLHttpRequest();
1142
+ let formData = new FormData();
1143
+ const method = data && typeof data !== "object" ? "GET" : "POST";
1144
+ ajax.addEventListener("load", async function (res) {
1145
+ console.log(res.target);
1146
+ callback(res.target);
1147
+ });
1148
+ if (data) {
1149
+ for (const key in data) {
1150
+ const value = data[key];
1151
+ formData.append(key, value);
1152
+ }
1153
+ }
1154
+ ajax.addEventListener("error", (e) => {
1155
+ return callback(e);
1156
+ });
1157
+ ajax.open(method, url, true);
1158
+ ajax.send(formData);
1159
+ }
1160
+ /**
1161
+ * An fetch based fetcher
1162
+ * ----------------------
1163
+ *
1164
+ * @param url string
1165
+ * @param method string
1166
+ * @param headers object
1167
+ * @param data object
1168
+ * @returns any
1169
+ */
1170
+ async function fetcher(url, method = "GET", headers, data) {
1171
+ return await fetch(url, {
1172
+ headers,
1173
+ method,
1174
+ body: JSON.stringify(data),
1175
+ }).catch((_err) => {
1176
+ return {
1177
+ async text() {
1178
+ return {
1179
+ message: JSON.stringify(`${method} ${url} net::ERR_FAILED`),
1180
+ };
1181
+ },
1182
+ };
1183
+ });
1184
+ }
1185
+
1186
+ function loadCradovaUICss(seconds = 0.3) {
1187
+ const css = `:root {
1188
+ --animation-timing: ${seconds + ""}s;
1189
+ }
1190
+
1191
+ .CRADOVA-UI-CIRCLE-OUT {
1192
+ animation: circle-out var(--animation-timing) ease forwards;
1193
+ }
1194
+
1195
+ .CRADOVA-UI-CIRCLE-IN {
1196
+ animation: circle-in var(--animation-timing) ease forwards;
1197
+ }
1198
+
1199
+ .CRADOVA-UI-SCALE-IN {
1200
+ animation: scale-in var(--animation-timing) ease forwards;
1201
+ }
1202
+
1203
+ .CRADOVA-UI-SCALE-OUT {
1204
+ animation: scale-out var(--animation-timing) ease forwards;
1205
+ }
1206
+
1207
+ .CRADOVA-UI-SLIDE-RIGHT {
1208
+ animation: slide-right var(--animation-timing) ease forwards;
1209
+ }
1210
+
1211
+ .CRADOVA-UI-SLIDE-LEFT {
1212
+ animation: slide-left var(--animation-timing) ease forwards;
1213
+ }
1214
+
1215
+ .CRADOVA-UI-SLIDE-UP {
1216
+ animation: slide-up var(--animation-timing) ease forwards;
1217
+ }
1218
+
1219
+ .CRADOVA-UI-SLIDE-DOWN {
1220
+ animation: slide-down var(--animation-timing) ease forwards;
1221
+ }
1222
+
1223
+ /* not done yet */
1224
+
1225
+ .CRADOVA-UI-FADE-IN {
1226
+ animation: fade-in var(--animation-timing) ease forwards;
1227
+ }
1228
+
1229
+ .CRADOVA-UI-FADE-OUT {
1230
+ animation: fade-out var(--animation-timing) ease forwards;
1231
+ }
1232
+
1233
+ /* ultility classes */
1234
+
1235
+ .CIRCLE-OUT {
1236
+ animation: fadeoff var(--animation-timing) ease forwards;
1237
+ }
1238
+
1239
+ .CIRCLE-IN {
1240
+ animation: fadein var(--animation-timing) ease forwards;
1241
+ }
1242
+
1243
+ /* animations */
1244
+
1245
+ @keyframes circle-out {
1246
+ from {
1247
+ border-radius: 49%;
1248
+ /* width: 100%; */
1249
+ /* height: 100%; */
1250
+ margin: auto;
1251
+ margin-top: 40%;
1252
+ }
1253
+
1254
+ to {
1255
+ border-radius: 100%;
1256
+ /* width: 0%; */
1257
+ /* height: 0%; */
1258
+ margin: auto;
1259
+ margin-top: 50%;
1260
+ }
1261
+ }
1262
+
1263
+ @keyframes circle-in {
1264
+ from {
1265
+ border-radius: 100%;
1266
+ /* width: 0%; */
1267
+ /* height: 0%; */
1268
+ margin: auto;
1269
+ margin-top: 40%;
1270
+ }
1271
+ to {
1272
+ border-radius: 0%;
1273
+ /* width: 100vw; */
1274
+ /* height: 100vh; */
1275
+ margin: auto;
1276
+ margin-top: 0%;
1277
+ }
1278
+ }
1279
+
1280
+ @keyframes scale-in {
1281
+ from {
1282
+ transform: scale(1);
1283
+ }
1284
+ to {
1285
+ transform: scale(0);
1286
+ }
1287
+ }
1288
+
1289
+
1290
+ @keyframes scale-out {
1291
+ from {
1292
+ transform: scale(0);
1293
+ }
1294
+ to {
1295
+ transform: scale(1);
1296
+ }
1297
+ }
1298
+
1299
+ @keyframes slide-right {
1300
+ from {
1301
+ margin-left: -140%;
1302
+ }
1303
+ to {
1304
+ margin-left: 0%;
1305
+ }
1306
+ }
1307
+
1308
+ @keyframes slide-left {
1309
+ from {
1310
+ margin-left: 140%;
1311
+ }
1312
+ to {
1313
+ margin-left: 0%;
1314
+ }
1315
+ }
1316
+
1317
+ @keyframes slide-up {
1318
+ from {
1319
+ margin-top: 140%;
1320
+ }
1321
+ to {
1322
+ margin-top: 0%;
1323
+ }
1324
+ }
1325
+
1326
+ @keyframes slide-down {
1327
+ from {
1328
+ margin-top: -140%;
1329
+ }
1330
+ to {
1331
+ margin-top: 0%;
1332
+ }
1333
+ }
1334
+
1335
+ @keyframes fade-in {
1336
+ from {
1337
+ opacity: 0;
1338
+ }
1339
+ to {
1340
+ opacity: 1;
1341
+ }
1342
+ }
1343
+
1344
+ @keyframes fade-out {
1345
+ from {
1346
+ opacity: 1;
1347
+ }
1348
+ to {
1349
+ opacity: 0;
1350
+ }
1351
+ }
1352
+
1353
+ /* ultility animations */
1354
+
1355
+
1356
+ @keyframes fadeoff {
1357
+ 50%{
1358
+ opacity: 0;
1359
+ }
1360
+ 100% {
1361
+ opacity: 0;
1362
+ }
1363
+ }
1364
+
1365
+ @keyframes fadein {
1366
+ 0% {
1367
+ opacity: 0;
1368
+ }
1369
+ 70%{
1370
+ opacity: 1;
1371
+ }
1372
+ 100% {
1373
+ opacity: 1;
1374
+ }
1375
+ } `;
1376
+ const style = document.createElement("style");
1377
+ style.innerHTML = css;
1378
+ document.head.appendChild(style);
1379
+ }
1380
+
1381
+ // the global dispatcher
1382
+ function cradovaDispatchtrack(nodes /*NodeListOf<Element>*/, stateID, state) {
1383
+ const updated = [];
1384
+ for (let i = 0; i < nodes.length; i++) {
1385
+ const element = nodes[i];
1386
+ // abort re-rendering if the state is not for this element
1387
+ if (!element.stateID || element.stateID !== stateID) {
1388
+ continue;
1389
+ }
1390
+ updated.push(element);
1391
+ if (typeof state === "object") {
1392
+ // updating the element's state
1393
+ for (const key in state) {
1394
+ // updating element styling
1395
+ if (key === "style") {
1396
+ for (const [k, v] of Object.entries(state[key])) {
1397
+ element.style[k] = v;
1398
+ }
1399
+ continue;
1400
+ }
1401
+ if (element.style[key] && key !== "src") {
1402
+ element.style[key] = state[key];
1403
+ continue;
1404
+ }
1405
+ if (element.style[key] === "" && key !== "src") {
1406
+ element.style[key] = state[key];
1407
+ continue;
1408
+ }
1409
+ if (typeof element[key] === "function") {
1410
+ element[key]();
1411
+ continue;
1412
+ }
1413
+ // updating element's inner text
1414
+ if (key === "text") {
1415
+ element.innerText = state[key];
1416
+ continue;
1417
+ }
1418
+ // setting element dimesion to full screen
1419
+ if (key === "fullscreen") {
1420
+ if (state[key]) {
1421
+ fullScreen(element).set();
1422
+ }
1423
+ else {
1424
+ fullScreen(element).exist();
1425
+ }
1426
+ continue;
1427
+ }
1428
+ // adding class name to element
1429
+ if (key === "class" && typeof state[key] === "string") {
1430
+ const classes = state[key].split(" ");
1431
+ for (let i = 0; i < classes.length; i++) {
1432
+ if (classes[i]) {
1433
+ element.classList.add(classes[i]);
1434
+ }
1435
+ }
1436
+ // console.log(element.className, "cl");
1437
+ continue;
1438
+ }
1439
+ // toggling element class
1440
+ if (key === "toggleclass") {
1441
+ element.classList.toggle(state[key]);
1442
+ // console.log(element.className, "tc");
1443
+ continue;
1444
+ }
1445
+ //removing element class
1446
+ if (key === "removeclass") {
1447
+ element.classList.remove(state[key]);
1448
+ // console.log(element.className, "rm");
1449
+ continue;
1450
+ }
1451
+ //removing element class
1452
+ if (key === "remove") {
1453
+ element.parentElement?.remove(element);
1454
+ continue;
1455
+ }
1456
+ // changing the element children tree
1457
+ if (key === "tree") {
1458
+ if (typeof state[key] === "function") {
1459
+ state[key] = state[key]();
1460
+ }
1461
+ if (typeof state[key] === "function") {
1462
+ state[key] = state[key]();
1463
+ }
1464
+ if (Array.isArray(state[key])) {
1465
+ throw new TypeError("cradova err invalid element, should be a single element or parent element from cradova");
1466
+ }
1467
+ if (!(state[key] instanceof HTMLElement)) {
1468
+ console.error("cradova err wrong element type: can't create element state on " +
1469
+ state[key]);
1470
+ throw new TypeError("cradova err invalid element, should be a html element from cradova");
1471
+ }
1472
+ // destroy the component tree
1473
+ element.innerHTML = "";
1474
+ // rebuild the component tree
1475
+ // console.log(state[key]);
1476
+ element.append(state[key]);
1477
+ continue;
1478
+ }
1479
+ element[key] = state[key];
1480
+ }
1481
+ }
1482
+ }
1483
+ return updated;
1484
+ }
1485
+ /**
1486
+ * Send a new state to specified element with stateID
1487
+ *
1488
+ * @param stateID
1489
+ * @param state
1490
+ * @returns element(s)
1491
+ */
1492
+ function dispatch(stateID, state) {
1493
+ // TODO: this will be updated to use data-stateid soon
1494
+ // speed test still going on
1495
+ const nodes = document.querySelectorAll(".cra_child_doc");
1496
+ let updated = [];
1497
+ if (typeof state === "undefined" && typeof stateID === "object") {
1498
+ for (const [id, eachState] of Object.entries(stateID)) {
1499
+ const node = cradovaDispatchtrack(nodes, id, eachState);
1500
+ updated.push(...node);
1501
+ }
1502
+ }
1503
+ else {
1504
+ if (typeof stateID === "string") {
1505
+ const node = cradovaDispatchtrack(nodes, stateID, state);
1506
+ updated.push(...node);
1507
+ }
1508
+ }
1509
+ return updated;
1510
+ }
1511
+ // for making the dom elements fulscreen
1512
+ function fullScreen(e) {
1513
+ return {
1514
+ set() {
1515
+ e.requestFullscreen().catch((err) => {
1516
+ throw err;
1517
+ });
1518
+ },
1519
+ exist() {
1520
+ document.exitFullscreen();
1521
+ },
1522
+ };
1523
+ }
1524
+ /*
1525
+ *** HOW TO USE ***
1526
+
1527
+ u("#container").fullscreen().toggle()
1528
+ u("#container").fullscreen().exist()
1529
+ u("#container").fullscreen().set()
1530
+ */
1531
+
1532
+ /**
1533
+ * @param {number} num
1534
+ * @returns uuid
1535
+ */
1536
+ function uuid(num = 10) {
1537
+ function dec2hex(dec) {
1538
+ return dec.toString(16).padStart(2, "0");
1539
+ }
1540
+ function generateId(len) {
1541
+ len = Math.round(len);
1542
+ return Array.from(crypto.getRandomValues(new Uint8Array(len || 10)), dec2hex).join("");
1543
+ }
1544
+ return generateId(num);
1545
+ }
1546
+ function PromptBeforeLeave() {
1547
+ window.addEventListener("beforeunload", (ev) => {
1548
+ const e = ev || window.event;
1549
+ if (e) {
1550
+ e.preventDefault();
1551
+ e.returnValue = "";
1552
+ }
1553
+ return "";
1554
+ });
1555
+ }
1556
+ /**
1557
+ Write CSS media in javascript
1558
+
1559
+ @example
1560
+
1561
+ media("min-width: 790px",
1562
+ ["#container",
1563
+ {
1564
+ width: "100%",
1565
+ height: "100%",
1566
+ "background-color": "#0000"
1567
+ }],
1568
+
1569
+ ["#header",
1570
+ {
1571
+ width: "100%",
1572
+ height: "20%",
1573
+ "background-color": "#fff"
1574
+ }]
1575
+ )
1576
+ */
1577
+ function media(value, ...properties) {
1578
+ /* This is for creating css
1579
+ @media styles using javascipt*/
1580
+ const styS = "@media only screen and (" +
1581
+ value +
1582
+ ") " +
1583
+ "{" +
1584
+ `
1585
+ `, styE = "}" +
1586
+ `
1587
+ `;
1588
+ let style = " ", aniSty = " ";
1589
+ const proplen = properties.length;
1590
+ let totalAnimation, Animation = " ";
1591
+ const animationStep = (num) => {
1592
+ style = " ";
1593
+ for (const [k, v] of Object.entries(properties[num][1])) {
1594
+ style +=
1595
+ "" +
1596
+ k +
1597
+ ": " +
1598
+ v +
1599
+ ";" +
1600
+ `
1601
+ `;
1602
+ }
1603
+ aniSty +=
1604
+ "" +
1605
+ properties[num][0] +
1606
+ "{" +
1607
+ `
1608
+ ` +
1609
+ style +
1610
+ "}" +
1611
+ `
1612
+ `;
1613
+ return aniSty;
1614
+ };
1615
+ for (let i = 0; i < proplen; i++) {
1616
+ Animation += animationStep(i);
1617
+ }
1618
+ let aniStyleTag = document.querySelector("style");
1619
+ if (aniStyleTag === null) {
1620
+ aniStyleTag = document.createElement("style");
1621
+ }
1622
+ aniStyleTag.media = "screen";
1623
+ totalAnimation =
1624
+ aniStyleTag.innerHTML +
1625
+ `
1626
+
1627
+ `;
1628
+ totalAnimation += styS + Animation + styE;
1629
+ aniStyleTag.innerHTML = totalAnimation;
1630
+ document.head.append(aniStyleTag);
1631
+ }
1632
+ /**
1633
+ Write CSS styles in Javascript
1634
+ @example
1635
+
1636
+ css("#container",
1637
+ {
1638
+ height: "100%",
1639
+ height: "100%",
1640
+ background-color: "#ff9800"
1641
+ })
1642
+
1643
+ css(".btn:hover",
1644
+ {
1645
+ height: "100%",
1646
+ height: "100%",
1647
+ background-color: "#ff9800"
1648
+ })
1649
+
1650
+ */
1651
+ function css(indentifier, properties) {
1652
+ /*This is for creating
1653
+ css styles using javascipt*/
1654
+ const styS = "" +
1655
+ indentifier +
1656
+ "" +
1657
+ "{" +
1658
+ `
1659
+ `;
1660
+ const styE = "}" +
1661
+ `
1662
+ `;
1663
+ let style = "", totalStyle = "";
1664
+ for (const [k, v] of Object.entries(properties)) {
1665
+ style +=
1666
+ "" +
1667
+ k +
1668
+ ": " +
1669
+ v +
1670
+ ";" +
1671
+ `
1672
+ `;
1673
+ }
1674
+ let styleTag = document.querySelector("style");
1675
+ if (styleTag !== null) {
1676
+ totalStyle += styleTag.innerHTML;
1677
+ totalStyle += styS + style + styE;
1678
+ styleTag.innerHTML = totalStyle;
1679
+ return;
1680
+ }
1681
+ styleTag = document.createElement("style");
1682
+ totalStyle +=
1683
+ styleTag.innerHTML +
1684
+ `
1685
+
1686
+ `;
1687
+ totalStyle += styS + style + styE;
1688
+ styleTag.innerHTML = totalStyle;
1689
+ document.head.append(styleTag);
1690
+ }
1691
+ /**
1692
+ Write animation value in javascript
1693
+
1694
+ @example
1695
+
1696
+ animate("popanimation",
1697
+ ["from",
1698
+ {
1699
+ transform: "scale3D(2)" ,
1700
+ height: "10%",
1701
+ "background-color": "#0000"
1702
+ }],
1703
+
1704
+ ["to",
1705
+ {
1706
+ transform: "scale3D(1)" ,
1707
+ height: "100%",
1708
+ "background-color": "#ff9800"
1709
+ }]
1710
+ )
1711
+
1712
+ */
1713
+ function animate(indentifier, ...properties) {
1714
+ /*This is for creating css
1715
+ animations using javascipt*/
1716
+ const styS = "@keyframes " +
1717
+ indentifier +
1718
+ " " +
1719
+ "{" +
1720
+ `
1721
+ `, styE = "}" +
1722
+ `
1723
+ `, proplen = properties.length;
1724
+ let style = " ", aniSty = " ", Animation = " ", totalAnimation = null;
1725
+ const animationStep = (num) => {
1726
+ style = " ";
1727
+ for (const [k, v] of Object.entries(properties[num][1])) {
1728
+ style +=
1729
+ "" +
1730
+ k +
1731
+ ": " +
1732
+ v +
1733
+ ";" +
1734
+ `
1735
+ `;
1736
+ }
1737
+ aniSty +=
1738
+ "" +
1739
+ properties[num][0] +
1740
+ "{" +
1741
+ `
1742
+ ` +
1743
+ style +
1744
+ "}" +
1745
+ `
1746
+ `;
1747
+ return aniSty;
1748
+ };
1749
+ for (let i = 0; i < proplen; i++) {
1750
+ Animation += animationStep(i);
1751
+ }
1752
+ let aniStyleTag = document.querySelector("style");
1753
+ if (aniStyleTag === null) {
1754
+ aniStyleTag = document.createElement("style");
1755
+ }
1756
+ aniStyleTag.media = "screen";
1757
+ totalAnimation =
1758
+ aniStyleTag.innerHTML +
1759
+ `
1760
+
1761
+ `;
1762
+ totalAnimation += styS + Animation + styE;
1763
+ aniStyleTag.innerHTML = totalAnimation;
1764
+ document.head.append(aniStyleTag);
1765
+ }
1766
+ /**
1767
+ *
1768
+ * @param {expession} condition
1769
+ * @param {function} callback
1770
+ */
1771
+ function assert(condition, callback) {
1772
+ if (condition) {
1773
+ return callback(condition);
1774
+ }
1775
+ // That didn't went well
1776
+ return " ";
1777
+ }
1778
+ const ls = {};
1779
+ ls.store = (name, value) => {
1780
+ localStorage.setItem(name, JSON.stringify(value));
1781
+ };
1782
+ ls.retrieve = (name) => {
1783
+ return localStorage.getItem(name);
1784
+ };
1785
+ ls.remove = (name) => {
1786
+ localStorage.removeItem(name);
1787
+ };
1788
+ ls.getKey = (index) => {
1789
+ return window.localStorage.key(index);
1790
+ };
1791
+ ls.clear = () => {
1792
+ localStorage.clear();
1793
+ };
1794
+ class list {
1795
+ constructor(component) {
1796
+ this.#stateID = uuid();
1797
+ this.#parentElement = null;
1798
+ this.#component = component;
1799
+ }
1800
+ #component;
1801
+ #stateID;
1802
+ #parentElement;
1803
+ build(datas) {
1804
+ if (!datas[0]) {
1805
+ return;
1806
+ }
1807
+ const elements = [];
1808
+ for (let i = 0; i < datas.length; i++) {
1809
+ const data = datas[i];
1810
+ const chtml = this.#component(data);
1811
+ const element = chtml({ stateID: this.#stateID });
1812
+ elements.push(element);
1813
+ }
1814
+ return elements;
1815
+ }
1816
+ update(datas) {
1817
+ if (!datas[0]) {
1818
+ return;
1819
+ }
1820
+ if (!this.#parentElement) {
1821
+ // only for the first call
1822
+ this.#parentElement = dispatch(this.#stateID, {
1823
+ display: "none",
1824
+ })[0].parentElement;
1825
+ }
1826
+ dispatch(this.#stateID, { remove: true });
1827
+ if (!this.#parentElement) {
1828
+ throw new Error("cannot update list");
1829
+ }
1830
+ for (let i = 0; i < datas.length; i++) {
1831
+ const data = datas[i];
1832
+ const chtml = this.#component(data);
1833
+ const element = chtml({ stateID: this.#stateID });
1834
+ this.#parentElement?.append(element);
1835
+ }
1836
+ }
1837
+ }
1838
+
1839
+ /**
1840
+ * Save values to memory
1841
+ * get them when needed
1842
+ */
1843
+ class memory {
1844
+ constructor(lastMemory) {
1845
+ this.#mem = {};
1846
+ this.#string = "cradova-memory-cache-key";
1847
+ if (lastMemory) {
1848
+ this.#mem = lastMemory;
1849
+ }
1850
+ }
1851
+ #mem;
1852
+ #string;
1853
+ get(key) {
1854
+ if (this.#mem[key]) {
1855
+ return this.#mem[key];
1856
+ }
1857
+ return null;
1858
+ }
1859
+ set(key, value) {
1860
+ this.#mem[key] = value;
1861
+ }
1862
+ load() {
1863
+ let memory = localStorage.getItem(this.#string);
1864
+ if (!memory)
1865
+ return false;
1866
+ memory = JSON.parse(memory);
1867
+ for (const mem in memory) {
1868
+ this.set(mem, memory[mem]);
1869
+ }
1870
+ return true;
1871
+ }
1872
+ save() {
1873
+ const memory = {};
1874
+ for (const mem in this.#mem) {
1875
+ memory[mem] = this.#mem[mem];
1876
+ }
1877
+ for (const val in memory) {
1878
+ if (val) {
1879
+ localStorage.setItem(this.#string, JSON.stringify(memory));
1880
+ break;
1881
+ }
1882
+ }
1883
+ }
1884
+ }
1885
+
1886
+ const Init = function (self) {
1887
+ const Wrapper = document.createElement("div");
1888
+ Wrapper.className = "Cradova-app-wrappper";
1889
+ Wrapper.id = "app-wrapper";
1890
+ // style can be over written by another css file
1891
+ css(".Cradova-app-wrappper", {
1892
+ display: "flex",
1893
+ "align-items": "center",
1894
+ "justify-content": "center",
1895
+ "flex-direction": "column",
1896
+ width: "100%",
1897
+ });
1898
+ Wrapper.stateID = "Cradova-app-wrappper-id";
1899
+ document.body.append(Wrapper);
1900
+ const lastMemory = window.localStorage.getItem("cradova-local-memory");
1901
+ if (lastMemory) {
1902
+ self.memory = new memory(JSON.parse(lastMemory));
1903
+ }
1904
+ else {
1905
+ self.memory = new memory(null);
1906
+ }
1907
+ return Wrapper;
1908
+ };
1909
+
1910
+ /*
1911
+
1912
+ """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1913
+ "
1914
+ " ██████╗ ██████╗ █████ ██████╗ ███████╗ ██╗ ██╗ █████
1915
+ " ██╔════╝ ██╔══██╗ ██╔═╗██ █ ██ ██╔═════╝ ██║ ██║ ██╔═╗██
1916
+ " ██║ ██████╔╝ ██████╗ █ ██ ██║ ██ ██║ ██║ ██████╗
1917
+ " ██║ ██╔══██ ██║ ██║ █ ██ ██║ ██ ╚██╗ ██╔╝ ██║ ██
1918
+ " ╚██████╗ ██║ ██║ ██║ ██║ ███████╔╝ ███████ ╚████╔╝ ██║ ██║
1919
+ " ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚════╝ ╚═══╝ ╚═╝ ╚═╝
1920
+ " JSONDB inside
1921
+ """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1922
+
1923
+ " =============================================================================
1924
+ " By Friday Candour
1925
+ " -----------------------------------------------------------------------------
1926
+ " =============================================================================
1927
+ " Cradova FrameWork
1928
+ " @version 1.*.*
1929
+ " -----------------------------------------------------------------------------
1930
+ " License: Apache V2
1931
+ " -----------------------------------------------------------------------------
1932
+ " fridaymaxtour@gmail.com ...
1933
+ " =============================================================================
1934
+
1935
+ Apache License
1936
+ Version 2.0, January 2004
1937
+ http://www.apache.org/licenses/
1938
+
1939
+ Copyright 2022 Friday Candour. All Rights Reserved.
1940
+ Licensed under the Apache License, Version 2.0 (the "License");
1941
+ you may not use this file except in compliance with the License.
1942
+ You may obtain a copy of the License at
1943
+ http://www.apache.org/licenses/LICENSE-2.0
1944
+ Unless required by applicable law or agreed to in writing, software
1945
+ distributed under the License is distributed on an "AS IS" BASIS,
1946
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1947
+ See the License for the specific language governing permissions and
1948
+ limitations under the License.
1949
+ */
1950
+ const make = function (txx) {
1951
+ if (Array.isArray(txx)) {
1952
+ txx = txx[0].trim();
1953
+ }
1954
+ if (!txx) {
1955
+ return {
1956
+ tag: "div",
1957
+ Classes: undefined,
1958
+ ID: undefined,
1959
+ innerValue: undefined,
1960
+ };
1961
+ }
1962
+ let tag;
1963
+ const itemsPurifier = (impure, items) => {
1964
+ const pureItems = [];
1965
+ for (let i = 0; i < items.length; i++) {
1966
+ if (items[i].includes(impure)) {
1967
+ items[i] = items[i].split(impure)[0];
1968
+ }
1969
+ pureItems.push(items[i]);
1970
+ }
1971
+ return pureItems;
1972
+ };
1973
+ let textContent;
1974
+ tag = txx.trim()[0] === "|" && "p";
1975
+ if (txx.includes("|")) {
1976
+ textContent = txx.split("|")[1];
1977
+ txx = txx.split("|")[0] && txx.split("|")[0];
1978
+ }
1979
+ const classes = itemsPurifier("#", txx.split("."));
1980
+ const ids = itemsPurifier(".", txx.split("#"));
1981
+ if (!tag) {
1982
+ tag = classes.shift();
1983
+ }
1984
+ if (!tag) {
1985
+ tag = ids.shift();
1986
+ }
1987
+ if (!tag) {
1988
+ tag = "div";
1989
+ }
1990
+ if (!txx.includes(".") && !txx.includes("#")) {
1991
+ tag = txx;
1992
+ ids.length = 0;
1993
+ classes.length = 0;
1994
+ }
1995
+ let ID = ids[1] ? ids[1].trim() : null;
1996
+ const className = classes.join(" ");
1997
+ let innerValue;
1998
+ if (textContent) {
1999
+ innerValue = textContent;
2000
+ }
2001
+ return { tag, className, ID, innerValue };
2002
+ };
2003
+ /**
2004
+ * Creates new cradova HTML element
2005
+ * @example
2006
+ * format for static _`p| am a p tag` // or _`p.class| am a p tag` or _`p#id| am a p tag` or _`p.class#id| am a p tag`
2007
+ * format for dynamic _(
2008
+ * "p| am a p tag" // or "p.class| am a p tag" or "p#id| am a p tag" or "p.class#id| am a p tag"
2009
+ * , {
2010
+ * //props like
2011
+ * text: "am a p tag",
2012
+ * style: {
2013
+ * color: "blue"
2014
+ * }
2015
+ * },
2016
+ * // place other children here like span
2017
+ * _`span| am a span tag like so`, // this is a static child
2018
+ * _("span| am a span tag like so", {style: {color: "brown"}}) // this is a dynamic child
2019
+ * )
2020
+ * @param {...any} element_initials
2021
+ * @returns function | HTMLElement
2022
+ *
2023
+ * static elements cannot be given props nor children nor state but dynamic can
2024
+ *
2025
+ * and static are useful too
2026
+ */
2027
+ const _ = (...element_initials) => {
2028
+ let properties, childrens = [], beforeMount;
2029
+ if (typeof element_initials[1] == "object" &&
2030
+ !(element_initials[1] instanceof HTMLElement && !element_initials[1].tagName)) {
2031
+ properties = element_initials[1];
2032
+ if (properties?.beforeMount) {
2033
+ beforeMount = properties["beforeMount"];
2034
+ }
2035
+ if (element_initials.length > 2) {
2036
+ childrens = element_initials.slice(2, element_initials.length);
2037
+ }
2038
+ }
2039
+ else {
2040
+ if (element_initials[1] instanceof HTMLElement ||
2041
+ typeof element_initials[1] === "function") {
2042
+ childrens = element_initials.slice(1, element_initials.length);
2043
+ }
2044
+ }
2045
+ if (element_initials[0].raw) {
2046
+ // getting the value of static cradova calls
2047
+ element_initials[0] = element_initials[0]["raw"][0];
2048
+ }
2049
+ // verifing the children array
2050
+ function identify(element_initials) {
2051
+ if (typeof element_initials !== "object") {
2052
+ element_initials = [element_initials];
2053
+ }
2054
+ const initials = make(element_initials[0]);
2055
+ // TODO: tag debugger
2056
+ // const { tag, className, ID, innerValue } = initials;
2057
+ // if (tag === "div" && properties?.style?.pp === "o") {
2058
+ // // console.log(properties.beforeMount);
2059
+ // properties.beforeMount();
2060
+ // }
2061
+ /**
2062
+ *
2063
+ * --- Cradova Element Initials ---
2064
+ * --------------------------------
2065
+ *
2066
+ * Note: this element has not been initialised!
2067
+ *
2068
+ * add to a parent element or call this return fuction
2069
+ *
2070
+ * .
2071
+ */
2072
+ return (...incoming) => {
2073
+ /*
2074
+ *
2075
+ * --- Cradova Element Initials ---
2076
+ * --------------------------------
2077
+ *
2078
+ * Note: this element has not been initialised!
2079
+ *
2080
+ * add to a parent element or call this return fuction
2081
+ *
2082
+ * .
2083
+ */
2084
+ let childrens2rd = [], props = {}, text;
2085
+ for (let i = 0; i < incoming.length; i++) {
2086
+ if (typeof incoming[i] === "function" ||
2087
+ incoming[i] instanceof HTMLElement
2088
+ // ||
2089
+ // incoming[i].tagName
2090
+ ) {
2091
+ childrens2rd.push(incoming[i]);
2092
+ continue;
2093
+ }
2094
+ // if (
2095
+ // !incoming[i]
2096
+ // ) {
2097
+ // console.log(incoming[i]);
2098
+ // continue;
2099
+ // }
2100
+ //
2101
+ if (
2102
+ // !incoming[i].tagName &&
2103
+ !(incoming[i] instanceof HTMLElement) &&
2104
+ !Array.isArray(incoming[i]) &&
2105
+ typeof incoming[i] === "object" &&
2106
+ !incoming[i].tagName) {
2107
+ if (incoming[i].beforeMount) {
2108
+ beforeMount = incoming[i]["beforeMount"];
2109
+ continue;
2110
+ }
2111
+ if (incoming[i].composedPath) {
2112
+ continue;
2113
+ }
2114
+ props = incoming[i];
2115
+ continue;
2116
+ }
2117
+ //
2118
+ if (typeof incoming[i] === "string") {
2119
+ text = incoming[i];
2120
+ continue;
2121
+ }
2122
+ }
2123
+ if (childrens.length) {
2124
+ childrens2rd.push(...childrens);
2125
+ }
2126
+ let element;
2127
+ try {
2128
+ element = document.createElement(initials.tag.trim());
2129
+ }
2130
+ catch (error) {
2131
+ throw new TypeError("cradova err invalid tag given " + initials.tag);
2132
+ }
2133
+ if (!element) {
2134
+ return;
2135
+ }
2136
+ if (initials.className) {
2137
+ element.className = initials.className.trim();
2138
+ }
2139
+ if (initials.ID) {
2140
+ element.id = initials.ID.trim();
2141
+ }
2142
+ if (initials.innerValue) {
2143
+ element.append(initials.innerValue);
2144
+ }
2145
+ for (const prop in properties) {
2146
+ if (prop === "style") {
2147
+ for (const [k, v] of Object.entries(properties[prop])) {
2148
+ element.style[k] = v;
2149
+ }
2150
+ continue;
2151
+ }
2152
+ if (element.style[prop] === "" && prop !== "src") {
2153
+ element.style[prop] = properties[prop];
2154
+ continue;
2155
+ }
2156
+ if (prop === "class" && typeof properties[prop] === "string") {
2157
+ const classes = properties[prop].split(" ");
2158
+ for (let i = 0; i < classes.length; i++) {
2159
+ if (classes[i]) {
2160
+ element.classList.add(classes[i]);
2161
+ }
2162
+ }
2163
+ continue;
2164
+ }
2165
+ if (prop === "text") {
2166
+ element.innerText = properties[prop];
2167
+ continue;
2168
+ }
2169
+ try {
2170
+ element[prop] = properties[prop];
2171
+ }
2172
+ catch (error) {
2173
+ throw new Error("cradova err invalid props " +
2174
+ prop +
2175
+ " for this element type with value " +
2176
+ properties[prop]);
2177
+ }
2178
+ }
2179
+ //
2180
+ // dynamic props
2181
+ // over-rides props that appear in the first level
2182
+ if (props && typeof props === "object" && !Array.isArray(props)) {
2183
+ for (const prop in props) {
2184
+ if (prop === "style") {
2185
+ for (const [k, v] of Object.entries(props[prop])) {
2186
+ element.style[k] = v;
2187
+ }
2188
+ continue;
2189
+ }
2190
+ if (prop === "text" && typeof props[prop] === "string") {
2191
+ element.innerText = props[prop];
2192
+ continue;
2193
+ }
2194
+ if (prop === "class" && typeof props[prop] === "string") {
2195
+ element.classList.add(props[prop]);
2196
+ continue;
2197
+ }
2198
+ if (prop === "beforeMount") {
2199
+ beforeMount = props["beforeMount"];
2200
+ continue;
2201
+ }
2202
+ if (prop === "fullscreen") {
2203
+ if (properties[prop]) {
2204
+ fullScreen(element).set();
2205
+ }
2206
+ else {
2207
+ fullScreen(element).exist();
2208
+ }
2209
+ continue;
2210
+ }
2211
+ try {
2212
+ element[prop] = props[prop];
2213
+ }
2214
+ catch (error) {
2215
+ // console.log(element);
2216
+ // console.log(props);
2217
+ console.error(error);
2218
+ }
2219
+ }
2220
+ }
2221
+ if (childrens2rd && childrens2rd[0]) {
2222
+ //
2223
+ for (let i = 0; i < childrens2rd.length; i++) {
2224
+ if (typeof childrens2rd[i] === "function") {
2225
+ const child = childrens2rd[i]();
2226
+ element.append(child);
2227
+ if (child.afterMount) {
2228
+ child.afterMount(child);
2229
+ child.afterMount = undefined;
2230
+ }
2231
+ continue;
2232
+ }
2233
+ if (Array.isArray(childrens2rd[i])) {
2234
+ const arrCX = childrens2rd[i];
2235
+ const arrSET = [];
2236
+ for (let p = 0; p < arrCX.length; p++) {
2237
+ if (!(arrCX[p] instanceof HTMLElement) &&
2238
+ typeof arrCX[p] !== "function" &&
2239
+ !Array.isArray(arrCX[p])) {
2240
+ throw new TypeError("cradova err invalid children list, should be a html element from cradova " +
2241
+ arrCX[p]);
2242
+ }
2243
+ arrSET.push(arrCX[p]);
2244
+ }
2245
+ //
2246
+ childrens2rd = [
2247
+ ...childrens2rd.slice(0, i + 1),
2248
+ ...arrSET,
2249
+ ...childrens2rd.slice(i + 1, childrens2rd.length),
2250
+ ];
2251
+ continue;
2252
+ }
2253
+ const child = childrens2rd[i];
2254
+ element.append(child);
2255
+ if (child.afterMount) {
2256
+ child.afterMount(child);
2257
+ child.afterMount = undefined;
2258
+ }
2259
+ }
2260
+ }
2261
+ if (text) {
2262
+ element.append(text);
2263
+ }
2264
+ // TODO: this will be updated to use data-stateid soon
2265
+ // spped test still going on
2266
+ if (element.stateID) {
2267
+ // adding cradova dynamic signature
2268
+ element.classList.add("cra_child_doc");
2269
+ }
2270
+ if (beforeMount) {
2271
+ beforeMount(element);
2272
+ }
2273
+ return element;
2274
+ };
2275
+ }
2276
+ if (typeof element_initials[0] !== "string") {
2277
+ return () => "empty cradova call";
2278
+ }
2279
+ const CradovaElemet = identify(element_initials);
2280
+ if (!CradovaElemet) {
2281
+ throw new Error("Cradova err invalid element initials " + element_initials);
2282
+ }
2283
+ return CradovaElemet;
2284
+ };
2285
+ Init(_);
2286
+ /**
2287
+ * Create element and get a callback to update their state
2288
+ * no need to manage stateIDs
2289
+ * ----------------------------------------------------------------
2290
+ *
2291
+ * @param element_initials
2292
+ * @param props
2293
+ * @returns
2294
+ */
2295
+ function $(element_initials = "div", props = {}) {
2296
+ props.stateID = uuid();
2297
+ const element = _(element_initials, props);
2298
+ return [element, dispatch.bind(null, props.stateID)];
2299
+ }
2300
+ const controls = function () {
2301
+ const svg = `<svg width="20" height="20" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
2302
+ <path d="M4.49975 5.625C4.3402 5.6242 4.18282 5.58788 4.03904 5.5187C3.89526 5.44951 3.76869 5.34919 3.6685 5.225L1.03725 2.0375C0.8835 1.84561 0.786745 1.61438 0.758014 1.37017C0.729283 1.12596 0.769733 0.878589 0.874753 0.65625C0.959928 0.463017 1.09892 0.298383 1.27514 0.182014C1.45136 0.0656449 1.65734 0.00245816 1.8685 0H7.131C7.34216 0.00245816 7.54815 0.0656449 7.72437 0.182014C7.90058 0.298383 8.03958 0.463017 8.12475 0.65625C8.22977 0.878589 8.27023 1.12596 8.24149 1.37017C8.21276 1.61438 8.11601 1.84561 7.96226 2.0375L5.331 5.225C5.23082 5.34919 5.10424 5.44951 4.96047 5.5187C4.81669 5.58788 4.65931 5.6242 4.49975 5.625Z" fill="#2c3e50"/>
2303
+ </svg>
2304
+ `;
2305
+ const icon = (styles) => _("div", { ...styles, innerHTML: svg });
2306
+ const constr = _("div", {
2307
+ display: "flex",
2308
+ position: "fixed",
2309
+ alignContent: "center",
2310
+ justifyContent: "space-around",
2311
+ flexDirection: "row",
2312
+ width: "80px",
2313
+ top: "4px",
2314
+ right: "4px",
2315
+ backgroundColor: "#fff",
2316
+ transform: "rotate(0deg)",
2317
+ border: "aqua 2px solid",
2318
+ borderRadius: "6px",
2319
+ }, icon({
2320
+ transform: "rotate(90deg)",
2321
+ /* border: "red 2px solid", */ onclick() {
2322
+ window.history.back();
2323
+ },
2324
+ }), icon({
2325
+ transform: "rotate(270deg)",
2326
+ /* border: "red 2px solid", */ onclick() {
2327
+ window.history.forward();
2328
+ },
2329
+ }));
2330
+ const cont = constr();
2331
+ if (cont) {
2332
+ document.body.append(cont);
2333
+ }
2334
+ };
2335
+ function register(modules) {
2336
+ for (let i = 0; i < modules.length; i++) {
2337
+ _[modules[i]] = modules[i];
2338
+ }
2339
+ }
2340
+ register([
2341
+ fragment,
2342
+ swipe,
2343
+ Store,
2344
+ Router,
2345
+ Screen,
2346
+ JSONDB,
2347
+ fetcher,
2348
+ littleAxios,
2349
+ loadCradovaUICss,
2350
+ assert,
2351
+ animate,
2352
+ PromptBeforeLeave,
2353
+ css,
2354
+ media,
2355
+ ls,
2356
+ list,
2357
+ $,
2358
+ controls,
2359
+ ]);
2360
+ for (const key in _) {
2361
+ console.log(key);
2362
+ }
2363
+
2364
+ return _;
2365
+
2366
+ }));