---
tags: [gradio-custom-component, ui, form, settings, dataclass]
title: gradio_propertysheet
short_description: Property Sheet Component for Gradio
colorFrom: blue
colorTo: green
sdk: gradio
pinned: true
app_file: space.py
---
# `gradio_propertysheet`
<a href="https://pypi.org/project/gradio_propertysheet/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_propertysheet"></a>
Property sheet
## Installation
```bash
pip install gradio_propertysheet
```
## Usage
```python
import os
from pathlib import Path
import gradio as gr
from dataclasses import dataclass, field, asdict
from typing import Literal
from gradio_propertysheet import PropertySheet
# --- 1. Dataclass Definitions ---
# Dataclasses for the Original Sidebar Demo
@dataclass
class ModelSettings:
"""Settings for loading models, VAEs, etc."""
model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(default="SDXL", metadata={"component": "dropdown", "label": "Base Model"})
custom_model_path: str = field(default="/path/to/default.safetensors", metadata={"label": "Custom Model Path", "interactive_if": {"field": "model_type", "value": "Custom"}})
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
@dataclass
class SamplingSettings:
"""Settings for the image sampling process."""
sampler_name: Literal["Euler", "Euler a", "DPM++ 2M Karras", "UniPC"] = field(default="DPM++ 2M Karras", metadata={"component": "dropdown", "label": "Sampler"})
steps: int = field(default=25, metadata={"component": "slider", "minimum": 1, "maximum": 150, "step": 1})
cfg_scale: float = field(default=7.0, metadata={"component": "slider", "minimum": 1.0, "maximum": 30.0, "step": 0.5})
@dataclass
class RenderConfig:
"""Main configuration object for rendering, grouping all settings."""
seed: int = field(default=-1, metadata={"component": "number_integer", "label": "Seed (-1 for random)"})
model: ModelSettings = field(default_factory=ModelSettings)
sampling: SamplingSettings = field(default_factory=SamplingSettings)
@dataclass
class Lighting:
"""Lighting settings for the environment."""
sun_intensity: float = field(default=1.0, metadata={"component": "slider", "minimum": 0, "maximum": 5, "step": 0.1})
color: str = field(default="#FFDDBB", metadata={"component": "colorpicker", "label": "Sun Color"})
@dataclass
class EnvironmentConfig:
"""Main configuration for the environment."""
background: Literal["Sky", "Color", "Image"] = field(default="Sky", metadata={"component": "dropdown"})
lighting: Lighting = field(default_factory=Lighting)
# Dataclasses for the Flyout Demo
@dataclass
class EulerSettings:
"""Settings specific to the Euler sampler."""
s_churn: float = field(default=0.0, metadata={"component": "slider", "minimum": 0.0, "maximum": 1.0, "step": 0.01})
@dataclass
class DPM_Settings:
"""Settings specific to DPM samplers."""
karras_style: bool = field(default=True, metadata={"label": "Use Karras Sigma Schedule"})
# --- 2. Data Mappings and Initial Instances ---
# Data for Original Sidebar Demo
initial_render_config = RenderConfig()
initial_env_config = EnvironmentConfig()
# Data for Flyout Demo
sampler_settings_map_py = {"Euler": EulerSettings(), "DPM++ 2M Karras": DPM_Settings(), "UniPC": None}
model_settings_map_py = {"SDXL 1.0": DPM_Settings(), "Stable Diffusion 1.5": EulerSettings(), "Pony": None}
# --- 3. CSS and JavaScript Loading ---
# Load external CSS file if it exists
script_path = Path(__file__).resolve()
script_dir = script_path.parent
css_path = script_dir / "custom.css"
flyout_css = ""
if css_path.exists():
with open(css_path, "r", encoding="utf8") as file:
flyout_css = file.read()
# JavaScript for positioning the flyout panel
head_script = f"""
<script>
function position_flyout(anchorId) {{
setTimeout(() => {{
const anchorRow = document.getElementById(anchorId).closest('.fake-input-container');
const flyoutElem = document.getElementById('flyout_panel');
if (anchorRow && flyoutElem && flyoutElem.style.display !== 'none') {{
const anchorRect = anchorRow.getBoundingClientRect();
const containerRect = anchorRow.closest('.flyout-context-area').getBoundingClientRect();
const flyoutWidth = flyoutElem.offsetWidth;
const flyoutHeight = flyoutElem.offsetHeight;
const topPosition = (anchorRect.top - containerRect.top) + (anchorRect.height / 2) - (flyoutHeight / 2);
const leftPosition = (anchorRect.left - containerRect.left) + (anchorRect.width / 2) - (flyoutWidth / 2);
flyoutElem.style.top = `${{topPosition}}px`;
flyoutElem.style.left = `${{leftPosition}}px`;
}}
}}, 50);
}}
</script>
"""
# --- 4. Gradio App Build ---
with gr.Blocks(css=flyout_css, head=head_script, title="PropertySheet Demos") as demo:
gr.Markdown("# PropertySheet Component Demos")
with gr.Tabs():
with gr.TabItem("Original Sidebar Demo"):
gr.Markdown("An example of using the `PropertySheet` component as a traditional sidebar for settings.")
render_state = gr.State(value=initial_render_config)
env_state = gr.State(value=initial_env_config)
sidebar_visible = gr.State(False)
with gr.Row():
with gr.Column(scale=3):
generate = gr.Button("Show Settings", variant="primary")
with gr.Row():
output_render_json = gr.JSON(label="Live Render State")
output_env_json = gr.JSON(label="Live Environment State")
with gr.Column(scale=1):
render_sheet = PropertySheet(
value=initial_render_config,
label="Render Settings",
width=400,
height=550,
visible=False,
root_label="Generator"
)
environment_sheet = PropertySheet(
value=initial_env_config,
label="Environment Settings",
width=400,
open=False,
visible=False,
root_label="General"
)
def change_visibility(is_visible, render_cfg, env_cfg):
new_visibility = not is_visible
button_text = "Hide Settings" if new_visibility else "Show Settings"
return (
new_visibility,
gr.update(visible=new_visibility, value=render_cfg),
gr.update(visible=new_visibility, value=env_cfg),
gr.update(value=button_text)
)
def handle_render_change(updated_config: RenderConfig, current_state: RenderConfig):
if updated_config is None:
return current_state, asdict(current_state), current_state
if updated_config.model.model_type != "Custom":
updated_config.model.custom_model_path = "/path/to/default.safetensors"
return updated_config, asdict(updated_config), updated_config
def handle_env_change(updated_config: EnvironmentConfig, current_state: EnvironmentConfig):
if updated_config is None:
return current_state, asdict(current_state), current_state
return updated_config, asdict(updated_config), current_state
generate.click(
fn=change_visibility,
inputs=[sidebar_visible, render_state, env_state],
outputs=[sidebar_visible, render_sheet, environment_sheet, generate]
)
render_sheet.change(
fn=handle_render_change,
inputs=[render_sheet, render_state],
outputs=[render_sheet, output_render_json, render_state]
)
environment_sheet.change(
fn=handle_env_change,
inputs=[environment_sheet, env_state],
outputs=[environment_sheet, output_env_json, env_state]
)
demo.load(
fn=lambda r_cfg, e_cfg: (asdict(r_cfg), asdict(e_cfg)),
inputs=[render_state, env_state],
outputs=[output_render_json, output_env_json]
)
with gr.TabItem("Flyout Popup Demo"):
gr.Markdown("An example of attaching a `PropertySheet` as a flyout panel to other components.")
flyout_visible = gr.State(False)
active_anchor_id = gr.State(None)
with gr.Column(elem_classes=["flyout-context-area"]):
with gr.Row(elem_classes=["fake-input-container", "no-border-dropdown"]):
sampler_dd = gr.Dropdown(choices=list(sampler_settings_map_py.keys()), label="Sampler", value="Euler", elem_id="sampler_dd", scale=10)
sampler_ear_btn = gr.Button("⚙️", elem_id="sampler_ear_btn", scale=1, elem_classes=["integrated-ear-btn"])
with gr.Row(elem_classes=["fake-input-container", "no-border-dropdown"]):
model_dd = gr.Dropdown(choices=list(model_settings_map_py.keys()), label="Model", value="SDXL 1.0", elem_id="model_dd", scale=10)
model_ear_btn = gr.Button("⚙️", elem_id="model_ear_btn", scale=1, elem_classes=["integrated-ear-btn"])
with gr.Column(visible=False, elem_id="flyout_panel", elem_classes=["flyout-sheet"]) as flyout_panel:
with gr.Row(elem_classes=["close-btn-row"]):
close_btn = gr.Button("×", elem_classes=["flyout-close-btn"])
flyout_sheet = PropertySheet(visible=False, container=False, label="Settings", show_group_name_only_one=False, disable_accordion=True)
def handle_flyout_toggle(is_vis, current_anchor, clicked_dropdown_id, settings_obj):
if is_vis and current_anchor == clicked_dropdown_id:
return False, None, gr.update(visible=False), gr.update(visible=False, value=None)
else:
return True, clicked_dropdown_id, gr.update(visible=True), gr.update(visible=True, value=settings_obj)
def update_ear_visibility(selection, settings_map):
has_settings = settings_map.get(selection) is not None
return gr.update(visible=has_settings)
def on_flyout_change(updated_settings, active_id, sampler_val, model_val):
if updated_settings is None or active_id is None: return
if active_id == sampler_dd.elem_id:
sampler_settings_map_py[sampler_val] = updated_settings
elif active_id == model_dd.elem_id:
model_settings_map_py[model_val] = updated_settings
def close_the_flyout():
return False, None, gr.update(visible=False), gr.update(visible=False, value=None)
sampler_dd.change(
fn=lambda sel: update_ear_visibility(sel, sampler_settings_map_py),
inputs=[sampler_dd],
outputs=[sampler_ear_btn]
).then(fn=close_the_flyout, outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet])
sampler_ear_btn.click(
fn=lambda is_vis, anchor, sel: handle_flyout_toggle(is_vis, anchor, sampler_dd.elem_id, sampler_settings_map_py.get(sel)),
inputs=[flyout_visible, active_anchor_id, sampler_dd],
outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet]
).then(fn=None, inputs=None, outputs=None, js=f"() => position_flyout('{sampler_dd.elem_id}')")
model_dd.change(
fn=lambda sel: update_ear_visibility(sel, model_settings_map_py),
inputs=[model_dd],
outputs=[model_ear_btn]
).then(fn=close_the_flyout, outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet])
model_ear_btn.click(
fn=lambda is_vis, anchor, sel: handle_flyout_toggle(is_vis, anchor, model_dd.elem_id, model_settings_map_py.get(sel)),
inputs=[flyout_visible, active_anchor_id, model_dd],
outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet]
).then(fn=None, inputs=None, outputs=None, js=f"() => position_flyout('{model_dd.elem_id}')")
flyout_sheet.change(
fn=on_flyout_change,
inputs=[flyout_sheet, active_anchor_id, sampler_dd, model_dd],
outputs=None
)
close_btn.click(
fn=close_the_flyout,
inputs=None,
outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet]
)
def initial_flyout_setup(sampler_val, model_val):
return {
sampler_ear_btn: update_ear_visibility(sampler_val, sampler_settings_map_py),
model_ear_btn: update_ear_visibility(model_val, model_settings_map_py)
}
demo.load(fn=initial_flyout_setup, inputs=[sampler_dd, model_dd], outputs=[sampler_ear_btn, model_ear_btn])
if __name__ == "__main__":
demo.launch()
```
## `PropertySheet`
### Initialization
<table>
<thead>
<tr>
<th align="left">name</th>
<th align="left" style="width: 25%;">type</th>
<th align="left">default</th>
<th align="left">description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>value</code></td>
<td align="left" style="width: 25%;">
```python
typing.Optional[typing.Any][Any, None]
```
</td>
<td align="left"><code>None</code></td>
<td align="left">The initial dataclass instance to render.</td>
</tr>
<tr>
<td align="left"><code>label</code></td>
<td align="left" style="width: 25%;">
```python
str | None
```
</td>
<td align="left"><code>None</code></td>
<td align="left">The main label for the component, displayed in the accordion header.</td>
</tr>
<tr>
<td align="left"><code>root_label</code></td>
<td align="left" style="width: 25%;">
```python
str
```
</td>
<td align="left"><code>"General"</code></td>
<td align="left">The label for the root group of properties.</td>
</tr>
<tr>
<td align="left"><code>show_group_name_only_one</code></td>
<td align="left" style="width: 25%;">
```python
bool
```
</td>
<td align="left"><code>True</code></td>
<td align="left">If True, only the group name is shown when there is a single group.</td>
</tr>
<tr>
<td align="left"><code>disable_accordion</code></td>
<td align="left" style="width: 25%;">
```python
bool
```
</td>
<td align="left"><code>False</code></td>
<td align="left">If True, disables the accordion functionality.</td>
</tr>
<tr>
<td align="left"><code>visible</code></td>
<td align="left" style="width: 25%;">
```python
bool
```
</td>
<td align="left"><code>True</code></td>
<td align="left">If False, the component will be hidden.</td>
</tr>
<tr>
<td align="left"><code>open</code></td>
<td align="left" style="width: 25%;">
```python
bool
```
</td>
<td align="left"><code>True</code></td>
<td align="left">If False, the accordion will be collapsed by default.</td>
</tr>
<tr>
<td align="left"><code>elem_id</code></td>
<td align="left" style="width: 25%;">
```python
str | None
```
</td>
<td align="left"><code>None</code></td>
<td align="left">An optional string that is assigned as the id of this component in the DOM.</td>
</tr>
<tr>
<td align="left"><code>scale</code></td>
<td align="left" style="width: 25%;">
```python
int | None
```
</td>
<td align="left"><code>None</code></td>
<td align="left">The relative size of the component in its container.</td>
</tr>
<tr>
<td align="left"><code>width</code></td>
<td align="left" style="width: 25%;">
```python
int | str | None
```
</td>
<td align="left"><code>None</code></td>
<td align="left">The width of the component in pixels.</td>
</tr>
<tr>
<td align="left"><code>height</code></td>
<td align="left" style="width: 25%;">
```python
int | str | None
```
</td>
<td align="left"><code>None</code></td>
<td align="left">The maximum height of the component's content area in pixels before scrolling.</td>
</tr>
<tr>
<td align="left"><code>min_width</code></td>
<td align="left" style="width: 25%;">
```python
int | None
```
</td>
<td align="left"><code>None</code></td>
<td align="left">The minimum width of the component in pixels.</td>
</tr>
<tr>
<td align="left"><code>container</code></td>
<td align="left" style="width: 25%;">
```python
bool
```
</td>
<td align="left"><code>True</code></td>
<td align="left">If True, wraps the component in a container with a background.</td>
</tr>
<tr>
<td align="left"><code>elem_classes</code></td>
<td align="left" style="width: 25%;">
```python
list[str] | str | None
```
</td>
<td align="left"><code>None</code></td>
<td align="left">An optional list of strings that are assigned as the classes of this component in the DOM.</td>
</tr>
</tbody></table>
### Events
| name | description |
|:-----|:------------|
| `change` | |
| `input` | |
| `expand` | |
| `collapse` | |
### User function
The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
- When used as an Input, the component only impacts the input signature of the user function.
- When used as an output, the component only impacts the return signature of the user function.
The code snippet below is accurate in cases where the component is used as both an input and an output.
- **As output:** Is passed, a new, updated instance of the dataclass.
- **As input:** Should return, the dataclass instance to process.
```python
def predict(
value: Any
) -> Any:
return value
```
Raw data
{
"_id": null,
"home_page": null,
"name": "gradio-propertysheet",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "gradio-custom-component, gradio-template-Fallback",
"author": null,
"author_email": "Eliseu Silva <elismasilva@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/4d/23/f1d7123053b96f1808ddd9cc8a5611c3a4687d9cbe2ddbd3b808cc7e2024/gradio_propertysheet-0.0.4.tar.gz",
"platform": null,
"description": "---\ntags: [gradio-custom-component, ui, form, settings, dataclass]\ntitle: gradio_propertysheet\nshort_description: Property Sheet Component for Gradio\ncolorFrom: blue\ncolorTo: green\nsdk: gradio\npinned: true\napp_file: space.py\n---\n\n# `gradio_propertysheet`\n<a href=\"https://pypi.org/project/gradio_propertysheet/\" target=\"_blank\"><img alt=\"PyPI - Version\" src=\"https://img.shields.io/pypi/v/gradio_propertysheet\"></a> \n\nProperty sheet\n\n## Installation\n\n```bash\npip install gradio_propertysheet\n```\n\n## Usage\n\n```python\nimport os\nfrom pathlib import Path\nimport gradio as gr\nfrom dataclasses import dataclass, field, asdict\nfrom typing import Literal\nfrom gradio_propertysheet import PropertySheet\n\n# --- 1. Dataclass Definitions ---\n\n# Dataclasses for the Original Sidebar Demo\n@dataclass\nclass ModelSettings:\n \"\"\"Settings for loading models, VAEs, etc.\"\"\"\n model_type: Literal[\"SD 1.5\", \"SDXL\", \"Pony\", \"Custom\"] = field(default=\"SDXL\", metadata={\"component\": \"dropdown\", \"label\": \"Base Model\"})\n custom_model_path: str = field(default=\"/path/to/default.safetensors\", metadata={\"label\": \"Custom Model Path\", \"interactive_if\": {\"field\": \"model_type\", \"value\": \"Custom\"}})\n vae_path: str = field(default=\"\", metadata={\"label\": \"VAE Path (optional)\"})\n\n@dataclass\nclass SamplingSettings:\n \"\"\"Settings for the image sampling process.\"\"\"\n sampler_name: Literal[\"Euler\", \"Euler a\", \"DPM++ 2M Karras\", \"UniPC\"] = field(default=\"DPM++ 2M Karras\", metadata={\"component\": \"dropdown\", \"label\": \"Sampler\"})\n steps: int = field(default=25, metadata={\"component\": \"slider\", \"minimum\": 1, \"maximum\": 150, \"step\": 1})\n cfg_scale: float = field(default=7.0, metadata={\"component\": \"slider\", \"minimum\": 1.0, \"maximum\": 30.0, \"step\": 0.5})\n\n@dataclass\nclass RenderConfig:\n \"\"\"Main configuration object for rendering, grouping all settings.\"\"\"\n seed: int = field(default=-1, metadata={\"component\": \"number_integer\", \"label\": \"Seed (-1 for random)\"})\n model: ModelSettings = field(default_factory=ModelSettings)\n sampling: SamplingSettings = field(default_factory=SamplingSettings)\n\n@dataclass\nclass Lighting:\n \"\"\"Lighting settings for the environment.\"\"\"\n sun_intensity: float = field(default=1.0, metadata={\"component\": \"slider\", \"minimum\": 0, \"maximum\": 5, \"step\": 0.1})\n color: str = field(default=\"#FFDDBB\", metadata={\"component\": \"colorpicker\", \"label\": \"Sun Color\"})\n\n@dataclass\nclass EnvironmentConfig:\n \"\"\"Main configuration for the environment.\"\"\"\n background: Literal[\"Sky\", \"Color\", \"Image\"] = field(default=\"Sky\", metadata={\"component\": \"dropdown\"})\n lighting: Lighting = field(default_factory=Lighting)\n\n# Dataclasses for the Flyout Demo\n@dataclass\nclass EulerSettings:\n \"\"\"Settings specific to the Euler sampler.\"\"\"\n s_churn: float = field(default=0.0, metadata={\"component\": \"slider\", \"minimum\": 0.0, \"maximum\": 1.0, \"step\": 0.01})\n\n@dataclass\nclass DPM_Settings:\n \"\"\"Settings specific to DPM samplers.\"\"\"\n karras_style: bool = field(default=True, metadata={\"label\": \"Use Karras Sigma Schedule\"})\n\n# --- 2. Data Mappings and Initial Instances ---\n\n# Data for Original Sidebar Demo\ninitial_render_config = RenderConfig()\ninitial_env_config = EnvironmentConfig()\n\n# Data for Flyout Demo\nsampler_settings_map_py = {\"Euler\": EulerSettings(), \"DPM++ 2M Karras\": DPM_Settings(), \"UniPC\": None}\nmodel_settings_map_py = {\"SDXL 1.0\": DPM_Settings(), \"Stable Diffusion 1.5\": EulerSettings(), \"Pony\": None}\n\n# --- 3. CSS and JavaScript Loading ---\n\n# Load external CSS file if it exists\nscript_path = Path(__file__).resolve()\nscript_dir = script_path.parent\ncss_path = script_dir / \"custom.css\"\nflyout_css = \"\"\nif css_path.exists():\n with open(css_path, \"r\", encoding=\"utf8\") as file:\n flyout_css = file.read()\n\n# JavaScript for positioning the flyout panel\nhead_script = f\"\"\"\n<script>\n function position_flyout(anchorId) {{\n setTimeout(() => {{\n const anchorRow = document.getElementById(anchorId).closest('.fake-input-container');\n const flyoutElem = document.getElementById('flyout_panel');\n \n if (anchorRow && flyoutElem && flyoutElem.style.display !== 'none') {{\n const anchorRect = anchorRow.getBoundingClientRect();\n const containerRect = anchorRow.closest('.flyout-context-area').getBoundingClientRect();\n \n const flyoutWidth = flyoutElem.offsetWidth;\n const flyoutHeight = flyoutElem.offsetHeight;\n\n const topPosition = (anchorRect.top - containerRect.top) + (anchorRect.height / 2) - (flyoutHeight / 2);\n const leftPosition = (anchorRect.left - containerRect.left) + (anchorRect.width / 2) - (flyoutWidth / 2);\n\n flyoutElem.style.top = `${{topPosition}}px`;\n flyoutElem.style.left = `${{leftPosition}}px`;\n }}\n }}, 50);\n }}\n</script>\n\"\"\"\n\n# --- 4. Gradio App Build ---\nwith gr.Blocks(css=flyout_css, head=head_script, title=\"PropertySheet Demos\") as demo:\n gr.Markdown(\"# PropertySheet Component Demos\")\n \n with gr.Tabs():\n with gr.TabItem(\"Original Sidebar Demo\"):\n gr.Markdown(\"An example of using the `PropertySheet` component as a traditional sidebar for settings.\")\n \n render_state = gr.State(value=initial_render_config)\n env_state = gr.State(value=initial_env_config)\n sidebar_visible = gr.State(False)\n \n with gr.Row():\n with gr.Column(scale=3): \n generate = gr.Button(\"Show Settings\", variant=\"primary\")\n with gr.Row():\n output_render_json = gr.JSON(label=\"Live Render State\")\n output_env_json = gr.JSON(label=\"Live Environment State\")\n\n with gr.Column(scale=1):\n render_sheet = PropertySheet(\n value=initial_render_config,\n label=\"Render Settings\",\n width=400,\n height=550,\n visible=False,\n root_label=\"Generator\" \n )\n environment_sheet = PropertySheet(\n value=initial_env_config,\n label=\"Environment Settings\",\n width=400,\n open=False,\n visible=False,\n root_label=\"General\" \n )\n\n def change_visibility(is_visible, render_cfg, env_cfg):\n new_visibility = not is_visible\n button_text = \"Hide Settings\" if new_visibility else \"Show Settings\"\n return (\n new_visibility,\n gr.update(visible=new_visibility, value=render_cfg),\n gr.update(visible=new_visibility, value=env_cfg),\n gr.update(value=button_text)\n )\n \n def handle_render_change(updated_config: RenderConfig, current_state: RenderConfig):\n if updated_config is None:\n return current_state, asdict(current_state), current_state\n if updated_config.model.model_type != \"Custom\":\n updated_config.model.custom_model_path = \"/path/to/default.safetensors\"\n return updated_config, asdict(updated_config), updated_config\n\n def handle_env_change(updated_config: EnvironmentConfig, current_state: EnvironmentConfig):\n if updated_config is None:\n return current_state, asdict(current_state), current_state\n return updated_config, asdict(updated_config), current_state\n\n generate.click(\n fn=change_visibility,\n inputs=[sidebar_visible, render_state, env_state],\n outputs=[sidebar_visible, render_sheet, environment_sheet, generate]\n )\n \n render_sheet.change(\n fn=handle_render_change,\n inputs=[render_sheet, render_state],\n outputs=[render_sheet, output_render_json, render_state]\n )\n \n environment_sheet.change(\n fn=handle_env_change,\n inputs=[environment_sheet, env_state],\n outputs=[environment_sheet, output_env_json, env_state]\n )\n \n demo.load(\n fn=lambda r_cfg, e_cfg: (asdict(r_cfg), asdict(e_cfg)),\n inputs=[render_state, env_state],\n outputs=[output_render_json, output_env_json]\n )\n\n with gr.TabItem(\"Flyout Popup Demo\"):\n gr.Markdown(\"An example of attaching a `PropertySheet` as a flyout panel to other components.\")\n \n flyout_visible = gr.State(False)\n active_anchor_id = gr.State(None)\n\n with gr.Column(elem_classes=[\"flyout-context-area\"]):\n with gr.Row(elem_classes=[\"fake-input-container\", \"no-border-dropdown\"]):\n sampler_dd = gr.Dropdown(choices=list(sampler_settings_map_py.keys()), label=\"Sampler\", value=\"Euler\", elem_id=\"sampler_dd\", scale=10)\n sampler_ear_btn = gr.Button(\"\u2699\ufe0f\", elem_id=\"sampler_ear_btn\", scale=1, elem_classes=[\"integrated-ear-btn\"])\n \n with gr.Row(elem_classes=[\"fake-input-container\", \"no-border-dropdown\"]):\n model_dd = gr.Dropdown(choices=list(model_settings_map_py.keys()), label=\"Model\", value=\"SDXL 1.0\", elem_id=\"model_dd\", scale=10)\n model_ear_btn = gr.Button(\"\u2699\ufe0f\", elem_id=\"model_ear_btn\", scale=1, elem_classes=[\"integrated-ear-btn\"])\n\n with gr.Column(visible=False, elem_id=\"flyout_panel\", elem_classes=[\"flyout-sheet\"]) as flyout_panel:\n with gr.Row(elem_classes=[\"close-btn-row\"]):\n close_btn = gr.Button(\"\u00d7\", elem_classes=[\"flyout-close-btn\"])\n flyout_sheet = PropertySheet(visible=False, container=False, label=\"Settings\", show_group_name_only_one=False, disable_accordion=True)\n\n def handle_flyout_toggle(is_vis, current_anchor, clicked_dropdown_id, settings_obj):\n if is_vis and current_anchor == clicked_dropdown_id:\n return False, None, gr.update(visible=False), gr.update(visible=False, value=None)\n else:\n return True, clicked_dropdown_id, gr.update(visible=True), gr.update(visible=True, value=settings_obj)\n\n def update_ear_visibility(selection, settings_map):\n has_settings = settings_map.get(selection) is not None\n return gr.update(visible=has_settings)\n\n def on_flyout_change(updated_settings, active_id, sampler_val, model_val):\n if updated_settings is None or active_id is None: return\n if active_id == sampler_dd.elem_id:\n sampler_settings_map_py[sampler_val] = updated_settings\n elif active_id == model_dd.elem_id:\n model_settings_map_py[model_val] = updated_settings\n \n def close_the_flyout():\n return False, None, gr.update(visible=False), gr.update(visible=False, value=None)\n \n sampler_dd.change(\n fn=lambda sel: update_ear_visibility(sel, sampler_settings_map_py),\n inputs=[sampler_dd],\n outputs=[sampler_ear_btn]\n ).then(fn=close_the_flyout, outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet])\n \n sampler_ear_btn.click(\n fn=lambda is_vis, anchor, sel: handle_flyout_toggle(is_vis, anchor, sampler_dd.elem_id, sampler_settings_map_py.get(sel)),\n inputs=[flyout_visible, active_anchor_id, sampler_dd],\n outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet]\n ).then(fn=None, inputs=None, outputs=None, js=f\"() => position_flyout('{sampler_dd.elem_id}')\")\n\n model_dd.change(\n fn=lambda sel: update_ear_visibility(sel, model_settings_map_py),\n inputs=[model_dd],\n outputs=[model_ear_btn]\n ).then(fn=close_the_flyout, outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet])\n \n model_ear_btn.click(\n fn=lambda is_vis, anchor, sel: handle_flyout_toggle(is_vis, anchor, model_dd.elem_id, model_settings_map_py.get(sel)),\n inputs=[flyout_visible, active_anchor_id, model_dd],\n outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet]\n ).then(fn=None, inputs=None, outputs=None, js=f\"() => position_flyout('{model_dd.elem_id}')\")\n \n flyout_sheet.change(\n fn=on_flyout_change,\n inputs=[flyout_sheet, active_anchor_id, sampler_dd, model_dd],\n outputs=None\n )\n\n close_btn.click(\n fn=close_the_flyout,\n inputs=None,\n outputs=[flyout_visible, active_anchor_id, flyout_panel, flyout_sheet]\n )\n\n def initial_flyout_setup(sampler_val, model_val):\n return {\n sampler_ear_btn: update_ear_visibility(sampler_val, sampler_settings_map_py),\n model_ear_btn: update_ear_visibility(model_val, model_settings_map_py)\n }\n demo.load(fn=initial_flyout_setup, inputs=[sampler_dd, model_dd], outputs=[sampler_ear_btn, model_ear_btn])\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n\n## `PropertySheet`\n\n### Initialization\n\n<table>\n<thead>\n<tr>\n<th align=\"left\">name</th>\n<th align=\"left\" style=\"width: 25%;\">type</th>\n<th align=\"left\">default</th>\n<th align=\"left\">description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"left\"><code>value</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\ntyping.Optional[typing.Any][Any, None]\n```\n\n</td>\n<td align=\"left\"><code>None</code></td>\n<td align=\"left\">The initial dataclass instance to render.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>label</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nstr | None\n```\n\n</td>\n<td align=\"left\"><code>None</code></td>\n<td align=\"left\">The main label for the component, displayed in the accordion header.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>root_label</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nstr\n```\n\n</td>\n<td align=\"left\"><code>\"General\"</code></td>\n<td align=\"left\">The label for the root group of properties.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>show_group_name_only_one</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nbool\n```\n\n</td>\n<td align=\"left\"><code>True</code></td>\n<td align=\"left\">If True, only the group name is shown when there is a single group.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>disable_accordion</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nbool\n```\n\n</td>\n<td align=\"left\"><code>False</code></td>\n<td align=\"left\">If True, disables the accordion functionality.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>visible</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nbool\n```\n\n</td>\n<td align=\"left\"><code>True</code></td>\n<td align=\"left\">If False, the component will be hidden.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>open</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nbool\n```\n\n</td>\n<td align=\"left\"><code>True</code></td>\n<td align=\"left\">If False, the accordion will be collapsed by default.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>elem_id</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nstr | None\n```\n\n</td>\n<td align=\"left\"><code>None</code></td>\n<td align=\"left\">An optional string that is assigned as the id of this component in the DOM.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>scale</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nint | None\n```\n\n</td>\n<td align=\"left\"><code>None</code></td>\n<td align=\"left\">The relative size of the component in its container.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>width</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nint | str | None\n```\n\n</td>\n<td align=\"left\"><code>None</code></td>\n<td align=\"left\">The width of the component in pixels.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>height</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nint | str | None\n```\n\n</td>\n<td align=\"left\"><code>None</code></td>\n<td align=\"left\">The maximum height of the component's content area in pixels before scrolling.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>min_width</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nint | None\n```\n\n</td>\n<td align=\"left\"><code>None</code></td>\n<td align=\"left\">The minimum width of the component in pixels.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>container</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nbool\n```\n\n</td>\n<td align=\"left\"><code>True</code></td>\n<td align=\"left\">If True, wraps the component in a container with a background.</td>\n</tr>\n\n<tr>\n<td align=\"left\"><code>elem_classes</code></td>\n<td align=\"left\" style=\"width: 25%;\">\n\n```python\nlist[str] | str | None\n```\n\n</td>\n<td align=\"left\"><code>None</code></td>\n<td align=\"left\">An optional list of strings that are assigned as the classes of this component in the DOM.</td>\n</tr>\n</tbody></table>\n\n\n### Events\n\n| name | description |\n|:-----|:------------|\n| `change` | |\n| `input` | |\n| `expand` | |\n| `collapse` | |\n\n\n\n### User function\n\nThe impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).\n\n- When used as an Input, the component only impacts the input signature of the user function.\n- When used as an output, the component only impacts the return signature of the user function.\n\nThe code snippet below is accurate in cases where the component is used as both an input and an output.\n\n- **As output:** Is passed, a new, updated instance of the dataclass.\n- **As input:** Should return, the dataclass instance to process.\n\n ```python\n def predict(\n value: Any\n ) -> Any:\n return value\n ```\n \n",
"bugtrack_url": null,
"license": null,
"summary": "Property sheet",
"version": "0.0.4",
"project_urls": null,
"split_keywords": [
"gradio-custom-component",
" gradio-template-fallback"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "f4cb0b7e38626254529b03bca266d8327bfa2507d7c70d6f6ac1a68e6f82c4d6",
"md5": "22193ee4fbdc02bfc6d2ae286b8196e7",
"sha256": "b0cf672cf437f9afc9b008ae727323f85ddfae34a74f14a2d9868ff22b0ffbcb"
},
"downloads": -1,
"filename": "gradio_propertysheet-0.0.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "22193ee4fbdc02bfc6d2ae286b8196e7",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 103202,
"upload_time": "2025-07-27T02:21:24",
"upload_time_iso_8601": "2025-07-27T02:21:24.899208Z",
"url": "https://files.pythonhosted.org/packages/f4/cb/0b7e38626254529b03bca266d8327bfa2507d7c70d6f6ac1a68e6f82c4d6/gradio_propertysheet-0.0.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4d23f1d7123053b96f1808ddd9cc8a5611c3a4687d9cbe2ddbd3b808cc7e2024",
"md5": "681d586cf0a67eb55add4b426d7b633f",
"sha256": "ccab50eb2df93f6ffe4cf87becee0f80ad639548a625e70061e8ae36cefceaae"
},
"downloads": -1,
"filename": "gradio_propertysheet-0.0.4.tar.gz",
"has_sig": false,
"md5_digest": "681d586cf0a67eb55add4b426d7b633f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 171217,
"upload_time": "2025-07-27T02:21:26",
"upload_time_iso_8601": "2025-07-27T02:21:26.443835Z",
"url": "https://files.pythonhosted.org/packages/4d/23/f1d7123053b96f1808ddd9cc8a5611c3a4687d9cbe2ddbd3b808cc7e2024/gradio_propertysheet-0.0.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-27 02:21:26",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "gradio-propertysheet"
}