diff --git a/README.md b/README.md index 037b7c8405..be2c0a2032 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ | Latest dev release | [![Github tag](https://img.shields.io/github/v/tag/holoviz/panel.svg?label=tag&colorB=11ccbb)](https://github.com/holoviz/panel/tags) [![dev-site](https://img.shields.io/website-up-down-green-red/https/pyviz-dev.github.io/panel.svg?label=dev%20website)](https://pyviz-dev.github.io/panel/) | | Latest release | [![Github release](https://img.shields.io/github/release/holoviz/panel.svg?label=tag&colorB=11ccbb)](https://github.com/holoviz/panel/releases) [![PyPI version](https://img.shields.io/pypi/v/panel.svg?colorB=cc77dd)](https://pypi.python.org/pypi/panel) [![panel version](https://img.shields.io/conda/v/pyviz/panel.svg?colorB=4488ff&style=flat)](https://anaconda.org/pyviz/panel) [![conda-forge version](https://img.shields.io/conda/v/conda-forge/panel.svg?label=conda%7Cconda-forge&colorB=4488ff)](https://anaconda.org/conda-forge/panel) [![defaults version](https://img.shields.io/conda/v/anaconda/panel.svg?label=conda%7Cdefaults&style=flat&colorB=4488ff)](https://anaconda.org/anaconda/panel) | | Docs | [![gh-pages](https://img.shields.io/github/last-commit/holoviz/panel/gh-pages.svg)](https://github.com/holoviz/panel/tree/gh-pages) [![site](https://img.shields.io/website-up-down-green-red/https/panel.holoviz.org.svg)](https://panel.holoviz.org) | +| Binder | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/holoviz/panel/binder?urlpath=lab/tree/examples) | | Support | [![Discourse](https://img.shields.io/discourse/status?server=https%3A%2F%2Fdiscourse.holoviz.org)](https://discourse.holoviz.org/) | - ## What is it? Panel provides tools for easily composing widgets, plots, tables, and other viewable objects and controls into custom analysis tools, apps, and dashboards. Panel works with visualizations from [Bokeh](https://bokeh.pydata.org), [Matplotlib](https://matplotlib.org/), [HoloViews](https://holoviews.org), and many other Python plotting libraries, making them instantly viewable either individually or when combined with interactive widgets that control them. Panel works equally well in [Jupyter Notebooks](http://jupyter.org), for creating quick data-exploration tools, or as standalone deployed apps and dashboards, and allows you to easily switch between those contexts as needed. @@ -50,7 +50,7 @@ Panel can be used in a wide range of development environments: ### Editor + Server -You can edit your Panel code as a .py file in any text editor, marking the objects you want to render as `.servable()`, then launch a server with `panel serve my_script.py --show` to open a browser tab showing your app or dashboard and backed by a live Python process. +You can edit your Panel code as a .py file in any text editor, marking the objects you want to render as `.servable()`, then launch a server with `panel serve my_script.py --show` to open a browser tab showing your app or dashboard and backed by a live Python process. If you want the server to automatically reload when you save code changes during development, then you should use `panel serve my_script.py --auto --show`. ### JupyterLab and Classic notebook diff --git a/binder/apt.txt b/binder/apt.txt new file mode 100644 index 0000000000..df634497d3 --- /dev/null +++ b/binder/apt.txt @@ -0,0 +1,2 @@ +libgl1-mesa-dev +xvfb \ No newline at end of file diff --git a/binder/jupyter-panel-apps-server/__init__.py b/binder/jupyter-panel-apps-server/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/binder/jupyter-panel-apps-server/examples-icon.svg b/binder/jupyter-panel-apps-server/examples-icon.svg new file mode 100644 index 0000000000..8be79f5432 --- /dev/null +++ b/binder/jupyter-panel-apps-server/examples-icon.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Panel + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/binder/jupyter-panel-apps-server/jupyter_panel_apps_server.py b/binder/jupyter-panel-apps-server/jupyter_panel_apps_server.py new file mode 100644 index 0000000000..7406108be9 --- /dev/null +++ b/binder/jupyter-panel-apps-server/jupyter_panel_apps_server.py @@ -0,0 +1,55 @@ +""" +Function to configure serving the panel example apps via jupyter-server-proxy. +""" +import pathlib +from glob import glob + +ICON_PATH = str((pathlib.Path(__file__).parent / "examples-icon.svg").absolute()) + +DONT_SERVE = [ + "examples/gallery/demos/attractors.ipynb", + "examples/gallery/demos/gapminders.ipynb", + "examples/gallery/demos/glaciers.ipynb", + "examples/gallery/demos/nyc_taxi.ipynb", + "examples/gallery/demos/portfolio-optimizer.ipynb", +] + + +def get_apps(): + return [ + app + for app in glob("examples/gallery/**/*.ipynb", recursive=True) + if not app in DONT_SERVE + ] + + +def panel_serve_examples(): + """Returns the jupyter-server-proxy configuration for serving the example notebooks as Panel + apps. + + Returns: + Dict: The configuration dictionary + """ + apps = get_apps() + # See: + # https://jupyter-server-proxy.readthedocs.io/en/latest/server-process.html + # https://github.com/holoviz/jupyter-panel-proxy/blob/master/panel_server/__init__.py + return { + "command": [ + "panel", + "serve", + *apps, + "--allow-websocket-origin=*", + "--port", + "{port}", + "--prefix", + "{base_url}panel", + ], + "absolute_url": True, + "timeout": 360, + "launcher_entry": { + "enabled": True, + "title": "Apps", + "icon_path": ICON_PATH, + }, + } diff --git a/binder/jupyter-panel-apps-server/setup.py b/binder/jupyter-panel-apps-server/setup.py new file mode 100644 index 0000000000..06ad936bb3 --- /dev/null +++ b/binder/jupyter-panel-apps-server/setup.py @@ -0,0 +1,14 @@ +"""This setup.py will install a package that configures the jupyter-server-proxy to +panel serve the example notebooks.""" +import setuptools + +setuptools.setup( + name="jupyter-panel-examples-server", + py_modules=["jupyter_panel_apps_server"], + entry_points={ + "jupyter_serverproxy_servers": [ + "panel = jupyter_panel_apps_server:panel_serve_examples", + ] + }, + install_requires=["jupyter-server-proxy", "panel"], +) diff --git a/binder/jupyter-voila-docs-server/__init__.py b/binder/jupyter-voila-docs-server/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/binder/jupyter-voila-docs-server/examples-icon.svg b/binder/jupyter-voila-docs-server/examples-icon.svg new file mode 100644 index 0000000000..8be79f5432 --- /dev/null +++ b/binder/jupyter-voila-docs-server/examples-icon.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Panel + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/binder/jupyter-voila-docs-server/jupyter_voila_docs_server.py b/binder/jupyter-voila-docs-server/jupyter_voila_docs_server.py new file mode 100644 index 0000000000..ed1e1fccd5 --- /dev/null +++ b/binder/jupyter-voila-docs-server/jupyter_voila_docs_server.py @@ -0,0 +1,56 @@ +""" +Function to configure serving the panel example apps via jupyter-server-proxy. +""" +import pathlib +from glob import glob + +ICON_PATH = str((pathlib.Path(__file__).parent / "examples-icon.svg").absolute()) + +DONT_SERVE = [ + "examples/gallery/demos/attractors.ipynb", + "examples/gallery/demos/gapminders.ipynb", + "examples/gallery/demos/glaciers.ipynb", + "examples/gallery/demos/nyc_taxi.ipynb", + "examples/gallery/demos/portfolio-optimizer.ipynb", +] + + +def get_apps(): + return [ + app + for app in glob("examples/gallery/**/*.ipynb", recursive=True) + if not app in DONT_SERVE + ] + + +def voila_serve_examples(): + """Returns the jupyter-server-proxy configuration for serving the example notebooks as Voila + Apps. + + Returns: + Dict: The configuration dictionary + """ + # See: + # https://jupyter-server-proxy.readthedocs.io/en/latest/server-process.html + # https://github.com/holoviz/jupyter-panel-proxy/blob/master/panel_server/__init__.py + return { + "command": [ + "voila", # voila examples/gallery/dynamic --strip_sources=False --base_url + "examples", + "--no-browser", + "--strip_sources=False", + "--port", + "{port}", + "--base_url", + "{base_url}docs/", + "--VoilaConfiguration.file_whitelist", + "'*.*'", + ], + "absolute_url": True, + "timeout": 360, + "launcher_entry": { + "enabled": True, + "title": "Docs", + "icon_path": ICON_PATH, + }, + } diff --git a/binder/jupyter-voila-docs-server/setup.py b/binder/jupyter-voila-docs-server/setup.py new file mode 100644 index 0000000000..2282c7a0ec --- /dev/null +++ b/binder/jupyter-voila-docs-server/setup.py @@ -0,0 +1,14 @@ +"""This setup.py will install a package that configures the jupyter-server-proxy to +panel serve the example notebooks.""" +import setuptools + +setuptools.setup( + name="jupyter-voila-docs-server", + py_modules=["jupyter_voila_docs_server"], + entry_points={ + "jupyter_serverproxy_servers": [ + "docs = jupyter_voila_docs_server:voila_serve_examples", + ] + }, + install_requires=["jupyter-server-proxy", "voila"], +) diff --git a/binder/postBuild b/binder/postBuild new file mode 100644 index 0000000000..8983f943d8 --- /dev/null +++ b/binder/postBuild @@ -0,0 +1,9 @@ +pip install voila>=0.2.10 -U +conda install -c conda-forge code-server +code-server --install-extension ms-python.python +SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension wesbos.theme-cobalt2 +SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension RandomFractalsInc.vscode-data-preview +SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension RandomFractalsInc.geo-data-viewer +SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension ritwickdey.liveserver +bokeh sampledata +panel build panel \ No newline at end of file diff --git a/binder/requirements.txt b/binder/requirements.txt new file mode 100644 index 0000000000..cbd0780066 --- /dev/null +++ b/binder/requirements.txt @@ -0,0 +1,10 @@ +-e .['all'] +-e binder/jupyter-panel-apps-server/. +-e binder/jupyter-voila-docs-server/. +pydeck +pyecharts +idom +xlsxwriter +pyarrow +jupyter_bokeh +jupyter-vscode-proxy diff --git a/binder/start b/binder/start new file mode 100644 index 0000000000..cf080bc09c --- /dev/null +++ b/binder/start @@ -0,0 +1,14 @@ +#!/bin/bash +export BOKEH_ALLOW_WS_ORIGIN=hub.gke2.mybinder.org +echo '' >> panel/template/base.py +echo 'BasicTemplate.param.site_url.default="./"' >> panel/template/base.py +export DISPLAY=:99.0 +export PYVISTA_OFF_SCREEN=true +export PYVISTA_USE_IPYVTK=true +export PYVISTA_PLOT_THEME=document +which Xvfb +Xvfb :99 -screen 0 1280x1024x24 > /dev/null 2>&1 & +sleep 3 +jupyter trust examples/**/*.ipynb +jupyter trust examples/**/**/*.ipynb +exec "$@" \ No newline at end of file diff --git a/examples/gallery/apis/stocks_altair.ipynb b/examples/gallery/apis/stocks_altair.ipynb index 88cc8f790c..08c40ce608 100644 --- a/examples/gallery/apis/stocks_altair.ipynb +++ b/examples/gallery/apis/stocks_altair.ipynb @@ -12,7 +12,7 @@ "\n", "from bokeh.sampledata import stocks\n", "\n", - "pn.extension('vega')" + "pn.extension('vega', sizing_mode=\"stretch_width\")" ] }, { @@ -41,7 +41,7 @@ "\n", "def get_plot(ticker, window_size):\n", " df = get_df(ticker, window_size)\n", - " return alt.Chart(df).mark_line().encode(x='date', y='close')" + " return alt.Chart(df).mark_line().encode(x='date', y='close').properties(width=\"container\", height=\"container\",)" ] }, { @@ -62,7 +62,7 @@ "interact = pn.interact(get_plot, ticker=tickers, window_size=(1, 21, 5))\n", "\n", "pn.Row(\n", - " pn.Column(title, interact[0]),\n", + " pn.Column(title, interact[0], sizing_mode=\"fixed\", width=300),\n", " interact[1]\n", ")" ] @@ -88,7 +88,7 @@ "@pn.depends(ticker.param.value, window.param.value)\n", "def get_plot(ticker, window_size):\n", " df = get_df(ticker, window_size)\n", - " return alt.Chart(df).mark_line().encode(x='date', y='close')\n", + " return alt.Chart(df).mark_line().encode(x='date', y='close').properties(width=\"container\", height=\"container\",)\n", "\n", "pn.Row(\n", " pn.Column(title, ticker, window),\n", @@ -121,10 +121,10 @@ " \n", " @param.depends('ticker', 'window_size')\n", " def plot(self):\n", - " return get_plot(self.ticker, self.window_size)\n", + " return get_plot(self.ticker, self.window_size).properties(width=\"container\", height=\"container\",)\n", " \n", "explorer = StockExplorer()\n", - "pn.Row(explorer.param, explorer.plot)" + "pn.Row(pn.Column(explorer.param, sizing_mode=\"stretch_width\", width=300), explorer.plot)" ] }, { @@ -146,7 +146,7 @@ "window = pn.widgets.IntSlider(name='Window', value=6, start=1, end=21)\n", "\n", "row = pn.Row(\n", - " pn.Column(title, ticker, window),\n", + " pn.Column(title, ticker, window, sizing_mode=\"fixed\", width=300),\n", " get_plot(ticker.options[0], window.value)\n", ")\n", "\n", @@ -156,7 +156,7 @@ "ticker.param.watch(update, 'value')\n", "window.param.watch(update, 'value')\n", "\n", - "row.servable()" + "row" ] }, { @@ -165,6 +165,30 @@ "source": [ "In practice, different projects will be suited to one or the other of these APIs, and most of Panel's functionality should be available from any API." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Let's wrap it into nice template that can be served via `panel serve stocks_altair.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "description=\"\"\"This example compares **four different implementations of the same app** using \n", + "\n", + "- the quick and easy ``interact`` function, \n", + "- more flexible *reactive* functions,\n", + "- declarative *Param-based* code, and \n", + "- explicit *callbacks*.\"\"\"\n", + "pn.template.FastListTemplate(site=\"Panel\", title=\"Altair Stock Explorer\", sidebar=[ticker, window], main=[description, row[1]]).servable();" + ] } ], "metadata": { @@ -174,5 +198,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/apis/stocks_hvplot.ipynb b/examples/gallery/apis/stocks_hvplot.ipynb index cd80f3bbc7..3e4c51e103 100644 --- a/examples/gallery/apis/stocks_hvplot.ipynb +++ b/examples/gallery/apis/stocks_hvplot.ipynb @@ -12,7 +12,7 @@ "\n", "from bokeh.sampledata import stocks\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -41,7 +41,7 @@ "\n", "def get_plot(ticker, window_size):\n", " df = get_df(ticker, window_size)\n", - " return df.hvplot.line('date', 'close', grid=True)" + " return df.hvplot.line('date', 'close', grid=True, responsive=True, height=300)" ] }, { @@ -62,7 +62,7 @@ "interact = pn.interact(get_plot, ticker=tickers, window_size=(1, 21, 5))\n", "\n", "pn.Row(\n", - " pn.Column(title, interact[0]),\n", + " pn.Column(title, interact[0], sizing_mode=\"fixed\", width=300),\n", " interact[1]\n", ")" ] @@ -88,10 +88,10 @@ "@pn.depends(ticker, window)\n", "def get_plot(ticker, window_size):\n", " df = get_df(ticker, window_size)\n", - " return df.hvplot.line('date', 'close', grid=True)\n", + " return df.hvplot.line('date', 'close', grid=True, responsive=True, height=300)\n", "\n", "pn.Row(\n", - " pn.Column(title, ticker, window),\n", + " pn.Column(title, ticker, window, sizing_mode=\"fixed\", width=300),\n", " get_plot\n", ")" ] @@ -123,7 +123,7 @@ " return get_plot(self.ticker, self.window_size)\n", " \n", "explorer = StockExplorer(name='Stock Explorer hvPlot')\n", - "pn.Row(explorer.param, explorer.plot)" + "pn.Row(pn.Column(explorer.param, sizing_mode=\"fixed\", width=300), explorer.plot)" ] }, { @@ -145,7 +145,7 @@ "window = pn.widgets.IntSlider(name='Window', value=6, start=1, end=21)\n", "\n", "row = pn.Row(\n", - " pn.Column(title, ticker, window),\n", + " pn.Column(title, ticker, window, sizing_mode=\"fixed\", width=300),\n", " get_plot(ticker.options[0], window.value)\n", ")\n", "\n", @@ -155,7 +155,7 @@ "ticker.param.watch(update, 'value')\n", "window.param.watch(update, 'value')\n", "\n", - "row.servable()" + "row" ] }, { @@ -164,6 +164,30 @@ "source": [ "In practice, different projects will be suited to one or the other of these APIs, and most of Panel's functionality should be available from any API." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve stocks_hvplot.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "description=\"\"\"This example compares **four different implementations of the same app** using \n", + "\n", + "- the quick and easy ``interact`` function, \n", + "- more flexible *reactive* functions,\n", + "- declarative *Param-based* code, and \n", + "- explicit *callbacks*.\"\"\"\n", + "pn.template.FastListTemplate(site=\"Panel\", title=\"hvPlot Stock Explorer\", sidebar=[ticker, window], main=[description, row[1]]).servable();" + ] } ], "metadata": { @@ -173,5 +197,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/apis/stocks_mpl.ipynb b/examples/gallery/apis/stocks_matplotlib.ipynb similarity index 85% rename from examples/gallery/apis/stocks_mpl.ipynb rename to examples/gallery/apis/stocks_matplotlib.ipynb index 3ff8b27a58..fcacbb2cbf 100644 --- a/examples/gallery/apis/stocks_mpl.ipynb +++ b/examples/gallery/apis/stocks_matplotlib.ipynb @@ -14,7 +14,7 @@ "\n", "from bokeh.sampledata import stocks\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -68,7 +68,7 @@ "interact = pn.interact(get_plot, ticker=tickers, window_size=(1, 21, 5))\n", "\n", "pn.Row(\n", - " pn.Column(title, interact[0]),\n", + " pn.Column(title, interact[0], sizing_mode=\"fixed\", width=300),\n", " interact[1]\n", ")" ] @@ -101,7 +101,7 @@ " return fig\n", "\n", "pn.Row(\n", - " pn.Column(title, ticker, window),\n", + " pn.Column(title, ticker, window, sizing_mode=\"fixed\", width=300),\n", " get_plot\n", ")" ] @@ -134,7 +134,7 @@ " return get_plot(self.ticker, self.window_size)\n", " \n", "explorer = StockExplorer()\n", - "pn.Row(explorer.param, explorer.plot)" + "pn.Row(pn.Column(explorer.param, sizing_mode=\"fixed\", width=300), explorer.plot)" ] }, { @@ -156,8 +156,8 @@ "window = pn.widgets.IntSlider(name='Window', value=6, start=1, end=21)\n", "\n", "row = pn.Row(\n", - " pn.Column(title, ticker, window),\n", - " get_plot(ticker.options[0], window.value)\n", + " pn.Column(title, ticker, window, sizing_mode=\"fixed\", width=300),\n", + " get_plot(ticker.options[0], window.value),\n", ")\n", "\n", "def update(event):\n", @@ -166,7 +166,7 @@ "ticker.param.watch(update, 'value')\n", "window.param.watch(update, 'value')\n", "\n", - "row.servable()" + "row" ] }, { @@ -175,6 +175,30 @@ "source": [ "In practice, different projects will be suited to one or the other of these APIs, and most of Panel's functionality should be available from any API." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve stocks_matplotlib.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "description=\"\"\"This example compares **four different implementations of the same app** using \n", + "\n", + "- the quick and easy ``interact`` function, \n", + "- more flexible *reactive* functions,\n", + "- declarative *Param-based* code, and \n", + "- explicit *callbacks*.\"\"\"\n", + "pn.template.FastListTemplate(site=\"Panel\", title=\"Matplotlib Stock Explorer\", sidebar=[ticker, window], main=[description, row[1]]).servable();" + ] } ], "metadata": { @@ -184,5 +208,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/apis/stocks_plotly.ipynb b/examples/gallery/apis/stocks_plotly.ipynb index 91e5991083..2a27f4ed65 100644 --- a/examples/gallery/apis/stocks_plotly.ipynb +++ b/examples/gallery/apis/stocks_plotly.ipynb @@ -12,7 +12,7 @@ "\n", "from bokeh.sampledata import stocks\n", "\n", - "pn.extension('plotly')" + "pn.extension('plotly', sizing_mode=\"stretch_width\")" ] }, { @@ -60,7 +60,7 @@ "interact = pn.interact(get_plot, ticker=tickers, window_size=(1, 21, 5))\n", "\n", "pn.Row(\n", - " pn.Column(title, interact[0]),\n", + " pn.Column(title, interact[0], sizing_mode=\"fixed\", width=300),\n", " interact[1]\n", ")" ] @@ -89,7 +89,7 @@ " return go.Scatter(x=df.date, y=df.close)\n", "\n", "pn.Row(\n", - " pn.Column(title, ticker, window),\n", + " pn.Column(title, ticker, window, sizing_mode=\"fixed\", width=300),\n", " get_plot\n", ")" ] @@ -122,7 +122,7 @@ " return get_plot(self.ticker, self.window_size)\n", " \n", "explorer = StockExplorer()\n", - "pn.Row(explorer.param, explorer.plot)" + "pn.Row(pn.Column(explorer.param, sizing_mode=\"fixed\", width=300), explorer.plot)" ] }, { @@ -144,7 +144,7 @@ "window = pn.widgets.IntSlider(name='Window', value=6, start=1, end=21)\n", "\n", "row = pn.Row(\n", - " pn.Column(title, ticker, window),\n", + " pn.Column(title, ticker, window, sizing_mode=\"fixed\", width=300),\n", " get_plot(ticker.options[0], window.value)\n", ")\n", "\n", @@ -154,7 +154,7 @@ "ticker.param.watch(update, 'value')\n", "window.param.watch(update, 'value')\n", "\n", - "row.servable()" + "row" ] }, { @@ -163,6 +163,30 @@ "source": [ "In practice, different projects will be suited to one or the other of these APIs, and most of Panel's functionality should be available from any API." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve stocks_plotly.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "description=\"\"\"This example compares **four different implementations of the same app** using \n", + "\n", + "- the quick and easy ``interact`` function, \n", + "- more flexible *reactive* functions,\n", + "- declarative *Param-based* code, and \n", + "- explicit *callbacks*.\"\"\"\n", + "pn.template.FastListTemplate(site=\"Panel\", title=\"Plotly Stock Explorer\", sidebar=[ticker, window], main=[description, row[1]]).servable();" + ] } ], "metadata": { @@ -172,5 +196,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/VTKInteractive.ipynb b/examples/gallery/demos/VTKInteractive.ipynb index 3496577fa2..0ba9f00f70 100644 --- a/examples/gallery/demos/VTKInteractive.ipynb +++ b/examples/gallery/demos/VTKInteractive.ipynb @@ -9,7 +9,7 @@ "import panel as pn\n", "import pyvista as pv\n", "from pyvista import examples\n", - "pn.extension('vtk')" + "pn.extension('vtk', sizing_mode=\"stretch_width\")" ] }, { @@ -364,7 +364,17 @@ "metadata": {}, "outputs": [], "source": [ - "pn.Row(vtkpan,pn.Column(actor_selection,pn.Tabs(('Scene controller', pn.Column(scene_props, light_props)), ('Actor properties',actor_props))), sizing_mode=\"stretch_both\").servable()" + "settings = pn.Column(actor_selection,pn.Tabs(('Scene controller', pn.Column(scene_props, light_props)), ('Actor properties',actor_props)))\n", + "pn.Row(vtkpan, settings)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve VTKInteractive.ipynb`" ] }, { @@ -372,26 +382,16 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "description=\"This example demonstrates the use of **VTK and pyvista** to display a *scene*\"\n", + "pn.template.FastListTemplate(site=\"Panel\", title=\"VTK Interactive\", sidebar=[settings], main=[description, vtkpan]).servable();" + ] } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.2" + "pygments_lexer": "ipython3" } }, "nbformat": 4, diff --git a/examples/gallery/demos/VTKSlicer.ipynb b/examples/gallery/demos/VTKSlicer.ipynb index 6f462414a4..a33f7c94cd 100644 --- a/examples/gallery/demos/VTKSlicer.ipynb +++ b/examples/gallery/demos/VTKSlicer.ipynb @@ -292,22 +292,9 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.5" + "pygments_lexer": "ipython3" } }, "nbformat": 4, diff --git a/examples/gallery/demos/VTKWarp.ipynb b/examples/gallery/demos/VTKWarp.ipynb index 6d5fa2db93..6dde53e5c6 100644 --- a/examples/gallery/demos/VTKWarp.ipynb +++ b/examples/gallery/demos/VTKWarp.ipynb @@ -9,14 +9,14 @@ "import panel as pn\n", "import numpy as np\n", "import pyvista as pv\n", - "pn.extension('vtk')" + "pn.extension('vtk', sizing_mode=\"stretch_width\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Temporal function inpired from http://holoviews.org/user_guide/Live_Data.html" + "Temporal function inspired from http://holoviews.org/user_guide/Live_Data.html" ] }, { @@ -71,7 +71,7 @@ " 'viewUp': [-0.41067028045654297, -0.40083757042884827, 0.8189500570297241]\n", "}\n", "vtkpan = pn.panel(pl.ren_win, orientation_widget=True, sizing_mode='stretch_both', camera=camera)\n", - "frame = pn.widgets.Player(value=0, start=0, end=50, interval=100, loop_policy=\"reflect\")\n", + "frame = pn.widgets.Player(value=0, start=0, end=50, interval=100, loop_policy=\"reflect\", height=100)\n", "\n", "@pn.depends(frame=frame.param.value)\n", "def update_3d_warp(frame):\n", @@ -83,7 +83,17 @@ " mesh_warped.points = mesh_ref.warp_by_scalar(factor=0.5).points\n", " vtkpan.synchronize()\n", "\n", - "pn.Column(frame, vtkpan, update_3d_warp, width=600, height=600).servable()" + "component = pn.Column(frame, vtkpan, update_3d_warp, height=600)\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve VTKWarp.ipynb`" ] }, { @@ -91,26 +101,15 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"VTK Warp\", main=[\"This app demonstrates the use of `VTK`\", component]).servable();" + ] } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.5" + "pygments_lexer": "ipython3" } }, "nbformat": 4, diff --git a/examples/gallery/demos/attractors.ipynb b/examples/gallery/demos/attractors.ipynb index f5dc7546fa..6a1201f198 100644 --- a/examples/gallery/demos/attractors.ipynb +++ b/examples/gallery/demos/attractors.ipynb @@ -44,5 +44,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/gapminders.ipynb b/examples/gallery/demos/gapminders.ipynb index cde2c46116..7740b49790 100644 --- a/examples/gallery/demos/gapminders.ipynb +++ b/examples/gallery/demos/gapminders.ipynb @@ -44,5 +44,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/glaciers.ipynb b/examples/gallery/demos/glaciers.ipynb index 1d1c509365..48499c3bb1 100644 --- a/examples/gallery/demos/glaciers.ipynb +++ b/examples/gallery/demos/glaciers.ipynb @@ -44,5 +44,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/nyc_taxi.ipynb b/examples/gallery/demos/nyc_taxi.ipynb index 51cd94c78e..5ff29e0dd0 100644 --- a/examples/gallery/demos/nyc_taxi.ipynb +++ b/examples/gallery/demos/nyc_taxi.ipynb @@ -44,5 +44,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/dynamic/dynamic_plot_layout.ipynb b/examples/gallery/dynamic/dynamic_plot_layout.ipynb index 06b22cc184..bb694f2103 100644 --- a/examples/gallery/dynamic/dynamic_plot_layout.ipynb +++ b/examples/gallery/dynamic/dynamic_plot_layout.ipynb @@ -10,14 +10,14 @@ "import numpy as np\n", "import holoviews as hv\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This example demonstrates how to dynamically add and remove plots from a layout (in this case a Column) using the ``pop`` and ``append`` methods (requires a live Pytbon server):" + "This example demonstrates how to dynamically add and remove plots from a layout (in this case a Column) using the ``pop`` and ``append`` methods (requires a live Python server):" ] }, { @@ -28,7 +28,7 @@ "source": [ "slider = pn.widgets.IntSlider(name='N', start=0, end=5)\n", "\n", - "column = pn.Column('This column will be populated with N Plots')\n", + "column = pn.Column('This column will be populated with N Plots', sizing_mode=\"stretch_width\")\n", "\n", "def set_plots(event):\n", " nplots = event.new-event.old\n", @@ -36,12 +36,33 @@ " if nplots < 0:\n", " column.pop(len(column)-1)\n", " elif nplots > 0:\n", - " column.append(hv.Scatter(np.random.randn(1000, 2)))\n", + " column.append(hv.Scatter(np.random.randn(1000, 2)).opts(responsive=True, height=300))\n", + " \n", + " column[0]=f'This column will be populated with {event.new} Plots'\n", " \n", "slider.param.watch(set_plots, 'value')\n", "slider.value = 1\n", "\n", - "pn.Row(slider, column).servable()" + "pn.Row(pn.Column(slider, sizing_mode=\"fixed\", width=300), column, sizing_mode=\"stretch_width\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve dynamic_plot_layout.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "description = \"This example demonstrates **how to dynamically add and remove plots** from a layout (in this case a Column) using the ``pop`` and ``append`` methods.\"\n", + "pn.template.FastListTemplate(site=\"Panel\", title=\"Dynamic Plot Layout\", sidebar=[slider], main=[description, column]).servable();" ] } ], @@ -52,5 +73,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/dynamic/dynamic_timeseries_image_analysis.ipynb b/examples/gallery/dynamic/dynamic_timeseries_image_analysis.ipynb index 9effe4536e..c4b6fb6af2 100644 --- a/examples/gallery/dynamic/dynamic_timeseries_image_analysis.ipynb +++ b/examples/gallery/dynamic/dynamic_timeseries_image_analysis.ipynb @@ -31,7 +31,7 @@ "import panel as pn\n", "\n", "hv.extension('bokeh')\n", - "pn.config.sizing_mode=\"stretch_width\"" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -194,7 +194,7 @@ " ),\n", " ),\n", ")\n", - "app.servable()" + "app" ] }, { @@ -212,6 +212,29 @@ "\n", "The `plots = ((plot_a + plot_b + plot_c) * vline_dmap).cols(1)` line is essential for making the app fast and responsive. Initially the `plot_a + plot_b + plot_c` where regenerated together with the `vline` everytime the `frame_slider.value` was changed. That made the app slower because it had to recalculate and retransfer much more data." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve dynamic_timeseries_image_analysis.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Dynamic Timeseries Image Analysis\", \n", + " main=[\n", + " \"The purpose of this app is to illustrate how you can **make an interactive and responsive tool for timeseries analysis of images** by combining a Panel `IntSlider`, some `@pn.depends` annotated plotting functions and a few HoloViews `DynamicMap`.\",\n", + " *app[2:]]\n", + ").servable();" + ] } ], "metadata": { diff --git a/examples/gallery/dynamic/dynamic_ui.ipynb b/examples/gallery/dynamic/dynamic_ui.ipynb index e7588efe1e..3f809c2bb6 100644 --- a/examples/gallery/dynamic/dynamic_ui.ipynb +++ b/examples/gallery/dynamic/dynamic_ui.ipynb @@ -15,7 +15,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This example demonstrates how to dynamically replace widgets in a layout to create responsive user interfaces (requires a live Python server)." + "This example demonstrates **how to dynamically replace widgets in a layout** to create responsive user interfaces (requires a live Python server)." ] }, { @@ -52,7 +52,25 @@ "pn.Column(\n", " '## Dynamically generated user interfaces',\n", " row\n", - ").servable()" + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve dynamic_ui.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Dynamic UI\", main=[\"This example demonstrates **how to dynamically replace widgets in a layout** to create responsive user interfaces\", row]).servable();" ] } ], @@ -63,5 +81,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/dynamic/dynamic_widget_values.ipynb b/examples/gallery/dynamic/dynamic_widget_values.ipynb index 0cd09e6fe2..ea5aeca04c 100644 --- a/examples/gallery/dynamic/dynamic_widget_values.ipynb +++ b/examples/gallery/dynamic/dynamic_widget_values.ipynb @@ -8,14 +8,14 @@ "source": [ "import panel as pn\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This example demonstrates how to control one set of widgets with another set of widgets, such as when the value of one widget changes the allowable values of another. Here the ``title_widget`` and ``value_widget`` control the title and ranges of the other set of widgets, respectively." + "This example demonstrates **how to control one set of widgets with another set of widgets**, such as when the value of one widget changes the allowable values of another. Here the ``title_widget`` and ``value_widget`` control the title and ranges of the other set of widgets, respectively." ] }, { @@ -55,7 +55,25 @@ "\n", "value_widget.param.watch(update_values, 'value')\n", "\n", - "pn.Row(meta_widgets, widgets).servable()" + "pn.Row(meta_widgets, widgets)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve dynamic_widget_values.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Dynamic Widget Labels and Values\", sidebar=[meta_widgets], main=[\"This example demonstrates **how to control one set of widgets with another set of widgets**.\", widgets]).servable();" ] } ], @@ -66,5 +84,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/external/DataTable.ipynb b/examples/gallery/external/DataTable.ipynb index 58a734fd45..42b69d261d 100644 --- a/examples/gallery/external/DataTable.ipynb +++ b/examples/gallery/external/DataTable.ipynb @@ -99,25 +99,30 @@ "table_with_export_buttons = pn.pane.HTML(html+script, sizing_mode='stretch_width', margin=(10,5,35,5))\n", "table_with_export_buttons" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Let's wrap the above into a nice app that can be run via `panel serve DataTable.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel Gallery\", title=\"DataTable\", main=[\"This example demonstrates **how to use the [jQuery DataTable extension](https://datatables.net/) with Panel** and use it to render a pandas DataFrame.\", table_with_export_buttons]).servable();" + ] } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" + "pygments_lexer": "ipython3" } }, "nbformat": 4, diff --git a/examples/gallery/external/Folium.ipynb b/examples/gallery/external/Folium.ipynb index 36862c0cc2..aec9ac58a4 100644 --- a/examples/gallery/external/Folium.ipynb +++ b/examples/gallery/external/Folium.ipynb @@ -35,7 +35,7 @@ "outputs": [], "source": [ "def get_map(lat=20.5936832, long=78.962883, zoom_start=5):\n", - " return fm.Map(location=[lat,long], zoom_start=zoom_start)\n", + " return fm.Map(location=[lat,long], zoom_start=zoom_start, width='100%', height=800)\n", "\n", "map = get_map()\n", "\n", @@ -151,11 +151,11 @@ " def __init__(self, **params):\n", " super().__init__(**params)\n", " self.map = get_map()\n", - " self.html_pane = pn.pane.HTML(sizing_mode=\"stretch_width\", min_height=600) \n", + " self.html_pane = pn.pane.HTML(sizing_mode=\"stretch_width\", height=830, margin=0) \n", " self.view = pn.Column(\n", " self.param.points_count,\n", " self.html_pane,\n", - " sizing_mode=\"stretch_width\", min_height=600,\n", + " sizing_mode=\"stretch_width\", height=875\n", " )\n", " self._update_map()\n", "\n", @@ -170,25 +170,30 @@ "app = PanelFoliumMap()\n", "app.view.embed()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve Folium.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Folium\", main=[\"This app demonstrates **how to use Folium with Panel**.\", app.view]).servable();" + ] } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.5" + "pygments_lexer": "ipython3" } }, "nbformat": 4, diff --git a/examples/gallery/external/deck.gl.ipynb b/examples/gallery/external/deck.gl.ipynb index f05a94b389..10140efb48 100644 --- a/examples/gallery/external/deck.gl.ipynb +++ b/examples/gallery/external/deck.gl.ipynb @@ -15,11 +15,11 @@ "source": [ "import panel as pn\n", "\n", - "js_files = {'deck': 'https://unpkg.com/deck.gl@^6.0.0/deckgl.min.js',\n", - " 'mapboxgl': 'https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.js'}\n", - "css_files = ['https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css']\n", + "js_files = {'deck': 'https://cdn.jsdelivr.net/npm/deck.gl@8.1.12/dist.min.js',\n", + " 'mapboxgl': 'https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.js'}\n", + "css_files = ['https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.css']\n", "\n", - "pn.extension(js_files=js_files, css_files=css_files)" + "pn.extension(js_files=js_files, css_files=css_files, sizing_mode=\"stretch_width\")" ] }, { @@ -57,7 +57,7 @@ "outputs": [], "source": [ "html = \"\"\"\n", - "
\n", + "
\n", "\n", "\n", "\"\"\" % cities\n", - "deckgl = pn.pane.HTML(html, height=500, width=800)" + "deckgl = pn.pane.HTML(html, height=500)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Next we can declare a Panel widget and define a ``jslink`` to update the deck.gl plot whenever the widget state changes. The example is adapted from http://deck.gl/showcases/gallery/viewport-transition but replaces D3 widgets with Panel-based widgets." + "Next we can declare a Panel widget and define a ``jslink`` to update the deck.gl plot whenever the widget state changes. The example is adapted from https://deck.gl/gallery/viewport-transition but replaces D3 widgets with Panel-based widgets." ] }, { @@ -99,19 +102,38 @@ "update_city = \"\"\"\n", "var d = CITIES[source.active];\n", "deckgl.setProps({\n", - " viewState: {\n", - " longitude: d.longitude,\n", - " latitude: d.latitude,\n", - " zoom: 10,\n", - " transitionInterpolator: new deck.FlyToInterpolator(),\n", - " transitionDuration: 5000\n", - " }\n", + " initialViewState: {\n", + " longitude: d.longitude,\n", + " latitude: d.latitude,\n", + " zoom: 10,\n", + " transitionInterpolator: new deck.FlyToInterpolator({speed: 1.5}),\n", + " transitionDuration: 'auto'\n", + " }\n", "});\n", "\"\"\"\n", "\n", "widget.jslink(deckgl, code={'active': update_city});\n", "\n", - "pn.Column(widget, deckgl)" + "component = pn.Column(widget, deckgl)\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve deckgl.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Deck.gl\", main=[\"This app **demonstrates loading deck.gl JSS and CSS components** and then linking it to Panel widgets.\", component]).servable();" ] } ], @@ -122,5 +144,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/layout/distribution_tabs.ipynb b/examples/gallery/layout/distribution_tabs.ipynb index 15851c87e0..b2f6b73160 100644 --- a/examples/gallery/layout/distribution_tabs.ipynb +++ b/examples/gallery/layout/distribution_tabs.ipynb @@ -10,7 +10,7 @@ "import numpy as np\n", "import holoviews as hv\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -27,13 +27,13 @@ "outputs": [], "source": [ "distributions = {\n", - " 'normal': np.random.normal,\n", - " 'uniform': np.random.uniform,\n", - " 'log-normal': np.random.lognormal,\n", - " 'exponential': np.random.exponential\n", + " 'NORMAL': np.random.normal,\n", + " 'UNIFORM': np.random.uniform,\n", + " 'LOG-NORMAL': np.random.lognormal,\n", + " 'EXPONENTIAL': np.random.exponential\n", "}\n", "\n", - "checkboxes = pn.widgets.ToggleGroup(options=distributions, behavior='radio')\n", + "checkboxes = pn.widgets.ToggleGroup(options=distributions, behavior='radio', button_type=\"success\")\n", "slider = pn.widgets.IntSlider(name='Number of observations', value=500, start=0, end=2000)\n", "\n", "@pn.depends(checkboxes.param.value, slider.param.value)\n", @@ -41,12 +41,31 @@ " values = hv.Dataset(distribution(size=n), 'values')\n", " return pn.Tabs(\n", " ('Plot', values.hist(adjoin=False).opts(\n", - " responsive=True, max_height=500, padding=0.1)),\n", + " responsive=True, max_height=500, padding=0.1, color=\"#00aa41\")),\n", " ('Summary', values.dframe().describe().T),\n", " ('Table', hv.Table(values)),\n", " )\n", "\n", - "pn.Row(pn.Column('### Distribution Type', checkboxes, slider), tabs).servable()" + "selections = pn.Column('### Distribution Type', checkboxes, slider)\n", + "pn.Row(selections, tabs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve distribution_tabs.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Distribution Tabs\", main=[\"This example demonstrates **how to plot several different types of outputs in a Tab**.\", selections, tabs]).servable();" ] } ], @@ -57,5 +76,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/layout/dynamic_tabs.ipynb b/examples/gallery/layout/dynamic_tabs.ipynb index fe8a74c6c8..e1f879bdde 100644 --- a/examples/gallery/layout/dynamic_tabs.ipynb +++ b/examples/gallery/layout/dynamic_tabs.ipynb @@ -8,7 +8,7 @@ "source": [ "import panel as pn\n", "\n", - "pn.extension('deckgl', 'plotly', 'vega')" + "pn.extension('deckgl', 'echarts', 'plotly', 'vega')" ] }, { @@ -96,7 +96,7 @@ "p.axis.visible=False\n", "p.grid.grid_line_color = None\n", "\n", - "bokeh_pane = pn.pane.Bokeh(p)" + "bokeh_pane = pn.pane.Bokeh(p, sizing_mode=\"stretch_both\", max_width=1300)" ] }, { @@ -145,6 +145,41 @@ "deck_gl = pn.pane.DeckGL(json_spec, mapbox_api_key=MAPBOX_KEY, sizing_mode='stretch_width', height=800)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Echarts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "echart = {\n", + " 'title': {\n", + " 'text': 'ECharts entry example'\n", + " },\n", + " 'tooltip': {},\n", + " 'legend': {\n", + " 'data':['Sales']\n", + " },\n", + " 'xAxis': {\n", + " 'data': [\"shirt\",\"cardign\",\"chiffon shirt\",\"pants\",\"heels\",\"socks\"]\n", + " },\n", + " 'yAxis': {},\n", + " 'series': [{\n", + " 'name': 'Sales',\n", + " 'type': 'bar',\n", + " 'data': [5, 20, 36, 10, 10, 20]\n", + " }],\n", + " }\n", + " \n", + "echarts_pane = pn.pane.ECharts(echart, height=800, width=800)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -169,12 +204,12 @@ " return pd.DataFrame(dict(y=ys), index=xs).hvplot(responsive=True)\n", "\n", "dmap = hv.DynamicMap(sine, kdims=['frequency', 'amplitude', 'function']).redim.range(\n", - " frequency=(0.1, 10), amplitude=(1, 10)).redim.values(function=['sin', 'cos', 'tan'])\n", + " frequency=(0.1, 10), amplitude=(1, 10)).redim.values(function=['sin', 'cos', 'tan']).opts(height=800, line_width=4)\n", "\n", "hv_panel = pn.pane.HoloViews(dmap, widgets={\n", " 'amplitude': pn.widgets.LiteralInput(value=1., type=(float, int)),\n", " 'function': pn.widgets.RadioButtonGroup,\n", - " 'frequency': {'value': 5}\n", + " 'frequency': {'value': 5}, \n", "}, center=True, sizing_mode='stretch_both').layout" ] }, @@ -208,7 +243,7 @@ "strm = ax0.streamplot(X, Y, U, V, color=U, linewidth=2, cmap=plt.cm.autumn)\n", "fig0.colorbar(strm.lines)\n", "\n", - "mpl_pane = pn.pane.Matplotlib(fig0, dpi=144)" + "mpl_pane = pn.pane.Matplotlib(fig0, dpi=144, height=800)" ] }, { @@ -256,15 +291,35 @@ "metadata": {}, "outputs": [], "source": [ - "pn.Tabs(\n", + "tabs = pn.Tabs(\n", " ('Altair', altair_pane),\n", " ('Bokeh', bokeh_pane),\n", " ('deck.GL', deck_gl),\n", + " ('Echarts', echarts_pane),\n", " ('HoloViews', hv_panel),\n", " ('Matplotlib', mpl_pane),\n", " ('Plotly', plotly_pane),\n", " dynamic=True\n", - ").servable()" + ")\n", + "tabs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve dynamic_tabs.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Dynamic Tabs\", main=[\"This example demonstrates **how to efficiently render a number of complex components in ``Tabs``** by using the `dynamic` parameter.\", tabs]).servable();" ] } ], diff --git a/examples/gallery/layout/plot_with_columns.ipynb b/examples/gallery/layout/plot_with_columns.ipynb index 449f162d10..40dd201446 100644 --- a/examples/gallery/layout/plot_with_columns.ipynb +++ b/examples/gallery/layout/plot_with_columns.ipynb @@ -11,14 +11,14 @@ "\n", "from bokeh.sampledata.autompg import autompg_clean\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This example demonstrates how to combine multiple columns of widgets into layout an overall layout." + "This example demonstrates how to combine multiple columns of widgets into an overall layout." ] }, { @@ -40,16 +40,38 @@ "def plot(x, y, color, facet):\n", " cmap = 'Category10' if color in cat else 'viridis'\n", " return autompg_clean.hvplot.scatter(\n", - " x, y, color=color or 'darkblue', by=facet, subplots=True, padding=0.1,\n", - " cmap=cmap, responsive=True, min_height=300\n", + " x, y, color=color or 'green', by=facet, subplots=True, padding=0.1,\n", + " cmap=cmap, responsive=True, min_height=500, size=100\n", " )\n", "\n", + "settings = pn.Row(pn.WidgetBox(x, y, color, facet))\n", "pn.Column(\n", " '### Auto MPG Explorer', \n", + " settings,\n", " plot,\n", - " pn.Row(pn.WidgetBox(x, y, color), pn.WidgetBox(facet)),\n", " width_policy='max'\n", - ").servable()" + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve dynamic_widget_values.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Auto MPG Explorer\", sidebar=[settings], \n", + " main=[\"This example demonstrates **how to combine multiple columns of components into an overall layout**.\", plot]\n", + ").servable();" ] } ], @@ -60,5 +82,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/links/bokeh_property_editor.ipynb b/examples/gallery/links/bokeh_property_editor.ipynb index a194c4d009..7ff5886877 100644 --- a/examples/gallery/links/bokeh_property_editor.ipynb +++ b/examples/gallery/links/bokeh_property_editor.ipynb @@ -26,11 +26,18 @@ "outputs": [], "source": [ "from bokeh.core.enums import LineDash, LineCap, MarkerType, NamedColor\n", - "from bokeh.models.plots import Model, _list_attr_splat\n", - "\n", - "def meta_widgets(model):\n", - " tabs = pn.Tabs(width=500)\n", - " widgets = get_widgets(model)\n", + "from bokeh.models.plots import Model, _list_attr_splat" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def meta_widgets(model, width=500):\n", + " tabs = pn.Tabs(width=width)\n", + " widgets = get_widgets(model, width=width-25)\n", " if widgets:\n", " tabs.append((type(model).__name__, widgets))\n", " for p, v in model.properties_with_values().items():\n", @@ -54,8 +61,15 @@ " return None\n", " elif not len(tabs) > 1:\n", " return tabs[0]\n", - " return tabs\n", - " \n", + " return tabs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "def get_widgets(model, skip_none=True, **kwargs):\n", " widgets = []\n", " for p, v in model.properties_with_values().items():\n", @@ -75,19 +89,23 @@ " w = pn.widgets.Select(options=list(NamedColor), **ps)\n", " else:\n", " w = pn.widgets.ColorPicker(**ps)\n", + " elif p==\"width\":\n", + " w = pn.widgets.IntSlider(start=400, end=800, **ps)\n", + " elif p in [\"inner_width\", \"outer_width\"]:\n", + " w = pn.widgets.IntSlider(start=0, end=20, **ps)\n", " elif p.endswith('width'):\n", " w = pn.widgets.FloatSlider(start=0, end=20, **ps)\n", " elif 'marker' in p:\n", - " w = pn.widgets.Select(name=p, options=list(MarkerType), value=v)\n", + " w = pn.widgets.Select(options=list(MarkerType), **ps)\n", " elif p.endswith('cap'):\n", - " w = pn.widgets.Select(name=p, options=list(LineCap), value=v)\n", + " w = pn.widgets.Select(options=list(LineCap), **ps)\n", " elif p == 'size':\n", " w = pn.widgets.FloatSlider(start=0, end=20, **ps)\n", " elif p.endswith('text') or p.endswith('label'):\n", " w = pn.widgets.TextInput(**ps)\n", " elif p.endswith('dash'):\n", " patterns = list(LineDash)\n", - " w = pn.widgets.Select(name=p, options=patterns, value=v or patterns[0])\n", + " w = pn.widgets.Select(options=patterns, value=v or patterns[0], **kwargs)\n", " else:\n", " continue\n", " w.jslink(model, value=p)\n", @@ -114,7 +132,29 @@ "xs = np.linspace(0, 10)\n", "r = p.scatter(xs, np.sin(xs))\n", "\n", - "pn.Row(p, meta_widgets(p))" + "editor=pn.Row(meta_widgets(p), p)\n", + "editor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve bokeh_property_editor.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Bokeh Property Editor\", \n", + " main=[pn.pane.Markdown(\"The Bokeh Property Editor enables you to fine tune the Bokeh plot.\", sizing_mode=\"stretch_width\"), editor]\n", + ").servable();" ] } ], @@ -125,5 +165,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/links/deck_gl_json_editor.ipynb b/examples/gallery/links/deck_gl_json_editor.ipynb index 3c4189b5c8..b84b42eace 100644 --- a/examples/gallery/links/deck_gl_json_editor.ipynb +++ b/examples/gallery/links/deck_gl_json_editor.ipynb @@ -16,7 +16,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This example demonstrates how to link a JSON editor to a DeckGL pane to enable live editing of a plot:" + "This example demonstrates how to `jslink` a JSON editor to a DeckGL pane to enable super fast, live editing of a plot:" ] }, { @@ -63,27 +63,39 @@ "view_editor.jscallback(args={'deck_gl': deck_gl}, value=\"deck_gl.initialViewState = JSON.parse(cb_obj.code)\")\n", "layer_editor.jscallback(args={'deck_gl': deck_gl}, value=\"deck_gl.layers = [JSON.parse(cb_obj.code)]\")\n", "\n", - "pn.Row(pn.Column(view_editor, layer_editor), deck_gl)" + "editor = pn.Row(pn.Column(view_editor, layer_editor), deck_gl)\n", + "editor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve deck_gl_json_editor.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Deck.gl Json Editor\", \n", + " main=[\n", + " pn.pane.Markdown(\"This example demonstrates two JSON editors `jslink`ed to a DeckGL pane to enable super fast, live editing of a plot:\", sizing_mode=\"stretch_width\"),\n", + " editor\n", + " ]\n", + ").servable();" ] } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.5" + "pygments_lexer": "ipython3" } }, "nbformat": 4, diff --git a/examples/gallery/links/holoviews_glyph_link.ipynb b/examples/gallery/links/holoviews_glyph_link.ipynb index 689c164d3c..73445322df 100644 --- a/examples/gallery/links/holoviews_glyph_link.ipynb +++ b/examples/gallery/links/holoviews_glyph_link.ipynb @@ -41,7 +41,7 @@ "\n", "# Declare a Points object and apply some options\n", "points = hv.Points(np.random.randn(200, 2)).options(\n", - " padding=0.1, width=500, height=500, line_color='black')\n", + " padding=0.1, height=500, line_color='black', responsive=True)\n", "\n", "# Link the widget value parameter to the property on the glyph\n", "alpha_widget.jslink(points, value='glyph.fill_alpha')\n", @@ -49,7 +49,32 @@ "color_widget.jslink(points, value='glyph.fill_color')\n", "marker_widget.jslink(points, value='glyph.marker')\n", "\n", - "pn.Row(points, pn.Column(alpha_widget, color_widget, marker_widget, size_widget))" + "editor=pn.Row(pn.Column(alpha_widget, color_widget, marker_widget, size_widget), points)\n", + "editor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve holoviews_glyph_link.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Holoviews Property Links\", \n", + " main=[\n", + " pn.pane.Markdown(\"HoloViews-generated Bokeh plots can be **`jslinked`** to widgets that control their properties. \\n\\nThis allows you to **export static HTML files that allow end-user customization** of appearance.\", sizing_mode=\"stretch_width\"), \n", + " editor\n", + " ]\n", + ").servable();" ] } ], @@ -60,5 +85,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/links/plotly_link.ipynb b/examples/gallery/links/plotly_link.ipynb index 86fea915e7..377bfb8abe 100644 --- a/examples/gallery/links/plotly_link.ipynb +++ b/examples/gallery/links/plotly_link.ipynb @@ -31,7 +31,7 @@ "fig = dict(data=contour, layout=layout)\n", "plotly_pane = pn.pane.Plotly(fig, width=600, height=500)\n", "\n", - "buttons = pn.widgets.RadioButtonGroup(value='Medium', options=['Low', 'Medium', 'High'])\n", + "buttons = pn.widgets.RadioButtonGroup(value='Medium', options=['Low', 'Medium', 'High'], button_type=\"success\")\n", "\n", "range_callback = \"\"\"\n", "var ncontours = [2, 5, 10]\n", @@ -41,7 +41,32 @@ "\n", "buttons.jslink(plotly_pane, code={'active': range_callback})\n", "\n", - "pn.Column(buttons, plotly_pane)" + "component=pn.Column(buttons, plotly_pane)\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve plotly_link.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Plotly JS Links\", main_max_width=\"650px\",\n", + " main=[\n", + " pn.pane.Markdown(\"Since Plotly plots are represented as simple JavaScript objects, we can easily define a **JS callback** to modify the data and trigger an update in a plot. \\n\\nThis allows you to **export your app as a static HTML file**.\", sizing_mode=\"stretch_width\"), \n", + " component\n", + " ]\n", + ").servable();" ] } ], @@ -52,5 +77,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/links/vega_heatmap_link.ipynb b/examples/gallery/links/vega_heatmap_link.ipynb index 31dd4a3d6a..44f74e276d 100644 --- a/examples/gallery/links/vega_heatmap_link.ipynb +++ b/examples/gallery/links/vega_heatmap_link.ipynb @@ -7,7 +7,7 @@ "outputs": [], "source": [ "import panel as pn\n", - "pn.extension('vega')" + "pn.extension('vega', sizing_mode=\"stretch_width\")" ] }, { @@ -33,7 +33,7 @@ " ]}\n", " }],\n", " \"mark\": \"rect\",\n", - " \"width\": 600,\n", + " \"width\": \"container\",\n", " \"height\": 400,\n", " \"encoding\": {\n", " \"x\": {\n", @@ -56,32 +56,92 @@ " \"stroke\": \"transparent\"\n", " }\n", " }\n", - "}\n", - "\n", - "vega = pn.pane.Vega(imdb, width=750, height=425)\n", - "\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "vega = pn.pane.Vega(imdb, height=425)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "# Declare range slider to adjust the color limits\n", "color_lims = pn.widgets.RangeSlider(name='Color limits', start=0, end=125, value=(0, 40), step=1)\n", "color_lims.jslink(vega, code={'value': \"\"\"\n", "target.data.encoding.color.scale = {domain: source.value};\n", "target.properties.data.change.emit()\n", - "\"\"\"})\n", - "\n", + "\"\"\"});" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "# Declare slider to control the number of bins along the x-axis\n", "imdb_bins = pn.widgets.IntSlider(name='IMDB Ratings Bins', start=0, end=125, value=60, step=25)\n", "imdb_bins.jslink(vega, code={'value': \"\"\"\n", "target.data.encoding.x.bin.maxbins = source.value;\n", "target.properties.data.change.emit()\n", - "\"\"\"})\n", - "\n", + "\"\"\"});" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "# Declare slider to control the number of bins along the y-axis\n", "tomato_bins = pn.widgets.IntSlider(name='Rotten Tomato Ratings Bins', start=0, end=125, value=40, step=25)\n", "tomato_bins.jslink(vega, code={'value': \"\"\"\n", "target.data.encoding.y.bin.maxbins = source.value;\n", "target.properties.data.change.emit()\n", - "\"\"\"})\n", + "\"\"\"});" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.Row(vega, pn.Column(color_lims, imdb_bins, tomato_bins, sizing_mode=\"fixed\", width=400))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", "\n", - "pn.Row(vega, pn.Column(color_lims, imdb_bins, tomato_bins))" + "Lets wrap it into nice template that can be served via `panel serve vega_heatmap_link.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Vega Heatmap w. JS Links\", \n", + " sidebar=[color_lims, imdb_bins, tomato_bins],\n", + " main=[\n", + " pn.pane.Markdown(\"This example demonstrates how to link Panel widgets to a **Vega pane** by editing the Vega spec using **js callbacks** and triggering updates in the plot.\"), \n", + " vega\n", + " ]\n", + ").servable();" ] } ], @@ -92,5 +152,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/param/action_button.ipynb b/examples/gallery/param/action_button.ipynb index 1fcf0ad33e..cbc076e60f 100644 --- a/examples/gallery/param/action_button.ipynb +++ b/examples/gallery/param/action_button.ipynb @@ -9,14 +9,16 @@ "import param\n", "import panel as pn\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This example demonstrates how to use ``param.Action`` to trigger an update in a method that depends on that parameter. Actions can trigger any function, but if we simply want to trigger a method that depends on that action we can define a small ``lambda`` function that triggers the parameter explicitly." + "## param.Action Example\n", + "\n", + "This example demonstrates how to use ``param.Action`` to trigger an update in a method that depends on that parameter. Actions can trigger any function, but if we simply want to trigger a method that depends on that action, then we can define a small ``lambda`` function that triggers the parameter explicitly." ] }, { @@ -30,22 +32,47 @@ " Demonstrates how to use param.Action to trigger an update.\n", " \"\"\"\n", "\n", - " number = param.Number(default=0)\n", - " \n", " action = param.Action(lambda x: x.param.trigger('action'), label='Click here!')\n", + " \n", + " number = param.Integer(default=0)\n", " \n", " @param.depends('action')\n", " def get_number(self):\n", + " self.number += 1\n", " return self.number\n", " \n", "action_example = ActionExample()\n", - "pn.Column(\n", - " '# param.Action Example',\n", + "component = pn.Column(\n", " pn.Row(\n", - " pn.Column(pn.panel(action_example.param, show_labels=False, show_name=False, margin=0),\n", - " 'Click the button to trigger an update in the output.'),\n", - " pn.WidgetBox(action_example.get_number, width=300))\n", - ").servable()" + " pn.Column(pn.panel(action_example, show_name=False, margin=0, widgets={\"action\": {\"button_type\": \"primary\"}, \"number\": {\"disabled\": True}}),\n", + " '**Click the button** to trigger an update in the output.'),\n", + " pn.panel(action_example.get_number, width=300), max_width=600)\n", + ")\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve action_button.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"param.Action Example\", \n", + " main=[\n", + " \"This example demonstrates **how to use ``param.Action`` to trigger an update** in a method that depends on that parameter.\\n\\nActions can trigger any function, but if we simply want to trigger a method that depends on that action, then we can define a small ``lambda`` function that triggers the parameter explicitly.\",\n", + " component,\n", + " ]\n", + ").servable();" ] } ], @@ -56,5 +83,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/param/deck_gl_global_power_plants.ipynb b/examples/gallery/param/deck_gl_global_power_plants.ipynb index f5b08319d0..c1591ef299 100644 --- a/examples/gallery/param/deck_gl_global_power_plants.ipynb +++ b/examples/gallery/param/deck_gl_global_power_plants.ipynb @@ -8,7 +8,7 @@ "source": [ "import panel as pn\n", "import pydeck as pdk\n", - "pn.extension('deckgl')" + "pn.extension('deckgl', sizing_mode=\"stretch_width\")" ] }, { @@ -195,25 +195,34 @@ " self.pane.param.trigger('object')\n", " \n", " def view(self):\n", - " return pn.Row(pn.Column(self.param, self._info), self.pane)\n", + " return pn.Row(pn.Column(self.param, pn.panel(self._info, height=200)), self.pane)\n", "\n", - "app = GlobalPowerPlantDatabaseApp()\n", - "app.view().servable()" + "component = GlobalPowerPlantDatabaseApp()\n", + "component.view()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Credits\n", + "## App\n", "\n", - "The DeckGl pane and this reference example was contributed by\n", - "\n", - "- [Marc Skov Madsen](https://datamodelsanalytics.com)\n", - "\n", - "and improved by\n", - "\n", - "- Philipp Rüdiger" + "Lets wrap it into nice template that can be served via `panel serve deck_gl_global_power_plants.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Global Power Plants\", \n", + " sidebar=[pn.Param(component, show_name=False)], \n", + " main=[\n", + " \"The data is from the [Global Power Plant Database](http://datasets.wri.org/dataset/540dcf46-f287-47ac-985d-269b04bea4c6/resource/c240ed2e-1190-4d7e-b1da-c66b72e08858/download/globalpowerplantdatabasev120).\",\n", + " pn.Column(component.pane, pn.panel(component._info, height=100))\n", + " ]\n", + " ).servable();" ] } ], diff --git a/examples/gallery/param/download_upload_csv.ipynb b/examples/gallery/param/download_upload_csv.ipynb index 0cbaec5856..d396cb5fcd 100644 --- a/examples/gallery/param/download_upload_csv.ipynb +++ b/examples/gallery/param/download_upload_csv.ipynb @@ -8,9 +8,7 @@ "\n", "In Panel the FileDownload widget allows downloading a file generated on the server the app is running on while the `FileInput` widget allows uploading a file. In this example we demonstrate a pipeline of two little apps one which allows generating a sample data CSV file and one which allows uploading this file and displays it as a Plotly plot. \n", "\n", - "For more details on how to use these components see [`FileInput`](../../reference/widgets/FileInput.ipynb) and [`FileDownload`](../../reference/widgets/FileDownload.ipynb) reference guides.\n", - "\n", - "**Authors**: [Marc Skov Madsen](https://datamodelsanalytics.com/) and Philipp Rudiger" + "For more details on how to use these components see [`FileInput`](../../reference/widgets/FileInput.ipynb) and [`FileDownload`](../../reference/widgets/FileDownload.ipynb) reference guides." ] }, { @@ -29,7 +27,7 @@ "\n", "import plotly.express as px\n", "\n", - "pn.extension('plotly')" + "pn.extension('plotly', sizing_mode=\"stretch_width\")" ] }, { @@ -65,17 +63,18 @@ " sample_df = param.DataFrame(doc=\"\"\"\n", " The current dataframe of samples.\"\"\")\n", " \n", - " generate_sample_df = param.Action(lambda self: self.update_sample_df(), doc=\"\"\"\n", + " generate_sample_df = param.Action(lambda self: self.update_sample_df(), label=\"Generate Data\", doc=\"\"\"\n", " An action callback which will update the sample_df.\"\"\")\n", " \n", - " file_name = param.String(default=\"sample_data.csv\", doc=\"\"\"\n", + " file_name = param.String(default=\"data.csv\", doc=\"\"\"\n", " The filename to save to.\"\"\")\n", " \n", " def __init__(self, **params):\n", " super().__init__(**params)\n", " self.update_sample_df()\n", - " self.download = pn.widgets.FileDownload(filename=self.file_name,\n", - " callback=self._download_callback)\n", + " self.download = pn.widgets.FileDownload(name=\"Download Data\", filename=self.file_name, callback=self._download_callback, button_type=\"primary\")\n", + " self.table = pn.widgets.Tabulator(self.sample_df.head(10), layout='fit_data_stretch', theme='site', height=360)\n", + " \n", "\n", " @pn.depends('file_name', watch=True)\n", " def _update_filename(self):\n", @@ -103,7 +102,11 @@ " \"FubId\": [random.choice(self.fub_ids) for _ in range(0,self.samples)],\n", " }\n", " self.sample_df = pd.DataFrame(sample_data) \n", - " \n", + " \n", + " @pn.depends(\"sample_df\", watch=True)\n", + " def _update_table(self):\n", + " if hasattr(self, \"table\"):\n", + " self.table.value = self.sample_df.head(10)\n", " \n", " def save_sample_data(self, event=None):\n", " if not self.sample_df is None:\n", @@ -111,15 +114,18 @@ " \n", " def view(self):\n", " return pn.Column(\n", + " \"## Generate and Download Data\",\n", " pn.Row(\n", - " pn.Param(self, parameters=['samples', 'voltage_bounds', 'time_bounds']),\n", - " pn.Column(self.param.generate_sample_df, self.param.file_name, self.download, align='end')\n", + " pn.Param(self, parameters=['samples', 'voltage_bounds', 'time_bounds', 'generate_sample_df'], show_name=False, widgets={\"generate_sample_df\": {\"button_type\": \"primary\"}}),\n", + " pn.Column(self.param.file_name, self.download, align='end', margin=(10,5,5,5)),\n", " ),\n", - " self.param.sample_df,\n", + " \"**Sample data (10 Rows)**\",\n", + " self.table,\n", " )\n", "\n", "sample_data_app = SampleDataApp()\n", - "sample_data_app.view()" + "sample_data_app_view = sample_data_app.view()\n", + "sample_data_app_view" ] }, { @@ -150,8 +156,11 @@ " @pn.depends(\"file_input.value\", watch=True)\n", " def _parse_file_input(self):\n", " value = self.file_input.value\n", - " string_io = io.StringIO(value.decode(\"utf8\"))\n", - " self.data = pd.read_csv(string_io, parse_dates=[\"Time\"])\n", + " if value:\n", + " string_io = io.StringIO(value.decode(\"utf8\"))\n", + " self.data = pd.read_csv(string_io, parse_dates=[\"Time\"])\n", + " else:\n", + " print(\"error\")\n", "\n", " @pn.depends('data', watch=True)\n", " def get_plot(self):\n", @@ -169,13 +178,15 @@ " \n", " def view(self):\n", " return pn.Column(\n", + " \"## Upload and Plot Data\",\n", " self.file_input,\n", " self.plotly_pane,\n", " )\n", " \n", "voltage_app = VoltageApp()\n", "\n", - "voltage_app.view()" + "voltage_app_view = voltage_app.view()\n", + "voltage_app_view" ] }, { @@ -191,25 +202,39 @@ "metadata": {}, "outputs": [], "source": [ - "sample_data_app = SampleDataApp()\n", - "voltage_app = VoltageApp()\n", - "\n", "description = \"\"\"\n", - "This application demonstrates the ability to download a file using the FileDownload widget \n", - "and uploading a file using the FileInput widget.\n", + "This application demonstrates the ability to **download** a file using the `FileDownload` widget \n", + "and **upload** a file using the `FileInput` widget.\n", "

