Metadata-Version: 2.4
Name: docxkit
Version: 0.1.0
Summary: Composable, styled report components on top of python-docx
Project-URL: Homepage, https://github.com/blockhaven-ai/docxkit
Author: docxkit contributors
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: document-generation,docx,python-docx,report,word
Classifier: Development Status :: 4 - Beta
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: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Office Suites
Classifier: Topic :: Text Processing :: Markup
Requires-Python: >=3.10
Requires-Dist: python-docx>=1.1.0
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == 'test'
Description-Content-Type: text/markdown

# docxkit

Composable, styled report components on top of [python-docx](https://python-docx.readthedocs.io/).

python-docx exposes a low-level API: runs, paragraphs, and raw OOXML for
anything visual (cell shading, table borders, letter spacing). docxkit wraps
that in reusable, themed building blocks for generated documents: KPI bands,
gradient-shaded heatmap tables, styled data tables, embedded figures,
typography presets, and score cards.

- Single dependency: `python-docx`.
- No plotting dependency. `image_figure` embeds pre-rendered image files
  (PNG, JPEG, ...) produced by any tool (matplotlib, plotly, etc.).
- Everything returns the underlying python-docx object, and the raw document
  is always reachable via `doc.docx`, so you can drop down to the low-level
  API at any point.

## Install

```bash
pip install docxkit
```

Requires Python 3.10+.

## Quick start

```python
from docxkit import Document, Theme

doc = Document(theme=Theme(primary="4472C4", font="Calibri"))
doc.title("Q2 Test Report", subtitle="2026-06-11")
doc.kpi_band([("Runs", "42"), ("Pass rate", "93%"), ("P50 latency", "1.2s")])
doc.section("Results by category")
doc.heatmap_table(
    headers=["Suite", "Correctness", "Robustness"],
    rows=[["parser", 9.1, 8.4], ["cli", 5.2, 4.1]],
    value_range=(0, 10),
    colormap="red_green",
)
doc.save("report.docx")
```

## Component catalog

### Title and typography

```python
doc.title("Report Title", subtitle="muted subtitle line")
doc.section("Section heading")            # Heading 1, theme color
doc.section("Subsection", level=2)
doc.eyebrow("category label")             # small, bold, upper-cased accent line
doc.paragraph("Body text", bold=False, italic=True, size=9.5,
              color="5A6472", align="left")
doc.bullet("List item")
doc.code_block("step 1  12ms\nstep 2  30ms")   # indented monospace block
doc.horizontal_rule()
doc.page_break()
```

### KPI band

A borderless single-row strip of metric cards. Each item is
`(label, value)` or `(label, value, caption)`.

```python
doc.kpi_band([
    ("Runs", "42", "last 30 days"),
    ("Pass rate", "93%", "+4 pts vs prior"),
    ("P50 latency", "1.2s"),
])
```

Cards split the usable page width evenly. The label renders upper-cased in
`theme.primary`, the value large and bold, the caption small and muted.
Override the card background with `fill="EEF2FA"`.

### Data table

Bordered table with a themed header row and optional zebra striping.

```python
doc.data_table(
    headers=["Case", "Suite", "Duration", "Status"],
    rows=[
        ["case-0041", "renderer", "4.21s", "pass"],
        ["case-0107", "parser", "3.90s", "pass"],
    ],
    zebra=True,
    mono_columns=(0,),                    # render column 0 in the mono font
    align=[None, None, "right", "center"],
    column_widths_in=[1.2, 1.5, 1.0, 1.0],  # optional fixed widths
)
```

### Heatmap table

Numeric cells are filled with a gradient color for their value and get
auto-contrast text (white on dark fills, dark on light fills). String cells
(row labels) render plain; `None` cells render as a neutral placeholder.

```python
doc.heatmap_table(
    headers=["Suite", "Correctness", "Robustness", "Docs"],
    rows=[
        ["parser", 9.1, 8.4, 6.0],
        ["cli", 5.2, 4.1, None],
    ],
    value_range=(0, 10),        # omit to infer from the data
    colormap="red_green",       # name or custom hex stops
    number_format="{:.1f}",
)
```

Built-in colormaps: `red_green`, `green_red`, `blue`, `heat`, `grey`.
A custom colormap is any sequence of two or more hex stops, low to high:
`colormap=("EAF1FB", "4472C4", "1F2A44")`.

### Score card

A titled metric table with gradient-shaded values and an optional
pass/fail column (`value >= threshold` passes).

```python
doc.score_card(
    "Release readiness — build 2026.06",
    {"Correctness": 8.6, "Robustness": 7.1, "Performance": 6.4},
    value_range=(0, 10),
    threshold=7.0,
)
```

### Image figure

Embeds a pre-rendered image with an optional caption. docxkit does not
render charts itself; pass a file produced by any plotting tool.

```python
doc.image_figure("chart.png", caption="Daily volume", width_in=6.0)
```

Accepts a path or a binary file-like object. Height scales to preserve the
aspect ratio.

## Theming reference

`Theme` is a frozen dataclass shared by every component. All colors are hex
strings (`"RRGGBB"`, `"#RRGGBB"`, or 3-digit shorthand), normalized on
construction.

| Field         | Default   | Used for                                   |
| ------------- | --------- | ------------------------------------------ |
| `primary`     | `4472C4`  | Eyebrows, KPI labels, accents              |
| `dark`        | `1F2A44`  | Title and heading text                     |
| `muted`       | `5A6472`  | Subtitles, captions, secondary text        |
| `good`        | `2E8540`  | PASS marks                                 |
| `bad`         | `C0392B`  | FAIL marks                                 |
| `font`        | `Calibri` | Body and heading font                      |
| `mono_font`   | `Consolas`| Code blocks, `mono_columns`                |
| `body_size`   | `10.5`    | Base body size (pt)                        |
| `border`      | `D5DAE2`  | Table borders, horizontal rules            |
| `header_fill` | = `dark`  | Table header row fill                      |
| `header_text` | `FFFFFF`  | Table header row text                      |
| `zebra_fill`  | `F2F5FA`  | Alternate row fill in zebra tables         |
| `card_fill`   | `F5F8FD`  | KPI card background                        |

```python
theme = Theme(primary="0E7C5A", font="Georgia", mono_font="Menlo")
doc = Document(theme=theme, margins_in=(0.7, 0.7, 0.7, 0.7))
```

Color helpers used by the components are public:

```python
from docxkit import gradient_color, lerp_color, contrast_text, COLORMAPS

gradient_color(7.5, 0, 10, "red_green")   # -> "8CB938" (interpolated hex)
contrast_text("1F2A44")                   # -> "FFFFFF"
```

## Full example

`examples/build_sample_report.py` builds a complete document exercising
every component with demo data:

```bash
python examples/build_sample_report.py
# wrote .../examples/sample_report.docx
```

## Development

```bash
pip install -e ".[test]"
pytest
```

Tests render each component, re-open the result with python-docx, and
assert the document structure (table dimensions, shading XML, text content,
embedded images).

## License

Apache-2.0. See [LICENSE](LICENSE).
