justalerts 2.0.0
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/LICENSE +21 -0
- package/README.md +126 -0
- package/dist/justalerts.css +138 -0
- package/dist/justalerts.js +293 -0
- package/dist/justalerts.min.css +4 -0
- package/dist/justalerts.min.js +30 -0
- package/index.d.ts +67 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Daniel Navarro Machín (DNMjustMe)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# justAlerts
|
|
2
|
+
|
|
3
|
+
Lightweight, accessible, dependency-free alerts and toast notifications for the browser.
|
|
4
|
+
By **Daniel Navarro Machín (DNMjustMe)** · [Live demo and playground](http://dnmjustme.x10.mx/justAlerts/)
|
|
5
|
+
|
|
6
|
+
*Español más abajo.*
|
|
7
|
+
|
|
8
|
+
- No jQuery or framework: plain JavaScript, about 5 KB gzipped (JS + CSS).
|
|
9
|
+
- Accessible: screen readers announce alerts and they can be closed with the keyboard.
|
|
10
|
+
- Six positions, titles, progress bar, pause on hover, light/dark theme, Spanish and English.
|
|
11
|
+
- Isolated styles (`ja-` prefix): it never touches your page's classes.
|
|
12
|
+
- TypeScript types included.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## English
|
|
17
|
+
|
|
18
|
+
### Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install justalerts
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import justAlerts from "justalerts";
|
|
26
|
+
import "justalerts/css"; // or "justalerts/min.css"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or straight from a CDN:
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/justalerts@2/dist/justalerts.min.css">
|
|
33
|
+
<script src="https://cdn.jsdelivr.net/npm/justalerts@2/dist/justalerts.min.js"></script>
|
|
34
|
+
<!-- exposes window.justAlerts -->
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Usage
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
justAlerts.success("Saved!");
|
|
41
|
+
justAlerts.danger("Something went wrong", { title: "Error" });
|
|
42
|
+
justAlerts.show({ type: "info", message: "Hello", position: "bottom-right", duration: 5000 });
|
|
43
|
+
justAlerts.closeAll();
|
|
44
|
+
justAlerts.config({ position: "bottom-center", theme: "dark", lang: "en" }); // default options
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`show()` and the shortcuts return `{ id, element, close() }`.
|
|
48
|
+
|
|
49
|
+
### Options
|
|
50
|
+
|
|
51
|
+
| Option | Default | Description |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| `type` | `"info"` | `success`, `danger`, `warning` or `info` |
|
|
54
|
+
| `message` | `""` | Alert text (escaped) |
|
|
55
|
+
| `title` | `""` | Optional bold title |
|
|
56
|
+
| `position` | `"top-right"` | `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, `bottom-right` |
|
|
57
|
+
| `duration` | `5000` | Visible milliseconds; `0` = never auto-closes |
|
|
58
|
+
| `offset` | `0` | Extra pixels from the edge |
|
|
59
|
+
| `html` | `false` | Treats the message as HTML (trusted content only) |
|
|
60
|
+
| `pauseOnHover` | `true` | Pauses the timer on hover or focus |
|
|
61
|
+
| `progress` | `true` | Time-left bar |
|
|
62
|
+
| `theme` | `"light"` | `light`, `dark` or `auto` |
|
|
63
|
+
| `lang` | `"auto"` | Language of "Close all": `es`, `en` or `auto` |
|
|
64
|
+
|
|
65
|
+
### v1 compatibility
|
|
66
|
+
|
|
67
|
+
With the `<script>` tag, `alerta(tipo, mensaje, x, y, tiempo, distancia)` and `close_all()` keep working as in v1. When imported as a module they are available as `justAlerts.legacy()` and `justAlerts.closeAll()`.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Español
|
|
72
|
+
|
|
73
|
+
### Instalación
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm install justalerts
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
import justAlerts from "justalerts";
|
|
81
|
+
import "justalerts/css"; // o "justalerts/min.css"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
O directamente desde un CDN:
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/justalerts@2/dist/justalerts.min.css">
|
|
88
|
+
<script src="https://cdn.jsdelivr.net/npm/justalerts@2/dist/justalerts.min.js"></script>
|
|
89
|
+
<!-- crea window.justAlerts -->
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Uso
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
justAlerts.success("¡Guardado!");
|
|
96
|
+
justAlerts.danger("Algo salió mal", { title: "Error" });
|
|
97
|
+
justAlerts.show({ type: "info", message: "Hola", position: "bottom-right", duration: 5000 });
|
|
98
|
+
justAlerts.closeAll();
|
|
99
|
+
justAlerts.config({ position: "bottom-center", theme: "dark", lang: "es" }); // opciones por defecto
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`show()` y los atajos devuelven `{ id, element, close() }`.
|
|
103
|
+
|
|
104
|
+
### Opciones
|
|
105
|
+
|
|
106
|
+
| Opción | Por defecto | Descripción |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| `type` | `"info"` | `success`, `danger`, `warning` o `info` |
|
|
109
|
+
| `message` | `""` | Texto de la alerta (se escapa) |
|
|
110
|
+
| `title` | `""` | Título opcional en negrita |
|
|
111
|
+
| `position` | `"top-right"` | `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, `bottom-right` |
|
|
112
|
+
| `duration` | `5000` | Milisegundos visibles; `0` = no se cierra sola |
|
|
113
|
+
| `offset` | `0` | Píxeles extra desde el borde |
|
|
114
|
+
| `html` | `false` | Interpreta el mensaje como HTML (solo contenido de confianza) |
|
|
115
|
+
| `pauseOnHover` | `true` | Pausa el tiempo al pasar el ratón o enfocar |
|
|
116
|
+
| `progress` | `true` | Barra de tiempo restante |
|
|
117
|
+
| `theme` | `"light"` | `light`, `dark` o `auto` |
|
|
118
|
+
| `lang` | `"auto"` | Idioma de "Cerrar todas": `es`, `en` o `auto` |
|
|
119
|
+
|
|
120
|
+
### Compatibilidad con la v1
|
|
121
|
+
|
|
122
|
+
Con la etiqueta `<script>`, `alerta(tipo, mensaje, x, y, tiempo, distancia)` y `close_all()` siguen funcionando como en la v1. Al importarla como módulo están disponibles como `justAlerts.legacy()` y `justAlerts.closeAll()`.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
MIT © Daniel Navarro Machín (DNMjustMe)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* justAlerts v2.0.0 · estilos
|
|
3
|
+
* Todas las clases llevan el prefijo "ja-": no afecta al resto de la página.
|
|
4
|
+
*/
|
|
5
|
+
.ja-stack {
|
|
6
|
+
--ja-offset: 16px;
|
|
7
|
+
position: fixed;
|
|
8
|
+
z-index: 2147483000;
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: 10px;
|
|
12
|
+
width: min(380px, calc(100vw - 24px));
|
|
13
|
+
pointer-events: none;
|
|
14
|
+
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
15
|
+
}
|
|
16
|
+
.ja-stack.ja-bottom { flex-direction: column-reverse; }
|
|
17
|
+
.ja-top { top: var(--ja-offset); }
|
|
18
|
+
.ja-bottom { bottom: var(--ja-offset); }
|
|
19
|
+
.ja-top-left, .ja-bottom-left { left: 12px; }
|
|
20
|
+
.ja-top-right, .ja-bottom-right { right: 12px; }
|
|
21
|
+
.ja-top-center, .ja-bottom-center { left: 50%; transform: translateX(-50%); }
|
|
22
|
+
|
|
23
|
+
.ja-list { display: flex; flex-direction: column; gap: 10px; }
|
|
24
|
+
.ja-bottom .ja-list { flex-direction: column-reverse; }
|
|
25
|
+
|
|
26
|
+
.ja-alert {
|
|
27
|
+
--ja-c: #0d6efd;
|
|
28
|
+
--ja-bg-icon: rgba(13, 110, 253, .12);
|
|
29
|
+
pointer-events: auto;
|
|
30
|
+
position: relative;
|
|
31
|
+
display: grid;
|
|
32
|
+
grid-template-columns: auto 1fr auto;
|
|
33
|
+
gap: 12px;
|
|
34
|
+
align-items: start;
|
|
35
|
+
padding: 14px 12px 16px 14px;
|
|
36
|
+
border-radius: 12px;
|
|
37
|
+
border-left: 5px solid var(--ja-c);
|
|
38
|
+
background: #fff;
|
|
39
|
+
color: #1f2937;
|
|
40
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, .18), 0 2px 6px rgba(0, 0, 0, .08);
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
font-size: 15px;
|
|
43
|
+
line-height: 1.45;
|
|
44
|
+
text-align: left;
|
|
45
|
+
animation: ja-in-right .35s cubic-bezier(.2, .8, .2, 1);
|
|
46
|
+
}
|
|
47
|
+
.ja-success { --ja-c: #198754; --ja-bg-icon: rgba(25, 135, 84, .13); }
|
|
48
|
+
.ja-danger { --ja-c: #dc3545; --ja-bg-icon: rgba(220, 53, 69, .12); }
|
|
49
|
+
.ja-warning { --ja-c: #e8a100; --ja-bg-icon: rgba(232, 161, 0, .15); }
|
|
50
|
+
.ja-info { --ja-c: #0d6efd; --ja-bg-icon: rgba(13, 110, 253, .12); }
|
|
51
|
+
|
|
52
|
+
.ja-alert.ja-dark {
|
|
53
|
+
background: #1f1f1f;
|
|
54
|
+
color: #ececec;
|
|
55
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, .5), 0 0 0 1px rgba(255, 255, 255, .06);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.ja-icon {
|
|
59
|
+
display: grid;
|
|
60
|
+
place-items: center;
|
|
61
|
+
width: 30px;
|
|
62
|
+
height: 30px;
|
|
63
|
+
border-radius: 50%;
|
|
64
|
+
background: var(--ja-bg-icon);
|
|
65
|
+
color: var(--ja-c);
|
|
66
|
+
}
|
|
67
|
+
.ja-icon svg { width: 17px; height: 17px; display: block; }
|
|
68
|
+
|
|
69
|
+
.ja-body { min-width: 0; padding-top: 4px; }
|
|
70
|
+
.ja-title { display: block; font-weight: 700; margin-bottom: 2px; }
|
|
71
|
+
.ja-message { overflow-wrap: anywhere; }
|
|
72
|
+
|
|
73
|
+
.ja-close {
|
|
74
|
+
appearance: none;
|
|
75
|
+
border: 0;
|
|
76
|
+
margin: 0;
|
|
77
|
+
padding: 6px;
|
|
78
|
+
border-radius: 8px;
|
|
79
|
+
background: transparent;
|
|
80
|
+
color: inherit;
|
|
81
|
+
opacity: .55;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
line-height: 0;
|
|
84
|
+
transition: opacity .2s, background-color .2s;
|
|
85
|
+
}
|
|
86
|
+
.ja-close:hover, .ja-close:focus-visible { opacity: 1; background: rgba(127, 127, 127, .15); outline: none; }
|
|
87
|
+
.ja-close:focus-visible { box-shadow: 0 0 0 2px var(--ja-c); }
|
|
88
|
+
.ja-close svg { width: 14px; height: 14px; display: block; }
|
|
89
|
+
|
|
90
|
+
.ja-progress { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: rgba(127, 127, 127, .15); }
|
|
91
|
+
.ja-progress span {
|
|
92
|
+
display: block;
|
|
93
|
+
height: 100%;
|
|
94
|
+
background: var(--ja-c);
|
|
95
|
+
transform-origin: left center;
|
|
96
|
+
animation-name: ja-progress;
|
|
97
|
+
animation-timing-function: linear;
|
|
98
|
+
animation-fill-mode: forwards;
|
|
99
|
+
}
|
|
100
|
+
.ja-paused .ja-progress span { animation-play-state: paused; }
|
|
101
|
+
|
|
102
|
+
.ja-close-all {
|
|
103
|
+
pointer-events: auto;
|
|
104
|
+
align-self: center;
|
|
105
|
+
appearance: none;
|
|
106
|
+
border: 0;
|
|
107
|
+
border-radius: 999px;
|
|
108
|
+
padding: 8px 18px;
|
|
109
|
+
background: rgba(20, 20, 20, .85);
|
|
110
|
+
color: #fff;
|
|
111
|
+
font: 600 13px/1 system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
box-shadow: 0 6px 18px rgba(0, 0, 0, .2);
|
|
114
|
+
transition: background-color .2s;
|
|
115
|
+
}
|
|
116
|
+
.ja-close-all:hover, .ja-close-all:focus-visible { background: rgba(20, 20, 20, 1); outline: none; }
|
|
117
|
+
.ja-close-all[hidden] { display: none; }
|
|
118
|
+
|
|
119
|
+
.ja-top-left .ja-alert, .ja-bottom-left .ja-alert { animation-name: ja-in-left; }
|
|
120
|
+
.ja-top-center .ja-alert { animation-name: ja-in-down; }
|
|
121
|
+
.ja-bottom-center .ja-alert { animation-name: ja-in-up; }
|
|
122
|
+
.ja-alert.ja-leaving { animation: ja-out .26s ease forwards; pointer-events: none; }
|
|
123
|
+
|
|
124
|
+
@keyframes ja-in-right { from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: none; } }
|
|
125
|
+
@keyframes ja-in-left { from { opacity: 0; transform: translateX(-40px); } to { opacity: 1; transform: none; } }
|
|
126
|
+
@keyframes ja-in-down { from { opacity: 0; transform: translateY(-24px); } to { opacity: 1; transform: none; } }
|
|
127
|
+
@keyframes ja-in-up { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
|
|
128
|
+
@keyframes ja-out { to { opacity: 0; transform: scale(.94); } }
|
|
129
|
+
@keyframes ja-progress { from { transform: scaleX(1); } to { transform: scaleX(0); } }
|
|
130
|
+
|
|
131
|
+
@media (max-width: 480px) {
|
|
132
|
+
.ja-stack { width: auto; left: 8px; right: 8px; transform: none; }
|
|
133
|
+
.ja-alert { font-size: 14px; }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@media (prefers-reduced-motion: reduce) {
|
|
137
|
+
.ja-alert, .ja-alert.ja-leaving { animation: none; }
|
|
138
|
+
}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* justAlerts v2.0.0
|
|
3
|
+
* Alertas y notificaciones ligeras, accesibles y sin dependencias.
|
|
4
|
+
* Daniel Navarro Machín (DNMjustMe) · http://dnmjustme.x10.mx/justAlerts/
|
|
5
|
+
*/
|
|
6
|
+
(function (root, factory) {
|
|
7
|
+
"use strict";
|
|
8
|
+
var api = factory(root);
|
|
9
|
+
if (typeof module === "object" && module.exports) {
|
|
10
|
+
module.exports = api;
|
|
11
|
+
} else {
|
|
12
|
+
root.justAlerts = api;
|
|
13
|
+
// Compatibilidad con la v1: alerta(tipo, mensaje, x, y, tiempo, distancia) y close_all()
|
|
14
|
+
root.alerta = api.legacy;
|
|
15
|
+
root.close_all = api.closeAll;
|
|
16
|
+
}
|
|
17
|
+
})(typeof window !== "undefined" ? window : this, function (root) {
|
|
18
|
+
"use strict";
|
|
19
|
+
|
|
20
|
+
var VERSION = "2.0.0";
|
|
21
|
+
var TYPES = ["success", "danger", "warning", "info"];
|
|
22
|
+
var POSITIONS = ["top-left", "top-center", "top-right", "bottom-left", "bottom-center", "bottom-right"];
|
|
23
|
+
|
|
24
|
+
var TEXTS = {
|
|
25
|
+
es: { closeAll: "Cerrar todas", close: "Cerrar notificación" },
|
|
26
|
+
en: { closeAll: "Close all", close: "Close notification" }
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
var svg = function (viewBox, d) {
|
|
30
|
+
return '<svg aria-hidden="true" focusable="false" viewBox="' + viewBox + '"><path fill="currentColor" d="' + d + '"/></svg>';
|
|
31
|
+
};
|
|
32
|
+
var ICONS = {
|
|
33
|
+
success: svg("0 0 512 512", "M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464a256 256 0 1 0 0-512 256 256 0 1 0 0 512zm113-303c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-111 111-47-47c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l64 64c9.4 9.4 24.6 9.4 33.9 0L369 209z"),
|
|
34
|
+
danger: svg("0 0 512 512", "M506.3 417 293 53c-16.3-28-57.5-28-74 0L5.7 417c-16.3 27.9 4.1 63 37 63h426.6c32.8 0 53.3-35 37-63zM232 168c0-13.3 10.7-24 24-24s24 10.7 24 24v128c0 13.3-10.7 24-24 24s-24-10.7-24-24V168zm24 248a31.4 31.4 0 1 1 0-62.9 31.4 31.4 0 1 1 0 62.9z"),
|
|
35
|
+
warning: svg("0 0 512 512", "M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7.2 40.1S486.3 480 472 480H40c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8.2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24v112c0 13.3 10.7 24 24 24s24-10.7 24-24V184c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0-64 0 32 32 0 1 0 64 0z"),
|
|
36
|
+
info: svg("0 0 512 512", "M256 512a256 256 0 1 0 0-512 256 256 0 1 0 0 512zM216 336h24v-64h-24c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24h-80c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"),
|
|
37
|
+
close: svg("0 0 384 512", "M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3l105.4 105.3c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256l105.3-105.4z")
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
var DEFAULTS = {
|
|
41
|
+
type: "info", // success | danger | warning | info
|
|
42
|
+
title: "", // título opcional (texto)
|
|
43
|
+
message: "",
|
|
44
|
+
position: "top-right", // top-left | top-center | top-right | bottom-left | bottom-center | bottom-right
|
|
45
|
+
duration: 5000, // ms; 0 = no se cierra sola
|
|
46
|
+
offset: 0, // px extra desde el borde de la pantalla
|
|
47
|
+
html: false, // true: el mensaje se interpreta como HTML (solo con contenido de confianza)
|
|
48
|
+
pauseOnHover: true, // pausa el tiempo al pasar el ratón o al enfocar la alerta
|
|
49
|
+
progress: true, // barra con el tiempo restante
|
|
50
|
+
theme: "light", // light | dark | auto
|
|
51
|
+
lang: "auto" // es | en | auto (usa <html lang> o el idioma del navegador)
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
var settings = assign({}, DEFAULTS);
|
|
55
|
+
var counter = 0;
|
|
56
|
+
var stacks = {}; // posición -> { el, list, closeAll }
|
|
57
|
+
var pending = []; // alertas pedidas antes de que exista <body>
|
|
58
|
+
|
|
59
|
+
function assign(target) {
|
|
60
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
61
|
+
var src = arguments[i];
|
|
62
|
+
if (!src) continue;
|
|
63
|
+
for (var k in src) {
|
|
64
|
+
if (Object.prototype.hasOwnProperty.call(src, k) && src[k] !== undefined) target[k] = src[k];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return target;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function texts(opts) {
|
|
71
|
+
var l = opts.lang === "auto"
|
|
72
|
+
? (document.documentElement.lang || navigator.language || "en")
|
|
73
|
+
: String(opts.lang);
|
|
74
|
+
l = l.slice(0, 2).toLowerCase();
|
|
75
|
+
return TEXTS[l] || TEXTS.en;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function reducedMotion() {
|
|
79
|
+
return !!(root.matchMedia && root.matchMedia("(prefers-reduced-motion: reduce)").matches);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isDark(theme) {
|
|
83
|
+
if (theme === "dark") return true;
|
|
84
|
+
if (theme === "auto") return !!(root.matchMedia && root.matchMedia("(prefers-color-scheme: dark)").matches);
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function getStack(position) {
|
|
89
|
+
if (stacks[position]) return stacks[position];
|
|
90
|
+
var el = document.createElement("div");
|
|
91
|
+
var vertical = position.split("-")[0];
|
|
92
|
+
el.className = "ja-stack ja-" + position + " ja-" + vertical;
|
|
93
|
+
|
|
94
|
+
var closeAll = document.createElement("button");
|
|
95
|
+
closeAll.type = "button";
|
|
96
|
+
closeAll.className = "ja-close-all";
|
|
97
|
+
closeAll.hidden = true;
|
|
98
|
+
closeAll.addEventListener("click", function () { api.closeAll(position); });
|
|
99
|
+
|
|
100
|
+
var list = document.createElement("div");
|
|
101
|
+
list.className = "ja-list";
|
|
102
|
+
|
|
103
|
+
el.appendChild(closeAll);
|
|
104
|
+
el.appendChild(list);
|
|
105
|
+
document.body.appendChild(el);
|
|
106
|
+
stacks[position] = { el: el, list: list, closeAll: closeAll };
|
|
107
|
+
return stacks[position];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function refreshStack(position) {
|
|
111
|
+
var stack = stacks[position];
|
|
112
|
+
if (!stack) return;
|
|
113
|
+
var alive = stack.list.querySelectorAll(".ja-alert:not(.ja-leaving)");
|
|
114
|
+
if (!alive.length && !stack.list.children.length) {
|
|
115
|
+
if (stack.el.parentNode) stack.el.parentNode.removeChild(stack.el);
|
|
116
|
+
delete stacks[position];
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (alive.length > 1) {
|
|
120
|
+
var t = texts(settings);
|
|
121
|
+
stack.closeAll.textContent = t.closeAll + " (" + alive.length + ")";
|
|
122
|
+
stack.closeAll.hidden = false;
|
|
123
|
+
} else {
|
|
124
|
+
stack.closeAll.hidden = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function normalize(options) {
|
|
129
|
+
var o = assign({}, settings, typeof options === "string" ? { message: options } : options);
|
|
130
|
+
if (TYPES.indexOf(o.type) === -1) o.type = "info";
|
|
131
|
+
if (POSITIONS.indexOf(o.position) === -1) o.position = DEFAULTS.position;
|
|
132
|
+
o.duration = Math.max(0, parseInt(o.duration, 10) || 0);
|
|
133
|
+
o.offset = Math.max(0, parseInt(o.offset, 10) || 0);
|
|
134
|
+
return o;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function create(o) {
|
|
138
|
+
var t = texts(o);
|
|
139
|
+
var id = "ja-" + Date.now().toString(36) + "-" + (++counter);
|
|
140
|
+
var stack = getStack(o.position);
|
|
141
|
+
if (o.offset) stack.el.style.setProperty("--ja-offset", (16 + o.offset) + "px");
|
|
142
|
+
|
|
143
|
+
var el = document.createElement("div");
|
|
144
|
+
el.id = id;
|
|
145
|
+
el.className = "ja-alert ja-" + o.type + (isDark(o.theme) ? " ja-dark" : "");
|
|
146
|
+
var urgent = o.type === "danger" || o.type === "warning";
|
|
147
|
+
el.setAttribute("role", urgent ? "alert" : "status");
|
|
148
|
+
el.setAttribute("aria-live", urgent ? "assertive" : "polite");
|
|
149
|
+
el.setAttribute("aria-atomic", "true");
|
|
150
|
+
|
|
151
|
+
var icon = document.createElement("span");
|
|
152
|
+
icon.className = "ja-icon";
|
|
153
|
+
icon.innerHTML = ICONS[o.type];
|
|
154
|
+
|
|
155
|
+
var body = document.createElement("div");
|
|
156
|
+
body.className = "ja-body";
|
|
157
|
+
if (o.title) {
|
|
158
|
+
var title = document.createElement("strong");
|
|
159
|
+
title.className = "ja-title";
|
|
160
|
+
title.textContent = o.title;
|
|
161
|
+
body.appendChild(title);
|
|
162
|
+
}
|
|
163
|
+
var msg = document.createElement("div");
|
|
164
|
+
msg.className = "ja-message";
|
|
165
|
+
if (o.html) msg.innerHTML = o.message; else msg.textContent = o.message;
|
|
166
|
+
body.appendChild(msg);
|
|
167
|
+
|
|
168
|
+
var btn = document.createElement("button");
|
|
169
|
+
btn.type = "button";
|
|
170
|
+
btn.className = "ja-close";
|
|
171
|
+
btn.setAttribute("aria-label", t.close);
|
|
172
|
+
btn.innerHTML = ICONS.close;
|
|
173
|
+
|
|
174
|
+
el.appendChild(icon);
|
|
175
|
+
el.appendChild(body);
|
|
176
|
+
el.appendChild(btn);
|
|
177
|
+
|
|
178
|
+
var bar = null;
|
|
179
|
+
if (o.duration && o.progress) {
|
|
180
|
+
var progress = document.createElement("div");
|
|
181
|
+
progress.className = "ja-progress";
|
|
182
|
+
bar = document.createElement("span");
|
|
183
|
+
bar.style.animationDuration = o.duration + "ms";
|
|
184
|
+
progress.appendChild(bar);
|
|
185
|
+
el.appendChild(progress);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Lo más nuevo junto al borde de la pantalla
|
|
189
|
+
stack.list.insertBefore(el, stack.list.firstChild);
|
|
190
|
+
|
|
191
|
+
var closed = false;
|
|
192
|
+
var timer = null;
|
|
193
|
+
var remaining = o.duration;
|
|
194
|
+
var startedAt = 0;
|
|
195
|
+
|
|
196
|
+
function start() {
|
|
197
|
+
if (!remaining || closed) return;
|
|
198
|
+
startedAt = Date.now();
|
|
199
|
+
timer = setTimeout(close, remaining);
|
|
200
|
+
el.classList.remove("ja-paused");
|
|
201
|
+
}
|
|
202
|
+
function pause() {
|
|
203
|
+
if (!timer) return;
|
|
204
|
+
clearTimeout(timer);
|
|
205
|
+
timer = null;
|
|
206
|
+
remaining = Math.max(0, remaining - (Date.now() - startedAt));
|
|
207
|
+
el.classList.add("ja-paused");
|
|
208
|
+
}
|
|
209
|
+
function close() {
|
|
210
|
+
if (closed) return;
|
|
211
|
+
closed = true;
|
|
212
|
+
clearTimeout(timer);
|
|
213
|
+
el.classList.add("ja-leaving");
|
|
214
|
+
refreshStack(o.position);
|
|
215
|
+
var done = function () {
|
|
216
|
+
if (el.parentNode) el.parentNode.removeChild(el);
|
|
217
|
+
refreshStack(o.position);
|
|
218
|
+
};
|
|
219
|
+
if (reducedMotion()) done(); else setTimeout(done, 260);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
btn.addEventListener("click", close);
|
|
223
|
+
if (o.pauseOnHover) {
|
|
224
|
+
el.addEventListener("mouseenter", pause);
|
|
225
|
+
el.addEventListener("mouseleave", start);
|
|
226
|
+
el.addEventListener("focusin", pause);
|
|
227
|
+
el.addEventListener("focusout", function (e) { if (!el.contains(e.relatedTarget)) start(); });
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
refreshStack(o.position);
|
|
231
|
+
start();
|
|
232
|
+
return { id: id, element: el, close: close };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function flush() {
|
|
236
|
+
var queue = pending;
|
|
237
|
+
pending = [];
|
|
238
|
+
queue.forEach(function (item) { item.handle._resolve(create(item.options)); });
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
var api = {
|
|
242
|
+
version: VERSION,
|
|
243
|
+
|
|
244
|
+
/** Muestra una alerta. Acepta un objeto de opciones o un texto. Devuelve { id, element, close() }. */
|
|
245
|
+
show: function (options) {
|
|
246
|
+
var o = normalize(options || {});
|
|
247
|
+
if (document.body) return create(o);
|
|
248
|
+
// Antes de que cargue la página: se muestra en cuanto exista <body>
|
|
249
|
+
var handle = { id: null, element: null, close: function () { handle._closed = true; } };
|
|
250
|
+
handle._resolve = function (real) {
|
|
251
|
+
handle.id = real.id; handle.element = real.element; handle.close = real.close;
|
|
252
|
+
if (handle._closed) real.close();
|
|
253
|
+
};
|
|
254
|
+
if (!pending.length) document.addEventListener("DOMContentLoaded", flush);
|
|
255
|
+
pending.push({ options: o, handle: handle });
|
|
256
|
+
return handle;
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
success: function (message, options) { return api.show(assign({}, options, { type: "success", message: message })); },
|
|
260
|
+
danger: function (message, options) { return api.show(assign({}, options, { type: "danger", message: message })); },
|
|
261
|
+
warning: function (message, options) { return api.show(assign({}, options, { type: "warning", message: message })); },
|
|
262
|
+
info: function (message, options) { return api.show(assign({}, options, { type: "info", message: message })); },
|
|
263
|
+
|
|
264
|
+
/** Cierra todas las alertas, o solo las de una posición. */
|
|
265
|
+
closeAll: function (position) {
|
|
266
|
+
Object.keys(stacks).forEach(function (pos) {
|
|
267
|
+
if (position && typeof position === "string" && pos !== position) return;
|
|
268
|
+
var list = stacks[pos].list.querySelectorAll(".ja-alert:not(.ja-leaving) .ja-close");
|
|
269
|
+
Array.prototype.forEach.call(list, function (b) { b.click(); });
|
|
270
|
+
});
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
/** Cambia las opciones por defecto (p. ej. { position: "bottom-right", theme: "dark", lang: "en" }). */
|
|
274
|
+
config: function (options) {
|
|
275
|
+
assign(settings, options);
|
|
276
|
+
return assign({}, settings);
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
/** API de la v1: alerta(tipo, mensaje, x, y, tiempo, distancia). El mensaje admite HTML, como antes. */
|
|
280
|
+
legacy: function (tipo, mensaje, x, y, tiempo, distancia) {
|
|
281
|
+
return api.show({
|
|
282
|
+
type: tipo,
|
|
283
|
+
message: mensaje,
|
|
284
|
+
position: (y === "bottom" ? "bottom" : "top") + "-" + (x === "left" ? "left" : "right"),
|
|
285
|
+
duration: tiempo,
|
|
286
|
+
offset: distancia,
|
|
287
|
+
html: true
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
return api;
|
|
293
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* justAlerts v2.0.0 · estilos
|
|
3
|
+
* Todas las clases llevan el prefijo "ja-": no afecta al resto de la página.
|
|
4
|
+
*/.ja-stack{--ja-offset:16px;position:fixed;z-index:2147483000;display:flex;flex-direction:column;gap:10px;width:min(380px,calc(100vw - 24px));pointer-events:none;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}.ja-stack.ja-bottom{flex-direction:column-reverse}.ja-top{top:var(--ja-offset)}.ja-bottom{bottom:var(--ja-offset)}.ja-bottom-left,.ja-top-left{left:12px}.ja-bottom-right,.ja-top-right{right:12px}.ja-bottom-center,.ja-top-center{left:50%;transform:translateX(-50%)}.ja-list{display:flex;flex-direction:column;gap:10px}.ja-bottom .ja-list{flex-direction:column-reverse}.ja-alert{--ja-c:#0d6efd;--ja-bg-icon:rgba(13, 110, 253, .12);pointer-events:auto;position:relative;display:grid;grid-template-columns:auto 1fr auto;gap:12px;align-items:start;padding:14px 12px 16px 14px;border-radius:12px;border-left:5px solid var(--ja-c);background:#fff;color:#1f2937;box-shadow:0 12px 32px rgba(0,0,0,.18),0 2px 6px rgba(0,0,0,.08);overflow:hidden;font-size:15px;line-height:1.45;text-align:left;animation:.35s cubic-bezier(.2,.8,.2,1) ja-in-right}.ja-success{--ja-c:#198754;--ja-bg-icon:rgba(25, 135, 84, .13)}.ja-danger{--ja-c:#dc3545;--ja-bg-icon:rgba(220, 53, 69, .12)}.ja-warning{--ja-c:#e8a100;--ja-bg-icon:rgba(232, 161, 0, .15)}.ja-info{--ja-c:#0d6efd;--ja-bg-icon:rgba(13, 110, 253, .12)}.ja-alert.ja-dark{background:#1f1f1f;color:#ececec;box-shadow:0 12px 32px rgba(0,0,0,.5),0 0 0 1px rgba(255,255,255,.06)}.ja-icon{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;background:var(--ja-bg-icon);color:var(--ja-c)}.ja-icon svg{width:17px;height:17px;display:block}.ja-body{min-width:0;padding-top:4px}.ja-title{display:block;font-weight:700;margin-bottom:2px}.ja-message{overflow-wrap:anywhere}.ja-close{appearance:none;border:0;margin:0;padding:6px;border-radius:8px;background:0 0;color:inherit;opacity:.55;cursor:pointer;line-height:0;transition:opacity .2s,background-color .2s}.ja-close:focus-visible,.ja-close:hover{opacity:1;background:rgba(127,127,127,.15);outline:0}.ja-close:focus-visible{box-shadow:0 0 0 2px var(--ja-c)}.ja-close svg{width:14px;height:14px;display:block}.ja-progress{position:absolute;left:0;right:0;bottom:0;height:3px;background:rgba(127,127,127,.15)}.ja-progress span{display:block;height:100%;background:var(--ja-c);transform-origin:left center;animation-name:ja-progress;animation-timing-function:linear;animation-fill-mode:forwards}.ja-paused .ja-progress span{animation-play-state:paused}.ja-close-all{pointer-events:auto;align-self:center;appearance:none;border:0;border-radius:999px;padding:8px 18px;background:rgba(20,20,20,.85);color:#fff;font:600 13px/1 system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif;cursor:pointer;box-shadow:0 6px 18px rgba(0,0,0,.2);transition:background-color .2s}.ja-close-all:focus-visible,.ja-close-all:hover{background:#141414;outline:0}.ja-close-all[hidden]{display:none}.ja-bottom-left .ja-alert,.ja-top-left .ja-alert{animation-name:ja-in-left}.ja-top-center .ja-alert{animation-name:ja-in-down}.ja-bottom-center .ja-alert{animation-name:ja-in-up}.ja-alert.ja-leaving{animation:.26s forwards ja-out;pointer-events:none}@keyframes ja-in-right{from{opacity:0;transform:translateX(40px)}to{opacity:1;transform:none}}@keyframes ja-in-left{from{opacity:0;transform:translateX(-40px)}to{opacity:1;transform:none}}@keyframes ja-in-down{from{opacity:0;transform:translateY(-24px)}to{opacity:1;transform:none}}@keyframes ja-in-up{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:none}}@keyframes ja-out{to{opacity:0;transform:scale(.94)}}@keyframes ja-progress{from{transform:scaleX(1)}to{transform:scaleX(0)}}@media (max-width:480px){.ja-stack{width:auto;left:8px;right:8px;transform:none}.ja-alert{font-size:14px}}@media (prefers-reduced-motion:reduce){.ja-alert,.ja-alert.ja-leaving{animation:none}}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* justAlerts v2.0.0
|
|
3
|
+
* Alertas y notificaciones ligeras, accesibles y sin dependencias.
|
|
4
|
+
* Daniel Navarro Machín (DNMjustMe) · http://dnmjustme.x10.mx/justAlerts/
|
|
5
|
+
*/
|
|
6
|
+
!function(e){"use strict";var t=function(e){var t="2.0.0",n=["success","danger","warning","info"],a=["top-left","top-center","top-right","bottom-left","bottom-center","bottom-right"],o={es:{closeAll:"Cerrar todas",close:"Cerrar notificación"},en:{closeAll:"Close all",close:"Close notification"}},s=function(e,t){return'<svg aria-hidden="true" focusable="false" viewBox="'+e+'"><path fill="currentColor" d="'+t+'"/></svg>'},r={success:s("0 0 512 512","M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464a256 256 0 1 0 0-512 256 256 0 1 0 0 512zm113-303c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-111 111-47-47c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l64 64c9.4 9.4 24.6 9.4 33.9 0L369 209z"),danger:s("0 0 512 512","M506.3 417 293 53c-16.3-28-57.5-28-74 0L5.7 417c-16.3 27.9 4.1 63 37 63h426.6c32.8 0 53.3-35 37-63zM232 168c0-13.3 10.7-24 24-24s24 10.7 24 24v128c0 13.3-10.7 24-24 24s-24-10.7-24-24V168zm24 248a31.4 31.4 0 1 1 0-62.9 31.4 31.4 0 1 1 0 62.9z"),warning:s("0 0 512 512","M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7.2 40.1S486.3 480 472 480H40c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8.2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24v112c0 13.3 10.7 24 24 24s24-10.7 24-24V184c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0-64 0 32 32 0 1 0 64 0z"),info:s("0 0 512 512","M256 512a256 256 0 1 0 0-512 256 256 0 1 0 0 512zM216 336h24v-64h-24c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24h-80c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"),close:s("0 0 384 512","M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3l105.4 105.3c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256l105.3-105.4z")},l={type:"info",// success | danger | warning | info
|
|
7
|
+
title:"",// título opcional (texto)
|
|
8
|
+
message:"",position:"top-right",// top-left | top-center | top-right | bottom-left | bottom-center | bottom-right
|
|
9
|
+
duration:5e3,// ms; 0 = no se cierra sola
|
|
10
|
+
offset:0,// px extra desde el borde de la pantalla
|
|
11
|
+
html:!1,// true: el mensaje se interpreta como HTML (solo con contenido de confianza)
|
|
12
|
+
pauseOnHover:!0,// pausa el tiempo al pasar el ratón o al enfocar la alerta
|
|
13
|
+
progress:!0,// barra con el tiempo restante
|
|
14
|
+
theme:"light",// light | dark | auto
|
|
15
|
+
lang:"auto"},i=m({},l),c=0,d={},u=[];// alertas pedidas antes de que exista <body>
|
|
16
|
+
function m(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];if(n)for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&void 0!==n[a]&&(e[a]=n[a])}return e}function f(e){var t="auto"===e.lang?document.documentElement.lang||navigator.language||"en":String(e.lang);return t=t.slice(0,2).toLowerCase(),o[t]||o.en}function p(){return!(!e.matchMedia||!e.matchMedia("(prefers-reduced-motion: reduce)").matches)}function v(t){return"dark"===t||"auto"===t&&!(!e.matchMedia||!e.matchMedia("(prefers-color-scheme: dark)").matches)}function h(e){if(d[e])return d[e];var t=document.createElement("div"),n=e.split("-")[0];t.className="ja-stack ja-"+e+" ja-"+n;var a=document.createElement("button");a.type="button",a.className="ja-close-all",a.hidden=!0,a.addEventListener("click",function(){E.closeAll(e)});var o=document.createElement("div");return o.className="ja-list",t.appendChild(a),t.appendChild(o),document.body.appendChild(t),d[e]={el:t,list:o,closeAll:a},d[e]}function g(e){var t=d[e];if(t){var n=t.list.querySelectorAll(".ja-alert:not(.ja-leaving)");if(!n.length&&!t.list.children.length)return t.el.parentNode&&t.el.parentNode.removeChild(t.el),void delete d[e];if(n.length>1){var a=f(i);t.closeAll.textContent=a.closeAll+" ("+n.length+")",t.closeAll.hidden=!1}else t.closeAll.hidden=!0}}function y(e){var t=m({},i,"string"==typeof e?{message:e}:e);return-1===n.indexOf(t.type)&&(t.type="info"),-1===a.indexOf(t.position)&&(t.position=l.position),t.duration=Math.max(0,parseInt(t.duration,10)||0),t.offset=Math.max(0,parseInt(t.offset,10)||0),t}function j(e){var t=f(e),n="ja-"+Date.now().toString(36)+"-"+ ++c,a=h(e.position);e.offset&&a.el.style.setProperty("--ja-offset",16+e.offset+"px");var o=document.createElement("div");o.id=n,o.className="ja-alert ja-"+e.type+(v(e.theme)?" ja-dark":"");var s="danger"===e.type||"warning"===e.type;o.setAttribute("role",s?"alert":"status"),o.setAttribute("aria-live",s?"assertive":"polite"),o.setAttribute("aria-atomic","true");var l=document.createElement("span");l.className="ja-icon",l.innerHTML=r[e.type];var i=document.createElement("div");if(i.className="ja-body",e.title){var d=document.createElement("strong");d.className="ja-title",d.textContent=e.title,i.appendChild(d)}var u=document.createElement("div");u.className="ja-message",e.html?u.innerHTML=e.message:u.textContent=e.message,i.appendChild(u);var m=document.createElement("button");m.type="button",m.className="ja-close",m.setAttribute("aria-label",t.close),m.innerHTML=r.close,o.appendChild(l),o.appendChild(i),o.appendChild(m);var y=null;if(e.duration&&e.progress){var j=document.createElement("div");j.className="ja-progress",(y=document.createElement("span")).style.animationDuration=e.duration+"ms",j.appendChild(y),o.appendChild(j)}
|
|
17
|
+
// Lo más nuevo junto al borde de la pantalla
|
|
18
|
+
a.list.insertBefore(o,a.list.firstChild);var C=!1,E=null,b=e.duration,w=0;function L(){b&&!C&&(w=Date.now(),E=setTimeout(M,b),o.classList.remove("ja-paused"))}function A(){E&&(clearTimeout(E),E=null,b=Math.max(0,b-(Date.now()-w)),o.classList.add("ja-paused"))}function M(){if(!C){C=!0,clearTimeout(E),o.classList.add("ja-leaving"),g(e.position);var t=function(){o.parentNode&&o.parentNode.removeChild(o),g(e.position)};p()?t():setTimeout(t,260)}}return m.addEventListener("click",M),e.pauseOnHover&&(o.addEventListener("mouseenter",A),o.addEventListener("mouseleave",L),o.addEventListener("focusin",A),o.addEventListener("focusout",function(e){o.contains(e.relatedTarget)||L()})),g(e.position),L(),{id:n,element:o,close:M}}function C(){var e=u;u=[],e.forEach(function(e){e.handle._resolve(j(e.options))})}var E={version:t,
|
|
19
|
+
/** Muestra una alerta. Acepta un objeto de opciones o un texto. Devuelve { id, element, close() }. */
|
|
20
|
+
show:function(e){var t=y(e||{});if(document.body)return j(t);
|
|
21
|
+
// Antes de que cargue la página: se muestra en cuanto exista <body>
|
|
22
|
+
var n={id:null,element:null,close:function(){n._closed=!0},_resolve:function(e){n.id=e.id,n.element=e.element,n.close=e.close,n._closed&&e.close()}};return u.length||document.addEventListener("DOMContentLoaded",C),u.push({options:t,handle:n}),n},success:function(e,t){return E.show(m({},t,{type:"success",message:e}))},danger:function(e,t){return E.show(m({},t,{type:"danger",message:e}))},warning:function(e,t){return E.show(m({},t,{type:"warning",message:e}))},info:function(e,t){return E.show(m({},t,{type:"info",message:e}))},
|
|
23
|
+
/** Cierra todas las alertas, o solo las de una posición. */
|
|
24
|
+
closeAll:function(e){Object.keys(d).forEach(function(t){if(!e||"string"!=typeof e||t===e){var n=d[t].list.querySelectorAll(".ja-alert:not(.ja-leaving) .ja-close");Array.prototype.forEach.call(n,function(e){e.click()})}})},
|
|
25
|
+
/** Cambia las opciones por defecto (p. ej. { position: "bottom-right", theme: "dark", lang: "en" }). */
|
|
26
|
+
config:function(e){return m(i,e),m({},i)},
|
|
27
|
+
/** API de la v1: alerta(tipo, mensaje, x, y, tiempo, distancia). El mensaje admite HTML, como antes. */
|
|
28
|
+
legacy:function(e,t,n,a,o,s){return E.show({type:e,message:t,position:("bottom"===a?"bottom":"top")+"-"+("left"===n?"left":"right"),duration:o,offset:s,html:!0})}};return E}(e);"object"==typeof module&&module.exports?module.exports=t:(e.justAlerts=t,
|
|
29
|
+
// Compatibilidad con la v1: alerta(tipo, mensaje, x, y, tiempo, distancia) y close_all()
|
|
30
|
+
e.alerta=t.legacy,e.close_all=t.closeAll)}("undefined"!=typeof window?window:this);
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Tipos de justAlerts 2.0 · http://dnmjustme.x10.mx/justAlerts/
|
|
2
|
+
// La librería se exporta con module.exports, por eso se declara con `export =`
|
|
3
|
+
// (con esModuleInterop también funciona `import justAlerts from "justalerts"`).
|
|
4
|
+
|
|
5
|
+
declare namespace justAlerts {
|
|
6
|
+
type AlertType = "success" | "danger" | "warning" | "info";
|
|
7
|
+
type Position =
|
|
8
|
+
| "top-left" | "top-center" | "top-right"
|
|
9
|
+
| "bottom-left" | "bottom-center" | "bottom-right";
|
|
10
|
+
|
|
11
|
+
interface Options {
|
|
12
|
+
/** Alert style. Default: "info". */
|
|
13
|
+
type?: AlertType;
|
|
14
|
+
/** Optional bold title (plain text). */
|
|
15
|
+
title?: string;
|
|
16
|
+
/** Alert text. Escaped unless `html` is true. */
|
|
17
|
+
message?: string;
|
|
18
|
+
/** Default: "top-right". */
|
|
19
|
+
position?: Position;
|
|
20
|
+
/** Visible milliseconds; 0 = never closes on its own. Default: 5000. */
|
|
21
|
+
duration?: number;
|
|
22
|
+
/** Extra pixels from the screen edge. Default: 0. */
|
|
23
|
+
offset?: number;
|
|
24
|
+
/** Treat `message` as HTML (trusted content only). Default: false. */
|
|
25
|
+
html?: boolean;
|
|
26
|
+
/** Pause the timer on hover or focus. Default: true. */
|
|
27
|
+
pauseOnHover?: boolean;
|
|
28
|
+
/** Show the time-left bar. Default: true. */
|
|
29
|
+
progress?: boolean;
|
|
30
|
+
/** Default: "light". */
|
|
31
|
+
theme?: "light" | "dark" | "auto";
|
|
32
|
+
/** Language of the built-in texts ("Close all"). Default: "auto". */
|
|
33
|
+
lang?: "es" | "en" | "auto";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface Handle {
|
|
37
|
+
/** Id of the alert element (null until the page has a <body>). */
|
|
38
|
+
id: string | null;
|
|
39
|
+
element: HTMLElement | null;
|
|
40
|
+
close(): void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface JustAlerts {
|
|
44
|
+
readonly version: string;
|
|
45
|
+
show(options: Options | string): Handle;
|
|
46
|
+
success(message: string, options?: Options): Handle;
|
|
47
|
+
danger(message: string, options?: Options): Handle;
|
|
48
|
+
warning(message: string, options?: Options): Handle;
|
|
49
|
+
info(message: string, options?: Options): Handle;
|
|
50
|
+
/** Close every alert, or only the ones at one position. */
|
|
51
|
+
closeAll(position?: Position): void;
|
|
52
|
+
/** Change the default options; returns the resulting defaults. */
|
|
53
|
+
config(options: Options): Required<Options>;
|
|
54
|
+
/** v1 API: alerta(tipo, mensaje, x, y, tiempo, distancia). The message accepts HTML. */
|
|
55
|
+
legacy(
|
|
56
|
+
tipo: AlertType,
|
|
57
|
+
mensaje: string,
|
|
58
|
+
x?: "left" | "right",
|
|
59
|
+
y?: "top" | "bottom",
|
|
60
|
+
tiempo?: number,
|
|
61
|
+
distancia?: number
|
|
62
|
+
): Handle;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
declare const justAlerts: justAlerts.JustAlerts;
|
|
67
|
+
export = justAlerts;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "justalerts",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Lightweight, accessible, dependency-free alerts and toast notifications for the browser.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"alerts",
|
|
7
|
+
"notifications",
|
|
8
|
+
"toast",
|
|
9
|
+
"snackbar",
|
|
10
|
+
"accessible",
|
|
11
|
+
"vanilla-js",
|
|
12
|
+
"no-dependencies"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "http://dnmjustme.x10.mx/justAlerts/",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"email": "dan.nm9906@gmail.com"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "Daniel Navarro Machín (DNMjustMe) <dan.nm9906@gmail.com> (http://dnmjustme.x10.mx/)",
|
|
20
|
+
"main": "dist/justalerts.js",
|
|
21
|
+
"types": "index.d.ts",
|
|
22
|
+
"style": "dist/justalerts.css",
|
|
23
|
+
"unpkg": "dist/justalerts.min.js",
|
|
24
|
+
"jsdelivr": "dist/justalerts.min.js",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./index.d.ts",
|
|
28
|
+
"default": "./dist/justalerts.js"
|
|
29
|
+
},
|
|
30
|
+
"./css": "./dist/justalerts.css",
|
|
31
|
+
"./min.css": "./dist/justalerts.min.css",
|
|
32
|
+
"./dist/*": "./dist/*",
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"sideEffects": [
|
|
36
|
+
"*.css"
|
|
37
|
+
],
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"index.d.ts"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"sync": "node scripts/sync.js",
|
|
44
|
+
"prepack": "node scripts/sync.js",
|
|
45
|
+
"test": "node scripts/sync.js && node scripts/test.js"
|
|
46
|
+
}
|
|
47
|
+
}
|