\n", - "Try filtering the data on the left, download the file by clicking on the Download button\n", + "Try filtering the data, download the file by clicking on the Download button\n", "and then plot it on the right by uploading that same file.\n", "\"\"\"\n", "\n", - "pn.Row(\n", - " sample_data_app.view(),\n", - " pn.Column(\n", - " description,\n", - " voltage_app.view(),\n", - " ),\n", + "component = pn.Column(\n", + " description,\n", + " sample_data_app_view,\n", + " voltage_app_view,\n", " sizing_mode='stretch_both'\n", - ").servable()" + ")\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve download_upload_csv.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Download and Upload CSV File\", main=[ description, sample_data_app_view, voltage_app_view,]).servable();" ] } ], diff --git a/examples/gallery/param/loading_indicator.ipynb b/examples/gallery/param/loading_indicator.ipynb index 1a799df1db..14d3fbca7e 100644 --- a/examples/gallery/param/loading_indicator.ipynb +++ b/examples/gallery/param/loading_indicator.ipynb @@ -12,24 +12,21 @@ "import numpy as np\n", "import holoviews.plotting.bokeh\n", "\n", - "pn.extension(loading_spinner='dots', loading_color='#00aa41')\n", + "pn.extension(loading_spinner='dots', loading_color='#00aa41', sizing_mode=\"stretch_width\")\n", "hv.extension('bokeh')" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pn.panel(hv.Curve([1, 2, 3], label='ABC').opts(fontsize={'title': '18pt'}))" - ] - }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Every pane, widget and layout provides the `loading` parameter. When set to `True` a spinner will overlay the panel and indicate that the panel is currently loading. When you set `loading` to false the spinner is removed. Using the `pn.extension` or by setting the equivalent parameters on `pn.config` we can select between different visual styles and colors for the loading indicator.\n", + "Every pane, widget and layout provides the **`loading` parameter**. When set to `True` a spinner will overlay the panel and indicate that the panel is currently loading. When you set `loading` to false the spinner is removed. \n", + "\n", + "Using the `pn.extension` or by setting the equivalent parameters on `pn.config` we can select between different visual styles and colors for the loading indicator.\n", + "\n", + "```python\n", + "pn.extension(loading_spinner='dots', loading_color='#00aa41')\n", + "```\n", "\n", "We can enable the loading indicator for reactive functions annotated with `depends` or `bind` globally using:\n", "\n", @@ -51,14 +48,50 @@ "metadata": {}, "outputs": [], "source": [ - "button = pn.widgets.Button(name=\"Update\", button_type=\"primary\")\n", + "button = pn.widgets.Button(name=\"UPDATE\", button_type=\"primary\")\n", "\n", "def random_plot(event):\n", - " if event: time.sleep(10)\n", + " if event: time.sleep(2)\n", " return hv.Points(np.random.rand(100, 2)).opts(\n", - " width=400, height=400, size=5)\n", + " width=400, height=400, size=8, color=\"green\")\n", "\n", - "pn.Column(button, pn.panel(pn.bind(random_plot, button), loading_indicator=True)).servable()" + "component = pn.Column(button, pn.panel(pn.bind(random_plot, button), loading_indicator=True))\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve download_upload_csv.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "description = \"\"\"\n", + "Every pane, widget and layout provides the **`loading` parameter**. When set to `True` a spinner will overlay the panel and indicate that the panel is currently loading. When you set `loading` to false the spinner is removed. \n", + "\n", + "Using the `pn.extension` or by setting the equivalent parameters on `pn.config` we can select between different visual styles and colors for the loading indicator.\n", + "\n", + "```python\n", + "pn.extension(loading_spinner='dots', loading_color='#00aa41')\n", + "```\n", + "\n", + "We can enable the loading indicator for reactive functions annotated with `depends` or `bind` globally using:\n", + "\n", + "```python\n", + "pn.param.ParamMethod.loading_indicator = True\n", + "```\n", + "\"\"\"\n", + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Loading Indicator\", \n", + " main=[ description, component]).servable();" ] } ], diff --git a/examples/gallery/param/param_subobjects.ipynb b/examples/gallery/param/param_subobjects.ipynb index 47d3663858..2406c941c4 100644 --- a/examples/gallery/param/param_subobjects.ipynb +++ b/examples/gallery/param/param_subobjects.ipynb @@ -46,7 +46,7 @@ " if 'style' not in params:\n", " params['style'] = Style(name='Style')\n", " super(Shape, self).__init__(**params)\n", - " self.figure = figure(x_range=(-1, 1), y_range=(-1, 1), width=400, height=400)\n", + " self.figure = figure(x_range=(-1, 1), y_range=(-1, 1), sizing_mode=\"stretch_width\", height=400)\n", " self.renderer = self.figure.line(*self._get_coords())\n", " self._update_style()\n", "\n", @@ -119,17 +119,39 @@ " return '## %s (radius=%.1f)' % (type(self.shape).__name__, self.shape.radius)\n", " \n", " def panel(self):\n", - " return pn.Column(self.title, self.view)\n", + " return pn.Column(self.title, self.view, sizing_mode=\"stretch_width\")\n", " \n", " \n", "# Instantiate and display ShapeViewer\n", "viewer = ShapeViewer()\n", "subpanel = pn.Column()\n", "\n", - "pn.Row(\n", - " pn.Column(pn.Param(viewer.param, expand_layout=subpanel), subpanel),\n", + "component = pn.Row(\n", + " pn.Column(pn.Param(viewer.param, expand_layout=subpanel, name=\"Shape Settings\"), subpanel),\n", " viewer.panel(),\n", - ").servable()" + ")\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve param_subobjects.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Param Sub Objects\", main=[ \n", + " pn.pane.Markdown(\"This example demonstrates how to use the `Param` library to express **nested hierarchies of classes** whose parameters can be edited in Panel or any other GUI.\", sizing_mode=\"stretch_width\"), \n", + " component,\n", + "]).servable();" ] } ], @@ -140,5 +162,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/param/precedence.ipynb b/examples/gallery/param/precedence.ipynb index 265c5fc667..ecb8897cd7 100644 --- a/examples/gallery/param/precedence.ipynb +++ b/examples/gallery/param/precedence.ipynb @@ -74,8 +74,15 @@ " self.param.z.precedence = self.z_precedence \n", " self.dummy_app.display_threshold = self.dummy_app_display_threshold\n", "\n", - "precedence_model = Precedence()\n", - "\n", + "precedence_model = Precedence()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "# Bulding the control app as a Param pane too.\n", "control_app = pn.Param(\n", " precedence_model.param,\n", @@ -86,8 +93,15 @@ " \"z_precedence\": {\"background\": \"#00c0d9\"},\n", " },\n", " show_name=False\n", - ")\n", - "\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "# Building the complete interactive example.\n", "interactive_precedence_app = pn.Column(\n", " \"## Precedence Example\",\n", @@ -97,7 +111,7 @@ " pn.Column(\"**Dummy app**\", precedence_model.dummy_app)\n", " )\n", ")\n", - "interactive_precedence_app.servable()" + "interactive_precedence_app" ] }, { @@ -105,7 +119,13 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Parameter Precedence\", main_max_width=\"700px\",\n", + " main=[\n", + " pn.pane.Markdown(\"This example demonstrates how to order and hide widgets by means of the **``precedence`` and ``display_threshold``** parameter attributes.\", sizing_mode=\"stretch_width\"),\n", + " interactive_precedence_app,\n", + " ]).servable();" + ] } ], "metadata": { diff --git a/examples/gallery/param/reactive_plots.ipynb b/examples/gallery/param/reactive_plots.ipynb index 1b7da32a99..93d7eb4b91 100644 --- a/examples/gallery/param/reactive_plots.ipynb +++ b/examples/gallery/param/reactive_plots.ipynb @@ -19,7 +19,7 @@ "\n", "from bokeh.sampledata.iris import flowers\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -61,10 +61,13 @@ " \n", " @param.depends('X_variable', 'Y_variable')\n", " def plot(self):\n", - " return flowers.hvplot.scatter(x=self.X_variable, y=self.Y_variable, by='species')\n", + " return flowers.hvplot.scatter(x=self.X_variable, y=self.Y_variable, by='species').opts(height=600)\n", " \n", " def panel(self):\n", - " return pn.Row(self.param, self.plot)\n", + " return pn.Row(\n", + " pn.Param(self, width=300, name = \"Plot Settings\", sizing_mode=\"fixed\"), \n", + " self.plot\n", + " )\n", "\n", "dashboard = IrisDashboard(name='Iris_Dashboard')" ] @@ -82,7 +85,30 @@ "metadata": {}, "outputs": [], "source": [ - "dashboard.panel().servable()" + "component = dashboard.panel()\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve reactive_plots.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Machine Learning Data Visualization\", \n", + " main=[\n", + " \"The [iris dataset](https://en.wikipedia.org/wiki/Iris_flower_data_set) is a standard example used to illustrate **machine-learning and visualization techniques**.\\n\\nHere, we show how to use [Panel](http://panel.pyviz.org) to create a dashboard for visualizing the dataset. The Panel dashboard uses [hvPlot](http://hvplot.pyviz.org) to create plots and [Param](https://param.pyviz.org) objects to create options for selecting the `X` and `Y` axis for the plot.\",\n", + " component \n", + " ]).servable();" ] } ], @@ -93,5 +119,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/param/reactive_tables.ipynb b/examples/gallery/param/reactive_tables.ipynb index 5080fb96b2..f5aa6bddf1 100644 --- a/examples/gallery/param/reactive_tables.ipynb +++ b/examples/gallery/param/reactive_tables.ipynb @@ -13,7 +13,7 @@ "from bokeh.sampledata.autompg import autompg_clean\n", "from bokeh.sampledata.population import data\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -31,11 +31,9 @@ "source": [ "class ReactiveTables(param.Parameterized):\n", " \n", - " title = param.String(default='Data Summary')\n", - " \n", " dataset = param.ObjectSelector(default='iris', objects=['iris', 'autompg', 'population'])\n", " \n", - " rows = param.Integer(default=10, bounds=(0, 100))\n", + " rows = param.Integer(default=10, bounds=(0, 19))\n", " \n", " @param.depends('dataset')\n", " def data(self):\n", @@ -50,22 +48,40 @@ " def summary(self):\n", " return self.data().describe()\n", " \n", - " @param.depends('title')\n", - " def header(self):\n", - " return '##' + self.title\n", - " \n", " @param.depends('data', 'rows')\n", " def table(self):\n", " return self.data().iloc[:self.rows]\n", " \n", " def panel(self):\n", " return pn.Row(\n", - " self.param,\n", - " pn.Column(self.header, self.summary, self.table),\n", + " pn.Param(self, name=\"Settings\", width=300, sizing_mode=\"fixed\"),\n", + " pn.Column(\"## Description\", self.summary, \"## Table\", self.table),\n", " min_height=1000)\n", " \n", - "reactive = ReactiveTables()\n", - "reactive.panel().servable()" + "component = ReactiveTables().panel()\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve reactive_tables.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(site=\"Panel\", title=\"Reactive Data Tables\", \n", + " main=[\n", + " \"This example demonstrates [Panel's](https://panel.holoviz.org) reactive programming paradigm using the [Param](https://param.holoviz.org) library to express parameters, plus methods with computation depending on those parameters. \\n\\nThis pattern can be used to update the plots and tables whenever a parameter value changes, without re-running computations unnecessarily.\",\n", + " component \n", + " ]).servable();" ] } ], @@ -76,5 +92,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/simple/altair_choropleth.ipynb b/examples/gallery/simple/altair_choropleth.ipynb index 084a14b3cf..809bd75097 100644 --- a/examples/gallery/simple/altair_choropleth.ipynb +++ b/examples/gallery/simple/altair_choropleth.ipynb @@ -32,9 +32,6 @@ "source = 'https://raw.githubusercontent.com/vega/vega/master/docs/data/population_engineers_hurricanes.csv'\n", "variable_list = ['population', 'engineers', 'hurricanes']\n", "\n", - "variable = pn.widgets.Select(options=variable_list, name='Variable')\n", - "\n", - "@pn.depends(variable.param.value)\n", "def get_map(variable):\n", " return alt.Chart(states).mark_geoshape().encode(\n", " alt.Color(variable, type='quantitative')\n", @@ -42,18 +39,51 @@ " lookup='id',\n", " from_=alt.LookupData(source, 'id', [variable])\n", " ).properties(\n", - " width=500,\n", - " height=300\n", + " width=\"container\",\n", + " height=300,\n", " ).project(\n", " type='albersUsa'\n", " ).repeat(\n", " row=[variable]\n", " )\n", "\n", + "variable = pn.widgets.Select(options=variable_list, name='Variable', width=250)\n", + "logo = pn.panel(altair_logo, height=150, align=\"center\")\n", + "vega_panel = pn.pane.Vega(sizing_mode=\"stretch_width\", margin=(10,100,10,5))\n", + " \n", + "@pn.depends(variable.param.value, watch=True)\n", + "def update_vega_pane(variable):\n", + " vega_panel.object = get_map(variable)\n", + "\n", + "update_vega_pane(variable.value)\n", + " \n", "pn.Row(\n", - " pn.Column('# Altair Choropleth Maps', pn.panel(altair_logo, height=150), variable),\n", - " get_map\n", - ").servable()" + " pn.Column('# Altair Choropleth Maps', logo, variable),\n", + " vega_panel\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve altair_chropleth.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Altair Choropleth Maps\", \n", + " sidebar=[logo, variable], \n", + " main=[\"A simple example demonstrating **how to use a *reactive function* depending on a single widget**, to render Altair/Vega plots.\", vega_panel]\n", + ").servable();" ] } ], @@ -64,5 +94,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/simple/clifford_interact.ipynb b/examples/gallery/simple/clifford_interact.ipynb index 5857a02adf..eeff26cd12 100644 --- a/examples/gallery/simple/clifford_interact.ipynb +++ b/examples/gallery/simple/clifford_interact.ipynb @@ -15,7 +15,7 @@ "from datashader import transfer_functions as tf\n", "from colorcet import palette_n\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -49,14 +49,41 @@ " agg = cvs.points(df, 'x', 'y')\n", " return tf.shade(agg, cmap=cmap)\n", "\n", - "pane = pn.interact(clifford_plot, a=(0,2), b=(0,2), c=(0,2), d=(0,2), n=(1,2e7), cmap=ps)\n", + "pane = pn.interact(clifford_plot, a=(0,2), b=(0,2), c=(0,2), d=(0,2), n=(int(1),int(2e7)), cmap=ps)\n", + "\n", "logo = \"https://tinyurl.com/y9c2zn65/logo_stacked_s.png\"\n", - "text = \"\"\"

