diff --git a/.github/workflows/export-notebooks.yml b/.github/workflows/export-notebooks.yml
index 64126a2..f9f1b76 100644
--- a/.github/workflows/export-notebooks.yml
+++ b/.github/workflows/export-notebooks.yml
@@ -5,9 +5,12 @@ on:
repository_dispatch:
types: [marimo-release]
- # Trigger on push to main
+ # Trigger on push to main, but ignore if in generated files
push:
branches: [main]
+ paths-ignore:
+ - 'generated/**'
+ - 'public/**'
# Trigger nightly
schedule:
@@ -17,7 +20,10 @@ on:
workflow_dispatch: {}
permissions:
+ pull-requests: write
contents: write
+ pages: write
+ id-token: write
env:
UV_SYSTEM_PYTHON: 1
@@ -40,6 +46,7 @@ jobs:
- name: ๐ฆ Install marimo
run: |
uv pip install marimo
+ uv pip install nbformat polars altair vega_datasets matplotlib pandas
- name: ๐ Clone marimo examples
run: |
@@ -71,4 +78,31 @@ jobs:
automated
assignees: |
mscolnick
- add-paths: 'generated/*'
+ add-paths: |
+ generated/*
+ public/*
+
+ deploy:
+ needs: export-notebooks
+ runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+
+ steps:
+ - name: ๐ฅ Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: github-pages
+
+ - name: ๐ฆ Setup Pages
+ uses: actions/configure-pages@v4
+
+ - name: ๐ Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: public
+
+ - name: ๐ Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/README.md b/README.md
index 496589c..ed95c00 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@ Automated CI pipeline for validating and exporting [marimo](https://github.com/m
- Automatically exports whitelisted marimo notebooks:
- to markdown
- - (soon) to HTML
- - (soon) to ipynb
- - (soon) to script
+ - to HTML
+ - to ipynb
+ - to script
- Triggers on:
- (todo) New marimo releases
- Pushes to main from this repo
diff --git a/generated/examples/ui/arrays_and_dicts.py.ipynb b/generated/examples/ui/arrays_and_dicts.py.ipynb
new file mode 100644
index 0000000..5bbca05
--- /dev/null
+++ b/generated/examples/ui/arrays_and_dicts.py.ipynb
@@ -0,0 +1,178 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Arrays and Dictionaries"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "MJUe",
+ "metadata": {},
+ "source": [
+ "Use `mo.ui.array` and `mo.ui.dictionary` to create UI elements that wrap\n",
+ "other elements.\n",
+ "\n",
+ "Because UI elements must be assigned to global variables,\n",
+ "these functions are required when the set of elements to create is not\n",
+ "known until runtime."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "create = mo.ui.button(label=\"Create new collections\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "create.center()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "lEQa",
+ "metadata": {},
+ "source": [
+ "UI Elements ..."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "PKri",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "create\n",
+ "\n",
+ "array = mo.ui.array(\n",
+ " [mo.ui.text()]\n",
+ " + [mo.ui.slider(1, 10) for _ in range(0, random.randint(2, 5))],\n",
+ ")\n",
+ "dictionary = mo.ui.dictionary(\n",
+ " {str(i): mo.ui.slider(1, 10) for i in range(0, random.randint(2, 5))}\n",
+ ")\n",
+ "\n",
+ "mo.hstack([array, dictionary], justify=\"space-around\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "Xref",
+ "metadata": {},
+ "source": [
+ "... and their values"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "SFPL",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.hstack([array.value, dictionary.value], justify=\"space-around\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "BYtC",
+ "metadata": {},
+ "source": [
+ "Key difference between marimo dict and standard python dict:\n",
+ "\n",
+ "The main reason to use `mo.ui.dictionary` is for reactive execution โ when you interact with an element in a `mo.ui.dictionary`, all cells that reference the `mo.ui.dictionary` run automatically, just like all other ui elements. When you use a regular dictionary, you don't get this reactivity."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "RGSE",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "create\n",
+ "\n",
+ "slider = mo.ui.slider(1, 10, show_value=True)\n",
+ "text = mo.ui.text()\n",
+ "date = mo.ui.date()\n",
+ "\n",
+ "mo_d = mo.ui.dictionary(\n",
+ " {\n",
+ " \"slider\": slider,\n",
+ " \"text\": text,\n",
+ " \"date\": date,\n",
+ " }\n",
+ ")\n",
+ "\n",
+ "py_d = {\n",
+ " \"slider\": slider,\n",
+ " \"text\": text,\n",
+ " \"date\": date,\n",
+ "}\n",
+ "\n",
+ "mo.hstack(\n",
+ " [\n",
+ " mo.vstack([\"marimo dict\", mo_d]),\n",
+ " mo.vstack([\"original elements\", mo.vstack([slider, text, date])]),\n",
+ " mo.vstack([\"python dict\", py_d]),\n",
+ " ],\n",
+ " justify=\"space-around\",\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Kclp",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo_d_ref = {k: mo_d[k].value for k in mo_d.value.keys()}\n",
+ "py_d_ref = {k: py_d[k].value for k in py_d.keys()}\n",
+ "mo.hstack(\n",
+ " [\n",
+ " mo.vstack([\"reference of marimo dict\", mo_d_ref]),\n",
+ " mo.vstack([\"reference of python dict\", py_d_ref]),\n",
+ " ],\n",
+ " justify=\"space-around\",\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "emfo",
+ "metadata": {},
+ "source": [
+ "Notice that when you interact with the UI elements in the marimo dict, the reference of marimo dict updates automatically. However, when you interact with the elements in the python dict, you need to manually re-run the cell to see the updated values."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Hstk",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo\n",
+ "import random"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/arrays_and_dicts.script.py b/generated/examples/ui/arrays_and_dicts.script.py
new file mode 100644
index 0000000..8522cbf
--- /dev/null
+++ b/generated/examples/ui/arrays_and_dicts.script.py
@@ -0,0 +1,102 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+import random
+
+# %%
+mo.md(
+ """
+ Use `mo.ui.array` and `mo.ui.dictionary` to create UI elements that wrap
+ other elements.
+
+ Because UI elements must be assigned to global variables,
+ these functions are required when the set of elements to create is not
+ known until runtime.
+ """
+)
+
+# %%
+mo.md(
+ r"""
+ Key difference between marimo dict and standard python dict:
+
+ The main reason to use `mo.ui.dictionary` is for reactive execution โ when you interact with an element in a `mo.ui.dictionary`, all cells that reference the `mo.ui.dictionary` run automatically, just like all other ui elements. When you use a regular dictionary, you don't get this reactivity.
+ """
+)
+
+# %%
+create = mo.ui.button(label="Create new collections")
+
+# %%
+mo.md("""UI Elements ...""")
+
+# %%
+mo.md(r"""Notice that when you interact with the UI elements in the marimo dict, the reference of marimo dict updates automatically. However, when you interact with the elements in the python dict, you need to manually re-run the cell to see the updated values.""")
+
+# %%
+mo.md("""... and their values""")
+
+# %%
+mo.md("""# Arrays and Dictionaries""")
+
+# %%
+create.center()
+
+# %%
+create
+
+slider = mo.ui.slider(1, 10, show_value=True)
+text = mo.ui.text()
+date = mo.ui.date()
+
+mo_d = mo.ui.dictionary(
+ {
+ "slider": slider,
+ "text": text,
+ "date": date,
+ }
+)
+
+py_d = {
+ "slider": slider,
+ "text": text,
+ "date": date,
+}
+
+mo.hstack(
+ [
+ mo.vstack(["marimo dict", mo_d]),
+ mo.vstack(["original elements", mo.vstack([slider, text, date])]),
+ mo.vstack(["python dict", py_d]),
+ ],
+ justify="space-around",
+)
+
+# %%
+create
+
+array = mo.ui.array(
+ [mo.ui.text()]
+ + [mo.ui.slider(1, 10) for _ in range(0, random.randint(2, 5))],
+)
+dictionary = mo.ui.dictionary(
+ {str(i): mo.ui.slider(1, 10) for i in range(0, random.randint(2, 5))}
+)
+
+mo.hstack([array, dictionary], justify="space-around")
+
+# %%
+mo_d_ref = {k: mo_d[k].value for k in mo_d.value.keys()}
+py_d_ref = {k: py_d[k].value for k in py_d.keys()}
+mo.hstack(
+ [
+ mo.vstack(["reference of marimo dict", mo_d_ref]),
+ mo.vstack(["reference of python dict", py_d_ref]),
+ ],
+ justify="space-around",
+)
+
+# %%
+mo.hstack([array.value, dictionary.value], justify="space-around")
\ No newline at end of file
diff --git a/generated/examples/ui/batch_and_form.py.ipynb b/generated/examples/ui/batch_and_form.py.ipynb
new file mode 100644
index 0000000..855f5fb
--- /dev/null
+++ b/generated/examples/ui/batch_and_form.py.ipynb
@@ -0,0 +1,112 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Batch and Form"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "MJUe",
+ "metadata": {},
+ "source": [
+ "Make custom UI elements using `batch()`, and turn any UI element\n",
+ "into a form with `form()`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "reset\n",
+ "\n",
+ "variables = (\n",
+ " mo.md(\n",
+ " \"\"\"\n",
+ " Choose your variable values\n",
+ "\n",
+ " {x}\n",
+ "\n",
+ " {y}\n",
+ " \"\"\"\n",
+ " )\n",
+ " .batch(\n",
+ " x=mo.ui.slider(start=1, stop=10, step=1, label=\"$x =$\"),\n",
+ " y=mo.ui.slider(start=1, stop=10, step=1, label=\"$y =$\"),\n",
+ " )\n",
+ " .form(show_clear_button=True, bordered=False)\n",
+ ")\n",
+ "\n",
+ "variables"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if variables.value is not None:\n",
+ " submitted_values[\"x\"].add(variables.value[\"x\"])\n",
+ " submitted_values[\"y\"].add(variables.value[\"y\"])\n",
+ "\n",
+ "x = variables.value[\"x\"] if variables.value else \"\\ldots\"\n",
+ "y = variables.value[\"y\"] if variables.value else \"\\ldots\"\n",
+ "\n",
+ "\n",
+ "mo.md(\n",
+ " f\"\"\"\n",
+ " At the moment,\n",
+ " $x = {x}$ and $y = {y}$\n",
+ "\n",
+ " All values ever assumed by $x$ and $y$ are\n",
+ "\n",
+ " {mo.hstack([mo.tree(submitted_values), reset], align=\"center\", gap=4)}\n",
+ " \"\"\"\n",
+ ").callout()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "reset\n",
+ "\n",
+ "submitted_values = {\"x\": set(), \"y\": set()}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "PKri",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "reset = mo.ui.button(label=\"reset history\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Xref",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/batch_and_form.script.py b/generated/examples/ui/batch_and_form.script.py
new file mode 100644
index 0000000..008d5a2
--- /dev/null
+++ b/generated/examples/ui/batch_and_form.script.py
@@ -0,0 +1,66 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+
+# %%
+mo.md(
+ """
+ Make custom UI elements using `batch()`, and turn any UI element
+ into a form with `form()`.
+ """
+)
+
+# %%
+reset = mo.ui.button(label="reset history")
+
+# %%
+mo.md("""# Batch and Form""")
+
+# %%
+reset
+
+submitted_values = {"x": set(), "y": set()}
+
+# %%
+reset
+
+variables = (
+ mo.md(
+ """
+ Choose your variable values
+
+ {x}
+
+ {y}
+ """
+ )
+ .batch(
+ x=mo.ui.slider(start=1, stop=10, step=1, label="$x =$"),
+ y=mo.ui.slider(start=1, stop=10, step=1, label="$y =$"),
+ )
+ .form(show_clear_button=True, bordered=False)
+)
+
+variables
+
+# %%
+if variables.value is not None:
+ submitted_values["x"].add(variables.value["x"])
+ submitted_values["y"].add(variables.value["y"])
+
+x = variables.value["x"] if variables.value else "\ldots"
+y = variables.value["y"] if variables.value else "\ldots"
+
+
+mo.md(
+ f"""
+ At the moment,
+ $x = {x}$ and $y = {y}$
+
+ All values ever assumed by $x$ and $y$ are
+
+ {mo.hstack([mo.tree(submitted_values), reset], align="center", gap=4)}
+ """
+).callout()
\ No newline at end of file
diff --git a/generated/examples/ui/data_explorer.py.ipynb b/generated/examples/ui/data_explorer.py.ipynb
new file mode 100644
index 0000000..69ba1d5
--- /dev/null
+++ b/generated/examples/ui/data_explorer.py.ipynb
@@ -0,0 +1,150 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Data Explorer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "MJUe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sample = \"https://github.com/vega/vega/blob/main/docs/data/stocks.csv\"\n",
+ "\n",
+ "mo.md(\n",
+ " f\"\"\"\n",
+ " This notebook lets you upload a CSV and plot its columns.\n",
+ "\n",
+ " You can download a sample CSV if you'd like.\n",
+ " \"\"\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.md(\n",
+ " f\"\"\"\n",
+ " {mo.hstack([mo.md(\"**Upload a CSV.**\")], justify=\"center\")}\n",
+ "\n",
+ " {uploaded_file}\n",
+ " \"\"\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.stop(not uploaded_file.name())\n",
+ "df = pd.read_csv(io.StringIO(uploaded_file.contents().decode()))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.ui.table(df, page_size=5, selection=None)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "PKri",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_type = mo.ui.dropdown(\n",
+ " [\"line\", \"hist\"], value=\"line\", label=\"Choose a plot type: \"\n",
+ ")\n",
+ "\n",
+ "x_column = mo.ui.dropdown(df.columns, label=\"Choose x-axis: \")\n",
+ "y_column = mo.ui.dropdown(df.columns, label=\"Choose y-axis: \")\n",
+ "color_column = mo.ui.dropdown(df.columns, label=\"Choose color-axis: \")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Xref",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.hstack(\n",
+ " [x_column, y_column, color_column, plot_type], justify=\"space-around\"\n",
+ ").callout(kind=\"warn\" if not x_column.value else \"neutral\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "SFPL",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.stop(not x_column.value)\n",
+ "\n",
+ "\n",
+ "def plot(x_column, y_column, color_column):\n",
+ " y_column = y_column or \"count()\"\n",
+ " title = f\"{y_column} by {x_column}\"\n",
+ " encoding = {\"x\": x_column, \"y\": y_column}\n",
+ " if color_column:\n",
+ " encoding[\"color\"] = color_column\n",
+ " if plot_type.value == \"line\":\n",
+ " chart = alt.Chart(df).mark_line()\n",
+ " else:\n",
+ " chart = alt.Chart(df).mark_bar().encode(x=alt.X(x_column, bin=True))\n",
+ " return chart.encode(**encoding).properties(title=title, width=\"container\")\n",
+ "\n",
+ "\n",
+ "plot(x_column.value, y_column.value, color_column.value)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "BYtC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "uploaded_file = mo.ui.file(filetypes=[\".csv\"], kind=\"area\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "RGSE",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo\n",
+ "import altair as alt\n",
+ "\n",
+ "\n",
+ "import io\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/data_explorer.script.py b/generated/examples/ui/data_explorer.script.py
new file mode 100644
index 0000000..1bb108d
--- /dev/null
+++ b/generated/examples/ui/data_explorer.script.py
@@ -0,0 +1,77 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+import altair as alt
+
+
+import io
+import matplotlib.pyplot as plt
+import pandas as pd
+
+# %%
+mo.md("""# Data Explorer""")
+
+# %%
+sample = "https://github.com/vega/vega/blob/main/docs/data/stocks.csv"
+
+mo.md(
+ f"""
+ This notebook lets you upload a CSV and plot its columns.
+
+ You can download a sample CSV if you'd like.
+ """
+)
+
+# %%
+uploaded_file = mo.ui.file(filetypes=[".csv"], kind="area")
+
+# %%
+mo.stop(not uploaded_file.name())
+df = pd.read_csv(io.StringIO(uploaded_file.contents().decode()))
+
+# %%
+mo.md(
+ f"""
+ {mo.hstack([mo.md("**Upload a CSV.**")], justify="center")}
+
+ {uploaded_file}
+ """
+)
+
+# %%
+mo.ui.table(df, page_size=5, selection=None)
+
+# %%
+plot_type = mo.ui.dropdown(
+ ["line", "hist"], value="line", label="Choose a plot type: "
+)
+
+x_column = mo.ui.dropdown(df.columns, label="Choose x-axis: ")
+y_column = mo.ui.dropdown(df.columns, label="Choose y-axis: ")
+color_column = mo.ui.dropdown(df.columns, label="Choose color-axis: ")
+
+# %%
+mo.hstack(
+ [x_column, y_column, color_column, plot_type], justify="space-around"
+).callout(kind="warn" if not x_column.value else "neutral")
+
+# %%
+mo.stop(not x_column.value)
+
+
+def plot(x_column, y_column, color_column):
+ y_column = y_column or "count()"
+ title = f"{y_column} by {x_column}"
+ encoding = {"x": x_column, "y": y_column}
+ if color_column:
+ encoding["color"] = color_column
+ if plot_type.value == "line":
+ chart = alt.Chart(df).mark_line()
+ else:
+ chart = alt.Chart(df).mark_bar().encode(x=alt.X(x_column, bin=True))
+ return chart.encode(**encoding).properties(title=title, width="container")
+
+
+plot(x_column.value, y_column.value, color_column.value)
\ No newline at end of file
diff --git a/generated/examples/ui/filterable_table.py.ipynb b/generated/examples/ui/filterable_table.py.ipynb
new file mode 100644
index 0000000..b013b0f
--- /dev/null
+++ b/generated/examples/ui/filterable_table.py.ipynb
@@ -0,0 +1,115 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Filterable DataFrame"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "MJUe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Read the csv\n",
+ "df = pd.read_json(data_url(\"cars.json\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create options for select widgets\n",
+ "manufacturer_options = df[\"Name\"].str.split().str[0].unique()\n",
+ "manufacturer_options.sort()\n",
+ "cylinder_options = df[\"Cylinders\"].unique().astype(str)\n",
+ "cylinder_options.sort()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create the filters\n",
+ "manufacturer = mo.ui.dropdown(manufacturer_options, label=\"Manufacturer\")\n",
+ "cylinders = mo.ui.dropdown(cylinder_options, label=\"Cylinders\")\n",
+ "\n",
+ "horse_power = mo.ui.range_slider.from_series(\n",
+ " df[\"Horsepower\"],\n",
+ " show_value=True,\n",
+ ")\n",
+ "\n",
+ "mo.hstack([manufacturer, horse_power, cylinders], gap=3).left()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_df(df)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "PKri",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def filter_df(df):\n",
+ " filtered_df = df\n",
+ " if manufacturer.value:\n",
+ " filtered_df = filtered_df[\n",
+ " filtered_df[\"Name\"].str.contains(manufacturer.value, case=False)\n",
+ " ]\n",
+ " if cylinders.value:\n",
+ " filtered_df = filtered_df[filtered_df[\"Cylinders\"] == cylinders.value]\n",
+ " if horse_power.value:\n",
+ " left, right = horse_power.value\n",
+ " filtered_df = filtered_df[\n",
+ " (filtered_df[\"Horsepower\"] >= left)\n",
+ " & (filtered_df[\"Horsepower\"] <= right)\n",
+ " ]\n",
+ " return filtered_df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Xref",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def data_url(file):\n",
+ " return f\"https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/{file}\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "SFPL",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo\n",
+ "import pandas as pd"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/filterable_table.script.py b/generated/examples/ui/filterable_table.script.py
new file mode 100644
index 0000000..91f46c2
--- /dev/null
+++ b/generated/examples/ui/filterable_table.script.py
@@ -0,0 +1,56 @@
+
+__generated_with = "0.9.30"
+
+# %%
+def data_url(file):
+ return f"https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/{file}"
+
+# %%
+import marimo as mo
+import pandas as pd
+
+# %%
+# Read the csv
+df = pd.read_json(data_url("cars.json"))
+
+# %%
+mo.md(r"""# Filterable DataFrame""")
+
+# %%
+# Create options for select widgets
+manufacturer_options = df["Name"].str.split().str[0].unique()
+manufacturer_options.sort()
+cylinder_options = df["Cylinders"].unique().astype(str)
+cylinder_options.sort()
+
+# %%
+# Create the filters
+manufacturer = mo.ui.dropdown(manufacturer_options, label="Manufacturer")
+cylinders = mo.ui.dropdown(cylinder_options, label="Cylinders")
+
+horse_power = mo.ui.range_slider.from_series(
+ df["Horsepower"],
+ show_value=True,
+)
+
+mo.hstack([manufacturer, horse_power, cylinders], gap=3).left()
+
+# %%
+def filter_df(df):
+ filtered_df = df
+ if manufacturer.value:
+ filtered_df = filtered_df[
+ filtered_df["Name"].str.contains(manufacturer.value, case=False)
+ ]
+ if cylinders.value:
+ filtered_df = filtered_df[filtered_df["Cylinders"] == cylinders.value]
+ if horse_power.value:
+ left, right = horse_power.value
+ filtered_df = filtered_df[
+ (filtered_df["Horsepower"] >= left)
+ & (filtered_df["Horsepower"] <= right)
+ ]
+ return filtered_df
+
+# %%
+filter_df(df)
\ No newline at end of file
diff --git a/generated/examples/ui/inputs.py.ipynb b/generated/examples/ui/inputs.py.ipynb
new file mode 100644
index 0000000..113331a
--- /dev/null
+++ b/generated/examples/ui/inputs.py.ipynb
@@ -0,0 +1,265 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Inputs\n",
+ "\n",
+ "There are many way that a user can input with your notebook, such as text boxes, sliders, dates, and more."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "MJUe",
+ "metadata": {},
+ "source": [
+ "## Text boxes"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.hstack(\n",
+ " [\n",
+ " username := mo.ui.text(label=\"Username\"),\n",
+ " email := mo.ui.text(label=\"Email\", kind=\"email\"),\n",
+ " mo.ui.text(label=\"Password\", kind=\"password\"),\n",
+ " ]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.stop(not username.value, mo.md(\"What is your name?\"))\n",
+ "\n",
+ "mo.md(f\"๐ Hello {username.value}, nice to meet you!\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.ui.text_area(\n",
+ " label=\"A space for your thoughts\", full_width=True, max_length=1000\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "PKri",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.ui.number(label=\"What is your favorite number?\", start=0, stop=10)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "Xref",
+ "metadata": {},
+ "source": [
+ "## Sliders"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "SFPL",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "slider = mo.ui.slider(0, 100, value=50, label=\"Basic slider\", show_value=True)\n",
+ "range_slider = mo.ui.range_slider(\n",
+ " 0, 100, value=(30, 70), label=\"Range slider\", show_value=True\n",
+ ")\n",
+ "custom_steps = mo.ui.slider(\n",
+ " steps=[1, 10, 100, 1000], value=10, label=\"Custom steps\", show_value=True\n",
+ ")\n",
+ "vertical = mo.ui.slider(\n",
+ " 0, 100, value=50, label=\"Vertical slider\", orientation=\"vertical\"\n",
+ ")\n",
+ "mo.vstack([slider, range_slider, custom_steps, vertical]).center()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "BYtC",
+ "metadata": {},
+ "source": [
+ "## Checkboxes and Radios"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "RGSE",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "COLORS = [\"red\", \"green\", \"blue\"]\n",
+ "colors = mo.ui.array(\n",
+ " [mo.ui.checkbox(label=color) for color in COLORS],\n",
+ ")\n",
+ "\n",
+ "shape = mo.ui.radio(\n",
+ " [\"circle\", \"square\", \"triangle\"], inline=True, value=\"square\"\n",
+ ")\n",
+ "mo.md(f\"\"\"\n",
+ "Let's build something:\n",
+ "\n",
+ "**Pick a shape:**\n",
+ "\n",
+ "{shape}\n",
+ "\n",
+ "**Pick a color:**\n",
+ "\n",
+ "{colors.hstack().left()}\n",
+ "\"\"\").center()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Kclp",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "selected_colors = [color for i, color in enumerate(COLORS) if colors.value[i]]\n",
+ "\n",
+ "\n",
+ "def draw_shape(shape, colors):\n",
+ " if not colors:\n",
+ " return \"\"\n",
+ "\n",
+ " gradient = \"\"\n",
+ " if isinstance(colors, list) and len(colors) > 1:\n",
+ " gradient_id = f\"grad{hash(tuple(colors)) % 1000}\"\n",
+ " stops = \"\".join(\n",
+ " [\n",
+ " f''\n",
+ " for i, color in enumerate(colors)\n",
+ " ]\n",
+ " )\n",
+ " gradient = f'{stops}'\n",
+ " fill_color = f\"url(#{gradient_id})\"\n",
+ " else:\n",
+ " fill_color = colors if isinstance(colors, str) else colors[0]\n",
+ "\n",
+ " if shape == \"circle\":\n",
+ " html = f''\n",
+ " elif shape == \"square\":\n",
+ " html = f''\n",
+ " elif shape == \"triangle\":\n",
+ " html = f''\n",
+ " else:\n",
+ " html = \"Shape not recognized\"\n",
+ " return mo.Html(html)\n",
+ "\n",
+ "\n",
+ "mo.md(f\"\"\"\n",
+ "A {\"/\".join(selected_colors)} {shape.value}:\n",
+ "{draw_shape(shape.value, selected_colors)}\n",
+ "\"\"\").center()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "emfo",
+ "metadata": {},
+ "source": [
+ "## Dates"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Hstk",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import datetime\n",
+ "\n",
+ "start_date = mo.ui.date(\n",
+ " label=\"Start date\",\n",
+ " start=datetime.date(2020, 1, 1),\n",
+ " stop=datetime.date(2020, 12, 31),\n",
+ ")\n",
+ "end_date = mo.ui.date(\n",
+ " label=\"End date\",\n",
+ " start=datetime.date(2020, 1, 1),\n",
+ " stop=datetime.date(2020, 12, 31),\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "nWHF",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.hstack(\n",
+ " [\n",
+ " mo.hstack([start_date, \"โก๏ธ\", end_date]).left(),\n",
+ " mo.md(f\"From {start_date.value} to {end_date.value}\"),\n",
+ " ]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "iLit",
+ "metadata": {},
+ "source": [
+ "## Dropdowns"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ZHCJ",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "single = mo.ui.dropdown(\n",
+ " [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\", \"Option 5\"],\n",
+ " label=\"Single select\",\n",
+ ")\n",
+ "multi = mo.ui.multiselect(\n",
+ " [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\", \"Option 5\"],\n",
+ " label=\"Multi select\",\n",
+ " value=[\"Option 1\", \"Option 2\"],\n",
+ ")\n",
+ "mo.hstack([single, multi])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ROlb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/inputs.script.py b/generated/examples/ui/inputs.script.py
new file mode 100644
index 0000000..6b33d7b
--- /dev/null
+++ b/generated/examples/ui/inputs.script.py
@@ -0,0 +1,157 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+
+# %%
+mo.md(r"""## Checkboxes and Radios""")
+
+# %%
+mo.md("""## Dates""")
+
+# %%
+mo.md(
+ r"""
+ # Inputs
+
+ There are many way that a user can input with your notebook, such as text boxes, sliders, dates, and more.
+ """
+)
+
+# %%
+mo.ui.number(label="What is your favorite number?", start=0, stop=10)
+
+# %%
+slider = mo.ui.slider(0, 100, value=50, label="Basic slider", show_value=True)
+range_slider = mo.ui.range_slider(
+ 0, 100, value=(30, 70), label="Range slider", show_value=True
+)
+custom_steps = mo.ui.slider(
+ steps=[1, 10, 100, 1000], value=10, label="Custom steps", show_value=True
+)
+vertical = mo.ui.slider(
+ 0, 100, value=50, label="Vertical slider", orientation="vertical"
+)
+mo.vstack([slider, range_slider, custom_steps, vertical]).center()
+
+# %%
+mo.md(r"""## Sliders""")
+
+# %%
+mo.ui.text_area(
+ label="A space for your thoughts", full_width=True, max_length=1000
+)
+
+# %%
+single = mo.ui.dropdown(
+ ["Option 1", "Option 2", "Option 3", "Option 4", "Option 5"],
+ label="Single select",
+)
+multi = mo.ui.multiselect(
+ ["Option 1", "Option 2", "Option 3", "Option 4", "Option 5"],
+ label="Multi select",
+ value=["Option 1", "Option 2"],
+)
+mo.hstack([single, multi])
+
+# %%
+COLORS = ["red", "green", "blue"]
+colors = mo.ui.array(
+ [mo.ui.checkbox(label=color) for color in COLORS],
+)
+
+shape = mo.ui.radio(
+ ["circle", "square", "triangle"], inline=True, value="square"
+)
+mo.md(f"""
+Let's build something:
+
+**Pick a shape:**
+
+{shape}
+
+**Pick a color:**
+
+{colors.hstack().left()}
+""").center()
+
+# %%
+import datetime
+
+start_date = mo.ui.date(
+ label="Start date",
+ start=datetime.date(2020, 1, 1),
+ stop=datetime.date(2020, 12, 31),
+)
+end_date = mo.ui.date(
+ label="End date",
+ start=datetime.date(2020, 1, 1),
+ stop=datetime.date(2020, 12, 31),
+)
+
+# %%
+mo.md(r"""## Text boxes""")
+
+# %%
+mo.md("""## Dropdowns""")
+
+# %%
+mo.hstack(
+ [
+ username := mo.ui.text(label="Username"),
+ email := mo.ui.text(label="Email", kind="email"),
+ mo.ui.text(label="Password", kind="password"),
+ ]
+)
+
+# %%
+selected_colors = [color for i, color in enumerate(COLORS) if colors.value[i]]
+
+
+def draw_shape(shape, colors):
+ if not colors:
+ return ""
+
+ gradient = ""
+ if isinstance(colors, list) and len(colors) > 1:
+ gradient_id = f"grad{hash(tuple(colors)) % 1000}"
+ stops = "".join(
+ [
+ f''
+ for i, color in enumerate(colors)
+ ]
+ )
+ gradient = f'{stops}'
+ fill_color = f"url(#{gradient_id})"
+ else:
+ fill_color = colors if isinstance(colors, str) else colors[0]
+
+ if shape == "circle":
+ html = f''
+ elif shape == "square":
+ html = f''
+ elif shape == "triangle":
+ html = f''
+ else:
+ html = "Shape not recognized"
+ return mo.Html(html)
+
+
+mo.md(f"""
+A {"/".join(selected_colors)} {shape.value}:
+{draw_shape(shape.value, selected_colors)}
+""").center()
+
+# %%
+mo.hstack(
+ [
+ mo.hstack([start_date, "โก๏ธ", end_date]).left(),
+ mo.md(f"From {start_date.value} to {end_date.value}"),
+ ]
+)
+
+# %%
+mo.stop(not username.value, mo.md("What is your name?"))
+
+mo.md(f"๐ Hello {username.value}, nice to meet you!")
\ No newline at end of file
diff --git a/generated/examples/ui/layout.py.ipynb b/generated/examples/ui/layout.py.ipynb
new file mode 100644
index 0000000..a89cbd3
--- /dev/null
+++ b/generated/examples/ui/layout.py.ipynb
@@ -0,0 +1,125 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Stacks"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "MJUe",
+ "metadata": {},
+ "source": [
+ "Use `mo.hstack` and `mo.vstack` to layout outputs in rows and columns."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "align = mo.ui.dropdown(\n",
+ " label=\"Align\", options=[\"start\", \"end\", \"center\", \"stretch\"]\n",
+ ")\n",
+ "justify = mo.ui.dropdown(\n",
+ " label=\"Justify\",\n",
+ " options=[\"start\", \"center\", \"end\", \"space-between\", \"space-around\"],\n",
+ ")\n",
+ "gap = mo.ui.number(label=\"Gap\", start=0, stop=100, value=1)\n",
+ "size = mo.ui.slider(label=\"Size\", start=60, stop=500)\n",
+ "wrap = mo.ui.checkbox(label=\"Wrap\")\n",
+ "\n",
+ "mo.md(\n",
+ " f\"\"\"\n",
+ " **Stack parameters**\n",
+ "\n",
+ " {mo.hstack([align, justify, gap, wrap], gap=0.25)}\n",
+ "\n",
+ " **Boxes {size}**\n",
+ " \"\"\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bkHC",
+ "metadata": {},
+ "source": [
+ "## Horizontal Stack: `hstack`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.hstack(\n",
+ " boxes,\n",
+ " align=align.value,\n",
+ " justify=justify.value,\n",
+ " gap=gap.value,\n",
+ " wrap=wrap.value,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "PKri",
+ "metadata": {},
+ "source": [
+ "## Vertical Stack: `vstack`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Xref",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.vstack(\n",
+ " boxes,\n",
+ " align=align.value,\n",
+ " gap=gap.value,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "SFPL",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def create_box(num):\n",
+ " box_size = size.value + num * 10\n",
+ " return mo.Html(\n",
+ " f\"
{str(num)}
\"\n",
+ " )\n",
+ "\n",
+ "\n",
+ "boxes = [create_box(i) for i in range(1, 5)]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "BYtC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/layout.script.py b/generated/examples/ui/layout.script.py
new file mode 100644
index 0000000..4425cfe
--- /dev/null
+++ b/generated/examples/ui/layout.script.py
@@ -0,0 +1,65 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+
+# %%
+mo.md("""## Vertical Stack: `vstack`""")
+
+# %%
+mo.md("""# Stacks""")
+
+# %%
+mo.md("""## Horizontal Stack: `hstack`""")
+
+# %%
+align = mo.ui.dropdown(
+ label="Align", options=["start", "end", "center", "stretch"]
+)
+justify = mo.ui.dropdown(
+ label="Justify",
+ options=["start", "center", "end", "space-between", "space-around"],
+)
+gap = mo.ui.number(label="Gap", start=0, stop=100, value=1)
+size = mo.ui.slider(label="Size", start=60, stop=500)
+wrap = mo.ui.checkbox(label="Wrap")
+
+mo.md(
+ f"""
+ **Stack parameters**
+
+ {mo.hstack([align, justify, gap, wrap], gap=0.25)}
+
+ **Boxes {size}**
+ """
+)
+
+# %%
+mo.md("""Use `mo.hstack` and `mo.vstack` to layout outputs in rows and columns.""")
+
+# %%
+def create_box(num):
+ box_size = size.value + num * 10
+ return mo.Html(
+ f"{str(num)}
"
+ )
+
+
+boxes = [create_box(i) for i in range(1, 5)]
+
+# %%
+mo.hstack(
+ boxes,
+ align=align.value,
+ justify=justify.value,
+ gap=gap.value,
+ wrap=wrap.value,
+)
+
+# %%
+mo.vstack(
+ boxes,
+ align=align.value,
+ gap=gap.value,
+)
\ No newline at end of file
diff --git a/generated/examples/ui/mermaid.py.ipynb b/generated/examples/ui/mermaid.py.ipynb
new file mode 100644
index 0000000..227752e
--- /dev/null
+++ b/generated/examples/ui/mermaid.py.ipynb
@@ -0,0 +1,74 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Hbol",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "MJUe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.mermaid(\n",
+ " \"\"\"\n",
+ "graph TD\n",
+ " A[Enter Chart Definition] --> B(Preview)\n",
+ " B --> C{decide}\n",
+ " C --> D[Keep]\n",
+ " C --> E[Edit Definition]\n",
+ " E --> B\n",
+ " D --> F[Save Image and Code]\n",
+ " F --> B\n",
+ "\"\"\"\n",
+ ").center()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "graph = mo.ui.code_editor(\n",
+ " value=\"\"\"sequenceDiagram\n",
+ " Alice->>John: Hello John, how are you?\n",
+ " John-->>Alice: Great!\n",
+ " Alice-)John: See you later!\"\"\",\n",
+ " language=\"mermaid\",\n",
+ " label=\"Mermaid editor\",\n",
+ ")\n",
+ "graph"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.md(\n",
+ " f\"\"\"\n",
+ " You can render mermaid directly inside `mo.md`. Using\n",
+ "\n",
+ " `mo.mermaid()`\n",
+ "\n",
+ " {mo.mermaid(graph.value)}\n",
+ " \"\"\"\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/mermaid.script.py b/generated/examples/ui/mermaid.script.py
new file mode 100644
index 0000000..13af23e
--- /dev/null
+++ b/generated/examples/ui/mermaid.script.py
@@ -0,0 +1,41 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+
+# %%
+mo.mermaid(
+ """
+graph TD
+ A[Enter Chart Definition] --> B(Preview)
+ B --> C{decide}
+ C --> D[Keep]
+ C --> E[Edit Definition]
+ E --> B
+ D --> F[Save Image and Code]
+ F --> B
+"""
+).center()
+
+# %%
+graph = mo.ui.code_editor(
+ value="""sequenceDiagram
+ Alice->>John: Hello John, how are you?
+ John-->>Alice: Great!
+ Alice-)John: See you later!""",
+ language="mermaid",
+ label="Mermaid editor",
+)
+graph
+
+# %%
+mo.md(
+ f"""
+ You can render mermaid directly inside `mo.md`. Using
+
+ `mo.mermaid()`
+
+ {mo.mermaid(graph.value)}
+ """
+)
\ No newline at end of file
diff --git a/generated/examples/ui/reactive_plots.py.ipynb b/generated/examples/ui/reactive_plots.py.ipynb
new file mode 100644
index 0000000..24b8ad0
--- /dev/null
+++ b/generated/examples/ui/reactive_plots.py.ipynb
@@ -0,0 +1,105 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Welcome to marimo!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "MJUe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "chart = mo.ui.altair_chart(scatter & bars)\n",
+ "chart"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "(filtered_data := mo.ui.table(chart.value))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.stop(not len(filtered_data.value))\n",
+ "mpg_hist = mo.ui.altair_chart(\n",
+ " alt.Chart(filtered_data.value)\n",
+ " .mark_bar()\n",
+ " .encode(alt.X(\"Miles_per_Gallon:Q\", bin=True), y=\"count()\")\n",
+ ")\n",
+ "horsepower_hist = mo.ui.altair_chart(\n",
+ " alt.Chart(filtered_data.value)\n",
+ " .mark_bar()\n",
+ " .encode(alt.X(\"Horsepower:Q\", bin=True), y=\"count()\")\n",
+ ")\n",
+ "mo.hstack([mpg_hist, horsepower_hist], justify=\"space-around\", widths=\"equal\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cars = data.cars()\n",
+ "brush = alt.selection_interval()\n",
+ "scatter = (\n",
+ " alt.Chart(cars)\n",
+ " .mark_point()\n",
+ " .encode(\n",
+ " x=\"Horsepower\",\n",
+ " y=\"Miles_per_Gallon\",\n",
+ " color=\"Origin\",\n",
+ " )\n",
+ " .add_params(brush)\n",
+ ")\n",
+ "bars = (\n",
+ " alt.Chart(cars)\n",
+ " .mark_bar()\n",
+ " .encode(y=\"Origin:N\", color=\"Origin:N\", x=\"count(Origin):Q\")\n",
+ " .transform_filter(brush)\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "PKri",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import altair as alt\n",
+ "from vega_datasets import data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Xref",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/reactive_plots.script.py b/generated/examples/ui/reactive_plots.script.py
new file mode 100644
index 0000000..3a2e73e
--- /dev/null
+++ b/generated/examples/ui/reactive_plots.script.py
@@ -0,0 +1,53 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import altair as alt
+from vega_datasets import data
+
+# %%
+import marimo as mo
+
+# %%
+cars = data.cars()
+brush = alt.selection_interval()
+scatter = (
+ alt.Chart(cars)
+ .mark_point()
+ .encode(
+ x="Horsepower",
+ y="Miles_per_Gallon",
+ color="Origin",
+ )
+ .add_params(brush)
+)
+bars = (
+ alt.Chart(cars)
+ .mark_bar()
+ .encode(y="Origin:N", color="Origin:N", x="count(Origin):Q")
+ .transform_filter(brush)
+)
+
+# %%
+mo.md("""# Welcome to marimo!""")
+
+# %%
+chart = mo.ui.altair_chart(scatter & bars)
+chart
+
+# %%
+(filtered_data := mo.ui.table(chart.value))
+
+# %%
+mo.stop(not len(filtered_data.value))
+mpg_hist = mo.ui.altair_chart(
+ alt.Chart(filtered_data.value)
+ .mark_bar()
+ .encode(alt.X("Miles_per_Gallon:Q", bin=True), y="count()")
+)
+horsepower_hist = mo.ui.altair_chart(
+ alt.Chart(filtered_data.value)
+ .mark_bar()
+ .encode(alt.X("Horsepower:Q", bin=True), y="count()")
+)
+mo.hstack([mpg_hist, horsepower_hist], justify="space-around", widths="equal")
\ No newline at end of file
diff --git a/generated/examples/ui/refresh.py.ipynb b/generated/examples/ui/refresh.py.ipynb
new file mode 100644
index 0000000..ac45951
--- /dev/null
+++ b/generated/examples/ui/refresh.py.ipynb
@@ -0,0 +1,139 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Hbol",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.hstack([\n",
+ " mo.vstack([\n",
+ " mo.md(\"## Settings | [`marimo.ui.slider`](https://docs.marimo.io/api/inputs/slider.html), [`marimo.ui.refresh`](https://docs.marimo.io/recipes.html#run-a-cell-on-a-timer)\\n---\"),\n",
+ " refresh_interval_slider,\n",
+ " n_points_slider,\n",
+ " refresher,\n",
+ " mo.md(\"## ISS Positions | [`marimo.ui.altair_chart`](https://docs.marimo.io/api/plotting.html#marimo.ui.altair_chart)\\n---\"),\n",
+ " mo.as_html(chart).style({\"width\": \"700px\"})\n",
+ " ], align=\"center\"),\n",
+ " mo.vstack([\n",
+ " mo.md(\"## Data | [`marimo.as_html`](https://docs.marimo.io/api/html.html)`(pd.DataFrame)`\\n---\"),\n",
+ " mo.as_html(iss_df)\n",
+ " ])\n",
+ "], justify=\"center\", wrap=True, gap=3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "MJUe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "hover=alt.selection_point(on=\"mouseover\", clear=\"mouseout\")\n",
+ "\n",
+ "# iss positions\n",
+ "iss_df = get_iss_positions()\n",
+ "iss = alt.Chart(iss_df[['longitude','latitude','timestamp']]).mark_circle(\n",
+ " stroke='black', size=100,\n",
+ ").encode(\n",
+ " longitude=alt.Longitude('longitude:Q'),\n",
+ " latitude='latitude:Q',\n",
+ " fill=alt.Fill('timestamp:Q', scale=alt.Scale(scheme='purples'), legend=None),\n",
+ " strokeWidth=alt.condition(hover, alt.value(3, empty=False), alt.value(0)),\n",
+ " tooltip=[\n",
+ " alt.Tooltip('longitude:Q', title='Longitude', format='.4f'),\n",
+ " alt.Tooltip('latitude:Q', title='Latitude', format='.4f'),\n",
+ " alt.Tooltip('timestamp:T', title='Timestamp', format='%Y-%m-%d %H:%M:%S')\n",
+ " ]\n",
+ ").add_params(hover)\n",
+ "\n",
+ "chart = alt.layer(sphere, world, iss).project(type=\"naturalEarth1\").properties(width=640, title=\"\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# load geo data from Vega Datasets\n",
+ "countries = alt.topo_feature(data.world_110m.url, 'countries')\n",
+ "\n",
+ "# world base\n",
+ "sphere = alt.Chart(alt.sphere()).mark_geoshape(\n",
+ " fill=\"aliceblue\", stroke=\"black\", strokeWidth=1.5\n",
+ ")\n",
+ "\n",
+ "# world map\n",
+ "world = alt.Chart(countries).mark_geoshape(\n",
+ " fill=\"mintcream\", stroke=\"black\", strokeWidth=0.35\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_iss_positions(refresher=refresher):\n",
+ " refresher\n",
+ " timepoints = [int(time())]\n",
+ " while len(timepoints) <= n_points_slider.value:\n",
+ " timepoints.append(timepoints[-1] - refresh_interval_slider.value)\n",
+ " else:\n",
+ " timepoints.pop(0)\n",
+ " timepoints_str = str(timepoints)[1:-1].replace(\" \", \"\")\n",
+ " iss_url = f\"https://api.wheretheiss.at/v1/satellites/25544/positions?timestamps={timepoints_str}\"\n",
+ " response = requests.get(iss_url)\n",
+ " df = pd.DataFrame(response.json())\n",
+ " df['timestamp'] = pd.to_datetime(df.timestamp, unit='s')\n",
+ " return df[['timestamp','latitude','longitude','altitude','velocity','visibility']]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "refresher = mo.ui.refresh(default_interval=f\"{refresh_interval_slider.value}s\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "PKri",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "refresh_interval_slider = mo.ui.slider(start=5, stop=60, step=1, value=10, label=\"refresh interval (default = 10 sec)\")\n",
+ "n_points_slider = mo.ui.slider(start=5, stop=30, step=1, value=15, label=\"number of points (default = 15)\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Xref",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import altair as alt\n",
+ "import marimo as mo\n",
+ "import pandas as pd\n",
+ "import requests\n",
+ "from time import time\n",
+ "from vega_datasets import data\n",
+ "\n",
+ "pd.options.display.max_rows = 30"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/refresh.script.py b/generated/examples/ui/refresh.script.py
new file mode 100644
index 0000000..55e3444
--- /dev/null
+++ b/generated/examples/ui/refresh.script.py
@@ -0,0 +1,85 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import altair as alt
+import marimo as mo
+import pandas as pd
+import requests
+from time import time
+from vega_datasets import data
+
+pd.options.display.max_rows = 30
+
+# %%
+# load geo data from Vega Datasets
+countries = alt.topo_feature(data.world_110m.url, 'countries')
+
+# world base
+sphere = alt.Chart(alt.sphere()).mark_geoshape(
+ fill="aliceblue", stroke="black", strokeWidth=1.5
+)
+
+# world map
+world = alt.Chart(countries).mark_geoshape(
+ fill="mintcream", stroke="black", strokeWidth=0.35
+)
+
+# %%
+refresh_interval_slider = mo.ui.slider(start=5, stop=60, step=1, value=10, label="refresh interval (default = 10 sec)")
+n_points_slider = mo.ui.slider(start=5, stop=30, step=1, value=15, label="number of points (default = 15)")
+
+# %%
+refresher = mo.ui.refresh(default_interval=f"{refresh_interval_slider.value}s")
+
+# %%
+def get_iss_positions(refresher=refresher):
+ refresher
+ timepoints = [int(time())]
+ while len(timepoints) <= n_points_slider.value:
+ timepoints.append(timepoints[-1] - refresh_interval_slider.value)
+ else:
+ timepoints.pop(0)
+ timepoints_str = str(timepoints)[1:-1].replace(" ", "")
+ iss_url = f"https://api.wheretheiss.at/v1/satellites/25544/positions?timestamps={timepoints_str}"
+ response = requests.get(iss_url)
+ df = pd.DataFrame(response.json())
+ df['timestamp'] = pd.to_datetime(df.timestamp, unit='s')
+ return df[['timestamp','latitude','longitude','altitude','velocity','visibility']]
+
+# %%
+hover=alt.selection_point(on="mouseover", clear="mouseout")
+
+# iss positions
+iss_df = get_iss_positions()
+iss = alt.Chart(iss_df[['longitude','latitude','timestamp']]).mark_circle(
+ stroke='black', size=100,
+).encode(
+ longitude=alt.Longitude('longitude:Q'),
+ latitude='latitude:Q',
+ fill=alt.Fill('timestamp:Q', scale=alt.Scale(scheme='purples'), legend=None),
+ strokeWidth=alt.condition(hover, alt.value(3, empty=False), alt.value(0)),
+ tooltip=[
+ alt.Tooltip('longitude:Q', title='Longitude', format='.4f'),
+ alt.Tooltip('latitude:Q', title='Latitude', format='.4f'),
+ alt.Tooltip('timestamp:T', title='Timestamp', format='%Y-%m-%d %H:%M:%S')
+ ]
+).add_params(hover)
+
+chart = alt.layer(sphere, world, iss).project(type="naturalEarth1").properties(width=640, title="")
+
+# %%
+mo.hstack([
+ mo.vstack([
+ mo.md("## Settings | [`marimo.ui.slider`](https://docs.marimo.io/api/inputs/slider.html), [`marimo.ui.refresh`](https://docs.marimo.io/recipes.html#run-a-cell-on-a-timer)\n---"),
+ refresh_interval_slider,
+ n_points_slider,
+ refresher,
+ mo.md("## ISS Positions | [`marimo.ui.altair_chart`](https://docs.marimo.io/api/plotting.html#marimo.ui.altair_chart)\n---"),
+ mo.as_html(chart).style({"width": "700px"})
+ ], align="center"),
+ mo.vstack([
+ mo.md("## Data | [`marimo.as_html`](https://docs.marimo.io/api/html.html)`(pd.DataFrame)`\n---"),
+ mo.as_html(iss_df)
+ ])
+], justify="center", wrap=True, gap=3)
\ No newline at end of file
diff --git a/generated/examples/ui/table.py.ipynb b/generated/examples/ui/table.py.ipynb
new file mode 100644
index 0000000..f013e18
--- /dev/null
+++ b/generated/examples/ui/table.py.ipynb
@@ -0,0 +1,255 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Tables\n",
+ "\n",
+ "> โSometimes Iโll start a sentence and I donโt even know where itโs going. I just hope I find it along the way.โ\n",
+ "โ Michael Scott"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "MJUe",
+ "metadata": {},
+ "source": [
+ "_Create rich tables with selectable rows using_ `mo.ui.table`."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "vblA",
+ "metadata": {},
+ "source": [
+ "**Single selection.**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "single_select_table = mo.ui.table(\n",
+ " office_characters,\n",
+ " selection=\"single\",\n",
+ " pagination=True,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.ui.tabs({\"table\": single_select_table, \"selection\": single_select_table.value})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "PKri",
+ "metadata": {},
+ "source": [
+ "**Multi-selection.**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Xref",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "multi_select_table = mo.ui.table(\n",
+ " office_characters,\n",
+ " selection=\"multi\",\n",
+ " pagination=True,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "SFPL",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.ui.tabs({\"table\": multi_select_table, \"selection\": multi_select_table.value})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "BYtC",
+ "metadata": {},
+ "source": [
+ "**No selection.**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "RGSE",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "table = mo.ui.table(\n",
+ " office_characters,\n",
+ " label=\"Employees\",\n",
+ " selection=None,\n",
+ ")\n",
+ "\n",
+ "table"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Kclp",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "office_characters = [\n",
+ " {\n",
+ " \"first_name\": \"Michael\",\n",
+ " \"last_name\": \"Scott\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=3),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\", rounded=True),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Jim\",\n",
+ " \"last_name\": \"Halpert\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=7),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Pam\",\n",
+ " \"last_name\": \"Beesly\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=3),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Dwight\",\n",
+ " \"last_name\": \"Schrute\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=7),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Angela\",\n",
+ " \"last_name\": \"Martin\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=5),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Kevin\",\n",
+ " \"last_name\": \"Malone\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=3),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Oscar\",\n",
+ " \"last_name\": \"Martinez\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=3),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Stanley\",\n",
+ " \"last_name\": \"Hudson\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=5),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Phyllis\",\n",
+ " \"last_name\": \"Vance\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=5),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Meredith\",\n",
+ " \"last_name\": \"Palmer\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=7),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Creed\",\n",
+ " \"last_name\": \"Bratton\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=3),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Ryan\",\n",
+ " \"last_name\": \"Howard\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=5),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Kelly\",\n",
+ " \"last_name\": \"Kapoor\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=3),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Toby\",\n",
+ " \"last_name\": \"Flenderson\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=3),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Darryl\",\n",
+ " \"last_name\": \"Philbin\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=7),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Erin\",\n",
+ " \"last_name\": \"Hannon\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=5),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Andy\",\n",
+ " \"last_name\": \"Bernard\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=5),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Jan\",\n",
+ " \"last_name\": \"Levinson\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=5),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"David\",\n",
+ " \"last_name\": \"Wallace\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=3),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ " {\n",
+ " \"first_name\": \"Holly\",\n",
+ " \"last_name\": \"Flax\",\n",
+ " \"skill\": mo.ui.slider(1, 10, value=7),\n",
+ " \"favorite place\": mo.image(src=\"https://picsum.photos/100\"),\n",
+ " },\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "emfo",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/table.script.py b/generated/examples/ui/table.script.py
new file mode 100644
index 0000000..0fc37d0
--- /dev/null
+++ b/generated/examples/ui/table.script.py
@@ -0,0 +1,180 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+
+# %%
+office_characters = [
+ {
+ "first_name": "Michael",
+ "last_name": "Scott",
+ "skill": mo.ui.slider(1, 10, value=3),
+ "favorite place": mo.image(src="https://picsum.photos/100", rounded=True),
+ },
+ {
+ "first_name": "Jim",
+ "last_name": "Halpert",
+ "skill": mo.ui.slider(1, 10, value=7),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Pam",
+ "last_name": "Beesly",
+ "skill": mo.ui.slider(1, 10, value=3),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Dwight",
+ "last_name": "Schrute",
+ "skill": mo.ui.slider(1, 10, value=7),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Angela",
+ "last_name": "Martin",
+ "skill": mo.ui.slider(1, 10, value=5),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Kevin",
+ "last_name": "Malone",
+ "skill": mo.ui.slider(1, 10, value=3),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Oscar",
+ "last_name": "Martinez",
+ "skill": mo.ui.slider(1, 10, value=3),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Stanley",
+ "last_name": "Hudson",
+ "skill": mo.ui.slider(1, 10, value=5),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Phyllis",
+ "last_name": "Vance",
+ "skill": mo.ui.slider(1, 10, value=5),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Meredith",
+ "last_name": "Palmer",
+ "skill": mo.ui.slider(1, 10, value=7),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Creed",
+ "last_name": "Bratton",
+ "skill": mo.ui.slider(1, 10, value=3),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Ryan",
+ "last_name": "Howard",
+ "skill": mo.ui.slider(1, 10, value=5),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Kelly",
+ "last_name": "Kapoor",
+ "skill": mo.ui.slider(1, 10, value=3),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Toby",
+ "last_name": "Flenderson",
+ "skill": mo.ui.slider(1, 10, value=3),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Darryl",
+ "last_name": "Philbin",
+ "skill": mo.ui.slider(1, 10, value=7),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Erin",
+ "last_name": "Hannon",
+ "skill": mo.ui.slider(1, 10, value=5),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Andy",
+ "last_name": "Bernard",
+ "skill": mo.ui.slider(1, 10, value=5),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Jan",
+ "last_name": "Levinson",
+ "skill": mo.ui.slider(1, 10, value=5),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "David",
+ "last_name": "Wallace",
+ "skill": mo.ui.slider(1, 10, value=3),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+ {
+ "first_name": "Holly",
+ "last_name": "Flax",
+ "skill": mo.ui.slider(1, 10, value=7),
+ "favorite place": mo.image(src="https://picsum.photos/100"),
+ },
+]
+
+# %%
+mo.md("""**Multi-selection.**""")
+
+# %%
+mo.md("""_Create rich tables with selectable rows using_ `mo.ui.table`.""")
+
+# %%
+mo.md(
+ """
+ # Tables
+
+ > โSometimes Iโll start a sentence and I donโt even know where itโs going. I just hope I find it along the way.โ
+ โ Michael Scott
+ """
+)
+
+# %%
+mo.md("""**Single selection.**""")
+
+# %%
+mo.md("""**No selection.**""")
+
+# %%
+single_select_table = mo.ui.table(
+ office_characters,
+ selection="single",
+ pagination=True,
+)
+
+# %%
+table = mo.ui.table(
+ office_characters,
+ label="Employees",
+ selection=None,
+)
+
+table
+
+# %%
+multi_select_table = mo.ui.table(
+ office_characters,
+ selection="multi",
+ pagination=True,
+)
+
+# %%
+mo.ui.tabs({"table": single_select_table, "selection": single_select_table.value})
+
+# %%
+mo.ui.tabs({"table": multi_select_table, "selection": multi_select_table.value})
\ No newline at end of file
diff --git a/generated/examples/ui/tabs.py.ipynb b/generated/examples/ui/tabs.py.ipynb
new file mode 100644
index 0000000..7e1a4d7
--- /dev/null
+++ b/generated/examples/ui/tabs.py.ipynb
@@ -0,0 +1,83 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "Hbol",
+ "metadata": {},
+ "source": [
+ "# Tabs"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "MJUe",
+ "metadata": {},
+ "source": [
+ "Use `mo.ui.tabs` to organize outputs."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "settings = mo.vstack(\n",
+ " [\n",
+ " mo.md(\"Edit User\"),\n",
+ " first := mo.ui.text(label=\"First Name\"),\n",
+ " last := mo.ui.text(label=\"Last Name\"),\n",
+ " ]\n",
+ ")\n",
+ "\n",
+ "organization = mo.vstack(\n",
+ " [\n",
+ " mo.md(\"Edit Organization\"),\n",
+ " org := mo.ui.text(label=\"Organization Name\", value=\"...\"),\n",
+ " employees := mo.ui.number(\n",
+ " label=\"Number of Employees\", start=0, stop=1000\n",
+ " ),\n",
+ " ]\n",
+ ")\n",
+ "\n",
+ "mo.ui.tabs(\n",
+ " {\n",
+ " \"๐งโโ User\": settings,\n",
+ " \"๐ข Organization\": organization,\n",
+ " }\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.md(\n",
+ " f\"\"\"\n",
+ " Welcome **{first.value} {last.value}** to **{org.value}**! You are \n",
+ " employee no. **{employees.value + 1}**.\n",
+ "\n",
+ " #{\"๐\" * (min(employees.value + 1, 1000))} \n",
+ " \"\"\"\n",
+ ") if all([first.value, last.value, org.value]) else None"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/tabs.script.py b/generated/examples/ui/tabs.script.py
new file mode 100644
index 0000000..fc39698
--- /dev/null
+++ b/generated/examples/ui/tabs.script.py
@@ -0,0 +1,47 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+
+# %%
+mo.md("""# Tabs""")
+
+# %%
+mo.md("""Use `mo.ui.tabs` to organize outputs.""")
+
+# %%
+settings = mo.vstack(
+ [
+ mo.md("Edit User"),
+ first := mo.ui.text(label="First Name"),
+ last := mo.ui.text(label="Last Name"),
+ ]
+)
+
+organization = mo.vstack(
+ [
+ mo.md("Edit Organization"),
+ org := mo.ui.text(label="Organization Name", value="..."),
+ employees := mo.ui.number(
+ label="Number of Employees", start=0, stop=1000
+ ),
+ ]
+)
+
+mo.ui.tabs(
+ {
+ "๐งโโ User": settings,
+ "๐ข Organization": organization,
+ }
+)
+
+# %%
+mo.md(
+ f"""
+ Welcome **{first.value} {last.value}** to **{org.value}**! You are
+ employee no. **{employees.value + 1}**.
+
+ #{"๐" * (min(employees.value + 1, 1000))}
+ """
+) if all([first.value, last.value, org.value]) else None
\ No newline at end of file
diff --git a/generated/examples/ui/task_list.py.ipynb b/generated/examples/ui/task_list.py.ipynb
new file mode 100644
index 0000000..81af93d
--- /dev/null
+++ b/generated/examples/ui/task_list.py.ipynb
@@ -0,0 +1,137 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Hbol",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.md(\"# Task List\").left()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "MJUe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "@dataclass\n",
+ "class Task:\n",
+ " name: str\n",
+ " done: bool = False"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vblA",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "get_tasks, set_tasks = mo.state([])\n",
+ "mutation_signal, set_mutation_signal = mo.state(False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bkHC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mutation_signal\n",
+ "\n",
+ "task_entry_box = mo.ui.text(placeholder=\"a task ...\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lEQa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_task():\n",
+ " if task_entry_box.value:\n",
+ " set_tasks(lambda v: v + [Task(task_entry_box.value)])\n",
+ " set_mutation_signal(True)\n",
+ "\n",
+ "\n",
+ "add_task_button = mo.ui.button(\n",
+ " label=\"add task\",\n",
+ " on_change=lambda _: add_task(),\n",
+ ")\n",
+ "\n",
+ "clear_tasks_button = mo.ui.button(\n",
+ " label=\"clear completed tasks\",\n",
+ " on_change=lambda _: set_tasks(\n",
+ " lambda v: [task for task in v if not task.done]\n",
+ " ),\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "PKri",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.hstack(\n",
+ " [task_entry_box, add_task_button, clear_tasks_button], justify=\"start\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "Xref",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "task_list = mo.ui.array(\n",
+ " [mo.ui.checkbox(value=task.done, label=task.name) for task in get_tasks()],\n",
+ " label=\"tasks\",\n",
+ " on_change=lambda v: set_tasks(\n",
+ " [Task(task.name, done=v[i]) for i, task in enumerate(get_tasks())]\n",
+ " ),\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "SFPL",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mo.as_html(task_list) if task_list.value else mo.md(\"No tasks! ๐\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "BYtC",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import marimo as mo"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "RGSE",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from dataclasses import dataclass"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/generated/examples/ui/task_list.script.py b/generated/examples/ui/task_list.script.py
new file mode 100644
index 0000000..36556dd
--- /dev/null
+++ b/generated/examples/ui/task_list.script.py
@@ -0,0 +1,62 @@
+
+__generated_with = "0.9.30"
+
+# %%
+import marimo as mo
+
+# %%
+from dataclasses import dataclass
+
+# %%
+mo.md("# Task List").left()
+
+# %%
+get_tasks, set_tasks = mo.state([])
+mutation_signal, set_mutation_signal = mo.state(False)
+
+# %%
+@dataclass
+class Task:
+ name: str
+ done: bool = False
+
+# %%
+mutation_signal
+
+task_entry_box = mo.ui.text(placeholder="a task ...")
+
+# %%
+task_list = mo.ui.array(
+ [mo.ui.checkbox(value=task.done, label=task.name) for task in get_tasks()],
+ label="tasks",
+ on_change=lambda v: set_tasks(
+ [Task(task.name, done=v[i]) for i, task in enumerate(get_tasks())]
+ ),
+)
+
+# %%
+def add_task():
+ if task_entry_box.value:
+ set_tasks(lambda v: v + [Task(task_entry_box.value)])
+ set_mutation_signal(True)
+
+
+add_task_button = mo.ui.button(
+ label="add task",
+ on_change=lambda _: add_task(),
+)
+
+clear_tasks_button = mo.ui.button(
+ label="clear completed tasks",
+ on_change=lambda _: set_tasks(
+ lambda v: [task for task in v if not task.done]
+ ),
+)
+
+# %%
+mo.as_html(task_list) if task_list.value else mo.md("No tasks! ๐")
+
+# %%
+mo.hstack(
+ [task_entry_box, add_task_button, clear_tasks_button], justify="start"
+)
\ No newline at end of file
diff --git a/public/examples/ui/arrays_and_dicts.py.html b/public/examples/ui/arrays_and_dicts.py.html
new file mode 100644
index 0000000..2b8da34
--- /dev/null
+++ b/public/examples/ui/arrays_and_dicts.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ arrays_and_dicts.py
+
+
+
+
+
+ arrays and dicts
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%20Arrays%20and%20Dictionaries%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20Use%20%60mo.ui.array%60%20and%20%60mo.ui.dictionary%60%20to%20create%20UI%20elements%20that%20wrap%20%0A%20%20%20%20%20%20%20%20other%20elements.%0A%0A%20%20%20%20%20%20%20%20Because%20UI%20elements%20must%20be%20assigned%20to%20global%20variables%2C%20%0A%20%20%20%20%20%20%20%20these%20functions%20are%20required%20when%20the%20set%20of%20elements%20to%20create%20is%20not%0A%20%20%20%20%20%20%20%20known%20until%20runtime.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20create%20%3D%20mo.ui.button(label%3D%22Create%20new%20collections%22)%0A%20%20%20%20return%20(create%2C)%0A%0A%0A%40app.cell%0Adef%20__(create)%3A%0A%20%20%20%20create.center()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22UI%20Elements%20...%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(create%2C%20mo%2C%20random)%3A%0A%20%20%20%20create%0A%0A%20%20%20%20array%20%3D%20mo.ui.array(%0A%20%20%20%20%20%20%20%20%5Bmo.ui.text()%5D%0A%20%20%20%20%20%20%20%20%2B%20%5Bmo.ui.slider(1%2C%2010)%20for%20_%20in%20range(0%2C%20random.randint(2%2C%205))%5D%2C%0A%20%20%20%20)%0A%20%20%20%20dictionary%20%3D%20mo.ui.dictionary(%0A%20%20%20%20%20%20%20%20%7Bstr(i)%3A%20mo.ui.slider(1%2C%2010)%20for%20i%20in%20range(0%2C%20random.randint(2%2C%205))%7D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.hstack(%5Barray%2C%20dictionary%5D%2C%20justify%3D%22space-around%22)%0A%20%20%20%20return%20array%2C%20dictionary%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22...%20and%20their%20values%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(array%2C%20dictionary%2C%20mo)%3A%0A%20%20%20%20mo.hstack(%5Barray.value%2C%20dictionary.value%5D%2C%20justify%3D%22space-around%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20Key%20difference%20between%20marimo%20dict%20and%20standard%20python%20dict%3A%0A%0A%20%20%20%20%20%20%20%20The%20main%20reason%20to%20use%20%60mo.ui.dictionary%60%20is%20for%20reactive%20execution%20%E2%80%94%20when%20you%20interact%20with%20an%20element%20in%20a%20%60mo.ui.dictionary%60%2C%20all%20cells%20that%20reference%20the%20%60mo.ui.dictionary%60%20run%20automatically%2C%20just%20like%20all%20other%20ui%20elements.%20When%20you%20use%20a%20regular%20dictionary%2C%20you%20don't%20get%20this%20reactivity.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(create%2C%20mo)%3A%0A%20%20%20%20create%0A%0A%20%20%20%20slider%20%3D%20mo.ui.slider(1%2C%2010%2C%20show_value%3DTrue)%0A%20%20%20%20text%20%3D%20mo.ui.text()%0A%20%20%20%20date%20%3D%20mo.ui.date()%0A%0A%20%20%20%20mo_d%20%3D%20mo.ui.dictionary(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22slider%22%3A%20slider%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22text%22%3A%20text%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22date%22%3A%20date%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%0A%20%20%20%20py_d%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22slider%22%3A%20slider%2C%0A%20%20%20%20%20%20%20%20%22text%22%3A%20text%2C%0A%20%20%20%20%20%20%20%20%22date%22%3A%20date%2C%0A%20%20%20%20%7D%0A%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.vstack(%5B%22marimo%20dict%22%2C%20mo_d%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.vstack(%5B%22original%20elements%22%2C%20mo.vstack(%5Bslider%2C%20text%2C%20date%5D)%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.vstack(%5B%22python%20dict%22%2C%20py_d%5D)%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20justify%3D%22space-around%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%20date%2C%20mo_d%2C%20py_d%2C%20slider%2C%20text%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo%2C%20mo_d%2C%20py_d)%3A%0A%20%20%20%20mo_d_ref%20%3D%20%7Bk%3A%20mo_d%5Bk%5D.value%20for%20k%20in%20mo_d.value.keys()%7D%0A%20%20%20%20py_d_ref%20%3D%20%7Bk%3A%20py_d%5Bk%5D.value%20for%20k%20in%20py_d.keys()%7D%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.vstack(%5B%22reference%20of%20marimo%20dict%22%2C%20mo_d_ref%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.vstack(%5B%22reference%20of%20python%20dict%22%2C%20py_d_ref%5D)%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20justify%3D%22space-around%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%20mo_d_ref%2C%20py_d_ref%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Notice%20that%20when%20you%20interact%20with%20the%20UI%20elements%20in%20the%20marimo%20dict%2C%20the%20reference%20of%20marimo%20dict%20updates%20automatically.%20However%2C%20when%20you%20interact%20with%20the%20elements%20in%20the%20python%20dict%2C%20you%20need%20to%20manually%20re-run%20the%20cell%20to%20see%20the%20updated%20values.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20random%0A%20%20%20%20return%20mo%2C%20random%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+0f7c05ebb1743397fe4684fdab1bf2e34cf40c99950bc50787a875f0f45c1fe3
+
+
diff --git a/public/examples/ui/batch_and_form.py.html b/public/examples/ui/batch_and_form.py.html
new file mode 100644
index 0000000..0fd2705
--- /dev/null
+++ b/public/examples/ui/batch_and_form.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ batch_and_form.py
+
+
+
+
+
+ batch and form
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%20Batch%20and%20Form%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20Make%20custom%20UI%20elements%20using%20%60batch()%60%2C%20and%20turn%20any%20UI%20element%0A%20%20%20%20%20%20%20%20into%20a%20form%20with%20%60form()%60.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20reset)%3A%0A%20%20%20%20reset%0A%0A%20%20%20%20variables%20%3D%20(%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20Choose%20your%20variable%20values%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7Bx%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7By%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.batch(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dmo.ui.slider(start%3D1%2C%20stop%3D10%2C%20step%3D1%2C%20label%3D%22%24x%20%3D%24%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dmo.ui.slider(start%3D1%2C%20stop%3D10%2C%20step%3D1%2C%20label%3D%22%24y%20%3D%24%22)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.form(show_clear_button%3DTrue%2C%20bordered%3DFalse)%0A%20%20%20%20)%0A%0A%20%20%20%20variables%0A%20%20%20%20return%20(variables%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20reset%2C%20submitted_values%2C%20variables)%3A%0A%20%20%20%20if%20variables.value%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20submitted_values%5B%22x%22%5D.add(variables.value%5B%22x%22%5D)%0A%20%20%20%20%20%20%20%20submitted_values%5B%22y%22%5D.add(variables.value%5B%22y%22%5D)%0A%0A%20%20%20%20x%20%3D%20variables.value%5B%22x%22%5D%20if%20variables.value%20else%20%22%5Cldots%22%0A%20%20%20%20y%20%3D%20variables.value%5B%22y%22%5D%20if%20variables.value%20else%20%22%5Cldots%22%0A%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20At%20the%20moment%2C%0A%20%20%20%20%20%20%20%20%24x%20%3D%20%7Bx%7D%24%20and%20%24y%20%3D%20%7By%7D%24%0A%0A%20%20%20%20%20%20%20%20All%20values%20ever%20assumed%20by%20%24x%24%20and%20%24y%24%20are%0A%0A%20%20%20%20%20%20%20%20%7Bmo.hstack(%5Bmo.tree(submitted_values)%2C%20reset%5D%2C%20align%3D%22center%22%2C%20gap%3D4)%7D%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20).callout()%0A%20%20%20%20return%20x%2C%20y%0A%0A%0A%40app.cell%0Adef%20__(reset)%3A%0A%20%20%20%20reset%0A%0A%20%20%20%20submitted_values%20%3D%20%7B%22x%22%3A%20set()%2C%20%22y%22%3A%20set()%7D%0A%20%20%20%20return%20(submitted_values%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20reset%20%3D%20mo.ui.button(label%3D%22reset%20history%22)%0A%20%20%20%20return%20(reset%2C)%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+bd665c51880ec864332075cc4f8830fd6f39773e917c21b4bdde5ec5dd662b25
+
+
diff --git a/public/examples/ui/data_explorer.py.html b/public/examples/ui/data_explorer.py.html
new file mode 100644
index 0000000..3174b46
--- /dev/null
+++ b/public/examples/ui/data_explorer.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ data_explorer.py
+
+
+
+
+
+ data explorer
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App(width%3D%22full%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%20Data%20Explorer%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20sample%20%3D%20%22https%3A%2F%2Fgithub.com%2Fvega%2Fvega%2Fblob%2Fmain%2Fdocs%2Fdata%2Fstocks.csv%22%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20This%20notebook%20lets%20you%20upload%20a%20CSV%20and%20plot%20its%20columns.%0A%0A%20%20%20%20%20%20%20%20You%20can%20download%20a%20%3Ca%20href%3D%22%7Bsample%7D%22%20target%3D%22_blank%22%3Esample%20CSV%3C%2Fa%3E%20if%20you'd%20like.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%20(sample%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo%2C%20uploaded_file)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20%7Bmo.hstack(%5Bmo.md(%22**Upload%20a%20CSV.**%22)%5D%2C%20justify%3D%22center%22)%7D%0A%0A%20%20%20%20%20%20%20%20%7Buploaded_file%7D%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(io%2C%20mo%2C%20pd%2C%20uploaded_file)%3A%0A%20%20%20%20mo.stop(not%20uploaded_file.name())%0A%20%20%20%20df%20%3D%20pd.read_csv(io.StringIO(uploaded_file.contents().decode()))%0A%20%20%20%20return%20(df%2C)%0A%0A%0A%40app.cell%0Adef%20__(df%2C%20mo)%3A%0A%20%20%20%20mo.ui.table(df%2C%20page_size%3D5%2C%20selection%3DNone)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(df%2C%20mo)%3A%0A%20%20%20%20plot_type%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20%5B%22line%22%2C%20%22hist%22%5D%2C%20value%3D%22line%22%2C%20label%3D%22Choose%20a%20plot%20type%3A%20%22%0A%20%20%20%20)%0A%0A%20%20%20%20x_column%20%3D%20mo.ui.dropdown(df.columns%2C%20label%3D%22Choose%20x-axis%3A%20%22)%0A%20%20%20%20y_column%20%3D%20mo.ui.dropdown(df.columns%2C%20label%3D%22Choose%20y-axis%3A%20%22)%0A%20%20%20%20color_column%20%3D%20mo.ui.dropdown(df.columns%2C%20label%3D%22Choose%20color-axis%3A%20%22)%0A%20%20%20%20return%20color_column%2C%20plot_type%2C%20x_column%2C%20y_column%0A%0A%0A%40app.cell%0Adef%20__(color_column%2C%20mo%2C%20plot_type%2C%20x_column%2C%20y_column)%3A%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5Bx_column%2C%20y_column%2C%20color_column%2C%20plot_type%5D%2C%20justify%3D%22space-around%22%0A%20%20%20%20).callout(kind%3D%22warn%22%20if%20not%20x_column.value%20else%20%22neutral%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(alt%2C%20color_column%2C%20df%2C%20mo%2C%20plot_type%2C%20x_column%2C%20y_column)%3A%0A%20%20%20%20mo.stop(not%20x_column.value)%0A%0A%0A%20%20%20%20def%20plot(x_column%2C%20y_column%2C%20color_column)%3A%0A%20%20%20%20%20%20%20%20y_column%20%3D%20y_column%20or%20%22count()%22%0A%20%20%20%20%20%20%20%20title%20%3D%20f%22%7By_column%7D%20by%20%7Bx_column%7D%22%0A%20%20%20%20%20%20%20%20encoding%20%3D%20%7B%22x%22%3A%20x_column%2C%20%22y%22%3A%20y_column%7D%0A%20%20%20%20%20%20%20%20if%20color_column%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20encoding%5B%22color%22%5D%20%3D%20color_column%0A%20%20%20%20%20%20%20%20if%20plot_type.value%20%3D%3D%20%22line%22%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20chart%20%3D%20alt.Chart(df).mark_line()%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20chart%20%3D%20alt.Chart(df).mark_bar().encode(x%3Dalt.X(x_column%2C%20bin%3DTrue))%0A%20%20%20%20%20%20%20%20return%20chart.encode(**encoding).properties(title%3Dtitle%2C%20width%3D%22container%22)%0A%0A%0A%20%20%20%20plot(x_column.value%2C%20y_column.value%2C%20color_column.value)%0A%20%20%20%20return%20(plot%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20uploaded_file%20%3D%20mo.ui.file(filetypes%3D%5B%22.csv%22%5D%2C%20kind%3D%22area%22)%0A%20%20%20%20return%20(uploaded_file%2C)%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20altair%20as%20alt%0A%0A%0A%20%20%20%20import%20io%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20return%20alt%2C%20io%2C%20mo%2C%20pd%2C%20plt%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+c68d44146d3677f0696e01bf94a8e61a00331338c87e648b5a1d83b95bc41206
+
+
diff --git a/public/examples/ui/filterable_table.py.html b/public/examples/ui/filterable_table.py.html
new file mode 100644
index 0000000..5d254fc
--- /dev/null
+++ b/public/examples/ui/filterable_table.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ filterable_table.py
+
+
+
+
+
+ filterable table
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%20Filterable%20DataFrame%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(data_url%2C%20pd)%3A%0A%20%20%20%20%23%20Read%20the%20csv%0A%20%20%20%20df%20%3D%20pd.read_json(data_url(%22cars.json%22))%0A%20%20%20%20return%20(df%2C)%0A%0A%0A%40app.cell%0Adef%20__(df)%3A%0A%20%20%20%20%23%20Create%20options%20for%20select%20widgets%0A%20%20%20%20manufacturer_options%20%3D%20df%5B%22Name%22%5D.str.split().str%5B0%5D.unique()%0A%20%20%20%20manufacturer_options.sort()%0A%20%20%20%20cylinder_options%20%3D%20df%5B%22Cylinders%22%5D.unique().astype(str)%0A%20%20%20%20cylinder_options.sort()%0A%20%20%20%20return%20cylinder_options%2C%20manufacturer_options%0A%0A%0A%40app.cell%0Adef%20__(cylinder_options%2C%20df%2C%20manufacturer_options%2C%20mo)%3A%0A%20%20%20%20%23%20Create%20the%20filters%0A%20%20%20%20manufacturer%20%3D%20mo.ui.dropdown(manufacturer_options%2C%20label%3D%22Manufacturer%22)%0A%20%20%20%20cylinders%20%3D%20mo.ui.dropdown(cylinder_options%2C%20label%3D%22Cylinders%22)%0A%0A%20%20%20%20horse_power%20%3D%20mo.ui.range_slider.from_series(%0A%20%20%20%20%20%20%20%20df%5B%22Horsepower%22%5D%2C%0A%20%20%20%20%20%20%20%20show_value%3DTrue%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.hstack(%5Bmanufacturer%2C%20horse_power%2C%20cylinders%5D%2C%20gap%3D3).left()%0A%20%20%20%20return%20cylinders%2C%20horse_power%2C%20manufacturer%0A%0A%0A%40app.cell%0Adef%20__(df%2C%20filter_df)%3A%0A%20%20%20%20filter_df(df)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(cylinders%2C%20horse_power%2C%20manufacturer)%3A%0A%20%20%20%20def%20filter_df(df)%3A%0A%20%20%20%20%20%20%20%20filtered_df%20%3D%20df%0A%20%20%20%20%20%20%20%20if%20manufacturer.value%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20filtered_df%20%3D%20filtered_df%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20filtered_df%5B%22Name%22%5D.str.contains(manufacturer.value%2C%20case%3DFalse)%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20if%20cylinders.value%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20filtered_df%20%3D%20filtered_df%5Bfiltered_df%5B%22Cylinders%22%5D%20%3D%3D%20cylinders.value%5D%0A%20%20%20%20%20%20%20%20if%20horse_power.value%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20left%2C%20right%20%3D%20horse_power.value%0A%20%20%20%20%20%20%20%20%20%20%20%20filtered_df%20%3D%20filtered_df%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(filtered_df%5B%22Horsepower%22%5D%20%3E%3D%20left)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%26%20(filtered_df%5B%22Horsepower%22%5D%20%3C%3D%20right)%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20return%20filtered_df%0A%20%20%20%20return%20(filter_df%2C)%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20def%20data_url(file)%3A%0A%20%20%20%20%20%20%20%20return%20f%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fvega-datasets%40v1.29.0%2Fdata%2F%7Bfile%7D%22%0A%20%20%20%20return%20(data_url%2C)%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20return%20mo%2C%20pd%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+8ed29935ea9619ee460098d33b4da3c7b07dcef17b5572f21e9351bffa86b859
+
+
diff --git a/public/examples/ui/inputs.py.html b/public/examples/ui/inputs.py.html
new file mode 100644
index 0000000..7494620
--- /dev/null
+++ b/public/examples/ui/inputs.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ inputs.py
+
+
+
+
+
+ inputs
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%20Inputs%0A%0A%20%20%20%20%20%20%20%20There%20are%20many%20way%20that%20a%20user%20can%20input%20with%20your%20notebook%2C%20such%20as%20text%20boxes%2C%20sliders%2C%20dates%2C%20and%20more.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Text%20boxes%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20username%20%3A%3D%20mo.ui.text(label%3D%22Username%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20email%20%3A%3D%20mo.ui.text(label%3D%22Email%22%2C%20kind%3D%22email%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.text(label%3D%22Password%22%2C%20kind%3D%22password%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%20email%2C%20username%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20username)%3A%0A%20%20%20%20mo.stop(not%20username.value%2C%20mo.md(%22What%20is%20your%20name%3F%22))%0A%0A%20%20%20%20mo.md(f%22%F0%9F%91%8B%20Hello%20%7Busername.value%7D%2C%20nice%20to%20meet%20you!%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.ui.text_area(%0A%20%20%20%20%20%20%20%20label%3D%22A%20space%20for%20your%20thoughts%22%2C%20full_width%3DTrue%2C%20max_length%3D1000%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.ui.number(label%3D%22What%20is%20your%20favorite%20number%3F%22%2C%20start%3D0%2C%20stop%3D10)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Sliders%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20slider%20%3D%20mo.ui.slider(0%2C%20100%2C%20value%3D50%2C%20label%3D%22Basic%20slider%22%2C%20show_value%3DTrue)%0A%20%20%20%20range_slider%20%3D%20mo.ui.range_slider(%0A%20%20%20%20%20%20%20%200%2C%20100%2C%20value%3D(30%2C%2070)%2C%20label%3D%22Range%20slider%22%2C%20show_value%3DTrue%0A%20%20%20%20)%0A%20%20%20%20custom_steps%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20steps%3D%5B1%2C%2010%2C%20100%2C%201000%5D%2C%20value%3D10%2C%20label%3D%22Custom%20steps%22%2C%20show_value%3DTrue%0A%20%20%20%20)%0A%20%20%20%20vertical%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%200%2C%20100%2C%20value%3D50%2C%20label%3D%22Vertical%20slider%22%2C%20orientation%3D%22vertical%22%0A%20%20%20%20)%0A%20%20%20%20mo.vstack(%5Bslider%2C%20range_slider%2C%20custom_steps%2C%20vertical%5D).center()%0A%20%20%20%20return%20custom_steps%2C%20range_slider%2C%20slider%2C%20vertical%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Checkboxes%20and%20Radios%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20COLORS%20%3D%20%5B%22red%22%2C%20%22green%22%2C%20%22blue%22%5D%0A%20%20%20%20colors%20%3D%20mo.ui.array(%0A%20%20%20%20%20%20%20%20%5Bmo.ui.checkbox(label%3Dcolor)%20for%20color%20in%20COLORS%5D%2C%0A%20%20%20%20)%0A%0A%20%20%20%20shape%20%3D%20mo.ui.radio(%0A%20%20%20%20%20%20%20%20%5B%22circle%22%2C%20%22square%22%2C%20%22triangle%22%5D%2C%20inline%3DTrue%2C%20value%3D%22square%22%0A%20%20%20%20)%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20Let's%20build%20something%3A%0A%0A%20%20%20%20**Pick%20a%20shape%3A**%0A%0A%20%20%20%20%7Bshape%7D%0A%0A%20%20%20%20**Pick%20a%20color%3A**%0A%0A%20%20%20%20%7Bcolors.hstack().left()%7D%0A%20%20%20%20%22%22%22).center()%0A%20%20%20%20return%20COLORS%2C%20colors%2C%20shape%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(COLORS%2C%20colors%2C%20mo%2C%20shape)%3A%0A%20%20%20%20selected_colors%20%3D%20%5Bcolor%20for%20i%2C%20color%20in%20enumerate(COLORS)%20if%20colors.value%5Bi%5D%5D%0A%0A%0A%20%20%20%20def%20draw_shape(shape%2C%20colors)%3A%0A%20%20%20%20%20%20%20%20if%20not%20colors%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%22%22%0A%0A%20%20%20%20%20%20%20%20gradient%20%3D%20%22%22%0A%20%20%20%20%20%20%20%20if%20isinstance(colors%2C%20list)%20and%20len(colors)%20%3E%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20gradient_id%20%3D%20f%22grad%7Bhash(tuple(colors))%20%25%201000%7D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20stops%20%3D%20%22%22.join(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f'%3Cstop%20offset%3D%22%7Bi%2F(len(colors)-1)%7D%22%20style%3D%22stop-color%3A%7Bcolor%7D%3B%22%20%2F%3E'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20i%2C%20color%20in%20enumerate(colors)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20gradient%20%3D%20f'%3Cdefs%3E%3ClinearGradient%20id%3D%22%7Bgradient_id%7D%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%22100%25%22%20y2%3D%22100%25%22%3E%7Bstops%7D%3C%2FlinearGradient%3E%3C%2Fdefs%3E'%0A%20%20%20%20%20%20%20%20%20%20%20%20fill_color%20%3D%20f%22url(%23%7Bgradient_id%7D)%22%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20fill_color%20%3D%20colors%20if%20isinstance(colors%2C%20str)%20else%20colors%5B0%5D%0A%0A%20%20%20%20%20%20%20%20if%20shape%20%3D%3D%20%22circle%22%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20html%20%3D%20f'%3Csvg%20width%3D%22100%22%20height%3D%22100%22%3E%7Bgradient%7D%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2240%22%20stroke%3D%22black%22%20stroke-width%3D%223%22%20fill%3D%22%7Bfill_color%7D%22%20%2F%3E%3C%2Fsvg%3E'%0A%20%20%20%20%20%20%20%20elif%20shape%20%3D%3D%20%22square%22%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20html%20%3D%20f'%3Csvg%20width%3D%22100%22%20height%3D%22100%22%3E%7Bgradient%7D%3Crect%20width%3D%2280%22%20height%3D%2280%22%20x%3D%2210%22%20y%3D%2210%22%20stroke%3D%22black%22%20stroke-width%3D%223%22%20fill%3D%22%7Bfill_color%7D%22%20%2F%3E%3C%2Fsvg%3E'%0A%20%20%20%20%20%20%20%20elif%20shape%20%3D%3D%20%22triangle%22%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20html%20%3D%20f'%3Csvg%20width%3D%22100%22%20height%3D%22100%22%3E%7Bgradient%7D%3Cpolygon%20points%3D%2250%2C10%2090%2C90%2010%2C90%22%20stroke%3D%22black%22%20stroke-width%3D%223%22%20fill%3D%22%7Bfill_color%7D%22%20%2F%3E%3C%2Fsvg%3E'%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20html%20%3D%20%22Shape%20not%20recognized%22%0A%20%20%20%20%20%20%20%20return%20mo.Html(html)%0A%0A%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20A%20%7B%22%2F%22.join(selected_colors)%7D%20%7Bshape.value%7D%3A%0A%20%20%20%20%7Bdraw_shape(shape.value%2C%20selected_colors)%7D%0A%20%20%20%20%22%22%22).center()%0A%20%20%20%20return%20draw_shape%2C%20selected_colors%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%23%20Dates%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20import%20datetime%0A%0A%20%20%20%20start_date%20%3D%20mo.ui.date(%0A%20%20%20%20%20%20%20%20label%3D%22Start%20date%22%2C%0A%20%20%20%20%20%20%20%20start%3Ddatetime.date(2020%2C%201%2C%201)%2C%0A%20%20%20%20%20%20%20%20stop%3Ddatetime.date(2020%2C%2012%2C%2031)%2C%0A%20%20%20%20)%0A%20%20%20%20end_date%20%3D%20mo.ui.date(%0A%20%20%20%20%20%20%20%20label%3D%22End%20date%22%2C%0A%20%20%20%20%20%20%20%20start%3Ddatetime.date(2020%2C%201%2C%201)%2C%0A%20%20%20%20%20%20%20%20stop%3Ddatetime.date(2020%2C%2012%2C%2031)%2C%0A%20%20%20%20)%0A%20%20%20%20return%20datetime%2C%20end_date%2C%20start_date%0A%0A%0A%40app.cell%0Adef%20__(end_date%2C%20mo%2C%20start_date)%3A%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.hstack(%5Bstart_date%2C%20%22%E2%9E%A1%EF%B8%8F%22%2C%20end_date%5D).left()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22From%20%7Bstart_date.value%7D%20to%20%7Bend_date.value%7D%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%23%20Dropdowns%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20single%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20%5B%22Option%201%22%2C%20%22Option%202%22%2C%20%22Option%203%22%2C%20%22Option%204%22%2C%20%22Option%205%22%5D%2C%0A%20%20%20%20%20%20%20%20label%3D%22Single%20select%22%2C%0A%20%20%20%20)%0A%20%20%20%20multi%20%3D%20mo.ui.multiselect(%0A%20%20%20%20%20%20%20%20%5B%22Option%201%22%2C%20%22Option%202%22%2C%20%22Option%203%22%2C%20%22Option%204%22%2C%20%22Option%205%22%5D%2C%0A%20%20%20%20%20%20%20%20label%3D%22Multi%20select%22%2C%0A%20%20%20%20%20%20%20%20value%3D%5B%22Option%201%22%2C%20%22Option%202%22%5D%2C%0A%20%20%20%20)%0A%20%20%20%20mo.hstack(%5Bsingle%2C%20multi%5D)%0A%20%20%20%20return%20multi%2C%20single%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+f28a83e86fd887f1ed846219237b7057be643b9a47f4fc267244dbf72daa3194
+
+
diff --git a/public/examples/ui/layout.py.html b/public/examples/ui/layout.py.html
new file mode 100644
index 0000000..e5bb9dc
--- /dev/null
+++ b/public/examples/ui/layout.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ layout.py
+
+
+
+
+
+ layout
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%20Stacks%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22Use%20%60mo.hstack%60%20and%20%60mo.vstack%60%20to%20layout%20outputs%20in%20rows%20and%20columns.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20align%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20label%3D%22Align%22%2C%20options%3D%5B%22start%22%2C%20%22end%22%2C%20%22center%22%2C%20%22stretch%22%5D%0A%20%20%20%20)%0A%20%20%20%20justify%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20label%3D%22Justify%22%2C%0A%20%20%20%20%20%20%20%20options%3D%5B%22start%22%2C%20%22center%22%2C%20%22end%22%2C%20%22space-between%22%2C%20%22space-around%22%5D%2C%0A%20%20%20%20)%0A%20%20%20%20gap%20%3D%20mo.ui.number(label%3D%22Gap%22%2C%20start%3D0%2C%20stop%3D100%2C%20value%3D1)%0A%20%20%20%20size%20%3D%20mo.ui.slider(label%3D%22Size%22%2C%20start%3D60%2C%20stop%3D500)%0A%20%20%20%20wrap%20%3D%20mo.ui.checkbox(label%3D%22Wrap%22)%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20**Stack%20parameters**%0A%0A%20%20%20%20%20%20%20%20%7Bmo.hstack(%5Balign%2C%20justify%2C%20gap%2C%20wrap%5D%2C%20gap%3D0.25)%7D%0A%0A%20%20%20%20%20%20%20%20**Boxes%20%7Bsize%7D**%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%20align%2C%20gap%2C%20justify%2C%20size%2C%20wrap%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%23%20Horizontal%20Stack%3A%20%60hstack%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(align%2C%20boxes%2C%20gap%2C%20justify%2C%20mo%2C%20wrap)%3A%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20boxes%2C%0A%20%20%20%20%20%20%20%20align%3Dalign.value%2C%0A%20%20%20%20%20%20%20%20justify%3Djustify.value%2C%0A%20%20%20%20%20%20%20%20gap%3Dgap.value%2C%0A%20%20%20%20%20%20%20%20wrap%3Dwrap.value%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%23%20Vertical%20Stack%3A%20%60vstack%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(align%2C%20boxes%2C%20gap%2C%20mo)%3A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20boxes%2C%0A%20%20%20%20%20%20%20%20align%3Dalign.value%2C%0A%20%20%20%20%20%20%20%20gap%3Dgap.value%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20size)%3A%0A%20%20%20%20def%20create_box(num)%3A%0A%20%20%20%20%20%20%20%20box_size%20%3D%20size.value%20%2B%20num%20*%2010%0A%20%20%20%20%20%20%20%20return%20mo.Html(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%3Cdiv%20style%3D'min-width%3A%20%7Bbox_size%7Dpx%3B%20min-height%3A%20%7Bbox_size%7Dpx%3B%20background-color%3A%20orange%3B%20text-align%3A%20center%3B%20line-height%3A%20%7Bbox_size%7Dpx'%3E%7Bstr(num)%7D%3C%2Fdiv%3E%22%0A%20%20%20%20%20%20%20%20)%0A%0A%0A%20%20%20%20boxes%20%3D%20%5Bcreate_box(i)%20for%20i%20in%20range(1%2C%205)%5D%0A%20%20%20%20return%20boxes%2C%20create_box%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+2ea7efa585004e48de7a867a1936efcc917871028ed5c5359dc136fdbd9de046
+
+
diff --git a/public/examples/ui/mermaid.py.html b/public/examples/ui/mermaid.py.html
new file mode 100644
index 0000000..55f8b49
--- /dev/null
+++ b/public/examples/ui/mermaid.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mermaid.py
+
+
+
+
+
+ mermaid
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.mermaid(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20graph%20TD%0A%20%20%20%20%20%20%20%20A%5BEnter%20Chart%20Definition%5D%20--%3E%20B(Preview)%0A%20%20%20%20%20%20%20%20B%20--%3E%20C%7Bdecide%7D%0A%20%20%20%20%20%20%20%20C%20--%3E%20D%5BKeep%5D%0A%20%20%20%20%20%20%20%20C%20--%3E%20E%5BEdit%20Definition%5D%0A%20%20%20%20%20%20%20%20E%20--%3E%20B%0A%20%20%20%20%20%20%20%20D%20--%3E%20F%5BSave%20Image%20and%20Code%5D%0A%20%20%20%20%20%20%20%20F%20--%3E%20B%0A%20%20%20%20%22%22%22%0A%20%20%20%20).center()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20graph%20%3D%20mo.ui.code_editor(%0A%20%20%20%20%20%20%20%20value%3D%22%22%22sequenceDiagram%0A%20%20%20%20%20%20%20%20Alice-%3E%3EJohn%3A%20Hello%20John%2C%20how%20are%20you%3F%0A%20%20%20%20%20%20%20%20John--%3E%3EAlice%3A%20Great!%0A%20%20%20%20%20%20%20%20Alice-)John%3A%20See%20you%20later!%22%22%22%2C%0A%20%20%20%20%20%20%20%20language%3D%22mermaid%22%2C%0A%20%20%20%20%20%20%20%20label%3D%22Mermaid%20editor%22%2C%0A%20%20%20%20)%0A%20%20%20%20graph%0A%20%20%20%20return%20(graph%2C)%0A%0A%0A%40app.cell%0Adef%20__(graph%2C%20mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20You%20can%20render%20mermaid%20directly%20inside%20%60mo.md%60.%20Using%0A%0A%20%20%20%20%20%20%20%20%60mo.mermaid()%60%0A%0A%20%20%20%20%20%20%20%20%7Bmo.mermaid(graph.value)%7D%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+4f536b84716767e550bc8731ad2f8299734482c6d1eabfd06c62979f49a85aff
+
+
diff --git a/public/examples/ui/reactive_plots.py.html b/public/examples/ui/reactive_plots.py.html
new file mode 100644
index 0000000..03b32a7
--- /dev/null
+++ b/public/examples/ui/reactive_plots.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reactive_plots.py
+
+
+
+
+
+ reactive plots
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App(width%3D%22full%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%20Welcome%20to%20marimo!%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(bars%2C%20mo%2C%20scatter)%3A%0A%20%20%20%20chart%20%3D%20mo.ui.altair_chart(scatter%20%26%20bars)%0A%20%20%20%20chart%0A%20%20%20%20return%20(chart%2C)%0A%0A%0A%40app.cell%0Adef%20__(chart%2C%20mo)%3A%0A%20%20%20%20(filtered_data%20%3A%3D%20mo.ui.table(chart.value))%0A%20%20%20%20return%20(filtered_data%2C)%0A%0A%0A%40app.cell%0Adef%20__(alt%2C%20filtered_data%2C%20mo)%3A%0A%20%20%20%20mo.stop(not%20len(filtered_data.value))%0A%20%20%20%20mpg_hist%20%3D%20mo.ui.altair_chart(%0A%20%20%20%20%20%20%20%20alt.Chart(filtered_data.value)%0A%20%20%20%20%20%20%20%20.mark_bar()%0A%20%20%20%20%20%20%20%20.encode(alt.X(%22Miles_per_Gallon%3AQ%22%2C%20bin%3DTrue)%2C%20y%3D%22count()%22)%0A%20%20%20%20)%0A%20%20%20%20horsepower_hist%20%3D%20mo.ui.altair_chart(%0A%20%20%20%20%20%20%20%20alt.Chart(filtered_data.value)%0A%20%20%20%20%20%20%20%20.mark_bar()%0A%20%20%20%20%20%20%20%20.encode(alt.X(%22Horsepower%3AQ%22%2C%20bin%3DTrue)%2C%20y%3D%22count()%22)%0A%20%20%20%20)%0A%20%20%20%20mo.hstack(%5Bmpg_hist%2C%20horsepower_hist%5D%2C%20justify%3D%22space-around%22%2C%20widths%3D%22equal%22)%0A%20%20%20%20return%20horsepower_hist%2C%20mpg_hist%0A%0A%0A%40app.cell%0Adef%20__(alt%2C%20data)%3A%0A%20%20%20%20cars%20%3D%20data.cars()%0A%20%20%20%20brush%20%3D%20alt.selection_interval()%0A%20%20%20%20scatter%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(cars)%0A%20%20%20%20%20%20%20%20.mark_point()%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3D%22Horsepower%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D%22Miles_per_Gallon%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22Origin%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.add_params(brush)%0A%20%20%20%20)%0A%20%20%20%20bars%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(cars)%0A%20%20%20%20%20%20%20%20.mark_bar()%0A%20%20%20%20%20%20%20%20.encode(y%3D%22Origin%3AN%22%2C%20color%3D%22Origin%3AN%22%2C%20x%3D%22count(Origin)%3AQ%22)%0A%20%20%20%20%20%20%20%20.transform_filter(brush)%0A%20%20%20%20)%0A%20%20%20%20return%20bars%2C%20brush%2C%20cars%2C%20scatter%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20altair%20as%20alt%0A%20%20%20%20from%20vega_datasets%20import%20data%0A%20%20%20%20return%20alt%2C%20data%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+1e3833036a1f6276edceaa8146b277e0b59829ca65d8c4646f91292c2cb07f03
+
+
diff --git a/public/examples/ui/refresh.py.html b/public/examples/ui/refresh.py.html
new file mode 100644
index 0000000..3d4e182
--- /dev/null
+++ b/public/examples/ui/refresh.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ refresh.py
+
+
+
+
+
+ refresh
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App(width%3D%22full%22)%0A%0A%0A%40app.cell%0Adef%20__(%0A%20%20%20%20chart%2C%0A%20%20%20%20iss_df%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20n_points_slider%2C%0A%20%20%20%20refresh_interval_slider%2C%0A%20%20%20%20refresher%2C%0A)%3A%0A%20%20%20%20mo.hstack(%5B%0A%20%20%20%20%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%20Settings%20%7C%20%5B%60marimo.ui.slider%60%5D(https%3A%2F%2Fdocs.marimo.io%2Fapi%2Finputs%2Fslider.html)%2C%20%5B%60marimo.ui.refresh%60%5D(https%3A%2F%2Fdocs.marimo.io%2Frecipes.html%23run-a-cell-on-a-timer)%5Cn---%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20refresh_interval_slider%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20n_points_slider%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20refresher%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%20ISS%20Positions%20%7C%20%5B%60marimo.ui.altair_chart%60%5D(https%3A%2F%2Fdocs.marimo.io%2Fapi%2Fplotting.html%23marimo.ui.altair_chart)%5Cn---%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.as_html(chart).style(%7B%22width%22%3A%20%22700px%22%7D)%0A%20%20%20%20%20%20%20%20%5D%2C%20align%3D%22center%22)%2C%0A%20%20%20%20%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22%23%23%20Data%20%7C%20%5B%60marimo.as_html%60%5D(https%3A%2F%2Fdocs.marimo.io%2Fapi%2Fhtml.html)%60(pd.DataFrame)%60%5Cn---%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.as_html(iss_df)%0A%20%20%20%20%20%20%20%20%5D)%0A%20%20%20%20%5D%2C%20justify%3D%22center%22%2C%20wrap%3DTrue%2C%20gap%3D3)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(alt%2C%20get_iss_positions%2C%20sphere%2C%20world)%3A%0A%20%20%20%20hover%3Dalt.selection_point(on%3D%22mouseover%22%2C%20clear%3D%22mouseout%22)%0A%0A%20%20%20%20%23%20iss%20positions%0A%20%20%20%20iss_df%20%3D%20get_iss_positions()%0A%20%20%20%20iss%20%3D%20alt.Chart(iss_df%5B%5B'longitude'%2C'latitude'%2C'timestamp'%5D%5D).mark_circle(%0A%20%20%20%20%20%20%20%20stroke%3D'black'%2C%20size%3D100%2C%0A%20%20%20%20).encode(%0A%20%20%20%20%20%20%20%20longitude%3Dalt.Longitude('longitude%3AQ')%2C%0A%20%20%20%20%20%20%20%20latitude%3D'latitude%3AQ'%2C%0A%20%20%20%20%20%20%20%20fill%3Dalt.Fill('timestamp%3AQ'%2C%20scale%3Dalt.Scale(scheme%3D'purples')%2C%20legend%3DNone)%2C%0A%20%20%20%20%20%20%20%20strokeWidth%3Dalt.condition(hover%2C%20alt.value(3%2C%20empty%3DFalse)%2C%20alt.value(0))%2C%0A%20%20%20%20%20%20%20%20tooltip%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip('longitude%3AQ'%2C%20title%3D'Longitude'%2C%20format%3D'.4f')%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip('latitude%3AQ'%2C%20title%3D'Latitude'%2C%20format%3D'.4f')%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alt.Tooltip('timestamp%3AT'%2C%20title%3D'Timestamp'%2C%20format%3D'%25Y-%25m-%25d%20%25H%3A%25M%3A%25S')%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20).add_params(hover)%0A%0A%20%20%20%20chart%20%3D%20alt.layer(sphere%2C%20world%2C%20iss).project(type%3D%22naturalEarth1%22).properties(width%3D640%2C%20title%3D%22%22)%0A%20%20%20%20return%20chart%2C%20hover%2C%20iss%2C%20iss_df%0A%0A%0A%40app.cell%0Adef%20__(alt%2C%20data)%3A%0A%20%20%20%20%23%20load%20geo%20data%20from%20Vega%20Datasets%0A%20%20%20%20countries%20%3D%20alt.topo_feature(data.world_110m.url%2C%20'countries')%0A%0A%20%20%20%20%23%20world%20base%0A%20%20%20%20sphere%20%3D%20alt.Chart(alt.sphere()).mark_geoshape(%0A%20%20%20%20%20%20%20%20fill%3D%22aliceblue%22%2C%20stroke%3D%22black%22%2C%20strokeWidth%3D1.5%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20world%20map%0A%20%20%20%20world%20%3D%20alt.Chart(countries).mark_geoshape(%0A%20%20%20%20%20%20%20%20fill%3D%22mintcream%22%2C%20stroke%3D%22black%22%2C%20strokeWidth%3D0.35%0A%20%20%20%20)%0A%20%20%20%20return%20countries%2C%20sphere%2C%20world%0A%0A%0A%40app.cell%0Adef%20__(%0A%20%20%20%20n_points_slider%2C%0A%20%20%20%20pd%2C%0A%20%20%20%20refresh_interval_slider%2C%0A%20%20%20%20refresher%2C%0A%20%20%20%20requests%2C%0A%20%20%20%20time%2C%0A)%3A%0A%20%20%20%20def%20get_iss_positions(refresher%3Drefresher)%3A%0A%20%20%20%20%20%20%20%20refresher%0A%20%20%20%20%20%20%20%20timepoints%20%3D%20%5Bint(time())%5D%0A%20%20%20%20%20%20%20%20while%20len(timepoints)%20%3C%3D%20n_points_slider.value%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20timepoints.append(timepoints%5B-1%5D%20-%20refresh_interval_slider.value)%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20timepoints.pop(0)%0A%20%20%20%20%20%20%20%20timepoints_str%20%3D%20str(timepoints)%5B1%3A-1%5D.replace(%22%20%22%2C%20%22%22)%0A%20%20%20%20%20%20%20%20iss_url%20%3D%20f%22https%3A%2F%2Fapi.wheretheiss.at%2Fv1%2Fsatellites%2F25544%2Fpositions%3Ftimestamps%3D%7Btimepoints_str%7D%22%0A%20%20%20%20%20%20%20%20response%20%3D%20requests.get(iss_url)%0A%20%20%20%20%20%20%20%20df%20%3D%20pd.DataFrame(response.json())%0A%20%20%20%20%20%20%20%20df%5B'timestamp'%5D%20%3D%20pd.to_datetime(df.timestamp%2C%20unit%3D's')%0A%20%20%20%20%20%20%20%20return%20df%5B%5B'timestamp'%2C'latitude'%2C'longitude'%2C'altitude'%2C'velocity'%2C'visibility'%5D%5D%0A%20%20%20%20return%20(get_iss_positions%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20refresh_interval_slider)%3A%0A%20%20%20%20refresher%20%3D%20mo.ui.refresh(default_interval%3Df%22%7Brefresh_interval_slider.value%7Ds%22)%0A%20%20%20%20return%20(refresher%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20refresh_interval_slider%20%3D%20mo.ui.slider(start%3D5%2C%20stop%3D60%2C%20step%3D1%2C%20value%3D10%2C%20label%3D%22refresh%20interval%20(default%20%3D%2010%20sec)%22)%0A%20%20%20%20n_points_slider%20%3D%20mo.ui.slider(start%3D5%2C%20stop%3D30%2C%20step%3D1%2C%20value%3D15%2C%20label%3D%22number%20of%20points%20(default%20%3D%2015)%22)%0A%20%20%20%20return%20n_points_slider%2C%20refresh_interval_slider%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20altair%20as%20alt%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20requests%0A%20%20%20%20from%20time%20import%20time%0A%20%20%20%20from%20vega_datasets%20import%20data%0A%0A%20%20%20%20pd.options.display.max_rows%20%3D%2030%0A%20%20%20%20return%20alt%2C%20data%2C%20mo%2C%20pd%2C%20requests%2C%20time%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+e9f6d132807713eaa3a9ed9f421babd77b4a2b9fec8b5eb9ce8bbf200bec9703
+
+
diff --git a/public/examples/ui/table.py.html b/public/examples/ui/table.py.html
new file mode 100644
index 0000000..17a71f8
--- /dev/null
+++ b/public/examples/ui/table.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ table.py
+
+
+
+
+
+ table
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%23%20Tables%0A%0A%20%20%20%20%20%20%20%20%3E%20%E2%80%9CSometimes%20I%E2%80%99ll%20start%20a%20sentence%20and%20I%20don%E2%80%99t%20even%20know%20where%20it%E2%80%99s%20going.%20I%20just%20hope%20I%20find%20it%20along%20the%20way.%E2%80%9D%0A%20%20%20%20%20%20%20%20%E2%80%94%20Michael%20Scott%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22_Create%20rich%20tables%20with%20selectable%20rows%20using_%20%60mo.ui.table%60.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22**Single%20selection.**%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20office_characters)%3A%0A%20%20%20%20single_select_table%20%3D%20mo.ui.table(%0A%20%20%20%20%20%20%20%20office_characters%2C%0A%20%20%20%20%20%20%20%20selection%3D%22single%22%2C%0A%20%20%20%20%20%20%20%20pagination%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(single_select_table%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20single_select_table)%3A%0A%20%20%20%20mo.ui.tabs(%7B%22table%22%3A%20single_select_table%2C%20%22selection%22%3A%20single_select_table.value%7D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22**Multi-selection.**%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20office_characters)%3A%0A%20%20%20%20multi_select_table%20%3D%20mo.ui.table(%0A%20%20%20%20%20%20%20%20office_characters%2C%0A%20%20%20%20%20%20%20%20selection%3D%22multi%22%2C%0A%20%20%20%20%20%20%20%20pagination%3DTrue%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(multi_select_table%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20multi_select_table)%3A%0A%20%20%20%20mo.ui.tabs(%7B%22table%22%3A%20multi_select_table%2C%20%22selection%22%3A%20multi_select_table.value%7D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22**No%20selection.**%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20office_characters)%3A%0A%20%20%20%20table%20%3D%20mo.ui.table(%0A%20%20%20%20%20%20%20%20office_characters%2C%0A%20%20%20%20%20%20%20%20label%3D%22Employees%22%2C%0A%20%20%20%20%20%20%20%20selection%3DNone%2C%0A%20%20%20%20)%0A%0A%20%20%20%20table%0A%20%20%20%20return%20(table%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20office_characters%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Michael%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Scott%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22%2C%20rounded%3DTrue)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Jim%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Halpert%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D7)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Pam%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Beesly%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Dwight%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Schrute%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D7)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Angela%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Martin%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Kevin%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Malone%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Oscar%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Martinez%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Stanley%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Hudson%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Phyllis%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Vance%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Meredith%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Palmer%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D7)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Creed%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Bratton%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Ryan%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Howard%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Kelly%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Kapoor%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Toby%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Flenderson%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Darryl%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Philbin%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D7)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Erin%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Hannon%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Andy%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Bernard%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Jan%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Levinson%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22David%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Wallace%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22first_name%22%3A%20%22Holly%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22last_name%22%3A%20%22Flax%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22skill%22%3A%20mo.ui.slider(1%2C%2010%2C%20value%3D7)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22favorite%20place%22%3A%20mo.image(src%3D%22https%3A%2F%2Fpicsum.photos%2F100%22)%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%5D%0A%20%20%20%20return%20(office_characters%2C)%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+9eab5ab4932a79f68ee7f6d93d1ea105551df88f353b909a9f913a578b4fd9f8
+
+
diff --git a/public/examples/ui/tabs.py.html b/public/examples/ui/tabs.py.html
new file mode 100644
index 0000000..66ff00e
--- /dev/null
+++ b/public/examples/ui/tabs.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tabs.py
+
+
+
+
+
+ tabs
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%20Tabs%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22Use%20%60mo.ui.tabs%60%20to%20organize%20outputs.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20settings%20%3D%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22Edit%20User%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20first%20%3A%3D%20mo.ui.text(label%3D%22First%20Name%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20last%20%3A%3D%20mo.ui.text(label%3D%22Last%20Name%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%0A%20%20%20%20organization%20%3D%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22Edit%20Organization%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20org%20%3A%3D%20mo.ui.text(label%3D%22Organization%20Name%22%2C%20value%3D%22...%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20employees%20%3A%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3D%22Number%20of%20Employees%22%2C%20start%3D0%2C%20stop%3D1000%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.ui.tabs(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%F0%9F%A7%99%E2%80%8D%E2%99%80%20User%22%3A%20settings%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%F0%9F%8F%A2%20Organization%22%3A%20organization%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%20employees%2C%20first%2C%20last%2C%20org%2C%20organization%2C%20settings%0A%0A%0A%40app.cell%0Adef%20__(employees%2C%20first%2C%20last%2C%20mo%2C%20org)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20Welcome%20**%7Bfirst.value%7D%20%7Blast.value%7D**%20to%20**%7Borg.value%7D**!%20You%20are%20%0A%20%20%20%20%20%20%20%20employee%20no.%20**%7Bemployees.value%20%2B%201%7D**.%0A%0A%20%20%20%20%20%20%20%20%23%7B%22%F0%9F%8E%89%22%20*%20(min(employees.value%20%2B%201%2C%201000))%7D%20%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%20if%20all(%5Bfirst.value%2C%20last.value%2C%20org.value%5D)%20else%20None%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+c6a7de9f503984a7782784897c40b4c7b1d5211d2c5ae0ff177e987c37be3447
+
+
diff --git a/public/examples/ui/task_list.py.html b/public/examples/ui/task_list.py.html
new file mode 100644
index 0000000..2ce7bbf
--- /dev/null
+++ b/public/examples/ui/task_list.py.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ task_list.py
+
+
+
+
+
+ task list
+
+
+
+
+
+
+
+
+
+ import%20marimo%0A%0A__generated_with%20%3D%20%220.9.30%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%23%20Task%20List%22).left()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(dataclass)%3A%0A%20%20%20%20%40dataclass%0A%20%20%20%20class%20Task%3A%0A%20%20%20%20%20%20%20%20name%3A%20str%0A%20%20%20%20%20%20%20%20done%3A%20bool%20%3D%20False%0A%20%20%20%20return%20(Task%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20get_tasks%2C%20set_tasks%20%3D%20mo.state(%5B%5D)%0A%20%20%20%20mutation_signal%2C%20set_mutation_signal%20%3D%20mo.state(False)%0A%20%20%20%20return%20get_tasks%2C%20mutation_signal%2C%20set_mutation_signal%2C%20set_tasks%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20mutation_signal)%3A%0A%20%20%20%20mutation_signal%0A%0A%20%20%20%20task_entry_box%20%3D%20mo.ui.text(placeholder%3D%22a%20task%20...%22)%0A%20%20%20%20return%20(task_entry_box%2C)%0A%0A%0A%40app.cell%0Adef%20__(Task%2C%20mo%2C%20set_mutation_signal%2C%20set_tasks%2C%20task_entry_box)%3A%0A%20%20%20%20def%20add_task()%3A%0A%20%20%20%20%20%20%20%20if%20task_entry_box.value%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20set_tasks(lambda%20v%3A%20v%20%2B%20%5BTask(task_entry_box.value)%5D)%0A%20%20%20%20%20%20%20%20set_mutation_signal(True)%0A%0A%0A%20%20%20%20add_task_button%20%3D%20mo.ui.button(%0A%20%20%20%20%20%20%20%20label%3D%22add%20task%22%2C%0A%20%20%20%20%20%20%20%20on_change%3Dlambda%20_%3A%20add_task()%2C%0A%20%20%20%20)%0A%0A%20%20%20%20clear_tasks_button%20%3D%20mo.ui.button(%0A%20%20%20%20%20%20%20%20label%3D%22clear%20completed%20tasks%22%2C%0A%20%20%20%20%20%20%20%20on_change%3Dlambda%20_%3A%20set_tasks(%0A%20%20%20%20%20%20%20%20%20%20%20%20lambda%20v%3A%20%5Btask%20for%20task%20in%20v%20if%20not%20task.done%5D%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20)%0A%20%20%20%20return%20add_task%2C%20add_task_button%2C%20clear_tasks_button%0A%0A%0A%40app.cell%0Adef%20__(add_task_button%2C%20clear_tasks_button%2C%20mo%2C%20task_entry_box)%3A%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5Btask_entry_box%2C%20add_task_button%2C%20clear_tasks_button%5D%2C%20justify%3D%22start%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(Task%2C%20get_tasks%2C%20mo%2C%20set_tasks)%3A%0A%20%20%20%20task_list%20%3D%20mo.ui.array(%0A%20%20%20%20%20%20%20%20%5Bmo.ui.checkbox(value%3Dtask.done%2C%20label%3Dtask.name)%20for%20task%20in%20get_tasks()%5D%2C%0A%20%20%20%20%20%20%20%20label%3D%22tasks%22%2C%0A%20%20%20%20%20%20%20%20on_change%3Dlambda%20v%3A%20set_tasks(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5BTask(task.name%2C%20done%3Dv%5Bi%5D)%20for%20i%2C%20task%20in%20enumerate(get_tasks())%5D%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(task_list%2C)%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20task_list)%3A%0A%20%20%20%20mo.as_html(task_list)%20if%20task_list.value%20else%20mo.md(%22No%20tasks!%20%F0%9F%8E%89%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20from%20dataclasses%20import%20dataclass%0A%20%20%20%20return%20(dataclass%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
+
+
+c6064d9774309e660802e79f377141c8f351b103edae3894b2d24a81c07e3360
+
+
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..5f7aa1e
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+ Marimo Examples
+
+
+
+ Marimo Examples
+
+
+
\ No newline at end of file
diff --git a/scripts/export_notebooks.py b/scripts/export_notebooks.py
index c2a9a2c..75650f4 100755
--- a/scripts/export_notebooks.py
+++ b/scripts/export_notebooks.py
@@ -21,12 +21,12 @@
]
def export_markdown(notebook_path: str) -> None:
- """Export a single marimo notebook to markdown."""
+ """Export a single marimo notebook to markdown format."""
output_path = f"{notebook_path}.md"
print(f"Exporting {notebook_path} to {output_path}")
result = subprocess.run(
- ["marimo", "export", "md", notebook_path, "-o", "generated/" + output_path],
+ ["marimo", "export", "md", notebook_path, "-o", f"generated/{output_path}"],
capture_output=True,
text=True,
)
@@ -36,8 +36,82 @@ def export_markdown(notebook_path: str) -> None:
print(result.stderr)
raise RuntimeError(f"Failed to export {notebook_path}")
+def export_html(notebook_path: str) -> None:
+ """Export a single marimo notebook to HTML format."""
+ ext = "html"
+ output_path = f"{notebook_path}.{ext}"
+ print(f"Exporting {notebook_path} to {output_path}")
+ result = subprocess.run(
+ ["marimo", "export", "html", notebook_path, "-o", f"public/{output_path}"],
+ capture_output=True,
+ text=True,
+ )
+
+ if result.returncode != 0:
+ print(f"Error exporting {notebook_path}:")
+ print(result.stderr)
+ raise RuntimeError(f"Failed to export {notebook_path}")
+
+def export_ipynb(notebook_path: str) -> None:
+ """Export a single marimo notebook to ipynb format."""
+ output_path = f"{notebook_path}.ipynb"
+ print(f"Exporting {notebook_path} to {output_path}")
+
+ result = subprocess.run(
+ ["marimo", "export", "ipynb", notebook_path, "-o", f"generated/{output_path}", "--sort", "top-down"],
+ capture_output=True,
+ text=True,
+ )
+
+ if result.returncode != 0:
+ print(f"Error exporting {notebook_path}:")
+ print(result.stderr)
+ raise RuntimeError(f"Failed to export {notebook_path}")
+
+def export_script(notebook_path: str) -> None:
+ """Export a single marimo notebook to a python script."""
+ output_path = f"{notebook_path.replace('.py', '.script.py')}"
+ print(f"Exporting {notebook_path} to {output_path}")
+
+ result = subprocess.run(
+ ["marimo", "export", "script", notebook_path, "-o", f"generated/{output_path}"],
+ capture_output=True,
+ text=True,
+ )
+
+ if result.returncode != 0:
+ print(f"Error exporting {notebook_path}:")
+ print(result.stderr)
+ raise RuntimeError(f"Failed to export {notebook_path}")
+
+def generate_index(dir: str) -> None:
+ """Generate the index.html file."""
+ print("Generating index.html")
+
+ with open("public/index.html", "w") as f:
+ f.write("""
+
+
+
+
+ Marimo Examples
+
+
+
+ Marimo Examples
+
+
+""")
+
def main():
- parser = argparse.ArgumentParser(description="Export marimo notebooks to markdown")
+ parser = argparse.ArgumentParser(description="Export marimo notebooks")
parser.add_argument(
"--examples-dir",
type=str,
@@ -50,11 +124,16 @@ def main():
if not os.path.exists(args.examples_dir):
raise FileNotFoundError(f"Examples directory not found: {args.examples_dir}")
+ generate_index(args.examples_dir)
+
# Process each whitelisted notebook
for notebook in WHITELISTED_NOTEBOOKS:
notebook_path = os.path.join(args.examples_dir, notebook)
if os.path.exists(notebook_path):
export_markdown(notebook_path)
+ # export_html(notebook_path)
+ export_ipynb(notebook_path)
+ export_script(notebook_path)
else:
print(f"Warning: Notebook not found: {notebook_path}")