|
|
---
|
|
|
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`
|
|
|
<img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.4%20-%20blue"> <a href="https://huggingface.co/spaces/elismasilva/gradio_propertysheet"><img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Demo-blue"></a><p><span>💻 <a href='https://github.com/DEVAIEXP/gradio_component_propertysheet'>Component GitHub Code</a></span></p>
|
|
|
|
|
|
The **PropertySheet** component for Gradio allows you to automatically generate a complete and interactive settings panel from a standard Python `dataclass`. It's designed to bring the power of IDE-like property editors directly into your Gradio applications.
|
|
|
|
|
|
<img src="https://huggingface.co/datasets/DEVAIEXP/assets/resolve/main/gradio_propertysheet.png" alt="PropertySheet Demo">
|
|
|
|
|
|
## Key Features
|
|
|
|
|
|
- **Automatic UI Generation**: Instantly converts `dataclass` fields into a structured UI.
|
|
|
- **Rich Component Support**: Automatically maps Python types to UI controls:
|
|
|
- `str` -> Text Input
|
|
|
- `int`, `float` -> Number Input
|
|
|
- `bool` -> Styled Checkbox
|
|
|
- `typing.Literal` -> Dropdown
|
|
|
- **Metadata-Driven Components**: Force a specific component using metadata:
|
|
|
- `metadata={"component": "slider"}`
|
|
|
- `metadata={"component": "colorpicker"}`
|
|
|
- **Nested Groups**: Nested `dataclasses` are rendered as collapsible groups for organization.
|
|
|
- **Conditional Visibility**: Show or hide fields based on the value of others using `interactive_if` metadata.
|
|
|
- **Built-in Helpers**:
|
|
|
- **Tooltips**: Add `help` text to any property's metadata for an info icon.
|
|
|
- **Reset Button**: Each property gets a button to reset its value to default.
|
|
|
- **Accordion Layout**: The entire component can act as a main collapsible accordion panel using the `open` parameter.
|
|
|
- **Theme-Aware**: Designed to look and feel native in all Gradio themes.
|
|
|
- **Dynamic Updates**: Supports advanced patterns where changing one field (e.g., a model selector) can dynamically update the options of another field (e.g., a sampler dropdown).
|
|
|
|
|
|
## 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
|
|
|
```
|
|
|
|
|
|
|