Use the widgets to vary the parameters of this \n", - "Clifford attractor.\n", - "

Note that many values result in nearly blank plots that contain only \n", - "a few scattered points.

\"\"\"\n", + "text = pn.pane.Markdown(\"\"\"\n", + "This example demonstrates **how to use the ``pn.interact`` function** to trigger updates in an image of a Clifford [attractor](https://en.wikipedia.org/wiki/Attractor) generated using the [Datashader](https://datashader.org) library. We speed up things using the **[numba](http://numba.pydata.org/) `jit` decorator**.\n", + "\n", + "You can **use the widgets** to vary the parameters of this [Clifford attractor](https://anaconda.org/jbednar/clifford_attractor).\n", + "\n", + "**Many values result in nearly blank plots** that contain only a few scattered points.\"\"\")\n", + "\n", + "pn.Row(pn.Column(logo, text, pane[0], width=400, sizing_mode=\"fixed\"), pn.layout.VSpacer(width=50), pane[1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", "\n", - "pn.Row(pn.Column(logo, text, pane[0]), pane[1]).servable()" + "Lets wrap it into nice template that can be served via `panel serve clifford_interact.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Clifford Attractor using Panel Interact, Numba and Datashader\", \n", + " sidebar=[logo, pane[0]], \n", + " main=[text, pane[1]],\n", + " main_max_width=\"650px\"\n", + ").servable();" ] } ], diff --git a/examples/gallery/simple/color_speech_recognition.ipynb b/examples/gallery/simple/color_speech_recognition.ipynb index d698d806ea..ce62a55268 100644 --- a/examples/gallery/simple/color_speech_recognition.ipynb +++ b/examples/gallery/simple/color_speech_recognition.ipynb @@ -10,7 +10,7 @@ "\n", "from panel.widgets import SpeechToText, GrammarList\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -74,23 +74,38 @@ "grammar_list = GrammarList()\n", "grammar_list.add_from_string(src, 1)\n", "\n", - "speech_to_text_color.grammars = grammar_list\n", - "\n", - "colors_html = \", \".join(\n", + "speech_to_text_color.grammars = grammar_list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "colors_html = \"Try \" + \", \".join(\n", " [f\"{color}\" for color in colors]\n", ")\n", - "content_html = f\"\"\"\n", - "

