Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- README.md +129 -51
- app.py +260 -225
- space.py +71 -35
- src/README.md +129 -51
- src/assets/gradio_logo_white.png +0 -0
- src/backend/gradio_creditspanel/creditspanel.py +116 -148
- src/backend/gradio_creditspanel/templates/component/index.js +0 -0
- src/backend/gradio_creditspanel/templates/component/style.css +1 -1
- src/demo/app.py +67 -32
- src/demo/space.py +71 -35
- src/frontend/Index.svelte +13 -0
- src/frontend/shared/MatrixEffect.svelte +21 -0
- src/frontend/shared/ScrollEffect.svelte +25 -2
- src/frontend/shared/StarWarsEffect.svelte +22 -0
- src/pyproject.toml +1 -1
README.md
CHANGED
@@ -10,7 +10,8 @@ app_file: space.py
|
|
10 |
---
|
11 |
|
12 |
# `gradio_creditspanel`
|
13 |
-
<
|
|
|
14 |
|
15 |
Credits Panel for Gradio UI
|
16 |
|
@@ -43,7 +44,7 @@ def setup_demo_files():
|
|
43 |
with open("./assets/logo.webp", "w") as f:
|
44 |
f.write("Placeholder WebP logo")
|
45 |
|
46 |
-
# ---
|
47 |
credits_list = [
|
48 |
{"section_title": "Project Leadership"},
|
49 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
@@ -72,6 +73,8 @@ DEFAULT_SPEEDS = {
|
|
72 |
"starwars": 70.0,
|
73 |
"matrix": 40.0
|
74 |
}
|
|
|
|
|
75 |
|
76 |
def update_panel(
|
77 |
effect: str,
|
@@ -89,39 +92,52 @@ def update_panel(
|
|
89 |
logo_height: str | None,
|
90 |
scroll_background_color: str | None,
|
91 |
scroll_title_color: str | None,
|
|
|
92 |
scroll_name_color: str | None,
|
93 |
layout_style: str,
|
94 |
title_uppercase: bool,
|
95 |
name_uppercase: bool,
|
96 |
section_title_uppercase: bool,
|
97 |
-
swap_font_sizes: bool
|
|
|
|
|
98 |
) -> dict:
|
99 |
"""Callback function that updates all properties of the CreditsPanel component."""
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
127 |
"""Updates sliders to sensible defaults when the animation effect is changed."""
|
@@ -163,6 +179,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
163 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
164 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
gr.Markdown("### Intro Text")
|
167 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
168 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
@@ -182,19 +206,20 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
182 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
183 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
184 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
|
|
185 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
186 |
|
187 |
-
panel = CreditsPanel(
|
|
|
188 |
credits=credits_list,
|
189 |
licenses=license_paths,
|
190 |
effect="scroll",
|
191 |
-
height=500,
|
192 |
speed=DEFAULT_SPEEDS["scroll"],
|
193 |
base_font_size=1.5,
|
194 |
intro_title="Gradio",
|
195 |
intro_subtitle="The best UI framework",
|
196 |
sidebar_position="right",
|
197 |
-
logo_path=
|
198 |
show_logo=True,
|
199 |
show_licenses=True,
|
200 |
show_credits=True,
|
@@ -205,11 +230,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
205 |
scroll_background_color="#000000",
|
206 |
scroll_title_color="#FFFFFF",
|
207 |
scroll_name_color="#FFFFFF",
|
|
|
208 |
layout_style="stacked",
|
209 |
title_uppercase=False,
|
210 |
name_uppercase=False,
|
211 |
section_title_uppercase=True,
|
212 |
swap_font_sizes_on_two_column=False,
|
|
|
|
|
213 |
)
|
214 |
|
215 |
inputs = [
|
@@ -227,15 +255,23 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
227 |
logo_width_input,
|
228 |
logo_height_input,
|
229 |
scroll_background_color,
|
230 |
-
scroll_title_color,
|
|
|
231 |
scroll_name_color,
|
232 |
layout_style_radio,
|
233 |
title_uppercase_checkbox,
|
234 |
name_uppercase_checkbox,
|
235 |
section_title_uppercase_checkbox,
|
236 |
-
swap_sizes_checkbox
|
|
|
|
|
237 |
]
|
238 |
|
|
|
|
|
|
|
|
|
|
|
239 |
layout_style_radio.change(
|
240 |
fn=toggle_swap_checkbox_visibility,
|
241 |
inputs=layout_style_radio,
|
@@ -270,7 +306,9 @@ if __name__ == "__main__":
|
|
270 |
<td align="left" style="width: 25%;">
|
271 |
|
272 |
```python
|
273 |
-
Any
|
|
|
|
|
274 |
```
|
275 |
|
276 |
</td>
|
@@ -279,21 +317,11 @@ Any
|
|
279 |
</tr>
|
280 |
|
281 |
<tr>
|
282 |
-
<td align="left"><code>
|
283 |
<td align="left" style="width: 25%;">
|
284 |
|
285 |
```python
|
286 |
-
|
287 |
-
typing.List[typing.Dict[str, str]],
|
288 |
-
typing.Callable,
|
289 |
-
NoneType,
|
290 |
-
][
|
291 |
-
typing.List[typing.Dict[str, str]][
|
292 |
-
typing.Dict[str, str][str, str]
|
293 |
-
],
|
294 |
-
Callable,
|
295 |
-
None,
|
296 |
-
]
|
297 |
```
|
298 |
|
299 |
</td>
|
@@ -302,7 +330,7 @@ typing.Union[
|
|
302 |
</tr>
|
303 |
|
304 |
<tr>
|
305 |
-
<td align="left"><code>
|
306 |
<td align="left" style="width: 25%;">
|
307 |
|
308 |
```python
|
@@ -315,11 +343,21 @@ int | str | None
|
|
315 |
</tr>
|
316 |
|
317 |
<tr>
|
318 |
-
<td align="left"><code>
|
319 |
<td align="left" style="width: 25%;">
|
320 |
|
321 |
```python
|
322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
```
|
324 |
|
325 |
</td>
|
@@ -566,6 +604,19 @@ str | None
|
|
566 |
<td align="left">None</td>
|
567 |
</tr>
|
568 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
569 |
<tr>
|
570 |
<td align="left"><code>layout_style</code></td>
|
571 |
<td align="left" style="width: 25%;">
|
@@ -631,6 +682,32 @@ bool
|
|
631 |
<td align="left">None</td>
|
632 |
</tr>
|
633 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
634 |
<tr>
|
635 |
<td align="left"><code>label</code></td>
|
636 |
<td align="left" style="width: 25%;">
|
@@ -844,7 +921,6 @@ The impact on the users predict function varies depending on whether the compone
|
|
844 |
|
845 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
846 |
|
847 |
-
- **As output:** Is passed, dict[str, Any] | None: The input payload, returned unchanged.
|
848 |
|
849 |
|
850 |
```python
|
@@ -852,7 +928,9 @@ The code snippet below is accurate in cases where the component is used as both
|
|
852 |
value: typing.Optional[typing.Dict[str, typing.Any]][
|
853 |
typing.Dict[str, typing.Any][str, Any], None
|
854 |
]
|
855 |
-
) -> Any
|
|
|
|
|
856 |
return value
|
857 |
```
|
858 |
|
|
|
10 |
---
|
11 |
|
12 |
# `gradio_creditspanel`
|
13 |
+
<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_creditspanel"><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_creditspanel'>Component GitHub Code</a></span></p>
|
14 |
+
|
15 |
|
16 |
Credits Panel for Gradio UI
|
17 |
|
|
|
44 |
with open("./assets/logo.webp", "w") as f:
|
45 |
f.write("Placeholder WebP logo")
|
46 |
|
47 |
+
# --- Credits list with sections ---
|
48 |
credits_list = [
|
49 |
{"section_title": "Project Leadership"},
|
50 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
|
|
73 |
"starwars": 70.0,
|
74 |
"matrix": 40.0
|
75 |
}
|
76 |
+
SCROLL_LOGO_PATH = "./assets/gradio_logo_white.png"
|
77 |
+
LOGO_PATH="./assets/logo.webp"
|
78 |
|
79 |
def update_panel(
|
80 |
effect: str,
|
|
|
92 |
logo_height: str | None,
|
93 |
scroll_background_color: str | None,
|
94 |
scroll_title_color: str | None,
|
95 |
+
scroll_section_title_color: str | None,
|
96 |
scroll_name_color: str | None,
|
97 |
layout_style: str,
|
98 |
title_uppercase: bool,
|
99 |
name_uppercase: bool,
|
100 |
section_title_uppercase: bool,
|
101 |
+
swap_font_sizes: bool,
|
102 |
+
show_scroll_logo: bool,
|
103 |
+
scroll_logo_height: str | None
|
104 |
) -> dict:
|
105 |
"""Callback function that updates all properties of the CreditsPanel component."""
|
106 |
+
|
107 |
+
scroll_logo_path = SCROLL_LOGO_PATH if show_scroll_logo else None
|
108 |
+
|
109 |
+
if not scroll_logo_height:
|
110 |
+
scroll_logo_height = "120px"
|
111 |
+
|
112 |
+
return {
|
113 |
+
"credits": credits_list,
|
114 |
+
"licenses": license_paths,
|
115 |
+
"effect": effect,
|
116 |
+
"speed": speed,
|
117 |
+
"base_font_size": base_font_size,
|
118 |
+
"intro_title": intro_title,
|
119 |
+
"intro_subtitle": intro_subtitle,
|
120 |
+
"sidebar_position": sidebar_position,
|
121 |
+
"logo_path": LOGO_PATH,
|
122 |
+
"show_logo": show_logo,
|
123 |
+
"show_licenses": show_licenses,
|
124 |
+
"show_credits": show_credits,
|
125 |
+
"logo_position": logo_position,
|
126 |
+
"logo_sizing": logo_sizing,
|
127 |
+
"logo_width": logo_width,
|
128 |
+
"logo_height": logo_height,
|
129 |
+
"scroll_background_color": scroll_background_color,
|
130 |
+
"scroll_title_color": scroll_title_color,
|
131 |
+
"scroll_name_color": scroll_name_color,
|
132 |
+
"scroll_section_title_color": scroll_section_title_color,
|
133 |
+
"layout_style": layout_style,
|
134 |
+
"title_uppercase": title_uppercase,
|
135 |
+
"name_uppercase": name_uppercase,
|
136 |
+
"section_title_uppercase": section_title_uppercase,
|
137 |
+
"swap_font_sizes_on_two_column": swap_font_sizes,
|
138 |
+
"scroll_logo_path": scroll_logo_path,
|
139 |
+
"scroll_logo_height": scroll_logo_height,
|
140 |
+
}
|
141 |
|
142 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
143 |
"""Updates sliders to sensible defaults when the animation effect is changed."""
|
|
|
179 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
180 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
181 |
|
182 |
+
gr.Markdown("### Scrolling Logo")
|
183 |
+
show_scroll_logo_checkbox = gr.Checkbox(
|
184 |
+
label="Show Logo in Credits Roll",
|
185 |
+
value=True,
|
186 |
+
info="Toggles the logo above the intro text."
|
187 |
+
)
|
188 |
+
scroll_logo_height_input = gr.Textbox(label="Scrolling Logo Height", value="100px")
|
189 |
+
|
190 |
gr.Markdown("### Intro Text")
|
191 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
192 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
|
|
206 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
207 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
208 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
209 |
+
scroll_section_title_color = gr.ColorPicker(label="Section Title Color", value="#FFFFFF")
|
210 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
211 |
|
212 |
+
panel = CreditsPanel(
|
213 |
+
height=500,
|
214 |
credits=credits_list,
|
215 |
licenses=license_paths,
|
216 |
effect="scroll",
|
|
|
217 |
speed=DEFAULT_SPEEDS["scroll"],
|
218 |
base_font_size=1.5,
|
219 |
intro_title="Gradio",
|
220 |
intro_subtitle="The best UI framework",
|
221 |
sidebar_position="right",
|
222 |
+
logo_path=LOGO_PATH,
|
223 |
show_logo=True,
|
224 |
show_licenses=True,
|
225 |
show_credits=True,
|
|
|
230 |
scroll_background_color="#000000",
|
231 |
scroll_title_color="#FFFFFF",
|
232 |
scroll_name_color="#FFFFFF",
|
233 |
+
scroll_section_title_color="#FFFFFF",
|
234 |
layout_style="stacked",
|
235 |
title_uppercase=False,
|
236 |
name_uppercase=False,
|
237 |
section_title_uppercase=True,
|
238 |
swap_font_sizes_on_two_column=False,
|
239 |
+
scroll_logo_path=SCROLL_LOGO_PATH,
|
240 |
+
scroll_logo_height="100px",
|
241 |
)
|
242 |
|
243 |
inputs = [
|
|
|
255 |
logo_width_input,
|
256 |
logo_height_input,
|
257 |
scroll_background_color,
|
258 |
+
scroll_title_color,
|
259 |
+
scroll_section_title_color,
|
260 |
scroll_name_color,
|
261 |
layout_style_radio,
|
262 |
title_uppercase_checkbox,
|
263 |
name_uppercase_checkbox,
|
264 |
section_title_uppercase_checkbox,
|
265 |
+
swap_sizes_checkbox,
|
266 |
+
show_scroll_logo_checkbox,
|
267 |
+
scroll_logo_height_input
|
268 |
]
|
269 |
|
270 |
+
demo.load(
|
271 |
+
fn=update_panel,
|
272 |
+
inputs=inputs,
|
273 |
+
outputs=panel
|
274 |
+
)
|
275 |
layout_style_radio.change(
|
276 |
fn=toggle_swap_checkbox_visibility,
|
277 |
inputs=layout_style_radio,
|
|
|
306 |
<td align="left" style="width: 25%;">
|
307 |
|
308 |
```python
|
309 |
+
typing.Optional[typing.Dict[str, typing.Any]][
|
310 |
+
typing.Dict[str, typing.Any][str, Any], None
|
311 |
+
]
|
312 |
```
|
313 |
|
314 |
</td>
|
|
|
317 |
</tr>
|
318 |
|
319 |
<tr>
|
320 |
+
<td align="left"><code>height</code></td>
|
321 |
<td align="left" style="width: 25%;">
|
322 |
|
323 |
```python
|
324 |
+
int | str | None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
```
|
326 |
|
327 |
</td>
|
|
|
330 |
</tr>
|
331 |
|
332 |
<tr>
|
333 |
+
<td align="left"><code>width</code></td>
|
334 |
<td align="left" style="width: 25%;">
|
335 |
|
336 |
```python
|
|
|
343 |
</tr>
|
344 |
|
345 |
<tr>
|
346 |
+
<td align="left"><code>credits</code></td>
|
347 |
<td align="left" style="width: 25%;">
|
348 |
|
349 |
```python
|
350 |
+
typing.Union[
|
351 |
+
typing.List[typing.Dict[str, str]],
|
352 |
+
typing.Callable,
|
353 |
+
NoneType,
|
354 |
+
][
|
355 |
+
typing.List[typing.Dict[str, str]][
|
356 |
+
typing.Dict[str, str][str, str]
|
357 |
+
],
|
358 |
+
Callable,
|
359 |
+
None,
|
360 |
+
]
|
361 |
```
|
362 |
|
363 |
</td>
|
|
|
604 |
<td align="left">None</td>
|
605 |
</tr>
|
606 |
|
607 |
+
<tr>
|
608 |
+
<td align="left"><code>scroll_section_title_color</code></td>
|
609 |
+
<td align="left" style="width: 25%;">
|
610 |
+
|
611 |
+
```python
|
612 |
+
str | None
|
613 |
+
```
|
614 |
+
|
615 |
+
</td>
|
616 |
+
<td align="left"><code>None</code></td>
|
617 |
+
<td align="left">None</td>
|
618 |
+
</tr>
|
619 |
+
|
620 |
<tr>
|
621 |
<td align="left"><code>layout_style</code></td>
|
622 |
<td align="left" style="width: 25%;">
|
|
|
682 |
<td align="left">None</td>
|
683 |
</tr>
|
684 |
|
685 |
+
<tr>
|
686 |
+
<td align="left"><code>scroll_logo_path</code></td>
|
687 |
+
<td align="left" style="width: 25%;">
|
688 |
+
|
689 |
+
```python
|
690 |
+
str | pathlib.Path | None
|
691 |
+
```
|
692 |
+
|
693 |
+
</td>
|
694 |
+
<td align="left"><code>None</code></td>
|
695 |
+
<td align="left">None</td>
|
696 |
+
</tr>
|
697 |
+
|
698 |
+
<tr>
|
699 |
+
<td align="left"><code>scroll_logo_height</code></td>
|
700 |
+
<td align="left" style="width: 25%;">
|
701 |
+
|
702 |
+
```python
|
703 |
+
str
|
704 |
+
```
|
705 |
+
|
706 |
+
</td>
|
707 |
+
<td align="left"><code>"120px"</code></td>
|
708 |
+
<td align="left">None</td>
|
709 |
+
</tr>
|
710 |
+
|
711 |
<tr>
|
712 |
<td align="left"><code>label</code></td>
|
713 |
<td align="left" style="width: 25%;">
|
|
|
921 |
|
922 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
923 |
|
|
|
924 |
|
925 |
|
926 |
```python
|
|
|
928 |
value: typing.Optional[typing.Dict[str, typing.Any]][
|
929 |
typing.Dict[str, typing.Any][str, Any], None
|
930 |
]
|
931 |
+
) -> typing.Optional[typing.Dict[str, typing.Any]][
|
932 |
+
typing.Dict[str, typing.Any][str, Any], None
|
933 |
+
]:
|
934 |
return value
|
935 |
```
|
936 |
|
app.py
CHANGED
@@ -1,226 +1,261 @@
|
|
1 |
-
# app.py
|
2 |
-
|
3 |
-
import gradio as gr
|
4 |
-
from gradio_creditspanel import CreditsPanel
|
5 |
-
import os
|
6 |
-
|
7 |
-
def setup_demo_files():
|
8 |
-
"""Creates necessary directories and dummy files for the demo."""
|
9 |
-
os.makedirs("
|
10 |
-
if not os.path.exists("
|
11 |
-
with open("
|
12 |
-
f.write("Apache License\nVersion 2.0, January 2004...")
|
13 |
-
if not os.path.exists("
|
14 |
-
with open("
|
15 |
-
f.write("MIT License\nCopyright (c) 2025 Author...")
|
16 |
-
os.makedirs("
|
17 |
-
if not os.path.exists("
|
18 |
-
with open("
|
19 |
-
f.write("Placeholder WebP logo")
|
20 |
-
|
21 |
-
# --- Credits list with sections ---
|
22 |
-
credits_list = [
|
23 |
-
{"section_title": "Project Leadership"},
|
24 |
-
{"title": "Project Manager", "name": "Emma Thompson"},
|
25 |
-
{"title": "Scrum Master", "name": "Ava Rodriguez"},
|
26 |
-
|
27 |
-
{"section_title": "Development Team"},
|
28 |
-
{"title": "Lead Developer", "name": "John Doe"},
|
29 |
-
{"title": "Senior Backend Engineer", "name": "Michael Chen"},
|
30 |
-
{"title": "Frontend Developer", "name": "Sarah Johnson"},
|
31 |
-
{"title": "UI/UX Designer", "name": "Jane Smith"},
|
32 |
-
{"title": "Database Architect", "name": "Alex Ray"},
|
33 |
-
|
34 |
-
{"section_title": "Quality & Operations"},
|
35 |
-
{"title": "DevOps Engineer", "name": "Liam Patel"},
|
36 |
-
{"title": "Quality Assurance Lead", "name": "Sam Wilson"},
|
37 |
-
{"title": "Test Automation Engineer", "name": "Olivia Brown"},
|
38 |
-
]
|
39 |
-
|
40 |
-
license_paths = {
|
41 |
-
"Gradio Framework": "
|
42 |
-
"This Component": "
|
43 |
-
}
|
44 |
-
|
45 |
-
DEFAULT_SPEEDS = {
|
46 |
-
"scroll": 40.0,
|
47 |
-
"starwars": 70.0,
|
48 |
-
"matrix": 40.0
|
49 |
-
}
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
gr.
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
scroll_background_color,
|
205 |
-
scroll_title_color,
|
206 |
-
scroll_name_color,
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
demo.launch()
|
|
|
1 |
+
# app.py
|
2 |
+
|
3 |
+
import gradio as gr
|
4 |
+
from gradio_creditspanel import CreditsPanel
|
5 |
+
import os
|
6 |
+
|
7 |
+
def setup_demo_files():
|
8 |
+
"""Creates necessary directories and dummy files for the demo."""
|
9 |
+
os.makedirs("LICENSES", exist_ok=True)
|
10 |
+
if not os.path.exists("LICENSES/Apache.txt"):
|
11 |
+
with open("LICENSES/Apache.txt", "w") as f:
|
12 |
+
f.write("Apache License\nVersion 2.0, January 2004...")
|
13 |
+
if not os.path.exists("LICENSES/MIT.txt"):
|
14 |
+
with open("LICENSES/MIT.txt", "w") as f:
|
15 |
+
f.write("MIT License\nCopyright (c) 2025 Author...")
|
16 |
+
os.makedirs("assets", exist_ok=True)
|
17 |
+
if not os.path.exists("./assets/logo.webp"):
|
18 |
+
with open("./assets/logo.webp", "w") as f:
|
19 |
+
f.write("Placeholder WebP logo")
|
20 |
+
|
21 |
+
# --- Credits list with sections ---
|
22 |
+
credits_list = [
|
23 |
+
{"section_title": "Project Leadership"},
|
24 |
+
{"title": "Project Manager", "name": "Emma Thompson"},
|
25 |
+
{"title": "Scrum Master", "name": "Ava Rodriguez"},
|
26 |
+
|
27 |
+
{"section_title": "Development Team"},
|
28 |
+
{"title": "Lead Developer", "name": "John Doe"},
|
29 |
+
{"title": "Senior Backend Engineer", "name": "Michael Chen"},
|
30 |
+
{"title": "Frontend Developer", "name": "Sarah Johnson"},
|
31 |
+
{"title": "UI/UX Designer", "name": "Jane Smith"},
|
32 |
+
{"title": "Database Architect", "name": "Alex Ray"},
|
33 |
+
|
34 |
+
{"section_title": "Quality & Operations"},
|
35 |
+
{"title": "DevOps Engineer", "name": "Liam Patel"},
|
36 |
+
{"title": "Quality Assurance Lead", "name": "Sam Wilson"},
|
37 |
+
{"title": "Test Automation Engineer", "name": "Olivia Brown"},
|
38 |
+
]
|
39 |
+
|
40 |
+
license_paths = {
|
41 |
+
"Gradio Framework": "./LICENSES/Apache.txt",
|
42 |
+
"This Component": "./LICENSES/MIT.txt"
|
43 |
+
}
|
44 |
+
|
45 |
+
DEFAULT_SPEEDS = {
|
46 |
+
"scroll": 40.0,
|
47 |
+
"starwars": 70.0,
|
48 |
+
"matrix": 40.0
|
49 |
+
}
|
50 |
+
SCROLL_LOGO_PATH = "./assets/gradio_logo_white.png"
|
51 |
+
LOGO_PATH="./assets/logo.webp"
|
52 |
+
|
53 |
+
def update_panel(
|
54 |
+
effect: str,
|
55 |
+
speed: float,
|
56 |
+
base_font_size: float,
|
57 |
+
intro_title: str,
|
58 |
+
intro_subtitle: str,
|
59 |
+
sidebar_position: str,
|
60 |
+
show_logo: bool,
|
61 |
+
show_licenses: bool,
|
62 |
+
show_credits: bool,
|
63 |
+
logo_position: str,
|
64 |
+
logo_sizing: str,
|
65 |
+
logo_width: str | None,
|
66 |
+
logo_height: str | None,
|
67 |
+
scroll_background_color: str | None,
|
68 |
+
scroll_title_color: str | None,
|
69 |
+
scroll_section_title_color: str | None,
|
70 |
+
scroll_name_color: str | None,
|
71 |
+
layout_style: str,
|
72 |
+
title_uppercase: bool,
|
73 |
+
name_uppercase: bool,
|
74 |
+
section_title_uppercase: bool,
|
75 |
+
swap_font_sizes: bool,
|
76 |
+
show_scroll_logo: bool,
|
77 |
+
scroll_logo_height: str | None
|
78 |
+
) -> dict:
|
79 |
+
"""Callback function that updates all properties of the CreditsPanel component."""
|
80 |
+
|
81 |
+
scroll_logo_path = SCROLL_LOGO_PATH if show_scroll_logo else None
|
82 |
+
|
83 |
+
if not scroll_logo_height:
|
84 |
+
scroll_logo_height = "120px"
|
85 |
+
|
86 |
+
return {
|
87 |
+
"credits": credits_list,
|
88 |
+
"licenses": license_paths,
|
89 |
+
"effect": effect,
|
90 |
+
"speed": speed,
|
91 |
+
"base_font_size": base_font_size,
|
92 |
+
"intro_title": intro_title,
|
93 |
+
"intro_subtitle": intro_subtitle,
|
94 |
+
"sidebar_position": sidebar_position,
|
95 |
+
"logo_path": LOGO_PATH,
|
96 |
+
"show_logo": show_logo,
|
97 |
+
"show_licenses": show_licenses,
|
98 |
+
"show_credits": show_credits,
|
99 |
+
"logo_position": logo_position,
|
100 |
+
"logo_sizing": logo_sizing,
|
101 |
+
"logo_width": logo_width,
|
102 |
+
"logo_height": logo_height,
|
103 |
+
"scroll_background_color": scroll_background_color,
|
104 |
+
"scroll_title_color": scroll_title_color,
|
105 |
+
"scroll_name_color": scroll_name_color,
|
106 |
+
"scroll_section_title_color": scroll_section_title_color,
|
107 |
+
"layout_style": layout_style,
|
108 |
+
"title_uppercase": title_uppercase,
|
109 |
+
"name_uppercase": name_uppercase,
|
110 |
+
"section_title_uppercase": section_title_uppercase,
|
111 |
+
"swap_font_sizes_on_two_column": swap_font_sizes,
|
112 |
+
"scroll_logo_path": scroll_logo_path,
|
113 |
+
"scroll_logo_height": scroll_logo_height,
|
114 |
+
}
|
115 |
+
|
116 |
+
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
117 |
+
"""Updates sliders to sensible defaults when the animation effect is changed."""
|
118 |
+
font_size = 1.5
|
119 |
+
if effect == "starwars":
|
120 |
+
font_size = 3.8
|
121 |
+
speed = DEFAULT_SPEEDS.get(effect, 40.0)
|
122 |
+
return speed, font_size
|
123 |
+
|
124 |
+
def toggle_swap_checkbox_visibility(layout: str) -> dict:
|
125 |
+
"""Show the swap checkbox only for the two-column layout."""
|
126 |
+
return gr.update(visible=(layout == 'two-column'))
|
127 |
+
|
128 |
+
with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
129 |
+
gr.Markdown(
|
130 |
+
"""
|
131 |
+
# Interactive CreditsPanel Demo
|
132 |
+
Use the sidebar controls to customize the `CreditsPanel` component in real-time.
|
133 |
+
"""
|
134 |
+
)
|
135 |
+
|
136 |
+
with gr.Sidebar(position="right"):
|
137 |
+
gr.Markdown("### Effects Settings")
|
138 |
+
effect_radio = gr.Radio(["scroll", "starwars", "matrix"], label="Animation Effect", value="scroll")
|
139 |
+
speed_slider = gr.Slider(minimum=5.0, maximum=100.0, step=1.0, value=DEFAULT_SPEEDS["scroll"], label="Animation Speed")
|
140 |
+
font_size_slider = gr.Slider(minimum=1.0, maximum=10.0, step=0.1, value=1.5, label="Base Font Size")
|
141 |
+
|
142 |
+
gr.Markdown("### Credits Layout Settings")
|
143 |
+
layout_style_radio = gr.Radio(
|
144 |
+
["stacked", "two-column"], label="Layout Style", value="stacked",
|
145 |
+
info="How to display titles and names."
|
146 |
+
)
|
147 |
+
swap_sizes_checkbox = gr.Checkbox(
|
148 |
+
label="Swap Title/Name Font Sizes", value=False,
|
149 |
+
info="Emphasize name over title in two-column layout.",
|
150 |
+
visible=False
|
151 |
+
)
|
152 |
+
title_uppercase_checkbox = gr.Checkbox(label="Title Uppercase", value=False)
|
153 |
+
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
154 |
+
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
155 |
+
|
156 |
+
gr.Markdown("### Scrolling Logo")
|
157 |
+
show_scroll_logo_checkbox = gr.Checkbox(
|
158 |
+
label="Show Logo in Credits Roll",
|
159 |
+
value=True,
|
160 |
+
info="Toggles the logo above the intro text."
|
161 |
+
)
|
162 |
+
scroll_logo_height_input = gr.Textbox(label="Scrolling Logo Height", value="100px")
|
163 |
+
|
164 |
+
gr.Markdown("### Intro Text")
|
165 |
+
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
166 |
+
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
167 |
+
|
168 |
+
gr.Markdown("### Layout & Visibility")
|
169 |
+
sidebar_position_radio = gr.Radio(["right", "bottom"], label="Sidebar Position", value="right")
|
170 |
+
show_logo_checkbox = gr.Checkbox(label="Show Logo", value=True)
|
171 |
+
show_licenses_checkbox = gr.Checkbox(label="Show Licenses", value=True)
|
172 |
+
show_credits_checkbox = gr.Checkbox(label="Show Credits", value=True)
|
173 |
+
|
174 |
+
gr.Markdown("### Logo Customization")
|
175 |
+
logo_position_radio = gr.Radio(["left", "center", "right"], label="Logo Position", value="center")
|
176 |
+
logo_sizing_radio = gr.Radio(["stretch", "crop", "resize"], label="Logo Sizing", value="resize")
|
177 |
+
logo_width_input = gr.Textbox(label="Logo Width", value="200px")
|
178 |
+
logo_height_input = gr.Textbox(label="Logo Height", value="100px")
|
179 |
+
|
180 |
+
gr.Markdown("### Color Settings (Scroll Effect)")
|
181 |
+
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
182 |
+
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
183 |
+
scroll_section_title_color = gr.ColorPicker(label="Section Title Color", value="#FFFFFF")
|
184 |
+
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
185 |
+
|
186 |
+
panel = CreditsPanel(
|
187 |
+
height=500,
|
188 |
+
credits=credits_list,
|
189 |
+
licenses=license_paths,
|
190 |
+
effect="scroll",
|
191 |
+
speed=DEFAULT_SPEEDS["scroll"],
|
192 |
+
base_font_size=1.5,
|
193 |
+
intro_title="Gradio",
|
194 |
+
intro_subtitle="The best UI framework",
|
195 |
+
sidebar_position="right",
|
196 |
+
logo_path=LOGO_PATH,
|
197 |
+
show_logo=True,
|
198 |
+
show_licenses=True,
|
199 |
+
show_credits=True,
|
200 |
+
logo_position="center",
|
201 |
+
logo_sizing="resize",
|
202 |
+
logo_width="200px",
|
203 |
+
logo_height="100px",
|
204 |
+
scroll_background_color="#000000",
|
205 |
+
scroll_title_color="#FFFFFF",
|
206 |
+
scroll_name_color="#FFFFFF",
|
207 |
+
scroll_section_title_color="#FFFFFF",
|
208 |
+
layout_style="stacked",
|
209 |
+
title_uppercase=False,
|
210 |
+
name_uppercase=False,
|
211 |
+
section_title_uppercase=True,
|
212 |
+
swap_font_sizes_on_two_column=False,
|
213 |
+
scroll_logo_path=SCROLL_LOGO_PATH,
|
214 |
+
scroll_logo_height="100px",
|
215 |
+
)
|
216 |
+
|
217 |
+
inputs = [
|
218 |
+
effect_radio,
|
219 |
+
speed_slider,
|
220 |
+
font_size_slider,
|
221 |
+
intro_title_input,
|
222 |
+
intro_subtitle_input,
|
223 |
+
sidebar_position_radio,
|
224 |
+
show_logo_checkbox,
|
225 |
+
show_licenses_checkbox,
|
226 |
+
show_credits_checkbox,
|
227 |
+
logo_position_radio,
|
228 |
+
logo_sizing_radio,
|
229 |
+
logo_width_input,
|
230 |
+
logo_height_input,
|
231 |
+
scroll_background_color,
|
232 |
+
scroll_title_color,
|
233 |
+
scroll_section_title_color,
|
234 |
+
scroll_name_color,
|
235 |
+
layout_style_radio,
|
236 |
+
title_uppercase_checkbox,
|
237 |
+
name_uppercase_checkbox,
|
238 |
+
section_title_uppercase_checkbox,
|
239 |
+
swap_sizes_checkbox,
|
240 |
+
show_scroll_logo_checkbox,
|
241 |
+
scroll_logo_height_input
|
242 |
+
]
|
243 |
+
|
244 |
+
demo.load(
|
245 |
+
fn=update_panel,
|
246 |
+
inputs=inputs,
|
247 |
+
outputs=panel
|
248 |
+
)
|
249 |
+
layout_style_radio.change(
|
250 |
+
fn=toggle_swap_checkbox_visibility,
|
251 |
+
inputs=layout_style_radio,
|
252 |
+
outputs=swap_sizes_checkbox
|
253 |
+
)
|
254 |
+
effect_radio.change(fn=update_ui_on_effect_change, inputs=effect_radio, outputs=[speed_slider, font_size_slider])
|
255 |
+
|
256 |
+
for input_component in inputs:
|
257 |
+
input_component.change(fn=update_panel, inputs=inputs, outputs=panel)
|
258 |
+
|
259 |
+
if __name__ == "__main__":
|
260 |
+
setup_demo_files()
|
261 |
demo.launch()
|
space.py
CHANGED
@@ -3,7 +3,7 @@ import gradio as gr
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
-
_docs = {'CreditsPanel': {'description': 'A Gradio component for displaying credits with customizable visual effects, such as scrolling or Star Wars-style animations.\
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
@@ -58,7 +58,7 @@ def setup_demo_files():
|
|
58 |
with open("./assets/logo.webp", "w") as f:
|
59 |
f.write("Placeholder WebP logo")
|
60 |
|
61 |
-
# ---
|
62 |
credits_list = [
|
63 |
{"section_title": "Project Leadership"},
|
64 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
@@ -87,6 +87,8 @@ DEFAULT_SPEEDS = {
|
|
87 |
"starwars": 70.0,
|
88 |
"matrix": 40.0
|
89 |
}
|
|
|
|
|
90 |
|
91 |
def update_panel(
|
92 |
effect: str,
|
@@ -104,39 +106,52 @@ def update_panel(
|
|
104 |
logo_height: str | None,
|
105 |
scroll_background_color: str | None,
|
106 |
scroll_title_color: str | None,
|
|
|
107 |
scroll_name_color: str | None,
|
108 |
layout_style: str,
|
109 |
title_uppercase: bool,
|
110 |
name_uppercase: bool,
|
111 |
section_title_uppercase: bool,
|
112 |
-
swap_font_sizes: bool
|
|
|
|
|
113 |
) -> dict:
|
114 |
\"\"\"Callback function that updates all properties of the CreditsPanel component.\"\"\"
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
142 |
\"\"\"Updates sliders to sensible defaults when the animation effect is changed.\"\"\"
|
@@ -178,6 +193,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
178 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
179 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
gr.Markdown("### Intro Text")
|
182 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
183 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
@@ -197,19 +220,20 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
197 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
198 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
199 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
|
|
200 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
201 |
|
202 |
-
panel = CreditsPanel(
|
|
|
203 |
credits=credits_list,
|
204 |
licenses=license_paths,
|
205 |
effect="scroll",
|
206 |
-
height=500,
|
207 |
speed=DEFAULT_SPEEDS["scroll"],
|
208 |
base_font_size=1.5,
|
209 |
intro_title="Gradio",
|
210 |
intro_subtitle="The best UI framework",
|
211 |
sidebar_position="right",
|
212 |
-
logo_path=
|
213 |
show_logo=True,
|
214 |
show_licenses=True,
|
215 |
show_credits=True,
|
@@ -220,11 +244,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
220 |
scroll_background_color="#000000",
|
221 |
scroll_title_color="#FFFFFF",
|
222 |
scroll_name_color="#FFFFFF",
|
|
|
223 |
layout_style="stacked",
|
224 |
title_uppercase=False,
|
225 |
name_uppercase=False,
|
226 |
section_title_uppercase=True,
|
227 |
swap_font_sizes_on_two_column=False,
|
|
|
|
|
228 |
)
|
229 |
|
230 |
inputs = [
|
@@ -242,15 +269,23 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
242 |
logo_width_input,
|
243 |
logo_height_input,
|
244 |
scroll_background_color,
|
245 |
-
scroll_title_color,
|
|
|
246 |
scroll_name_color,
|
247 |
layout_style_radio,
|
248 |
title_uppercase_checkbox,
|
249 |
name_uppercase_checkbox,
|
250 |
section_title_uppercase_checkbox,
|
251 |
-
swap_sizes_checkbox
|
|
|
|
|
252 |
]
|
253 |
|
|
|
|
|
|
|
|
|
|
|
254 |
layout_style_radio.change(
|
255 |
fn=toggle_swap_checkbox_visibility,
|
256 |
inputs=layout_style_radio,
|
@@ -294,7 +329,6 @@ The impact on the users predict function varies depending on whether the compone
|
|
294 |
|
295 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
296 |
|
297 |
-
- **As input:** Is passed, dict[str, Any] | None: The input payload, returned unchanged.
|
298 |
|
299 |
|
300 |
```python
|
@@ -302,7 +336,9 @@ def predict(
|
|
302 |
value: typing.Optional[typing.Dict[str, typing.Any]][
|
303 |
typing.Dict[str, typing.Any][str, Any], None
|
304 |
]
|
305 |
-
) -> Any
|
|
|
|
|
306 |
return value
|
307 |
```
|
308 |
""", elem_classes=["md-custom", "CreditsPanel-user-fn"], header_links=True)
|
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
+
_docs = {'CreditsPanel': {'description': 'A Gradio component for displaying credits with customizable visual effects, such as scrolling or Star Wars-style animations.\nThis component is configured via a single dictionary `value` that holds all settings.\nIt supports displaying a logo, licenses, sections, and various text styling options.\n\n EVENTS (list): Supported events for the component, currently only `change`.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Dict[str, typing.Any]][\n typing.Dict[str, typing.Any][str, Any], None\n]', 'default': 'None', 'description': None}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': None}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': None}, 'credits': {'type': 'typing.Union[\n typing.List[typing.Dict[str, str]],\n typing.Callable,\n NoneType,\n][\n typing.List[typing.Dict[str, str]][\n typing.Dict[str, str][str, str]\n ],\n Callable,\n None,\n]', 'default': 'None', 'description': None}, 'licenses': {'type': 'typing.Optional[typing.Dict[str, str | pathlib.Path]][\n typing.Dict[str, str | pathlib.Path][\n str, str | pathlib.Path\n ],\n None,\n]', 'default': 'None', 'description': None}, 'effect': {'type': '"scroll" | "starwars" | "matrix"', 'default': '"scroll"', 'description': None}, 'speed': {'type': 'float', 'default': '40.0', 'description': None}, 'base_font_size': {'type': 'float', 'default': '1.5', 'description': None}, 'intro_title': {'type': 'str | None', 'default': 'None', 'description': None}, 'intro_subtitle': {'type': 'str | None', 'default': 'None', 'description': None}, 'sidebar_position': {'type': '"right" | "bottom"', 'default': '"right"', 'description': None}, 'logo_path': {'type': 'str | pathlib.Path | None', 'default': 'None', 'description': None}, 'show_logo': {'type': 'bool', 'default': 'True', 'description': None}, 'show_licenses': {'type': 'bool', 'default': 'True', 'description': None}, 'show_credits': {'type': 'bool', 'default': 'True', 'description': None}, 'logo_position': {'type': '"center" | "left" | "right"', 'default': '"center"', 'description': None}, 'logo_sizing': {'type': '"stretch" | "crop" | "resize"', 'default': '"resize"', 'description': None}, 'logo_width': {'type': 'int | str | None', 'default': 'None', 'description': None}, 'logo_height': {'type': 'int | str | None', 'default': 'None', 'description': None}, 'scroll_background_color': {'type': 'str | None', 'default': 'None', 'description': None}, 'scroll_title_color': {'type': 'str | None', 'default': 'None', 'description': None}, 'scroll_name_color': {'type': 'str | None', 'default': 'None', 'description': None}, 'scroll_section_title_color': {'type': 'str | None', 'default': 'None', 'description': None}, 'layout_style': {'type': '"stacked" | "two-column"', 'default': '"stacked"', 'description': None}, 'title_uppercase': {'type': 'bool', 'default': 'False', 'description': None}, 'name_uppercase': {'type': 'bool', 'default': 'False', 'description': None}, 'section_title_uppercase': {'type': 'bool', 'default': 'True', 'description': None}, 'swap_font_sizes_on_two_column': {'type': 'bool', 'default': 'False', 'description': None}, 'scroll_logo_path': {'type': 'str | pathlib.Path | None', 'default': 'None', 'description': None}, 'scroll_logo_height': {'type': 'str', 'default': '"120px"', 'description': None}, 'label': {'type': 'str | gradio.i18n.I18nData | None', 'default': 'None', 'description': None}, 'every': {'type': 'float | None', 'default': 'None', 'description': None}, 'inputs': {'type': 'typing.Union[\n gradio.components.base.Component,\n typing.Sequence[gradio.components.base.Component],\n set[gradio.components.base.Component],\n NoneType,\n][\n gradio.components.base.Component,\n typing.Sequence[gradio.components.base.Component][\n gradio.components.base.Component\n ],\n set[gradio.components.base.Component],\n None,\n]', 'default': 'None', 'description': None}, 'show_label': {'type': 'bool', 'default': 'False', 'description': None}, 'container': {'type': 'bool', 'default': 'True', 'description': None}, 'scale': {'type': 'int | None', 'default': 'None', 'description': None}, 'min_width': {'type': 'int', 'default': '160', 'description': None}, 'interactive': {'type': 'bool | None', 'default': 'None', 'description': None}, 'visible': {'type': 'bool', 'default': 'True', 'description': None}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': None}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': None}, 'render': {'type': 'bool', 'default': 'True', 'description': None}, 'key': {'type': 'int | str | tuple[int | str, Ellipsis] | None', 'default': 'None', 'description': None}, 'preserved_by_key': {'type': 'list[str] | str | None', 'default': '"value"', 'description': None}}, 'postprocess': {'value': {'type': 'typing.Optional[typing.Dict[str, typing.Any]][\n typing.Dict[str, typing.Any][str, Any], None\n]', 'description': None}}, 'preprocess': {'return': {'type': 'typing.Optional[typing.Dict[str, typing.Any]][\n typing.Dict[str, typing.Any][str, Any], None\n]', 'description': None}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the CreditsPanel 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.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'CreditsPanel': []}}}
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
|
|
58 |
with open("./assets/logo.webp", "w") as f:
|
59 |
f.write("Placeholder WebP logo")
|
60 |
|
61 |
+
# --- Credits list with sections ---
|
62 |
credits_list = [
|
63 |
{"section_title": "Project Leadership"},
|
64 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
|
|
87 |
"starwars": 70.0,
|
88 |
"matrix": 40.0
|
89 |
}
|
90 |
+
SCROLL_LOGO_PATH = "./assets/gradio_logo_white.png"
|
91 |
+
LOGO_PATH="./assets/logo.webp"
|
92 |
|
93 |
def update_panel(
|
94 |
effect: str,
|
|
|
106 |
logo_height: str | None,
|
107 |
scroll_background_color: str | None,
|
108 |
scroll_title_color: str | None,
|
109 |
+
scroll_section_title_color: str | None,
|
110 |
scroll_name_color: str | None,
|
111 |
layout_style: str,
|
112 |
title_uppercase: bool,
|
113 |
name_uppercase: bool,
|
114 |
section_title_uppercase: bool,
|
115 |
+
swap_font_sizes: bool,
|
116 |
+
show_scroll_logo: bool,
|
117 |
+
scroll_logo_height: str | None
|
118 |
) -> dict:
|
119 |
\"\"\"Callback function that updates all properties of the CreditsPanel component.\"\"\"
|
120 |
+
|
121 |
+
scroll_logo_path = SCROLL_LOGO_PATH if show_scroll_logo else None
|
122 |
+
|
123 |
+
if not scroll_logo_height:
|
124 |
+
scroll_logo_height = "120px"
|
125 |
+
|
126 |
+
return {
|
127 |
+
"credits": credits_list,
|
128 |
+
"licenses": license_paths,
|
129 |
+
"effect": effect,
|
130 |
+
"speed": speed,
|
131 |
+
"base_font_size": base_font_size,
|
132 |
+
"intro_title": intro_title,
|
133 |
+
"intro_subtitle": intro_subtitle,
|
134 |
+
"sidebar_position": sidebar_position,
|
135 |
+
"logo_path": LOGO_PATH,
|
136 |
+
"show_logo": show_logo,
|
137 |
+
"show_licenses": show_licenses,
|
138 |
+
"show_credits": show_credits,
|
139 |
+
"logo_position": logo_position,
|
140 |
+
"logo_sizing": logo_sizing,
|
141 |
+
"logo_width": logo_width,
|
142 |
+
"logo_height": logo_height,
|
143 |
+
"scroll_background_color": scroll_background_color,
|
144 |
+
"scroll_title_color": scroll_title_color,
|
145 |
+
"scroll_name_color": scroll_name_color,
|
146 |
+
"scroll_section_title_color": scroll_section_title_color,
|
147 |
+
"layout_style": layout_style,
|
148 |
+
"title_uppercase": title_uppercase,
|
149 |
+
"name_uppercase": name_uppercase,
|
150 |
+
"section_title_uppercase": section_title_uppercase,
|
151 |
+
"swap_font_sizes_on_two_column": swap_font_sizes,
|
152 |
+
"scroll_logo_path": scroll_logo_path,
|
153 |
+
"scroll_logo_height": scroll_logo_height,
|
154 |
+
}
|
155 |
|
156 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
157 |
\"\"\"Updates sliders to sensible defaults when the animation effect is changed.\"\"\"
|
|
|
193 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
194 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
195 |
|
196 |
+
gr.Markdown("### Scrolling Logo")
|
197 |
+
show_scroll_logo_checkbox = gr.Checkbox(
|
198 |
+
label="Show Logo in Credits Roll",
|
199 |
+
value=True,
|
200 |
+
info="Toggles the logo above the intro text."
|
201 |
+
)
|
202 |
+
scroll_logo_height_input = gr.Textbox(label="Scrolling Logo Height", value="100px")
|
203 |
+
|
204 |
gr.Markdown("### Intro Text")
|
205 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
206 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
|
|
220 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
221 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
222 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
223 |
+
scroll_section_title_color = gr.ColorPicker(label="Section Title Color", value="#FFFFFF")
|
224 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
225 |
|
226 |
+
panel = CreditsPanel(
|
227 |
+
height=500,
|
228 |
credits=credits_list,
|
229 |
licenses=license_paths,
|
230 |
effect="scroll",
|
|
|
231 |
speed=DEFAULT_SPEEDS["scroll"],
|
232 |
base_font_size=1.5,
|
233 |
intro_title="Gradio",
|
234 |
intro_subtitle="The best UI framework",
|
235 |
sidebar_position="right",
|
236 |
+
logo_path=LOGO_PATH,
|
237 |
show_logo=True,
|
238 |
show_licenses=True,
|
239 |
show_credits=True,
|
|
|
244 |
scroll_background_color="#000000",
|
245 |
scroll_title_color="#FFFFFF",
|
246 |
scroll_name_color="#FFFFFF",
|
247 |
+
scroll_section_title_color="#FFFFFF",
|
248 |
layout_style="stacked",
|
249 |
title_uppercase=False,
|
250 |
name_uppercase=False,
|
251 |
section_title_uppercase=True,
|
252 |
swap_font_sizes_on_two_column=False,
|
253 |
+
scroll_logo_path=SCROLL_LOGO_PATH,
|
254 |
+
scroll_logo_height="100px",
|
255 |
)
|
256 |
|
257 |
inputs = [
|
|
|
269 |
logo_width_input,
|
270 |
logo_height_input,
|
271 |
scroll_background_color,
|
272 |
+
scroll_title_color,
|
273 |
+
scroll_section_title_color,
|
274 |
scroll_name_color,
|
275 |
layout_style_radio,
|
276 |
title_uppercase_checkbox,
|
277 |
name_uppercase_checkbox,
|
278 |
section_title_uppercase_checkbox,
|
279 |
+
swap_sizes_checkbox,
|
280 |
+
show_scroll_logo_checkbox,
|
281 |
+
scroll_logo_height_input
|
282 |
]
|
283 |
|
284 |
+
demo.load(
|
285 |
+
fn=update_panel,
|
286 |
+
inputs=inputs,
|
287 |
+
outputs=panel
|
288 |
+
)
|
289 |
layout_style_radio.change(
|
290 |
fn=toggle_swap_checkbox_visibility,
|
291 |
inputs=layout_style_radio,
|
|
|
329 |
|
330 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
331 |
|
|
|
332 |
|
333 |
|
334 |
```python
|
|
|
336 |
value: typing.Optional[typing.Dict[str, typing.Any]][
|
337 |
typing.Dict[str, typing.Any][str, Any], None
|
338 |
]
|
339 |
+
) -> typing.Optional[typing.Dict[str, typing.Any]][
|
340 |
+
typing.Dict[str, typing.Any][str, Any], None
|
341 |
+
]:
|
342 |
return value
|
343 |
```
|
344 |
""", elem_classes=["md-custom", "CreditsPanel-user-fn"], header_links=True)
|
src/README.md
CHANGED
@@ -10,7 +10,8 @@ app_file: space.py
|
|
10 |
---
|
11 |
|
12 |
# `gradio_creditspanel`
|
13 |
-
<
|
|
|
14 |
|
15 |
Credits Panel for Gradio UI
|
16 |
|
@@ -43,7 +44,7 @@ def setup_demo_files():
|
|
43 |
with open("./assets/logo.webp", "w") as f:
|
44 |
f.write("Placeholder WebP logo")
|
45 |
|
46 |
-
# ---
|
47 |
credits_list = [
|
48 |
{"section_title": "Project Leadership"},
|
49 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
@@ -72,6 +73,8 @@ DEFAULT_SPEEDS = {
|
|
72 |
"starwars": 70.0,
|
73 |
"matrix": 40.0
|
74 |
}
|
|
|
|
|
75 |
|
76 |
def update_panel(
|
77 |
effect: str,
|
@@ -89,39 +92,52 @@ def update_panel(
|
|
89 |
logo_height: str | None,
|
90 |
scroll_background_color: str | None,
|
91 |
scroll_title_color: str | None,
|
|
|
92 |
scroll_name_color: str | None,
|
93 |
layout_style: str,
|
94 |
title_uppercase: bool,
|
95 |
name_uppercase: bool,
|
96 |
section_title_uppercase: bool,
|
97 |
-
swap_font_sizes: bool
|
|
|
|
|
98 |
) -> dict:
|
99 |
"""Callback function that updates all properties of the CreditsPanel component."""
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
127 |
"""Updates sliders to sensible defaults when the animation effect is changed."""
|
@@ -163,6 +179,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
163 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
164 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
gr.Markdown("### Intro Text")
|
167 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
168 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
@@ -182,19 +206,20 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
182 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
183 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
184 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
|
|
185 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
186 |
|
187 |
-
panel = CreditsPanel(
|
|
|
188 |
credits=credits_list,
|
189 |
licenses=license_paths,
|
190 |
effect="scroll",
|
191 |
-
height=500,
|
192 |
speed=DEFAULT_SPEEDS["scroll"],
|
193 |
base_font_size=1.5,
|
194 |
intro_title="Gradio",
|
195 |
intro_subtitle="The best UI framework",
|
196 |
sidebar_position="right",
|
197 |
-
logo_path=
|
198 |
show_logo=True,
|
199 |
show_licenses=True,
|
200 |
show_credits=True,
|
@@ -205,11 +230,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
205 |
scroll_background_color="#000000",
|
206 |
scroll_title_color="#FFFFFF",
|
207 |
scroll_name_color="#FFFFFF",
|
|
|
208 |
layout_style="stacked",
|
209 |
title_uppercase=False,
|
210 |
name_uppercase=False,
|
211 |
section_title_uppercase=True,
|
212 |
swap_font_sizes_on_two_column=False,
|
|
|
|
|
213 |
)
|
214 |
|
215 |
inputs = [
|
@@ -227,15 +255,23 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
227 |
logo_width_input,
|
228 |
logo_height_input,
|
229 |
scroll_background_color,
|
230 |
-
scroll_title_color,
|
|
|
231 |
scroll_name_color,
|
232 |
layout_style_radio,
|
233 |
title_uppercase_checkbox,
|
234 |
name_uppercase_checkbox,
|
235 |
section_title_uppercase_checkbox,
|
236 |
-
swap_sizes_checkbox
|
|
|
|
|
237 |
]
|
238 |
|
|
|
|
|
|
|
|
|
|
|
239 |
layout_style_radio.change(
|
240 |
fn=toggle_swap_checkbox_visibility,
|
241 |
inputs=layout_style_radio,
|
@@ -270,7 +306,9 @@ if __name__ == "__main__":
|
|
270 |
<td align="left" style="width: 25%;">
|
271 |
|
272 |
```python
|
273 |
-
Any
|
|
|
|
|
274 |
```
|
275 |
|
276 |
</td>
|
@@ -279,21 +317,11 @@ Any
|
|
279 |
</tr>
|
280 |
|
281 |
<tr>
|
282 |
-
<td align="left"><code>
|
283 |
<td align="left" style="width: 25%;">
|
284 |
|
285 |
```python
|
286 |
-
|
287 |
-
typing.List[typing.Dict[str, str]],
|
288 |
-
typing.Callable,
|
289 |
-
NoneType,
|
290 |
-
][
|
291 |
-
typing.List[typing.Dict[str, str]][
|
292 |
-
typing.Dict[str, str][str, str]
|
293 |
-
],
|
294 |
-
Callable,
|
295 |
-
None,
|
296 |
-
]
|
297 |
```
|
298 |
|
299 |
</td>
|
@@ -302,7 +330,7 @@ typing.Union[
|
|
302 |
</tr>
|
303 |
|
304 |
<tr>
|
305 |
-
<td align="left"><code>
|
306 |
<td align="left" style="width: 25%;">
|
307 |
|
308 |
```python
|
@@ -315,11 +343,21 @@ int | str | None
|
|
315 |
</tr>
|
316 |
|
317 |
<tr>
|
318 |
-
<td align="left"><code>
|
319 |
<td align="left" style="width: 25%;">
|
320 |
|
321 |
```python
|
322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
```
|
324 |
|
325 |
</td>
|
@@ -566,6 +604,19 @@ str | None
|
|
566 |
<td align="left">None</td>
|
567 |
</tr>
|
568 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
569 |
<tr>
|
570 |
<td align="left"><code>layout_style</code></td>
|
571 |
<td align="left" style="width: 25%;">
|
@@ -631,6 +682,32 @@ bool
|
|
631 |
<td align="left">None</td>
|
632 |
</tr>
|
633 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
634 |
<tr>
|
635 |
<td align="left"><code>label</code></td>
|
636 |
<td align="left" style="width: 25%;">
|
@@ -844,7 +921,6 @@ The impact on the users predict function varies depending on whether the compone
|
|
844 |
|
845 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
846 |
|
847 |
-
- **As output:** Is passed, dict[str, Any] | None: The input payload, returned unchanged.
|
848 |
|
849 |
|
850 |
```python
|
@@ -852,7 +928,9 @@ The code snippet below is accurate in cases where the component is used as both
|
|
852 |
value: typing.Optional[typing.Dict[str, typing.Any]][
|
853 |
typing.Dict[str, typing.Any][str, Any], None
|
854 |
]
|
855 |
-
) -> Any
|
|
|
|
|
856 |
return value
|
857 |
```
|
858 |
|
|
|
10 |
---
|
11 |
|
12 |
# `gradio_creditspanel`
|
13 |
+
<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_creditspanel"><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_creditspanel'>Component GitHub Code</a></span></p>
|
14 |
+
|
15 |
|
16 |
Credits Panel for Gradio UI
|
17 |
|
|
|
44 |
with open("./assets/logo.webp", "w") as f:
|
45 |
f.write("Placeholder WebP logo")
|
46 |
|
47 |
+
# --- Credits list with sections ---
|
48 |
credits_list = [
|
49 |
{"section_title": "Project Leadership"},
|
50 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
|
|
73 |
"starwars": 70.0,
|
74 |
"matrix": 40.0
|
75 |
}
|
76 |
+
SCROLL_LOGO_PATH = "./assets/gradio_logo_white.png"
|
77 |
+
LOGO_PATH="./assets/logo.webp"
|
78 |
|
79 |
def update_panel(
|
80 |
effect: str,
|
|
|
92 |
logo_height: str | None,
|
93 |
scroll_background_color: str | None,
|
94 |
scroll_title_color: str | None,
|
95 |
+
scroll_section_title_color: str | None,
|
96 |
scroll_name_color: str | None,
|
97 |
layout_style: str,
|
98 |
title_uppercase: bool,
|
99 |
name_uppercase: bool,
|
100 |
section_title_uppercase: bool,
|
101 |
+
swap_font_sizes: bool,
|
102 |
+
show_scroll_logo: bool,
|
103 |
+
scroll_logo_height: str | None
|
104 |
) -> dict:
|
105 |
"""Callback function that updates all properties of the CreditsPanel component."""
|
106 |
+
|
107 |
+
scroll_logo_path = SCROLL_LOGO_PATH if show_scroll_logo else None
|
108 |
+
|
109 |
+
if not scroll_logo_height:
|
110 |
+
scroll_logo_height = "120px"
|
111 |
+
|
112 |
+
return {
|
113 |
+
"credits": credits_list,
|
114 |
+
"licenses": license_paths,
|
115 |
+
"effect": effect,
|
116 |
+
"speed": speed,
|
117 |
+
"base_font_size": base_font_size,
|
118 |
+
"intro_title": intro_title,
|
119 |
+
"intro_subtitle": intro_subtitle,
|
120 |
+
"sidebar_position": sidebar_position,
|
121 |
+
"logo_path": LOGO_PATH,
|
122 |
+
"show_logo": show_logo,
|
123 |
+
"show_licenses": show_licenses,
|
124 |
+
"show_credits": show_credits,
|
125 |
+
"logo_position": logo_position,
|
126 |
+
"logo_sizing": logo_sizing,
|
127 |
+
"logo_width": logo_width,
|
128 |
+
"logo_height": logo_height,
|
129 |
+
"scroll_background_color": scroll_background_color,
|
130 |
+
"scroll_title_color": scroll_title_color,
|
131 |
+
"scroll_name_color": scroll_name_color,
|
132 |
+
"scroll_section_title_color": scroll_section_title_color,
|
133 |
+
"layout_style": layout_style,
|
134 |
+
"title_uppercase": title_uppercase,
|
135 |
+
"name_uppercase": name_uppercase,
|
136 |
+
"section_title_uppercase": section_title_uppercase,
|
137 |
+
"swap_font_sizes_on_two_column": swap_font_sizes,
|
138 |
+
"scroll_logo_path": scroll_logo_path,
|
139 |
+
"scroll_logo_height": scroll_logo_height,
|
140 |
+
}
|
141 |
|
142 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
143 |
"""Updates sliders to sensible defaults when the animation effect is changed."""
|
|
|
179 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
180 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
181 |
|
182 |
+
gr.Markdown("### Scrolling Logo")
|
183 |
+
show_scroll_logo_checkbox = gr.Checkbox(
|
184 |
+
label="Show Logo in Credits Roll",
|
185 |
+
value=True,
|
186 |
+
info="Toggles the logo above the intro text."
|
187 |
+
)
|
188 |
+
scroll_logo_height_input = gr.Textbox(label="Scrolling Logo Height", value="100px")
|
189 |
+
|
190 |
gr.Markdown("### Intro Text")
|
191 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
192 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
|
|
206 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
207 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
208 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
209 |
+
scroll_section_title_color = gr.ColorPicker(label="Section Title Color", value="#FFFFFF")
|
210 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
211 |
|
212 |
+
panel = CreditsPanel(
|
213 |
+
height=500,
|
214 |
credits=credits_list,
|
215 |
licenses=license_paths,
|
216 |
effect="scroll",
|
|
|
217 |
speed=DEFAULT_SPEEDS["scroll"],
|
218 |
base_font_size=1.5,
|
219 |
intro_title="Gradio",
|
220 |
intro_subtitle="The best UI framework",
|
221 |
sidebar_position="right",
|
222 |
+
logo_path=LOGO_PATH,
|
223 |
show_logo=True,
|
224 |
show_licenses=True,
|
225 |
show_credits=True,
|
|
|
230 |
scroll_background_color="#000000",
|
231 |
scroll_title_color="#FFFFFF",
|
232 |
scroll_name_color="#FFFFFF",
|
233 |
+
scroll_section_title_color="#FFFFFF",
|
234 |
layout_style="stacked",
|
235 |
title_uppercase=False,
|
236 |
name_uppercase=False,
|
237 |
section_title_uppercase=True,
|
238 |
swap_font_sizes_on_two_column=False,
|
239 |
+
scroll_logo_path=SCROLL_LOGO_PATH,
|
240 |
+
scroll_logo_height="100px",
|
241 |
)
|
242 |
|
243 |
inputs = [
|
|
|
255 |
logo_width_input,
|
256 |
logo_height_input,
|
257 |
scroll_background_color,
|
258 |
+
scroll_title_color,
|
259 |
+
scroll_section_title_color,
|
260 |
scroll_name_color,
|
261 |
layout_style_radio,
|
262 |
title_uppercase_checkbox,
|
263 |
name_uppercase_checkbox,
|
264 |
section_title_uppercase_checkbox,
|
265 |
+
swap_sizes_checkbox,
|
266 |
+
show_scroll_logo_checkbox,
|
267 |
+
scroll_logo_height_input
|
268 |
]
|
269 |
|
270 |
+
demo.load(
|
271 |
+
fn=update_panel,
|
272 |
+
inputs=inputs,
|
273 |
+
outputs=panel
|
274 |
+
)
|
275 |
layout_style_radio.change(
|
276 |
fn=toggle_swap_checkbox_visibility,
|
277 |
inputs=layout_style_radio,
|
|
|
306 |
<td align="left" style="width: 25%;">
|
307 |
|
308 |
```python
|
309 |
+
typing.Optional[typing.Dict[str, typing.Any]][
|
310 |
+
typing.Dict[str, typing.Any][str, Any], None
|
311 |
+
]
|
312 |
```
|
313 |
|
314 |
</td>
|
|
|
317 |
</tr>
|
318 |
|
319 |
<tr>
|
320 |
+
<td align="left"><code>height</code></td>
|
321 |
<td align="left" style="width: 25%;">
|
322 |
|
323 |
```python
|
324 |
+
int | str | None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
```
|
326 |
|
327 |
</td>
|
|
|
330 |
</tr>
|
331 |
|
332 |
<tr>
|
333 |
+
<td align="left"><code>width</code></td>
|
334 |
<td align="left" style="width: 25%;">
|
335 |
|
336 |
```python
|
|
|
343 |
</tr>
|
344 |
|
345 |
<tr>
|
346 |
+
<td align="left"><code>credits</code></td>
|
347 |
<td align="left" style="width: 25%;">
|
348 |
|
349 |
```python
|
350 |
+
typing.Union[
|
351 |
+
typing.List[typing.Dict[str, str]],
|
352 |
+
typing.Callable,
|
353 |
+
NoneType,
|
354 |
+
][
|
355 |
+
typing.List[typing.Dict[str, str]][
|
356 |
+
typing.Dict[str, str][str, str]
|
357 |
+
],
|
358 |
+
Callable,
|
359 |
+
None,
|
360 |
+
]
|
361 |
```
|
362 |
|
363 |
</td>
|
|
|
604 |
<td align="left">None</td>
|
605 |
</tr>
|
606 |
|
607 |
+
<tr>
|
608 |
+
<td align="left"><code>scroll_section_title_color</code></td>
|
609 |
+
<td align="left" style="width: 25%;">
|
610 |
+
|
611 |
+
```python
|
612 |
+
str | None
|
613 |
+
```
|
614 |
+
|
615 |
+
</td>
|
616 |
+
<td align="left"><code>None</code></td>
|
617 |
+
<td align="left">None</td>
|
618 |
+
</tr>
|
619 |
+
|
620 |
<tr>
|
621 |
<td align="left"><code>layout_style</code></td>
|
622 |
<td align="left" style="width: 25%;">
|
|
|
682 |
<td align="left">None</td>
|
683 |
</tr>
|
684 |
|
685 |
+
<tr>
|
686 |
+
<td align="left"><code>scroll_logo_path</code></td>
|
687 |
+
<td align="left" style="width: 25%;">
|
688 |
+
|
689 |
+
```python
|
690 |
+
str | pathlib.Path | None
|
691 |
+
```
|
692 |
+
|
693 |
+
</td>
|
694 |
+
<td align="left"><code>None</code></td>
|
695 |
+
<td align="left">None</td>
|
696 |
+
</tr>
|
697 |
+
|
698 |
+
<tr>
|
699 |
+
<td align="left"><code>scroll_logo_height</code></td>
|
700 |
+
<td align="left" style="width: 25%;">
|
701 |
+
|
702 |
+
```python
|
703 |
+
str
|
704 |
+
```
|
705 |
+
|
706 |
+
</td>
|
707 |
+
<td align="left"><code>"120px"</code></td>
|
708 |
+
<td align="left">None</td>
|
709 |
+
</tr>
|
710 |
+
|
711 |
<tr>
|
712 |
<td align="left"><code>label</code></td>
|
713 |
<td align="left" style="width: 25%;">
|
|
|
921 |
|
922 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
923 |
|
|
|
924 |
|
925 |
|
926 |
```python
|
|
|
928 |
value: typing.Optional[typing.Dict[str, typing.Any]][
|
929 |
typing.Dict[str, typing.Any][str, Any], None
|
930 |
]
|
931 |
+
) -> typing.Optional[typing.Dict[str, typing.Any]][
|
932 |
+
typing.Dict[str, typing.Any][str, Any], None
|
933 |
+
]:
|
934 |
return value
|
935 |
```
|
936 |
|
src/assets/gradio_logo_white.png
ADDED
![]() |
src/backend/gradio_creditspanel/creditspanel.py
CHANGED
@@ -13,7 +13,8 @@ import os
|
|
13 |
class CreditsPanel(Component):
|
14 |
"""
|
15 |
A Gradio component for displaying credits with customizable visual effects, such as scrolling or Star Wars-style animations.
|
16 |
-
|
|
|
17 |
|
18 |
Attributes:
|
19 |
EVENTS (list): Supported events for the component, currently only `change`.
|
@@ -23,11 +24,13 @@ class CreditsPanel(Component):
|
|
23 |
|
24 |
def __init__(
|
25 |
self,
|
26 |
-
value: Any = None,
|
27 |
-
credits: List[Dict[str, str]] | Callable | None = None,
|
28 |
*,
|
|
|
29 |
height: int | str | None = None,
|
30 |
width: int | str | None = None,
|
|
|
|
|
31 |
licenses: Dict[str, str | Path] | None = None,
|
32 |
effect: Literal["scroll", "starwars", "matrix"] = "scroll",
|
33 |
speed: float = 40.0,
|
@@ -46,11 +49,15 @@ class CreditsPanel(Component):
|
|
46 |
scroll_background_color: str | None = None,
|
47 |
scroll_title_color: str | None = None,
|
48 |
scroll_name_color: str | None = None,
|
|
|
49 |
layout_style: Literal["stacked", "two-column"] = "stacked",
|
50 |
title_uppercase: bool = False,
|
51 |
name_uppercase: bool = False,
|
52 |
section_title_uppercase: bool = True,
|
53 |
swap_font_sizes_on_two_column: bool = False,
|
|
|
|
|
|
|
54 |
label: str | I18nData | None = None,
|
55 |
every: float | None = None,
|
56 |
inputs: Component | Sequence[Component] | set[Component] | None = None,
|
@@ -70,74 +77,77 @@ class CreditsPanel(Component):
|
|
70 |
Initialize the CreditsPanel component.
|
71 |
|
72 |
Args:
|
73 |
-
value (Any, optional):
|
74 |
-
|
75 |
-
height (int | str | None, optional):
|
76 |
-
width (int | str | None, optional):
|
77 |
-
|
78 |
-
|
|
|
79 |
speed (float, optional): Animation speed in seconds. Defaults to 40.0.
|
80 |
-
base_font_size (float, optional): Base font size in rem
|
81 |
-
intro_title (str | None, optional): Title for the intro
|
82 |
-
intro_subtitle (str | None, optional): Subtitle for the intro
|
83 |
sidebar_position (Literal["right", "bottom"], optional): Position of the licenses sidebar. Defaults to "right".
|
84 |
-
logo_path (str | Path | None, optional): Path or URL to the logo
|
85 |
-
show_logo (bool, optional): Whether to display the logo. Defaults to True.
|
86 |
show_licenses (bool, optional): Whether to display licenses. Defaults to True.
|
87 |
-
show_credits (bool, optional): Whether to display the credits. Defaults to True.
|
88 |
-
logo_position (Literal["center", "left", "right"], optional):
|
89 |
-
logo_sizing (Literal["stretch", "crop", "resize"], optional):
|
90 |
-
logo_width (int | str | None, optional):
|
91 |
-
logo_height (int | str | None, optional):
|
92 |
-
scroll_background_color (str | None, optional): Background color for scroll effect.
|
93 |
scroll_title_color (str | None, optional): Color for credit titles.
|
94 |
scroll_name_color (str | None, optional): Color for credit names.
|
95 |
-
|
|
|
96 |
title_uppercase (bool, optional): Whether to display titles in uppercase. Defaults to False.
|
97 |
-
name_uppercase (bool, optional): Whether to display names in uppercase. Defaults to False.
|
98 |
section_title_uppercase (bool, optional): Whether to display section titles in uppercase. Defaults to True.
|
99 |
-
swap_font_sizes_on_two_column (bool, optional):
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
show_label (bool, optional): Whether to show the label. Defaults to False.
|
104 |
-
container (bool, optional): Whether to render in a container. Defaults to True.
|
105 |
-
scale (int | None, optional): Scaling factor for the component.
|
106 |
-
min_width (int, optional): Minimum width in pixels. Defaults to 160.
|
107 |
-
interactive (bool | None, optional): Whether the component is interactive.
|
108 |
-
visible (bool, optional): Whether the component is visible. Defaults to True.
|
109 |
-
elem_id (str | None, optional): Custom HTML element ID.
|
110 |
-
elem_classes (list[str] | str | None, optional): CSS classes for the component.
|
111 |
-
render (bool, optional): Whether to render the component. Defaults to True.
|
112 |
-
key (int | str | tuple[int | str, ...] | None, optional): Component key for state preservation.
|
113 |
-
preserved_by_key (list[str] | str | None, optional): Properties preserved by key. Defaults to "value".
|
114 |
"""
|
|
|
115 |
self.height = height
|
116 |
self.width = width
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
self.
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
|
142 |
super().__init__(
|
143 |
label=label,
|
@@ -154,35 +164,14 @@ class CreditsPanel(Component):
|
|
154 |
key=key,
|
155 |
visible=visible,
|
156 |
preserved_by_key=preserved_by_key,
|
157 |
-
value=
|
158 |
)
|
159 |
|
160 |
-
def
|
161 |
-
"""
|
162 |
-
|
163 |
-
|
164 |
-
Returns:
|
165 |
-
Dict[str, str]: Dictionary mapping license names to their content or error messages if loading fails.
|
166 |
-
"""
|
167 |
-
processed = {}
|
168 |
-
for name, path in self.licenses_paths.items():
|
169 |
-
try:
|
170 |
-
with open(path, "r", encoding="utf-8") as f:
|
171 |
-
processed[name] = f.read()
|
172 |
-
except Exception as e:
|
173 |
-
processed[name] = f"Error loading license file '{path}':\n{e}"
|
174 |
-
return processed
|
175 |
-
|
176 |
-
def _process_logo_path(self) -> Dict[str, Any] | None:
|
177 |
-
"""
|
178 |
-
Process the logo path, handling both local files and URLs.
|
179 |
-
|
180 |
-
Returns:
|
181 |
-
Dict[str, Any] | None: Dictionary with logo details (path, url, orig_name, mime_type) or None if no logo_path is provided or the file is not found.
|
182 |
-
"""
|
183 |
-
if not self.logo_path:
|
184 |
return None
|
185 |
-
path = str(
|
186 |
if is_http_url_like(path):
|
187 |
return {"path": None, "url": path, "orig_name": Path(path).name, "mime_type": None}
|
188 |
if os.path.exists(path):
|
@@ -191,75 +180,55 @@ class CreditsPanel(Component):
|
|
191 |
|
192 |
def preprocess(self, payload: Dict[str, Any] | None) -> Dict[str, Any] | None:
|
193 |
"""
|
194 |
-
|
195 |
-
|
196 |
-
Args:
|
197 |
-
payload (Dict[str, Any] | None): Input data to preprocess.
|
198 |
-
|
199 |
-
Returns:
|
200 |
-
Dict[str, Any] | None: The input payload, returned unchanged.
|
201 |
"""
|
202 |
return payload
|
203 |
|
204 |
-
def postprocess(self, value: Any) -> Dict[str, Any] | None:
|
205 |
"""
|
206 |
-
|
207 |
-
|
|
|
208 |
Args:
|
209 |
-
value (Any):
|
210 |
|
211 |
Returns:
|
212 |
-
Dict[str, Any] | None:
|
213 |
"""
|
214 |
-
|
215 |
-
if not credits_source and not self.licenses_paths:
|
216 |
return None
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
"logo_width": self.logo_width,
|
233 |
-
"logo_height": self.logo_height,
|
234 |
-
"scroll_background_color": self.scroll_background_color,
|
235 |
-
"scroll_title_color": self.scroll_title_color,
|
236 |
-
"scroll_name_color": self.scroll_name_color,
|
237 |
-
"layout_style": self.layout_style,
|
238 |
-
"title_uppercase": self.title_uppercase,
|
239 |
-
"name_uppercase": self.name_uppercase,
|
240 |
-
"section_title_uppercase": self.section_title_uppercase,
|
241 |
-
"swap_font_sizes_on_two_column": self.swap_font_sizes_on_two_column,
|
242 |
-
}
|
243 |
|
244 |
-
|
245 |
-
"""
|
246 |
-
|
247 |
|
248 |
-
|
249 |
-
|
250 |
-
|
|
|
251 |
return {"type": "object"}
|
252 |
|
253 |
def example_payload(self) -> Any:
|
254 |
-
"""
|
255 |
-
|
256 |
-
|
257 |
-
Returns:
|
258 |
-
Dict[str, Any]: Example data structure for the component's payload.
|
259 |
-
"""
|
260 |
return {
|
261 |
-
"credits": [{"title": "Example", "name": "Credit"}],
|
262 |
-
"licenses": {},
|
263 |
"effect": "scroll",
|
264 |
"speed": 20,
|
265 |
"sidebar_position": "right",
|
@@ -274,18 +243,17 @@ class CreditsPanel(Component):
|
|
274 |
"scroll_background_color": None,
|
275 |
"scroll_title_color": None,
|
276 |
"scroll_name_color": None,
|
|
|
277 |
"layout_style": "stacked",
|
278 |
"title_uppercase": False,
|
279 |
"name_uppercase": False,
|
280 |
"section_title_uppercase": True,
|
281 |
"swap_font_sizes_on_two_column": False,
|
|
|
|
|
282 |
}
|
283 |
|
284 |
def example_value(self) -> Any:
|
285 |
-
"""
|
286 |
-
|
287 |
-
|
288 |
-
Returns:
|
289 |
-
List[Dict[str, str]]: Example list of credits.
|
290 |
-
"""
|
291 |
-
return [{"title": "Example", "name": "Credit"}]
|
|
|
13 |
class CreditsPanel(Component):
|
14 |
"""
|
15 |
A Gradio component for displaying credits with customizable visual effects, such as scrolling or Star Wars-style animations.
|
16 |
+
This component is configured via a single dictionary `value` that holds all settings.
|
17 |
+
It supports displaying a logo, licenses, sections, and various text styling options.
|
18 |
|
19 |
Attributes:
|
20 |
EVENTS (list): Supported events for the component, currently only `change`.
|
|
|
24 |
|
25 |
def __init__(
|
26 |
self,
|
27 |
+
value: Dict[str, Any] | None = None,
|
|
|
28 |
*,
|
29 |
+
# Structural parameters
|
30 |
height: int | str | None = None,
|
31 |
width: int | str | None = None,
|
32 |
+
# Configuration parameters (will be part of the `value` dictionary)
|
33 |
+
credits: List[Dict[str, str]] | Callable | None = None,
|
34 |
licenses: Dict[str, str | Path] | None = None,
|
35 |
effect: Literal["scroll", "starwars", "matrix"] = "scroll",
|
36 |
speed: float = 40.0,
|
|
|
49 |
scroll_background_color: str | None = None,
|
50 |
scroll_title_color: str | None = None,
|
51 |
scroll_name_color: str | None = None,
|
52 |
+
scroll_section_title_color: str | None = None,
|
53 |
layout_style: Literal["stacked", "two-column"] = "stacked",
|
54 |
title_uppercase: bool = False,
|
55 |
name_uppercase: bool = False,
|
56 |
section_title_uppercase: bool = True,
|
57 |
swap_font_sizes_on_two_column: bool = False,
|
58 |
+
scroll_logo_path: str | Path | None = None,
|
59 |
+
scroll_logo_height: str = "120px",
|
60 |
+
# Standard Gradio parameters
|
61 |
label: str | I18nData | None = None,
|
62 |
every: float | None = None,
|
63 |
inputs: Component | Sequence[Component] | set[Component] | None = None,
|
|
|
77 |
Initialize the CreditsPanel component.
|
78 |
|
79 |
Args:
|
80 |
+
value (Dict[str, Any], optional): The dictionary containing the component's full configuration.
|
81 |
+
If provided, it overrides all other configuration parameters.
|
82 |
+
height (int | str | None, optional): The structural height of the component.
|
83 |
+
width (int | str | None, optional): The structural width of the component.
|
84 |
+
credits (List[Dict[str, str]] | Callable | None, optional): List of credits, can include section headers.
|
85 |
+
licenses (Dict[str, str | Path] | None, optional): Dictionary mapping license names to file paths.
|
86 |
+
effect (Literal["scroll", "starwars", "matrix"], optional): Visual effect for the credits. Defaults to "scroll".
|
87 |
speed (float, optional): Animation speed in seconds. Defaults to 40.0.
|
88 |
+
base_font_size (float, optional): Base font size in rem. Defaults to 1.5.
|
89 |
+
intro_title (str | None, optional): Title for the intro sequence.
|
90 |
+
intro_subtitle (str | None, optional): Subtitle for the intro sequence.
|
91 |
sidebar_position (Literal["right", "bottom"], optional): Position of the licenses sidebar. Defaults to "right".
|
92 |
+
logo_path (str | Path | None, optional): Path or URL to the main static logo.
|
93 |
+
show_logo (bool, optional): Whether to display the main logo. Defaults to True.
|
94 |
show_licenses (bool, optional): Whether to display licenses. Defaults to True.
|
95 |
+
show_credits (bool, optional): Whether to display the credits panel. Defaults to True.
|
96 |
+
logo_position (Literal["center", "left", "right"], optional): Main logo alignment. Defaults to "center".
|
97 |
+
logo_sizing (Literal["stretch", "crop", "resize"], optional): Main logo sizing mode. Defaults to "resize".
|
98 |
+
logo_width (int | str | None, optional): Main logo width.
|
99 |
+
logo_height (int | str | None, optional): Main logo height.
|
100 |
+
scroll_background_color (str | None, optional): Background color for the scroll effect.
|
101 |
scroll_title_color (str | None, optional): Color for credit titles.
|
102 |
scroll_name_color (str | None, optional): Color for credit names.
|
103 |
+
scroll_section_title_color (str | None, optional): Color for section titles in the scroll effect.
|
104 |
+
layout_style (Literal["stacked", "two-column"], optional): Layout for credits. Defaults to "stacked".
|
105 |
title_uppercase (bool, optional): Whether to display titles in uppercase. Defaults to False.
|
106 |
+
name_uppercase (bool, optional): Whether to display names in uppercase. Defaults to False.
|
107 |
section_title_uppercase (bool, optional): Whether to display section titles in uppercase. Defaults to True.
|
108 |
+
swap_font_sizes_on_two_column (bool, optional): Swaps title and name font sizes in two-column layout. Defaults to False.
|
109 |
+
scroll_logo_path (str | Path | None, optional): Path or URL to a logo inside the scrolling credits.
|
110 |
+
scroll_logo_height (str, optional): The height of the scrolling logo. Defaults to "120px".
|
111 |
+
(Other standard Gradio arguments)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
"""
|
113 |
+
# Structural parameters are stored directly on self.
|
114 |
self.height = height
|
115 |
self.width = width
|
116 |
+
|
117 |
+
# All other configuration parameters are bundled into a dictionary.
|
118 |
+
# This dictionary is the component's main `value`.
|
119 |
+
self._config = {
|
120 |
+
"credits": credits if credits is not None else [],
|
121 |
+
"licenses": licenses or {},
|
122 |
+
"effect": effect,
|
123 |
+
"speed": speed,
|
124 |
+
"base_font_size": base_font_size,
|
125 |
+
"intro_title": intro_title,
|
126 |
+
"intro_subtitle": intro_subtitle,
|
127 |
+
"sidebar_position": sidebar_position,
|
128 |
+
"logo_path": logo_path,
|
129 |
+
"show_logo": show_logo,
|
130 |
+
"show_licenses": show_licenses,
|
131 |
+
"show_credits": show_credits,
|
132 |
+
"logo_position": logo_position,
|
133 |
+
"logo_sizing": logo_sizing,
|
134 |
+
"logo_width": logo_width,
|
135 |
+
"logo_height": logo_height,
|
136 |
+
"scroll_background_color": scroll_background_color,
|
137 |
+
"scroll_title_color": scroll_title_color,
|
138 |
+
"scroll_name_color": scroll_name_color,
|
139 |
+
"scroll_section_title_color": scroll_section_title_color,
|
140 |
+
"layout_style": layout_style,
|
141 |
+
"title_uppercase": title_uppercase,
|
142 |
+
"name_uppercase": name_uppercase,
|
143 |
+
"section_title_uppercase": section_title_uppercase,
|
144 |
+
"swap_font_sizes_on_two_column": swap_font_sizes_on_two_column,
|
145 |
+
"scroll_logo_path": scroll_logo_path,
|
146 |
+
"scroll_logo_height": scroll_logo_height,
|
147 |
+
}
|
148 |
+
|
149 |
+
# If a `value` dictionary is passed directly, it overrides the individual parameters.
|
150 |
+
initial_value = value if value is not None else self._config
|
151 |
|
152 |
super().__init__(
|
153 |
label=label,
|
|
|
164 |
key=key,
|
165 |
visible=visible,
|
166 |
preserved_by_key=preserved_by_key,
|
167 |
+
value=initial_value, # The component's state is its configuration dictionary.
|
168 |
)
|
169 |
|
170 |
+
def _process_image_path(self, image_path: str | Path | None) -> Dict[str, Any] | None:
|
171 |
+
"""Helper function to process an image path, handling local files and URLs."""
|
172 |
+
if not image_path:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
return None
|
174 |
+
path = str(image_path)
|
175 |
if is_http_url_like(path):
|
176 |
return {"path": None, "url": path, "orig_name": Path(path).name, "mime_type": None}
|
177 |
if os.path.exists(path):
|
|
|
180 |
|
181 |
def preprocess(self, payload: Dict[str, Any] | None) -> Dict[str, Any] | None:
|
182 |
"""
|
183 |
+
Passes the payload from the frontend through, unmodified.
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
"""
|
185 |
return payload
|
186 |
|
187 |
+
def postprocess(self, value: Dict[str, Any] | None) -> Dict[str, Any] | None:
|
188 |
"""
|
189 |
+
Processes the component's `value` dictionary to prepare data for the frontend.
|
190 |
+
This involves resolving file paths for licenses and images.
|
191 |
+
|
192 |
Args:
|
193 |
+
value (Dict[str, Any] | None): The component's configuration dictionary.
|
194 |
|
195 |
Returns:
|
196 |
+
Dict[str, Any] | None: The processed dictionary ready to be sent to the frontend.
|
197 |
"""
|
198 |
+
if not value:
|
|
|
199 |
return None
|
200 |
+
|
201 |
+
processed_value = value.copy()
|
202 |
+
|
203 |
+
# Process license file paths from the 'licenses' dictionary
|
204 |
+
license_paths = processed_value.get("licenses", {})
|
205 |
+
processed_licenses = {}
|
206 |
+
if isinstance(license_paths, dict): # Check if licenses are in the expected format
|
207 |
+
for name, path in license_paths.items():
|
208 |
+
try:
|
209 |
+
with open(path, "r", encoding="utf-8") as f:
|
210 |
+
processed_licenses[name] = f.read()
|
211 |
+
except Exception as e:
|
212 |
+
# Silently fail or log, to avoid crashing the app for a missing license file
|
213 |
+
processed_licenses[name] = f"Error loading license file '{path}':\n{e}"
|
214 |
+
processed_value["licenses"] = processed_licenses
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
|
216 |
+
# Process image paths
|
217 |
+
processed_value["logo_path"] = self._process_image_path(processed_value.get("logo_path"))
|
218 |
+
processed_value["scroll_logo_path"] = self._process_image_path(processed_value.get("scroll_logo_path"))
|
219 |
|
220 |
+
return processed_value
|
221 |
+
|
222 |
+
def api_info(self) -> Dict[str, Any]:
|
223 |
+
"""Returns API info for the component."""
|
224 |
return {"type": "object"}
|
225 |
|
226 |
def example_payload(self) -> Any:
|
227 |
+
"""Returns an example payload for the component's API."""
|
228 |
+
# This now directly returns a dictionary matching the `value` structure.
|
|
|
|
|
|
|
|
|
229 |
return {
|
230 |
+
"credits": [{"title": "API Example", "name": "Credit"}],
|
231 |
+
"licenses": {"MIT": "MIT License text..."},
|
232 |
"effect": "scroll",
|
233 |
"speed": 20,
|
234 |
"sidebar_position": "right",
|
|
|
243 |
"scroll_background_color": None,
|
244 |
"scroll_title_color": None,
|
245 |
"scroll_name_color": None,
|
246 |
+
"scroll_section_title_color": None,
|
247 |
"layout_style": "stacked",
|
248 |
"title_uppercase": False,
|
249 |
"name_uppercase": False,
|
250 |
"section_title_uppercase": True,
|
251 |
"swap_font_sizes_on_two_column": False,
|
252 |
+
"scroll_logo_path": None,
|
253 |
+
"scroll_logo_height": "120px",
|
254 |
}
|
255 |
|
256 |
def example_value(self) -> Any:
|
257 |
+
"""Returns an example value for the component."""
|
258 |
+
# The example value is now the entire configuration dictionary.
|
259 |
+
return self.example_payload()
|
|
|
|
|
|
|
|
src/backend/gradio_creditspanel/templates/component/index.js
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
src/backend/gradio_creditspanel/templates/component/style.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
.block.svelte-239wnu{position:relative;margin:0;box-shadow:var(--block-shadow);border-width:var(--block-border-width);border-color:var(--block-border-color);border-radius:var(--block-radius);background:var(--block-background-fill);width:100%;line-height:var(--line-sm)}.block.fullscreen.svelte-239wnu{border-radius:0}.auto-margin.svelte-239wnu{margin-left:auto;margin-right:auto}.block.border_focus.svelte-239wnu{border-color:var(--color-accent)}.block.border_contrast.svelte-239wnu{border-color:var(--body-text-color)}.padded.svelte-239wnu{padding:var(--block-padding)}.hidden.svelte-239wnu{display:none}.flex.svelte-239wnu{display:flex;flex-direction:column}.hide-container.svelte-239wnu:not(.fullscreen){margin:0;box-shadow:none;--block-border-width:0;background:transparent;padding:0;overflow:visible}.resize-handle.svelte-239wnu{position:absolute;bottom:0;right:0;width:10px;height:10px;fill:var(--block-border-color);cursor:nwse-resize}.fullscreen.svelte-239wnu{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:1000;overflow:auto}.animating.svelte-239wnu{animation:svelte-239wnu-pop-out .1s ease-out forwards}@keyframes svelte-239wnu-pop-out{0%{position:fixed;top:var(--start-top);left:var(--start-left);width:var(--start-width);height:var(--start-height);z-index:100}to{position:fixed;top:0vh;left:0vw;width:100vw;height:100vh;z-index:1000}}.placeholder.svelte-239wnu{border-radius:var(--block-radius);border-width:var(--block-border-width);border-color:var(--block-border-color);border-style:dashed}Tables */ table,tr,td,th{margin-top:var(--spacing-sm);margin-bottom:var(--spacing-sm);padding:var(--spacing-xl)}.md code,.md pre{background:none;font-family:var(--font-mono);font-size:var(--text-sm);text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:2;tab-size:2;-webkit-hyphens:none;hyphens:none}.md pre[class*=language-]::selection,.md pre[class*=language-] ::selection,.md code[class*=language-]::selection,.md code[class*=language-] ::selection{text-shadow:none;background:#b3d4fc}.md pre{padding:1em;margin:.5em 0;overflow:auto;position:relative;margin-top:var(--spacing-sm);margin-bottom:var(--spacing-sm);box-shadow:none;border:none;border-radius:var(--radius-md);background:var(--code-background-fill);padding:var(--spacing-xxl);font-family:var(--font-mono);text-shadow:none;border-radius:var(--radius-sm);white-space:nowrap;display:block;white-space:pre}.md :not(pre)>code{padding:.1em;border-radius:var(--radius-xs);white-space:normal;background:var(--code-background-fill);border:1px solid var(--panel-border-color);padding:var(--spacing-xxs) var(--spacing-xs)}.md .token.comment,.md .token.prolog,.md .token.doctype,.md .token.cdata{color:#708090}.md .token.punctuation{color:#999}.md .token.namespace{opacity:.7}.md .token.property,.md .token.tag,.md .token.boolean,.md .token.number,.md .token.constant,.md .token.symbol,.md .token.deleted{color:#905}.md .token.selector,.md .token.attr-name,.md .token.string,.md .token.char,.md .token.builtin,.md .token.inserted{color:#690}.md .token.atrule,.md .token.attr-value,.md .token.keyword{color:#07a}.md .token.function,.md .token.class-name{color:#dd4a68}.md .token.regex,.md .token.important,.md .token.variable{color:#e90}.md .token.important,.md .token.bold{font-weight:700}.md .token.italic{font-style:italic}.md .token.entity{cursor:help}.dark .md .token.comment,.dark .md .token.prolog,.dark .md .token.cdata{color:#5c6370}.dark .md .token.doctype,.dark .md .token.punctuation,.dark .md .token.entity{color:#abb2bf}.dark .md .token.attr-name,.dark .md .token.class-name,.dark .md .token.boolean,.dark .md .token.constant,.dark .md .token.number,.dark .md .token.atrule{color:#d19a66}.dark .md .token.keyword{color:#c678dd}.dark .md .token.property,.dark .md .token.tag,.dark .md .token.symbol,.dark .md .token.deleted,.dark .md .token.important{color:#e06c75}.dark .md .token.selector,.dark .md .token.string,.dark .md .token.char,.dark .md .token.builtin,.dark .md .token.inserted,.dark .md .token.regex,.dark .md .token.attr-value,.dark .md .token.attr-value>.token.punctuation{color:#98c379}.dark .md .token.variable,.dark .md .token.operator,.dark .md .token.function{color:#61afef}.dark .md .token.url{color:#56b6c2}span.svelte-1m32c2s div[class*=code_wrap]{position:relative}span.svelte-1m32c2s span.katex{font-size:var(--text-lg);direction:ltr}span.svelte-1m32c2s div[class*=code_wrap]>button{z-index:1;cursor:pointer;border-bottom-left-radius:var(--radius-sm);padding:var(--spacing-md);width:25px;height:25px;position:absolute;right:0}span.svelte-1m32c2s .check{opacity:0;z-index:var(--layer-top);transition:opacity .2s;background:var(--code-background-fill);color:var(--body-text-color);position:absolute;top:var(--size-1-5);left:var(--size-1-5)}span.svelte-1m32c2s p:not(:first-child){margin-top:var(--spacing-xxl)}span.svelte-1m32c2s .md-header-anchor{margin-left:-25px;padding-right:8px;line-height:1;color:var(--body-text-color-subdued);opacity:0}span.svelte-1m32c2s h1:hover .md-header-anchor,span.svelte-1m32c2s h2:hover .md-header-anchor,span.svelte-1m32c2s h3:hover .md-header-anchor,span.svelte-1m32c2s h4:hover .md-header-anchor,span.svelte-1m32c2s h5:hover .md-header-anchor,span.svelte-1m32c2s h6:hover .md-header-anchor{opacity:1}span.md.svelte-1m32c2s .md-header-anchor>svg{color:var(--body-text-color-subdued)}span.svelte-1m32c2s table{word-break:break-word}div.svelte-17qq50w>.md.prose{font-weight:var(--block-info-text-weight);font-size:var(--block-info-text-size);line-height:var(--line-sm)}div.svelte-17qq50w>.md.prose *{color:var(--block-info-text-color)}div.svelte-17qq50w{margin-bottom:var(--spacing-md)}span.has-info.svelte-zgrq3{margin-bottom:var(--spacing-xs)}span.svelte-zgrq3:not(.has-info){margin-bottom:var(--spacing-lg)}span.svelte-zgrq3{display:inline-block;position:relative;z-index:var(--layer-4);border:solid var(--block-title-border-width) var(--block-title-border-color);border-radius:var(--block-title-radius);background:var(--block-title-background-fill);padding:var(--block-title-padding);color:var(--block-title-text-color);font-weight:var(--block-title-text-weight);font-size:var(--block-title-text-size);line-height:var(--line-sm)}span[dir=rtl].svelte-zgrq3{display:block}.hide.svelte-zgrq3{margin:0;height:0}label.svelte-13ao5pu.svelte-13ao5pu{display:inline-flex;align-items:center;z-index:var(--layer-2);box-shadow:var(--block-label-shadow);border:var(--block-label-border-width) solid var(--block-label-border-color);border-top:none;border-left:none;border-radius:var(--block-label-radius);background:var(--block-label-background-fill);padding:var(--block-label-padding);pointer-events:none;color:var(--block-label-text-color);font-weight:var(--block-label-text-weight);font-size:var(--block-label-text-size);line-height:var(--line-sm)}.gr-group label.svelte-13ao5pu.svelte-13ao5pu{border-top-left-radius:0}label.float.svelte-13ao5pu.svelte-13ao5pu{position:absolute;top:var(--block-label-margin);left:var(--block-label-margin)}label.svelte-13ao5pu.svelte-13ao5pu:not(.float){position:static;margin-top:var(--block-label-margin);margin-left:var(--block-label-margin)}.hide.svelte-13ao5pu.svelte-13ao5pu{height:0}span.svelte-13ao5pu.svelte-13ao5pu{opacity:.8;margin-right:var(--size-2);width:calc(var(--block-label-text-size) - 1px);height:calc(var(--block-label-text-size) - 1px)}.hide-label.svelte-13ao5pu.svelte-13ao5pu{box-shadow:none;border-width:0;background:transparent;overflow:visible}label[dir=rtl].svelte-13ao5pu.svelte-13ao5pu{border:var(--block-label-border-width) solid var(--block-label-border-color);border-top:none;border-right:none;border-bottom-left-radius:var(--block-radius);border-bottom-right-radius:var(--block-label-radius);border-top-left-radius:var(--block-label-radius)}label[dir=rtl].svelte-13ao5pu span.svelte-13ao5pu{margin-left:var(--size-2);margin-right:0}button.svelte-qgco6m{display:flex;justify-content:center;align-items:center;gap:1px;z-index:var(--layer-2);border-radius:var(--radius-xs);color:var(--block-label-text-color);border:1px solid transparent;padding:var(--spacing-xxs)}button.svelte-qgco6m:hover{background-color:var(--background-fill-secondary)}button[disabled].svelte-qgco6m{opacity:.5;box-shadow:none}button[disabled].svelte-qgco6m:hover{cursor:not-allowed}.padded.svelte-qgco6m{background:var(--bg-color)}button.svelte-qgco6m:hover,button.highlight.svelte-qgco6m{cursor:pointer;color:var(--color-accent)}.padded.svelte-qgco6m:hover{color:var(--block-label-text-color)}span.svelte-qgco6m{padding:0 1px;font-size:10px}div.svelte-qgco6m{display:flex;align-items:center;justify-content:center;transition:filter .2s ease-in-out}.x-small.svelte-qgco6m{width:10px;height:10px}.small.svelte-qgco6m{width:14px;height:14px}.medium.svelte-qgco6m{width:20px;height:20px}.large.svelte-qgco6m{width:22px;height:22px}.pending.svelte-qgco6m{animation:svelte-qgco6m-flash .5s infinite}@keyframes svelte-qgco6m-flash{0%{opacity:.5}50%{opacity:1}to{opacity:.5}}.transparent.svelte-qgco6m{background:transparent;border:none;box-shadow:none}.empty.svelte-3w3rth{display:flex;justify-content:center;align-items:center;margin-top:calc(0px - var(--size-6));height:var(--size-full)}.icon.svelte-3w3rth{opacity:.5;height:var(--size-5);color:var(--body-text-color)}.small.svelte-3w3rth{min-height:calc(var(--size-32) - 20px)}.large.svelte-3w3rth{min-height:calc(var(--size-64) - 20px)}.unpadded_box.svelte-3w3rth{margin-top:0}.small_parent.svelte-3w3rth{min-height:100%!important}.dropdown-arrow.svelte-145leq6,.dropdown-arrow.svelte-ihhdbf{fill:currentColor}.circle.svelte-ihhdbf{fill:currentColor;opacity:.1}svg.svelte-pb9pol{animation:svelte-pb9pol-spin 1.5s linear infinite}@keyframes svelte-pb9pol-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}h2.svelte-1xg7h5n{font-size:var(--text-xl)!important}p.svelte-1xg7h5n,h2.svelte-1xg7h5n{white-space:pre-line}.wrap.svelte-1xg7h5n{display:flex;flex-direction:column;justify-content:center;align-items:center;min-height:var(--size-60);color:var(--block-label-text-color);line-height:var(--line-md);height:100%;padding-top:var(--size-3);text-align:center;margin:auto var(--spacing-lg)}.or.svelte-1xg7h5n{color:var(--body-text-color-subdued);display:flex}.icon-wrap.svelte-1xg7h5n{width:30px;margin-bottom:var(--spacing-lg)}@media (--screen-md){.wrap.svelte-1xg7h5n{font-size:var(--text-lg)}}.hovered.svelte-1xg7h5n{color:var(--color-accent)}div.svelte-q32hvf{border-top:1px solid transparent;display:flex;max-height:100%;justify-content:center;align-items:center;gap:var(--spacing-sm);height:auto;align-items:flex-end;color:var(--block-label-text-color);flex-shrink:0}.show_border.svelte-q32hvf{border-top:1px solid var(--block-border-color);margin-top:var(--spacing-xxl);box-shadow:var(--shadow-drop)}.source-selection.svelte-15ls1gu{display:flex;align-items:center;justify-content:center;border-top:1px solid var(--border-color-primary);width:100%;margin-left:auto;margin-right:auto;height:var(--size-10)}.icon.svelte-15ls1gu{width:22px;height:22px;margin:var(--spacing-lg) var(--spacing-xs);padding:var(--spacing-xs);color:var(--neutral-400);border-radius:var(--radius-md)}.selected.svelte-15ls1gu{color:var(--color-accent)}.icon.svelte-15ls1gu:hover,.icon.svelte-15ls1gu:focus{color:var(--color-accent)}.icon-button-wrapper.svelte-1h0hs6p{display:flex;flex-direction:row;align-items:center;justify-content:center;z-index:var(--layer-2);gap:var(--spacing-sm);box-shadow:var(--shadow-drop);border:1px solid var(--border-color-primary);background:var(--block-background-fill);padding:var(--spacing-xxs)}.icon-button-wrapper.hide-top-corner.svelte-1h0hs6p{border-top:none;border-right:none;border-radius:var(--block-label-right-radius)}.icon-button-wrapper.display-top-corner.svelte-1h0hs6p{border-radius:var(--radius-sm) 0 0 var(--radius-sm);top:var(--spacing-sm);right:-1px}.icon-button-wrapper.svelte-1h0hs6p:not(.top-panel){border:1px solid var(--border-color-primary);border-radius:var(--radius-sm)}.top-panel.svelte-1h0hs6p{position:absolute;top:var(--block-label-margin);right:var(--block-label-margin);margin:0}.icon-button-wrapper.svelte-1h0hs6p button{margin:var(--spacing-xxs);border-radius:var(--radius-xs);position:relative}.icon-button-wrapper.svelte-1h0hs6p a.download-link:not(:last-child),.icon-button-wrapper.svelte-1h0hs6p button:not(:last-child){margin-right:var(--spacing-xxs)}.icon-button-wrapper.svelte-1h0hs6p a.download-link:not(:last-child):not(.no-border *):after,.icon-button-wrapper.svelte-1h0hs6p button:not(:last-child):not(.no-border *):after{content:"";position:absolute;right:-4.5px;top:15%;height:70%;width:1px;background-color:var(--border-color-primary)}.icon-button-wrapper.svelte-1h0hs6p>*{height:100%}svg.svelte-43sxxs.svelte-43sxxs{width:var(--size-20);height:var(--size-20)}svg.svelte-43sxxs path.svelte-43sxxs{fill:var(--loader-color)}div.svelte-43sxxs.svelte-43sxxs{z-index:var(--layer-2)}.margin.svelte-43sxxs.svelte-43sxxs{margin:var(--size-4)}.wrap.svelte-17v219f.svelte-17v219f{display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:var(--layer-2);transition:opacity .1s ease-in-out;border-radius:var(--block-radius);background:var(--block-background-fill);padding:0 var(--size-6);max-height:var(--size-screen-h);overflow:hidden}.wrap.center.svelte-17v219f.svelte-17v219f{top:0;right:0;left:0}.wrap.default.svelte-17v219f.svelte-17v219f{top:0;right:0;bottom:0;left:0}.hide.svelte-17v219f.svelte-17v219f{opacity:0;pointer-events:none}.generating.svelte-17v219f.svelte-17v219f{animation:svelte-17v219f-pulseStart 1s cubic-bezier(.4,0,.6,1),svelte-17v219f-pulse 2s cubic-bezier(.4,0,.6,1) 1s infinite;border:2px solid var(--color-accent);background:transparent;z-index:var(--layer-1);pointer-events:none}.translucent.svelte-17v219f.svelte-17v219f{background:none}@keyframes svelte-17v219f-pulseStart{0%{opacity:0}to{opacity:1}}@keyframes svelte-17v219f-pulse{0%,to{opacity:1}50%{opacity:.5}}.loading.svelte-17v219f.svelte-17v219f{z-index:var(--layer-2);color:var(--body-text-color)}.eta-bar.svelte-17v219f.svelte-17v219f{position:absolute;top:0;right:0;bottom:0;left:0;transform-origin:left;opacity:.8;z-index:var(--layer-1);transition:10ms;background:var(--background-fill-secondary)}.progress-bar-wrap.svelte-17v219f.svelte-17v219f{border:1px solid var(--border-color-primary);background:var(--background-fill-primary);width:55.5%;height:var(--size-4)}.progress-bar.svelte-17v219f.svelte-17v219f{transform-origin:left;background-color:var(--loader-color);width:var(--size-full);height:var(--size-full)}.progress-level.svelte-17v219f.svelte-17v219f{display:flex;flex-direction:column;align-items:center;gap:1;z-index:var(--layer-2);width:var(--size-full)}.progress-level-inner.svelte-17v219f.svelte-17v219f{margin:var(--size-2) auto;color:var(--body-text-color);font-size:var(--text-sm);font-family:var(--font-mono)}.meta-text.svelte-17v219f.svelte-17v219f{position:absolute;bottom:0;right:0;z-index:var(--layer-2);padding:var(--size-1) var(--size-2);font-size:var(--text-sm);font-family:var(--font-mono)}.meta-text-center.svelte-17v219f.svelte-17v219f{display:flex;position:absolute;top:0;right:0;justify-content:center;align-items:center;transform:translateY(var(--size-6));z-index:var(--layer-2);padding:var(--size-1) var(--size-2);font-size:var(--text-sm);font-family:var(--font-mono);text-align:center}.error.svelte-17v219f.svelte-17v219f{box-shadow:var(--shadow-drop);border:solid 1px var(--error-border-color);border-radius:var(--radius-full);background:var(--error-background-fill);padding-right:var(--size-4);padding-left:var(--size-4);color:var(--error-text-color);font-weight:var(--weight-semibold);font-size:var(--text-lg);line-height:var(--line-lg);font-family:var(--font)}.minimal.svelte-17v219f.svelte-17v219f{pointer-events:none}.minimal.svelte-17v219f .progress-text.svelte-17v219f{background:var(--block-background-fill)}.border.svelte-17v219f.svelte-17v219f{border:1px solid var(--border-color-primary)}.clear-status.svelte-17v219f.svelte-17v219f{position:absolute;display:flex;top:var(--size-2);right:var(--size-2);justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-1)}.toast-body.svelte-syezpc{display:flex;position:relative;right:0;left:0;align-items:center;margin:var(--size-6) var(--size-4);margin:auto;border-radius:var(--container-radius);overflow:hidden;pointer-events:auto}.toast-body.error.svelte-syezpc{border:1px solid var(--color-red-700);background:var(--color-red-50)}.dark .toast-body.error.svelte-syezpc{border:1px solid var(--color-red-500);background-color:var(--color-grey-950)}.toast-body.warning.svelte-syezpc{border:1px solid var(--color-yellow-700);background:var(--color-yellow-50)}.dark .toast-body.warning.svelte-syezpc{border:1px solid var(--color-yellow-500);background-color:var(--color-grey-950)}.toast-body.info.svelte-syezpc{border:1px solid var(--color-grey-700);background:var(--color-grey-50)}.dark .toast-body.info.svelte-syezpc{border:1px solid var(--color-grey-500);background-color:var(--color-grey-950)}.toast-body.success.svelte-syezpc{border:1px solid var(--color-green-700);background:var(--color-green-50)}.dark .toast-body.success.svelte-syezpc{border:1px solid var(--color-green-500);background-color:var(--color-grey-950)}.toast-title.svelte-syezpc{display:flex;align-items:center;font-weight:var(--weight-bold);font-size:var(--text-lg);line-height:var(--line-sm)}.toast-title.error.svelte-syezpc{color:var(--color-red-700)}.dark .toast-title.error.svelte-syezpc{color:var(--color-red-50)}.toast-title.warning.svelte-syezpc{color:var(--color-yellow-700)}.dark .toast-title.warning.svelte-syezpc{color:var(--color-yellow-50)}.toast-title.info.svelte-syezpc{color:var(--color-grey-700)}.dark .toast-title.info.svelte-syezpc{color:var(--color-grey-50)}.toast-title.success.svelte-syezpc{color:var(--color-green-700)}.dark .toast-title.success.svelte-syezpc{color:var(--color-green-50)}.toast-close.svelte-syezpc{margin:0 var(--size-3);border-radius:var(--size-3);padding:0px var(--size-1-5);font-size:var(--size-5);line-height:var(--size-5)}.toast-close.error.svelte-syezpc{color:var(--color-red-700)}.dark .toast-close.error.svelte-syezpc{color:var(--color-red-500)}.toast-close.warning.svelte-syezpc{color:var(--color-yellow-700)}.dark .toast-close.warning.svelte-syezpc{color:var(--color-yellow-500)}.toast-close.info.svelte-syezpc{color:var(--color-grey-700)}.dark .toast-close.info.svelte-syezpc{color:var(--color-grey-500)}.toast-close.success.svelte-syezpc{color:var(--color-green-700)}.dark .toast-close.success.svelte-syezpc{color:var(--color-green-500)}.toast-text.svelte-syezpc{font-size:var(--text-lg);word-wrap:break-word;overflow-wrap:break-word;word-break:break-word}.toast-text.error.svelte-syezpc{color:var(--color-red-700)}.dark .toast-text.error.svelte-syezpc{color:var(--color-red-50)}.toast-text.warning.svelte-syezpc{color:var(--color-yellow-700)}.dark .toast-text.warning.svelte-syezpc{color:var(--color-yellow-50)}.toast-text.info.svelte-syezpc{color:var(--color-grey-700)}.dark .toast-text.info.svelte-syezpc{color:var(--color-grey-50)}.toast-text.success.svelte-syezpc{color:var(--color-green-700)}.dark .toast-text.success.svelte-syezpc{color:var(--color-green-50)}.toast-details.svelte-syezpc{margin:var(--size-3) var(--size-3) var(--size-3) 0;width:100%}.toast-icon.svelte-syezpc{display:flex;position:absolute;position:relative;flex-shrink:0;justify-content:center;align-items:center;margin:var(--size-2);border-radius:var(--radius-full);padding:var(--size-1);padding-left:calc(var(--size-1) - 1px);width:35px;height:35px}.toast-icon.error.svelte-syezpc{color:var(--color-red-700)}.dark .toast-icon.error.svelte-syezpc{color:var(--color-red-500)}.toast-icon.warning.svelte-syezpc{color:var(--color-yellow-700)}.dark .toast-icon.warning.svelte-syezpc{color:var(--color-yellow-500)}.toast-icon.info.svelte-syezpc{color:var(--color-grey-700)}.dark .toast-icon.info.svelte-syezpc{color:var(--color-grey-500)}.toast-icon.success.svelte-syezpc{color:var(--color-green-700)}.dark .toast-icon.success.svelte-syezpc{color:var(--color-green-500)}@keyframes svelte-syezpc-countdown{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.timer.svelte-syezpc{position:absolute;bottom:0;left:0;transform-origin:0 0;animation:svelte-syezpc-countdown 10s linear forwards;width:100%;height:var(--size-1)}.timer.error.svelte-syezpc{background:var(--color-red-700)}.dark .timer.error.svelte-syezpc{background:var(--color-red-500)}.timer.warning.svelte-syezpc{background:var(--color-yellow-700)}.dark .timer.warning.svelte-syezpc{background:var(--color-yellow-500)}.timer.info.svelte-syezpc{background:var(--color-grey-700)}.dark .timer.info.svelte-syezpc{background:var(--color-grey-500)}.timer.success.svelte-syezpc{background:var(--color-green-700)}.dark .timer.success.svelte-syezpc{background:var(--color-green-500)}.hidden.svelte-syezpc{display:none}.toast-text.svelte-syezpc a{text-decoration:underline}.toast-wrap.svelte-gatr8h{display:flex;position:fixed;top:var(--size-4);right:var(--size-4);flex-direction:column;align-items:end;gap:var(--size-2);z-index:var(--layer-top);width:calc(100% - var(--size-8))}@media (--screen-sm){.toast-wrap.svelte-gatr8h{width:calc(var(--size-96) + var(--size-10))}}.streaming-bar.svelte-ga0jj6{position:absolute;bottom:0;left:0;right:0;height:4px;background-color:var(--primary-600);animation:svelte-ga0jj6-countdown linear forwards;z-index:1}@keyframes svelte-ga0jj6-countdown{0%{transform:translate(0)}to{transform:translate(-100%)}}.wrapper.svelte-1t8lt48.svelte-1t8lt48{width:100%;height:100%;overflow:hidden;position:relative;font-family:sans-serif}.credits-container.svelte-1t8lt48.svelte-1t8lt48{position:absolute;bottom:0;transform:translateY(100%);width:100%;text-align:center;animation:svelte-1t8lt48-scroll var(--animation-duration) linear infinite;padding:0 2rem;box-sizing:border-box}.section-title.svelte-1t8lt48.svelte-1t8lt48{margin-top:4rem;margin-bottom:2.5rem;font-weight:700}.credit.intro-block.svelte-1t8lt48.svelte-1t8lt48{margin-bottom:5rem}.credit.svelte-1t8lt48.svelte-1t8lt48{margin-bottom:2rem}.credit.svelte-1t8lt48 h2.svelte-1t8lt48,.credit.svelte-1t8lt48 p.svelte-1t8lt48{margin:.5rem 0;font-family:sans-serif}.credit-two-column.svelte-1t8lt48.svelte-1t8lt48{display:flex;justify-content:space-between;align-items:baseline;text-align:left;margin:.8rem auto;max-width:80%;gap:1rem}.credit-two-column.svelte-1t8lt48 .title.svelte-1t8lt48{flex:1;text-align:right;padding-right:1rem}.credit-two-column.svelte-1t8lt48 .name.svelte-1t8lt48{flex:1;text-align:left;padding-left:1rem}.uppercase.svelte-1t8lt48.svelte-1t8lt48{text-transform:uppercase}@keyframes svelte-1t8lt48-scroll{0%{transform:translateY(100%)}to{transform:translateY(-100%)}}.viewport.svelte-upsott.svelte-upsott{width:100%;height:100%;position:relative;overflow:hidden;perspective:400px;-webkit-mask-image:linear-gradient(to bottom,black 60%,transparent 100%);mask-image:linear-gradient(to bottom,black 60%,transparent 100%);font-family:Droid Sans,sans-serif;font-weight:700}.stars.svelte-upsott.svelte-upsott{position:absolute;top:0;left:0;width:1px;height:1px;background:transparent;z-index:0;animation:svelte-upsott-twinkle 10s linear infinite}.stars.small.svelte-upsott.svelte-upsott{animation-duration:10s}.stars.medium.svelte-upsott.svelte-upsott{animation-duration:15s}.stars.large.svelte-upsott.svelte-upsott{animation-duration:20s}@keyframes svelte-upsott-twinkle{0%{opacity:.6}50%{opacity:1}to{opacity:.6}}.crawl.svelte-upsott.svelte-upsott{position:absolute;width:100%;bottom:0;transform-origin:50% 100%;animation:svelte-upsott-crawl-animation var(--animation-duration) linear infinite;z-index:1;text-align:center}@keyframes svelte-upsott-crawl-animation{0%{transform:rotateX(60deg) translateY(100%) translateZ(100px)}to{transform:rotateX(60deg) translateY(-150%) translateZ(-1200px)}}.uppercase.svelte-upsott.svelte-upsott{text-transform:uppercase}.section-title.svelte-upsott.svelte-upsott{margin-top:5rem;margin-bottom:3rem;font-weight:700}.credit.intro-block.svelte-upsott.svelte-upsott{margin-bottom:5rem}.credit.svelte-upsott.svelte-upsott{margin-bottom:2rem}.credit.svelte-upsott h2.svelte-upsott,.credit.svelte-upsott p.svelte-upsott{margin:.5rem 0;padding:0;white-space:nowrap}.credit-two-column.svelte-upsott.svelte-upsott{display:flex;justify-content:space-between;align-items:baseline;margin:.8rem auto;width:90%;white-space:nowrap}.credit-two-column.svelte-upsott .spacer.svelte-upsott{flex-grow:1;border-bottom:1px dotted rgba(254,218,74,.3);margin:0 1em;transform:translateY(-.5em)}.matrix-container.svelte-1851m15.svelte-1851m15{width:100%;height:100%;position:relative;overflow:hidden}canvas.svelte-1851m15.svelte-1851m15{display:block;position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.credits-scroll-overlay.svelte-1851m15.svelte-1851m15{position:absolute;top:0;left:0;width:100%;height:100%;z-index:2;color:#fff;font-family:monospace;text-align:center;-webkit-mask-image:linear-gradient(transparent,black 20%,black 80%,transparent);mask-image:linear-gradient(transparent,black 20%,black 80%,transparent)}.credits-content.svelte-1851m15.svelte-1851m15{position:absolute;width:100%;bottom:0;transform:translateY(100%);animation:svelte-1851m15-scroll-from-bottom var(--animation-duration) linear infinite;padding:0 2rem;box-sizing:border-box}@keyframes svelte-1851m15-scroll-from-bottom{0%{transform:translateY(100%)}to{transform:translateY(-100%)}}.uppercase.svelte-1851m15.svelte-1851m15{text-transform:uppercase}.section-title.svelte-1851m15.svelte-1851m15{margin-top:4rem;margin-bottom:2.5rem;font-weight:700;color:#5f5;text-shadow:0 0 8px #0f0}.credit-block.intro-block.svelte-1851m15.svelte-1851m15{margin-bottom:5rem}.credit-block.svelte-1851m15.svelte-1851m15{margin-bottom:2.5em}.title.svelte-1851m15.svelte-1851m15{color:#0f0;opacity:.8}.name.svelte-1851m15.svelte-1851m15{font-weight:700;color:#5f5;text-shadow:0 0 5px #0f0}.credit-two-column.svelte-1851m15.svelte-1851m15{display:flex;justify-content:space-between;align-items:baseline;text-align:left;margin:.8em auto;max-width:80%;gap:1em}.credit-two-column.svelte-1851m15 .title.svelte-1851m15{flex:1;text-align:right;padding-right:1em}.credit-two-column.svelte-1851m15 .name.svelte-1851m15{flex:1;text-align:left;padding-left:1em}.unstyled-link.svelte-151nsdd{all:unset;cursor:pointer}img.svelte-kxeri3{object-fit:cover}.image-container.svelte-x2tujq.svelte-x2tujq{height:100%;position:relative;min-width:var(--size-20)}.image-container.svelte-x2tujq button.svelte-x2tujq{width:var(--size-full);height:var(--size-full);border-radius:var(--radius-lg);display:flex;align-items:center;justify-content:center}.image-frame.svelte-x2tujq img{width:var(--size-full);height:var(--size-full);object-fit:scale-down}.selectable.svelte-x2tujq.svelte-x2tujq{cursor:crosshair}.fullscreen-controls svg{position:relative;top:0}.image-container:fullscreen{background-color:#000;display:flex;justify-content:center;align-items:center}.image-container:fullscreen img{max-width:90vw;max-height:90vh;object-fit:scale-down}.image-frame.svelte-x2tujq.svelte-x2tujq{width:auto;height:100%;display:flex;align-items:center;justify-content:center}.block{border:none!important;box-shadow:none!important;border-style:none!important}.outer-logo-wrapper.svelte-1hawtr7.svelte-1hawtr7,.outer-credits-wrapper.svelte-1hawtr7.svelte-1hawtr7{display:flex;flex-direction:column;width:100%;border:none}.logo-panel.svelte-1hawtr7.svelte-1hawtr7{background:var(--background-fill-primary);border:none;display:flex!important;align-items:center;justify-content:var(--logo-justify, center);padding:0 0 20px;width:100%}.credits-panel-wrapper.svelte-1hawtr7.svelte-1hawtr7{display:flex;flex-direction:var(--panel-direction, row);min-height:var(--size-full, 500px);width:100%;background:var(--background-fill-primary);border:1px solid var(--border-color-primary);border-radius:var(--radius-lg);overflow:hidden}.main-credits-panel.svelte-1hawtr7.svelte-1hawtr7{flex-grow:1;flex-shrink:1;min-width:200px;background:#000;overflow:hidden;position:relative}.licenses-sidebar.svelte-1hawtr7.svelte-1hawtr7{width:calc(100% - var(--main-panel-width, 400px));max-width:100%;max-height:var(--sidebar-max-height, none);flex-shrink:1;flex-grow:1;background:var(--background-fill-secondary);overflow-y:auto;border-left:var(--border-left, 1px solid var(--border-color-primary));border-top:var(--border-top, none)}.licenses-sidebar.svelte-1hawtr7 h3.svelte-1hawtr7{margin:var(--spacing-lg);font-size:var(--text-lg)}.licenses-sidebar.svelte-1hawtr7 li.svelte-1hawtr7{padding:0;margin:0;cursor:default;border-bottom:1px solid var(--border-color-primary)}.licenses-sidebar.svelte-1hawtr7 li button.svelte-1hawtr7{background:none;border:none;font:inherit;color:inherit;text-align:left;width:100%;cursor:pointer;padding:var(--spacing-md) var(--spacing-lg);transition:background-color .2s}.licenses-sidebar.svelte-1hawtr7 li button.svelte-1hawtr7:hover{background-color:var(--background-fill-primary)}.licenses-sidebar.svelte-1hawtr7 li button.svelte-1hawtr7:focus-visible{outline:2px solid var(--color-accent);outline-offset:-2px}.licenses-sidebar.svelte-1hawtr7 li button.selected.svelte-1hawtr7{background-color:var(--color-accent);color:#fff;font-weight:700}.license-display.svelte-1hawtr7.svelte-1hawtr7{padding:var(--spacing-lg);overflow-y:auto;flex-grow:1;border-top:1px solid var(--border-color-primary);background:var(--background-fill-primary)}.license-display.svelte-1hawtr7 h4.svelte-1hawtr7{margin-top:0}.license-display.svelte-1hawtr7 pre.svelte-1hawtr7{white-space:pre-wrap;word-break:break-word;font-size:var(--text-sm);color:var(--body-text-color-subdued)}
|
|
|
1 |
+
.block.svelte-239wnu{position:relative;margin:0;box-shadow:var(--block-shadow);border-width:var(--block-border-width);border-color:var(--block-border-color);border-radius:var(--block-radius);background:var(--block-background-fill);width:100%;line-height:var(--line-sm)}.block.fullscreen.svelte-239wnu{border-radius:0}.auto-margin.svelte-239wnu{margin-left:auto;margin-right:auto}.block.border_focus.svelte-239wnu{border-color:var(--color-accent)}.block.border_contrast.svelte-239wnu{border-color:var(--body-text-color)}.padded.svelte-239wnu{padding:var(--block-padding)}.hidden.svelte-239wnu{display:none}.flex.svelte-239wnu{display:flex;flex-direction:column}.hide-container.svelte-239wnu:not(.fullscreen){margin:0;box-shadow:none;--block-border-width:0;background:transparent;padding:0;overflow:visible}.resize-handle.svelte-239wnu{position:absolute;bottom:0;right:0;width:10px;height:10px;fill:var(--block-border-color);cursor:nwse-resize}.fullscreen.svelte-239wnu{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:1000;overflow:auto}.animating.svelte-239wnu{animation:svelte-239wnu-pop-out .1s ease-out forwards}@keyframes svelte-239wnu-pop-out{0%{position:fixed;top:var(--start-top);left:var(--start-left);width:var(--start-width);height:var(--start-height);z-index:100}to{position:fixed;top:0vh;left:0vw;width:100vw;height:100vh;z-index:1000}}.placeholder.svelte-239wnu{border-radius:var(--block-radius);border-width:var(--block-border-width);border-color:var(--block-border-color);border-style:dashed}Tables */ table,tr,td,th{margin-top:var(--spacing-sm);margin-bottom:var(--spacing-sm);padding:var(--spacing-xl)}.md code,.md pre{background:none;font-family:var(--font-mono);font-size:var(--text-sm);text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:2;tab-size:2;-webkit-hyphens:none;hyphens:none}.md pre[class*=language-]::selection,.md pre[class*=language-] ::selection,.md code[class*=language-]::selection,.md code[class*=language-] ::selection{text-shadow:none;background:#b3d4fc}.md pre{padding:1em;margin:.5em 0;overflow:auto;position:relative;margin-top:var(--spacing-sm);margin-bottom:var(--spacing-sm);box-shadow:none;border:none;border-radius:var(--radius-md);background:var(--code-background-fill);padding:var(--spacing-xxl);font-family:var(--font-mono);text-shadow:none;border-radius:var(--radius-sm);white-space:nowrap;display:block;white-space:pre}.md :not(pre)>code{padding:.1em;border-radius:var(--radius-xs);white-space:normal;background:var(--code-background-fill);border:1px solid var(--panel-border-color);padding:var(--spacing-xxs) var(--spacing-xs)}.md .token.comment,.md .token.prolog,.md .token.doctype,.md .token.cdata{color:#708090}.md .token.punctuation{color:#999}.md .token.namespace{opacity:.7}.md .token.property,.md .token.tag,.md .token.boolean,.md .token.number,.md .token.constant,.md .token.symbol,.md .token.deleted{color:#905}.md .token.selector,.md .token.attr-name,.md .token.string,.md .token.char,.md .token.builtin,.md .token.inserted{color:#690}.md .token.atrule,.md .token.attr-value,.md .token.keyword{color:#07a}.md .token.function,.md .token.class-name{color:#dd4a68}.md .token.regex,.md .token.important,.md .token.variable{color:#e90}.md .token.important,.md .token.bold{font-weight:700}.md .token.italic{font-style:italic}.md .token.entity{cursor:help}.dark .md .token.comment,.dark .md .token.prolog,.dark .md .token.cdata{color:#5c6370}.dark .md .token.doctype,.dark .md .token.punctuation,.dark .md .token.entity{color:#abb2bf}.dark .md .token.attr-name,.dark .md .token.class-name,.dark .md .token.boolean,.dark .md .token.constant,.dark .md .token.number,.dark .md .token.atrule{color:#d19a66}.dark .md .token.keyword{color:#c678dd}.dark .md .token.property,.dark .md .token.tag,.dark .md .token.symbol,.dark .md .token.deleted,.dark .md .token.important{color:#e06c75}.dark .md .token.selector,.dark .md .token.string,.dark .md .token.char,.dark .md .token.builtin,.dark .md .token.inserted,.dark .md .token.regex,.dark .md .token.attr-value,.dark .md .token.attr-value>.token.punctuation{color:#98c379}.dark .md .token.variable,.dark .md .token.operator,.dark .md .token.function{color:#61afef}.dark .md .token.url{color:#56b6c2}span.svelte-1m32c2s div[class*=code_wrap]{position:relative}span.svelte-1m32c2s span.katex{font-size:var(--text-lg);direction:ltr}span.svelte-1m32c2s div[class*=code_wrap]>button{z-index:1;cursor:pointer;border-bottom-left-radius:var(--radius-sm);padding:var(--spacing-md);width:25px;height:25px;position:absolute;right:0}span.svelte-1m32c2s .check{opacity:0;z-index:var(--layer-top);transition:opacity .2s;background:var(--code-background-fill);color:var(--body-text-color);position:absolute;top:var(--size-1-5);left:var(--size-1-5)}span.svelte-1m32c2s p:not(:first-child){margin-top:var(--spacing-xxl)}span.svelte-1m32c2s .md-header-anchor{margin-left:-25px;padding-right:8px;line-height:1;color:var(--body-text-color-subdued);opacity:0}span.svelte-1m32c2s h1:hover .md-header-anchor,span.svelte-1m32c2s h2:hover .md-header-anchor,span.svelte-1m32c2s h3:hover .md-header-anchor,span.svelte-1m32c2s h4:hover .md-header-anchor,span.svelte-1m32c2s h5:hover .md-header-anchor,span.svelte-1m32c2s h6:hover .md-header-anchor{opacity:1}span.md.svelte-1m32c2s .md-header-anchor>svg{color:var(--body-text-color-subdued)}span.svelte-1m32c2s table{word-break:break-word}div.svelte-17qq50w>.md.prose{font-weight:var(--block-info-text-weight);font-size:var(--block-info-text-size);line-height:var(--line-sm)}div.svelte-17qq50w>.md.prose *{color:var(--block-info-text-color)}div.svelte-17qq50w{margin-bottom:var(--spacing-md)}span.has-info.svelte-zgrq3{margin-bottom:var(--spacing-xs)}span.svelte-zgrq3:not(.has-info){margin-bottom:var(--spacing-lg)}span.svelte-zgrq3{display:inline-block;position:relative;z-index:var(--layer-4);border:solid var(--block-title-border-width) var(--block-title-border-color);border-radius:var(--block-title-radius);background:var(--block-title-background-fill);padding:var(--block-title-padding);color:var(--block-title-text-color);font-weight:var(--block-title-text-weight);font-size:var(--block-title-text-size);line-height:var(--line-sm)}span[dir=rtl].svelte-zgrq3{display:block}.hide.svelte-zgrq3{margin:0;height:0}label.svelte-13ao5pu.svelte-13ao5pu{display:inline-flex;align-items:center;z-index:var(--layer-2);box-shadow:var(--block-label-shadow);border:var(--block-label-border-width) solid var(--block-label-border-color);border-top:none;border-left:none;border-radius:var(--block-label-radius);background:var(--block-label-background-fill);padding:var(--block-label-padding);pointer-events:none;color:var(--block-label-text-color);font-weight:var(--block-label-text-weight);font-size:var(--block-label-text-size);line-height:var(--line-sm)}.gr-group label.svelte-13ao5pu.svelte-13ao5pu{border-top-left-radius:0}label.float.svelte-13ao5pu.svelte-13ao5pu{position:absolute;top:var(--block-label-margin);left:var(--block-label-margin)}label.svelte-13ao5pu.svelte-13ao5pu:not(.float){position:static;margin-top:var(--block-label-margin);margin-left:var(--block-label-margin)}.hide.svelte-13ao5pu.svelte-13ao5pu{height:0}span.svelte-13ao5pu.svelte-13ao5pu{opacity:.8;margin-right:var(--size-2);width:calc(var(--block-label-text-size) - 1px);height:calc(var(--block-label-text-size) - 1px)}.hide-label.svelte-13ao5pu.svelte-13ao5pu{box-shadow:none;border-width:0;background:transparent;overflow:visible}label[dir=rtl].svelte-13ao5pu.svelte-13ao5pu{border:var(--block-label-border-width) solid var(--block-label-border-color);border-top:none;border-right:none;border-bottom-left-radius:var(--block-radius);border-bottom-right-radius:var(--block-label-radius);border-top-left-radius:var(--block-label-radius)}label[dir=rtl].svelte-13ao5pu span.svelte-13ao5pu{margin-left:var(--size-2);margin-right:0}button.svelte-qgco6m{display:flex;justify-content:center;align-items:center;gap:1px;z-index:var(--layer-2);border-radius:var(--radius-xs);color:var(--block-label-text-color);border:1px solid transparent;padding:var(--spacing-xxs)}button.svelte-qgco6m:hover{background-color:var(--background-fill-secondary)}button[disabled].svelte-qgco6m{opacity:.5;box-shadow:none}button[disabled].svelte-qgco6m:hover{cursor:not-allowed}.padded.svelte-qgco6m{background:var(--bg-color)}button.svelte-qgco6m:hover,button.highlight.svelte-qgco6m{cursor:pointer;color:var(--color-accent)}.padded.svelte-qgco6m:hover{color:var(--block-label-text-color)}span.svelte-qgco6m{padding:0 1px;font-size:10px}div.svelte-qgco6m{display:flex;align-items:center;justify-content:center;transition:filter .2s ease-in-out}.x-small.svelte-qgco6m{width:10px;height:10px}.small.svelte-qgco6m{width:14px;height:14px}.medium.svelte-qgco6m{width:20px;height:20px}.large.svelte-qgco6m{width:22px;height:22px}.pending.svelte-qgco6m{animation:svelte-qgco6m-flash .5s infinite}@keyframes svelte-qgco6m-flash{0%{opacity:.5}50%{opacity:1}to{opacity:.5}}.transparent.svelte-qgco6m{background:transparent;border:none;box-shadow:none}.empty.svelte-3w3rth{display:flex;justify-content:center;align-items:center;margin-top:calc(0px - var(--size-6));height:var(--size-full)}.icon.svelte-3w3rth{opacity:.5;height:var(--size-5);color:var(--body-text-color)}.small.svelte-3w3rth{min-height:calc(var(--size-32) - 20px)}.large.svelte-3w3rth{min-height:calc(var(--size-64) - 20px)}.unpadded_box.svelte-3w3rth{margin-top:0}.small_parent.svelte-3w3rth{min-height:100%!important}.dropdown-arrow.svelte-145leq6,.dropdown-arrow.svelte-ihhdbf{fill:currentColor}.circle.svelte-ihhdbf{fill:currentColor;opacity:.1}svg.svelte-pb9pol{animation:svelte-pb9pol-spin 1.5s linear infinite}@keyframes svelte-pb9pol-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}h2.svelte-1xg7h5n{font-size:var(--text-xl)!important}p.svelte-1xg7h5n,h2.svelte-1xg7h5n{white-space:pre-line}.wrap.svelte-1xg7h5n{display:flex;flex-direction:column;justify-content:center;align-items:center;min-height:var(--size-60);color:var(--block-label-text-color);line-height:var(--line-md);height:100%;padding-top:var(--size-3);text-align:center;margin:auto var(--spacing-lg)}.or.svelte-1xg7h5n{color:var(--body-text-color-subdued);display:flex}.icon-wrap.svelte-1xg7h5n{width:30px;margin-bottom:var(--spacing-lg)}@media (--screen-md){.wrap.svelte-1xg7h5n{font-size:var(--text-lg)}}.hovered.svelte-1xg7h5n{color:var(--color-accent)}div.svelte-q32hvf{border-top:1px solid transparent;display:flex;max-height:100%;justify-content:center;align-items:center;gap:var(--spacing-sm);height:auto;align-items:flex-end;color:var(--block-label-text-color);flex-shrink:0}.show_border.svelte-q32hvf{border-top:1px solid var(--block-border-color);margin-top:var(--spacing-xxl);box-shadow:var(--shadow-drop)}.source-selection.svelte-15ls1gu{display:flex;align-items:center;justify-content:center;border-top:1px solid var(--border-color-primary);width:100%;margin-left:auto;margin-right:auto;height:var(--size-10)}.icon.svelte-15ls1gu{width:22px;height:22px;margin:var(--spacing-lg) var(--spacing-xs);padding:var(--spacing-xs);color:var(--neutral-400);border-radius:var(--radius-md)}.selected.svelte-15ls1gu{color:var(--color-accent)}.icon.svelte-15ls1gu:hover,.icon.svelte-15ls1gu:focus{color:var(--color-accent)}.icon-button-wrapper.svelte-1h0hs6p{display:flex;flex-direction:row;align-items:center;justify-content:center;z-index:var(--layer-2);gap:var(--spacing-sm);box-shadow:var(--shadow-drop);border:1px solid var(--border-color-primary);background:var(--block-background-fill);padding:var(--spacing-xxs)}.icon-button-wrapper.hide-top-corner.svelte-1h0hs6p{border-top:none;border-right:none;border-radius:var(--block-label-right-radius)}.icon-button-wrapper.display-top-corner.svelte-1h0hs6p{border-radius:var(--radius-sm) 0 0 var(--radius-sm);top:var(--spacing-sm);right:-1px}.icon-button-wrapper.svelte-1h0hs6p:not(.top-panel){border:1px solid var(--border-color-primary);border-radius:var(--radius-sm)}.top-panel.svelte-1h0hs6p{position:absolute;top:var(--block-label-margin);right:var(--block-label-margin);margin:0}.icon-button-wrapper.svelte-1h0hs6p button{margin:var(--spacing-xxs);border-radius:var(--radius-xs);position:relative}.icon-button-wrapper.svelte-1h0hs6p a.download-link:not(:last-child),.icon-button-wrapper.svelte-1h0hs6p button:not(:last-child){margin-right:var(--spacing-xxs)}.icon-button-wrapper.svelte-1h0hs6p a.download-link:not(:last-child):not(.no-border *):after,.icon-button-wrapper.svelte-1h0hs6p button:not(:last-child):not(.no-border *):after{content:"";position:absolute;right:-4.5px;top:15%;height:70%;width:1px;background-color:var(--border-color-primary)}.icon-button-wrapper.svelte-1h0hs6p>*{height:100%}svg.svelte-43sxxs.svelte-43sxxs{width:var(--size-20);height:var(--size-20)}svg.svelte-43sxxs path.svelte-43sxxs{fill:var(--loader-color)}div.svelte-43sxxs.svelte-43sxxs{z-index:var(--layer-2)}.margin.svelte-43sxxs.svelte-43sxxs{margin:var(--size-4)}.wrap.svelte-17v219f.svelte-17v219f{display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:var(--layer-2);transition:opacity .1s ease-in-out;border-radius:var(--block-radius);background:var(--block-background-fill);padding:0 var(--size-6);max-height:var(--size-screen-h);overflow:hidden}.wrap.center.svelte-17v219f.svelte-17v219f{top:0;right:0;left:0}.wrap.default.svelte-17v219f.svelte-17v219f{top:0;right:0;bottom:0;left:0}.hide.svelte-17v219f.svelte-17v219f{opacity:0;pointer-events:none}.generating.svelte-17v219f.svelte-17v219f{animation:svelte-17v219f-pulseStart 1s cubic-bezier(.4,0,.6,1),svelte-17v219f-pulse 2s cubic-bezier(.4,0,.6,1) 1s infinite;border:2px solid var(--color-accent);background:transparent;z-index:var(--layer-1);pointer-events:none}.translucent.svelte-17v219f.svelte-17v219f{background:none}@keyframes svelte-17v219f-pulseStart{0%{opacity:0}to{opacity:1}}@keyframes svelte-17v219f-pulse{0%,to{opacity:1}50%{opacity:.5}}.loading.svelte-17v219f.svelte-17v219f{z-index:var(--layer-2);color:var(--body-text-color)}.eta-bar.svelte-17v219f.svelte-17v219f{position:absolute;top:0;right:0;bottom:0;left:0;transform-origin:left;opacity:.8;z-index:var(--layer-1);transition:10ms;background:var(--background-fill-secondary)}.progress-bar-wrap.svelte-17v219f.svelte-17v219f{border:1px solid var(--border-color-primary);background:var(--background-fill-primary);width:55.5%;height:var(--size-4)}.progress-bar.svelte-17v219f.svelte-17v219f{transform-origin:left;background-color:var(--loader-color);width:var(--size-full);height:var(--size-full)}.progress-level.svelte-17v219f.svelte-17v219f{display:flex;flex-direction:column;align-items:center;gap:1;z-index:var(--layer-2);width:var(--size-full)}.progress-level-inner.svelte-17v219f.svelte-17v219f{margin:var(--size-2) auto;color:var(--body-text-color);font-size:var(--text-sm);font-family:var(--font-mono)}.meta-text.svelte-17v219f.svelte-17v219f{position:absolute;bottom:0;right:0;z-index:var(--layer-2);padding:var(--size-1) var(--size-2);font-size:var(--text-sm);font-family:var(--font-mono)}.meta-text-center.svelte-17v219f.svelte-17v219f{display:flex;position:absolute;top:0;right:0;justify-content:center;align-items:center;transform:translateY(var(--size-6));z-index:var(--layer-2);padding:var(--size-1) var(--size-2);font-size:var(--text-sm);font-family:var(--font-mono);text-align:center}.error.svelte-17v219f.svelte-17v219f{box-shadow:var(--shadow-drop);border:solid 1px var(--error-border-color);border-radius:var(--radius-full);background:var(--error-background-fill);padding-right:var(--size-4);padding-left:var(--size-4);color:var(--error-text-color);font-weight:var(--weight-semibold);font-size:var(--text-lg);line-height:var(--line-lg);font-family:var(--font)}.minimal.svelte-17v219f.svelte-17v219f{pointer-events:none}.minimal.svelte-17v219f .progress-text.svelte-17v219f{background:var(--block-background-fill)}.border.svelte-17v219f.svelte-17v219f{border:1px solid var(--border-color-primary)}.clear-status.svelte-17v219f.svelte-17v219f{position:absolute;display:flex;top:var(--size-2);right:var(--size-2);justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-1)}.toast-body.svelte-syezpc{display:flex;position:relative;right:0;left:0;align-items:center;margin:var(--size-6) var(--size-4);margin:auto;border-radius:var(--container-radius);overflow:hidden;pointer-events:auto}.toast-body.error.svelte-syezpc{border:1px solid var(--color-red-700);background:var(--color-red-50)}.dark .toast-body.error.svelte-syezpc{border:1px solid var(--color-red-500);background-color:var(--color-grey-950)}.toast-body.warning.svelte-syezpc{border:1px solid var(--color-yellow-700);background:var(--color-yellow-50)}.dark .toast-body.warning.svelte-syezpc{border:1px solid var(--color-yellow-500);background-color:var(--color-grey-950)}.toast-body.info.svelte-syezpc{border:1px solid var(--color-grey-700);background:var(--color-grey-50)}.dark .toast-body.info.svelte-syezpc{border:1px solid var(--color-grey-500);background-color:var(--color-grey-950)}.toast-body.success.svelte-syezpc{border:1px solid var(--color-green-700);background:var(--color-green-50)}.dark .toast-body.success.svelte-syezpc{border:1px solid var(--color-green-500);background-color:var(--color-grey-950)}.toast-title.svelte-syezpc{display:flex;align-items:center;font-weight:var(--weight-bold);font-size:var(--text-lg);line-height:var(--line-sm)}.toast-title.error.svelte-syezpc{color:var(--color-red-700)}.dark .toast-title.error.svelte-syezpc{color:var(--color-red-50)}.toast-title.warning.svelte-syezpc{color:var(--color-yellow-700)}.dark .toast-title.warning.svelte-syezpc{color:var(--color-yellow-50)}.toast-title.info.svelte-syezpc{color:var(--color-grey-700)}.dark .toast-title.info.svelte-syezpc{color:var(--color-grey-50)}.toast-title.success.svelte-syezpc{color:var(--color-green-700)}.dark .toast-title.success.svelte-syezpc{color:var(--color-green-50)}.toast-close.svelte-syezpc{margin:0 var(--size-3);border-radius:var(--size-3);padding:0px var(--size-1-5);font-size:var(--size-5);line-height:var(--size-5)}.toast-close.error.svelte-syezpc{color:var(--color-red-700)}.dark .toast-close.error.svelte-syezpc{color:var(--color-red-500)}.toast-close.warning.svelte-syezpc{color:var(--color-yellow-700)}.dark .toast-close.warning.svelte-syezpc{color:var(--color-yellow-500)}.toast-close.info.svelte-syezpc{color:var(--color-grey-700)}.dark .toast-close.info.svelte-syezpc{color:var(--color-grey-500)}.toast-close.success.svelte-syezpc{color:var(--color-green-700)}.dark .toast-close.success.svelte-syezpc{color:var(--color-green-500)}.toast-text.svelte-syezpc{font-size:var(--text-lg);word-wrap:break-word;overflow-wrap:break-word;word-break:break-word}.toast-text.error.svelte-syezpc{color:var(--color-red-700)}.dark .toast-text.error.svelte-syezpc{color:var(--color-red-50)}.toast-text.warning.svelte-syezpc{color:var(--color-yellow-700)}.dark .toast-text.warning.svelte-syezpc{color:var(--color-yellow-50)}.toast-text.info.svelte-syezpc{color:var(--color-grey-700)}.dark .toast-text.info.svelte-syezpc{color:var(--color-grey-50)}.toast-text.success.svelte-syezpc{color:var(--color-green-700)}.dark .toast-text.success.svelte-syezpc{color:var(--color-green-50)}.toast-details.svelte-syezpc{margin:var(--size-3) var(--size-3) var(--size-3) 0;width:100%}.toast-icon.svelte-syezpc{display:flex;position:absolute;position:relative;flex-shrink:0;justify-content:center;align-items:center;margin:var(--size-2);border-radius:var(--radius-full);padding:var(--size-1);padding-left:calc(var(--size-1) - 1px);width:35px;height:35px}.toast-icon.error.svelte-syezpc{color:var(--color-red-700)}.dark .toast-icon.error.svelte-syezpc{color:var(--color-red-500)}.toast-icon.warning.svelte-syezpc{color:var(--color-yellow-700)}.dark .toast-icon.warning.svelte-syezpc{color:var(--color-yellow-500)}.toast-icon.info.svelte-syezpc{color:var(--color-grey-700)}.dark .toast-icon.info.svelte-syezpc{color:var(--color-grey-500)}.toast-icon.success.svelte-syezpc{color:var(--color-green-700)}.dark .toast-icon.success.svelte-syezpc{color:var(--color-green-500)}@keyframes svelte-syezpc-countdown{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.timer.svelte-syezpc{position:absolute;bottom:0;left:0;transform-origin:0 0;animation:svelte-syezpc-countdown 10s linear forwards;width:100%;height:var(--size-1)}.timer.error.svelte-syezpc{background:var(--color-red-700)}.dark .timer.error.svelte-syezpc{background:var(--color-red-500)}.timer.warning.svelte-syezpc{background:var(--color-yellow-700)}.dark .timer.warning.svelte-syezpc{background:var(--color-yellow-500)}.timer.info.svelte-syezpc{background:var(--color-grey-700)}.dark .timer.info.svelte-syezpc{background:var(--color-grey-500)}.timer.success.svelte-syezpc{background:var(--color-green-700)}.dark .timer.success.svelte-syezpc{background:var(--color-green-500)}.hidden.svelte-syezpc{display:none}.toast-text.svelte-syezpc a{text-decoration:underline}.toast-wrap.svelte-gatr8h{display:flex;position:fixed;top:var(--size-4);right:var(--size-4);flex-direction:column;align-items:end;gap:var(--size-2);z-index:var(--layer-top);width:calc(100% - var(--size-8))}@media (--screen-sm){.toast-wrap.svelte-gatr8h{width:calc(var(--size-96) + var(--size-10))}}.streaming-bar.svelte-ga0jj6{position:absolute;bottom:0;left:0;right:0;height:4px;background-color:var(--primary-600);animation:svelte-ga0jj6-countdown linear forwards;z-index:1}@keyframes svelte-ga0jj6-countdown{0%{transform:translate(0)}to{transform:translate(-100%)}}.wrapper.svelte-1nrfbo6.svelte-1nrfbo6{width:100%;height:100%;overflow:hidden;position:relative;font-family:sans-serif}.scroll-logo-container.svelte-1nrfbo6.svelte-1nrfbo6{text-align:center;margin-bottom:2rem}.scroll-logo-container.svelte-1nrfbo6 img.svelte-1nrfbo6{display:block;margin-left:auto;margin-right:auto;max-width:80%;object-fit:contain}.credits-container.svelte-1nrfbo6.svelte-1nrfbo6{position:absolute;bottom:0;transform:translateY(100%);width:100%;text-align:center;animation:svelte-1nrfbo6-scroll var(--animation-duration) linear infinite;padding:0 2rem;box-sizing:border-box}.section-title.svelte-1nrfbo6.svelte-1nrfbo6{margin-top:4rem;margin-bottom:2.5rem;font-weight:700}.credit.intro-block.svelte-1nrfbo6.svelte-1nrfbo6{margin-bottom:5rem}.credit.svelte-1nrfbo6.svelte-1nrfbo6{margin-bottom:2rem}.credit.svelte-1nrfbo6 h2.svelte-1nrfbo6,.credit.svelte-1nrfbo6 p.svelte-1nrfbo6{margin:.5rem 0;font-family:sans-serif}.credit-two-column.svelte-1nrfbo6.svelte-1nrfbo6{display:flex;justify-content:space-between;align-items:baseline;text-align:left;margin:.8rem auto;max-width:80%;gap:1rem}.credit-two-column.svelte-1nrfbo6 .title.svelte-1nrfbo6{flex:1;text-align:right;padding-right:1rem}.credit-two-column.svelte-1nrfbo6 .name.svelte-1nrfbo6{flex:1;text-align:left;padding-left:1rem}.uppercase.svelte-1nrfbo6.svelte-1nrfbo6{text-transform:uppercase}@keyframes svelte-1nrfbo6-scroll{0%{transform:translateY(100%)}to{transform:translateY(-100%)}}.viewport.svelte-1hia40q.svelte-1hia40q{width:100%;height:100%;position:relative;overflow:hidden;perspective:400px;-webkit-mask-image:linear-gradient(to bottom,black 60%,transparent 100%);mask-image:linear-gradient(to bottom,black 60%,transparent 100%);font-family:Droid Sans,sans-serif;font-weight:700}.stars.svelte-1hia40q.svelte-1hia40q{position:absolute;top:0;left:0;width:1px;height:1px;background:transparent;z-index:0;animation:svelte-1hia40q-twinkle 10s linear infinite}.stars.small.svelte-1hia40q.svelte-1hia40q{animation-duration:10s}.stars.medium.svelte-1hia40q.svelte-1hia40q{animation-duration:15s}.stars.large.svelte-1hia40q.svelte-1hia40q{animation-duration:20s}@keyframes svelte-1hia40q-twinkle{0%{opacity:.6}50%{opacity:1}to{opacity:.6}}.crawl.svelte-1hia40q.svelte-1hia40q{position:absolute;width:100%;bottom:0;transform-origin:50% 100%;animation:svelte-1hia40q-crawl-animation var(--animation-duration) linear infinite;z-index:1;text-align:center}@keyframes svelte-1hia40q-crawl-animation{0%{transform:rotateX(60deg) translateY(100%) translateZ(100px)}to{transform:rotateX(60deg) translateY(-150%) translateZ(-1200px)}}.scroll-logo-container.svelte-1hia40q.svelte-1hia40q{text-align:center;margin-bottom:2rem}.scroll-logo-container.svelte-1hia40q img.svelte-1hia40q{display:block;margin-left:auto;margin-right:auto;max-width:70%;object-fit:contain;filter:grayscale(1) sepia(100%) hue-rotate(15deg) saturate(8) brightness(1.2)}.uppercase.svelte-1hia40q.svelte-1hia40q{text-transform:uppercase}.section-title.svelte-1hia40q.svelte-1hia40q{margin-top:5rem;margin-bottom:3rem;font-weight:700}.credit.intro-block.svelte-1hia40q.svelte-1hia40q{margin-bottom:5rem}.credit.svelte-1hia40q.svelte-1hia40q{margin-bottom:2rem}.credit.svelte-1hia40q h2.svelte-1hia40q,.credit.svelte-1hia40q p.svelte-1hia40q{margin:.5rem 0;padding:0;white-space:nowrap}.credit-two-column.svelte-1hia40q.svelte-1hia40q{display:flex;justify-content:space-between;align-items:baseline;margin:.8rem auto;width:90%;white-space:nowrap}.credit-two-column.svelte-1hia40q .spacer.svelte-1hia40q{flex-grow:1;border-bottom:1px dotted rgba(254,218,74,.3);margin:0 1em;transform:translateY(-.5em)}.matrix-container.svelte-1bt5wt2.svelte-1bt5wt2{width:100%;height:100%;position:relative;overflow:hidden}canvas.svelte-1bt5wt2.svelte-1bt5wt2{display:block;position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.credits-scroll-overlay.svelte-1bt5wt2.svelte-1bt5wt2{position:absolute;top:0;left:0;width:100%;height:100%;z-index:2;color:#fff;font-family:monospace;text-align:center;-webkit-mask-image:linear-gradient(transparent,black 20%,black 80%,transparent);mask-image:linear-gradient(transparent,black 20%,black 80%,transparent)}.credits-content.svelte-1bt5wt2.svelte-1bt5wt2{position:absolute;width:100%;bottom:0;transform:translateY(100%);animation:svelte-1bt5wt2-scroll-from-bottom var(--animation-duration) linear infinite;padding:0 2rem;box-sizing:border-box}@keyframes svelte-1bt5wt2-scroll-from-bottom{0%{transform:translateY(100%)}to{transform:translateY(-100%)}}.uppercase.svelte-1bt5wt2.svelte-1bt5wt2{text-transform:uppercase}.section-title.svelte-1bt5wt2.svelte-1bt5wt2{margin-top:4rem;margin-bottom:2.5rem;font-weight:700;color:#5f5;text-shadow:0 0 8px #0f0}.credit-block.intro-block.svelte-1bt5wt2.svelte-1bt5wt2{margin-bottom:5rem}.credit-block.svelte-1bt5wt2.svelte-1bt5wt2{margin-bottom:2.5em}.title.svelte-1bt5wt2.svelte-1bt5wt2{color:#0f0;opacity:.8}.name.svelte-1bt5wt2.svelte-1bt5wt2{font-weight:700;color:#5f5;text-shadow:0 0 5px #0f0}.credit-two-column.svelte-1bt5wt2.svelte-1bt5wt2{display:flex;justify-content:space-between;align-items:baseline;text-align:left;margin:.8em auto;max-width:80%;gap:1em}.credit-two-column.svelte-1bt5wt2 .title.svelte-1bt5wt2{flex:1;text-align:right;padding-right:1em}.credit-two-column.svelte-1bt5wt2 .name.svelte-1bt5wt2{flex:1;text-align:left;padding-left:1em}.scroll-logo-container.svelte-1bt5wt2.svelte-1bt5wt2{text-align:center;margin-bottom:2rem}.scroll-logo-container.svelte-1bt5wt2 img.svelte-1bt5wt2{display:block;margin-left:auto;margin-right:auto;max-width:80%;object-fit:contain;filter:grayscale(1) brightness(.5) sepia(100%) hue-rotate(50deg) saturate(500%)}.unstyled-link.svelte-151nsdd{all:unset;cursor:pointer}img.svelte-kxeri3{object-fit:cover}.image-container.svelte-x2tujq.svelte-x2tujq{height:100%;position:relative;min-width:var(--size-20)}.image-container.svelte-x2tujq button.svelte-x2tujq{width:var(--size-full);height:var(--size-full);border-radius:var(--radius-lg);display:flex;align-items:center;justify-content:center}.image-frame.svelte-x2tujq img{width:var(--size-full);height:var(--size-full);object-fit:scale-down}.selectable.svelte-x2tujq.svelte-x2tujq{cursor:crosshair}.fullscreen-controls svg{position:relative;top:0}.image-container:fullscreen{background-color:#000;display:flex;justify-content:center;align-items:center}.image-container:fullscreen img{max-width:90vw;max-height:90vh;object-fit:scale-down}.image-frame.svelte-x2tujq.svelte-x2tujq{width:auto;height:100%;display:flex;align-items:center;justify-content:center}.block{border:none!important;box-shadow:none!important;border-style:none!important}.outer-logo-wrapper.svelte-1hawtr7.svelte-1hawtr7,.outer-credits-wrapper.svelte-1hawtr7.svelte-1hawtr7{display:flex;flex-direction:column;width:100%;border:none}.logo-panel.svelte-1hawtr7.svelte-1hawtr7{background:var(--background-fill-primary);border:none;display:flex!important;align-items:center;justify-content:var(--logo-justify, center);padding:0 0 20px;width:100%}.credits-panel-wrapper.svelte-1hawtr7.svelte-1hawtr7{display:flex;flex-direction:var(--panel-direction, row);min-height:var(--size-full, 500px);width:100%;background:var(--background-fill-primary);border:1px solid var(--border-color-primary);border-radius:var(--radius-lg);overflow:hidden}.main-credits-panel.svelte-1hawtr7.svelte-1hawtr7{flex-grow:1;flex-shrink:1;min-width:200px;background:#000;overflow:hidden;position:relative}.licenses-sidebar.svelte-1hawtr7.svelte-1hawtr7{width:calc(100% - var(--main-panel-width, 400px));max-width:100%;max-height:var(--sidebar-max-height, none);flex-shrink:1;flex-grow:1;background:var(--background-fill-secondary);overflow-y:auto;border-left:var(--border-left, 1px solid var(--border-color-primary));border-top:var(--border-top, none)}.licenses-sidebar.svelte-1hawtr7 h3.svelte-1hawtr7{margin:var(--spacing-lg);font-size:var(--text-lg)}.licenses-sidebar.svelte-1hawtr7 li.svelte-1hawtr7{padding:0;margin:0;cursor:default;border-bottom:1px solid var(--border-color-primary)}.licenses-sidebar.svelte-1hawtr7 li button.svelte-1hawtr7{background:none;border:none;font:inherit;color:inherit;text-align:left;width:100%;cursor:pointer;padding:var(--spacing-md) var(--spacing-lg);transition:background-color .2s}.licenses-sidebar.svelte-1hawtr7 li button.svelte-1hawtr7:hover{background-color:var(--background-fill-primary)}.licenses-sidebar.svelte-1hawtr7 li button.svelte-1hawtr7:focus-visible{outline:2px solid var(--color-accent);outline-offset:-2px}.licenses-sidebar.svelte-1hawtr7 li button.selected.svelte-1hawtr7{background-color:var(--color-accent);color:#fff;font-weight:700}.license-display.svelte-1hawtr7.svelte-1hawtr7{padding:var(--spacing-lg);overflow-y:auto;flex-grow:1;border-top:1px solid var(--border-color-primary);background:var(--background-fill-primary)}.license-display.svelte-1hawtr7 h4.svelte-1hawtr7{margin-top:0}.license-display.svelte-1hawtr7 pre.svelte-1hawtr7{white-space:pre-wrap;word-break:break-word;font-size:var(--text-sm);color:var(--body-text-color-subdued)}
|
src/demo/app.py
CHANGED
@@ -18,7 +18,7 @@ def setup_demo_files():
|
|
18 |
with open("./assets/logo.webp", "w") as f:
|
19 |
f.write("Placeholder WebP logo")
|
20 |
|
21 |
-
# ---
|
22 |
credits_list = [
|
23 |
{"section_title": "Project Leadership"},
|
24 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
@@ -47,6 +47,8 @@ DEFAULT_SPEEDS = {
|
|
47 |
"starwars": 70.0,
|
48 |
"matrix": 40.0
|
49 |
}
|
|
|
|
|
50 |
|
51 |
def update_panel(
|
52 |
effect: str,
|
@@ -64,39 +66,52 @@ def update_panel(
|
|
64 |
logo_height: str | None,
|
65 |
scroll_background_color: str | None,
|
66 |
scroll_title_color: str | None,
|
|
|
67 |
scroll_name_color: str | None,
|
68 |
layout_style: str,
|
69 |
title_uppercase: bool,
|
70 |
name_uppercase: bool,
|
71 |
section_title_uppercase: bool,
|
72 |
-
swap_font_sizes: bool
|
|
|
|
|
73 |
) -> dict:
|
74 |
"""Callback function that updates all properties of the CreditsPanel component."""
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
|
101 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
102 |
"""Updates sliders to sensible defaults when the animation effect is changed."""
|
@@ -138,6 +153,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
138 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
139 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
gr.Markdown("### Intro Text")
|
142 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
143 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
@@ -157,19 +180,20 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
157 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
158 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
159 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
|
|
160 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
161 |
|
162 |
-
panel = CreditsPanel(
|
|
|
163 |
credits=credits_list,
|
164 |
licenses=license_paths,
|
165 |
effect="scroll",
|
166 |
-
height=500,
|
167 |
speed=DEFAULT_SPEEDS["scroll"],
|
168 |
base_font_size=1.5,
|
169 |
intro_title="Gradio",
|
170 |
intro_subtitle="The best UI framework",
|
171 |
sidebar_position="right",
|
172 |
-
logo_path=
|
173 |
show_logo=True,
|
174 |
show_licenses=True,
|
175 |
show_credits=True,
|
@@ -180,11 +204,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
180 |
scroll_background_color="#000000",
|
181 |
scroll_title_color="#FFFFFF",
|
182 |
scroll_name_color="#FFFFFF",
|
|
|
183 |
layout_style="stacked",
|
184 |
title_uppercase=False,
|
185 |
name_uppercase=False,
|
186 |
section_title_uppercase=True,
|
187 |
swap_font_sizes_on_two_column=False,
|
|
|
|
|
188 |
)
|
189 |
|
190 |
inputs = [
|
@@ -202,15 +229,23 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
202 |
logo_width_input,
|
203 |
logo_height_input,
|
204 |
scroll_background_color,
|
205 |
-
scroll_title_color,
|
|
|
206 |
scroll_name_color,
|
207 |
layout_style_radio,
|
208 |
title_uppercase_checkbox,
|
209 |
name_uppercase_checkbox,
|
210 |
section_title_uppercase_checkbox,
|
211 |
-
swap_sizes_checkbox
|
|
|
|
|
212 |
]
|
213 |
|
|
|
|
|
|
|
|
|
|
|
214 |
layout_style_radio.change(
|
215 |
fn=toggle_swap_checkbox_visibility,
|
216 |
inputs=layout_style_radio,
|
|
|
18 |
with open("./assets/logo.webp", "w") as f:
|
19 |
f.write("Placeholder WebP logo")
|
20 |
|
21 |
+
# --- Credits list with sections ---
|
22 |
credits_list = [
|
23 |
{"section_title": "Project Leadership"},
|
24 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
|
|
47 |
"starwars": 70.0,
|
48 |
"matrix": 40.0
|
49 |
}
|
50 |
+
SCROLL_LOGO_PATH = "./assets/gradio_logo_white.png"
|
51 |
+
LOGO_PATH="./assets/logo.webp"
|
52 |
|
53 |
def update_panel(
|
54 |
effect: str,
|
|
|
66 |
logo_height: str | None,
|
67 |
scroll_background_color: str | None,
|
68 |
scroll_title_color: str | None,
|
69 |
+
scroll_section_title_color: str | None,
|
70 |
scroll_name_color: str | None,
|
71 |
layout_style: str,
|
72 |
title_uppercase: bool,
|
73 |
name_uppercase: bool,
|
74 |
section_title_uppercase: bool,
|
75 |
+
swap_font_sizes: bool,
|
76 |
+
show_scroll_logo: bool,
|
77 |
+
scroll_logo_height: str | None
|
78 |
) -> dict:
|
79 |
"""Callback function that updates all properties of the CreditsPanel component."""
|
80 |
+
|
81 |
+
scroll_logo_path = SCROLL_LOGO_PATH if show_scroll_logo else None
|
82 |
+
|
83 |
+
if not scroll_logo_height:
|
84 |
+
scroll_logo_height = "120px"
|
85 |
+
|
86 |
+
return {
|
87 |
+
"credits": credits_list,
|
88 |
+
"licenses": license_paths,
|
89 |
+
"effect": effect,
|
90 |
+
"speed": speed,
|
91 |
+
"base_font_size": base_font_size,
|
92 |
+
"intro_title": intro_title,
|
93 |
+
"intro_subtitle": intro_subtitle,
|
94 |
+
"sidebar_position": sidebar_position,
|
95 |
+
"logo_path": LOGO_PATH,
|
96 |
+
"show_logo": show_logo,
|
97 |
+
"show_licenses": show_licenses,
|
98 |
+
"show_credits": show_credits,
|
99 |
+
"logo_position": logo_position,
|
100 |
+
"logo_sizing": logo_sizing,
|
101 |
+
"logo_width": logo_width,
|
102 |
+
"logo_height": logo_height,
|
103 |
+
"scroll_background_color": scroll_background_color,
|
104 |
+
"scroll_title_color": scroll_title_color,
|
105 |
+
"scroll_name_color": scroll_name_color,
|
106 |
+
"scroll_section_title_color": scroll_section_title_color,
|
107 |
+
"layout_style": layout_style,
|
108 |
+
"title_uppercase": title_uppercase,
|
109 |
+
"name_uppercase": name_uppercase,
|
110 |
+
"section_title_uppercase": section_title_uppercase,
|
111 |
+
"swap_font_sizes_on_two_column": swap_font_sizes,
|
112 |
+
"scroll_logo_path": scroll_logo_path,
|
113 |
+
"scroll_logo_height": scroll_logo_height,
|
114 |
+
}
|
115 |
|
116 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
117 |
"""Updates sliders to sensible defaults when the animation effect is changed."""
|
|
|
153 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
154 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
155 |
|
156 |
+
gr.Markdown("### Scrolling Logo")
|
157 |
+
show_scroll_logo_checkbox = gr.Checkbox(
|
158 |
+
label="Show Logo in Credits Roll",
|
159 |
+
value=True,
|
160 |
+
info="Toggles the logo above the intro text."
|
161 |
+
)
|
162 |
+
scroll_logo_height_input = gr.Textbox(label="Scrolling Logo Height", value="100px")
|
163 |
+
|
164 |
gr.Markdown("### Intro Text")
|
165 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
166 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
|
|
180 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
181 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
182 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
183 |
+
scroll_section_title_color = gr.ColorPicker(label="Section Title Color", value="#FFFFFF")
|
184 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
185 |
|
186 |
+
panel = CreditsPanel(
|
187 |
+
height=500,
|
188 |
credits=credits_list,
|
189 |
licenses=license_paths,
|
190 |
effect="scroll",
|
|
|
191 |
speed=DEFAULT_SPEEDS["scroll"],
|
192 |
base_font_size=1.5,
|
193 |
intro_title="Gradio",
|
194 |
intro_subtitle="The best UI framework",
|
195 |
sidebar_position="right",
|
196 |
+
logo_path=LOGO_PATH,
|
197 |
show_logo=True,
|
198 |
show_licenses=True,
|
199 |
show_credits=True,
|
|
|
204 |
scroll_background_color="#000000",
|
205 |
scroll_title_color="#FFFFFF",
|
206 |
scroll_name_color="#FFFFFF",
|
207 |
+
scroll_section_title_color="#FFFFFF",
|
208 |
layout_style="stacked",
|
209 |
title_uppercase=False,
|
210 |
name_uppercase=False,
|
211 |
section_title_uppercase=True,
|
212 |
swap_font_sizes_on_two_column=False,
|
213 |
+
scroll_logo_path=SCROLL_LOGO_PATH,
|
214 |
+
scroll_logo_height="100px",
|
215 |
)
|
216 |
|
217 |
inputs = [
|
|
|
229 |
logo_width_input,
|
230 |
logo_height_input,
|
231 |
scroll_background_color,
|
232 |
+
scroll_title_color,
|
233 |
+
scroll_section_title_color,
|
234 |
scroll_name_color,
|
235 |
layout_style_radio,
|
236 |
title_uppercase_checkbox,
|
237 |
name_uppercase_checkbox,
|
238 |
section_title_uppercase_checkbox,
|
239 |
+
swap_sizes_checkbox,
|
240 |
+
show_scroll_logo_checkbox,
|
241 |
+
scroll_logo_height_input
|
242 |
]
|
243 |
|
244 |
+
demo.load(
|
245 |
+
fn=update_panel,
|
246 |
+
inputs=inputs,
|
247 |
+
outputs=panel
|
248 |
+
)
|
249 |
layout_style_radio.change(
|
250 |
fn=toggle_swap_checkbox_visibility,
|
251 |
inputs=layout_style_radio,
|
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 = {'CreditsPanel': {'description': 'A Gradio component for displaying credits with customizable visual effects, such as scrolling or Star Wars-style animations.\
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
@@ -58,7 +58,7 @@ def setup_demo_files():
|
|
58 |
with open("./assets/logo.webp", "w") as f:
|
59 |
f.write("Placeholder WebP logo")
|
60 |
|
61 |
-
# ---
|
62 |
credits_list = [
|
63 |
{"section_title": "Project Leadership"},
|
64 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
@@ -87,6 +87,8 @@ DEFAULT_SPEEDS = {
|
|
87 |
"starwars": 70.0,
|
88 |
"matrix": 40.0
|
89 |
}
|
|
|
|
|
90 |
|
91 |
def update_panel(
|
92 |
effect: str,
|
@@ -104,39 +106,52 @@ def update_panel(
|
|
104 |
logo_height: str | None,
|
105 |
scroll_background_color: str | None,
|
106 |
scroll_title_color: str | None,
|
|
|
107 |
scroll_name_color: str | None,
|
108 |
layout_style: str,
|
109 |
title_uppercase: bool,
|
110 |
name_uppercase: bool,
|
111 |
section_title_uppercase: bool,
|
112 |
-
swap_font_sizes: bool
|
|
|
|
|
113 |
) -> dict:
|
114 |
\"\"\"Callback function that updates all properties of the CreditsPanel component.\"\"\"
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
142 |
\"\"\"Updates sliders to sensible defaults when the animation effect is changed.\"\"\"
|
@@ -178,6 +193,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
178 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
179 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
gr.Markdown("### Intro Text")
|
182 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
183 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
@@ -197,19 +220,20 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
197 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
198 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
199 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
|
|
200 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
201 |
|
202 |
-
panel = CreditsPanel(
|
|
|
203 |
credits=credits_list,
|
204 |
licenses=license_paths,
|
205 |
effect="scroll",
|
206 |
-
height=500,
|
207 |
speed=DEFAULT_SPEEDS["scroll"],
|
208 |
base_font_size=1.5,
|
209 |
intro_title="Gradio",
|
210 |
intro_subtitle="The best UI framework",
|
211 |
sidebar_position="right",
|
212 |
-
logo_path=
|
213 |
show_logo=True,
|
214 |
show_licenses=True,
|
215 |
show_credits=True,
|
@@ -220,11 +244,14 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
220 |
scroll_background_color="#000000",
|
221 |
scroll_title_color="#FFFFFF",
|
222 |
scroll_name_color="#FFFFFF",
|
|
|
223 |
layout_style="stacked",
|
224 |
title_uppercase=False,
|
225 |
name_uppercase=False,
|
226 |
section_title_uppercase=True,
|
227 |
swap_font_sizes_on_two_column=False,
|
|
|
|
|
228 |
)
|
229 |
|
230 |
inputs = [
|
@@ -242,15 +269,23 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="CreditsPanel Demo") as demo:
|
|
242 |
logo_width_input,
|
243 |
logo_height_input,
|
244 |
scroll_background_color,
|
245 |
-
scroll_title_color,
|
|
|
246 |
scroll_name_color,
|
247 |
layout_style_radio,
|
248 |
title_uppercase_checkbox,
|
249 |
name_uppercase_checkbox,
|
250 |
section_title_uppercase_checkbox,
|
251 |
-
swap_sizes_checkbox
|
|
|
|
|
252 |
]
|
253 |
|
|
|
|
|
|
|
|
|
|
|
254 |
layout_style_radio.change(
|
255 |
fn=toggle_swap_checkbox_visibility,
|
256 |
inputs=layout_style_radio,
|
@@ -294,7 +329,6 @@ The impact on the users predict function varies depending on whether the compone
|
|
294 |
|
295 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
296 |
|
297 |
-
- **As input:** Is passed, dict[str, Any] | None: The input payload, returned unchanged.
|
298 |
|
299 |
|
300 |
```python
|
@@ -302,7 +336,9 @@ def predict(
|
|
302 |
value: typing.Optional[typing.Dict[str, typing.Any]][
|
303 |
typing.Dict[str, typing.Any][str, Any], None
|
304 |
]
|
305 |
-
) -> Any
|
|
|
|
|
306 |
return value
|
307 |
```
|
308 |
""", elem_classes=["md-custom", "CreditsPanel-user-fn"], header_links=True)
|
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
+
_docs = {'CreditsPanel': {'description': 'A Gradio component for displaying credits with customizable visual effects, such as scrolling or Star Wars-style animations.\nThis component is configured via a single dictionary `value` that holds all settings.\nIt supports displaying a logo, licenses, sections, and various text styling options.\n\n EVENTS (list): Supported events for the component, currently only `change`.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Dict[str, typing.Any]][\n typing.Dict[str, typing.Any][str, Any], None\n]', 'default': 'None', 'description': None}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': None}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': None}, 'credits': {'type': 'typing.Union[\n typing.List[typing.Dict[str, str]],\n typing.Callable,\n NoneType,\n][\n typing.List[typing.Dict[str, str]][\n typing.Dict[str, str][str, str]\n ],\n Callable,\n None,\n]', 'default': 'None', 'description': None}, 'licenses': {'type': 'typing.Optional[typing.Dict[str, str | pathlib.Path]][\n typing.Dict[str, str | pathlib.Path][\n str, str | pathlib.Path\n ],\n None,\n]', 'default': 'None', 'description': None}, 'effect': {'type': '"scroll" | "starwars" | "matrix"', 'default': '"scroll"', 'description': None}, 'speed': {'type': 'float', 'default': '40.0', 'description': None}, 'base_font_size': {'type': 'float', 'default': '1.5', 'description': None}, 'intro_title': {'type': 'str | None', 'default': 'None', 'description': None}, 'intro_subtitle': {'type': 'str | None', 'default': 'None', 'description': None}, 'sidebar_position': {'type': '"right" | "bottom"', 'default': '"right"', 'description': None}, 'logo_path': {'type': 'str | pathlib.Path | None', 'default': 'None', 'description': None}, 'show_logo': {'type': 'bool', 'default': 'True', 'description': None}, 'show_licenses': {'type': 'bool', 'default': 'True', 'description': None}, 'show_credits': {'type': 'bool', 'default': 'True', 'description': None}, 'logo_position': {'type': '"center" | "left" | "right"', 'default': '"center"', 'description': None}, 'logo_sizing': {'type': '"stretch" | "crop" | "resize"', 'default': '"resize"', 'description': None}, 'logo_width': {'type': 'int | str | None', 'default': 'None', 'description': None}, 'logo_height': {'type': 'int | str | None', 'default': 'None', 'description': None}, 'scroll_background_color': {'type': 'str | None', 'default': 'None', 'description': None}, 'scroll_title_color': {'type': 'str | None', 'default': 'None', 'description': None}, 'scroll_name_color': {'type': 'str | None', 'default': 'None', 'description': None}, 'scroll_section_title_color': {'type': 'str | None', 'default': 'None', 'description': None}, 'layout_style': {'type': '"stacked" | "two-column"', 'default': '"stacked"', 'description': None}, 'title_uppercase': {'type': 'bool', 'default': 'False', 'description': None}, 'name_uppercase': {'type': 'bool', 'default': 'False', 'description': None}, 'section_title_uppercase': {'type': 'bool', 'default': 'True', 'description': None}, 'swap_font_sizes_on_two_column': {'type': 'bool', 'default': 'False', 'description': None}, 'scroll_logo_path': {'type': 'str | pathlib.Path | None', 'default': 'None', 'description': None}, 'scroll_logo_height': {'type': 'str', 'default': '"120px"', 'description': None}, 'label': {'type': 'str | gradio.i18n.I18nData | None', 'default': 'None', 'description': None}, 'every': {'type': 'float | None', 'default': 'None', 'description': None}, 'inputs': {'type': 'typing.Union[\n gradio.components.base.Component,\n typing.Sequence[gradio.components.base.Component],\n set[gradio.components.base.Component],\n NoneType,\n][\n gradio.components.base.Component,\n typing.Sequence[gradio.components.base.Component][\n gradio.components.base.Component\n ],\n set[gradio.components.base.Component],\n None,\n]', 'default': 'None', 'description': None}, 'show_label': {'type': 'bool', 'default': 'False', 'description': None}, 'container': {'type': 'bool', 'default': 'True', 'description': None}, 'scale': {'type': 'int | None', 'default': 'None', 'description': None}, 'min_width': {'type': 'int', 'default': '160', 'description': None}, 'interactive': {'type': 'bool | None', 'default': 'None', 'description': None}, 'visible': {'type': 'bool', 'default': 'True', 'description': None}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': None}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': None}, 'render': {'type': 'bool', 'default': 'True', 'description': None}, 'key': {'type': 'int | str | tuple[int | str, Ellipsis] | None', 'default': 'None', 'description': None}, 'preserved_by_key': {'type': 'list[str] | str | None', 'default': '"value"', 'description': None}}, 'postprocess': {'value': {'type': 'typing.Optional[typing.Dict[str, typing.Any]][\n typing.Dict[str, typing.Any][str, Any], None\n]', 'description': None}}, 'preprocess': {'return': {'type': 'typing.Optional[typing.Dict[str, typing.Any]][\n typing.Dict[str, typing.Any][str, Any], None\n]', 'description': None}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the CreditsPanel 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.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'CreditsPanel': []}}}
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
|
|
58 |
with open("./assets/logo.webp", "w") as f:
|
59 |
f.write("Placeholder WebP logo")
|
60 |
|
61 |
+
# --- Credits list with sections ---
|
62 |
credits_list = [
|
63 |
{"section_title": "Project Leadership"},
|
64 |
{"title": "Project Manager", "name": "Emma Thompson"},
|
|
|
87 |
"starwars": 70.0,
|
88 |
"matrix": 40.0
|
89 |
}
|
90 |
+
SCROLL_LOGO_PATH = "./assets/gradio_logo_white.png"
|
91 |
+
LOGO_PATH="./assets/logo.webp"
|
92 |
|
93 |
def update_panel(
|
94 |
effect: str,
|
|
|
106 |
logo_height: str | None,
|
107 |
scroll_background_color: str | None,
|
108 |
scroll_title_color: str | None,
|
109 |
+
scroll_section_title_color: str | None,
|
110 |
scroll_name_color: str | None,
|
111 |
layout_style: str,
|
112 |
title_uppercase: bool,
|
113 |
name_uppercase: bool,
|
114 |
section_title_uppercase: bool,
|
115 |
+
swap_font_sizes: bool,
|
116 |
+
show_scroll_logo: bool,
|
117 |
+
scroll_logo_height: str | None
|
118 |
) -> dict:
|
119 |
\"\"\"Callback function that updates all properties of the CreditsPanel component.\"\"\"
|
120 |
+
|
121 |
+
scroll_logo_path = SCROLL_LOGO_PATH if show_scroll_logo else None
|
122 |
+
|
123 |
+
if not scroll_logo_height:
|
124 |
+
scroll_logo_height = "120px"
|
125 |
+
|
126 |
+
return {
|
127 |
+
"credits": credits_list,
|
128 |
+
"licenses": license_paths,
|
129 |
+
"effect": effect,
|
130 |
+
"speed": speed,
|
131 |
+
"base_font_size": base_font_size,
|
132 |
+
"intro_title": intro_title,
|
133 |
+
"intro_subtitle": intro_subtitle,
|
134 |
+
"sidebar_position": sidebar_position,
|
135 |
+
"logo_path": LOGO_PATH,
|
136 |
+
"show_logo": show_logo,
|
137 |
+
"show_licenses": show_licenses,
|
138 |
+
"show_credits": show_credits,
|
139 |
+
"logo_position": logo_position,
|
140 |
+
"logo_sizing": logo_sizing,
|
141 |
+
"logo_width": logo_width,
|
142 |
+
"logo_height": logo_height,
|
143 |
+
"scroll_background_color": scroll_background_color,
|
144 |
+
"scroll_title_color": scroll_title_color,
|
145 |
+
"scroll_name_color": scroll_name_color,
|
146 |
+
"scroll_section_title_color": scroll_section_title_color,
|
147 |
+
"layout_style": layout_style,
|
148 |
+
"title_uppercase": title_uppercase,
|
149 |
+
"name_uppercase": name_uppercase,
|
150 |
+
"section_title_uppercase": section_title_uppercase,
|
151 |
+
"swap_font_sizes_on_two_column": swap_font_sizes,
|
152 |
+
"scroll_logo_path": scroll_logo_path,
|
153 |
+
"scroll_logo_height": scroll_logo_height,
|
154 |
+
}
|
155 |
|
156 |
def update_ui_on_effect_change(effect: str) -> tuple[float, float]:
|
157 |
\"\"\"Updates sliders to sensible defaults when the animation effect is changed.\"\"\"
|
|
|
193 |
name_uppercase_checkbox = gr.Checkbox(label="Name Uppercase", value=False)
|
194 |
section_title_uppercase_checkbox = gr.Checkbox(label="Section Uppercase", value=True)
|
195 |
|
196 |
+
gr.Markdown("### Scrolling Logo")
|
197 |
+
show_scroll_logo_checkbox = gr.Checkbox(
|
198 |
+
label="Show Logo in Credits Roll",
|
199 |
+
value=True,
|
200 |
+
info="Toggles the logo above the intro text."
|
201 |
+
)
|
202 |
+
scroll_logo_height_input = gr.Textbox(label="Scrolling Logo Height", value="100px")
|
203 |
+
|
204 |
gr.Markdown("### Intro Text")
|
205 |
intro_title_input = gr.Textbox(label="Intro Title", value="Gradio")
|
206 |
intro_subtitle_input = gr.Textbox(label="Intro Subtitle", value="The best UI framework")
|
|
|
220 |
gr.Markdown("### Color Settings (Scroll Effect)")
|
221 |
scroll_background_color = gr.ColorPicker(label="Background Color", value="#000000")
|
222 |
scroll_title_color = gr.ColorPicker(label="Title Color", value="#FFFFFF")
|
223 |
+
scroll_section_title_color = gr.ColorPicker(label="Section Title Color", value="#FFFFFF")
|
224 |
scroll_name_color = gr.ColorPicker(label="Name Color", value="#FFFFFF")
|
225 |
|
226 |
+
panel = CreditsPanel(
|
227 |
+
height=500,
|
228 |
credits=credits_list,
|
229 |
licenses=license_paths,
|
230 |
effect="scroll",
|
|
|
231 |
speed=DEFAULT_SPEEDS["scroll"],
|
232 |
base_font_size=1.5,
|
233 |
intro_title="Gradio",
|
234 |
intro_subtitle="The best UI framework",
|
235 |
sidebar_position="right",
|
236 |
+
logo_path=LOGO_PATH,
|
237 |
show_logo=True,
|
238 |
show_licenses=True,
|
239 |
show_credits=True,
|
|
|
244 |
scroll_background_color="#000000",
|
245 |
scroll_title_color="#FFFFFF",
|
246 |
scroll_name_color="#FFFFFF",
|
247 |
+
scroll_section_title_color="#FFFFFF",
|
248 |
layout_style="stacked",
|
249 |
title_uppercase=False,
|
250 |
name_uppercase=False,
|
251 |
section_title_uppercase=True,
|
252 |
swap_font_sizes_on_two_column=False,
|
253 |
+
scroll_logo_path=SCROLL_LOGO_PATH,
|
254 |
+
scroll_logo_height="100px",
|
255 |
)
|
256 |
|
257 |
inputs = [
|
|
|
269 |
logo_width_input,
|
270 |
logo_height_input,
|
271 |
scroll_background_color,
|
272 |
+
scroll_title_color,
|
273 |
+
scroll_section_title_color,
|
274 |
scroll_name_color,
|
275 |
layout_style_radio,
|
276 |
title_uppercase_checkbox,
|
277 |
name_uppercase_checkbox,
|
278 |
section_title_uppercase_checkbox,
|
279 |
+
swap_sizes_checkbox,
|
280 |
+
show_scroll_logo_checkbox,
|
281 |
+
scroll_logo_height_input
|
282 |
]
|
283 |
|
284 |
+
demo.load(
|
285 |
+
fn=update_panel,
|
286 |
+
inputs=inputs,
|
287 |
+
outputs=panel
|
288 |
+
)
|
289 |
layout_style_radio.change(
|
290 |
fn=toggle_swap_checkbox_visibility,
|
291 |
inputs=layout_style_radio,
|
|
|
329 |
|
330 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
331 |
|
|
|
332 |
|
333 |
|
334 |
```python
|
|
|
336 |
value: typing.Optional[typing.Dict[str, typing.Any]][
|
337 |
typing.Dict[str, typing.Any][str, Any], None
|
338 |
]
|
339 |
+
) -> typing.Optional[typing.Dict[str, typing.Any]][
|
340 |
+
typing.Dict[str, typing.Any][str, Any], None
|
341 |
+
]:
|
342 |
return value
|
343 |
```
|
344 |
""", elem_classes=["md-custom", "CreditsPanel-user-fn"], header_links=True)
|
src/frontend/Index.svelte
CHANGED
@@ -29,6 +29,7 @@
|
|
29 |
* @property {number | string | null} logo_height - Logo height.
|
30 |
* @property {string | null} scroll_background_color - Scroll effect background color.
|
31 |
* @property {string | null} scroll_title_color - Credit title color.
|
|
|
32 |
* @property {string | null} scroll_name_color - Credit name color.
|
33 |
* @property {number} title_font_size - Title font size (unused in StarWarsEffect).
|
34 |
* @property {number} name_font_size - Name font size (unused in StarWarsEffect).
|
@@ -37,6 +38,8 @@
|
|
37 |
* @property {boolean} name_uppercase - Transform name to uppercase.
|
38 |
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
|
39 |
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes in two-column layout.
|
|
|
|
|
40 |
*/
|
41 |
export let value: Value | null = null;
|
42 |
export let elem_id = "";
|
@@ -77,12 +80,15 @@
|
|
77 |
logo_height: null,
|
78 |
scroll_background_color: null,
|
79 |
scroll_title_color: null,
|
|
|
80 |
scroll_name_color: null,
|
81 |
layout_style: "stacked",
|
82 |
title_uppercase: false,
|
83 |
name_uppercase: false,
|
84 |
section_title_uppercase: true,
|
85 |
swap_font_sizes_on_two_column: false,
|
|
|
|
|
86 |
};
|
87 |
|
88 |
// Tracks selected license for display
|
@@ -211,9 +217,12 @@
|
|
211 |
name_color={effectiveValue.scroll_name_color}
|
212 |
layout_style={effectiveValue.layout_style}
|
213 |
title_uppercase={effectiveValue.title_uppercase}
|
|
|
214 |
name_uppercase={effectiveValue.name_uppercase}
|
215 |
section_title_uppercase={effectiveValue.section_title_uppercase}
|
216 |
swap_font_sizes_on_two_column={effectiveValue.swap_font_sizes_on_two_column}
|
|
|
|
|
217 |
/>
|
218 |
{:else if effectiveValue.effect === "starwars"}
|
219 |
<StarWarsEffect
|
@@ -227,6 +236,8 @@
|
|
227 |
name_uppercase={effectiveValue.name_uppercase}
|
228 |
section_title_uppercase={effectiveValue.section_title_uppercase}
|
229 |
swap_font_sizes_on_two_column={effectiveValue.swap_font_sizes_on_two_column}
|
|
|
|
|
230 |
/>
|
231 |
{:else if effectiveValue.effect === "matrix"}
|
232 |
<MatrixEffect
|
@@ -240,6 +251,8 @@
|
|
240 |
name_uppercase={effectiveValue.name_uppercase}
|
241 |
section_title_uppercase={effectiveValue.section_title_uppercase}
|
242 |
swap_font_sizes_on_two_column={effectiveValue.swap_font_sizes_on_two_column}
|
|
|
|
|
243 |
/>
|
244 |
{/if}
|
245 |
</div>
|
|
|
29 |
* @property {number | string | null} logo_height - Logo height.
|
30 |
* @property {string | null} scroll_background_color - Scroll effect background color.
|
31 |
* @property {string | null} scroll_title_color - Credit title color.
|
32 |
+
* @property {string | null} scroll_section_title_color - Section title color.
|
33 |
* @property {string | null} scroll_name_color - Credit name color.
|
34 |
* @property {number} title_font_size - Title font size (unused in StarWarsEffect).
|
35 |
* @property {number} name_font_size - Name font size (unused in StarWarsEffect).
|
|
|
38 |
* @property {boolean} name_uppercase - Transform name to uppercase.
|
39 |
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
|
40 |
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes in two-column layout.
|
41 |
+
* @property {{path: string | null, url: string | null, ...} | null} scroll_logo_path - Logo to display inside the scroll.
|
42 |
+
* @property {string} scroll_logo_height - Height of the scrolling logo.
|
43 |
*/
|
44 |
export let value: Value | null = null;
|
45 |
export let elem_id = "";
|
|
|
80 |
logo_height: null,
|
81 |
scroll_background_color: null,
|
82 |
scroll_title_color: null,
|
83 |
+
scroll_section_title_color: null,
|
84 |
scroll_name_color: null,
|
85 |
layout_style: "stacked",
|
86 |
title_uppercase: false,
|
87 |
name_uppercase: false,
|
88 |
section_title_uppercase: true,
|
89 |
swap_font_sizes_on_two_column: false,
|
90 |
+
scroll_logo_path: null,
|
91 |
+
scroll_logo_height: "120px",
|
92 |
};
|
93 |
|
94 |
// Tracks selected license for display
|
|
|
217 |
name_color={effectiveValue.scroll_name_color}
|
218 |
layout_style={effectiveValue.layout_style}
|
219 |
title_uppercase={effectiveValue.title_uppercase}
|
220 |
+
scroll_section_title_color={effectiveValue.scroll_section_title_color}
|
221 |
name_uppercase={effectiveValue.name_uppercase}
|
222 |
section_title_uppercase={effectiveValue.section_title_uppercase}
|
223 |
swap_font_sizes_on_two_column={effectiveValue.swap_font_sizes_on_two_column}
|
224 |
+
scroll_logo_path={effectiveValue.scroll_logo_path}
|
225 |
+
scroll_logo_height={effectiveValue.scroll_logo_height}
|
226 |
/>
|
227 |
{:else if effectiveValue.effect === "starwars"}
|
228 |
<StarWarsEffect
|
|
|
236 |
name_uppercase={effectiveValue.name_uppercase}
|
237 |
section_title_uppercase={effectiveValue.section_title_uppercase}
|
238 |
swap_font_sizes_on_two_column={effectiveValue.swap_font_sizes_on_two_column}
|
239 |
+
scroll_logo_path={effectiveValue.scroll_logo_path}
|
240 |
+
scroll_logo_height={effectiveValue.scroll_logo_height}
|
241 |
/>
|
242 |
{:else if effectiveValue.effect === "matrix"}
|
243 |
<MatrixEffect
|
|
|
251 |
name_uppercase={effectiveValue.name_uppercase}
|
252 |
section_title_uppercase={effectiveValue.section_title_uppercase}
|
253 |
swap_font_sizes_on_two_column={effectiveValue.swap_font_sizes_on_two_column}
|
254 |
+
scroll_logo_path={effectiveValue.scroll_logo_path}
|
255 |
+
scroll_logo_height={effectiveValue.scroll_logo_height}
|
256 |
/>
|
257 |
{/if}
|
258 |
</div>
|
src/frontend/shared/MatrixEffect.svelte
CHANGED
@@ -14,6 +14,8 @@
|
|
14 |
* @property {boolean} name_uppercase - Transform name to uppercase.
|
15 |
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
|
16 |
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes.
|
|
|
|
|
17 |
*/
|
18 |
export let credits: Props["credits"];
|
19 |
export let speed: number = 20;
|
@@ -25,6 +27,8 @@
|
|
25 |
export let name_uppercase: boolean = false;
|
26 |
export let section_title_uppercase: boolean = true;
|
27 |
export let swap_font_sizes_on_two_column: boolean = false;
|
|
|
|
|
28 |
|
29 |
// Combines intro and credits for display
|
30 |
$: display_items = (() => {
|
@@ -142,6 +146,11 @@
|
|
142 |
bind:this={contentElement}
|
143 |
style="--animation-duration: {speed}s;"
|
144 |
>
|
|
|
|
|
|
|
|
|
|
|
145 |
{#each display_items as item}
|
146 |
<!-- Render Section Title -->
|
147 |
{#if item.section_title}
|
@@ -305,4 +314,16 @@
|
|
305 |
text-align: left;
|
306 |
padding-left: 1em;
|
307 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
308 |
</style>
|
|
|
14 |
* @property {boolean} name_uppercase - Transform name to uppercase.
|
15 |
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
|
16 |
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes.
|
17 |
+
* @property {{path: string | null, url: string | null, ...} | null} scroll_logo_path - Logo to display inside the scroll.
|
18 |
+
* @property {string} scroll_logo_height - Height of the scrolling logo.
|
19 |
*/
|
20 |
export let credits: Props["credits"];
|
21 |
export let speed: number = 20;
|
|
|
27 |
export let name_uppercase: boolean = false;
|
28 |
export let section_title_uppercase: boolean = true;
|
29 |
export let swap_font_sizes_on_two_column: boolean = false;
|
30 |
+
export let scroll_logo_path: { url: string | null } | null = null;
|
31 |
+
export let scroll_logo_height: string = "120px";
|
32 |
|
33 |
// Combines intro and credits for display
|
34 |
$: display_items = (() => {
|
|
|
146 |
bind:this={contentElement}
|
147 |
style="--animation-duration: {speed}s;"
|
148 |
>
|
149 |
+
{#if scroll_logo_path?.url}
|
150 |
+
<div class="scroll-logo-container">
|
151 |
+
<img src={scroll_logo_path.url} alt="Scrolling Logo" style:height={scroll_logo_height} />
|
152 |
+
</div>
|
153 |
+
{/if}
|
154 |
{#each display_items as item}
|
155 |
<!-- Render Section Title -->
|
156 |
{#if item.section_title}
|
|
|
314 |
text-align: left;
|
315 |
padding-left: 1em;
|
316 |
}
|
317 |
+
.scroll-logo-container {
|
318 |
+
text-align: center;
|
319 |
+
margin-bottom: 2rem;
|
320 |
+
}
|
321 |
+
.scroll-logo-container img {
|
322 |
+
display: block;
|
323 |
+
margin-left: auto;
|
324 |
+
margin-right: auto;
|
325 |
+
max-width: 80%;
|
326 |
+
object-fit: contain;
|
327 |
+
filter: grayscale(1) brightness(0.5) sepia(100%) hue-rotate(50deg) saturate(500%);
|
328 |
+
}
|
329 |
</style>
|
src/frontend/shared/ScrollEffect.svelte
CHANGED
@@ -7,6 +7,7 @@
|
|
7 |
* @property {number} base_font_size - Base font size in rem (default: 1.5).
|
8 |
* @property {string | null} background_color - Background color (default: black).
|
9 |
* @property {string | null} title_color - Title text color (default: white).
|
|
|
10 |
* @property {string | null} name_color - Name text color (default: white).
|
11 |
* @property {string | null} intro_title - Optional intro title.
|
12 |
* @property {string | null} intro_subtitle - Optional intro subtitle.
|
@@ -15,12 +16,16 @@
|
|
15 |
* @property {boolean} name_uppercase - Transform name to uppercase.
|
16 |
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
|
17 |
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes.
|
|
|
|
|
|
|
18 |
*/
|
19 |
export let credits: Props['credits'];
|
20 |
export let speed: number;
|
21 |
export let base_font_size: number = 1.5;
|
22 |
export let background_color: string | null = null;
|
23 |
export let title_color: string | null = null;
|
|
|
24 |
export let name_color: string | null = null;
|
25 |
export let intro_title: string | null = null;
|
26 |
export let intro_subtitle: string | null = null;
|
@@ -29,6 +34,8 @@
|
|
29 |
export let name_uppercase: boolean = false;
|
30 |
export let section_title_uppercase: boolean = true;
|
31 |
export let swap_font_sizes_on_two_column: boolean = false;
|
|
|
|
|
32 |
|
33 |
// Flag to trigger animation reset
|
34 |
let reset = false;
|
@@ -48,8 +55,8 @@
|
|
48 |
|
49 |
// Reactive styles for title and name
|
50 |
$: title_style = (is_intro: boolean) => `color: ${title_color || 'white'}; font-size: ${is_intro ? base_font_size * 1.5 : base_font_size}rem;`;
|
51 |
-
$: name_style = (is_intro: boolean) => `color: ${name_color || 'white'}; font-size: ${is_intro ? base_font_size * 0.9 : base_font_size * 0.8}rem;`;
|
52 |
-
$: section_title_style = `color: ${title_color || 'white'}; font-size: ${base_font_size * 1.2}rem;`;
|
53 |
|
54 |
// Reset animation on prop changes
|
55 |
function resetAnimation() {
|
@@ -64,6 +71,11 @@
|
|
64 |
<div class="wrapper" style:--animation-duration="{speed}s" style:background={background_color || 'black'}>
|
65 |
{#if !reset}
|
66 |
<div class="credits-container">
|
|
|
|
|
|
|
|
|
|
|
67 |
{#each display_items as item}
|
68 |
<!-- Render Section Title -->
|
69 |
{#if item.section_title}
|
@@ -108,6 +120,17 @@
|
|
108 |
position: relative;
|
109 |
font-family: sans-serif;
|
110 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
|
112 |
/* Animated container holding all credit items */
|
113 |
.credits-container {
|
|
|
7 |
* @property {number} base_font_size - Base font size in rem (default: 1.5).
|
8 |
* @property {string | null} background_color - Background color (default: black).
|
9 |
* @property {string | null} title_color - Title text color (default: white).
|
10 |
+
* @property {string | null} scroll_section_title_color - Section title color.
|
11 |
* @property {string | null} name_color - Name text color (default: white).
|
12 |
* @property {string | null} intro_title - Optional intro title.
|
13 |
* @property {string | null} intro_subtitle - Optional intro subtitle.
|
|
|
16 |
* @property {boolean} name_uppercase - Transform name to uppercase.
|
17 |
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
|
18 |
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes.
|
19 |
+
* @property {{path: string | null, url: string | null, ...} | null} scroll_logo_path - Logo to display inside the scroll.
|
20 |
+
* @property {string} scroll_logo_height - Height of the scrolling logo.
|
21 |
+
*
|
22 |
*/
|
23 |
export let credits: Props['credits'];
|
24 |
export let speed: number;
|
25 |
export let base_font_size: number = 1.5;
|
26 |
export let background_color: string | null = null;
|
27 |
export let title_color: string | null = null;
|
28 |
+
export let scroll_section_title_color: string | null = null;
|
29 |
export let name_color: string | null = null;
|
30 |
export let intro_title: string | null = null;
|
31 |
export let intro_subtitle: string | null = null;
|
|
|
34 |
export let name_uppercase: boolean = false;
|
35 |
export let section_title_uppercase: boolean = true;
|
36 |
export let swap_font_sizes_on_two_column: boolean = false;
|
37 |
+
export let scroll_logo_path: { url: string | null } | null = null;
|
38 |
+
export let scroll_logo_height: string = "120px";
|
39 |
|
40 |
// Flag to trigger animation reset
|
41 |
let reset = false;
|
|
|
55 |
|
56 |
// Reactive styles for title and name
|
57 |
$: title_style = (is_intro: boolean) => `color: ${title_color || 'white'}; font-size: ${is_intro ? base_font_size * 1.5 : base_font_size}rem;`;
|
58 |
+
$: name_style = (is_intro: boolean) => `color: ${name_color || 'white'}; font-size: ${is_intro ? base_font_size * 0.9 : base_font_size * 0.8}rem;`;
|
59 |
+
$: section_title_style = `color: ${scroll_section_title_color || title_color || 'white'}; font-size: ${base_font_size * 1.2}rem;`;
|
60 |
|
61 |
// Reset animation on prop changes
|
62 |
function resetAnimation() {
|
|
|
71 |
<div class="wrapper" style:--animation-duration="{speed}s" style:background={background_color || 'black'}>
|
72 |
{#if !reset}
|
73 |
<div class="credits-container">
|
74 |
+
{#if scroll_logo_path?.url}
|
75 |
+
<div class="scroll-logo-container" style:height={scroll_logo_height}>
|
76 |
+
<img src={scroll_logo_path.url} alt="Scrolling Logo" style:height={scroll_logo_height} />
|
77 |
+
</div>
|
78 |
+
{/if}
|
79 |
{#each display_items as item}
|
80 |
<!-- Render Section Title -->
|
81 |
{#if item.section_title}
|
|
|
120 |
position: relative;
|
121 |
font-family: sans-serif;
|
122 |
}
|
123 |
+
.scroll-logo-container {
|
124 |
+
text-align: center;
|
125 |
+
margin-bottom: 2rem; /* Space between logo and intro text */
|
126 |
+
}
|
127 |
+
.scroll-logo-container img {
|
128 |
+
display: block;
|
129 |
+
margin-left: auto;
|
130 |
+
margin-right: auto;
|
131 |
+
max-width: 80%;
|
132 |
+
object-fit: contain;
|
133 |
+
}
|
134 |
|
135 |
/* Animated container holding all credit items */
|
136 |
.credits-container {
|
src/frontend/shared/StarWarsEffect.svelte
CHANGED
@@ -19,6 +19,8 @@
|
|
19 |
* @property {boolean} name_uppercase - Transform name to uppercase.
|
20 |
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
|
21 |
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes.
|
|
|
|
|
22 |
*/
|
23 |
export let credits: Props['credits'];
|
24 |
export let speed: number = 40;
|
@@ -33,6 +35,8 @@
|
|
33 |
export let name_uppercase: boolean = false;
|
34 |
export let section_title_uppercase: boolean = true;
|
35 |
export let swap_font_sizes_on_two_column: boolean = false;
|
|
|
|
|
36 |
|
37 |
// Reactive styles
|
38 |
$: title_style = (is_intro: boolean) => `color: ${title_color || '#feda4a'}; font-size: ${is_intro ? base_font_size * 1.5 : base_font_size}rem;`;
|
@@ -84,6 +88,11 @@
|
|
84 |
<div class="stars large" style="box-shadow: {large_stars};"></div>
|
85 |
|
86 |
<div class="crawl" bind:this={crawlElement} style="--animation-duration: {speed}s;">
|
|
|
|
|
|
|
|
|
|
|
87 |
{#each display_items as item}
|
88 |
<!-- Render Section Title -->
|
89 |
{#if item.section_title}
|
@@ -112,6 +121,7 @@
|
|
112 |
</div>
|
113 |
|
114 |
<style>
|
|
|
115 |
.viewport {
|
116 |
width: 100%;
|
117 |
height: 100%;
|
@@ -146,6 +156,18 @@
|
|
146 |
}
|
147 |
|
148 |
/* STYLES */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
.uppercase { text-transform: uppercase; }
|
150 |
|
151 |
.section-title {
|
|
|
19 |
* @property {boolean} name_uppercase - Transform name to uppercase.
|
20 |
* @property {boolean} section_title_uppercase - Transform section title to uppercase.
|
21 |
* @property {boolean} swap_font_sizes_on_two_column - Swap title/name font sizes.
|
22 |
+
* @property {{path: string | null, url: string | null, ...} | null} scroll_logo_path - Logo to display inside the scroll.
|
23 |
+
* @property {string} scroll_logo_height - Height of the scrolling logo.
|
24 |
*/
|
25 |
export let credits: Props['credits'];
|
26 |
export let speed: number = 40;
|
|
|
35 |
export let name_uppercase: boolean = false;
|
36 |
export let section_title_uppercase: boolean = true;
|
37 |
export let swap_font_sizes_on_two_column: boolean = false;
|
38 |
+
export let scroll_logo_path: { url: string | null } | null = null;
|
39 |
+
export let scroll_logo_height: string = "120px";
|
40 |
|
41 |
// Reactive styles
|
42 |
$: title_style = (is_intro: boolean) => `color: ${title_color || '#feda4a'}; font-size: ${is_intro ? base_font_size * 1.5 : base_font_size}rem;`;
|
|
|
88 |
<div class="stars large" style="box-shadow: {large_stars};"></div>
|
89 |
|
90 |
<div class="crawl" bind:this={crawlElement} style="--animation-duration: {speed}s;">
|
91 |
+
{#if scroll_logo_path?.url}
|
92 |
+
<div class="scroll-logo-container">
|
93 |
+
<img src={scroll_logo_path.url} alt="Scrolling Logo" style:height={scroll_logo_height} />
|
94 |
+
</div>
|
95 |
+
{/if}
|
96 |
{#each display_items as item}
|
97 |
<!-- Render Section Title -->
|
98 |
{#if item.section_title}
|
|
|
121 |
</div>
|
122 |
|
123 |
<style>
|
124 |
+
|
125 |
.viewport {
|
126 |
width: 100%;
|
127 |
height: 100%;
|
|
|
156 |
}
|
157 |
|
158 |
/* STYLES */
|
159 |
+
.scroll-logo-container {
|
160 |
+
text-align: center;
|
161 |
+
margin-bottom: 2rem;
|
162 |
+
}
|
163 |
+
.scroll-logo-container img {
|
164 |
+
display: block;
|
165 |
+
margin-left: auto;
|
166 |
+
margin-right: auto;
|
167 |
+
max-width: 70%;
|
168 |
+
object-fit: contain;
|
169 |
+
filter: grayscale(1) sepia(100%) hue-rotate(15deg) saturate(8) brightness(1.2);
|
170 |
+
}
|
171 |
.uppercase { text-transform: uppercase; }
|
172 |
|
173 |
.section-title {
|
src/pyproject.toml
CHANGED
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
|
|
8 |
|
9 |
[project]
|
10 |
name = "gradio_creditspanel"
|
11 |
-
version = "0.0.
|
12 |
description = "Credits Panel for Gradio UI"
|
13 |
readme = "README.md"
|
14 |
license = "apache-2.0"
|
|
|
8 |
|
9 |
[project]
|
10 |
name = "gradio_creditspanel"
|
11 |
+
version = "0.0.4"
|
12 |
description = "Credits Panel for Gradio UI"
|
13 |
readme = "README.md"
|
14 |
license = "apache-2.0"
|