# justAlerts 3

SweetAlert-style **modals, forms, step wizards and toasts** for the browser: lightweight, accessible and dependency-free.
By **Daniel Navarro Machín (DNMjustMe)** · [Website, visual builder and examples](https://www.dnmjustme.x10.mx/justAlerts/)

*Español más abajo.*

- **Modals**: alert, confirm, prompt and custom dialogs with animated icons, three buttons, timer, images and HTML.
- **Forms**: build them from a field list (text, email, select, radio, checkboxes, range, file with previews…) or inject your own `<form>` / `<template>`. Native + custom (async) validation, values returned as a typed object.
- **Async confirm**: `onConfirm` shows a loading button; throw to show the error inside the modal, return a value to resolve with it.
- **Step wizard** with progress dots, Back button and values kept between steps.
- **Toasts** with titles, six positions, action buttons ("Undo"), live `update()` and `promise()` toasts (loading → success / error).
- **Accessible**: focus trap and restore, inert background, Esc and backdrop, ARIA roles, screen-reader announcements, reduced motion.
- About 14 KB gzipped (JS + CSS), no dependencies, light/dark/auto theme, Spanish and English, TypeScript types.
- Compatible with v1 and v2 code.

## Install

```bash
npm install justalerts
```

```js
import justAlerts from "justalerts";
import "justalerts/css"; // or "justalerts/min.css"
```

Or from the CDN (exposes `window.justAlerts`):

```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/justalerts@3/dist/justalerts.min.css">
<script src="https://cdn.jsdelivr.net/npm/justalerts@3/dist/justalerts.min.js"></script>
```

Every version stays available: `justalerts@3`, `justalerts@2` and `justalerts@1` (v1 needs jQuery). See the [version history](https://www.dnmjustme.x10.mx/justAlerts/#versiones).

## Modals

```js
await justAlerts.alert({ type: "success", title: "Saved!", text: "Your changes are safe." });

if (await justAlerts.confirm("Delete the file?", { text: "This cannot be undone.", confirm: { text: "Yes, delete", style: "danger" } })) {
  justAlerts.success("Deleted");
}

const email = await justAlerts.prompt({ title: "Your email", input: { type: "email", required: true } }); // string or null

const r = await justAlerts.modal({
  type: "question", title: "Save changes?",
  confirm: "Save", deny: "Don't save", cancel: true, timer: 10000
}); // { confirmed, action: "confirm" | "deny" | "cancel" | "close" | "esc" | "backdrop" | "timer", value }
```

## Forms

```js
const data = await justAlerts.form([
  { name: "name", label: "Name", required: true, width: "half" },
  { name: "age", label: "Age", type: "number", min: 18, width: "half" },
  { name: "plan", label: "Plan", type: "select", options: { basic: "Basic", pro: "Pro" }, required: true },
  { name: "extras", label: "Extras", type: "checkboxes", options: ["Support", "Domain"] },
  { name: "user", label: "Username", required: true,
    validate: async v => (await isTaken(v)) ? "That username is taken" : true }
], { title: "Sign up", size: "lg" });
// → { name: "Ana", age: 27, plan: "pro", extras: ["Domain"], user: "ana" } or null
```

Field options: `name`, `type` (`text`, `email`, `password`, `number`, `tel`, `url`, `date`, `time`, `color`, `textarea`, `select`, `radio`, `checkboxes`, `checkbox`, `range`, `file`…), `label`, `placeholder`, `value`, `required`, `min`, `max`, `step`, `minLength`, `maxLength`, `pattern`, `options`, `hint`, `width: "half"`, `rows`, `multiple`, `accept`, `preview`, `unit`, `attrs`, `validate(value, values)`.

Your own markup works too: `form: "#my-template"`, a `<form>` element or an HTML string. Values are read with `justAlerts.serialize()` (checkbox groups → arrays, numbers → `Number`, files → `File`).

### Sending a form

```js
const res = await justAlerts.modal({
  title: "Contact", form: fields, cancel: true, loadingText: "Sending…",
  onConfirm: async values => {
    const r = await fetch("/api/contact", { method: "POST", body: JSON.stringify(values) });
    if (!r.ok) throw new Error("The server did not respond"); // shown inside the modal
    return r.json();                                          // becomes res.value
  }
});
```

## Step wizard

```js
const { completed, values } = await justAlerts.steps([
  { name: "account", title: "Your account", form: [{ name: "email", type: "email", required: true }] },
  { name: "profile", title: "Your profile", form: [{ name: "alias", label: "Alias" }] },
  { title: "All set?", text: "Review and finish." }
], { cancel: true });
// values → { account: { email }, profile: { alias }, step3: true }
```

## Toasts

```js
justAlerts.success("Saved!");
justAlerts.danger("Something went wrong", { title: "Error", position: "bottom-right" });

const t = justAlerts.info("Uploading…", { duration: 0 });
t.update({ type: "success", message: "Uploaded", duration: 3000 });

justAlerts.warning("Message deleted", { action: { label: "Undo", onClick: () => restore() } });

await justAlerts.promise(fetch("/api/save"), {
  loading: "Saving…", success: "Saved", error: e => "Error: " + e.message
});

justAlerts.config({ position: "bottom-center", theme: "dark", lang: "en" }); // defaults
```

Toast options: `type`, `title`, `message`, `position`, `duration` (0 = sticky), `offset`, `html`, `pauseOnHover`, `progress`, `action`, `theme`, `lang`.

## More

- `justAlerts.mixin({ theme: "dark", size: "sm" })` returns the modal functions with your defaults.
- `justAlerts.current()` returns the open modal controller: `values()`, `update()`, `loading()`, `error()`, `fieldError()`, `close()`, `stopTimer()`, `resumeTimer()`, `timeLeft()`.
- Theme with CSS variables: `--ja-primary`, `--ja-radius`, `--ja-font`, `--ja-success`, `--ja-danger`…
- Full option reference and visual builder: https://www.dnmjustme.x10.mx/justAlerts/

## Upgrading

Nothing breaks: v2 code (`show`, `success`…, `closeAll`, `config`) and v1 code (`alerta(type, message, x, y, time, distance)` and `close_all()` with the `<script>` tag) keep working.

---

## Español

**Modales, formularios, asistentes por pasos y avisos** al estilo de SweetAlert: ligeros, accesibles y sin dependencias.

```bash
npm install justalerts
```

```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/justalerts@3/dist/justalerts.min.css">
<script src="https://cdn.jsdelivr.net/npm/justalerts@3/dist/justalerts.min.js"></script>
```

```js
// Modal de confirmación → true / false
if (await justAlerts.confirm("¿Borrar el archivo?", { confirm: { text: "Sí, borrar", style: "danger" } })) {
  justAlerts.success("Borrado");
}

// Formulario → objeto con los valores, o null si se cancela
const datos = await justAlerts.form([
  { name: "nombre", label: "Nombre", required: true },
  { name: "correo", label: "Correo", type: "email", required: true }
], { title: "Contacto" });

// Envío con botón de carga: si lanzas un error, se muestra dentro del modal
await justAlerts.modal({ title: "Enviar", form: campos, onConfirm: async v => enviar(v) });

// Asistente por pasos con "Atrás"
const { completed, values } = await justAlerts.steps([{ title: "Paso 1", input: "text" }, { title: "Paso 2", text: "Fin" }]);

// Avisos: con acción, actualizables y de promesa
justAlerts.warning("Mensaje borrado", { action: { label: "Deshacer", onClick: deshacer } });
justAlerts.promise(guardar(), { loading: "Guardando…", success: "Guardado", error: "No se pudo guardar" });
```

Los textos propios (Aceptar, Cancelar, Siguiente, errores de validación…) salen en español o inglés según `<html lang>` o la opción `lang`.

Todas las versiones siguen disponibles: `justalerts@3`, `justalerts@2` y `justalerts@1` (la v1 necesita jQuery). El código de la v1 y de la v2 sigue funcionando con la v3.

Referencia completa, constructor visual y ejemplos: https://www.dnmjustme.x10.mx/justAlerts/

---

MIT © 2021–2026 Daniel Navarro Machín (DNMjustMe)
