elismasilva commited on
Commit
e1ddfe9
·
verified ·
1 Parent(s): 4b5a5aa

Upload folder using huggingface_hub

Browse files
README.md CHANGED
@@ -10,7 +10,7 @@ app_file: space.py
10
  ---
11
 
12
  # `gradio_propertysheet`
13
- <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.8%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>
14
 
15
  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.
16
 
@@ -39,6 +39,7 @@ The **PropertySheet** component for Gradio allows you to automatically generate
39
 
40
  ## Installation
41
 
 
42
  ```bash
43
  pip install gradio_propertysheet
44
  ```
@@ -65,7 +66,7 @@ class ModelSettings:
65
  default="/path/to/default.safetensors",
66
  metadata={
67
  "label": "Custom Model Path",
68
- "interactive_if": {"field": "model.model_type", "value": "Custom"},
69
  },
70
  )
71
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
@@ -101,7 +102,7 @@ class SamplingSettings:
101
  "minimum": 0.0,
102
  "maximum": 1.0,
103
  "step": 0.01,
104
- "interactive_if": {"field": "sampling.enable_advanced", "value": True},
105
  },
106
  )
107
  temperature: float = field(
@@ -114,6 +115,7 @@ class SamplingSettings:
114
  "step": 0.1
115
  }
116
  )
 
117
  @dataclass
118
  class RenderConfig:
119
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
@@ -124,7 +126,6 @@ class RenderConfig:
124
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
125
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
126
 
127
-
128
  @dataclass
129
  class Lighting:
130
  sun_intensity: float = field(
@@ -235,7 +236,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
235
  height=550,
236
  visible=False,
237
  root_label="Generator",
238
- interactive=True
239
  )
240
  environment_sheet = PropertySheet(
241
  value=initial_env_config,
@@ -244,7 +245,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
244
  open=False,
245
  visible=False,
246
  root_label="General",
247
- interactive=True
 
248
  )
249
 
250
  def change_visibility(is_visible, render_cfg, env_cfg):
@@ -551,6 +553,19 @@ bool
551
  <td align="left">If True, only the group name is shown when there is a single group.</td>
552
  </tr>
553
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  <tr>
555
  <td align="left"><code>disable_accordion</code></td>
556
  <td align="left" style="width: 25%;">
 
10
  ---
11
 
12
  # `gradio_propertysheet`
13
+ <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.9%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>
14
 
15
  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.
16
 
 
39
 
40
  ## Installation
41
 
42
+
43
  ```bash
44
  pip install gradio_propertysheet
45
  ```
 
66
  default="/path/to/default.safetensors",
67
  metadata={
68
  "label": "Custom Model Path",
69
+ "interactive_if": {"field": "model_type", "value": "Custom"},
70
  },
71
  )
72
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
 
102
  "minimum": 0.0,
103
  "maximum": 1.0,
104
  "step": 0.01,
105
+ "interactive_if": {"field": "enable_advanced", "value": True},
106
  },
107
  )
108
  temperature: float = field(
 
115
  "step": 0.1
116
  }
117
  )
118
+
119
  @dataclass
120
  class RenderConfig:
121
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
 
126
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
127
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
128
 
 
129
  @dataclass
130
  class Lighting:
131
  sun_intensity: float = field(
 
236
  height=550,
237
  visible=False,
238
  root_label="Generator",
239
+ interactive=True
240
  )
241
  environment_sheet = PropertySheet(
242
  value=initial_env_config,
 
245
  open=False,
246
  visible=False,
247
  root_label="General",
248
+ interactive=True,
249
+ root_properties_first=False
250
  )
251
 
252
  def change_visibility(is_visible, render_cfg, env_cfg):
 
553
  <td align="left">If True, only the group name is shown when there is a single group.</td>
554
  </tr>
555
 
