@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 CHANGED
@@ -1 +1,687 @@
1
- # artha-js
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).
@@ -1 +1 @@
1
- artha-message{width:100%;padding:10px;text-align:left;font-size:1em;cursor:default}artha-message[type=error]{background-color:#f2dede;color:#b94a48}artha-message[type=success]{background-color:#dff0d8;color:#468847}artha-message[type=warning]{background-color:#fcf8e3;color:#c09853}artha-message[type=info]{background-color:#d9edf7;color:#3a87ad}/*# sourceMappingURL=artha.min.css.map */
1
+ artha-message{width:100%;padding:10px;text-align:left;font-size:1em;cursor:default}artha-message[type=error]{background-color:#f2dede;color:#b94a48}artha-message[type=success]{background-color:#dff0d8;color:#468847}artha-message[type=warning]{background-color:#fcf8e3;color:#c09853}artha-message[type=info]{background-color:#d9edf7;color:#3a87ad}artha-loader{display:inline-flex;flex-direction:column;align-items:center}artha-loader .loader-content{display:flex;justify-content:center;align-items:center;gap:10px}artha-loader[type=dots] .loader-content>div{width:10px;height:10px;background-color:#3b82f6;border-radius:50%;animation:dot 1.2s infinite ease-in-out}artha-loader[type=dots] .loader-content>div:nth-of-type(1){animation-delay:0s}artha-loader[type=dots] .loader-content>div:nth-of-type(2){animation-delay:.2s}artha-loader[type=dots] .loader-content>div:nth-of-type(3){animation-delay:.4s}artha-loader[type=ring] .loader-content>div{width:32px;height:32px;border:3px solid #93c5fd;border-top-color:#3b82f6;border-radius:50%;animation:ring .8s linear infinite}artha-loader span{font-size:1rem;color:#5b6e8c}@keyframes dot{0%,100%{transform:scale(0.8);opacity:.4}50%{transform:scale(1.2);opacity:1}}@keyframes ring{to{transform:rotate(360deg)}}/*# sourceMappingURL=artha.min.css.map */
@@ -1 +1 @@
1
- {"version":3,"sourceRoot":"","sources":["../src/scss/message.scss","../src/scss/colors.scss"],"names":[],"mappings":"AAEA,cACI,WACA,aACA,gBACA,cACA,eAEA,0BACI,iBCLqB,QDMrB,MCVe,QDYnB,4BACI,iBCRuB,QDSvB,MCbiB,QDerB,4BACI,iBCXuB,QDYvB,MChBiB,QDkBrB,yBACI,iBCdoB,QDepB,MCnBc","file":"artha.min.css"}
1
+ {"version":3,"sourceRoot":"","sources":["../src/scss/message.scss","../src/scss/colors.scss","../src/scss/loader.scss"],"names":[],"mappings":"AAEA,cACI,WACA,aACA,gBACA,cACA,eAEA,0BACI,iBCLqB,QDMrB,MCVe,QDYnB,4BACI,iBCRuB,QDSvB,MCbiB,QDerB,4BACI,iBCXuB,QDYvB,MChBiB,QDkBrB,yBACI,iBCdoB,QDepB,MCnBc,QCFtB,aACI,oBACA,sBACA,mBAEA,6BACI,aACA,uBACA,mBACA,SAKI,4CACI,WACA,YACA,iBDTO,QCUP,kBACA,wCAEA,2DACI,mBAEJ,2DACI,oBAEJ,2DACI,oBAQR,4CACI,WACA,YACA,yBACA,iBDhCO,QCiCP,kBACA,mCAIZ,kBACI,eACA,MDtCa,QC0CrB,eACI,QACI,qBACA,WAEJ,IACI,qBACA,WAIR,gBACI,GACI","file":"artha.min.css"}