**English** | [Korean](README.ko.md) | [Japanese](README.ja.md)

# mendraw

`mendraw` is the JavaScript-target package for using Mendix client values and
already-installed `.mpk` widget assets from Gleam.

Its responsibility is intentionally narrow:

- typed wrappers for the Mendix Pluggable Widget client API;
- Redraw interop for pluggable and classic widget components;
- deterministic binding generation from `build/widgets/*` assets;
- synthetic Mendix-compatible values for non-Mendix web applications.

`mendraw` **does not** search the Marketplace, authenticate a user, launch a
browser, download packages, manage a global cache, or write a lockfile. Those
package-manager responsibilities belong to
[`mxpak`](https://github.com/glendix-labs/mxpak).

## Install

```sh
gleam add mendraw@2
```

The package targets JavaScript. Applications rendering Mendix widgets also need
the JavaScript peer packages required by those widgets, normally React and
React DOM.

## Use an installed MPK package

### 1. Install package assets with mxpak

Configure package acquisition under mxpak's namespace:

```toml
[tools.mxpak]
mode = "extract"

[tools.mxpak.widgets.Charts]
version = "3.0.0"
# id = 12345
# s3_id = "com/..." # optional direct-download identifier
```

Run the standalone `mxp` CLI from the project root:

```sh
mxp install
```

For a local Git/path dependency on mxpak, the equivalent Gleam entrypoint is:

```sh
gleam run -t erlang -m mxpak/install
```

Either command owns package resolution and writes extracted assets below
`build/widgets/`.

### 2. Generate Mendraw bindings

```sh
gleam run -m mendraw/install
```

Mendraw reads the installed assets, generates `src/widgets/*.gleam`, and writes
the JavaScript component registry into Mendraw's build output. Running the
command again regenerates the same binding modules, so stale generated source
is not silently retained.

### 3. Render the component

```gleam
import gleam/result
import mendraw/interop
import mendraw/mendix
import mendraw/mendix/editable_value
import mendraw/widget
import redraw

pub fn view(
  props props: mendix.JsProps,
) -> Result(redraw.Element, widget.WidgetError) {
  let value = mendix.get_prop_required(props, "textAttr")
  let current_text = editable_value.display_value(value)
  use component <- result.try(widget.component("Switch"))
  Ok(interop.component_el(component, [
    widget.prop("caption", "Title"),
    widget.editable_prop(
      "textAttr",
      current_text,
      editable_value.display_value(value),
      fn(updated_text) {
        editable_value.set_text_value(value, updated_text)
      },
    ),
    widget.action_prop("onClick", fn() {
      editable_value.set_text_value(value, "Updated")
    }),
  ], []))
}
```

## Classic widgets

Classic/Dojo assets installed by mxpak are wrapped in a React component by the
Mendraw generator:

```gleam
import mendraw/classic

classic.render("CameraWidget.widget.CameraWidget", [
  #("mfToExecute", classic.to_value(microflow)),
  #("preferRearCamera", classic.to_value(True)),
])
```

Both `render` and `render_with_class` return a descriptive `Result` when a
binding is missing.

## Mendix client values

The `mendraw/mendix/*` modules wrap runtime-owned JavaScript handles instead of
recreating Mendix business behavior:

```gleam
import gleam/option
import mendraw/mendix
import mendraw/mendix/action
import mendraw/mendix/editable_value
import mendraw/mendix/list_value

let status = list_value.status(data_source)
let display = editable_value.display_value(attribute)
editable_value.set_text_value(attribute, "Updated")
action.execute_action(on_click)

case mendix.get_prop(props, "optionalValue") {
  option.Some(value) -> value
  option.None -> fallback_value
}
```

Important modules include:

| Module | Responsibility |
| --- | --- |
| `mendraw/mendix` | Core handles, status values, property access, option conversion |
| `mendraw/mendix/editable_value` | Editable values and validation |
| `mendraw/mendix/list_value` | Data-source paging, filtering, sorting, and reload |
| `mendraw/mendix/list_attribute` | Per-item attribute/action/expression access |
| `mendraw/mendix/filter` | Typed filter expression construction |
| `mendraw/mendix/date` | JavaScript date boundary |
| `mendraw/mendix/decimal` | Big.js boundary conversion |
| `mendraw/widget` | Generated pluggable component lookup and property adapters |
| `mendraw/classic` | Generated classic component lookup |
| `mendraw/interop` | Typed JavaScript component to Redraw element conversion |
| `mendraw/synthetic` | Mendix-compatible values for external data |

## Synthetic data

`mendraw/synthetic` can construct `ListValue`, `ObjectItem`, and
`ListAttributeValue` compatible objects for rendering an installed Mendix
widget outside the Mendix Runtime. It does not fetch remote data or install the
widget package; applications provide the data and mxpak provides the assets.

## Relationship to the other repositories

```text
mxpak       installs and caches package assets
  ↓ build/widgets/*
mendraw     generates typed bindings and models Mendix client values
  ↓ public Gleam APIs
glendix     builds Mendix widgets and provides the Lustre/React bridge
```

Each package can be used independently. A project that only needs Mendix client
types or synthetic values depends on Mendraw alone. A project that only needs
package acquisition uses mxpak alone.

## Development

```sh
gleam deps download
gleam format --check
gleam check
gleam build --warnings-as-errors
gleam docs build
gleam test --runtime bun
```

## License

[MIT License](LICENCE)