556
+ <tr>
557
+ <td align="left"><code>root_properties_first</code></td>
558
+ <td align="left" style="width: 25%;">
559
+
560
+ ```python
561
+ bool
562
+ ```
563
+
564
+ </td>
565
+ <td align="left"><code>True</code></td>
566
+ <td align="left">If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.</td>
567
+ </tr>
568
+
569
  <tr>
570
  <td align="left"><code>disable_accordion</code></td>
571
  <td align="left" style="width: 25%;">
app.py CHANGED
@@ -17,7 +17,7 @@ class ModelSettings:
17
  default="/path/to/default.safetensors",
18
  metadata={
19
  "label": "Custom Model Path",
20
- "interactive_if": {"field": "model.model_type", "value": "Custom"},
21
  },
22
  )
23
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
@@ -53,7 +53,7 @@ class SamplingSettings:
53
  "minimum": 0.0,
54
  "maximum": 1.0,
55
  "step": 0.01,
56
- "interactive_if": {"field": "sampling.enable_advanced", "value": True},
57
  },
58
  )
59
  temperature: float = field(
@@ -66,6 +66,7 @@ class SamplingSettings:
66
  "step": 0.1
67
  }
68
  )
 
69
  @dataclass
70
  class RenderConfig:
71
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
@@ -76,7 +77,6 @@ class RenderConfig:
76
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
77
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
78
 
79
-
80
  @dataclass
81
  class Lighting:
82
  sun_intensity: float = field(
@@ -187,7 +187,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
187
  height=550,
188
  visible=False,
189
  root_label="Generator",
190
- interactive=True
191
  )
192
  environment_sheet = PropertySheet(
193
  value=initial_env_config,
@@ -196,7 +196,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
196
  open=False,
197
  visible=False,
198
  root_label="General",
199
- interactive=True
 
200
  )
201
 
202
  def change_visibility(is_visible, render_cfg, env_cfg):
 
17
  default="/path/to/default.safetensors",
18
  metadata={
19
  "label": "Custom Model Path",
20
+ "interactive_if": {"field": "model_type", "value": "Custom"},
21
  },
22
  )
23
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
 
53
  "minimum": 0.0,
54
  "maximum": 1.0,
55
  "step": 0.01,
56
+ "interactive_if": {"field": "enable_advanced", "value": True},
57
  },
58
  )
59
  temperature: float = field(
 
66
  "step": 0.1
67
  }
68
  )
69
+
70
  @dataclass
71
  class RenderConfig:
72
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
 
77
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
78
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
79
 
 
80
  @dataclass
81
  class Lighting:
82
  sun_intensity: float = field(
 
187
  height=550,
188
  visible=False,
189
  root_label="Generator",
190
+ interactive=True
191
  )
192
  environment_sheet = PropertySheet(
193
  value=initial_env_config,
 
196
  open=False,
197
  visible=False,
198
  root_label="General",
199
+ interactive=True,
200
+ root_properties_first=False
201
  )
202
 
203
  def change_visibility(is_visible, render_cfg, env_cfg):
space.py CHANGED
@@ -3,7 +3,7 @@ import gradio as gr
3
  from app import demo as app
4
  import os
5
 
6
- _docs = {'PropertySheet': {'description': 'A Gradio component that renders a dynamic UI from a Python dataclass instance.\nIt allows for nested settings and automatically infers input types.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Any][Any, None]', 'default': 'None', 'description': 'The initial dataclass instance to render.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The main label for the component, displayed in the accordion header.'}, 'root_label': {'type': 'str', 'default': '"General"', 'description': 'The label for the root group of properties.'}, 'show_group_name_only_one': {'type': 'bool', 'default': 'True', 'description': 'If True, only the group name is shown when there is a single group.'}, 'disable_accordion': {'type': 'bool', 'default': 'False', 'description': 'If True, disables the accordion functionality.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'open': {'type': 'bool', 'default': 'True', 'description': 'If False, the accordion will be collapsed by default.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component in its container.'}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': "The maximum height of the component's content area in pixels before scrolling."}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, wraps the component in a container with a background.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the DOM.'}}, 'postprocess': {'value': {'type': 'Any', 'description': 'The dataclass instance to process.'}}, 'preprocess': {'return': {'type': 'Any', 'description': 'A new, updated instance of the dataclass.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the PropertySheet changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'input': {'type': None, 'default': None, 'description': 'This listener is triggered when the user changes the value of the PropertySheet.'}, 'expand': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is expanded.'}, 'collapse': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is collapsed.'}, 'undo': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clicks the undo button in component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'PropertySheet': []}}}
7
 
