Metadata-Version: 2.4
Name: anyjsonviewer
Version: 0.2.0
Summary: An anywidget wrapper for @textea/json-viewer
Requires-Python: >=3.12
Requires-Dist: anywidget>=0.10.0
Requires-Dist: traitlets>=5.14.3
Description-Content-Type: text/markdown

# anyjsonviewer

An [anywidget](https://anywidget.dev) wrapper around
[`@textea/json-viewer`](https://github.com/TexteaInc/json-viewer), giving you an
interactive, collapsible JSON viewer inside Jupyter, JupyterLab, VS Code,
Marimo, or any other frontend that supports Jupyter widgets.

## Installation

```sh
pip install anyjsonviewer
```

Or with uv:

```sh
uv add anyjsonviewer
```

## Usage

```python
from anyjsonviewer import JsonViewer

JsonViewer(
    data={
        "name": "anyjsonviewer",
        "tags": ["json", "viewer", "anywidget"],
        "nested": {"count": 3, "ok": True},
    },
    theme="dark",
)
```

### Traits

All props are synced traits, so you can update them from Python and the view
re-renders live:

| Trait | Type | Default | Description |
| --- | --- | --- | --- |
| `data` | any JSON-serializable | `None` | The data to display. |
| `root_name` | `str \| None` | `"root"` | Label for the root node. `None` hides it. |
| `theme` | `str` | `"light"` | `"light"`, `"dark"`, or `"auto"`. |
| `class_name` | `str \| None` | `None` | Custom CSS class on the root element. |
| `style` | `dict \| None` | `None` | Inline CSS styles for the root element. |
| `indent_width` | `int` | `3` | Indentation width for nested objects. |
| `default_inspect_depth` | `int` | `5` | Depth to auto-expand on first render. Set to `0` to fully collapse. |
| `max_display_length` | `int` | `30` | Hide items in arrays/objects past this count. |
| `group_arrays_after_length` | `int` | `100` | Group arrays into bracketed chunks after this length. |
| `collapse_strings_after_length` | `int` | `50` | Truncate long strings; click to expand. |
| `object_sort_keys` | `bool` | `False` | Sort object keys alphabetically. |
| `quotes_on_keys` | `bool` | `True` | Wrap keys in quotes. |
| `display_data_types` | `bool` | `True` | Show type annotations next to values. |
| `display_size` | `bool` | `True` | Show length of arrays/objects. |
| `display_comma` | `bool` | `True` | Show trailing commas. |
| `highlight_updates` | `bool` | `True` | Briefly highlight values when they change. |
| `enable_clipboard` | `bool` | `False` | Show copy-to-clipboard buttons. |
| `enable_add` | `bool` | `False` | Show "add" buttons on objects/arrays. |
| `enable_delete` | `bool` | `False` | Show "delete" buttons on items. |
| `editable` | `bool` | `False` | Allow inline editing of values. |

When `editable`, `enable_add`, or `enable_delete` are on, edits round-trip
through the `data` trait — change something in the UI and the new value
becomes visible from Python.

```python
w = JsonViewer(data={"a": 1})
w.theme = "dark"         # live update
w.data = {"a": 1, "b": 2}
```

### Using with Marimo

Marimo's `mo.ui.anywidget()` wrapper exposes `.value` as a dict of every
synced trait, so to get just the JSON you'd write `wrapper.value["data"]`.
You can also keep a reference to the underlying widget and use it directly:

```python
viewer = JsonViewer(data=my_data)
ui = mo.ui.anywidget(viewer)
ui                  # render in a cell
viewer.data         # ← just the JSON, same as in Jupyter
ui.value["data"]    # ← Marimo wrapper-native equivalent
```

## Development

The widget's JavaScript lives in `js/index.jsx` and is bundled with
[`esbuild`](https://esbuild.github.io/) into `src/anyjsonviewer/static/widget.js`.

```sh
# Install Python deps
uv sync

# Install JS deps
npm install

# One-off build
npm run build

# Watch mode (pair with ANYWIDGET_HMR=1 in your notebook)
npm run dev
```

Building the wheel automatically runs the JS build via a custom Hatch hook:

```sh
uv build
```

To skip the JS build step (e.g. in CI where you've already built the bundle),
set `ANYJSONVIEWER_SKIP_JS_BUILD=1`.

## License

MIT
