Metadata-Version: 2.4
Name: fastblocks-htmy
Version: 0.5.0
Summary: Type-safe htmy components and a FastBlocks adapter over the fastblocks-ui design system
Author-email: FastBlocks UI Team <team@fastblocks-ui.dev>
License-Expression: BSD-3-Clause
Project-URL: Repository, https://github.com/lesleslie/fastblocks-htmy
Keywords: htmy,components,fastblocks,html,design-system,type-safe
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Requires-Python: >=3.13
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastblocks-ui<0.9,>=0.8
Requires-Dist: htmy<0.14,>=0.13
Provides-Extra: dev
Requires-Dist: crackerjack>=0.50.1; extra == "dev"
Requires-Dist: ruff>=0.8.0; extra == "dev"
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
Requires-Dist: pyright>=1.1.300; extra == "dev"
Requires-Dist: jinja2>=3.1; extra == "dev"
Dynamic: license-file

# FastBlocks htmy

Type-safe [htmy](https://pypi.org/project/htmy/) components and a FastBlocks adapter
built on top of the [`fastblocks-ui`](https://github.com/lesleslie/fastblocks-ui)
design system.

`fastblocks-htmy` is the **FastBlocks-native** layer: where `fastblocks-ui` ships the
CSS and zero-dependency string helpers, this package wraps them in typed, composable
htmy components and provides the adapter that registers assets and template globals
with a FastBlocks app (ACB `[[ ]]` delimiters).

> **Design principle:** this is a *thin* wrapper. It never reimplements styling —
> every component renders the corresponding `fastblocks-ui` helper output wrapped in
> htmy's `SafeStr`. A parity test enforces that the two layers can't diverge.

## Status

All 27 `fastblocks-ui` manifest components (including `validation_summary`) now have
a typed htmy wrapper, plus the FastBlocks adapter (`asset_paths`, `asset_urls`,
`template_globals`, `trusted_components`). `Button`, `Container`, `Table`, and `Field`
were hand-written first (Phase 1); the rest were added by WS-16's manifest-driven
codegen (`scripts/generate_components.py`) — see `fastblocks_htmy/ui/_generated.py`
and `fastblocks_htmy/layout/_generated.py`, and each carve-out module's docstring
(`Columns`, `Select`, `Tabs`, `Dropdown`, `Navbar`, `Breadcrumb`, `NavList`,
`NavGroups`, `ValidationSummary`) for
which components are hand-written instead and why.

## Install

```bash
pip install fastblocks-htmy   # pulls fastblocks-ui (>=0.8,<0.9) and htmy
```

## Usage

```python
import asyncio
from htmy import Renderer
from fastblocks_htmy import Button

html = asyncio.run(Renderer().render(Button("Save", variant="primary")))
# -> '<button class="ui-button is-primary" type="button">Save</button>'
```

### FastBlocks integration

**Status note (unverified against a live FastBlocks app as of this writing — see the
integration test in `tests/test_fastblocks_integration.py` for what's actually
confirmed).** Two integration paths exist with different maturity:

1. **String helpers as plain Jinja globals — the path most likely to already work.**
   `ui_button`/`ui_card`/`ui_field`/`ui_alert` (and the rest of
   `fastblocks_ui`'s exports) are ordinary functions returning strings. Registered
   via `templates.env.globals.update(template_globals())` on FastBlocks' plain
   Jinja2 adapter, calling them from a template is no different from calling any
   other Jinja global function:

   ```python
   from fastblocks_htmy.fastblocks import asset_paths, asset_urls, template_globals

   # Mount the shipped fastblocks-ui assets (resolved from the installed wheel):
   app.mount("/static/fastblocks-ui", StaticFiles(directory=asset_paths()["root"]))

   # Register components + helpers as template globals (cache-busted asset URLs included):
   templates.env.globals.update(template_globals())
   ```

   ```html
   <link rel="stylesheet" href="[[ fastblocks_ui_css ]]">
   [[ ui_button(text="Save", variant="primary") ]]
   ```

1. **Typed htmy components used directly as `[[ Button(...) ]]` template
   expressions — do not rely on this yet.** Two independent issues mean this is
   *not* known to work as a bare template expression today:

   - FastBlocks' real htmy component-loading path discovers components from
     `.py` **source files** under a `templates/<app>/components/` search path,
     validated by a sandboxed AST loader that only allows `dataclasses`/`typing`
     as top-level imports. Every component in `fastblocks_htmy/ui/` and
     `fastblocks_htmy/layout/` imports `fastblocks_ui`, `htmy`, and `..base` —
     all of which that loader would reject if these files were dropped into a
     discovered-components directory as-is.
   - Independently of the above, a bare instantiated component handed to a
     template engine's normal output mechanism only renders correctly if
     something actually calls `.htmy(context)` on it (which is what FastBlocks'
     `render_component()` template global does). `FastBlocksComponent` now
     provides a best-effort `__str__`/`__html__` fallback so accidental bare
     stringification doesn't print a dataclass repr, but this has not been
     proven against FastBlocks' real `render_component()`-mediated rendering
     path with a passing integration test yet.

   Until that's resolved (tracked in `fastblocks-ui`'s roadmap under the
   cross-repo remediation plan), prefer path 1 above for anything rendered
   through an actual FastBlocks template. The typed components remain fully
   usable via direct `Renderer().render(...)` calls, as this package's own tests do.

## Relationship to fastblocks-ui

| Package | Role | Dependencies |
| --- | --- | --- |
| `fastblocks-ui` | CSS + tokens + manifest + string helpers | none (zero runtime deps) |
| `fastblocks-htmy` | typed htmy components + FastBlocks adapter | `fastblocks-ui`, `htmy` |

See the architecture decision record in
[`fastblocks-ui/docs/roadmap.md`](https://github.com/lesleslie/fastblocks-ui/blob/main/docs/roadmap.md).

## License

BSD-3-Clause