8
  abs_path = os.path.join(os.path.dirname(__file__), "css.css")
9
 
@@ -57,7 +57,7 @@ class ModelSettings:
57
  default="/path/to/default.safetensors",
58
  metadata={
59
  "label": "Custom Model Path",
60
- "interactive_if": {"field": "model.model_type", "value": "Custom"},
61
  },
62
  )
63
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
@@ -93,7 +93,7 @@ class SamplingSettings:
93
  "minimum": 0.0,
94
  "maximum": 1.0,
95
  "step": 0.01,
96
- "interactive_if": {"field": "sampling.enable_advanced", "value": True},
97
  },
98
  )
99
  temperature: float = field(
@@ -106,6 +106,7 @@ class SamplingSettings:
106
  "step": 0.1
107
  }
108
  )
 
109
  @dataclass
110
  class RenderConfig:
111
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
@@ -116,7 +117,6 @@ class RenderConfig:
116
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
117
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
118
 
119
-
120
  @dataclass
121
  class Lighting:
122
  sun_intensity: float = field(
@@ -227,7 +227,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
227
  height=550,
228
  visible=False,
229
  root_label="Generator",
230
- interactive=True
231
  )
232
  environment_sheet = PropertySheet(
233
  value=initial_env_config,
@@ -236,7 +236,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
236
  open=False,
237
  visible=False,
238
  root_label="General",
239
- interactive=True
 
240
  )
241
 
242
  def change_visibility(is_visible, render_cfg, env_cfg):
 
3
  from app import demo as app
4
  import os
5
 
6
+ _docs = {'PropertySheet': {'description': 'A Gradio component that renders a dynamic UI from a Python dataclass instance.\nIt allows for nested settings and automatically infers input types.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Any][Any, None]', 'default': 'None', 'description': 'The initial dataclass instance to render.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The main label for the component, displayed in the accordion header.'}, 'root_label': {'type': 'str', 'default': '"General"', 'description': 'The label for the root group of properties.'}, 'show_group_name_only_one': {'type': 'bool', 'default': 'True', 'description': 'If True, only the group name is shown when there is a single group.'}, 'root_properties_first': {'type': 'bool', 'default': 'True', 'description': 'If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.'}, 'disable_accordion': {'type': 'bool', 'default': 'False', 'description': 'If True, disables the accordion functionality.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'open': {'type': 'bool', 'default': 'True', 'description': 'If False, the accordion will be collapsed by default.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component in its container.'}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': "The maximum height of the component's content area in pixels before scrolling."}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, wraps the component in a container with a background.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the DOM.'}}, 'postprocess': {'value': {'type': 'Any', 'description': 'The dataclass instance to process.'}}, 'preprocess': {'return': {'type': 'Any', 'description': 'A new, updated instance of the dataclass.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the PropertySheet changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'input': {'type': None, 'default': None, 'description': 'This listener is triggered when the user changes the value of the PropertySheet.'}, 'expand': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is expanded.'}, 'collapse': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is collapsed.'}, 'undo': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clicks the undo button in component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'PropertySheet': []}}}
7
 
8
  abs_path = os.path.join(os.path.dirname(__file__), "css.css")
9
 
 
57
  default="/path/to/default.safetensors",
58
  metadata={
59
  "label": "Custom Model Path",
60
+ "interactive_if": {"field": "model_type", "value": "Custom"},
61
  },
62
  )
63
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
 
