@dogiloki/artha-js 1.0.0 → 1.2.1
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/README.md +687 -1
- package/dist/artha.min.css +1 -1
- package/dist/artha.min.css.map +1 -1
- package/dist/artha.min.js +29 -21
- package/package.json +11 -4
- package/src/abstract/BaseComponent.js +201 -0
- package/src/components/artha-container.js +22 -55
- package/src/components/artha-form.js +11 -4
- package/src/components/artha-loader.js +68 -0
- package/src/components/artha-message.js +6 -8
- package/src/components/loaders/LoaderBase.js +30 -0
- package/src/components/loaders/LoaderDots.js +11 -0
- package/src/components/loaders/LoaderRing.js +5 -0
- package/src/core/EventBus.js +94 -5
- package/src/core/TaskQueue.js +14 -9
- package/src/core/Util.js +15 -12
- package/src/core/XHR.js +44 -9
- package/src/scss/colors.scss +5 -1
- package/src/scss/loader.scss +70 -0
- package/src/scss/main.scss +1 -0
- package/src/scss/message.scss +8 -8
- package/src/core/Config.js +0 -47
package/src/core/EventBus.js
CHANGED
|
@@ -1,33 +1,122 @@
|
|
|
1
1
|
const EVENT_BUS=new EventTarget();
|
|
2
2
|
|
|
3
3
|
export default class EventBus{
|
|
4
|
+
|
|
5
|
+
static debug=false;
|
|
6
|
+
static listeners=new Map();
|
|
7
|
+
static any_listeners=new Set();
|
|
4
8
|
|
|
5
9
|
// Emitir evento
|
|
6
10
|
static emit(name,data){
|
|
11
|
+
if(this.debug){
|
|
12
|
+
try{
|
|
13
|
+
console.log(`[EventBus] emit -> ${name}`,structuredClone(data));
|
|
14
|
+
}catch(ex){
|
|
15
|
+
console.log(`[EventBus] emit -> ${name}`,data);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
this.any_listeners.forEach(cb=>{
|
|
19
|
+
try{
|
|
20
|
+
cb(name,data);
|
|
21
|
+
}catch(ex){
|
|
22
|
+
console.error(`[EventBus error] ${name}`,ex);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
7
25
|
EVENT_BUS.dispatchEvent(new CustomEvent(name,{detail:data}));
|
|
8
26
|
}
|
|
9
27
|
|
|
28
|
+
// Emitir y esperar promesa (async listeners)
|
|
29
|
+
static emitAsync(name,data){
|
|
30
|
+
this.any_listeners.forEach(cb=>{
|
|
31
|
+
try{
|
|
32
|
+
cb(name,data);
|
|
33
|
+
}catch(ex){
|
|
34
|
+
console.error(`[EventBus error] ${name}`,ex);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const listeners=this.listeners.get(name)||[];
|
|
38
|
+
const results=listeners.map(async({callback})=>{
|
|
39
|
+
try{
|
|
40
|
+
return await callback(data);
|
|
41
|
+
}catch(ex){
|
|
42
|
+
console.error(`[EventBus error] ${name}`,ex);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return Promise.all(results);
|
|
47
|
+
}
|
|
48
|
+
|
|
10
49
|
// Escuchar evento
|
|
11
50
|
static on(name,callback){
|
|
12
51
|
const handler=(evt)=>{
|
|
13
52
|
callback(evt.detail);
|
|
14
53
|
};
|
|
15
|
-
EVENT_BUS.addEventListener(name,
|
|
16
|
-
|
|
54
|
+
EVENT_BUS.addEventListener(name,handler);
|
|
55
|
+
if(!this.listeners.has(name)){
|
|
56
|
+
this.listeners.set(name,[]);
|
|
57
|
+
}
|
|
58
|
+
this.listeners.get(name).push({callback,handler});
|
|
59
|
+
return ()=>this.off(name,callback);
|
|
17
60
|
}
|
|
18
61
|
|
|
19
62
|
// Escucha una sola vez
|
|
20
63
|
static once(name,callback){
|
|
21
64
|
const handler=(evt)=>{
|
|
22
65
|
callback(evt.detail);
|
|
23
|
-
|
|
66
|
+
this.off(name,callback);
|
|
24
67
|
};
|
|
25
|
-
EVENT_BUS.addEventListener(name,
|
|
68
|
+
EVENT_BUS.addEventListener(name,handler,{once:true});
|
|
69
|
+
// Guardar referencia
|
|
70
|
+
if(!this.listeners.has(name)){
|
|
71
|
+
this.listeners.set(name,[]);
|
|
72
|
+
}
|
|
73
|
+
this.listeners.get(name).push({callback,handler});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Escuchar todos los eventos
|
|
77
|
+
static onAny(callback){
|
|
78
|
+
this.any_listeners.add(callback);
|
|
79
|
+
return ()=>this.any_listeners.delete(callback);
|
|
26
80
|
}
|
|
27
81
|
|
|
28
82
|
// Remover listener manualmente
|
|
29
83
|
static off(name,callback){
|
|
30
|
-
|
|
84
|
+
if(!this.listeners.has(name)) return;
|
|
85
|
+
const arr=this.listeners.get(name);
|
|
86
|
+
const filtered=arr.filter(item=>{
|
|
87
|
+
if(item.callback===callback){
|
|
88
|
+
EVENT_BUS.removeEventListener(name,item.handler);
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
});
|
|
93
|
+
if(filtered.length!==arr.length){
|
|
94
|
+
this.listeners.set(name,filtered);
|
|
95
|
+
}
|
|
96
|
+
if(filtered.length===0){
|
|
97
|
+
this.listeners.delete(name);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Limpiar todos los listeners de un evento
|
|
102
|
+
static clean(name){
|
|
103
|
+
if(!this.listeners.has(name)) return;
|
|
104
|
+
const arr=this.listeners.get(name);
|
|
105
|
+
arr.forEach(({handler})=>{
|
|
106
|
+
EVENT_BUS.removeEventListener(name,handler);
|
|
107
|
+
});
|
|
108
|
+
this.listeners.delete(name);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Limpiar todo
|
|
112
|
+
static clearAll(){
|
|
113
|
+
this.listeners.forEach((arr,name)=>{
|
|
114
|
+
arr.forEach(({handler})=>{
|
|
115
|
+
EVENT_BUS.removeEventListener(name,handler);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
this.listeners.clear();
|
|
119
|
+
this.any_listeners.clear();
|
|
31
120
|
}
|
|
32
121
|
|
|
33
122
|
}
|
package/src/core/TaskQueue.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import Config from "./Config.js";
|
|
2
1
|
import Util from "./Util.js";
|
|
3
2
|
import ArthaMessage from "../components/artha-message.js";
|
|
4
3
|
|
|
5
4
|
export default class TaskQueue{
|
|
6
5
|
|
|
6
|
+
static defaults={
|
|
7
|
+
title:"Petición en proceso...",
|
|
8
|
+
close:false,
|
|
9
|
+
message:null
|
|
10
|
+
};
|
|
7
11
|
static INSTNACE=null;
|
|
8
12
|
|
|
9
13
|
static singleton(){
|
|
@@ -50,7 +54,7 @@ class TaskQueueItem{
|
|
|
50
54
|
constructor(id,callback,options){
|
|
51
55
|
this.id=id;
|
|
52
56
|
this.callback=callback;
|
|
53
|
-
options={...
|
|
57
|
+
options={...TaskQueue.defaults,...options};
|
|
54
58
|
const {
|
|
55
59
|
title,
|
|
56
60
|
close,
|
|
@@ -127,20 +131,21 @@ class TaskQueueItem{
|
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
133
|
message=message||json.message||"Operación completada";
|
|
130
|
-
if(message){
|
|
131
|
-
this.message_element?.show(message,json?.status??null);
|
|
132
|
-
}
|
|
133
134
|
// Validar respuesta http
|
|
134
135
|
if(Util.withinRange(data.status,200,299)){
|
|
135
|
-
if(
|
|
136
|
+
if(message){
|
|
137
|
+
this.message_element?.show(message,json?.status??null);
|
|
138
|
+
}else{
|
|
136
139
|
this.message_element?.success("Operación completada");
|
|
137
140
|
}
|
|
138
|
-
this.status="success";
|
|
141
|
+
this.status=json?.status||"success";
|
|
139
142
|
}else{
|
|
140
|
-
if(
|
|
143
|
+
if(message){
|
|
144
|
+
this.message_element?.show(message,json?.status??null);
|
|
145
|
+
}else{
|
|
141
146
|
this.message_element?.error("Error en la respuesta del servidor");
|
|
142
147
|
}
|
|
143
|
-
this.status="error";
|
|
148
|
+
this.status=json?.status||"error";
|
|
144
149
|
this.onFinalize();
|
|
145
150
|
return;
|
|
146
151
|
}
|
package/src/core/Util.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import Config from "./Config.js";
|
|
2
|
-
|
|
3
1
|
export default class Util{
|
|
2
|
+
|
|
3
|
+
static defaults={
|
|
4
|
+
locale:"es-MX",
|
|
5
|
+
currency:"MXN",
|
|
6
|
+
money:{
|
|
7
|
+
style:"currency",
|
|
8
|
+
digits:2
|
|
9
|
+
}
|
|
10
|
+
};
|
|
4
11
|
|
|
5
12
|
static getMeta(name){
|
|
6
13
|
const meta=document.querySelector(`meta[name="${name}"]`);
|
|
@@ -37,21 +44,19 @@ export default class Util{
|
|
|
37
44
|
|
|
38
45
|
static formatMoney(value,options={}){
|
|
39
46
|
const {
|
|
40
|
-
locale=
|
|
41
|
-
currency=
|
|
42
|
-
digits=
|
|
47
|
+
locale=this.defaults.locale,
|
|
48
|
+
currency=this.defaults.currency,
|
|
49
|
+
digits=this.defaults.money.digits,
|
|
50
|
+
style=this.defaults.money.style
|
|
43
51
|
}=options;
|
|
44
52
|
value=value.toString();
|
|
45
|
-
if(value.endsWith(".") && !add_decimals){
|
|
46
|
-
add_decimals=true;
|
|
47
|
-
}
|
|
48
53
|
let amount=Number(value.replace(/[^0-9.]/g,""));
|
|
49
54
|
if(isNaN(amount)){
|
|
50
55
|
return value;
|
|
51
56
|
}
|
|
52
57
|
let minimum=0;
|
|
53
58
|
return new Intl.NumberFormat(locale,{
|
|
54
|
-
style:
|
|
59
|
+
style:style,
|
|
55
60
|
currency,
|
|
56
61
|
minimum,
|
|
57
62
|
digits
|
|
@@ -68,9 +73,7 @@ export default class Util{
|
|
|
68
73
|
|
|
69
74
|
static createElement(type,value=null,options={}){
|
|
70
75
|
const el=document.createElement(type,options);
|
|
71
|
-
if(value
|
|
72
|
-
return el;
|
|
73
|
-
}
|
|
76
|
+
if(value===null) return el;
|
|
74
77
|
if(Array.isArray(value)){
|
|
75
78
|
value.forEach((item)=>{
|
|
76
79
|
el.appendChild(item);
|
package/src/core/XHR.js
CHANGED
|
@@ -1,10 +1,34 @@
|
|
|
1
|
-
import Config from './Config.js';
|
|
2
1
|
import Util from './Util.js';
|
|
3
2
|
|
|
4
3
|
export default class XHR{
|
|
5
4
|
|
|
5
|
+
static defaults={
|
|
6
|
+
method:"GET",
|
|
7
|
+
url:null,
|
|
8
|
+
uri:"",
|
|
9
|
+
headers:{},
|
|
10
|
+
data:{},
|
|
11
|
+
query:{},
|
|
12
|
+
files:{},
|
|
13
|
+
response_type:"json",
|
|
14
|
+
with_credentials:false,
|
|
15
|
+
timeout:0,
|
|
16
|
+
retry:false,
|
|
17
|
+
retry_delay:5000,
|
|
18
|
+
transformResponse:(xhr)=>{
|
|
19
|
+
return xhr.response;
|
|
20
|
+
},
|
|
21
|
+
onLoad:()=>{},
|
|
22
|
+
onData:()=>{},
|
|
23
|
+
onError:()=>{},
|
|
24
|
+
onTimeout:()=>{},
|
|
25
|
+
onProgress:()=>{},
|
|
26
|
+
onAbort:()=>{},
|
|
27
|
+
onAction:()=>{},
|
|
28
|
+
};
|
|
29
|
+
|
|
6
30
|
static request(options){
|
|
7
|
-
options={...
|
|
31
|
+
options={...this.defaults,...options};
|
|
8
32
|
const {
|
|
9
33
|
method,
|
|
10
34
|
url,
|
|
@@ -18,6 +42,7 @@ export default class XHR{
|
|
|
18
42
|
timeout,
|
|
19
43
|
retry,
|
|
20
44
|
retry_delay,
|
|
45
|
+
transformResponse,
|
|
21
46
|
onLoad,
|
|
22
47
|
onData,
|
|
23
48
|
onError,
|
|
@@ -26,6 +51,14 @@ export default class XHR{
|
|
|
26
51
|
onAbort,
|
|
27
52
|
onAction
|
|
28
53
|
}=options;
|
|
54
|
+
const safeTransform=(xhr)=>{
|
|
55
|
+
try{
|
|
56
|
+
return transformResponse(xhr);
|
|
57
|
+
}catch(ex){
|
|
58
|
+
console.error("transformResponse error:",ex);
|
|
59
|
+
return xhr.response;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
29
62
|
url??="/"+uri;
|
|
30
63
|
const xhr=new XMLHttpRequest();
|
|
31
64
|
const query_string=Object.keys(query).length?"?"+Object.entries(query)
|
|
@@ -71,35 +104,37 @@ export default class XHR{
|
|
|
71
104
|
xhr.addEventListener("load",()=>{
|
|
72
105
|
onLoad(xhr);
|
|
73
106
|
if(Util.withinRange(xhr.status,200,299)){
|
|
74
|
-
onData(xhr,xhr
|
|
107
|
+
onData(xhr,safeTransform(xhr));
|
|
75
108
|
}else{
|
|
76
|
-
onError(xhr
|
|
109
|
+
onError(safeTransform(xhr));
|
|
77
110
|
}
|
|
78
111
|
});
|
|
79
112
|
|
|
80
113
|
// Error
|
|
81
114
|
xhr.addEventListener("error",()=>{
|
|
115
|
+
const retry_options={...options};
|
|
82
116
|
if(retry){
|
|
83
117
|
setTimeout(()=>{
|
|
84
|
-
XHR.request(
|
|
118
|
+
XHR.request(retry_options);
|
|
85
119
|
},retry_delay);
|
|
86
120
|
}
|
|
87
|
-
onError(xhr
|
|
121
|
+
onError(safeTransform(xhr));
|
|
88
122
|
});
|
|
89
123
|
|
|
90
124
|
// Aborto
|
|
91
125
|
xhr.addEventListener("abort",()=>{
|
|
92
|
-
onAbort(xhr
|
|
126
|
+
onAbort(safeTransform(xhr));
|
|
93
127
|
});
|
|
94
128
|
|
|
95
129
|
// Tiempo de espera
|
|
96
130
|
xhr.addEventListener("timeout",()=>{
|
|
131
|
+
const retry_options={...options};
|
|
97
132
|
if(retry){
|
|
98
133
|
setTimeout(()=>{
|
|
99
|
-
XHR.request(
|
|
134
|
+
XHR.request(retry_options);
|
|
100
135
|
},retry_delay);
|
|
101
136
|
}
|
|
102
|
-
onTimeout(xhr
|
|
137
|
+
onTimeout(safeTransform(xhr));
|
|
103
138
|
});
|
|
104
139
|
|
|
105
140
|
// Progreso
|
package/src/scss/colors.scss
CHANGED
|
@@ -6,4 +6,8 @@ $msg-text-info-color: #3a87ad;
|
|
|
6
6
|
$msg-background-error-color: #f2dede;
|
|
7
7
|
$msg-background-success-color: #dff0d8;
|
|
8
8
|
$msg-background-warning-color: #fcf8e3;
|
|
9
|
-
$msg-background-info-color: #d9edf7;
|
|
9
|
+
$msg-background-info-color: #d9edf7;
|
|
10
|
+
|
|
11
|
+
$loader-primary-color: #3b82f6;
|
|
12
|
+
$loader-secondary-color: #93c5fd;
|
|
13
|
+
$loader-muted-color: #5b6e8c;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
@use './colors.scss' as *;
|
|
2
|
+
|
|
3
|
+
artha-loader{
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
align-items: center;
|
|
7
|
+
|
|
8
|
+
.loader-content{
|
|
9
|
+
display: flex;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
align-items: center;
|
|
12
|
+
gap: 10px;
|
|
13
|
+
}
|
|
14
|
+
&[type="dots"]{
|
|
15
|
+
.loader-content{
|
|
16
|
+
|
|
17
|
+
>div{
|
|
18
|
+
width: 10px;
|
|
19
|
+
height: 10px;
|
|
20
|
+
background-color: $loader-primary-color;
|
|
21
|
+
border-radius: 50%;
|
|
22
|
+
animation: dot 1.2s infinite ease-in-out;
|
|
23
|
+
|
|
24
|
+
&:nth-of-type(1){
|
|
25
|
+
animation-delay: 0s;
|
|
26
|
+
}
|
|
27
|
+
&:nth-of-type(2){
|
|
28
|
+
animation-delay: 0.2s;
|
|
29
|
+
}
|
|
30
|
+
&:nth-of-type(3){
|
|
31
|
+
animation-delay: 0.4s;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
&[type="ring"]{
|
|
37
|
+
.loader-content{
|
|
38
|
+
|
|
39
|
+
>div{
|
|
40
|
+
width: 32px;
|
|
41
|
+
height: 32px;
|
|
42
|
+
border: 3px solid $loader-secondary-color;
|
|
43
|
+
border-top-color: $loader-primary-color;
|
|
44
|
+
border-radius: 50%;
|
|
45
|
+
animation: ring 0.8s linear infinite;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
span{
|
|
50
|
+
font-size: 1rem;
|
|
51
|
+
color: $loader-muted-color;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@keyframes dot{
|
|
56
|
+
0%,100%{
|
|
57
|
+
transform: scale(0.8);
|
|
58
|
+
opacity: 0.4;
|
|
59
|
+
}
|
|
60
|
+
50%{
|
|
61
|
+
transform: scale(1.2);
|
|
62
|
+
opacity: 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@keyframes ring{
|
|
67
|
+
to{
|
|
68
|
+
transform: rotate(360deg);
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/scss/main.scss
CHANGED
package/src/scss/message.scss
CHANGED
|
@@ -8,19 +8,19 @@ artha-message{
|
|
|
8
8
|
cursor: default;
|
|
9
9
|
|
|
10
10
|
&[type="error"]{
|
|
11
|
-
background-color: $
|
|
12
|
-
color: $
|
|
11
|
+
background-color: $msg-background-error-color;
|
|
12
|
+
color: $msg-text-error-color;
|
|
13
13
|
}
|
|
14
14
|
&[type="success"]{
|
|
15
|
-
background-color: $
|
|
16
|
-
color: $
|
|
15
|
+
background-color: $msg-background-success-color;
|
|
16
|
+
color: $msg-text-success-color;
|
|
17
17
|
}
|
|
18
18
|
&[type="warning"]{
|
|
19
|
-
background-color: $
|
|
20
|
-
color: $
|
|
19
|
+
background-color: $msg-background-warning-color;
|
|
20
|
+
color: $msg-text-warning-color;
|
|
21
21
|
}
|
|
22
22
|
&[type="info"]{
|
|
23
|
-
background-color: $
|
|
24
|
-
color: $
|
|
23
|
+
background-color: $msg-background-info-color;
|
|
24
|
+
color: $msg-text-info-color;
|
|
25
25
|
}
|
|
26
26
|
}
|
package/src/core/Config.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
const DEFAULT_CONFIG={
|
|
2
|
-
locale:"es-MX",
|
|
3
|
-
currency:"MXN",
|
|
4
|
-
money:{
|
|
5
|
-
digits:2
|
|
6
|
-
},
|
|
7
|
-
xhr:{
|
|
8
|
-
method:"GET",
|
|
9
|
-
url:null,
|
|
10
|
-
uri:"",
|
|
11
|
-
headers:{},
|
|
12
|
-
data:{},
|
|
13
|
-
query:{},
|
|
14
|
-
files:{},
|
|
15
|
-
response_type:"json",
|
|
16
|
-
with_credentials:false,
|
|
17
|
-
timeout:0,
|
|
18
|
-
retry:false,
|
|
19
|
-
retry_delay:5000,
|
|
20
|
-
onLoad:()=>{},
|
|
21
|
-
onData:()=>{},
|
|
22
|
-
onError:()=>{},
|
|
23
|
-
onTimeout:()=>{},
|
|
24
|
-
onProgress:()=>{},
|
|
25
|
-
onAbort:()=>{},
|
|
26
|
-
onAction:()=>{},
|
|
27
|
-
},
|
|
28
|
-
task_queue:{
|
|
29
|
-
title:"Petición en proceso...",
|
|
30
|
-
close:false,
|
|
31
|
-
message:null
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export default class Config{
|
|
36
|
-
|
|
37
|
-
static SETTINGS={...DEFAULT_CONFIG};
|
|
38
|
-
|
|
39
|
-
static set(options){
|
|
40
|
-
this.SETTINGS={...this.SETTINGS,...options};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static get(path,def=null){
|
|
44
|
-
return path.split(".").reduce((o,p)=>o?o[p]:def,this.SETTINGS);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
}
|