diff --git a/_freeze/html/shiny-python/execute-results/html.json b/_freeze/html/shiny-python/execute-results/html.json
index a62b7b7a..ab6099b4 100644
--- a/_freeze/html/shiny-python/execute-results/html.json
+++ b/_freeze/html/shiny-python/execute-results/html.json
@@ -1,8 +1,8 @@
{
- "hash": "40dc3403f4fb24778e2da69caafe04e2",
+ "hash": "cf56359b42105783623638e7d3ed3df0",
"result": {
"engine": "knitr",
- "markdown": "---\ntitle: \"Shiny for Python :: Cheatsheet\"\ndescription: \" \"\nimage-alt: \"\"\nexecute:\n eval: true\n output: false\n warning: true\n---\n\n::: {.cell .column-margin}\n\n
\n Download PDF
\n\n\n
\n:::\n\n\n\n\n## Build an App\n\nA **Shiny** app is an interactive web page (**ui**) powered by a live Python session run by a **server** (or by a browser with Shinylive).\n\nUsers can manipulate the UI, which will cause the server to update the UI's displays (by running Python code).\n\nSave your app as `app.py` in a directory with the files it uses.\n\n- **app-name:** The directory name is the app name\n\n\n\n- **app.py**\n\n- www/: Place images, CSS, etc. to share with the browser in a folder named \"www\"\n\n- Include any other scripts, data sets, or assets used by the app in the same directory.\n\nRun `shiny create .` in the terminal to generate a template `app.py` file\n\nLaunch apps with `shiny run app.py --reload`\n\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nfrom shiny import App, render, ui\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Nest Python functions to build an HTML interface\napp_ui = ui.page_fluid( # Layout the UI with Layout Functions\n \n # Add Inputs with ui.input_*() functions \n ui.input_slider(\n \"n\", \"Sample Size\", 0, 1000, 20\n ),\n # Add Outputs with ui.ouput_*() functions\n ui.output_plot(\"dist\")\n)\n\ndef server(input, output, session):\n \n # For each output, define a function that generates the output\n @output # Designate output functions with the @output decorator\n @render.plot # Specify the type of output with a @render. decorator\n def dist(): # Use the output id as the function name\n \n # Call the values of UI inputs with input.()\n x = np.random.randn(input.n()) \n plt.hist(x, range=[-3, 3])\n\n# Call App() to combine app_ui and server() into an interactive app\napp = App(app_ui, server)\n```\n:::\n\n\n\n\n## Share\n\nShare your app in three ways:\n\n1. Host it on [shinyapps.io](shinyapps.io), a cloud based service from Posit.\n To deploy Shiny apps:\n\n - Create a free or professional account at [shinyapps.io](shinyapps.io)\n - Use the reconnect-python package to publish with `rsconnect deploy shiny `\n\n2. Purchase Posit Connect, a publishing platform for R and Python.\n [posit.co/products/enterprise/connect/](posit.co/products/enterprise/connect/)\n\n3. Use open source deployment options.\n [shiny.posit.co/py/docs/deploy.html](https://shiny.posit.co/py/docs/deploy.html)\n\n## Shinylive\n\nShinylive apps use WebAssembly to run entirely in a browser--no need for a special server to run Python.\n\n- Edit and/or host Shinylive apps at shinylive.io\n- Create a Shinylive version of an app to deploy with `shinylive export myapp site`. Then deploy to a hosting site like Github or Netifly.\n- Embed Shinylive apps in Quarto sites, blogs, etc\n\nTo embed a Shinylive app in a Quarto doc, include the below syntax.\n\n````markdown\n---\nfilters:\n- shinylive\n---\n \nAn embedded Shinylive app:\n \n```{{r}}\n#| standalone: true\n# [App.py code here...]\n```\n````\n\n## Outputs\n\nMatch ui.output_\\* functions to @render.\\* decorators\n\n+-----------------------+-------------------------------------------------------------------------------+\n| decorator | function |\n+=======================+===============================================================================+\n| `@render.data_frame` | `ui.output_data_frame(id)` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.image` | `ui.output_image(id, width, height, click, dblclick, hover, brush, inline)` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.plot` | `ui.output_plot(id, width, height, click, dblclick, hover, brush, inline)` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.table` | `ui.output_table(id)` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.text` | `ui.output_text(id, container, inline)` also `ui.output_text_verbatim()` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.ui` | `ui.output_ui(id, inline, container, ...)` also `ui.output_html()` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@sessiom.download` | `ui.output_download_button(id, label, icon,...)` |\n+-----------------------+-------------------------------------------------------------------------------+\n\n: Table of `@render.*()` decorators and their associated `ui.output_*()` functions.\n\n## Inputs\n\nUse a `ui.input_*()` function to make an input widget that saves a value as `input.`. Input values are reactive and need to be called as `input.()`.\n\n- `ui.input_action_button(id, label, icon, width, ...)`\n\n- `ui.input_action_link(id, label, icon, ...)`\n\n- `ui.input_checkbox(id, label, value, width)`\n\n- `ui.input_checkbox_group(id, label, choices, selected, inline, width)`\n\n- `ui.input_date(id, label, value, min, max, format, startview, weekstart, language, width, autoclose, datesdisabled, daysofweekdisabled)`\n\n- `ui.input_date_range(id, label, start, end, min, max, format, startview, weekstart, language, separator, width, autoclose)`\n\n- `ui.input_file(id, label, multiple, accept, width, buttonLabel, placeholder, capture)`\n\n- `ui.input_numeric(id, label, value, min, max, step, width)`\n\n- `ui.input_password(id, label, value, width, placeholder)`\n\n- `ui.input_radio_buttons(id, label, choices, selected, inline, width)`\n\n- `ui.input_select(id, label, choices, selected, multiple, selectize, width, size) Also ui.input_selectize()`\n\n- `ui.input_slider(id, label, min, max, value, step, ticks, animate, width, sep, pre, post, timeFormat, timezone, dragRange)`\n\n- `ui.input_switch(id, label, value, width)`\n\n- `ui.input_text(id, label, value, width, placeholder, autocomplete, spellcheck) Also ui.input_text_area()`\n\n\n\n## Reactivity\n\nReactive values work together with reactive functions. Call a reactive value from within the arguments of one of these functions to avoid the error `No current reactive context`.\n\n![](images/reactivity-diagram-python.png){fig-align=\"center\"}\n\n::: {.callout-note appearance=\"minimal\" icon=\"false\" collapse=\"true\"}\n## Expand to read about the reactivity diagram {aria-hidden=\"true\"}\n\n### Phases in the reactivity diagram\n\n- Create your own reactive values\n - `ui.input_*()`\n - `reactive.Value()``\n - `@reactive.file_reader()`\n - `@reactive.poll()`\n- Perform side effects\n - `@reactive.Effect`\n- Schedule updates\n - `reactive.invalidate_later()`\n- Create reactive expressions\n - `reactive.Calc()`\n- Remove reactivity\n - `reactive.isolate()`\n- React based on event\n - `@reactive.event()`\n- Render reactive output\n - `@output`\n - `@render*`\n:::\n\n### Create Your own Reactive Values\n\n- `ui.input_*()` makes an input widget that saves a reactive value as `input.()`.\n- `reactive.value( )` Creates an object whose value you can set.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n app_ui = ui.page_fluid(\n ui.input_text(\"a\", \"A\")\n )\n \n def server(input, output, session):\n rv = reactive.Value()\n rv.set(5) \n #...\n ```\n :::\n\n\n\n\n### Create Reactive Expressions\n\n- `@reactive.Calc` makes a function a reactive expression. Shiny notifies functions that use the expression when it becomes invalidated, triggering recomputation. Shiny caches the value of the expression while it is valid to avoid unnecessary computation.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.Calc\n def re():\n return input.a() + input.b()\n #...\n ```\n :::\n\n\n\n\n### React Based on Event\n\n- `@reactive.event()` Makes a function react only when a specified value is invalidated, here `input.a`.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.Calc \n @reactive.event(input.a) \n def re():\n return input.b() \n #...\n ```\n :::\n\n\n\n\n### Display Reactive Output\n\n- `ui.output_*()` adds an output element to the UI.\n- `@output`, `@render.*` are decorators to identify and render outputs\n- `def ():` A function to generate the output\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n app_ui = ui.page_fluid(\n ui.input_text(\"a\", \"A\"), \n ui.output_text(\"b\"),\n )\n \n def server(input, output, session ):\n @output \n @render.text \n def b():\n return input.a()\n ```\n :::\n\n\n\n\n### Perform Side Effects\n\n- `@reactive.Effect` Reactively trigger a function with a side effect. Call a reactive value or use `@reactive.event` to specify when the function will rerun.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.Effect\n @reactive.event(input.a) \n def print():\n print(\"Hi\") \n #...\n ```\n :::\n\n\n\n\n### Remove Reactivity\n\n- `reactive.isolate()`Create non-reactive context within a reactive function. Calling a reactive value within this context will not cause the calling function to re-execute should the value become invalid.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n # ...\n def server(input, output, session):\n @output \n @render.text \n def a():\n with reactive.isolate():\n return input.a() \n #...\n ```\n :::\n\n\n\n\n## Layouts\n\nCombine multiple elements into a \"single element\" that has its own properties with a panel function:\n\n- `ui.panel_absolute()`\n- `ui.panel_conditional()`\n- `ui.panel_fixed()`\n- `ui.panel_main()`\n- `ui.panel_sidebar()`\n- `ui.panel_title()`\n- `ui.panel_well()`\n- `ui.row() / ui.column()`\n\n\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nui.panel_well(\n ui.input_date(...),\n ui.input_action_button(...)\n)\n```\n:::\n\n\n\n\nLayout panels with a layout function. Add elements as arguments of the layout functions.\n\n- `ui.layout_sidebar()`\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n app_ui = ui.page_fluid(\n ui.panel_title( ), \n ui.layout_sidebar(\n ui.panel_sidebar( ),\n )\n ) \n ```\n :::\n\n\n\n\n- `ui.row()`\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n app_ui = ui.page_fluid(\n ui.row(\n ui.column(width = 4), ui.column(width = 2, offset = 3),\n ),\n ui.row(\n ui.column(width = 12)\n )\n )\n ```\n :::\n\n\n\n\nLayer `ui.nav( )`s on top of each other, and navigate between them, with:\n\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\n# navset tab\nui.page_fluid(\n ui.navset_tab(\n ui.nav(\"tab 1\", \"contents\"), \n ui.nav(\"tab 2\", \"contents\"), \n ui.nav(\"tab 3\", \"contents\")\n )\n)\n\n# navpill list\nui.page_fluid(\n ui.navset_pill_list(\n ui.nav(\"tab 1\", \"contents\"), \n ui.nav(\"tab 2\", \"contents\"), \n ui.nav(\"tab 3\", \"contents\")\n )\n)\n\n# navbar page\nui.page_navbar(\n ui.nav(\"tab 1\", \"contents\"), \n ui.nav(\"tab 2\", \"contents\"), \n ui.nav(\"tab 3\", \"contents\"), \n title = \"Page\"\n)\n```\n:::\n\n\n\n\n## Themes\n\nUse the shinyswatch package to add existing bootstrap themes to your Shiny app ui.\n\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nimport shinyswatch\n\napp_ui = ui.page_fluid(\n shinyswatch.theme.darkly(), \n # ...\n)\n```\n:::\n\n\n\n\n## Shiny for R Comparison\n\nShiny for Python is quite similar to Shiny for R with a few important differences:\n\n\n1. Call inputs as `input.()`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n input$x\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n input.x()\n ```\n :::\n\n\n\n\n2. Use decorators to create and render outputs. Define outputs as functions `def ():`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n output$y <- \n renderText(z())\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @output \n @renderText \n def y():\n return z()\n ```\n :::\n\n\n\n\n3. To create a reactive expression, use `@reactive.Calc`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n z <- reactive({ \n input$x + 1\n })\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.Calc \n def z():\n return input.x()+1\n ```\n :::\n\n\n\n \n4. To create an observer, use `@reactive.Effect`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n a <- observe({ \n print(input$x)\n })\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.Effect \n def a():\n print(input.x())\n ```\n :::\n\n\n\n\n5. Combine these with `@reactive.event`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n b <- eventReactive(\n input$goCue,\n {input$x + 1}\n )\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.Calc \n @reactive.event(input.go_cue )\n def b():\n return input.x() + 1\n ```\n :::\n\n\n\n \n6. Use `reactive.Value()` instead of `reactiveVal()`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n reactiveVal(1)\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n reactive.Value(1)\n ```\n :::\n\n\n\n\n7. Use `nav_*()` instead of `*Tab()`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n insertTab() \n appendTab() \n # etc.\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n nav_insert() \n nav_append() \n # etc.\n ```\n :::\n\n\n\n\n8. Functions are intuitively organized into submodules\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n dateInput() \n textInput() \n # etc.\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n ui.input_date() \n ui.input_text() \n # etc.\n ```\n :::\n\n\n\n\n------------------------------------------------------------------------\n\nCC BY SA Posit Software, PBC • [info\\@posit.co](mailto:info@posit.co) • [posit.co](https://posit.co)\n\nLearn more at [shiny.posit.co/py/](https://shiny.posit.co/py/)\n\nUpdated: 2024-05.\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\npackageVersion(\"shiny\")\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] '1.8.1.1'\n```\n\n\n:::\n:::\n\n\n\n\n------------------------------------------------------------------------\n",
+ "markdown": "---\ntitle: \"Shiny for Python :: Cheatsheet\"\ndescription: \" \"\nimage-alt: \"\"\nexecute:\n eval: false\n output: false\n---\n\n::: {.cell .column-margin}\n\n:::\n\n\n\n## Build an App\n\nA **Shiny** app is an interactive web page (**ui**) powered by a live Python session run by a **server** (or by a browser with Shinylive).\n\nUsers can manipulate the UI, which will cause the server to update the UI's displays (by running Python code).\n\nSave your app as `app.py` in a directory with the files it uses.\n\n- **app-name:** The directory name is the app name\n- **app.py**\n- www/: Place images, CSS, etc. to share with the browser in a folder named \"www\"\n- Include any other scripts, data sets, or assets used by the app in the same directory.\n\nRun `shiny create .` in the terminal to generate an `app.py` file based on a template.\n\nLaunch apps with `shiny run app.py --reload`\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nfrom shiny import App, render, ui\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Nest Python functions to build an HTML interface\napp_ui = ui.page_fluid( # Layout the UI with Layout Functions\n \n # Add Inputs with ui.input_*() functions \n ui.input_slider(\n \"n\", \"Sample Size\", 0, 1000, 20\n ),\n # Add Outputs with ui.ouput_*() functions\n ui.output_plot(\"dist\")\n)\n\ndef server(input, output, session):\n \n # For each output, define a function that generates the output\n @render.plot # Specify the type of output with a @render. decorator\n def dist(): # Use the output id as the function name\n \n # Call the values of UI inputs with input.()\n x = np.random.randn(input.n()) \n plt.hist(x, range=[-3, 3])\n\n# Call App() to combine app_ui and server() into an interactive app\napp = App(app_ui, server)\n```\n:::\n\n\n\n## Share\n\nShare your app in three ways:\n\n1. Host it on [shinyapps.io](https://www.shinyapps.io/), a cloud based service from Posit.\n To deploy Shiny apps:\n\n - Create a free or professional account at [shinyapps.io](https://www.shinyapps.io/)\n - Use the reconnect-python package to publish with `rsconnect deploy shiny `\n\n2. Purchase Posit Connect, a publishing platform for R and Python.\n [posit.co/products/enterprise/connect/](https://posit.co/products/enterprise/connect/)\n\n3. Use open source deployment options.\n [shiny.posit.co/py/docs/deploy.html](https://shiny.posit.co/py/docs/deploy.html)\n\n## Shinylive\n\nShinylive apps use WebAssembly to run entirely in a browser--no need for a special server to run Python.\n\n- Edit and/or host Shinylive apps at shinylive.io\n- Create a Shinylive version of an app to deploy with `shinylive export myapp site`. Then deploy to a hosting site like Github or Netifly.\n- Embed Shinylive apps in Quarto sites, blogs, etc\n\nTo embed a Shinylive app in a Quarto doc, include the below syntax.\n\n```` markdown\n---\nfilters:\n- shinylive\n---\n \nAn embedded Shinylive app:\n \n```{{r}}\n#| standalone: true\n# [App.py code here...]\n```\n````\n\n## Outputs\n\nMatch ui.output\\_\\* functions to @render.\\* decorators\n\n| decorator | function |\n|------------------|------------------------------------------------------|\n| `@render.data_frame` | `ui.output_data_frame(id)` |\n| `@render.image` | `ui.output_image(id, width, height, click, dblclick, hover, brush, inline)` |\n| `@render.plot` | `ui.output_plot(id, width, height, click, dblclick, hover, brush, inline)` |\n| `@render.table` | `ui.output_table(id)` |\n| `@render.text` | `ui.output_text(id, container, inline)` also `ui.output_text_verbatim()` |\n| `@render.ui` | `ui.output_ui(id, inline, container, ...)` also `ui.output_html()` |\n| `@sessiom.download` | `ui.output_download_button(id, label, icon,...)` |\n\n: Table of `@render.*()` decorators and their associated `ui.output_*()` functions.\n\n## Inputs\n\nUse a `ui.input_*()` function to make an input widget that saves a value as `input.`.\nInput values are reactive and need to be called as `input.()`.\n\n- `ui.input_action_button(id, label, icon, width, ...)`\n\n- `ui.input_action_link(id, label, icon, ...)`\n\n- `ui.input_checkbox(id, label, value, width)`\n\n- `ui.input_checkbox_group(id, label, choices, selected, inline, width)`\n\n- `ui.input_date(id, label, value, min, max, format, startview, weekstart, language, width, autoclose, datesdisabled, daysofweekdisabled)`\n\n- `ui.input_date_range(id, label, start, end, min, max, format, startview, weekstart, language, separator, width, autoclose)`\n\n- `ui.input_file(id, label, multiple, accept, width, buttonLabel, placeholder, capture)`\n\n- `ui.input_numeric(id, label, value, min, max, step, width)`\n\n- `ui.input_password(id, label, value, width, placeholder)`\n\n- `ui.input_radio_buttons(id, label, choices, selected, inline, width)`\n\n- `ui.input_select(id, label, choices, selected, multiple, selectize, width, size) Also ui.input_selectize()`\n\n- `ui.input_slider(id, label, min, max, value, step, ticks, animate, width, sep, pre, post, timeFormat, timezone, dragRange)`\n\n- `ui.input_switch(id, label, value, width)`\n\n- `ui.input_text(id, label, value, width, placeholder, autocomplete, spellcheck) Also ui.input_text_area()`\n\n\n\n## Reactivity\n\nReactive values work together with reactive functions.\nCall a reactive value from within the arguments of one of these functions to avoid the error `No current reactive context`.\n\n![](images/reactivity-diagram-python.png){fig-align=\"center\"}\n\n::: {.callout-note appearance=\"minimal\" icon=\"false\" collapse=\"true\"}\n## Expand to read about the reactivity diagram {aria-hidden=\"true\"}\n\n### Phases in the reactivity diagram\n\n- Create your own reactive values\n - `ui.input_*()`\n - \\`reactive.Value()\\`\\`\n - `@reactive.file_reader()`\n - `@reactive.poll()`\n- Perform side effects\n - `@reactive.Effect`\n- Schedule updates\n - `reactive.invalidate_later()`\n- Create reactive expressions\n - `reactive.Calc()`\n- Remove reactivity\n - `reactive.isolate()`\n- React based on event\n - `@reactive.event()`\n- Render reactive output\n - `@render*`\n:::\n\n### Create Your own Reactive Values\n\n- `ui.input_*()` makes an input widget that saves a reactive value as `input.()`.\n\n- `reactive.value( )` Creates an object whose value you can set.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n app_ui = ui.page_fluid(\n ui.input_text(\"a\", \"A\")\n )\n \n def server(input, output, session):\n rv = reactive.Value()\n rv.set(5) \n #...\n ```\n :::\n\n\n\n### Create Reactive Expressions\n\n- `@reactive.calc` makes a function a reactive expression.\n Shiny notifies functions that use the expression when it becomes invalidated, triggering recomputation.\n Shiny caches the value of the expression while it is valid to avoid unnecessary computation.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.calc\n def re():\n return input.a() + input.b()\n #...\n ```\n :::\n\n\n\n### React Based on Event\n\n- `@reactive.event()` Makes a function react only when a specified value is invalidated, here `input.a`.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.Calc \n @reactive.event(input.a) \n def re():\n return input.b() \n #...\n ```\n :::\n\n\n\n### Display Reactive Output\n\n- `ui.output_*()` adds an output element to the UI.\n\n- `@render.*` decorators render outputs\n\n- `def ():` A function to generate the output\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n app_ui = ui.page_fluid(\n ui.input_text(\"a\", \"A\"), \n ui.output_text(\"b\"),\n )\n \n def server(input, output, session ):\n @render.text \n def b():\n return input.a()\n ```\n :::\n\n\n\n### Perform Side Effects\n\n- `@reactive.effect` Reactively trigger a function with a side effect.\n Call a reactive value or use `@reactive.event` to specify when the function will rerun.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.effect\n @reactive.event(input.a) \n def print():\n print(\"Hi\") \n #...\n ```\n :::\n\n\n\n### Remove Reactivity\n\n- `reactive.isolate()`Create non-reactive context within a reactive function.\n Calling a reactive value within this context will not cause the calling function to re-execute should the value become invalid.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n # ...\n def server(input, output, session):\n @render.text \n def a():\n with reactive.isolate():\n return input.a() \n #...\n ```\n :::\n\n\n\n## Layouts\n\nCombine multiple elements into a \"single element\" that has its own properties with a panel function:\n\n- `ui.panel_absolute()`\n- `ui.panel_conditional()`\n- `ui.panel_fixed()`\n- `ui.panel_main()`\n- `ui.panel_sidebar()`\n- `ui.panel_title()`\n- `ui.panel_well()`\n- `ui.row() / ui.column()`\n\nLayout panels with a layout function.\nAdd elements as arguments of the layout functions.\n\n- `ui.page_sidebar()`\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\napp_ui = ui.page_sider( \n ui.sidebar(\"Sidebar\", bg=\"#f8f8f), \n \"Main content\", \n) \n```\n:::\n\n\n\n- `ui.layout_columns()` with \\`ui.card()\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\napp_ui = ui.page_fillable(\n ui.layout_columns(\n ui.card(\n ...\n ),\n ui.card(\n ...\n ),\n )\n)\n```\n:::\n\n\n\nUse `ui.nav_panel` with `ui.page_navbar` to create tabs:\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\n# navset tab\napp_ui = ui.page_navbar( \n ui.nav_panel(\"A\", \"Page A content\"), \n ui.nav_panel(\"B\", \"Page B content\"), \n ui.nav_panel(\"C\", \"Page C content\"), \n title=\"App with navbar\", \n id=\"page\", \n) \n```\n:::\n\n\n\n## Themes\n\nUse the shinyswatch package to add existing bootstrap themes to your Shiny app ui.\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nimport shinyswatch\n\napp_ui = ui.page_fluid(\n shinyswatch.theme.darkly(), \n # ...\n)\n```\n:::\n\n\n\n## Shiny for R Comparison\n\nShiny for Python is quite similar to Shiny for R with a few important differences:\n\n1. Call inputs as `input.()`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n input$x\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n input.x()\n ```\n :::\n\n\n\n2. Use decorators to create and render outputs. Define outputs as functions `def ():`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n output$y <-\n renderText(z())\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @renderText \n def y():\n return z()\n ```\n :::\n\n\n\n3. To create a reactive expression, use `@reactive.calc`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n z <- reactive({\n input$x + 1\n })\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.calc \n def z():\n return input.x()+1\n ```\n :::\n\n\n\n4. To create an observer, use `@reactive.effect`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n a <- observe({\n print(input$x)\n })\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.effect \n def a():\n print(input.x())\n ```\n :::\n\n\n\n5. Combine these with `@reactive.event`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n b <- eventReactive(\n input$goCue,\n {\n input$x + 1\n }\n )\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.calc \n @reactive.event(input.go_cue )\n def b():\n return input.x() + 1\n ```\n :::\n\n\n\n6. Use `reactive.Value()` instead of `reactiveVal()`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n reactiveVal(1)\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n reactive.value(1)\n ```\n :::\n\n\n\n7. Use `nav_*()` instead of `*Tab()`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n insertTab()\n appendTab()\n # etc.\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n nav_insert() \n nav_append() \n # etc.\n ```\n :::\n\n\n\n8. Functions are intuitively organized into submodules\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n dateInput()\n textInput()\n # etc.\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n ui.input_date() \n ui.input_text() \n # etc.\n ```\n :::\n\n\n\n------------------------------------------------------------------------\n\nCC BY SA Posit Software, PBC • [info\\@posit.co](mailto:info@posit.co) • [posit.co](https://posit.co)\n\nLearn more at [shiny.posit.co/py/](https://shiny.posit.co/py/)\n\nUpdated: 2024-05.\n\nVersion: Shiny 0.10.2\n\n------------------------------------------------------------------------\n",
"supporting": [],
"filters": [
"rmarkdown/pagebreak.lua"
diff --git a/html/images/logo-shiny.png b/html/images/logo-shiny.png
index eda670e6..a9128b8a 100644
Binary files a/html/images/logo-shiny.png and b/html/images/logo-shiny.png differ
diff --git a/html/shiny-python.qmd b/html/shiny-python.qmd
index d59b75dc..e79d6b50 100644
--- a/html/shiny-python.qmd
+++ b/html/shiny-python.qmd
@@ -3,9 +3,8 @@ title: "Shiny for Python :: Cheatsheet"
description: " "
image-alt: ""
execute:
- eval: true
+ eval: false
output: false
- warning: true
---
```{r}
@@ -31,13 +30,8 @@ Users can manipulate the UI, which will cause the server to update the UI's disp
Save your app as `app.py` in a directory with the files it uses.
- **app-name:** The directory name is the app name
-
-
-
- **app.py**
-
- www/: Place images, CSS, etc. to share with the browser in a folder named "www"
-
- Include any other scripts, data sets, or assets used by the app in the same directory.
Run `shiny create .` in the terminal to generate an `app.py` file based on a template.
@@ -45,8 +39,6 @@ Run `shiny create .` in the terminal to generate an `app.py` file based on a tem
Launch apps with `shiny run app.py --reload`
```{python}
-#| eval: false
-
from shiny import App, render, ui
import matplotlib.pyplot as plt
import numpy as np
@@ -102,7 +94,7 @@ Shinylive apps use WebAssembly to run entirely in a browser--no need for a speci
To embed a Shinylive app in a Quarto doc, include the below syntax.
-````markdown
+```` markdown
---
filters:
- shinylive
@@ -118,31 +110,24 @@ An embedded Shinylive app:
## Outputs
-Match ui.output_\* functions to @render.\* decorators
-
-+-----------------------+-------------------------------------------------------------------------------+
-| decorator | function |
-+=======================+===============================================================================+
-| `@render.data_frame` | `ui.output_data_frame(id)` |
-+-----------------------+-------------------------------------------------------------------------------+
-| `@render.image` | `ui.output_image(id, width, height, click, dblclick, hover, brush, inline)` |
-+-----------------------+-------------------------------------------------------------------------------+
-| `@render.plot` | `ui.output_plot(id, width, height, click, dblclick, hover, brush, inline)` |
-+-----------------------+-------------------------------------------------------------------------------+
-| `@render.table` | `ui.output_table(id)` |
-+-----------------------+-------------------------------------------------------------------------------+
-| `@render.text` | `ui.output_text(id, container, inline)` also `ui.output_text_verbatim()` |
-+-----------------------+-------------------------------------------------------------------------------+
-| `@render.ui` | `ui.output_ui(id, inline, container, ...)` also `ui.output_html()` |
-+-----------------------+-------------------------------------------------------------------------------+
-| `@sessiom.download` | `ui.output_download_button(id, label, icon,...)` |
-+-----------------------+-------------------------------------------------------------------------------+
+Match ui.output\_\* functions to @render.\* decorators
+
+| decorator | function |
+|------------------|------------------------------------------------------|
+| `@render.data_frame` | `ui.output_data_frame(id)` |
+| `@render.image` | `ui.output_image(id, width, height, click, dblclick, hover, brush, inline)` |
+| `@render.plot` | `ui.output_plot(id, width, height, click, dblclick, hover, brush, inline)` |
+| `@render.table` | `ui.output_table(id)` |
+| `@render.text` | `ui.output_text(id, container, inline)` also `ui.output_text_verbatim()` |
+| `@render.ui` | `ui.output_ui(id, inline, container, ...)` also `ui.output_html()` |
+| `@sessiom.download` | `ui.output_download_button(id, label, icon,...)` |
: Table of `@render.*()` decorators and their associated `ui.output_*()` functions.
## Inputs
-Use a `ui.input_*()` function to make an input widget that saves a value as `input.`. Input values are reactive and need to be called as `input.()`.
+Use a `ui.input_*()` function to make an input widget that saves a value as `input.`.
+Input values are reactive and need to be called as `input.()`.
- `ui.input_action_button(id, label, icon, width, ...)`
@@ -176,7 +161,8 @@ Use a `ui.input_*()` function to make an input widget that saves a value as `inp
## Reactivity
-Reactive values work together with reactive functions. Call a reactive value from within the arguments of one of these functions to avoid the error `No current reactive context`.
+Reactive values work together with reactive functions.
+Call a reactive value from within the arguments of one of these functions to avoid the error `No current reactive context`.
![](images/reactivity-diagram-python.png){fig-align="center"}
@@ -187,7 +173,7 @@ Reactive values work together with reactive functions. Call a reactive value fro
- Create your own reactive values
- `ui.input_*()`
- - `reactive.Value()``
+ - \`reactive.Value()\`\`
- `@reactive.file_reader()`
- `@reactive.poll()`
- Perform side effects
@@ -207,16 +193,15 @@ Reactive values work together with reactive functions. Call a reactive value fro
### Create Your own Reactive Values
- `ui.input_*()` makes an input widget that saves a reactive value as `input.()`.
+
- `reactive.value( )` Creates an object whose value you can set.
```{python}
- #| eval: false
-
#...
app_ui = ui.page_fluid(
ui.input_text("a", "A")
)
-
+
def server(input, output, session):
rv = reactive.Value()
rv.set(5)
@@ -225,11 +210,11 @@ Reactive values work together with reactive functions. Call a reactive value fro
### Create Reactive Expressions
-- `@reactive.calc` makes a function a reactive expression. Shiny notifies functions that use the expression when it becomes invalidated, triggering recomputation. Shiny caches the value of the expression while it is valid to avoid unnecessary computation.
+- `@reactive.calc` makes a function a reactive expression.
+ Shiny notifies functions that use the expression when it becomes invalidated, triggering recomputation.
+ Shiny caches the value of the expression while it is valid to avoid unnecessary computation.
```{python}
- #| eval: false
-
#...
def server(input, output, session ):
@reactive.calc
@@ -243,8 +228,6 @@ Reactive values work together with reactive functions. Call a reactive value fro
- `@reactive.event()` Makes a function react only when a specified value is invalidated, here `input.a`.
```{python}
- #| eval: false
-
#...
def server(input, output, session ):
@reactive.Calc
@@ -257,17 +240,17 @@ Reactive values work together with reactive functions. Call a reactive value fro
### Display Reactive Output
- `ui.output_*()` adds an output element to the UI.
+
- `@render.*` decorators render outputs
+
- `def ():` A function to generate the output
```{python}
- #| eval: false
-
app_ui = ui.page_fluid(
ui.input_text("a", "A"),
ui.output_text("b"),
)
-
+
def server(input, output, session ):
@render.text
def b():
@@ -276,11 +259,10 @@ Reactive values work together with reactive functions. Call a reactive value fro
### Perform Side Effects
-- `@reactive.effect` Reactively trigger a function with a side effect. Call a reactive value or use `@reactive.event` to specify when the function will rerun.
+- `@reactive.effect` Reactively trigger a function with a side effect.
+ Call a reactive value or use `@reactive.event` to specify when the function will rerun.
```{python}
- #| eval: false
-
#...
def server(input, output, session ):
@reactive.effect
@@ -292,11 +274,10 @@ Reactive values work together with reactive functions. Call a reactive value fro
### Remove Reactivity
-- `reactive.isolate()`Create non-reactive context within a reactive function. Calling a reactive value within this context will not cause the calling function to re-execute should the value become invalid.
+- `reactive.isolate()`Create non-reactive context within a reactive function.
+ Calling a reactive value within this context will not cause the calling function to re-execute should the value become invalid.
```{python}
- #| eval: false
-
# ...
def server(input, output, session):
@render.text
@@ -310,32 +291,30 @@ Reactive values work together with reactive functions. Call a reactive value fro
Combine multiple elements into a "single element" that has its own properties with a panel function:
-- `ui.panel_absolute()`
-- `ui.panel_conditional()`
-- `ui.panel_fixed()`
-- `ui.panel_main()`
-- `ui.panel_sidebar()`
-- `ui.panel_title()`
-- `ui.panel_well()`
-- `ui.row() / ui.column()`
+- `ui.panel_absolute()`
+- `ui.panel_conditional()`
+- `ui.panel_fixed()`
+- `ui.panel_main()`
+- `ui.panel_sidebar()`
+- `ui.panel_title()`
+- `ui.panel_well()`
+- `ui.row() / ui.column()`
-Layout panels with a layout function. Add elements as arguments of the layout functions.
+Layout panels with a layout function.
+Add elements as arguments of the layout functions.
- `ui.page_sidebar()`
```{python}
-#| eval: false
-
app_ui = ui.page_sider(
ui.sidebar("Sidebar", bg="#f8f8f),
"Main content",
)
```
-- `ui.layout_columns()` with `ui.card()
+- `ui.layout_columns()` with \`ui.card()
```{python}
-# | eval: false
app_ui = ui.page_fillable(
ui.layout_columns(
ui.card(
@@ -351,8 +330,6 @@ app_ui = ui.page_fillable(
Use `ui.nav_panel` with `ui.page_navbar` to create tabs:
```{python}
-#| eval: false
-
# navset tab
app_ui = ui.page_navbar(
ui.nav_panel("A", "Page A content"),
@@ -368,8 +345,6 @@ app_ui = ui.page_navbar(
Use the shinyswatch package to add existing bootstrap themes to your Shiny app ui.
```{python}
-#| eval: false
-
import shinyswatch
app_ui = ui.page_fluid(
@@ -382,29 +357,25 @@ app_ui = ui.page_fluid(
Shiny for Python is quite similar to Shiny for R with a few important differences:
-
1. Call inputs as `input.()`
- R
```{r}
- #| eval: false
input$x
```
- Python
```{python}
- #| eval: false
input.x()
```
-2. Use decorators to create and render outputs. Define outputs as functions `def ():`
+2. Use decorators to create and render outputs. Define outputs as functions `def ():`
- R
```{r}
- #| eval: false
output$y <-
renderText(z())
```
@@ -412,18 +383,16 @@ Shiny for Python is quite similar to Shiny for R with a few important difference
- Python
```{python}
- #| eval: false
@renderText
def y():
return z()
```
-3. To create a reactive expression, use `@reactive.calc`
+3. To create a reactive expression, use `@reactive.calc`
- R
```{r}
- #| eval: false
z <- reactive({
input$x + 1
})
@@ -432,18 +401,16 @@ Shiny for Python is quite similar to Shiny for R with a few important difference
- Python
```{python}
- #| eval: false
@reactive.calc
def z():
return input.x()+1
```
-
-4. To create an observer, use `@reactive.effect`
+
+4. To create an observer, use `@reactive.effect`
- R
```{r}
- #| eval: false
a <- observe({
print(input$x)
})
@@ -452,18 +419,16 @@ Shiny for Python is quite similar to Shiny for R with a few important difference
- Python
```{python}
- #| eval: false
@reactive.effect
def a():
print(input.x())
```
-5. Combine these with `@reactive.event`
+5. Combine these with `@reactive.event`
- R
```{r}
- #| eval: false
b <- eventReactive(
input$goCue,
{
@@ -475,35 +440,31 @@ Shiny for Python is quite similar to Shiny for R with a few important difference
- Python
```{python}
- #| eval: false
@reactive.calc
@reactive.event(input.go_cue )
def b():
return input.x() + 1
```
-
-6. Use `reactive.Value()` instead of `reactiveVal()`
+
+6. Use `reactive.Value()` instead of `reactiveVal()`
- R
```{r}
- #| eval: false
reactiveVal(1)
```
- Python
```{python}
- #| eval: false
reactive.value(1)
- ```
+ ```
-7. Use `nav_*()` instead of `*Tab()`
+7. Use `nav_*()` instead of `*Tab()`
- R
```{r}
- #| eval: false
insertTab()
appendTab()
# etc.
@@ -512,18 +473,16 @@ Shiny for Python is quite similar to Shiny for R with a few important difference
- Python
```{python}
- #| eval: false
nav_insert()
nav_append()
# etc.
- ```
+ ```
-8. Functions are intuitively organized into submodules
+8. Functions are intuitively organized into submodules
- R
```{r}
- #| eval: false
dateInput()
textInput()
# etc.
@@ -532,11 +491,10 @@ Shiny for Python is quite similar to Shiny for R with a few important difference
- Python
```{python}
- #| eval: false
ui.input_date()
ui.input_text()
# etc.
- ```
+ ```
------------------------------------------------------------------------
@@ -546,10 +504,6 @@ Learn more at [shiny.posit.co/py/](https://shiny.posit.co/py/)
Updated: `r format(Sys.Date(), "%Y-%m")`.
-```{r}
-#| output: true
-
-packageVersion("shiny")
-```
+Version: Shiny 0.10.2
------------------------------------------------------------------------
diff --git a/keynotes/shiny-python.key b/keynotes/shiny-python.key
index 61858fef..ece5ed23 100644
Binary files a/keynotes/shiny-python.key and b/keynotes/shiny-python.key differ
diff --git a/pngs/shiny-python.png b/pngs/shiny-python.png
new file mode 100644
index 00000000..c8bfb3ff
Binary files /dev/null and b/pngs/shiny-python.png differ
diff --git "a/pngs/\342\200\216shiny-python.png" "b/pngs/\342\200\216shiny-python.png"
deleted file mode 100644
index 30a01268..00000000
Binary files "a/pngs/\342\200\216shiny-python.png" and /dev/null differ
diff --git a/shiny-python.pdf b/shiny-python.pdf
index 75539413..f385e6d4 100644
Binary files a/shiny-python.pdf and b/shiny-python.pdf differ