93
  "minimum": 0.0,
94
  "maximum": 1.0,
95
  "step": 0.01,
96
+ "interactive_if": {"field": "enable_advanced", "value": True},
97
  },
98
  )
99
  temperature: float = field(
 
106
  "step": 0.1
107
  }
108
  )
109
+
110
  @dataclass
111
  class RenderConfig:
112
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
 
117
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
118
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
119
 
 
120
  @dataclass
121
  class Lighting:
122
  sun_intensity: float = field(
 
227
  height=550,
228
  visible=False,
229
  root_label="Generator",
230
+ interactive=True
231
  )
232
  environment_sheet = PropertySheet(
233
  value=initial_env_config,
 
236
  open=False,
237
  visible=False,
238
  root_label="General",
239
+ interactive=True,
240
+ root_properties_first=False
241
  )
242
 
243
  def change_visibility(is_visible, render_cfg, env_cfg):
src/README.md CHANGED
@@ -10,7 +10,7 @@ app_file: space.py
10
  ---
11
 
12
  # `gradio_propertysheet`
13
- <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.8%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>
14
 
15
  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.
16
 
@@ -39,6 +39,7 @@ The **PropertySheet** component for Gradio allows you to automatically generate
39
 
40
  ## Installation
41
 
 
42
  ```bash
43
  pip install gradio_propertysheet
44
  ```
@@ -65,7 +66,7 @@ class ModelSettings:
65
  default="/path/to/default.safetensors",
66
  metadata={
67
  "label": "Custom Model Path",
68
- "interactive_if": {"field": "model.model_type", "value": "Custom"},
69
  },
70
  )
71
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
@@ -101,7 +102,7 @@ class SamplingSettings:
101
  "minimum": 0.0,
102
  "maximum": 1.0,
103
  "step": 0.01,
104
- "interactive_if": {"field": "sampling.enable_advanced", "value": True},
105
  },
106
  )
107
  temperature: float = field(
@@ -114,6 +115,7 @@ class SamplingSettings:
114
  "step": 0.1
115
  }
116
  )
 
117
  @dataclass
118
  class RenderConfig:
119
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
@@ -124,7 +126,6 @@ class RenderConfig:
124
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
125
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
126
 
127
-
128
  @dataclass
129
  class Lighting:
130
  sun_intensity: float = field(
@@ -235,7 +236,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
235
  height=550,
236
  visible=False,
237
  root_label="Generator",
238
- interactive=True
239
  )
240
  environment_sheet = PropertySheet(
241
  value=initial_env_config,
@@ -244,7 +245,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
244
  open=False,
245
  visible=False,
246
  root_label="General",
247
- interactive=True
 
248
  )
249
 
250
  def change_visibility(is_visible, render_cfg, env_cfg):
@@ -551,6 +553,19 @@ bool
551
  <td align="left">If True, only the group name is shown when there is a single group.</td>
552
  </tr>
553
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  <tr>
555
  <td align="left"><code>disable_accordion</code></td>
556
  <td align="left" style="width: 25%;">
 
10
  ---
11
 
12
  # `gradio_propertysheet`
13
+ <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.9%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>
14
 
15
  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.
16
 
 
39
 
40
  ## Installation
41
 
42
+
43
  ```bash
44
  pip install gradio_propertysheet
45
  ```
 
66
  default="/path/to/default.safetensors",
67
  metadata={
68
  "label": "Custom Model Path",
69
+ "interactive_if": {"field": "model_type", "value": "Custom"},
70
  },
71
  )
72
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
 
102
  "minimum": 0.0,
103
  "maximum": 1.0,
104
  "step": 0.01,
105
+ "interactive_if": {"field": "enable_advanced", "value": True},
106
  },
107
  )
108
  temperature: float = field(
 
115
  "step": 0.1
116
  }
117
  )
118
+
119
  @dataclass
120
  class RenderConfig:
121
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
 
126
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
127
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
128
 
 
129
  @dataclass
