Skip to content

Commit

Permalink
add demo
Browse files Browse the repository at this point in the history
  • Loading branch information
maartenbreddels committed Feb 19, 2024
1 parent f911fd2 commit 57f075f
Show file tree
Hide file tree
Showing 4 changed files with 352 additions and 3 deletions.
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,38 @@
Build on top of ipyreact
ipywidget wrapper for [Ant Design components](https://ant.design/) using [ipyreact](https://github.com/widgetti/ipyreact/).

# Demo

https://github.com/widgetti/ipyantd/assets/1765949/419020e8-27ad-4722-9d00-5a5e0dad17f3

# Components

The following components are wrapped (more will be coming):

- General
- Button
- Layout
- Flex
- Grid (Col / Row)
- Navigation
- Dropdown
- Data entry
- DatePicker
- ColorPicker
- Select
- Switch
- Feedback
- Modal

# Installation

```
pip install ipyantd
```

# Dev install

```
npm ci
npm run build
pip install -e .
```
232 changes: 232 additions & 0 deletions examples/demo.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "e88d1c8e",
"metadata": {},
"outputs": [],
"source": [
"import ipyantd.widgets as antd\n",
"import ipyantd.icons.widgets as icons\n",
"import ipyreact"
]
},
{
"cell_type": "markdown",
"id": "a713bb10",
"metadata": {},
"source": [
"# Widget interface\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e84fa867",
"metadata": {},
"outputs": [],
"source": [
"import ipywidgets\n",
"from IPython.display import clear_output\n",
"\n",
"options = [\n",
" dict(label=\"Apple\", value=\"apple\"),\n",
" dict(label=\"Pear\", value=\"pear\"),\n",
" dict(label=\"Cherry\", value=\"cherry\"),\n",
"]\n",
"\n",
"menu_items = [\n",
" dict(key=\"1\", label=ipyreact.Widget(_type=\"div\", children=[\"Click me 1\"], events={\"onClick\": print})),\n",
" dict(key=\"2\", label=ipyreact.Widget(_type=\"div\", children=[\"Click me 2\"], events={\"onClick\": print})),\n",
"]\n",
"text = \"\"\"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n",
"Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. \n",
"Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. \n",
"Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. \n",
"Duis semper.\n",
"Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue.\n",
"\"\"\"\n",
"\n",
"\n",
"def dialog_open(event_data):\n",
" with output:\n",
" clear_output(wait=True)\n",
" print(\"Modal opened\")\n",
" dialog.value = True\n",
"\n",
"\n",
"def dialog_close(event_data):\n",
" with output:\n",
" clear_output(wait=True)\n",
" print(\"Modal closed\")\n",
" dialog.value = False\n",
" \n",
"def show_value(change):\n",
" new = change[\"new\"]\n",
" with output:\n",
" clear_output(wait=True)\n",
" print(\"value = \", new)\n",
"\n",
"def report_click(event_data=None):\n",
" with output:\n",
" clear_output(wait=True)\n",
" print(\"Clicked\")\n",
"\n",
"demo = ipyreact.Widget(_type=\"div\", children=[\n",
" antd.Row(props=dict(gutter=[48,48], style={\"padding\": \"100px\"}), children=[\n",
" antd.Col(props=dict(span=8, style={\"boxSizing\": \"border-box\"}), children=[\n",
" ipyreact.Widget(_type=\"div\", children=[\n",
" antd.Button(children=[\"Button\"], props=dict(type=\"primary\"), events={\"onClick\": report_click}),\n",
" antd.Button(children=[\"Button\"]),\n",
" ]),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" antd.Button(children=[\"Button\"], props=dict(type=\"primary\", shape=\"round\")),\n",
" antd.Button(props=dict(type=\"primary\", shape=\"circle\", icon=icons.Icon(\"SearchOutlined\"))),\n",
" antd.Button(props=dict(shape=\"circle\", icon=icons.Icon(\"SearchOutlined\"))),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" antd.Button(children=[\"Button\"], props=dict(type=\"text\")),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" antd.Button(children=[\"Button\"], props=dict(type=\"primary\", size=\"small\")),\n",
" antd.Button(children=[\"Button\"], props=dict(size=\"small\")),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" antd.Button(children=[\"Button\"], props=dict(type=\"primary\", shape=\"round\", size=\"small\")),\n",
" antd.Button(props=dict(type=\"primary\", shape=\"circle\", icon=icons.Icon(\"SearchOutlined\"), size=\"small\")),\n",
" antd.Button(props=dict(shape=\"circle\", icon=icons.Icon(\"SearchOutlined\"), size=\"small\")),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" antd.Button(children=[\"Button\"], props=dict(type=\"text\", size=\"small\")),\n",
" ]),\n",
" \n",
" # sliders\n",
" antd.Col(props=dict(span=8), children=[\n",
" antd.Slider(value=0, props=dict(min=0, max=100)),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" slider_range := antd.Slider(value=[20, 70], props=dict(min=0, max=100, range=True)),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" slider := antd.Slider(value=30, props=dict(min=0, max=100, tooltip=dict(open=True))),\n",
" ]),\n",
"\n",
" # select\n",
" antd.Col(props=dict(span=8), children=[\n",
" select := antd.Select(value=\"pear\", props=dict(options=options, style=dict(width=\"120px\"))),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" multi_select := antd.Select(value=[\"cherry\"], props=dict(options=options, style=dict(width=\"220px\"), mode=\"multiple\"))\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" # only supported in 5.31+\n",
" # antd.Select(value=\"pear\", props=dict(options=options, variant=\"filled\", style=dict(width=\"120px\"))),\n",
" ]),\n",
" \n",
" # misc\n",
" antd.Col(props=dict(span=8), children=[\n",
" switch := antd.Switch(value=True),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" dropdown := antd.Dropdown(props=dict(menu=dict(items=menu_items), trigger=[\"click\"]), children=\n",
" [ipyreact.Widget(_type=\"span\", children=[\"Menu\"])]\n",
" ),\n",
" ]),\n",
" antd.Col(props=dict(span=8), children=[\n",
" dialog := antd.Modal(events={\"onOk\": dialog_close, \"onCancel\": dialog_close}, children=[\n",
" ipyreact.Widget(_type=\"div\", children=[text])\n",
" ]),\n",
" antd.Button(children=[\"Dialog\"], props=dict(type=\"primary\"), events={\"onClick\": dialog_open}),\n",
" ]),\n",
"\n",
" \n",
" ]),\n",
" output := ipywidgets.Output()\n",
"])\n",
"select.observe(show_value, \"value\")\n",
"multi_select.observe(show_value, \"value\")\n",
"slider.observe(show_value, \"value\")\n",
"slider_range.observe(show_value, \"value\")\n",
"switch.observe(show_value, \"value\")\n",
"with output:\n",
" print(\" \")\n",
"demo"
]
},
{
"cell_type": "markdown",
"id": "bcfd2971",
"metadata": {},
"source": [
"# Solara component interface\n",
"\n",
"Coming soon"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8b2bc0b3",
"metadata": {},
"outputs": [],
"source": [
"import ipyantd.icons.widgets as icons"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d4ca25cc",
"metadata": {},
"outputs": [],
"source": [
"# import ipyantd.components as antd\n",
"# # import solara\n",
"# import reacton\n",
"# import ipyreact"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5fdc936b",
"metadata": {},
"outputs": [],
"source": [
"# @reacton.component\n",
"# def Page():\n",
"# with antd.Flex(props=dict(style={\"padding\": \"24px\"}, gap=\"small\")) as m:\n",
"# antd.Button(children=[\"Button\"], props=dict(type=\"primary\"))\n",
"# antd.Button(children=[\"Button\"])\n",
"# antd.Button(children=[\"Button\"], props=dict(type=\"primary\", shape=\"round\"))\n",
"# antd.Button(children=[\"Button\"], props=dict(type=\"primary\", shape=\"round\"))\n",
"# <Button type=\"primary\" shape=\"circle\" icon={<SearchOutlined />} />\n",
"# return m\n",
"# Page()"
]
}
],
"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.9.16"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
52 changes: 50 additions & 2 deletions ipyantd/assets/antd-jupyter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,54 @@
import * as React from "react";
import { Slider } from "antd";
import * as antd from "antd";

export function SliderStatefull({ value, setValue, ...rest }) {
return <Slider value={value} onChange={(v) => setValue(v)} {...rest} />;
return <antd.Slider value={value} onChange={(v) => setValue(v)} {...rest} />;
}

export function SelectStatefull({ value, setValue, ...rest }) {
return <antd.Select value={value} onChange={(v) => setValue(v)} {...rest} />;
}

export function SwitchStatefull({ value, setValue, ...rest }) {
return <antd.Switch value={value} onChange={(v) => setValue(v)} {...rest} />;
}

export function DropdownStatefull({ value, setValue, ...rest }) {
const onOpenChange = (open, info) => {
setValue(open);
if (rest.onOpenChange) {
rest.onOpenChange({ open, info });
}
};
return <antd.Dropdown open={value} onOpenChange={onOpenChange} {...rest} />;
}

export function ModalStatefull({ value, setValue, ...rest }) {
const onOpenChange = (open) => {
setValue(open);
if (rest.onOpenChange) {
rest.afterOpenChange(open);
}
};
const handleOk = () => {
// setValue(false);
if (rest.onOk) {
rest.onOk();
}
};
const handleCancel = () => {
// setValue(false);
if (rest.onCancel) {
rest.onCancel();
}
};
return (
<antd.Modal
open={value}
afterOpenChange={onOpenChange}
onOk={handleOk}
onCancel={handleCancel}
{...rest}
/>
);
}
32 changes: 32 additions & 0 deletions ipyantd/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,38 @@ class Flex(ipyreact.Widget):
_type = traitlets.Unicode("Flex").tag(sync=True)


class Row(ipyreact.Widget):
_module = traitlets.Unicode("antd").tag(sync=True)
_type = traitlets.Unicode("Row").tag(sync=True)


class Col(ipyreact.Widget):
_module = traitlets.Unicode("antd").tag(sync=True)
_type = traitlets.Unicode("Col").tag(sync=True)


class Select(ipyreact.ValueWidget):
_module = traitlets.Unicode("antd-jupyter").tag(sync=True)
_type = traitlets.Unicode("SelectStatefull").tag(sync=True)


class Switch(ipyreact.ValueWidget):
_module = traitlets.Unicode("antd-jupyter").tag(sync=True)
_type = traitlets.Unicode("SwitchStatefull").tag(sync=True)


class Dropdown(ipyreact.ValueWidget):
value = traitlets.Bool(False).tag(sync=True)
_module = traitlets.Unicode("antd-jupyter").tag(sync=True)
_type = traitlets.Unicode("DropdownStatefull").tag(sync=True)


class Modal(ipyreact.ValueWidget):
value = traitlets.Bool(False).tag(sync=True)
_module = traitlets.Unicode("antd-jupyter").tag(sync=True)
_type = traitlets.Unicode("ModalStatefull").tag(sync=True)


class DatePicker(ipyreact.ValueWidget):
# _module = traitlets.Unicode("antd").tag(sync=True)
# _type = traitlets.Unicode("DatePicker").tag(sync=True)
Expand Down

0 comments on commit 57f075f

Please sign in to comment.