Skip to main content

Property sheet

Project description


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

Static Badge

💻 Component GitHub Code

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.

PropertySheet Demo" alt="PropertySheet Demo GIF">

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

pip install gradio_propertysheet

Usage

import gradio as gr
from dataclasses import dataclass, field, asdict
from typing import Literal
from gradio_propertysheet import PropertySheet

# --- Main Configuration Dataclasses for the "Render Settings" Sheet ---
@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", "help": "The algorithm for the diffusion process."}
    )
    steps: int = field(
        default=25,
        metadata={"component": "slider", "minimum": 1, "maximum": 150, "step": 1, "label": "Sampling Steps", "help": "More steps can improve quality."}
    )
    cfg_scale: float = field(
        default=7.0,
        metadata={"component": "slider", "minimum": 1.0, "maximum": 30.0, "step": 0.5, "label": "CFG Scale", "help": "How strongly the prompt is adhered to."}
    )

@dataclass
class ImageSettings:
    """Settings for image dimensions."""
    width: int = field(
        default=1024,
        metadata={"component": "slider", "minimum": 512, "maximum": 2048, "step": 64, "label": "Image Width"}
    )
    height: int = field(
        default=1024,
        metadata={"component": "slider", "minimum": 512, "maximum": 2048, "step": 64, "label": "Image Height"}
    )

@dataclass
class PostprocessingSettings:
    """Settings for image post-processing effects."""
    restore_faces: bool = field(
        default=True,
        metadata={"label": "Restore Faces", "help": "Use a secondary model to fix distorted faces."}
    )
    enable_hr: bool = field(
        default=False,
        metadata={"label": "Hires. fix", "help": "Enable a second pass at a higher resolution."}
    )
    denoising_strength: float = field(
        default=0.45,
        metadata={"component": "slider", "minimum": 0.0, "maximum": 1.0, "step": 0.01, "label": "Denoising Strength", "interactive_if": {"field": "enable_hr", "value": True}}
    )

@dataclass
class AdvancedSettings:
    """Advanced and rarely changed settings."""
    clip_skip: int = field(
        default=2,
        metadata={"component": "slider", "minimum": 1, "maximum": 12, "step": 1, "label": "CLIP Skip", "help": "Skip final layers of the text encoder."}
    )
    noise_schedule: Literal["Default", "Karras", "Exponential"] = field(
        default="Karras",
        metadata={"component": "dropdown", "label": "Noise Schedule"}
    )
    do_not_scale_cond_uncond: bool = field(
        default=False,
        metadata={"label": "Do not scale cond/uncond"}
    )
    s_churn: int = field(
        default=1,
        metadata={"component": "number_integer", "minimum": 1, "maximum": 12, "label": "S_churn", "help": "S_churn value for generation."}
    )

@dataclass
class ScriptSettings:
    """Settings for automation scripts like X/Y/Z plots."""
    script_name: Literal["None", "Prompt matrix", "X/Y/Z plot"] = field(
        default="None",
        metadata={"component": "dropdown", "label": "Script"}
    )
    x_values: str = field(
        default="-1, 10, 20",
        metadata={"label": "X axis values", "interactive_if": {"field": "script_name", "value": "X/Y/Z plot"}}
    )
    y_values: str = field(
        default="",
        metadata={"label": "Y axis values", "interactive_if": {"field": "script_name", "value": "X/Y/Z plot"}}
    )

@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)", "help": "The random seed for generation."}
    )
    batch_size: int = field(
        default=1,
        metadata={"component": "slider", "minimum": 1, "maximum": 8, "step": 1, "label": "Batch Size"}
    )
    # Nested groups
    model: ModelSettings = field(default_factory=ModelSettings)
    sampling: SamplingSettings = field(default_factory=SamplingSettings)
    image: ImageSettings = field(default_factory=ImageSettings)
    postprocessing: PostprocessingSettings = field(default_factory=PostprocessingSettings)
    scripts: ScriptSettings = field(default_factory=ScriptSettings)
    advanced: AdvancedSettings = field(default_factory=AdvancedSettings)


@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})
    ambient_occlusion: bool = field(default=True, metadata={"label": "Ambient Occlusion"})
    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)


# --- Initial Instances ---
initial_render_config = RenderConfig()
initial_env_config = EnvironmentConfig()