130
  class Lighting:
131
  sun_intensity: float = field(
 
236
  height=550,
237
  visible=False,
238
  root_label="Generator",
239
+ interactive=True
240
  )
241
  environment_sheet = PropertySheet(
242
  value=initial_env_config,
 
245
  open=False,
246
  visible=False,
247
  root_label="General",
248
+ interactive=True,
249
+ root_properties_first=False
250
  )
251
 
252
  def change_visibility(is_visible, render_cfg, env_cfg):
 
553
  <td align="left">If True, only the group name is shown when there is a single group.</td>
554
  </tr>
555
 
556
+ <tr>
557
+ <td align="left"><code>root_properties_first</code></td>
558
+ <td align="left" style="width: 25%;">
559
+
560
+ ```python
561
+ bool
562
+ ```
563
+
564
+ </td>
565
+ <td align="left"><code>True</code></td>
566
+ <td align="left">If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.</td>
567
+ </tr>
568
+
569
  <tr>
570
  <td align="left"><code>disable_accordion</code></td>
571
  <td align="left" style="width: 25%;">
src/backend/gradio_propertysheet/propertysheet.py CHANGED
@@ -42,6 +42,7 @@ class PropertySheet(Component):
42
  label: str | None = None,
43
  root_label: str = "General",
44
  show_group_name_only_one: bool = True,
 
45
  disable_accordion: bool = False,
46
  visible: bool = True,
47
  open: bool = True,
@@ -62,6 +63,7 @@ class PropertySheet(Component):
62
  label: The main label for the component, displayed in the accordion header.
63
  root_label: The label for the root group of properties.
64
  show_group_name_only_one: If True, only the group name is shown when there is a single group.
 
65
  disable_accordion: If True, disables the accordion functionality.
66
  visible: If False, the component will be hidden.
67
  open: If False, the accordion will be collapsed by default.
@@ -86,6 +88,7 @@ class PropertySheet(Component):
86
  self.open = open
87
  self.root_label = root_label
88
  self.show_group_name_only_one = show_group_name_only_one
 
89
  self.disable_accordion = disable_accordion
90
 
