diff --git a/docs/check-autoreacton.ipynb b/docs/check-autoreacton.ipynb
new file mode 100644
index 00000000..df41b088
--- /dev/null
+++ b/docs/check-autoreacton.ipynb
@@ -0,0 +1,143 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "10166727-57df-4c2b-9c1d-dc2ba12a3a13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from ipyautoui import autoreacton as ar"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "52b8e1aa-f2b7-4e54-9ac8-0e6ec98b27c4",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "869397c387ae4f8f9e7d6cea008c68e1",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/html": [
+ "Cannot show widget. You probably want to rerun the code cell above (Click in the code cell, and press Shift+Enter ⇧+↩)."
+ ],
+ "text/plain": [
+ "Cannot show ipywidgets in text"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "ar.AutoBox()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "722396e3-1c5e-4366-b8ef-a7221e9b1de4",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "RuntimeError",
+ "evalue": "Could not create widget with {'data': a b\n0 1 3\n1 2 4}",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
+ "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:388\u001b[0m, in \u001b[0;36mElement._create_widget\u001b[0;34m(self, kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 388\u001b[0m widget \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcomponent\u001b[38;5;241m.\u001b[39mwidget(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 389\u001b[0m hold_trait_notifications \u001b[38;5;241m=\u001b[39m widget\u001b[38;5;241m.\u001b[39mhold_trait_notifications\n",
+ "\u001b[0;31mTypeError\u001b[0m: EditGrid.__init__() missing 1 required positional argument: 'schema'",
+ "\nThe above exception was the direct cause of the following exception:\n",
+ "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)",
+ "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/IPython/core/formatters.py:922\u001b[0m, in \u001b[0;36mIPythonDisplayFormatter.__call__\u001b[0;34m(self, obj)\u001b[0m\n\u001b[1;32m 920\u001b[0m method \u001b[38;5;241m=\u001b[39m get_real_method(obj, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprint_method)\n\u001b[1;32m 921\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m method \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 922\u001b[0m method()\n\u001b[1;32m 923\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m\n",
+ "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:332\u001b[0m, in \u001b[0;36mElement._ipython_display_\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 331\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_ipython_display_\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m--> 332\u001b[0m display(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmime_bundle)\n",
+ "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:2211\u001b[0m, in \u001b[0;36mdisplay\u001b[0;34m(el, mime_bundle)\u001b[0m\n\u001b[1;32m 2209\u001b[0m box \u001b[38;5;241m=\u001b[39m widgets\u001b[38;5;241m.\u001b[39mVBox(_view_count\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0\u001b[39m)\n\u001b[1;32m 2210\u001b[0m el \u001b[38;5;241m=\u001b[39m _wrap(el, jupyter_decorator_components)\n\u001b[0;32m-> 2211\u001b[0m widget, rc \u001b[38;5;241m=\u001b[39m render(el, container\u001b[38;5;241m=\u001b[39mbox)\n\u001b[1;32m 2212\u001b[0m displayed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 2214\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcheck_view_count\u001b[39m(change):\n",
+ "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:2171\u001b[0m, in \u001b[0;36mrender\u001b[0;34m(element, container, children_trait, handle_error, initial_state)\u001b[0m\n\u001b[1;32m 2169\u001b[0m container \u001b[38;5;241m=\u001b[39m container \u001b[38;5;129;01mor\u001b[39;00m widgets\u001b[38;5;241m.\u001b[39mVBox()\n\u001b[1;32m 2170\u001b[0m _rc \u001b[38;5;241m=\u001b[39m _RenderContext(element, container, children_trait\u001b[38;5;241m=\u001b[39mchildren_trait, handle_error\u001b[38;5;241m=\u001b[39mhandle_error, initial_state\u001b[38;5;241m=\u001b[39minitial_state)\n\u001b[0;32m-> 2171\u001b[0m _rc\u001b[38;5;241m.\u001b[39mrender(element, _rc\u001b[38;5;241m.\u001b[39mcontainer)\n\u001b[1;32m 2172\u001b[0m local\u001b[38;5;241m.\u001b[39mlast_rc \u001b[38;5;241m=\u001b[39m weakref\u001b[38;5;241m.\u001b[39mref(_rc)\n\u001b[1;32m 2173\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m container, _rc\n",
+ "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:1469\u001b[0m, in \u001b[0;36m_RenderContext.render\u001b[0;34m(***failed resolving arguments***)\u001b[0m\n\u001b[1;32m 1467\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreconsolidating \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 1468\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1469\u001b[0m widget \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reconsolidate(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39melement, default_key\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/\u001b[39m\u001b[38;5;124m\"\u001b[39m, parent_key\u001b[38;5;241m=\u001b[39mROOT_KEY)\n\u001b[1;32m 1470\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 1471\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreconsolidating \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n",
+ "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:1939\u001b[0m, in \u001b[0;36m_RenderContext._reconsolidate\u001b[0;34m(self, el, default_key, parent_key)\u001b[0m\n\u001b[1;32m 1937\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1938\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCreating new widget: \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m\"\u001b[39m, el, key)\n\u001b[0;32m-> 1939\u001b[0m widget, orphan_ids \u001b[38;5;241m=\u001b[39m el\u001b[38;5;241m.\u001b[39m_create_widget(kwargs)\n\u001b[1;32m 1941\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m el\u001b[38;5;241m.\u001b[39mis_shared:\n\u001b[1;32m 1942\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_shared_widgets[el] \u001b[38;5;241m=\u001b[39m widget\n",
+ "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:401\u001b[0m, in \u001b[0;36mElement._create_widget\u001b[0;34m(self, kwargs)\u001b[0m\n\u001b[1;32m 399\u001b[0m widget\u001b[38;5;241m.\u001b[39m_react_meta \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mdict\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_meta)\n\u001b[1;32m 400\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m--> 401\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCould not create widget \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcomponent\u001b[38;5;241m.\u001b[39mwidget\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m with \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkwargs\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01me\u001b[39;00m\n\u001b[1;32m 402\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m name, callback \u001b[38;5;129;01min\u001b[39;00m listeners\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m 403\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m callback \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
+ "\u001b[0;31mRuntimeError\u001b[0m: Could not create widget with {'data': a b\n0 1 3\n1 2 4}"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "ipyautoui.custom.editgrid.EditGrid(data = a b\n",
+ "0 1 3\n",
+ "1 2 4)"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import pandas as pd\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "41aef1de-7061-44ef-aa7c-642c64b1b3f2",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "1ab26b73259148c69224b8f69c64c2a6",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/html": [
+ "Cannot show widget. You probably want to rerun the code cell above (Click in the code cell, and press Shift+Enter ⇧+↩)."
+ ],
+ "text/plain": [
+ "Cannot show ipywidgets in text"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "ar.SaveButtonBar()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2a9cca53-19ab-4b35-af8f-ff5b89d0920b",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/environment.yml b/environment.yml
index 1c3b66d6..dc43bc89 100644
--- a/environment.yml
+++ b/environment.yml
@@ -21,6 +21,7 @@ dependencies:
- altair # optional
- halo # optional
- plotly # optional
+ - reacton
- pip
- pip:
- maplocal==0.2.1
diff --git a/src/ipyautoui/autoreacton.py b/src/ipyautoui/autoreacton.py
new file mode 100644
index 00000000..b223beab
--- /dev/null
+++ b/src/ipyautoui/autoreacton.py
@@ -0,0 +1,173 @@
+import datetime
+import typing
+from typing import Any, Dict, Union
+
+import ipywidgets
+import numpy as np
+from numpy import ndarray
+
+import reacton
+from reacton.core import ContainerAdder, Element, _get_render_context
+
+from reacton import ipywidgets as w
+from reacton.ipywidgets import Layout
+from reacton.utils import implements
+
+import ipyautoui
+from ipyautoui import autoui
+from ipywidgets import *
+
+from collections.abc import Sequence
+
+# to execute run:
+# `python -m ipyautoui.autoreacton`
+
+if __name__ == "__main__":
+ from reacton import generate
+
+ class CodeGen(generate.CodeGen):
+ def get_extra_argument(self, cls):
+ return {ipywidgets.Button: [("on_click", None, typing.Callable[[], Any])]}.get(cls, [])
+
+ current_module = __import__(__name__)
+
+ CodeGen([autoui]).generate(__file__)
+
+# generated code:
+
+
+def _AutoBox(
+ align_horizontal: bool = True,
+ box_style: str = "",
+ children: Sequence[Element[ipywidgets.Widget]] = (),
+ description: str = None,
+ hide: bool = True,
+ indent: bool = False,
+ layout: Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]] = {},
+ nested: bool = False,
+ show_description: bool = True,
+ show_title: bool = True,
+ tabbable: bool = None,
+ title: str = None,
+ tooltip: str = None,
+ widget: Any = ToggleButton(value=False, layout=Layout(width="600px"), tooltip="placeholder..."),
+ on_align_horizontal: typing.Callable[[bool], Any] = None,
+ on_box_style: typing.Callable[[str], Any] = None,
+ on_children: typing.Callable[[Sequence[Element[ipywidgets.Widget]]], Any] = None,
+ on_description: typing.Callable[[str], Any] = None,
+ on_hide: typing.Callable[[bool], Any] = None,
+ on_indent: typing.Callable[[bool], Any] = None,
+ on_layout: typing.Callable[[Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]]], Any] = None,
+ on_nested: typing.Callable[[bool], Any] = None,
+ on_show_description: typing.Callable[[bool], Any] = None,
+ on_show_title: typing.Callable[[bool], Any] = None,
+ on_tabbable: typing.Callable[[bool], Any] = None,
+ on_title: typing.Callable[[str], Any] = None,
+ on_tooltip: typing.Callable[[str], Any] = None,
+ on_widget: typing.Callable[[Any], Any] = None,
+) -> Element[ipyautoui.autobox.AutoBox]:
+ """
+ :param box_style: Use a predefined styling for the box.
+ :param children: List of widget children
+ :param tabbable: Is widget tabbable?
+ :param tooltip: A tooltip caption.
+ """
+ ...
+
+
+@implements(_AutoBox)
+def AutoBox(**kwargs):
+ if isinstance(kwargs.get("layout"), dict):
+ kwargs["layout"] = w.Layout(**kwargs["layout"])
+ widget_cls = ipyautoui.autobox.AutoBox
+ comp = reacton.core.ComponentWidget(widget=widget_cls)
+ return Element(comp, kwargs=kwargs)
+
+
+del _AutoBox
+
+
+def _EditGrid(
+ box_style: str = "",
+ children: Sequence[Element[ipywidgets.Widget]] = (),
+ close_crud_dialogue_on_action: bool = False,
+ description: str = None,
+ layout: Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]] = {},
+ show_copy_dialogue: bool = False,
+ show_description: bool = True,
+ show_title: bool = True,
+ tabbable: bool = None,
+ title: str = None,
+ tooltip: str = None,
+ warn_on_delete: bool = False,
+ on_box_style: typing.Callable[[str], Any] = None,
+ on_children: typing.Callable[[Sequence[Element[ipywidgets.Widget]]], Any] = None,
+ on_close_crud_dialogue_on_action: typing.Callable[[bool], Any] = None,
+ on_description: typing.Callable[[str], Any] = None,
+ on_layout: typing.Callable[[Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]]], Any] = None,
+ on_show_copy_dialogue: typing.Callable[[bool], Any] = None,
+ on_show_description: typing.Callable[[bool], Any] = None,
+ on_show_title: typing.Callable[[bool], Any] = None,
+ on_tabbable: typing.Callable[[bool], Any] = None,
+ on_title: typing.Callable[[str], Any] = None,
+ on_tooltip: typing.Callable[[str], Any] = None,
+ on_warn_on_delete: typing.Callable[[bool], Any] = None,
+) -> Element[ipyautoui.custom.editgrid.EditGrid]:
+ """
+ :param box_style: Use a predefined styling for the box.
+ :param children: List of widget children
+ :param tabbable: Is widget tabbable?
+ :param tooltip: A tooltip caption.
+ """
+ ...
+
+
+@implements(_EditGrid)
+def EditGrid(**kwargs):
+ if isinstance(kwargs.get("layout"), dict):
+ kwargs["layout"] = w.Layout(**kwargs["layout"])
+ widget_cls = ipyautoui.custom.editgrid.EditGrid
+ comp = reacton.core.ComponentWidget(widget=widget_cls)
+ return Element(comp, kwargs=kwargs)
+
+
+del _EditGrid
+
+
+def _SaveButtonBar(
+ box_style: str = "",
+ children: Sequence[Element[ipywidgets.Widget]] = (),
+ fns_onrevert: list = [],
+ fns_onsave: list = [],
+ layout: Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]] = {},
+ tabbable: bool = None,
+ tooltip: str = None,
+ unsaved_changes: bool = False,
+ on_box_style: typing.Callable[[str], Any] = None,
+ on_children: typing.Callable[[Sequence[Element[ipywidgets.Widget]]], Any] = None,
+ on_fns_onrevert: typing.Callable[[list], Any] = None,
+ on_fns_onsave: typing.Callable[[list], Any] = None,
+ on_layout: typing.Callable[[Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]]], Any] = None,
+ on_tabbable: typing.Callable[[bool], Any] = None,
+ on_tooltip: typing.Callable[[str], Any] = None,
+ on_unsaved_changes: typing.Callable[[bool], Any] = None,
+) -> Element[ipyautoui.custom.buttonbars.SaveButtonBar]:
+ """
+ :param box_style: Use a predefined styling for the box.
+ :param children: List of widget children
+ :param tabbable: Is widget tabbable?
+ :param tooltip: A tooltip caption.
+ """
+ ...
+
+
+@implements(_SaveButtonBar)
+def SaveButtonBar(**kwargs):
+ if isinstance(kwargs.get("layout"), dict):
+ kwargs["layout"] = w.Layout(**kwargs["layout"])
+ widget_cls = ipyautoui.custom.buttonbars.SaveButtonBar
+ comp = reacton.core.ComponentWidget(widget=widget_cls)
+ return Element(comp, kwargs=kwargs)
+
+
+del _SaveButtonBar