# --- Gradio Application ---
with gr.Blocks(title="PropertySheet Demo") as demo:
    gr.Markdown("# PropertySheet Component Demo")
    gr.Markdown("An example of a realistic application layout using the `PropertySheet` component as a sidebar for settings.")
    gr.Markdown("<span>💻 <a href='https://github.com/DEVAIEXP/gradio_component_propertysheet'>Component GitHub Code</a></span>")
    
    with gr.Row():
        # Main content area on the left
        with gr.Column(scale=3):
            #gr.Image(label="Main Viewport", height=500, value=None)
            gr.Textbox(label="AI Prompt", lines=3, placeholder="Enter your prompt here...")
            gr.Button("Generate", variant="primary")
            with gr.Row():
                output_render_json = gr.JSON(label="Live Render State")
                output_env_json = gr.JSON(label="Live Environment State")

        # Sidebar with Property Sheets on the right
        with gr.Column(scale=1):
            render_sheet = PropertySheet(
                value=initial_render_config, 
                label="Render Settings",
                width=400,
                height=550  # Set a fixed height to demonstrate internal scrolling
            )
            environment_sheet = PropertySheet(
                value=initial_env_config,
                label="Environment Settings",
                width=400,
                open=False  # Start collapsed to show the accordion feature
            )

    # --- Event Handlers ---
    def handle_render_change(updated_config: RenderConfig | None):
        """Callback to process changes from the Render Settings sheet."""
        if updated_config is None:
            return initial_render_config, asdict(initial_render_config)
        
        # Example of business logic: reset custom path if not in custom mode
        if updated_config.model.model_type != "Custom":
            updated_config.model.custom_model_path = "/path/to/default.safetensors"
            
        return updated_config, asdict(updated_config)

    def handle_env_change(updated_config: EnvironmentConfig | None):
        """Callback to process changes from the Environment Settings sheet."""
        if updated_config is None:
            return initial_env_config, asdict(initial_env_config)
        return updated_config, asdict(updated_config)

    render_sheet.change(
        fn=handle_render_change,
        inputs=[render_sheet],
        outputs=[render_sheet, output_render_json]
    )
    environment_sheet.change(
        fn=handle_env_change,
        inputs=[environment_sheet],
        outputs=[environment_sheet, output_env_json]
    )
   
    # Load initial state into JSON viewers on app load
    demo.load(
        fn=lambda: (asdict(initial_render_config), asdict(initial_env_config)),
        outputs=[output_render_json, output_env_json]
    )

if __name__ == "__main__":
    demo.launch()

PropertySheet

Initialization

name type default description
value
typing.Optional[typing.Any][Any, None]
None The initial dataclass instance to render.
label
str | None
None The main label for the component, displayed in the accordion header.
visible
bool
True If False, the component will be hidden.
open
bool
True If False, the accordion will be collapsed by default.
elem_id
str | None
None An optional string that is assigned as the id of this component in the DOM.
scale
int | None
None The relative size of the component in its container.
width
int | str | None
None The width of the component in pixels.
height
int | str | None
None The maximum height of the component's content area in pixels before scrolling.
min_width
int | None
None The minimum width of the component in pixels.
container
bool
True If True, wraps the component in a container with a background.
elem_classes
list[str] | str | None
None An optional list of strings that are assigned as the classes of this component in the DOM.

Events

name description
change Triggered when a value is changed and committed (e.g., on slider release, or after unfocusing a textbox).
input Triggered on every keystroke or slider movement.
expand Triggered when the main accordion is opened.
collapse Triggered when the main accordion is closed.

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.

def predict(
    value: Any
) -> Any:
    return value

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gradio_propertysheet-0.0.3.tar.gz (169.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gradio_propertysheet-0.0.3-py3-none-any.whl (102.6 kB view details)

Uploaded Python 3

File details

Details for the file gradio_propertysheet-0.0.3.tar.gz.

File metadata

  • Download URL: gradio_propertysheet-0.0.3.tar.gz
  • Upload date:
  • Size: 169.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.11

File hashes

Hashes for gradio_propertysheet-0.0.3.tar.gz
Algorithm Hash digest
SHA256 6846d0ef91aca0a362fcdc63f329bdd0d8a26ef5f202d1fac2bd7160ad8e6985
MD5 07ada5ade9389a5f14d260e46f6a3d40
BLAKE2b-256 48329ee177bcfd70186041e00de7ae2b50f973968f0030b92961ed100220bb17

See more details on using hashes here.

File details

Details for the file gradio_propertysheet-0.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for gradio_propertysheet-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 85750471f7044c6c36821db9e797d2c0b2cfd8b3a6e739bb5f35cbfd5c522596
MD5 f685f34a0fadb16a85f5b8e30a3d71d6
BLAKE2b-256 783e1603509db4d3ca057737c1e084336af2e95d8c455635d78c8628bf727d46

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page