91
  super().__init__(
@@ -132,23 +135,39 @@ class PropertySheet(Component):
132
  if is_nested_dataclass:
133
  group_obj = getattr(current_value, field.name)
134
  group_props = []
135
- for group_field in dataclasses.fields(group_obj):
136
- metadata = extract_prop_metadata(group_obj, group_field)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  metadata["name"] = f"{field.name}.{group_field.name}"
138
  group_props.append(metadata)
139
 
140
- base_group_name = field.metadata.get("label", field.name.replace("_", " ").title())
141
  unique_group_name = base_group_name
142
  counter = 2
143
- # If the name is already used, append a counter until it's unique
144
  while unique_group_name in used_group_names:
145
  unique_group_name = f"{base_group_name} ({counter})"
146
  counter += 1
147
 
148
- used_group_names.add(unique_group_name) # Add the final unique name to the set
149
  json_schema.append({"group_name": unique_group_name, "properties": group_props})
150
  else:
151
- # Collect root properties to be processed later
152
  root_properties.append(extract_prop_metadata(current_value, field))
153
 
154
  # Process root properties, if any exist
@@ -161,8 +180,11 @@ class PropertySheet(Component):
161
  unique_root_label = f"{base_root_label} ({counter})"
162
  counter += 1
163
 
164
- # No need to add to used_group_names as it's the last one
165
- json_schema.insert(0, {"group_name": unique_root_label, "properties": root_properties})
 
 
 
166
 
167
  return json_schema
168
 
 
42
  label: str | None = None,
43
  root_label: str = "General",
44
  show_group_name_only_one: bool = True,
45
+ root_properties_first: bool = True,
46
  disable_accordion: bool = False,
47
  visible: bool = True,
48
  open: bool = True,
 
63
  label: The main label for the component, displayed in the accordion header.
64
  root_label: The label for the root group of properties.
65
  show_group_name_only_one: If True, only the group name is shown when there is a single group.
66
+ root_properties_first: If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.
67
  disable_accordion: If True, disables the accordion functionality.
68
  visible: If False, the component will be hidden.
69
  open: If False, the accordion will be collapsed by default.
 
88
  self.open = open
89
  self.root_label = root_label
90
  self.show_group_name_only_one = show_group_name_only_one
91
+ self.root_properties_first = root_properties_first
92
  self.disable_accordion = disable_accordion
93
 
94
  super().__init__(
 
135
  if is_nested_dataclass:
136
  group_obj = getattr(current_value, field.name)
137
  group_props = []
138
+ group_type = type(group_obj)
139
+ parent_dataclass = next((b for b in group_type.__bases__ if dataclasses.is_dataclass(b)), None)
140
+
141
+ reordered_fields = []
142
+ if parent_dataclass:
143
+ all_fields = dataclasses.fields(group_type)
144
+ parent_field_names = {f.name for f in dataclasses.fields(parent_dataclass)}
145
+
146
+ own_fields = [f for f in all_fields if f.name not in parent_field_names]
147
+ inherited_fields = [f for f in all_fields if f.name in parent_field_names]
148
+ reordered_fields = own_fields + inherited_fields
149
+ else:
150
+ reordered_fields = dataclasses.fields(group_type)
151
+
152
+ for group_field in reordered_fields:
153
+ metadata = extract_prop_metadata(group_obj, group_field)
154
+ if "interactive_if" in metadata and "." not in metadata["interactive_if"]["field"]:
155
+ relative_field_name = metadata["interactive_if"]["field"]
156
+ metadata["interactive_if"]["field"] = f"{field.name}.{relative_field_name}"
157
+
158
  metadata["name"] = f"{field.name}.{group_field.name}"
159
  group_props.append(metadata)
160
 
161
+ base_group_name = field.name.replace("_", " ").title()
162
  unique_group_name = base_group_name
163
  counter = 2
 
164
  while unique_group_name in used_group_names:
165
  unique_group_name = f"{base_group_name} ({counter})"
166
  counter += 1
167
 
168
+ used_group_names.add(unique_group_name)
169
  json_schema.append({"group_name": unique_group_name, "properties": group_props})
170
  else:
 
171
  root_properties.append(extract_prop_metadata(current_value, field))
172
 
173
  # Process root properties, if any exist
 
180
  unique_root_label = f"{base_root_label} ({counter})"
181
  counter += 1
182
 
183
+ root_group = {"group_name": unique_root_label, "properties": root_properties}
184
+ if self.root_properties_first:
185
+ json_schema.insert(0, root_group)
186
+ else:
187
+ json_schema.append(root_group)
188
 
189
  return json_schema
190
 
src/demo/app.py CHANGED
@@ -17,7 +17,7 @@ class ModelSettings:
17
  default="/path/to/default.safetensors",
18
  metadata={
19
  "label": "Custom Model Path",
20
- "interactive_if": {"field": "model.model_type", "value": "Custom"},
21
  },
22
  )
23
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
@@ -53,7 +53,7 @@ class SamplingSettings:
53
  "minimum": 0.0,
54
  "maximum": 1.0,
55
  "step": 0.01,
56
- "interactive_if": {"field": "sampling.enable_advanced", "value": True},
57
  },
58
  )
59
  temperature: float = field(
@@ -66,6 +66,7 @@ class SamplingSettings:
66
  "step": 0.1
67
  }
68
  )
 
69
  @dataclass
70
  class RenderConfig:
71
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
@@ -76,7 +77,6 @@ class RenderConfig:
76
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
77
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
78
 
79
-
80
  @dataclass
81
  class Lighting:
82
  sun_intensity: float = field(
@@ -187,7 +187,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
187
  height=550,
188
  visible=False,
189
  root_label="Generator",
190
- interactive=True
191
  )
