@dogiloki/artha-js 1.2.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/package.json +1 -1
package/README.md
CHANGED
|
@@ -1 +1,687 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Artha JS
|
|
2
|
+
|
|
3
|
+
Mini librería para construir interfaces HTML reactivas con Web Components, peticiones XHR, cola de tareas y mensajes visuales sin depender de frameworks.
|
|
4
|
+
|
|
5
|
+
`Artha JS` expone un conjunto pequeño de utilidades y componentes personalizados pensados para:
|
|
6
|
+
|
|
7
|
+
- enviar formularios por XMLHttpRequest
|
|
8
|
+
- renderizar listas o bloques desde respuestas JSON
|
|
9
|
+
- mostrar loaders y mensajes de estado
|
|
10
|
+
- coordinar eventos globales entre componentes
|
|
11
|
+
|
|
12
|
+
## Contenido
|
|
13
|
+
|
|
14
|
+
- [¿Qué incluye?](#que-incluye)
|
|
15
|
+
- [Instalación](#instalación)
|
|
16
|
+
- [Inicio rápido](#inicio-rápido)
|
|
17
|
+
- [Exportaciones](#exportaciones)
|
|
18
|
+
- [Componentes](#componentes)
|
|
19
|
+
- [Core](#core)
|
|
20
|
+
- [Flujo de respuesta esperado](#flujo-de-respuesta-esperado)
|
|
21
|
+
- [Eventos útiles](#eventos-útiles)
|
|
22
|
+
- [Desarrollo](#desarrollo)
|
|
23
|
+
- [Licencia](#licencia)
|
|
24
|
+
|
|
25
|
+
## ¿Qué incluye?
|
|
26
|
+
|
|
27
|
+
La librería exporta estas piezas:
|
|
28
|
+
|
|
29
|
+
- `Util`: helpers de DOM, formato y utilidades generales
|
|
30
|
+
- `EventBus`: bus global de eventos
|
|
31
|
+
- `TaskQueue`: cola simple para evitar tareas duplicadas y coordinar estados
|
|
32
|
+
- `XHR`: wrapper ligero sobre `XMLHttpRequest`
|
|
33
|
+
- `ArthaMessage`: componente para mostrar mensajes de estado
|
|
34
|
+
- `ArthaLoader`: componente visual de carga
|
|
35
|
+
- `ArthaContainer`: componente para cargar y renderizar datos
|
|
36
|
+
- `ArthaForm`: formulario con envío asíncrono
|
|
37
|
+
|
|
38
|
+
Al importar `dist/artha.min.js`, la librería registra automáticamente estos custom elements:
|
|
39
|
+
|
|
40
|
+
- `artha-container`
|
|
41
|
+
- `artha-form`
|
|
42
|
+
- `artha-message`
|
|
43
|
+
- `artha-loader`
|
|
44
|
+
|
|
45
|
+
## Instalación
|
|
46
|
+
|
|
47
|
+
### Desde npm
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install @dogiloki/artha-js
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Importando el bundle
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
import {
|
|
57
|
+
XHR,
|
|
58
|
+
EventBus,
|
|
59
|
+
TaskQueue,
|
|
60
|
+
Util,
|
|
61
|
+
ArthaForm,
|
|
62
|
+
ArthaContainer,
|
|
63
|
+
ArthaMessage,
|
|
64
|
+
ArthaLoader
|
|
65
|
+
} from "@dogiloki/artha-js/dist/artha.min.js";
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Importando estilos
|
|
69
|
+
|
|
70
|
+
Si tu bundler soporta CSS desde dependencias:
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
import "@dogiloki/artha-js/dist/artha.min.css";
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
O bien desde HTML:
|
|
77
|
+
|
|
78
|
+
```html
|
|
79
|
+
<link rel="stylesheet" href="./node_modules/@dogiloki/artha-js/dist/artha.min.css">
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Inicio rápido
|
|
83
|
+
|
|
84
|
+
Ejemplo mínimo con un formulario y un contenedor que carga datos remotos:
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<!DOCTYPE html>
|
|
88
|
+
<html lang="es">
|
|
89
|
+
<head>
|
|
90
|
+
<meta charset="UTF-8">
|
|
91
|
+
<meta name="csrf-token" content="TOKEN_OPCIONAL">
|
|
92
|
+
<link rel="stylesheet" href="./dist/artha.min.css">
|
|
93
|
+
</head>
|
|
94
|
+
<body>
|
|
95
|
+
<artha-form
|
|
96
|
+
id="user-form"
|
|
97
|
+
action="/api/user"
|
|
98
|
+
method="POST">
|
|
99
|
+
<input type="text" name="name" placeholder="Nombre">
|
|
100
|
+
<input type="email" name="email" placeholder="Correo">
|
|
101
|
+
<button type="submit">Guardar</button>
|
|
102
|
+
</artha-form>
|
|
103
|
+
|
|
104
|
+
<artha-container
|
|
105
|
+
id="users"
|
|
106
|
+
action="/api/users"
|
|
107
|
+
method="GET"
|
|
108
|
+
template="user-template">
|
|
109
|
+
</artha-container>
|
|
110
|
+
|
|
111
|
+
<template id="user-template">
|
|
112
|
+
<article>
|
|
113
|
+
<h3 data-wire="name"></h3>
|
|
114
|
+
<p data-wire="email"></p>
|
|
115
|
+
<small data-wire="id"></small>
|
|
116
|
+
</article>
|
|
117
|
+
</template>
|
|
118
|
+
|
|
119
|
+
<script type="module">
|
|
120
|
+
import "./dist/artha.min.js";
|
|
121
|
+
</script>
|
|
122
|
+
</body>
|
|
123
|
+
</html>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Exportaciones
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
import {
|
|
130
|
+
Util,
|
|
131
|
+
EventBus,
|
|
132
|
+
TaskQueue,
|
|
133
|
+
XHR,
|
|
134
|
+
ArthaMessage,
|
|
135
|
+
ArthaLoader,
|
|
136
|
+
ArthaContainer,
|
|
137
|
+
ArthaForm
|
|
138
|
+
} from "./dist/artha.min.js";
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Al cargar el módulo también se emiten dos eventos globales:
|
|
142
|
+
|
|
143
|
+
- `artha:before-register`
|
|
144
|
+
- `artha:after-register`
|
|
145
|
+
|
|
146
|
+
Esto sirve, por ejemplo, para personalizar la transformación de respuestas antes de registrar los componentes:
|
|
147
|
+
|
|
148
|
+
```js
|
|
149
|
+
import { EventBus, XHR } from "./dist/artha.min.js";
|
|
150
|
+
|
|
151
|
+
EventBus.on("artha:before-register", () => {
|
|
152
|
+
XHR.defaults.transformResponse = (xhr) => ({
|
|
153
|
+
data: xhr.response,
|
|
154
|
+
message: null,
|
|
155
|
+
errors: null,
|
|
156
|
+
status: "success"
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Componentes
|
|
162
|
+
|
|
163
|
+
### `artha-message`
|
|
164
|
+
|
|
165
|
+
Componente para mostrar mensajes visuales.
|
|
166
|
+
|
|
167
|
+
### Tipos soportados
|
|
168
|
+
|
|
169
|
+
- `info`
|
|
170
|
+
- `success`
|
|
171
|
+
- `warning`
|
|
172
|
+
- `error`
|
|
173
|
+
|
|
174
|
+
### Ejemplo
|
|
175
|
+
|
|
176
|
+
```html
|
|
177
|
+
<artha-message id="feedback"></artha-message>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
const message = document.getElementById("feedback");
|
|
182
|
+
|
|
183
|
+
message.info("Cargando información...");
|
|
184
|
+
message.success("Guardado correctamente");
|
|
185
|
+
message.warning("Faltan campos por revisar");
|
|
186
|
+
message.error("Ocurrió un error");
|
|
187
|
+
message.hidden();
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### API pública
|
|
191
|
+
|
|
192
|
+
- `show(message, type)`
|
|
193
|
+
- `info(message)`
|
|
194
|
+
- `success(message)`
|
|
195
|
+
- `warning(message)`
|
|
196
|
+
- `error(message)`
|
|
197
|
+
- `hidden()`
|
|
198
|
+
|
|
199
|
+
### `artha-loader`
|
|
200
|
+
|
|
201
|
+
Loader visual para estados de carga.
|
|
202
|
+
|
|
203
|
+
### Atributos
|
|
204
|
+
|
|
205
|
+
- `type`: tipo de loader. Default: `ring`
|
|
206
|
+
- `text`: texto mostrado debajo del loader. Default: `Petición en proceso...`
|
|
207
|
+
|
|
208
|
+
### Tipos disponibles
|
|
209
|
+
|
|
210
|
+
- `ring`
|
|
211
|
+
- `dots`
|
|
212
|
+
- `bar`
|
|
213
|
+
- `wave`
|
|
214
|
+
|
|
215
|
+
Nota: en la implementación actual `bar` y `wave` reutilizan la misma clase visual que `dots`.
|
|
216
|
+
|
|
217
|
+
### Ejemplo
|
|
218
|
+
|
|
219
|
+
```html
|
|
220
|
+
<artha-loader type="ring" text="Cargando usuarios"></artha-loader>
|
|
221
|
+
<artha-loader type="dots" text="Procesando"></artha-loader>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### `artha-form`
|
|
225
|
+
|
|
226
|
+
Formulario asíncrono basado en `XMLHttpRequest`.
|
|
227
|
+
|
|
228
|
+
### Comportamiento
|
|
229
|
+
|
|
230
|
+
- intercepta el evento `submit`
|
|
231
|
+
- valida los campos con `checkValidity()`
|
|
232
|
+
- envía los datos por XHR
|
|
233
|
+
- muestra mensajes con `artha-message`
|
|
234
|
+
- rellena campos automáticamente si la respuesta trae `data`
|
|
235
|
+
|
|
236
|
+
### Atributos útiles
|
|
237
|
+
|
|
238
|
+
- `action`: endpoint del formulario
|
|
239
|
+
- `method`: método HTTP
|
|
240
|
+
- `response-type`: tipo de respuesta del XHR. Default: `json`
|
|
241
|
+
- `disable-submit`: impide el envío automático al presionar Enter
|
|
242
|
+
- `message-target`: selector interno para localizar el mensaje asociado
|
|
243
|
+
- `id`: usado para identificar la tarea en `TaskQueue`
|
|
244
|
+
|
|
245
|
+
### Ejemplo
|
|
246
|
+
|
|
247
|
+
```html
|
|
248
|
+
<artha-form id="profile-form" action="/api/profile" method="POST">
|
|
249
|
+
<artha-message></artha-message>
|
|
250
|
+
<input type="text" name="name" required>
|
|
251
|
+
<input type="email" name="email" required>
|
|
252
|
+
<label>
|
|
253
|
+
<input type="checkbox" name="active">
|
|
254
|
+
Activo
|
|
255
|
+
</label>
|
|
256
|
+
<button type="submit">Guardar</button>
|
|
257
|
+
<button type="reset">Limpiar</button>
|
|
258
|
+
</artha-form>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### API pública
|
|
262
|
+
|
|
263
|
+
- `submit()`
|
|
264
|
+
- `reset(resetMessage = true)`
|
|
265
|
+
- `resetMessage()`
|
|
266
|
+
- `checkValidity()`
|
|
267
|
+
- `loadInputs(selector = "input,select,textarea")`
|
|
268
|
+
- `fillFromJson(json, reset = true)`
|
|
269
|
+
- `getValue(name)`
|
|
270
|
+
- `input(name)`
|
|
271
|
+
|
|
272
|
+
### Eventos emitidos
|
|
273
|
+
|
|
274
|
+
- `load`: se dispara cuando XHR termina de cargar
|
|
275
|
+
- `resolve`: se dispara cuando la respuesta fue aceptada y procesada
|
|
276
|
+
- `component-ready`: heredado de `BaseComponent`
|
|
277
|
+
|
|
278
|
+
### `artha-container`
|
|
279
|
+
|
|
280
|
+
Componente para cargar, renderizar y refrescar datos remotos, o actualizar vistas existentes.
|
|
281
|
+
|
|
282
|
+
### Casos de uso
|
|
283
|
+
|
|
284
|
+
- listados
|
|
285
|
+
- tarjetas
|
|
286
|
+
- tablas simples
|
|
287
|
+
- bloques con plantillas HTML
|
|
288
|
+
- selección simple o múltiple
|
|
289
|
+
- refresco desde eventos globales
|
|
290
|
+
|
|
291
|
+
### Atributos útiles
|
|
292
|
+
|
|
293
|
+
- `action`: endpoint a consultar
|
|
294
|
+
- `method`: método HTTP. Default: `GET`
|
|
295
|
+
- `template`: id de un `<template>` o referencia configurada en el componente
|
|
296
|
+
- `pagination`: valor configurado pero no aplicado directamente en la clase actual. Default: `10`
|
|
297
|
+
- `message`: referencia al mensaje asociado
|
|
298
|
+
- `message-target`: selector interno alternativo para localizar un `artha-message`
|
|
299
|
+
- `searcher`: activa el comportamiento de búsqueda si existe un `input-search`
|
|
300
|
+
- `selectable`: permite seleccionar items
|
|
301
|
+
- `multiple`: permite múltiples selecciones
|
|
302
|
+
- `refresh-on`: nombres de eventos del `EventBus`, separados por coma
|
|
303
|
+
- `id`: identificador del contenedor
|
|
304
|
+
|
|
305
|
+
### Ejemplo con plantilla
|
|
306
|
+
|
|
307
|
+
```html
|
|
308
|
+
<artha-container
|
|
309
|
+
id="users"
|
|
310
|
+
action="/api/users"
|
|
311
|
+
method="GET"
|
|
312
|
+
template="user-card"
|
|
313
|
+
selectable
|
|
314
|
+
multiple
|
|
315
|
+
refresh-on="users:reload,users:updated">
|
|
316
|
+
<artha-message></artha-message>
|
|
317
|
+
</artha-container>
|
|
318
|
+
|
|
319
|
+
<template id="user-card">
|
|
320
|
+
<article class="user-card">
|
|
321
|
+
<h3 data-wire="name"></h3>
|
|
322
|
+
<p data-wire="email"></p>
|
|
323
|
+
<span data-wire="active:boolean"></span>
|
|
324
|
+
</article>
|
|
325
|
+
</template>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### API pública
|
|
329
|
+
|
|
330
|
+
- `refresh(search = null)`: vuelve a pedir los datos remotos
|
|
331
|
+
- `refreshWithData(data)`: actualiza un item ya renderizado por `data.id`
|
|
332
|
+
- `render(results, refresh = false, refreshChildren = true)`
|
|
333
|
+
- `renderItem(data, refreshChildren = true, update = null)`
|
|
334
|
+
- `reset()`: limpia la selección
|
|
335
|
+
- `selection()`: devuelve el store de selección
|
|
336
|
+
- propiedad `value`: ids seleccionados
|
|
337
|
+
|
|
338
|
+
### Selección
|
|
339
|
+
|
|
340
|
+
Si `selectable` está activo:
|
|
341
|
+
|
|
342
|
+
- `container.value` devuelve el id seleccionado
|
|
343
|
+
- si también `multiple` está activo, devuelve un arreglo de ids
|
|
344
|
+
- `reset()` limpia la selección actual
|
|
345
|
+
|
|
346
|
+
### Eventos emitidos
|
|
347
|
+
|
|
348
|
+
- `load`
|
|
349
|
+
- `resolve`
|
|
350
|
+
- `dynamic-content-loaded`
|
|
351
|
+
- `item-rendered`
|
|
352
|
+
- `item-selected`
|
|
353
|
+
- `item-deselected`
|
|
354
|
+
- `component-ready`
|
|
355
|
+
|
|
356
|
+
### Sistema `data-wire`
|
|
357
|
+
|
|
358
|
+
El renderizado se basa en atributos `data-wire` dentro de la plantilla.
|
|
359
|
+
|
|
360
|
+
Formato general:
|
|
361
|
+
|
|
362
|
+
```html
|
|
363
|
+
data-wire="ruta"
|
|
364
|
+
data-wire="ruta:atributo"
|
|
365
|
+
data-wire="ruta:atributo:append"
|
|
366
|
+
data-wire="ruta:boolean"
|
|
367
|
+
data-wire="ruta:boolean:chooser"
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Ejemplos de `data-wire`
|
|
371
|
+
|
|
372
|
+
Texto simple:
|
|
373
|
+
|
|
374
|
+
```html
|
|
375
|
+
<span data-wire="name"></span>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Propiedad anidada:
|
|
379
|
+
|
|
380
|
+
```html
|
|
381
|
+
<span data-wire="user.email"></span>
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Append sobre contenido actual:
|
|
385
|
+
|
|
386
|
+
```html
|
|
387
|
+
<span data-wire="price:textContent:append">$ </span>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Booleano como check o cross:
|
|
391
|
+
|
|
392
|
+
```html
|
|
393
|
+
<span data-wire="active:boolean"></span>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Booleano con selección por plantilla:
|
|
397
|
+
|
|
398
|
+
```html
|
|
399
|
+
<div data-wire="status:boolean:chooser">
|
|
400
|
+
<template data-chooser-value="approved">
|
|
401
|
+
<span>Aprobado</span>
|
|
402
|
+
</template>
|
|
403
|
+
<template data-chooser-value="rejected">
|
|
404
|
+
<span>Rechazado</span>
|
|
405
|
+
</template>
|
|
406
|
+
<template data-chooser-default>
|
|
407
|
+
<span>Pendiente</span>
|
|
408
|
+
</template>
|
|
409
|
+
</div>
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Renderizado de arreglos
|
|
413
|
+
|
|
414
|
+
El componente soporta rutas terminadas en `[]` para iterar datos. Internamente, busca elementos marcados con `fillable` o `iterable`.
|
|
415
|
+
|
|
416
|
+
Ejemplo conceptual:
|
|
417
|
+
|
|
418
|
+
```html
|
|
419
|
+
<ul data-wire="tags[]">
|
|
420
|
+
<li>
|
|
421
|
+
<span fillable></span>
|
|
422
|
+
</li>
|
|
423
|
+
</ul>
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Nota: el flujo más sólido en la implementación actual es renderizar texto, booleanos y arreglos. Si quieres usar mapeos más avanzados, conviene probarlos primero en tu caso concreto.
|
|
427
|
+
|
|
428
|
+
## Core
|
|
429
|
+
|
|
430
|
+
### `XHR`
|
|
431
|
+
|
|
432
|
+
Wrapper de `XMLHttpRequest` con callbacks y opciones centralizadas.
|
|
433
|
+
|
|
434
|
+
### Uso básico
|
|
435
|
+
|
|
436
|
+
```js
|
|
437
|
+
import { XHR } from "./dist/artha.min.js";
|
|
438
|
+
|
|
439
|
+
XHR.request({
|
|
440
|
+
url: "/api/users",
|
|
441
|
+
method: "GET",
|
|
442
|
+
headers: {
|
|
443
|
+
Accept: "application/json"
|
|
444
|
+
},
|
|
445
|
+
onData: (xhr, data) => {
|
|
446
|
+
console.log("ok", data);
|
|
447
|
+
},
|
|
448
|
+
onError: (error) => {
|
|
449
|
+
console.error("error", error);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Opciones disponibles
|
|
455
|
+
|
|
456
|
+
- `method`: default `GET`
|
|
457
|
+
- `url`: URL final
|
|
458
|
+
- `uri`: alternativa para construir `"/" + uri"`
|
|
459
|
+
- `headers`: headers adicionales
|
|
460
|
+
- `data`: datos del formulario
|
|
461
|
+
- `query`: query params para GET
|
|
462
|
+
- `files`: archivos o listas de archivos
|
|
463
|
+
- `response_type`: default `json`
|
|
464
|
+
- `with_credentials`: default `false`
|
|
465
|
+
- `timeout`: default `0`
|
|
466
|
+
- `retry`: reintenta en `error` o `timeout`
|
|
467
|
+
- `retry_delay`: default `5000`
|
|
468
|
+
- `transformResponse(xhr)`: transforma `xhr.response`
|
|
469
|
+
- `onLoad(xhr)`
|
|
470
|
+
- `onData(xhr, transformed)`
|
|
471
|
+
- `onError(transformed)`
|
|
472
|
+
- `onTimeout(transformed)`
|
|
473
|
+
- `onProgress(event, loaded, total)`
|
|
474
|
+
- `onAbort(transformed)`
|
|
475
|
+
- `onAction(xhr)`
|
|
476
|
+
|
|
477
|
+
### Notas de comportamiento
|
|
478
|
+
|
|
479
|
+
- si existe `<meta name="csrf-token">` o `<meta name="csrf_token">`, se envía como header `X-CSRF-Token`
|
|
480
|
+
- para métodos distintos de `GET`, la librería envía `FormData`
|
|
481
|
+
- también agrega `_method` dentro del `FormData`
|
|
482
|
+
- si hay token CSRF, también agrega `csrf_token` al cuerpo
|
|
483
|
+
|
|
484
|
+
### `TaskQueue`
|
|
485
|
+
|
|
486
|
+
Evita ejecutar dos tareas con el mismo id al mismo tiempo y centraliza el cierre de estados.
|
|
487
|
+
|
|
488
|
+
### Uso básico
|
|
489
|
+
|
|
490
|
+
```js
|
|
491
|
+
import { TaskQueue } from "./dist/artha.min.js";
|
|
492
|
+
|
|
493
|
+
const queue = TaskQueue.singleton();
|
|
494
|
+
|
|
495
|
+
queue.loadTask("save-user", "Guardando usuario...", (task) => {
|
|
496
|
+
setTimeout(() => {
|
|
497
|
+
task.resolve({
|
|
498
|
+
status: 200,
|
|
499
|
+
response: JSON.stringify({
|
|
500
|
+
status: "success",
|
|
501
|
+
message: "Usuario guardado",
|
|
502
|
+
data: { id: 1 }
|
|
503
|
+
})
|
|
504
|
+
});
|
|
505
|
+
}, 500);
|
|
506
|
+
}, {
|
|
507
|
+
close: true
|
|
508
|
+
});
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### Defaults
|
|
512
|
+
|
|
513
|
+
```js
|
|
514
|
+
TaskQueue.defaults = {
|
|
515
|
+
title: "Petición en proceso...",
|
|
516
|
+
close: false,
|
|
517
|
+
message: null
|
|
518
|
+
};
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Observaciones
|
|
522
|
+
|
|
523
|
+
- cada tarea necesita un id único
|
|
524
|
+
- si se repite el id mientras sigue activa, se cancela la nueva tarea
|
|
525
|
+
- si se pasa un `ArthaMessage`, la cola actualiza sus estados visuales
|
|
526
|
+
- `close: true` intenta cerrar el mensaje automáticamente al finalizar
|
|
527
|
+
|
|
528
|
+
### `EventBus`
|
|
529
|
+
|
|
530
|
+
Bus global basado en `EventTarget`.
|
|
531
|
+
|
|
532
|
+
### Uso
|
|
533
|
+
|
|
534
|
+
```js
|
|
535
|
+
import { EventBus } from "./dist/artha.min.js";
|
|
536
|
+
|
|
537
|
+
const unsubscribe = EventBus.on("users:reload", (data) => {
|
|
538
|
+
console.log("recargar", data);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
EventBus.emit("users:reload", { source: "manual" });
|
|
542
|
+
EventBus.emitAsync("users:reload", { source: "async" });
|
|
543
|
+
unsubscribe();
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### API pública
|
|
547
|
+
|
|
548
|
+
- `EventBus.emit(name, data)`
|
|
549
|
+
- `EventBus.emitAsync(name, data)`
|
|
550
|
+
- `EventBus.on(name, callback)`
|
|
551
|
+
- `EventBus.once(name, callback)`
|
|
552
|
+
- `EventBus.onAny(callback)`
|
|
553
|
+
- `EventBus.off(name, callback)`
|
|
554
|
+
- `EventBus.clean(name)`
|
|
555
|
+
- `EventBus.clearAll()`
|
|
556
|
+
|
|
557
|
+
### Debug
|
|
558
|
+
|
|
559
|
+
```js
|
|
560
|
+
EventBus.debug = true;
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### `Util`
|
|
564
|
+
|
|
565
|
+
Utilidades generales.
|
|
566
|
+
|
|
567
|
+
### API pública
|
|
568
|
+
|
|
569
|
+
- `Util.getMeta(name)`
|
|
570
|
+
- `Util.getValueByPath(obj, path, defaultValue = null)`
|
|
571
|
+
- `Util.modal(element, visible = -1)`
|
|
572
|
+
- `Util.modalById(id, visible = -1)`
|
|
573
|
+
- `Util.formatMoney(value, options = {})`
|
|
574
|
+
- `Util.numberRandom(min, max)`
|
|
575
|
+
- `Util.withinRange(value, min, max)`
|
|
576
|
+
- `Util.createElement(type, value = null, options = {})`
|
|
577
|
+
|
|
578
|
+
### Ejemplos
|
|
579
|
+
|
|
580
|
+
```js
|
|
581
|
+
Util.getMeta("csrf-token");
|
|
582
|
+
Util.getValueByPath({ user: { name: "Ana" } }, "user.name");
|
|
583
|
+
Util.modalById("panel", true);
|
|
584
|
+
Util.formatMoney("1234.5");
|
|
585
|
+
Util.numberRandom(1, 10);
|
|
586
|
+
Util.withinRange(204, 200, 299);
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
## Flujo de respuesta esperado
|
|
590
|
+
|
|
591
|
+
`ArthaForm` y `ArthaContainer` funcionan mejor cuando el backend responde con una estructura parecida a esta:
|
|
592
|
+
|
|
593
|
+
```json
|
|
594
|
+
{
|
|
595
|
+
"status": "success",
|
|
596
|
+
"message": "Operación completada",
|
|
597
|
+
"data": []
|
|
598
|
+
}
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
También soporta errores con este formato:
|
|
602
|
+
|
|
603
|
+
```json
|
|
604
|
+
{
|
|
605
|
+
"status": "error",
|
|
606
|
+
"message": "No se pudo completar la operación",
|
|
607
|
+
"errors": {
|
|
608
|
+
"email": ["El correo ya existe"]
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
Si tu API responde con otro formato, puedes adaptar la salida usando `XHR.defaults.transformResponse`.
|
|
614
|
+
|
|
615
|
+
## Eventos útiles
|
|
616
|
+
|
|
617
|
+
### Eventos de componentes
|
|
618
|
+
|
|
619
|
+
- `component-ready`
|
|
620
|
+
- `load`
|
|
621
|
+
- `resolve`
|
|
622
|
+
- `dynamic-content-loaded`
|
|
623
|
+
- `item-rendered`
|
|
624
|
+
- `item-selected`
|
|
625
|
+
- `item-deselected`
|
|
626
|
+
|
|
627
|
+
### Eventos globales de Artha
|
|
628
|
+
|
|
629
|
+
- `artha:before-register`
|
|
630
|
+
- `artha:after-register`
|
|
631
|
+
|
|
632
|
+
### Ejemplo de refresco entre componentes
|
|
633
|
+
|
|
634
|
+
```js
|
|
635
|
+
import { EventBus } from "./dist/artha.min.js";
|
|
636
|
+
|
|
637
|
+
EventBus.emit("users:updated", { id: 3, name: "Nuevo nombre" });
|
|
638
|
+
EventBus.emit("users:reload");
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
Y en el contenedor:
|
|
642
|
+
|
|
643
|
+
```html
|
|
644
|
+
<artha-container
|
|
645
|
+
action="/api/users"
|
|
646
|
+
template="user-template"
|
|
647
|
+
refresh-on="users:reload,users:updated">
|
|
648
|
+
</artha-container>
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
## Desarrollo
|
|
652
|
+
|
|
653
|
+
### Instalar dependencias
|
|
654
|
+
|
|
655
|
+
```bash
|
|
656
|
+
npm install
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Desarrollo
|
|
660
|
+
|
|
661
|
+
Compilar CSS en modo watch:
|
|
662
|
+
|
|
663
|
+
```bash
|
|
664
|
+
npm run dev:css
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
Levantar servidor local:
|
|
668
|
+
|
|
669
|
+
```bash
|
|
670
|
+
npm run dev:server
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
Ejecutar ambos:
|
|
674
|
+
|
|
675
|
+
```bash
|
|
676
|
+
npm run dev
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
### Build
|
|
680
|
+
|
|
681
|
+
```bash
|
|
682
|
+
npm run build
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
## Licencia
|
|
686
|
+
|
|
687
|
+
MIT. Consulta [`LICENSE`](./LICENSE).
|