Metadata-Version: 2.4
Name: xeolux-loadingkit
Version: 0.6.0
Summary: Loaders, skeleton screens, overlays et indicateurs HTMX pour Django.
Author-email: Xeolux <contact@xeolux.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/Xeolux-Corp/xeolux-loadingkit
Project-URL: Repository, https://github.com/Xeolux-Corp/xeolux-loadingkit
Project-URL: Bug Tracker, https://github.com/Xeolux-Corp/xeolux-loadingkit/issues
Keywords: django,loading,skeleton,htmx,spinner,overlay,xeolux
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: django>=4.2
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-django; extra == "dev"
Dynamic: license-file

# xeolux-loadingkit

[![PyPI version](https://img.shields.io/pypi/v/xeolux-loadingkit)](https://pypi.org/project/xeolux-loadingkit/)
[![Python](https://img.shields.io/pypi/pyversions/xeolux-loadingkit)](https://pypi.org/project/xeolux-loadingkit/)
[![Django](https://img.shields.io/badge/django-4.2%2B-green)](https://www.djangoproject.com/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![CI](https://github.com/Xeolux-Corp/xeolux-loadingkit/actions/workflows/ci.yml/badge.svg)](https://github.com/Xeolux-Corp/xeolux-loadingkit/actions)

> Package Django léger pour ajouter des loaders, skeleton screens, overlays, toasts et indicateurs HTMX dans n'importe quel projet.

Fait partie de la suite **Xeolux** — packages Django minimalistes et réutilisables.

---

## Fonctionnalités

| Template tag | Description |
|---|---|
| `{% xeolux_loadingkit_css %}` | Injecte la feuille CSS du package |
| `{% xeolux_loadingkit_js %}` | Injecte le JS optionnel (`XeoluxLoadingKit` API) |
| `{% xeolux_loader %}` | Spinner animé (sm / md / lg) avec texte optionnel |
| `{% xeolux_overlay %}` | Overlay plein écran avec backdrop blur |
| `{% xeolux_skeleton %}` | Skeleton shimmer — 15 types |
| `{% xeolux_htmx_indicator %}` | Indicateur compatible HTMX |
| `{% xeolux_progress %}` | Barre de progression déterminée |
| `{% xeolux_topbar %}` | Barre fine en haut de page (style NProgress) |
| `{% xeolux_toast %}` | Notification toast (info / success / warning / error) |

**Tout composant accepte un paramètre `theme="dark"` ou `theme="light"`** pour forcer le thème localement, indépendamment du système.

---

## Installation

```bash
pip install xeolux-loadingkit
```

### Ajout dans `INSTALLED_APPS`

```python
# settings.py
INSTALLED_APPS = [
    ...
    "xeolux_loadingkit",
]
```

> `django.contrib.staticfiles` doit également être présent (il l'est par défaut).

---

## Utilisation

### 1. Injecter le CSS (et le JS optionnel)

```django
{% load xeolux_loadingkit %}

<head>
  {% xeolux_loadingkit_css %}
</head>
<body>
  ...
  {% xeolux_loadingkit_js %}  {# optionnel — active l'API XeoluxLoadingKit #}
</body>
```

---

### 2. Loader (spinner)

```django
{% xeolux_loader %}
{% xeolux_loader size="sm" %}
{% xeolux_loader size="lg" text="Veuillez patienter" %}
{% xeolux_loader size="md" theme="dark" %}
```

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `size` | `str` | `"md"` | `"sm"`, `"md"` ou `"lg"` |
| `text` | `str\|None` | `None` | Texte à côté du spinner |
| `theme` | `str\|None` | `None` | `"dark"` ou `"light"` pour forcer le thème |

---

### 3. Overlay

```django
{% xeolux_overlay %}
{% xeolux_overlay text="Traitement en cours..." active=True %}
```

```javascript
// Via JS — ou avec {% xeolux_loadingkit_js %}
XeoluxLoadingKit.overlay.show("Sauvegarde...");
XeoluxLoadingKit.overlay.hide();
```

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `text` | `str` | `"Chargement en cours..."` | Texte de l'overlay |
| `active` | `bool` | `False` | Visible au rendu |
| `theme` | `str\|None` | `None` | `"dark"` ou `"light"` |

---

### 4. Skeleton — 15 types

```django
{% xeolux_skeleton %}                                {# text #}
{% xeolux_skeleton type="card" %}
{% xeolux_skeleton type="avatar" %}
{% xeolux_skeleton type="table" lines=4 rows=5 %}
{% xeolux_skeleton type="form" lines=3 %}
{% xeolux_skeleton type="list" lines=5 %}
{% xeolux_skeleton type="list-detail" lines=4 %}     {# avatar + titre + sous-titre + meta #}
{% xeolux_skeleton type="image" format="portrait" %}
{% xeolux_skeleton type="nav" %}
{% xeolux_skeleton type="footer" lines=4 %}
{% xeolux_skeleton type="dashboard" lines=3 %}
{% xeolux_skeleton type="product" %}
{% xeolux_skeleton type="profile" %}
{% xeolux_skeleton type="hero" lines=2 %}            {# section hero pleine largeur #}
{% xeolux_skeleton type="sidebar" lines=6 %}         {# navigation latérale #}
```

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `type` | `str` | `"text"` | 15 types — voir ci-dessus |
| `lines` | `int` | `3` | Lignes / items selon le type (1–20) |
| `rows` | `int` | `4` | Rangées pour `"table"` (1–50) |
| `format` | `str` | `"landscape"` | Format image : `"square"`, `"landscape"`, `"portrait"`, `"panoramic"`, `"thumbnail"` |
| `theme` | `str\|None` | `None` | `"dark"` ou `"light"` |

---

### 5. Indicateur HTMX

```django
<button hx-post="/save/" hx-indicator="#xeolux-htmx-loader">
  Enregistrer
</button>

{% xeolux_htmx_indicator text="Enregistrement..." %}
```

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `text` | `str` | `"Chargement..."` | Texte pendant la requête |
| `theme` | `str\|None` | `None` | `"dark"` ou `"light"` |

---

### 6. Barre de progression

```django
{% xeolux_progress value=65 label="Upload" %}
{% xeolux_progress value=80 striped=True animated=True %}
{% xeolux_progress value=100 animated=False %}
```

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `value` | `int\|float` | `0` | Valeur 0–100 |
| `label` | `str\|None` | `None` | Texte au-dessus de la barre |
| `animated` | `bool` | `True` | Effet shimmer |
| `striped` | `bool` | `False` | Motif rayé |
| `theme` | `str\|None` | `None` | `"dark"` ou `"light"` |

---

### 7. Topbar

```django
{# Rendu dans le <body> — invisible par défaut #}
{% xeolux_topbar %}

{# Déterminé — progression à 60% #}
{% xeolux_topbar active=True value=60 %}
```

```javascript
// Via JS (nécessite {% xeolux_loadingkit_js %})
XeoluxLoadingKit.topbar.start();     // indéterminé (s'arrête à 90%)
XeoluxLoadingKit.topbar.set(70);     // progression déterminée
XeoluxLoadingKit.topbar.done();      // 100% puis disparaît
XeoluxLoadingKit.topbar.reset();     // réinitialise silencieusement
```

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `active` | `bool` | `False` | En cours de chargement |
| `done` | `bool` | `False` | Complété — disparaît après 700 ms |
| `animated` | `bool` | `True` | Effet shimmer |
| `value` | `int\|float\|None` | `None` | Progression déterminée 0–100 |
| `theme` | `str\|None` | `None` | `"dark"` ou `"light"` |

---

### 8. Toast

```django
{# Dans un template Django — rendu statique #}
{% xeolux_toast message="Sauvegardé !" type="success" %}
{% xeolux_toast message="Erreur réseau." type="error" dismissible=False %}
{% xeolux_toast message="Mise à jour disponible." type="info" %}
{% xeolux_toast message="Vérifiez vos données." type="warning" theme="dark" %}
```

```javascript
// Via JS (nécessite {% xeolux_loadingkit_js %})
XeoluxLoadingKit.toast.show("Sauvegardé !", "success");
XeoluxLoadingKit.toast.show("Erreur réseau", "error", { duration: 6000 });
XeoluxLoadingKit.toast.show("Info", "info", { dismissible: false });
```

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `message` | `str` | `""` | Texte de la notification |
| `type` | `str` | `"info"` | `"info"`, `"success"`, `"warning"`, `"error"` |
| `dismissible` | `bool` | `True` | Bouton de fermeture |
| `theme` | `str\|None` | `None` | `"dark"` ou `"light"` |

---

## Exemple Django complet (avec HTMX)

### `views.py`

```python
from django.views.generic import TemplateView
from django.http import HttpResponse
import time

class DashboardView(TemplateView):
    template_name = "dashboard.html"

def save_profile(request):
    # Simule un traitement
    time.sleep(0.5)
    return HttpResponse('<p id="result" class="text-green-600">Profil sauvegardé !</p>')
```

### `dashboard.html`

```django
{% load xeolux_loadingkit %}
<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  {% xeolux_loadingkit_css %}
  <script src="https://unpkg.com/htmx.org@1.9.12"></script>
</head>
<body>
  {# Topbar — initialisée par JS #}
  {% xeolux_topbar %}

  {# Overlay — contrôlé par JS ou HTMX events #}
  {% xeolux_overlay text="Chargement du tableau de bord..." %}

  {# Contenu principal #}
  <main>
    <h1>Tableau de bord</h1>

    {# Skeleton affiché pendant le chargement (swappé par HTMX) #}
    <div id="stats"
         hx-get="/api/stats/"
         hx-trigger="load"
         hx-indicator="#xeolux-htmx-loader">
      {% xeolux_skeleton type="dashboard" lines=4 %}
    </div>

    {# Formulaire avec barre de progression #}
    <form hx-post="/save-profile/"
          hx-target="#result"
          hx-on::before-request="XeoluxLoadingKit.topbar.start()"
          hx-on::after-request="XeoluxLoadingKit.topbar.done()">
      {% csrf_token %}
      <input type="text" name="name">
      <button type="submit">Sauvegarder</button>
    </form>
    <div id="result"></div>

    {# Indicateur HTMX #}
    {% xeolux_htmx_indicator text="Enregistrement..." %}
  </main>

  {% xeolux_loadingkit_js %}
  <script>
    // Démarrer la topbar au chargement de la page
    document.addEventListener("DOMContentLoaded", function () {
      XeoluxLoadingKit.topbar.start();
      window.addEventListener("load", function () {
        XeoluxLoadingKit.topbar.done();
      });
    });
  </script>
</body>
</html>
```

---

## Personnalisation CSS

```css
:root {
  --xlk-primary:      #3b6cf7;   /* Couleur principale */
  --xlk-bg:           #ffffff;   /* Fond des composants */
  --xlk-muted:        #e2e6f0;   /* Fond des skeletons / track */
  --xlk-text:         #374151;   /* Couleur du texte */
  --xlk-overlay-bg:   rgba(15, 20, 40, 0.55);
  --xlk-radius:       0.5rem;    /* Border-radius global */
  --xlk-speed:        0.7s;      /* Vitesse des animations */
  --xlk-font:         inherit;   /* Police des composants */
}
```

Le dark mode est **automatique** via `prefers-color-scheme: dark`.  
Pour forcer un thème sur un composant, utilisez le paramètre `theme="dark"` ou `theme="light"`.

---

## API JavaScript (`XeoluxLoadingKit`)

Disponible après `{% xeolux_loadingkit_js %}` :

```javascript
// Topbar
XeoluxLoadingKit.topbar.start()    // démarrer (indéterminé, s'arrête à 90%)
XeoluxLoadingKit.topbar.set(70)    // progression à 70%
XeoluxLoadingKit.topbar.done()     // 100% + disparaît
XeoluxLoadingKit.topbar.reset()    // réinitialiser silencieusement

// Overlay
XeoluxLoadingKit.overlay.show()              // afficher
XeoluxLoadingKit.overlay.show("Sauvegarde...") // avec texte
XeoluxLoadingKit.overlay.hide()              // masquer

// Toast
XeoluxLoadingKit.toast.show("Sauvegardé !", "success")
XeoluxLoadingKit.toast.show("Erreur", "error", { duration: 6000 })
XeoluxLoadingKit.toast.show("Info", "info", { dismissible: false })
// duration=0 → toast permanent (dismissible seulement)
```

---

## Lancer les tests

```bash
pip install -e ".[dev]"
python -m pytest tests/ -v
```

---

## Build & Publication PyPI

```bash
pip install build twine
rm -rf dist/ build/ *.egg-info
python -m build
twine check dist/*
twine upload dist/*
```

---

## Structure du projet

```
xeolux-loadingkit/
├── .github/workflows/ci.yml       ← CI GitHub Actions
├── xeolux_loadingkit/
│   ├── __init__.py
│   ├── apps.py
│   ├── py.typed                   ← PEP 561 type marker
│   ├── templatetags/
│   │   └── xeolux_loadingkit.py   ← 9 template tags
│   ├── templates/xeolux_loadingkit/
│   │   ├── loader.html
│   │   ├── overlay.html
│   │   ├── skeleton.html          ← 15 types
│   │   ├── htmx_indicator.html
│   │   ├── progress.html
│   │   ├── topbar.html
│   │   └── toast.html
│   └── static/xeolux_loadingkit/
│       ├── css/loadingkit.css
│       └── js/loadingkit.js       ← API JS optionnelle
├── tests/test_template_tags.py
├── demo/index.html
├── CHANGELOG.md
├── README.md
├── pyproject.toml
├── LICENSE
└── MANIFEST.in
```

---

## Compatibilité

| Django | Python |
|--------|--------|
| 4.2    | 3.10, 3.11, 3.12 |
| 5.0    | 3.10, 3.11, 3.12 |
| 5.1    | 3.10, 3.11, 3.12 |

---

## Licence

MIT © [Xeolux](https://github.com/Xeolux-Corp)


---

## Fonctionnalités

| Template tag | Description |
|---|---|
| `{% xeolux_loadingkit_css %}` | Injecte la feuille CSS du package |
| `{% xeolux_loader %}` | Spinner animé (sm / md / lg) avec texte optionnel |
| `{% xeolux_overlay %}` | Overlay plein écran avec backdrop blur |
| `{% xeolux_skeleton %}` | Skeleton shimmer (text / card / avatar / table / form) |
| `{% xeolux_htmx_indicator %}` | Indicateur compatible HTMX |

---

## Installation

```bash
pip install xeolux-loadingkit
```

### Ajout dans `INSTALLED_APPS`

```python
# settings.py
INSTALLED_APPS = [
    ...
    "xeolux_loadingkit",
]
```

> `django.contrib.staticfiles` doit également être présent (il l'est par défaut).

---

## Utilisation

### 1. Injecter le CSS

Placez ce tag dans le `<head>` de votre template de base, **après** avoir chargé la bibliothèque :

```django
{% load xeolux_loadingkit %}

<head>
  {% xeolux_loadingkit_css %}
</head>
```

---

### 2. Loader (spinner)

```django
{# Taille par défaut (md) #}
{% xeolux_loader %}

{# Avec taille et texte #}
{% xeolux_loader size="sm" %}
{% xeolux_loader size="md" text="Chargement..." %}
{% xeolux_loader size="lg" text="Veuillez patienter" %}
```

**Paramètres :**

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `size` | `str` | `"md"` | `"sm"`, `"md"` ou `"lg"` |
| `text` | `str\|None` | `None` | Texte affiché à côté du spinner |

---

### 3. Overlay

```django
{# Overlay inactif (caché) #}
{% xeolux_overlay %}

{# Overlay actif (visible) #}
{% xeolux_overlay text="Traitement en cours..." active=True %}
```

Pour l'activer dynamiquement via JavaScript :

```javascript
document.querySelector('.xlk-overlay').classList.add('xlk-overlay--active');
```

**Paramètres :**

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `text` | `str` | `"Chargement en cours..."` | Texte de l'overlay |
| `active` | `bool` | `False` | Si `True`, l'overlay est visible au chargement |

---

### 4. Skeleton

```django
{# Texte (défaut) #}
{% xeolux_skeleton %}
{% xeolux_skeleton type="text" lines=4 %}

{# Card #}
{% xeolux_skeleton type="card" %}

{# Avatar #}
{% xeolux_skeleton type="avatar" %}

{# Tableau #}
{% xeolux_skeleton type="table" lines=4 rows=5 %}

{# Formulaire #}
{% xeolux_skeleton type="form" lines=3 %}
```

**Paramètres :**

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `type` | `str` | `"text"` | `"text"`, `"card"`, `"avatar"`, `"table"`, `"form"` |
| `lines` | `int` | `3` | Nombre de lignes (text / form) ou colonnes (table) |
| `rows` | `int` | `4` | Nombre de lignes pour le type `"table"` |

---

### 5. Indicateur HTMX

```django
{% xeolux_htmx_indicator text="Chargement..." %}
```

L'indicateur est **masqué par défaut** et devient visible pendant une requête HTMX grâce à la classe `.htmx-indicator` standard.

#### Exemple complet avec HTMX

```django
<button
    hx-post="/save/"
    hx-target="#result"
    hx-indicator="#xeolux-htmx-loader">
    Enregistrer
</button>

{% xeolux_htmx_indicator text="Enregistrement..." %}
```

**Paramètres :**

| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| `text` | `str` | `"Chargement..."` | Texte affiché pendant la requête |

---

## Personnalisation CSS

Toutes les valeurs visuelles sont contrôlées par des variables CSS. Surchargez-les dans votre propre feuille de style :

```css
:root {
  --xlk-primary:      #3b6cf7;   /* Couleur principale (spinner, accents) */
  --xlk-bg:           #ffffff;   /* Fond de l'overlay intérieur */
  --xlk-muted:        #e2e6f0;   /* Fond des skeletons et du spinner */
  --xlk-text:         #374151;   /* Couleur du texte */
  --xlk-overlay-bg:   rgba(15, 20, 40, 0.55); /* Fond de l'overlay plein écran */
  --xlk-radius:       0.5rem;    /* Border-radius global */
  --xlk-speed:        0.7s;      /* Vitesse des animations */
}
```

---

## Tester dans un projet Django

1. Installez le package en mode éditable depuis la racine du repo :

```bash
pip install -e /chemin/vers/xeolux-loadingkit
```

2. Ajoutez `"xeolux_loadingkit"` dans `INSTALLED_APPS`.

3. Dans n'importe quel template :

```django
{% load xeolux_loadingkit %}
{% xeolux_loadingkit_css %}
{% xeolux_loader size="md" text="Chargement..." %}
```

4. Lancez `python manage.py collectstatic` si vous êtes en production.

---

## Lancer les tests

```bash
# Depuis la racine du repo
pip install django pytest pytest-django
python -m pytest tests/ -v
```

---

## Build & Publication PyPI

### Build local

```bash
pip install build twine
python -m build
```

Les fichiers `.tar.gz` et `.whl` seront générés dans `dist/`.

### Vérifier le package

```bash
twine check dist/*
```

### Publier sur TestPyPI (recommandé avant la vraie publication)

```bash
twine upload --repository testpypi dist/*
```

Tester l'installation depuis TestPyPI :

```bash
pip install --index-url https://test.pypi.org/simple/ xeolux-loadingkit
```

### Publier sur PyPI

```bash
twine upload dist/*
```

> Vous aurez besoin d'un compte PyPI et d'un token API.  
> Configurez `~/.pypirc` ou utilisez la variable d'environnement `TWINE_PASSWORD`.

---

## Structure du projet

```
xeolux-loadingkit/
├── xeolux_loadingkit/
│   ├── __init__.py
│   ├── apps.py
│   ├── templatetags/
│   │   ├── __init__.py
│   │   └── xeolux_loadingkit.py
│   ├── templates/
│   │   └── xeolux_loadingkit/
│   │       ├── loader.html
│   │       ├── overlay.html
│   │       ├── skeleton.html
│   │       └── htmx_indicator.html
│   └── static/
│       └── xeolux_loadingkit/
│           └── css/
│               └── loadingkit.css
├── tests/
│   └── test_template_tags.py
├── README.md
├── pyproject.toml
├── LICENSE
└── MANIFEST.in
```

---

## Compatibilité

| Django | Python |
|--------|--------|
| 4.2    | 3.10, 3.11, 3.12 |
| 5.0    | 3.10, 3.11, 3.12 |
| 5.1    | 3.10, 3.11, 3.12 |

---

## Licence

MIT © [Xeolux](https://github.com/xeolux)