Speech Color Changer

\n", + "content = f\"\"\"\n", + "**Tap/click the microphone icon** and **say a color** to change the background color of the app.\n", "\n", - "

Tap/click the microphone icon and say a color to change the background color of the app. Try {colors_html}\n", + "Please **use Chrome** as it has the best support for the Speech to Text Api.\n", "\"\"\"\n", "\n", - "content_panel = pn.pane.HTML(content_html, sizing_mode=\"stretch_width\")\n", - "\n", - "app = pn.Column(height=500, width=500, css_classes=[\"color-app\"])\n", + "content_panel = pn.pane.Markdown(content)\n", + "colors_panel = pn.pane.HTML(colors_html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app = pn.Column(height=700, css_classes=[\"color-app\"])\n", "style_panel = pn.pane.HTML(width=0, height=0, sizing_mode=\"fixed\")\n", "\n", - "result_panel = pn.pane.Markdown(sizing_mode=\"stretch_width\")\n", + "result_panel = pn.pane.Markdown()\n", "\n", "@pn.depends(speech_to_text_color, watch=True)\n", "def update_result_panel(results_last):\n", @@ -100,16 +115,32 @@ " result_panel.object = \"Result received: \" + results_last\n", " else:\n", " app.background = \"white\"\n", - " result_panel.object = \"Result received: \" + results_last + \" (Not recognized)\"\n", - "\n", + " result_panel.object = \"Result received: \" + results_last + \" (Not recognized)\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "app[:] = [\n", " style_panel,\n", " content_panel,\n", " speech_to_text_color,\n", " result_panel,\n", + " colors_html,\n", "]\n", + "app" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", "\n", - "app.servable()" + "Lets wrap it into nice template that can be served via `panel serve color_speech_recognition.ipynb`" ] }, { @@ -117,7 +148,13 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Speech Recognition - Color App\", \n", + " main=[app], main_max_width=\"768px\"\n", + ").servable();" + ] } ], "metadata": { diff --git a/examples/gallery/simple/deckgl_game_of_life.ipynb b/examples/gallery/simple/deckgl_game_of_life.ipynb index 13d3cf5641..d54649d8c5 100644 --- a/examples/gallery/simple/deckgl_game_of_life.ipynb +++ b/examples/gallery/simple/deckgl_game_of_life.ipynb @@ -11,7 +11,7 @@ "import pandas as pd\n", "import panel as pn\n", "\n", - "pn.extension('deckgl')" + "pn.extension('deckgl', sizing_mode=\"stretch_width\")" ] }, { @@ -172,11 +172,11 @@ "def toggle_periodic_callback(event):\n", " if event.new:\n", " periodic_toggle.name = 'Stop'\n", - " periodic_toggle.button_type = 'danger'\n", + " periodic_toggle.button_type = 'warning'\n", " periodic_cb.start()\n", " else:\n", " periodic_toggle.name = 'Run'\n", - " periodic_toggle.button_type = 'success'\n", + " periodic_toggle.button_type = 'primary'\n", " periodic_cb.stop()\n", " \n", "def update_period(event):\n", @@ -198,7 +198,7 @@ "source": [ "board = new_board(30, 30)\n", "\n", - "gol = pn.pane.DeckGL(board_json, width=600, height=600)\n", + "gol = pn.pane.DeckGL(board_json, height=400)\n", "\n", "run_gol()\n", "\n", @@ -216,11 +216,56 @@ "\n", "periodic_cb = pn.state.add_periodic_callback(run_gol, start=False, period=period.value)\n", "\n", + "settings = pn.Row(period, periodic_toggle, reset, width=400, sizing_mode=\"fixed\")\n", + "\n", "pn.Column(\n", " '## Game of Life (using Deck.GL)',\n", " gol,\n", - " pn.Row(period, periodic_toggle, reset)\n", - ").servable()" + " settings,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve deckgl_game_of_life.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "description = \"\"\"\n", + "**Conway's Game of Life** is a classic demonstration of *emergence*, where higher level patterns form from a few simple rules. Fantastic patterns emerge when the game is let to run long enough.\n", + "\n", + "The **rules** here, to borrow from [Wikipedia](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life), are as follows:\n", + "\n", + "- Any live cell with fewer than two live neighbours dies, as if by underpopulation.\n", + "- Any live cell with two or three live neighbours lives on to the next generation.\n", + "- Any live cell with more than three live neighbours dies, as if by overpopulation.\n", + "- Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.\n", + "\n", + "This demo was **adapted from [PyDeck's Conway Game of Life example](https://github.com/uber/deck.gl/blob/66c75051d5b385db31f0a4322dff054779824783/bindings/pydeck/examples/06%20-%20Conway's%20Game%20of%20Life.ipynb)**, full copyright lies with the original authors.\n", + "\n", + "This modified example demonstrates **how to display and update a `DeckGL` pane with a periodic callback** by modifying the JSON representation and triggering an update.\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Deck.gl - Game of Life\", \n", + " main=[ pn.Column(description, settings), gol, ], main_max_width=\"768px\",\n", + ").servable();" ] } ], diff --git a/examples/gallery/simple/defer_data_load.ipynb b/examples/gallery/simple/defer_data_load.ipynb index 429f671234..f8d49772c9 100644 --- a/examples/gallery/simple/defer_data_load.ipynb +++ b/examples/gallery/simple/defer_data_load.ipynb @@ -8,7 +8,10 @@ "source": [ "import panel as pn\n", "import pandas as pd\n", - "import hvplot.pandas" + "import hvplot.pandas\n", + "import time\n", + "\n", + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -26,7 +29,7 @@ "source": [ "stocks_url = 'https://raw.githubusercontent.com/vega/datalib/master/test/data/stocks.csv'\n", "\n", - "select_ticker = pn.widgets.Select(name='Stock Ticker')\n", + "select_ticker = pn.widgets.Select(name='Stock Ticker', width=250, sizing_mode=\"fixed\")\n", "\n", "def load_data():\n", " if 'stocks' not in pn.state.cache: \n", @@ -57,9 +60,36 @@ "def plot_ticker(ticker):\n", " if 'stocks' not in pn.state.cache or not ticker:\n", " return pn.indicators.LoadingSpinner(value=True)\n", - " return pn.state.cache['stocks'].loc[ticker].hvplot.line('date', 'price')\n", + " time.sleep(0.5)\n", + " return pn.state.cache['stocks'].loc[ticker].hvplot.line('date', 'price', color=\"#C01754\", line_width=6)\n", + "\n", + "pn.Row(select_ticker, plot_ticker)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", "\n", - "pn.Row(select_ticker, plot_ticker).servable()" + "Lets wrap it into nice template that can be served via `panel serve defer_data_load.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Defer Data Load\", \n", + " sidebar=[select_ticker], \n", + " main=[\n", + " \"This app demonstrates how to **defer the loading** of the data and population of the widgets until the page is rendered\",\n", + " plot_ticker,\n", + " ]\n", + ").servable();" ] } ], diff --git a/examples/gallery/simple/file_download_examples.ipynb b/examples/gallery/simple/file_download_examples.ipynb index 2b70445cad..c396a96455 100644 --- a/examples/gallery/simple/file_download_examples.ipynb +++ b/examples/gallery/simple/file_download_examples.ipynb @@ -6,9 +6,7 @@ "source": [ "# File Download Example\n", "\n", - "The **purpose** of this notebook is to provide code examples and **code snippets** that enable you to quickly add FileDownload to your Panel dashboard or application.\n", - "\n", - "This notebook was originally contributed because I had problems creating the right code to enable downloading DataFrames in `xlsx` format. See [FileDownload widget produces empty file for dataframe](https://github.com/holoviz/panel/issues/1241)." + "The **purpose** of this notebook is to provide code examples and **code snippets** that enable you to quickly add FileDownload to your Panel dashboard or application." ] }, { @@ -17,32 +15,86 @@ "metadata": {}, "outputs": [], "source": [ + "import numpy as np\n", "import pandas as pd\n", "import panel as pn\n", "from io import BytesIO\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Source: Pandas DataFrame" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data=pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Target: `.csv`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def get_csv():\n", + " return BytesIO(data.to_csv().encode())\n", + "\n", + "file_download_csv = pn.widgets.FileDownload(filename=\"data.csv\", callback=get_csv, button_type=\"primary\")\n", + "file_download_csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Source: DataFrame" + "### Target: `.csv.zip`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def get_csv_zip():\n", + " output = BytesIO()\n", + " output.name = \"data.csv\"\n", + " data.to_csv(output, compression=\"zip\")\n", + " output.seek(0)\n", + " return output\n", + "\n", + "file_download_csv_zip = pn.widgets.FileDownload(filename=\"data.csv.zip\", callback=get_csv_zip, button_type=\"primary\")\n", + "file_download_csv_zip" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### File: XLSX\n", + "### Target: `.xlsx`\n", "\n", - "Please note you need to have the packages\n", + "Please note you need to install one of the packages\n", "\n", - "- [XlsxWriter](https://xlsxwriter.readthedocs.io/index.html)\n", + "- [XlsxWriter](https://xlsxwriter.readthedocs.io/index.html) or\n", "- [OpenPyXL](https://openpyxl.readthedocs.io/en/stable/)\n", "\n", - "installed for being able to use the `.to_excel` method of a DataFrame." + "to be able to use the `.to_excel` method of a DataFrame." ] }, { @@ -51,9 +103,7 @@ "metadata": {}, "outputs": [], "source": [ - "data=pd.DataFrame({\"a\": [1]})\n", - "\n", - "def get_file():\n", + "def get_xlsx():\n", " output = BytesIO()\n", " writer = pd.ExcelWriter(output, engine='xlsxwriter')\n", " data.to_excel(writer, sheet_name=\"Data\")\n", @@ -61,8 +111,54 @@ " output.seek(0) # Important!\n", " return output\n", "\n", - "file_download = pn.widgets.FileDownload(filename=\"data.xlsx\", callback=get_file)\n", - "file_download" + "file_download_xlsx = pn.widgets.FileDownload(filename=\"data.xlsx\", callback=get_xlsx, button_type=\"primary\")\n", + "file_download_xlsx" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Target: `.json`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def get_json():\n", + " return BytesIO(data.to_json(orient=\"records\").encode())\n", + "\n", + "file_download_json = pn.widgets.FileDownload(filename=\"data.json\", callback=get_json, button_type=\"primary\")\n", + "file_download_json" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Target: `.parquet`\n", + "\n", + "Please note you need to have the `pyarrow` package installed for this to work." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def get_parquet():\n", + " output = BytesIO()\n", + " output.name = \"data.parquet\"\n", + " data.to_parquet(output)\n", + " output.seek(0)\n", + " return output\n", + "\n", + "file_download_parquet = pn.widgets.FileDownload(filename=\"data.parquet\", callback=get_parquet, button_type=\"primary\")\n", + "file_download_parquet" ] }, { @@ -71,16 +167,34 @@ "source": [ "## Contributions\n", "\n", - "Example Contributions are very welcome. For example for `DataFrame` to `csv`, `parquet` and `json`." + "Example Contributions are very welcome. For example for `DataFrame` to `html` or `pdf`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Credits\n", + "## App\n", "\n", - "- [Marc Skov Madsen](https://datamodelsanalytics.com)" + "Lets wrap it into nice template that can be served via `panel serve file_download_examples.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"File Download\", \n", + " main=[\n", + " \"This app demonstrates how to **download a Pandas DataFrame** using different formats.\",\n", + " pn.Column(\n", + " pn.pane.HTML(\"

🐼
\", height=75, margin=(50,5,10,5)),\n", + " file_download_csv, file_download_csv_zip, file_download_xlsx, file_download_json, file_download_parquet),\n", + " ], main_max_width=\"768px\",\n", + ").servable();" ] } ], diff --git a/examples/gallery/simple/iris_kmeans.ipynb b/examples/gallery/simple/iris_kmeans.ipynb index 299726ec84..00566347f5 100644 --- a/examples/gallery/simple/iris_kmeans.ipynb +++ b/examples/gallery/simple/iris_kmeans.ipynb @@ -11,7 +11,7 @@ "\n", "from sklearn.cluster import KMeans\n", "from bokeh.sampledata import iris\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -40,14 +40,39 @@ " est = kmeans.fit(iris.flowers.iloc[:, :-1].values)\n", " flowers['labels'] = est.labels_.astype('str')\n", " centers = flowers.groupby('labels').mean()\n", - " return (flowers.sort_values('labels').hvplot.scatter(x, y, c='labels') *\n", - " centers.hvplot.scatter(x, y, marker='x', color='black', size=200,\n", + " return (flowers.sort_values('labels').hvplot.scatter(x, y, c='labels', size=100, height=500) *\n", + " centers.hvplot.scatter(x, y, marker='x', color='black', size=400,\n", " padding=0.1, line_width=5))\n", "\n", "pn.Column(\n", " '# Iris K-Means Clustering',\n", " pn.Row(pn.WidgetBox(x, y, n_clusters), get_clusters)\n", - ").servable()" + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve iris_kmeans.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", title=\"Iris Kmeans\", \n", + " sidebar=[x, y, n_clusters],\n", + " main=[\n", + " \"This app provides an example of **building a simple dashboard using Panel**.\\n\\nIt demonstrates how to take the output of **k-means clustering on the Iris dataset** using scikit-learn, parameterizing the number of clusters and the variables to plot.\\n\\nThe entire clustering and plotting pipeline is expressed as a **single reactive function** that responsively returns an updated plot when one of the widgets changes.\\n\\n The **`x` marks the center** of the cluster.\"\"\",\n", + " get_clusters\n", + " ]\n", + ").servable();" ] } ], @@ -58,5 +83,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/simple/loading_spinner.ipynb b/examples/gallery/simple/loading_spinner.ipynb index 3e433d95c4..c14416245d 100644 --- a/examples/gallery/simple/loading_spinner.ipynb +++ b/examples/gallery/simple/loading_spinner.ipynb @@ -11,7 +11,7 @@ "import holoviews as hv\n", "import numpy as np\n", "\n", - "pn.extension(loading_spinner='dots', loading_color='#00aa41')" + "pn.extension(loading_spinner='dots', loading_color='#00aa41', sizing_mode=\"stretch_width\")" ] }, { @@ -29,49 +29,55 @@ "metadata": {}, "outputs": [], "source": [ - "button = pn.widgets.Button(name=\"Update\", margin=(0, 32, 0, 57))\n", + "button = pn.widgets.Button(name=\"Update\", margin=(0, 32, 0, 57), button_type=\"primary\")\n", "\n", "def random_plot():\n", " return hv.Points(np.random.rand(100, 2)).opts(\n", - " width=400, height=400, size=5)\n", + " width=400, height=400, size=8, color=\"#838383\")\n", "\n", "hv_pane = pn.pane.HoloViews(random_plot())\n", "\n", "def update(event):\n", " with pn.param.set_values(hv_pane, loading=True):\n", - " time.sleep(10)\n", + " time.sleep(1.5)\n", " hv_pane.object = random_plot()\n", " \n", "button.on_click(update)\n", "\n", - "pn.Column(button, hv_pane).servable()" + "component = pn.Column(button, hv_pane)\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve loading_spinner.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Loading Spinner\", \n", + " main=[\n", + " \"\"\"**Every pane, widget and layout provides the `loading` parameter**.\\n\\nWhen set to `True` a spinner will overlay the panel and indicate that the panel is currently loading. When you set `loading` to false the spinner is removed.\\n\\nUsing the `pn.extension` or by setting the equivalent parameters on `pn.config` we can select between **different visual styles and colors** for the loading indicator.\"\"\",\n", + " component\n", + " ], main_max_width=\"768px\",\n", + ").servable();" ] } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.2" - }, - "widgets": { - "application/vnd.jupyter.widget-state+json": { - "state": {}, - "version_major": 2, - "version_minor": 0 - } + "pygments_lexer": "ipython3" } }, "nbformat": 4, diff --git a/examples/gallery/simple/random_number_generator.ipynb b/examples/gallery/simple/random_number_generator.ipynb index 76afb58010..d99541a89e 100644 --- a/examples/gallery/simple/random_number_generator.ipynb +++ b/examples/gallery/simple/random_number_generator.ipynb @@ -8,16 +8,16 @@ "source": [ "import panel as pn\n", "import numpy as np\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This example creates a random number generator that periodically updates every two seconds, or with a click of a button.\n", + "This example creates a **random number generator** that periodically updates every two seconds, or with a click of a button.\n", "\n", - "This demonstrates how to add a periodic callback, how to link a button and a toggle to a couple callbacks--the former to manually generate a random number and the latter to toggle periodic generation of a random number." + "This demonstrates how to add a **periodic callback** and how to link a button and a toggle to a couple callbacks. The button to manually generate a random number and the toggle to toggle periodic generation of a random number." ] }, { @@ -32,8 +32,10 @@ "def toggle_periodic_callback(event):\n", " if event.new is True:\n", " periodic_cb.start()\n", + " periodic_toggle.name=\"STOP Periodic Generation\"\n", " else:\n", " periodic_cb.stop()\n", + " periodic_toggle.name=\"START Periodic Generation\"\n", " \n", "def update_period(event):\n", " periodic_cb.period = event.new\n", @@ -41,10 +43,10 @@ "static_text = pn.widgets.StaticText(name='Periodic Random Number Generator',\n", " value='000000')\n", "\n", - "generate_button = pn.widgets.Button(name='Generate New Number')\n", + "generate_button = pn.widgets.Button(name='GENERATE New Number')\n", "generate_button.on_click(generate_random_number)\n", "\n", - "periodic_toggle = pn.widgets.Toggle(name='Periodically Generate',\n", + "periodic_toggle = pn.widgets.Toggle(name='START Periodic Generation',\n", " value=False, button_type='primary')\n", "periodic_toggle.param.watch(toggle_periodic_callback, 'value')\n", "\n", @@ -55,7 +57,32 @@ " generate_random_number, period=period.value, start=False)\n", "\n", "col = pn.Column(generate_button, period, periodic_toggle, static_text)\n", - "col.servable()" + "col" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve random_number_generator.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Random Number Generator\", \n", + " main=[\n", + " \"This example creates a **random number generator** that updates periodically or with the click of a button.\\n\\nThis demonstrates how to add a **periodic callback** and how to link a button and a toggle to a couple of callbacks.\",\n", + " col,\n", + " ], main_max_width=\"768px\",\n", + ").servable();" ] } ], diff --git a/examples/gallery/simple/save_filtered_df.ipynb b/examples/gallery/simple/save_filtered_df.ipynb index 7109727d2f..c83ef3dcc3 100644 --- a/examples/gallery/simple/save_filtered_df.ipynb +++ b/examples/gallery/simple/save_filtered_df.ipynb @@ -11,7 +11,7 @@ "from bokeh.sampledata.autompg import autompg\n", "from io import StringIO\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -46,7 +46,36 @@ " callback=filtered_file, filename='filtered_autompg.csv'\n", ")\n", "\n", - "pn.Column(pn.Row(years, mpg), fd, pn.panel(filtered_mpg, width=600), width=600).servable()" + "pn.Column(pn.Row(years, mpg), fd, pn.panel(filtered_mpg, width=600), width=600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve save_filtered_df.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Save Filtered Dataframe\", \n", + " main=[\n", + " pn.Column(\n", + " \"This app demonstrates how to **filter and download a Pandas DataFrame**.\",\n", + " pn.pane.HTML(\"
🐼
\", height=75, margin=(50,5,10,5)),\n", + " ),\n", + " pn.Column(years, mpg, fd), \n", + " pn.Column(filtered_mpg, height=600, scroll=True),\n", + " ], main_max_width=\"768px\",\n", + ").servable();" ] } ], diff --git a/examples/gallery/simple/sync_location.ipynb b/examples/gallery/simple/sync_location.ipynb index cf949fc79e..c95adaef16 100644 --- a/examples/gallery/simple/sync_location.ipynb +++ b/examples/gallery/simple/sync_location.ipynb @@ -6,7 +6,9 @@ "metadata": {}, "outputs": [], "source": [ - "import panel as pn" + "import panel as pn\n", + "\n", + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -31,7 +33,32 @@ " pn.state.location.sync(widget2, {'value': 'text_value'})\n", " pn.state.location.sync(widget3, {'value': 'range_value'})\n", "\n", - "pn.Row(widget, widget2, widget3).servable()" + "pn.Row(widget, widget2, widget3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve sync_location.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Sync Location\", \n", + " main=[\n", + " \"This example demonstrates **how to sync widget state with the URL bar**. The widgets values are set from the URL parameters on page load and the URL parameters are set when a widget value changes.\",\n", + " pn.Column(widget, widget2, widget3),\n", + " ], main_max_width=\"768px\",\n", + ").servable();" ] } ], diff --git a/examples/gallery/simple/temperature_distribution.ipynb b/examples/gallery/simple/temperature_distribution.ipynb index fc50eede9d..927629a776 100644 --- a/examples/gallery/simple/temperature_distribution.ipynb +++ b/examples/gallery/simple/temperature_distribution.ipynb @@ -12,7 +12,7 @@ "\n", "from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { @@ -40,15 +40,15 @@ "@pn.depends(bins.param.value, kde.param.value,\n", " observations.param.value, bandwidth.param.value)\n", "def get_plot(bins, kde, obs, bw):\n", - " plot = sea_surface_temperature.hvplot.hist(bins=bins, normed=True, xlabel='Temperature (C)', padding=0.1)\n", + " plot = sea_surface_temperature.hvplot.hist(bins=bins, normed=True, xlabel='Temperature (C)', padding=0.1, color=\"#A01346\")\n", " if kde:\n", - " plot *= sea_surface_temperature.hvplot.kde().opts(bandwidth=bw)\n", + " plot *= sea_surface_temperature.hvplot.kde().opts(bandwidth=bw, color=\"#A01346\")\n", " if obs:\n", " plot *= hv.Spikes(sea_surface_temperature, 'temperature').opts(\n", - " line_width=0.1, alpha=0.1, spike_length=-0.01)\n", + " line_width=0.1, alpha=0.1, spike_length=0.14, color=\"#A01346\")\n", " return plot\n", "\n", - "widgets = pn.WidgetBox('## Sea surface temperatures', bins, observations, kde)\n", + "widgets = pn.WidgetBox(bins, observations, kde)\n", "\n", "def add_bandwidth(event):\n", " if event.new:\n", @@ -58,7 +58,35 @@ "\n", "kde.param.watch(add_bandwidth, 'value')\n", "\n", - "pn.Row(widgets, get_plot).servable()" + "pn.Row(widgets, get_plot)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve temperature_distribution.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "description=\"\"\"This example demonstrates how to put widgets together to build a simple UI for exploring the distribution of sea surface temperatures, as follows:\n", + "\n", + "- Declare the various widgets\n", + "- Declare a function that is decorated with the `pn.depends` to express the dependencies on the widget values\n", + "- Define a callback that pops up the bandwidth slider to control the kernel density estimate (if it has been enabled).\"\"\"\n", + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Temperature Distribution\",\n", + " sidebar=[widgets],\n", + " main=[description, get_plot], main_max_width=\"768px\",\n", + ").servable();" ] } ], @@ -69,5 +97,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/streaming/hardware_automation.ipynb b/examples/gallery/streaming/hardware_automation.ipynb index 888d792e28..f9a08e63cd 100644 --- a/examples/gallery/streaming/hardware_automation.ipynb +++ b/examples/gallery/streaming/hardware_automation.ipynb @@ -13,14 +13,16 @@ "from holoviews.streams import Buffer\n", "from bokeh.models import Button, Slider, Spinner\n", "import time\n", - "import asyncio" + "import asyncio\n", + "\n", + "pn.extension(sizing_mode=\"stretch_width\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This app provides a simple example of a graphical interface for scientific instrument control using panel for layout/interaction and [Holoviews](http://holoviews.org) for buffering and plotting data from the instrument.\n", + "This app provides a simple example of a graphical interface for scientific instrument control using Panel for layout/interaction and [Holoviews](http://holoviews.org) for buffering and plotting data from the instrument.\n", "\n", "First we make a mock instrument for this standalone example. The non-mock version of this class would communicate with the instrument (via serial/USB or NI-VISA, etc.)" ] @@ -64,7 +66,7 @@ "\n", "example_df = pd.DataFrame(columns=make_df().columns)\n", "buffer = Buffer(example_df, length=1000, index=False)\n", - "plot = hv.DynamicMap(hv.Curve, streams=[buffer]).opts(padding=0.1, width=600, xlim=(0, None))" + "plot = hv.DynamicMap(hv.Curve, streams=[buffer]).opts(padding=0.1, height=600, xlim=(0, None), responsive=True)" ] }, { @@ -86,8 +88,8 @@ "LABEL_CSV_STOP = \"Stop save\"\n", "CSV_FILENAME = 'tmp.csv'\n", "\n", - "button_startstop = Button(label=LABEL_START)\n", - "button_csv = Button(label=LABEL_CSV_START)\n", + "button_startstop = Button(label=LABEL_START, button_type=\"primary\")\n", + "button_csv = Button(label=LABEL_CSV_START, button_type=\"success\")\n", "offset = Slider(title='Offset', start=-10.0, end=10.0, value=0.0, step=0.1)\n", "interval = Spinner(title=\"Interval (sec)\", value=0.1, step=0.01)" ] @@ -126,7 +128,7 @@ " await asyncio.sleep(interval_sec - time_spent_buffering)\n", "\n", "\n", - "def toggle_csv():\n", + "def toggle_csv(*events):\n", " global save_to_csv\n", " if button_csv.label == LABEL_CSV_START:\n", " button_csv.label = LABEL_CSV_STOP\n", @@ -137,7 +139,7 @@ " button_csv.label = LABEL_CSV_START\n", "\n", "\n", - "def start_stop():\n", + "def start_stop(*events):\n", " global acquisition_task, save_to_csv\n", " if button_startstop.label == LABEL_START:\n", " button_startstop.label = LABEL_STOP\n", @@ -170,12 +172,39 @@ "hv.extension('bokeh')\n", "hv.renderer('bokeh').theme = 'caliber'\n", "controls = pn.WidgetBox('# Controls',\n", - " interval,\n", " button_startstop,\n", " button_csv,\n", - " offset)\n", + " interval,\n", + " offset,\n", + " )\n", + "\n", + "pn.Row(plot, controls)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", "\n", - "pn.Row(plot, controls).servable()" + "Lets wrap it into nice template that can be served via `panel serve hardware_automation.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Hardware Automation, IoT, Streaming and Async\", \n", + " sidebar=[*controls], \n", + " main=[\n", + " \"This app provides a simple example of a graphical interface for **scientific instrument control** using Panel for layout/interaction and [Holoviews](http://holoviews.org) for buffering and plotting data from the instrument.\",\n", + " plot,\n", + " ]\n", + ").servable();" ] } ], diff --git a/examples/gallery/streaming/streaming_perspective.ipynb b/examples/gallery/streaming/streaming_perspective.ipynb index 61552c6d79..a25ff9eef1 100644 --- a/examples/gallery/streaming/streaming_perspective.ipynb +++ b/examples/gallery/streaming/streaming_perspective.ipynb @@ -13,6 +13,13 @@ "pn.extension('perspective', sizing_mode='stretch_width')" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This example demonstrates the powerful streaming capabilities of the `Perspective` pane." + ] + }, { "cell_type": "code", "execution_count": null, @@ -33,10 +40,37 @@ "\n", "cb = pn.state.add_periodic_callback(stream, 50)\n", "\n", - "pn.Column(\n", + "component = pn.Column(\n", " pn.Row(cb.param.period, rollover, perspective.param.theme),\n", - " perspective\n", - ").servable()" + " perspective,\n", + " pn.layout.HSpacer(height=35), # Needed if user selects vaporwave theme in template\n", + ")\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve streaming_perspective.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Streaming Perspective\", \n", + " main=[\n", + " \"This example demonstrates the **powerful streaming capabilities** of Panel and the `Perspective` pane.\",\n", + " component,\n", + " ]\n", + ").servable();" ] } ], diff --git a/examples/gallery/streaming/streaming_tabulator.ipynb b/examples/gallery/streaming/streaming_tabulator.ipynb index 0264253e67..7a64d5ff42 100644 --- a/examples/gallery/streaming/streaming_tabulator.ipynb +++ b/examples/gallery/streaming/streaming_tabulator.ipynb @@ -10,7 +10,14 @@ "import pandas as pd\n", "import panel as pn\n", "\n", - "pn.extension()" + "pn.extension(sizing_mode=\"stretch_width\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This example demonstrates the powerful streaming capabilities of the `Tabulator` widget." ] }, { @@ -43,10 +50,36 @@ "\n", "cb = pn.state.add_periodic_callback(stream, 200)\n", "\n", - "pn.Column(\n", + "component = pn.Column(\n", " pn.Row(cb.param.period, rollover, follow, width=400),\n", " tabulator,\n", - ").servable()" + ")\n", + "component" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App\n", + "\n", + "Lets wrap it into nice template that can be served via `panel serve streaming_tabulator.ipynb`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.template.FastListTemplate(\n", + " site=\"Panel\", \n", + " title=\"Streaming Tabulator\", \n", + " main=[\n", + " \"This example demonstrates the **powerful streaming capabilities** of Panel and the `Tabulator` widget.\",\n", + " component,\n", + " ]\n", + ").servable();" ] } ], diff --git a/examples/gallery/templates/material_template.ipynb b/examples/gallery/templates/material_template.ipynb index c4a811eb44..91eebb4493 100644 --- a/examples/gallery/templates/material_template.ipynb +++ b/examples/gallery/templates/material_template.ipynb @@ -23,7 +23,7 @@ "\n", "[Panel](https://panel.holoviz.org/index.html) is a framework for creating awesome analytics apps in Python.\n", "\n", - "In Panel you are able to customize the layout and style using a custom [Template](https://panel.holoviz.org/user_guide/Templates.html).\n", + "**In Panel you are able to customize the layout and style using a [Custom Template](https://panel.holoviz.org/user_guide/Templates.html).**\n", "\n", "One popular design specification is [Material Design](https://material.io/design/). The following frameworks aims to implement the Material Design specification\n", "\n", @@ -33,8 +33,8 @@ "\n", "The `mwc` components should be the easiest to integrate with Panel, so we will base the following on `mwc` with a fall back to `mdc` when needed.\n", "\n", - "\"Girl \n", - "\"Girl " + "\"Girl \n", + "\"Girl " ] }, { @@ -54,9 +54,11 @@ "metadata": {}, "outputs": [], "source": [ - "%%HTML\n", + "fonts_html = \"\"\"\n", "\n", - "" + "\n", + "\"\"\"\n", + "pn.pane.HTML(fonts_html, height=0, width=0, sizing_mode=\"fixed\", margin=0)" ] }, { @@ -76,13 +78,15 @@ "metadata": {}, "outputs": [], "source": [ - "%%HTML\n", + "modules_html = \"\"\"\n", "\n", "\n", "\n", "\n", "\n", - "" + "\n", + "\"\"\"\n", + "pn.pane.HTML(modules_html, height=0, width=0, sizing_mode=\"fixed\", margin=0)" ] }, { @@ -98,7 +102,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%HTML\n", + "example_html = \"\"\"\n", "
\n", "\n", " Material App\n", @@ -110,12 +114,12 @@ "
\n", " \n", " \n", - "
Panel App
\n", + "
Panel App using Custom Template
\n", " \n", " \n", " \n", "
\n", - "
\n", + "
\n", "

Main Content!

\n", " \n", " \n", @@ -144,7 +148,9 @@ " bar.scrollTarget = drawer.getElementsByClassName('appContent')[0];\n", " }\n", "\n", - "
" + "
\n", + "\"\"\"\n", + "pn.pane.HTML(example_html, sizing_mode=\"stretch_width\", height=300)" ] }, { @@ -173,10 +179,19 @@ "metadata": {}, "outputs": [], "source": [ - "%%HTML\n", + "grid_import_html = \"\"\"\n", "\n", - "\n", - "\n", + "\"\"\"\n", + "pn.pane.HTML(grid_import_html, height=0, width=0, sizing_mode=\"fixed\", margin=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "grid_example_html = \"\"\"\n", "
\n", "
\n", "
\n", @@ -191,8 +206,6 @@ "
\n", "
\n", "
\n", - " \n", - " \n", "" + "\n", + "\"\"\"\n", + "pn.pane.Markdown(grid_example_html, sizing_mode=\"stretch_width\", height=500)" ] }, { @@ -275,7 +290,8 @@ " align-items: left;\n", "}\n", ".appMain {\n", - " margin: 10px;\n", + " margin: 25px;\n", + " padding: 25px;\n", "}\n", "\n", "\n", @@ -299,8 +315,9 @@ " \n", " \n", "
\n", + " {{ embed(roots.Styles) }}\n", "

Content!

\n", - "

This is a Panel app with a Material template allowing us to compose multiple Panel objects into a single HTML document.


\n", + "

This is a Panel app using a custom template based on Material Design. It works both in the Notebook and as a web app.


\n", " \n", " \n", " \n", @@ -353,6 +370,16 @@ "Let's use the template" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# The style_panel supports incrementally adding css in cells below for educational reasons\n", + "style_panel = pn.pane.HTML(\"\", height=0, width=0, sizing_mode=\"fixed\", margin=0)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -361,7 +388,7 @@ "source": [ "tmpl = pn.Template(template=template)\n", "\n", - "tmpl.add_variable('app_title', 'Panel App')\n", + "tmpl.add_variable('app_title', 'Panel App using Custom Template')\n", "material_green = \"rgb(0, 128, 0)\"\n", "material_purple= \"#9C27B0\"\n", "color = material_green\n", @@ -374,6 +401,7 @@ "tmpl.add_panel('E', hv.Curve([1, 2, 3]).opts(height=200,color=color, line_width=line_width, responsive=True))\n", "tmpl.add_panel('F', hv.Curve([1, 2, 3]).opts(height=200,color=color, line_width=line_width, responsive=True))\n", "tmpl.add_panel('G', hv.Curve([1, 2, 3]).opts(height=200,color=color, line_width=line_width, responsive=True))\n", + "tmpl.add_panel('Styles', style_panel)\n", "tmpl" ] }, @@ -410,8 +438,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%HTML\n", - "\n", + "dark_theme_style = \"\"\"\n", " @@ -27,44 +26,260 @@ + + + + + + + + +
+ + + + + + + + + Click to toggle the Theme +
+

+ + Click to visit the Panel web site +

+
+

Applications running on the server

+
+
+
+
+ +
+ +
+
+ +
+

Made with 🐍, ❤️, Fast and Panel.

+
+
+
+ diff --git a/panel/models/player.ts b/panel/models/player.ts index fc9db2e73a..6165636117 100644 --- a/panel/models/player.ts +++ b/panel/models/player.ts @@ -39,11 +39,16 @@ export class PlayerView extends WidgetView { toggle_disable() { this.sliderEl.disabled = this.model.disabled - for (const el of this.buttonEl.children) - el.disabled = this.model.disabled + for (const el of this.buttonEl.children){ + const anyEl = el + anyEl.disabled = this.model.disabled + } + for (const el of this.loop_state.children) { - if (el.tagName == "input") - el.disabled = this.model.disabled + if (el.tagName == "input"){ + const anyEl = el + anyEl.disabled = this.model.disabled + } } } diff --git a/panel/models/plotly.ts b/panel/models/plotly.ts index a2bdfa5926..049be442a6 100644 --- a/panel/models/plotly.ts +++ b/panel/models/plotly.ts @@ -150,7 +150,7 @@ export class PlotlyPlotView extends PanelHTMLBoxView { this.plot() } - _trace_data(): void { + _trace_data(): any { const data = []; for (let i = 0; i < this.model.data.length; i++) { data.push(this._get_trace(i, false)); @@ -199,7 +199,7 @@ export class PlotlyPlotView extends PanelHTMLBoxView { this._layout_wrapper.on('plotly_restyle', (eventData: any) => { this.model.restyle_data = filterEventData( this._layout_wrapper, eventData, 'restyle'); - + this._updateViewportProperty(); }); diff --git a/panel/models/tabulator.ts b/panel/models/tabulator.ts index 6d38949864..03875a358a 100644 --- a/panel/models/tabulator.ts +++ b/panel/models/tabulator.ts @@ -113,7 +113,7 @@ export class DataTabulatorView extends PanelHTMLBoxView { ajax.sendRequest = () => { return view.requestPage(ajax.params.page, ajax.params.sorters) } - tabulator.modules.page._parseRemoteData = (data: any) => {} + tabulator.modules.page._parseRemoteData = () => {} } requestPage(page: number, sorters: any[]): Promise { diff --git a/panel/template/fast/css/fast_bokeh.css b/panel/template/fast/css/fast_bokeh.css index c84feec7ce..e51553c7bf 100644 --- a/panel/template/fast/css/fast_bokeh.css +++ b/panel/template/fast/css/fast_bokeh.css @@ -1036,7 +1036,7 @@ border-radius: calc(var(--corner-radius) * 1px); } -input[type=file] { +.bk-root input[type=file] { background: transparent; width: 100%; height: 100px; @@ -1045,15 +1045,15 @@ input[type=file] { text-align: center; margin: auto; } -input[type=file][disabled]:hover { +.bk-root input[type=file][disabled]:hover { cursor: not-allowed; border-color: var(--neutral-outline-rest); } -input[type=file]:hover { +.bk-root input[type=file]:hover { border-color: var(--neutral-outline-hover); } -input[type=file]:active { +.bk-root input[type=file]:active { border: 3px dashed var(--neutral-outline-active); } diff --git a/panel/tests/pane/test_alert.py b/panel/tests/pane/test_alert.py index 6431c325d2..337fb5f394 100644 --- a/panel/tests/pane/test_alert.py +++ b/panel/tests/pane/test_alert.py @@ -26,7 +26,7 @@ def test_alert_type_change(alert_type, document, comm): assert set(alert.css_classes) == {"alert", f"alert-{alert_type}"} assert set(model.css_classes) == {"alert", f"alert-{alert_type}", "markdown"} - + def test_existing_css_classes(): """Test that an alert can change alert_type""" alert = Alert(text="This is some text", css_classes=["important"]) @@ -62,6 +62,6 @@ def test_all_view(): if __name__.startswith("bokeh"): - pn.config.sizing_mode="stretch_width" + pn.extension(sizing_mode="stretch_width") test_all_view().servable() print("served") diff --git a/panel/tests/pane/test_markup.py b/panel/tests/pane/test_markup.py index eac19f4efe..23378a9746 100644 --- a/panel/tests/pane/test_markup.py +++ b/panel/tests/pane/test_markup.py @@ -13,13 +13,13 @@ def test_get_markdown_pane_type(): @pd_available def test_get_dataframe_pane_type(): import pandas as pd - df = pd.util.testing.makeDataFrame() + df = pd._testing.makeDataFrame() assert PaneBase.get_pane_type(df) is DataFrame @pd_available def test_get_series_pane_type(): import pandas as pd - df = pd.util.testing.makeDataFrame() + df = pd._testing.makeDataFrame() assert PaneBase.get_pane_type(df.iloc[:, 0]) is DataFrame @streamz_available @@ -113,7 +113,7 @@ def test_html_pane(document, comm): @pd_available def test_dataframe_pane_pandas(document, comm): import pandas as pd - pane = DataFrame(pd.util.testing.makeDataFrame()) + pane = DataFrame(pd._testing.makeDataFrame()) # Create pane model = pane.get_root(document, comm=comm) @@ -122,7 +122,7 @@ def test_dataframe_pane_pandas(document, comm): orig_text = model.text # Replace Pane.object - pane.object = pd.util.testing.makeMixedDataFrame() + pane.object = pd._testing.makeMixedDataFrame() assert pane._models[model.ref['id']][0] is model assert model.text.startswith('<table') assert model.text != orig_text @@ -137,7 +137,7 @@ def test_dataframe_pane_streamz(document, comm): from streamz.dataframe import Random sdf = Random(interval='200ms', freq='50ms') pane = DataFrame(sdf) - + assert pane._stream is None # Create pane diff --git a/panel/tests/template/fast/test_fast_grid_template.py b/panel/tests/template/fast/test_fast_grid_template.py index 48b1dc1e1d..82e3b07009 100644 --- a/panel/tests/template/fast/test_fast_grid_template.py +++ b/panel/tests/template/fast/test_fast_grid_template.py @@ -145,7 +145,6 @@ def _fast_button_card(): def test_app(): - pn.config.sizing_mode = "stretch_width" app = FastGridTemplate( title="FastGridTemplate", ) @@ -159,4 +158,5 @@ def test_app(): if __name__.startswith("bokeh"): + pn.extension(sizing_mode="stretch_width") test_app().servable() diff --git a/panel/tests/template/fast/test_fast_list_template.py b/panel/tests/template/fast/test_fast_list_template.py index 42ab9863c9..8481993821 100644 --- a/panel/tests/template/fast/test_fast_list_template.py +++ b/panel/tests/template/fast/test_fast_list_template.py @@ -20,7 +20,6 @@ def test_template_theme_parameter(): def test_app(): - pn.config.sizing_mode = "stretch_width" app = FastListTemplate( title="FastListTemplate", site="Panel", @@ -38,4 +37,5 @@ def test_app(): if __name__.startswith("bokeh"): + pn.extension(sizing_mode="stretch_width") test_app().servable() diff --git a/panel/tests/template/test_manual.py b/panel/tests/template/test_manual.py index b70ecba63e..93802f6ffa 100644 --- a/panel/tests/template/test_manual.py +++ b/panel/tests/template/test_manual.py @@ -39,7 +39,6 @@ def test_template_with_sidebar(template_class=pn.template.VanillaTemplate, theme theme=theme ) vanilla.site="My Site" - pn.config.sizing_mode = "stretch_both" xs = np.linspace(0, np.pi) @@ -115,7 +114,6 @@ def test_template_with_no_sidebar(template_class=pn.template.VanillaTemplate, th theme=theme ) vanilla.main_max_width="1100px" - pn.config.sizing_mode = "stretch_both" xs = np.linspace(0, np.pi) freq = pn.widgets.FloatSlider(name="Frequency", start=0, end=10, value=2) @@ -204,5 +202,6 @@ def _get_app(): return template_func(template_class=template_class, theme=theme) if __name__.startswith("bokeh"): + pn.extension(sizing_mode="stretch_width") _get_app().servable() # test_template_with_no_sidebar().servable() diff --git a/panel/tests/template/test_vanilla_manual.py b/panel/tests/template/test_vanilla_manual.py index 3f5e409fcc..b7da3fe30b 100644 --- a/panel/tests/template/test_vanilla_manual.py +++ b/panel/tests/template/test_vanilla_manual.py @@ -22,8 +22,6 @@ def test_vanilla_with_sidebar(): logo=LOGO, ) - pn.config.sizing_mode = "stretch_width" - xs = np.linspace(0, np.pi) freq = pn.widgets.FloatSlider(name="Frequency", start=0, end=10, value=2) phase = pn.widgets.FloatSlider(name="Phase", start=0, end=np.pi) @@ -84,8 +82,6 @@ def test_vanilla_with_no_sidebar(): favicon="https://raw.githubusercontent.com/MarcSkovMadsen/awesome-panel/2781d86d4ed141889d633748879a120d7d8e777a/assets/images/favicon.ico", ) - pn.config.sizing_mode = "stretch_width" - xs = np.linspace(0, np.pi) freq = pn.widgets.FloatSlider(name="Frequency", start=0, end=10, value=2) phase = pn.widgets.FloatSlider(name="Phase", start=0, end=np.pi) @@ -127,5 +123,6 @@ def cosine(freq, phase): if __name__.startswith("bokeh"): + pn.extension(sizing_mode="stretch_width") test_vanilla_with_sidebar().servable() # test_vanilla_with_no_sidebar().servable() diff --git a/panel/tests/widgets/test_speech_to_text.py b/panel/tests/widgets/test_speech_to_text.py index 5adf83d087..7fa03703d3 100644 --- a/panel/tests/widgets/test_speech_to_text.py +++ b/panel/tests/widgets/test_speech_to_text.py @@ -272,6 +272,6 @@ def update_result_panel(results_last): if __name__.startswith("bokeh"): - pn.config.sizing_mode = "stretch_width" + pn.extension(sizing_mode="stretch_width") # test_get_advanced_app().servable() test_get_color_app().servable() diff --git a/panel/tests/widgets/test_tables.py b/panel/tests/widgets/test_tables.py index 3754afa21b..a9a3db630c 100644 --- a/panel/tests/widgets/test_tables.py +++ b/panel/tests/widgets/test_tables.py @@ -5,7 +5,7 @@ try: import pandas as pd - from pandas.util.testing import ( + from pandas._testing import ( makeCustomDataframe, makeMixedDataFrame, makeTimeDataFrame ) except ImportError: @@ -504,7 +504,7 @@ def test_tabulator_stream_dict_rollover(document, comm): for col, values in model.source.data.items(): np.testing.assert_array_equal(values, expected[col]) - + def test_tabulator_patch_scalars(document, comm): df = makeMixedDataFrame() table = Tabulator(df) diff --git a/panel/tests/widgets/test_text_to_speech.py b/panel/tests/widgets/test_text_to_speech.py index f076d54333..e46dea335d 100644 --- a/panel/tests/widgets/test_text_to_speech.py +++ b/panel/tests/widgets/test_text_to_speech.py @@ -296,5 +296,5 @@ def test_get_app(): if __name__.startswith("bokeh"): - pn.config.sizing_mode = "stretch_width" + pn.extension(sizing_mode="stretch_width") test_get_app().servable() diff --git a/setup.py b/setup.py index e57a9c90eb..58d0bd089a 100644 --- a/setup.py +++ b/setup.py @@ -149,7 +149,7 @@ def run(self): 'ipywidgets_bokeh', 'ipyvolume', 'ipyleaflet', - 'xarray <0.17' + 'xarray <0.17', ], 'tests': _tests, 'recommended': _recommended, diff --git a/tox.ini b/tox.ini index 913dd2511c..6f59a42031 100644 --- a/tox.ini +++ b/tox.ini @@ -15,7 +15,7 @@ commands = flake8 [_unit] description = Run unit tests deps = .[tests] -commands = pytest panel --cov=./ +commands = pytest panel --cov=./panel [_unit_deploy] description = Run unit tests without coverage