192
  environment_sheet = PropertySheet(
193
  value=initial_env_config,
@@ -196,7 +196,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
196
  open=False,
197
  visible=False,
198
  root_label="General",
199
- interactive=True
 
200
  )
201
 
202
  def change_visibility(is_visible, render_cfg, env_cfg):
 
17
  default="/path/to/default.safetensors",
18
  metadata={
19
  "label": "Custom Model Path",
20
+ "interactive_if": {"field": "model_type", "value": "Custom"},
21
  },
22
  )
23
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
 
53
  "minimum": 0.0,
54
  "maximum": 1.0,
55
  "step": 0.01,
56
+ "interactive_if": {"field": "enable_advanced", "value": True},
57
  },
58
  )
59
  temperature: float = field(
 
66
  "step": 0.1
67
  }
68
  )
69
+
70
  @dataclass
71
  class RenderConfig:
72
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
 
77
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
78
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
79
 
 
80
  @dataclass
81
  class Lighting:
82
  sun_intensity: float = field(
 
187
  height=550,
188
  visible=False,
189
  root_label="Generator",
190
+ interactive=True
191
  )
192
  environment_sheet = PropertySheet(
193
  value=initial_env_config,
 
196
  open=False,
197
  visible=False,
198
  root_label="General",
199
+ interactive=True,
200
+ root_properties_first=False
201
  )
202
 
203
  def change_visibility(is_visible, render_cfg, env_cfg):
src/demo/space.py CHANGED
@@ -3,7 +3,7 @@ import gradio as gr
3
  from app import demo as app
4
  import os
5
 
6
- _docs = {'PropertySheet': {'description': 'A Gradio component that renders a dynamic UI from a Python dataclass instance.\nIt allows for nested settings and automatically infers input types.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Any][Any, None]', 'default': 'None', 'description': 'The initial dataclass instance to render.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The main label for the component, displayed in the accordion header.'}, 'root_label': {'type': 'str', 'default': '"General"', 'description': 'The label for the root group of properties.'}, 'show_group_name_only_one': {'type': 'bool', 'default': 'True', 'description': 'If True, only the group name is shown when there is a single group.'}, 'disable_accordion': {'type': 'bool', 'default': 'False', 'description': 'If True, disables the accordion functionality.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'open': {'type': 'bool', 'default': 'True', 'description': 'If False, the accordion will be collapsed by default.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component in its container.'}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': "The maximum height of the component's content area in pixels before scrolling."}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, wraps the component in a container with a background.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the DOM.'}}, 'postprocess': {'value': {'type': 'Any', 'description': 'The dataclass instance to process.'}}, 'preprocess': {'return': {'type': 'Any', 'description': 'A new, updated instance of the dataclass.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the PropertySheet changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'input': {'type': None, 'default': None, 'description': 'This listener is triggered when the user changes the value of the PropertySheet.'}, 'expand': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is expanded.'}, 'collapse': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is collapsed.'}, 'undo': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clicks the undo button in component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'PropertySheet': []}}}
7
 
8
  abs_path = os.path.join(os.path.dirname(__file__), "css.css")
9
 
@@ -57,7 +57,7 @@ class ModelSettings:
57
  default="/path/to/default.safetensors",
58
  metadata={
59
  "label": "Custom Model Path",
60
- "interactive_if": {"field": "model.model_type", "value": "Custom"},
61
  },
62
  )
63
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
@@ -93,7 +93,7 @@ class SamplingSettings:
93
  "minimum": 0.0,
94
  "maximum": 1.0,
95
  "step": 0.01,
96
- "interactive_if": {"field": "sampling.enable_advanced", "value": True},
97
  },
98
  )
99
  temperature: float = field(
@@ -106,6 +106,7 @@ class SamplingSettings:
106
  "step": 0.1
107
  }
108
  )
 
109
  @dataclass
110
  class RenderConfig:
111
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
@@ -116,7 +117,6 @@ class RenderConfig:
116
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
117
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
118
 
