Metadata-Version: 2.4
Name: django-sample-components
Version: 0.1.8
Summary: A handy collection of reusable Django UI components, allowing me to share and integrate elements efficiently across various projects.
License: MIT
License-File: LICENSE
Author: Gustavo Rizzo S M de Albuquerque
Author-email: grizzo.albu@gmail.com
Requires-Python: >=3.14,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: crispy-bootstrap5 (>=2024.10,<2025.0)
Requires-Dist: django (>=5.2.0,<7.0.0)
Requires-Dist: django-crispy-forms (>=2.3,<3.0.0)
Requires-Dist: django-htmx (>=1.27.0,<2.0.0)
Description-Content-Type: text/markdown

# django-sample-components

[![PyPI](https://img.shields.io/pypi/v/django-sample-components.svg)](https://pypi.org/project/django-sample-components/)

A reusable Django library that provides ready-to-use UI components — template tags, templates, and static assets — for use across Django projects.

Components are split into two groups:

- **Static** (`{% load sample_tags %}`) — pure server-side rendered components, no JavaScript dependencies beyond Bootstrap.
- **Async** (`{% load async_tags %}`) — interactive components powered by [HTMX](https://htmx.org/) that update without page reloads.


## Installation

```bash
pip install django-sample-components
# or
poetry add django-sample-components
```

Add to `INSTALLED_APPS` in `settings.py`:

```python
INSTALLED_APPS = [
    # ...
    'django_sample_components',
    'django_htmx',   # required for async components
]
```

Add `HtmxMiddleware` to `MIDDLEWARE` (required for async components):

```python
MIDDLEWARE = [
    # ...
    'django_htmx.middleware.HtmxMiddleware',
]
```

Include the library URLs in your project's `urls.py`:

```python
from django.urls import include, path

urlpatterns = [
    path('components/', include('django_sample_components.urls')),
]
```

Collect static files:

```bash
python manage.py collectstatic
```


## Static Components

Load with `{% load sample_tags %}` in any template. No HTMX or JavaScript required (except Bootstrap JS for `simple_popup`).

| Tag | Type | Quick usage |
|-----|------|-------------|
| [`greeting`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/static/greeting.md) | simple_tag | `{% greeting "Alice" %}` |
| [`show_today_timestamp`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/static/show_today_timestamp.md) | simple_tag | `{% show_today_timestamp %}` |
| [`simple_typewriter`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/static/simple_typewriter.md) | simple_tag | `{% simple_typewriter words %}` |
| [`simple_button`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/static/simple_button.md) | simple_tag | `{% simple_button "Label" href="/url" btn_type="primary" %}` |
| [`simple_toast`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/static/simple_toast.md) | simple_tag | `{% simple_toast position="bottom-end" autohide=True delay=6000 %}` |
| [`shout`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/static/shout.md) | block_tag | `{% shout %}...{% endshout %}` |
| [`simple_alert`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/static/simple_alert.md) | block_tag | `{% simple_alert type="success" %}...{% endsimple_alert %}` |
| [`simple_popup`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/static/simple_popup.md) | block_tag | `{% simple_popup name_button="Open" title="Title" %}...{% endsimple_popup %}` |

### Quick example

```django
{% load sample_tags %}

{% simple_alert type="success" %}
    Your changes have been saved.
{% endsimple_alert %}

{% simple_popup name_button="Open" title="Confirm" size="sm" %}
    <p>Are you sure?</p>
{% endsimple_popup %}

{% simple_button "Download" href="/files/report.pdf" icon_before="fa fa-download" %}

{# Toast container for Django messages + JS API (window.showToast) #}
{% simple_toast position="bottom-end" autohide=True delay=5000 %}
```


## Async Components (HTMX)

Load with `{% load async_tags %}`. These components require HTMX and `django-htmx`. The easiest way to set them up is to extend `master_async.html`, which includes HTMX and handles CSRF automatically.

| Tag | Quick usage | Doc |
|-----|-------------|-----|
| [`async_counter`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_counter.md) | `{% async_counter initial_value=0 step=1 %}` | [docs](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_counter.md) |
| [`async_lazy_load`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_lazy_load.md) | `{% async_lazy_load url="/async/lazy-load/" delay_ms=1200 %}` | [docs](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_lazy_load.md) |
| [`async_active_search`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_active_search.md) | `{% async_active_search search_url="/search/" %}` | [docs](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_active_search.md) |
| [`async_lazy_popup`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_lazy_popup.md) | `{% async_lazy_popup name_button="Open" content_url="/content/" %}` | [docs](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_lazy_popup.md) |
| [`async_sum_form`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_sum_form.md) | `{% async_sum_form %}` | [docs](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_sum_form.md) |
| [`async_registration_form`](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_registration_form.md) | `{% async_registration_form %}` | [docs](https://github.com/GustavoRizzo/django-sample-components/blob/main/docs/async/async_registration_form.md) |

### Quick example

```django
{% load async_tags %}

{# Counter with step 5, bounded 0–100 #}
{% async_counter initial_value=0 step=5 min_value=0 max_value=100 %}

{# Live search against your own endpoint #}
{% async_active_search search_url="/contacts/search/" placeholder="Search contacts..." %}

{# Modal that loads content only when opened #}
{% async_lazy_popup name_button="View Report" title="Monthly Report"
                    content_url="/reports/monthly/" size="lg" %}

{# Lazy load any endpoint on reveal #}
{% async_lazy_load url="/async/counter/component/?initial_value=10&step=2" delay_ms=2000 %}

{# Async forms #}
{% async_sum_form %}
{% async_registration_form %}
```

### HTMX setup in your own base template

If you are not extending `master_async.html`, add the following to your base template:

```django
{% load django_htmx %}

<head>
    {% htmx_script %}
    {% django_htmx_script %}
</head>
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
    ...
</body>
```


## Static vs Async — key differences

| | Static (`sample_tags`) | Async (`async_tags`) |
|---|---|---|
| Rendered | Server-side, with the page | On demand via HTMX |
| JavaScript | None (Bootstrap JS for popups) | HTMX required |
| Page reload | N/A | Never |
| Dependencies | Bootstrap CSS/JS | Bootstrap CSS/JS + HTMX + django-htmx |
| Best for | Simple UI elements | Interactive, live, or heavy-content components |


## Running locally

```bash
git clone https://github.com/GustavoRizzo/django-sample-components.git
cd django-sample-components
poetry install
poetry run task run-demo
```

Open `http://127.0.0.1:8000` to browse the component showcase.

### Tests

```bash
poetry run task test
```


## Publishing

```bash
poetry version patch   # bump version (e.g. 0.1.0 → 0.1.1)
poetry build
poetry publish
```

Update the version in both `pyproject.toml` and `django_sample_components/__init__.py` before releasing.