119
-
120
  @dataclass
121
  class Lighting:
122
  sun_intensity: float = field(
@@ -227,7 +227,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
227
  height=550,
228
  visible=False,
229
  root_label="Generator",
230
- interactive=True
231
  )
232
  environment_sheet = PropertySheet(
233
  value=initial_env_config,
@@ -236,7 +236,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
236
  open=False,
237
  visible=False,
238
  root_label="General",
239
- interactive=True
 
240
  )
241
 
242
  def change_visibility(is_visible, render_cfg, env_cfg):
 
3
  from app import demo as app
4
  import os
5
 
6
+ _docs = {'PropertySheet': {'description': 'A Gradio component that renders a dynamic UI from a Python dataclass instance.\nIt allows for nested settings and automatically infers input types.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Any][Any, None]', 'default': 'None', 'description': 'The initial dataclass instance to render.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The main label for the component, displayed in the accordion header.'}, 'root_label': {'type': 'str', 'default': '"General"', 'description': 'The label for the root group of properties.'}, 'show_group_name_only_one': {'type': 'bool', 'default': 'True', 'description': 'If True, only the group name is shown when there is a single group.'}, 'root_properties_first': {'type': 'bool', 'default': 'True', 'description': 'If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.'}, 'disable_accordion': {'type': 'bool', 'default': 'False', 'description': 'If True, disables the accordion functionality.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'open': {'type': 'bool', 'default': 'True', 'description': 'If False, the accordion will be collapsed by default.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component in its container.'}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': "The maximum height of the component's content area in pixels before scrolling."}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, wraps the component in a container with a background.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the DOM.'}}, 'postprocess': {'value': {'type': 'Any', 'description': 'The dataclass instance to process.'}}, 'preprocess': {'return': {'type': 'Any', 'description': 'A new, updated instance of the dataclass.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the PropertySheet changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'input': {'type': None, 'default': None, 'description': 'This listener is triggered when the user changes the value of the PropertySheet.'}, 'expand': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is expanded.'}, 'collapse': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is collapsed.'}, 'undo': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clicks the undo button in component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'PropertySheet': []}}}
7
 
8
  abs_path = os.path.join(os.path.dirname(__file__), "css.css")
9
 
 
57
  default="/path/to/default.safetensors",
58
  metadata={
59
  "label": "Custom Model Path",
60
+ "interactive_if": {"field": "model_type", "value": "Custom"},
61
  },
62
  )
63
  vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
 
93
  "minimum": 0.0,
94
  "maximum": 1.0,
95
  "step": 0.01,
96
+ "interactive_if": {"field": "enable_advanced", "value": True},
97
  },
98
  )
99
  temperature: float = field(
 
106
  "step": 0.1
107
  }
108
  )
109
+
110
  @dataclass
111
  class RenderConfig:
112
  randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
 
117
  model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
118
  sampling: SamplingSettings = field(default_factory=SamplingSettings)
119
 
 
120
  @dataclass
121
  class Lighting:
122
  sun_intensity: float = field(
 
227
  height=550,
228
  visible=False,
229
  root_label="Generator",
230
+ interactive=True
231
  )
232
  environment_sheet = PropertySheet(
233
  value=initial_env_config,
 
236
  open=False,
237
  visible=False,
238
  root_label="General",
239
+ interactive=True,
240
+ root_properties_first=False
241
  )
242
 
243
  def change_visibility(is_visible, render_cfg, env_cfg):
src/pyproject.toml CHANGED
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
8
 
9
  [project]
10
  name = "gradio_propertysheet"
11
- version = "0.0.8"
12
  description = "Property sheet"
13
  readme = "README.md"
14
  license = "apache-2.0"
 
8
 
9
  [project]
10
  name = "gradio_propertysheet"
11
+ version = "0.0.9"
12
  description = "Property sheet"
13
  readme = "README.md"
14
  license = "apache-2.0"