LPX55 commited on
Commit
4cc700d
·
1 Parent(s): 4478d67

Refactor app.py to utilize shared functions for greeting, calculation, and image processing, enhancing modularity and code reuse. Introduce space loading tabs for dynamic integration of popular Hugging Face Spaces.

Browse files
Files changed (8) hide show
  1. .gitignore +2 -1
  2. README.md +55 -1
  3. app.py +97 -179
  4. calculator_tab.py +1 -1
  5. greeting_tab.py +1 -1
  6. sepia_tab.py +1 -1
  7. shared_functions.py +48 -0
  8. space_loader_tab.py +65 -0
.gitignore CHANGED
@@ -1,2 +1,3 @@
1
  env/
2
- __pycache__
 
 
1
  env/
2
+ __pycache__
3
+ __pycache__/*
README.md CHANGED
@@ -10,4 +10,58 @@ pinned: false
10
  license: openrail
11
  ---
12
 
13
- This is a demo from this article: https://www.tomsoderlund.com/ai/building-ai-powered-rest-api
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  license: openrail
11
  ---
12
 
13
+ # Dynamic Space Loading
14
+ ---
15
+
16
+ ## 1. **Sending Data To/From IFrames**
17
+
18
+ ### **A. Standard Web (HTML/JS) Context**
19
+ - **IFrames are sandboxed:** By default, an iframe is isolated from the parent page for security reasons.
20
+ - **postMessage API:**
21
+ - The standard way to communicate between a parent page and an iframe (and vice versa) is using the [window.postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) API.
22
+ - This requires both the parent and the iframe to have JavaScript code that listens for and sends messages.
23
+ - Example:
24
+ - Parent: `iframeEl.contentWindow.postMessage({data: "hello"}, "https://iframe-domain.com")`
25
+ - IFrame: `window.parent.postMessage({data: "hi back"}, "https://parent-domain.com")`
26
+ - **Limitations in Gradio:**
27
+ - Gradio does not expose a built-in way to inject custom JS for postMessage into the iframe or parent.
28
+ - If you control both the parent and the iframe (i.e., both are your own apps), you could add custom JS to both and use postMessage.
29
+ - If the iframe is a third-party app (like a Hugging Face Space you don’t control), you cannot inject JS into it, so you cannot send/receive data programmatically.
30
+
31
+ ### **B. Gradio Context**
32
+ - **No built-in Gradio API for iframe communication.**
33
+ - **You can use gr.HTML to inject a script into the parent,** but you cannot inject into the iframe if you don’t control its code.
34
+
35
+ ---
36
+
37
+ ## 2. **Sending Data Between Tabs in Gradio**
38
+
39
+ - **Tabs in Gradio are just layout elements:** All components in all tabs exist in the same Python process and can share state.
40
+ - **You can use gr.State or any shared variable:**
41
+ - For example, you can have a gr.State object that is updated in one tab and read in another.
42
+ - You can also use hidden components or callbacks to pass data between tabs.
43
+ ---
44
+
45
+ ## 3. **Summary Table**
46
+
47
+ | Method | Parent ↔ IFrame | Tab ↔ Tab (Gradio) |
48
+ |-----------------------|:--------------:|:------------------:|
49
+ | postMessage (JS) | Yes (if you control both) | N/A |
50
+ | gr.State | No | Yes |
51
+ | Hidden Components | No | Yes |
52
+ | gradio API | No | Yes |
53
+
54
+ ---
55
+
56
+ ## 4. **Practical Recommendations**
57
+
58
+ - **For arbitrary Hugging Face Spaces in iframes:**
59
+ - You cannot send/receive data programmatically unless the Space itself is designed to listen for postMessage.
60
+ - **For your own Spaces:**
61
+ - You can add JS to both parent and iframe to use postMessage.
62
+ - **For Gradio tabs:**
63
+ - Use gr.State or shared components for seamless data transfer.
64
+
65
+ ---
66
+
67
+ **If you want a code example for tab-to-tab data sharing, or want to explore advanced iframe communication (with custom JS), let me know!**
app.py CHANGED
@@ -4,58 +4,40 @@ import numpy as np
4
  from style import js_func, css_func
5
  import tempfile
6
  import pandas as pd
 
 
7
  from greeting_tab import greeting_tab
8
  from calculator_tab import calculator_tab
9
  from sepia_tab import sepia_tab
 
10
 
11
- def greet(name="Stranger", intensity=1, exclaim=False):
12
- greeting = f"Hello, {name}{'!' * int(intensity)}"
13
- if exclaim:
14
- greeting = greeting.upper()
15
- return greeting
16
-
17
- def calculator(num1, operation, num2):
18
- if operation == "add":
19
- result = num1 + num2
20
- elif operation == "subtract":
21
- result = num1 - num2
22
- elif operation == "multiply":
23
- result = num1 * num2
24
- elif operation == "divide":
25
- if num2 == 0:
26
- raise gr.Error("Cannot divide by zero!")
27
- result = num1 / num2
28
- return result
29
-
30
- def sepia(input_img):
31
- sepia_filter = np.array([
32
- [0.393, 0.769, 0.189],
33
- [0.349, 0.686, 0.168],
34
- [0.272, 0.534, 0.131]
35
- ])
36
- sepia_img = input_img @ sepia_filter.T
37
- sepia_img = np.clip(sepia_img, 0, 255).astype(np.uint8)
38
- return sepia_img
39
-
40
- def download_text(text):
41
- if not text:
42
- text = ""
43
- with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w", encoding="utf-8") as f:
44
- f.write(text)
45
- return f.name
46
-
47
- def download_csv(result):
48
- if result is None:
49
- result = ""
50
- df = pd.DataFrame({"Result": [result]})
51
- with tempfile.NamedTemporaryFile(delete=False, suffix=".csv", mode="w", encoding="utf-8") as f:
52
- df.to_csv(f, index=False)
53
- return f.name
54
 
55
  theme = gr.Theme.from_hub("LPX55/modal_ai")
56
 
57
  with gr.Blocks(theme=theme, js=js_func, css=css_func) as demo:
58
  show_space_tab = gr.State(False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  with gr.Sidebar(width="25vw"):
60
  gr.Markdown("""
61
  # 🤖 API + MCP Demo
@@ -73,14 +55,13 @@ with gr.Blocks(theme=theme, js=js_func, css=css_func) as demo:
73
  - [Calculator](#calculator)
74
  - [Sepia Image](#sepia-image)
75
  - [Custom IFrame Loader](#custom-iframe-loader)
 
76
  ---
77
  ### [GitHub Repo](https://github.com/yourrepo) | [Docs](https://yourdocs)
78
  ---
79
  **Tips:**
80
  - Try the examples in each tab!
81
  - Download your results with the button on the right.
82
-
83
-
84
  """)
85
  gr.Code(
86
  """from gradio_client import Client
@@ -95,15 +76,83 @@ print(client.predict("Alex", 5, False, api_name="/greet"))
95
  load_sam_iframe_btn = gr.Button("Load SAM2.1 Masking Tool (iframe)", elem_id="load-sam-iframe-btn")
96
  load_sam_api_btn = gr.Button("Load SAM2.1 Masking Tool (API Proxy)", elem_id="load-sam-api-btn")
97
  open_sam_tab_btn = gr.Button("Open SAM2.1 Masking Tool in New Tab", elem_id="open-sam-tab-btn")
 
 
 
 
 
 
 
 
 
 
98
 
99
  with gr.Tab("Greeting"):
100
- greeting_tab()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
  with gr.Tab("Calculator"):
103
- calculator_tab()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  with gr.Tab("Sepia Image"):
106
  sepia_tab()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
  # Add state variables for each dynamic tab
109
  extra_space_open = gr.State(True)
@@ -112,151 +161,20 @@ print(client.predict("Alex", 5, False, api_name="/greet"))
112
  sam_api_tab_open = gr.State(True)
113
  custom_iframe_tab_open = gr.State(True)
114
 
115
- with gr.Tab("Extra Space", visible=False) as extra_space_tab:
116
- @gr.render(inputs=extra_space_open)
117
- def render_extra_space(is_open):
118
- if is_open:
119
- gr.Markdown("## External Gradio Space")
120
- gr.HTML('<iframe src="https://huggingface.co/spaces/gradio/calculator" width="100%" height="600" style="border:none;"></iframe>')
121
- close_btn = gr.Button("Close Tab")
122
- def close_tab():
123
- return gr.Tab(visible=False), False
124
- close_btn.click(fn=close_tab, outputs=[extra_space_tab, extra_space_open])
125
-
126
- with gr.Tab("SAM2.1 Masking Tool (gr.load)", visible=False) as sam_tab:
127
- @gr.render(inputs=sam_tab_open)
128
- def render_sam_tab(is_open):
129
- if is_open:
130
- gr.Markdown("## LPX55/SAM2_1-Image-Predictor-Masking-Tool-CPU (gr.load)")
131
- sam_interface = gr.load("LPX55/SAM2_1-Image-Predictor-Masking-Tool-CPU", src="spaces")
132
- close_btn = gr.Button("Close Tab")
133
- def close_tab():
134
- return gr.Tab(visible=False), False
135
- close_btn.click(fn=close_tab, outputs=[sam_tab, sam_tab_open])
136
-
137
- with gr.Tab("SAM2.1 Masking Tool (iframe)", visible=False) as sam_iframe_tab:
138
- @gr.render(inputs=sam_iframe_tab_open)
139
- def render_sam_iframe_tab(is_open):
140
- if is_open:
141
- gr.Markdown("## LPX55/SAM2_1-Image-Predictor-Masking-Tool-CPU (iframe)")
142
- gr.HTML('<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>')
143
- close_btn = gr.Button("Close Tab")
144
- def close_tab():
145
- return gr.Tab(visible=False), False
146
- close_btn.click(fn=close_tab, outputs=[sam_iframe_tab, sam_iframe_tab_open])
147
-
148
- with gr.Tab("SAM2.1 Masking Tool (API Proxy)", visible=False) as sam_api_tab:
149
- @gr.render(inputs=sam_api_tab_open)
150
- def render_sam_api_tab(is_open):
151
- if is_open:
152
- gr.Markdown("## LPX55/SAM2_1-Image-Predictor-Masking-Tool-CPU (API Proxy)")
153
- api_image = gr.Image(label="Input Image")
154
- api_btn = gr.Button("Run Remote Masking")
155
- api_output = gr.Textbox(label="API Response (raw)")
156
- def call_sam_api(image):
157
- import requests
158
- import base64
159
- import json
160
- if image is None:
161
- return "No image uploaded."
162
- with open(image, "rb") as f:
163
- img_b64 = base64.b64encode(f.read()).decode()
164
- payload = {"data": [img_b64]}
165
- try:
166
- resp = requests.post(
167
- "https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space/run/predict",
168
- json=payload,
169
- timeout=60
170
- )
171
- if resp.status_code == 200:
172
- return json.dumps(resp.json(), indent=2)
173
- else:
174
- return f"Error: {resp.status_code} {resp.text}"
175
- except Exception as e:
176
- return f"Exception: {str(e)}"
177
- api_btn.click(fn=call_sam_api, inputs=api_image, outputs=api_output)
178
- close_btn = gr.Button("Close Tab")
179
- def close_tab():
180
- return gr.Tab(visible=False), False
181
- close_btn.click(fn=close_tab, outputs=[sam_api_tab, sam_api_tab_open])
182
-
183
- with gr.Tab("Custom IFrame Loader") as custom_iframe_tab:
184
- @gr.render(inputs=custom_iframe_tab_open)
185
- def render_custom_iframe_tab(is_open):
186
- if is_open:
187
- gr.Markdown("## Load Any IFrame URL")
188
- custom_url = gr.Textbox(label="IFrame URL", placeholder="https://example.com")
189
- load_custom_iframe_btn = gr.Button("Load IFrame")
190
- custom_iframe = gr.HTML(visible=True)
191
- def load_custom_iframe(url):
192
- if not url:
193
- return "<div style='color:red'>Please enter a URL.</div>"
194
- return f'<iframe src="{url}" width="100%" height="800" style="border:none;"></iframe>'
195
- load_custom_iframe_btn.click(fn=load_custom_iframe, inputs=custom_url, outputs=custom_iframe)
196
- close_btn = gr.Button("Close Tab")
197
- def close_tab():
198
- return gr.Tab(visible=False), False
199
- close_btn.click(fn=close_tab, outputs=[custom_iframe_tab, custom_iframe_tab_open])
200
-
201
- # Iframe lazy load pattern
202
- heavy_iframe_src = gr.State("")
203
- with gr.Tab("Heavy Space (iframe - lazy load)", visible=False) as heavy_iframe_tab:
204
- iframe_html = gr.HTML("")
205
- close_btn = gr.Button("Close Tab")
206
- def close_heavy_iframe_tab():
207
- return gr.Tab(visible=False), ""
208
- close_btn.click(fn=close_heavy_iframe_tab, outputs=[heavy_iframe_tab, iframe_html])
209
- def open_heavy_iframe_tab():
210
- src = '<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>'
211
- return gr.Tab(visible=True), src
212
- open_heavy_iframe_btn = gr.Button("Open Heavy Space (iframe - lazy load)")
213
- open_heavy_iframe_btn.click(fn=open_heavy_iframe_tab, outputs=[heavy_iframe_tab, iframe_html])
214
-
215
- # Iframe always loaded pattern
216
- with gr.Tab("Heavy Space (iframe - always loaded)", visible=True) as heavy_iframe_always_tab:
217
- gr.HTML('<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>')
218
- close_btn2 = gr.Button("Close Tab")
219
- def close_heavy_iframe_always_tab():
220
- return gr.Tab(visible=False)
221
- close_btn2.click(fn=close_heavy_iframe_always_tab, outputs=heavy_iframe_always_tab)
222
- open_heavy_iframe_always_btn = gr.Button("Open Heavy Space (iframe - always loaded)")
223
- def open_heavy_iframe_always_tab():
224
- return gr.Tab(visible=True)
225
- open_heavy_iframe_always_btn.click(fn=open_heavy_iframe_always_tab, outputs=heavy_iframe_always_tab)
226
-
227
  def show_tab():
228
  return gr.Tab(visible=True)
229
 
230
  load_space_btn.click(fn=show_tab, outputs=[extra_space_tab])
231
 
232
- def show_sam_tab():
233
- return gr.Tab(visible=True)
234
-
235
- load_sam_btn.click(fn=show_sam_tab, outputs=[sam_tab])
236
-
237
- def show_sam_iframe_tab():
238
- iframe_html = '<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>'
239
- return gr.Tab(visible=True), iframe_html
240
-
241
- load_sam_iframe_btn.click(fn=show_sam_iframe_tab, outputs=[sam_iframe_tab, sam_iframe])
242
-
243
  def show_sam_api_tab():
244
  return gr.Tab(visible=True)
245
 
246
- load_sam_api_btn.click(fn=show_sam_api_tab, outputs=[sam_api_tab])
247
-
248
  def open_in_new_tab():
249
  # This function does nothing server-side, but the button will have a link
250
  pass
251
 
252
  open_sam_tab_btn.click(fn=open_in_new_tab, inputs=None, outputs=None, js="window.open('https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space', '_blank')")
253
 
254
- gr.Markdown("""
255
- ---
256
- ## 📡 API Usage
257
- - Every function in this demo is automatically available as a REST API!
258
- - View the [OpenAPI schema](./openapi.json) or click "Use via API" in the footer.
259
- - Try the [gradio_client](https://www.gradio.app/guides/getting-started-with-the-python-client) or [@gradio/client](https://www.gradio.app/guides/getting-started-with-the-js-client) to call these endpoints programmatically.
260
- """)
261
 
262
  demo.launch(mcp_server=True)
 
4
  from style import js_func, css_func
5
  import tempfile
6
  import pandas as pd
7
+ from shared_functions import greet, calculator, sepia, download_text, download_csv
8
+
9
  from greeting_tab import greeting_tab
10
  from calculator_tab import calculator_tab
11
  from sepia_tab import sepia_tab
12
+ from space_loader_tab import gr_load_tab, iframe_loader_tab
13
 
14
+ import json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  theme = gr.Theme.from_hub("LPX55/modal_ai")
17
 
18
  with gr.Blocks(theme=theme, js=js_func, css=css_func) as demo:
19
  show_space_tab = gr.State(False)
20
+ # Iframe lazy load pattern
21
+ heavy_iframe_src = gr.State("")
22
+ with gr.Tab("Heavy Space (iframe - lazy load)", visible=False) as heavy_iframe_tab:
23
+ iframe_html = gr.HTML("")
24
+ close_btn = gr.Button("Close Tab")
25
+ def close_heavy_iframe_tab():
26
+ return gr.Tab(visible=False), ""
27
+ close_btn.click(fn=close_heavy_iframe_tab, outputs=[heavy_iframe_tab, iframe_html])
28
+ def open_heavy_iframe_tab():
29
+ src = '<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>'
30
+ return gr.Tab(visible=True), src
31
+ # Iframe always loaded pattern
32
+ with gr.Tab("Heavy Space (iframe - always loaded)", visible=False) as heavy_iframe_always_tab:
33
+ gr.HTML('<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>')
34
+ close_btn2 = gr.Button("Close Tab")
35
+ def close_heavy_iframe_always_tab():
36
+ return gr.Tab(visible=False)
37
+ close_btn2.click(fn=close_heavy_iframe_always_tab, outputs=heavy_iframe_always_tab)
38
+ def open_heavy_iframe_always_tab():
39
+ return gr.Tab(visible=True)
40
+
41
  with gr.Sidebar(width="25vw"):
42
  gr.Markdown("""
43
  # 🤖 API + MCP Demo
 
55
  - [Calculator](#calculator)
56
  - [Sepia Image](#sepia-image)
57
  - [Custom IFrame Loader](#custom-iframe-loader)
58
+ - [Space Loader](#space-loader)
59
  ---
60
  ### [GitHub Repo](https://github.com/yourrepo) | [Docs](https://yourdocs)
61
  ---
62
  **Tips:**
63
  - Try the examples in each tab!
64
  - Download your results with the button on the right.
 
 
65
  """)
66
  gr.Code(
67
  """from gradio_client import Client
 
76
  load_sam_iframe_btn = gr.Button("Load SAM2.1 Masking Tool (iframe)", elem_id="load-sam-iframe-btn")
77
  load_sam_api_btn = gr.Button("Load SAM2.1 Masking Tool (API Proxy)", elem_id="load-sam-api-btn")
78
  open_sam_tab_btn = gr.Button("Open SAM2.1 Masking Tool in New Tab", elem_id="open-sam-tab-btn")
79
+ open_heavy_iframe_btn = gr.Button("Open Heavy Space (iframe - lazy load)")
80
+ open_heavy_iframe_btn.click(fn=open_heavy_iframe_tab, outputs=[heavy_iframe_tab, iframe_html])
81
+ open_heavy_iframe_always_btn = gr.Button("Open Heavy Space (iframe - always loaded)")
82
+ open_heavy_iframe_always_btn.click(fn=open_heavy_iframe_always_tab, outputs=heavy_iframe_always_tab)
83
+
84
+ # All tabs grouped together for a unified tab bar
85
+ shared_state = gr.State({"greeting": None, "calculation": None})
86
+ shared_state_box = gr.JSON(label="Shared Data Between Tabs")
87
+ def pretty_json(state):
88
+ return json.dumps(state, indent=2, ensure_ascii=False)
89
 
90
  with gr.Tab("Greeting"):
91
+ name = gr.Textbox(label="Name", info="Enter your name", placeholder="e.g. Alex")
92
+ intensity = gr.Slider(1, 20, value=3, step=1, label="Intensity", info="How excited should the greeting be?")
93
+ with gr.Accordion("Advanced Options", open=False):
94
+ exclaim = gr.Checkbox(label="Shout (all caps)", info="Make the greeting all uppercase and add exclamations")
95
+ greet_btn = gr.Button("Greet")
96
+ greet_output = gr.Textbox(label="Greeting", lines=2)
97
+ download_greet_btn = gr.DownloadButton(label="Download Greeting", value=download_text, inputs=greet_output)
98
+ gr.Examples(
99
+ [["Jill", 1, False], ["Sam", 3, True], ["Alex", 5, False]],
100
+ inputs=[name, intensity, exclaim],
101
+ outputs=greet_output,
102
+ fn=greet
103
+ )
104
+ def update_greeting_state(greeting, state):
105
+ state = dict(state)
106
+ state["greeting"] = greeting
107
+ return state
108
+ greet_btn.click(greet, [name, intensity, exclaim], greet_output).then(update_greeting_state, [greet_output, shared_state], shared_state)
109
 
110
  with gr.Tab("Calculator"):
111
+ num1 = gr.Number(label="Number 1", info="First number")
112
+ operation = gr.Radio(["add", "subtract", "multiply", "divide"], label="Operation", info="Choose the operation")
113
+ num2 = gr.Number(label="Number 2", info="Second number")
114
+ calc_btn = gr.Button("Calculate")
115
+ calc_output = gr.Number(label="Result")
116
+ download_calc_btn = gr.DownloadButton(label="Download Result", value=download_csv, inputs=calc_output)
117
+ gr.Examples(
118
+ [[45, "add", 3], [3.14, "divide", 2], [144, "multiply", 2.5], [0, "subtract", 1.2]],
119
+ inputs=[num1, operation, num2],
120
+ outputs=calc_output,
121
+ fn=calculator
122
+ )
123
+ def update_calc_state(result, state):
124
+ state = dict(state)
125
+ state["calculation"] = result
126
+ return state
127
+ calc_btn.click(calculator, [num1, operation, num2], calc_output).then(update_calc_state, [calc_output, shared_state], shared_state)
128
 
129
  with gr.Tab("Sepia Image"):
130
  sepia_tab()
131
+ with gr.Tab("Space Loader (gr.load)"):
132
+ gr_load_tab()
133
+ with gr.Tab("Space Loader (iframe)"):
134
+ iframe_loader_tab()
135
+ with gr.Tab("Extra Space", visible=False) as extra_space_tab:
136
+ gr.Markdown("## External Gradio Space")
137
+ gr.HTML('<iframe src="https://huggingface.co/spaces/gradio/calculator" width="100%" height="600" style="border:none;"></iframe>')
138
+ close_btn = gr.Button("Close Tab")
139
+ def close_tab():
140
+ return gr.Tab(visible=False)
141
+ close_btn.click(fn=close_tab, outputs=extra_space_tab)
142
+ with gr.Tab("Custom IFrame Loader") as custom_iframe_tab:
143
+ gr.Markdown("## Load Any IFrame URL")
144
+ custom_url = gr.Textbox(label="IFrame URL", placeholder="https://example.com")
145
+ load_custom_iframe_btn = gr.Button("Load IFrame")
146
+ custom_iframe = gr.HTML(visible=True)
147
+ def load_custom_iframe(url):
148
+ if not url:
149
+ return "<div style='color:red'>Please enter a URL.</div>"
150
+ return f'<iframe src="{url}" width="100%" height="800" style="border:none;"></iframe>'
151
+ load_custom_iframe_btn.click(fn=load_custom_iframe, inputs=custom_url, outputs=custom_iframe)
152
+ close_btn = gr.Button("Close Tab")
153
+ def close_tab_custom():
154
+ return gr.Tab(visible=False)
155
+ close_btn.click(fn=close_tab_custom, outputs=custom_iframe_tab)
156
 
157
  # Add state variables for each dynamic tab
158
  extra_space_open = gr.State(True)
 
161
  sam_api_tab_open = gr.State(True)
162
  custom_iframe_tab_open = gr.State(True)
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  def show_tab():
165
  return gr.Tab(visible=True)
166
 
167
  load_space_btn.click(fn=show_tab, outputs=[extra_space_tab])
168
 
 
 
 
 
 
 
 
 
 
 
 
169
  def show_sam_api_tab():
170
  return gr.Tab(visible=True)
171
 
 
 
172
  def open_in_new_tab():
173
  # This function does nothing server-side, but the button will have a link
174
  pass
175
 
176
  open_sam_tab_btn.click(fn=open_in_new_tab, inputs=None, outputs=None, js="window.open('https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space', '_blank')")
177
 
178
+ shared_state.change(pretty_json, shared_state, shared_state_box)
 
 
 
 
 
 
179
 
180
  demo.launch(mcp_server=True)
calculator_tab.py CHANGED
@@ -1,5 +1,5 @@
1
  import gradio as gr
2
- from app import calculator, download_csv
3
 
4
  def calculator_tab():
5
  gr.Markdown("## Toy Calculator")
 
1
  import gradio as gr
2
+ from shared_functions import calculator, download_csv
3
 
4
  def calculator_tab():
5
  gr.Markdown("## Toy Calculator")
greeting_tab.py CHANGED
@@ -1,5 +1,5 @@
1
  import gradio as gr
2
- from app import greet, download_text
3
 
4
  def greeting_tab():
5
  gr.Markdown("## Greeting Generator")
 
1
  import gradio as gr
2
+ from shared_functions import greet, download_text
3
 
4
  def greeting_tab():
5
  gr.Markdown("## Greeting Generator")
sepia_tab.py CHANGED
@@ -1,5 +1,5 @@
1
  import gradio as gr
2
- from app import sepia
3
 
4
  def sepia_tab():
5
  gr.Markdown("## Sepia Image Filter")
 
1
  import gradio as gr
2
+ from shared_functions import sepia
3
 
4
  def sepia_tab():
5
  gr.Markdown("## Sepia Image Filter")
shared_functions.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+ import pandas as pd
3
+ import numpy as np
4
+ import gradio as gr
5
+
6
+ def greet(name="Stranger", intensity=1, exclaim=False):
7
+ greeting = f"Hello, {name}{'!' * int(intensity)}"
8
+ if exclaim:
9
+ greeting = greeting.upper()
10
+ return greeting
11
+
12
+ def calculator(num1, operation, num2):
13
+ if operation == "add":
14
+ result = num1 + num2
15
+ elif operation == "subtract":
16
+ result = num1 - num2
17
+ elif operation == "multiply":
18
+ result = num1 * num2
19
+ elif operation == "divide":
20
+ if num2 == 0:
21
+ raise gr.Error("Cannot divide by zero!")
22
+ result = num1 / num2
23
+ return result
24
+
25
+ def sepia(input_img):
26
+ sepia_filter = np.array([
27
+ [0.393, 0.769, 0.189],
28
+ [0.349, 0.686, 0.168],
29
+ [0.272, 0.534, 0.131]
30
+ ])
31
+ sepia_img = input_img @ sepia_filter.T
32
+ sepia_img = np.clip(sepia_img, 0, 255).astype(np.uint8)
33
+ return sepia_img
34
+
35
+ def download_text(text):
36
+ if not text:
37
+ text = ""
38
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w", encoding="utf-8") as f:
39
+ f.write(text)
40
+ return f.name
41
+
42
+ def download_csv(result):
43
+ if result is None:
44
+ result = ""
45
+ df = pd.DataFrame({"Result": [result]})
46
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".csv", mode="w", encoding="utf-8") as f:
47
+ df.to_csv(f, index=False)
48
+ return f.name
space_loader_tab.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ POPULAR_SPACES = [
4
+ "gradio/calculator",
5
+ "gradio/image-classification",
6
+ "huggingface-projects/llama-2-7b-chat",
7
+ "gradio/englishtranslator",
8
+ "gradio/blocks-gallery"
9
+ ]
10
+
11
+ def gr_load_tab():
12
+ gr.Markdown("## Load a Popular Hugging Face Space (gr.load)")
13
+ space_dropdown = gr.Dropdown(POPULAR_SPACES, label="Popular Spaces", interactive=True)
14
+ load_btn = gr.Button("Load Space")
15
+ error_box = gr.Markdown(visible=False)
16
+ with gr.Column():
17
+ gr.Markdown("### gr.load() Interface")
18
+ loaded_interface = gr.Blocks()
19
+
20
+ def load_space(space):
21
+ if not space or "/" not in space:
22
+ return gr.update(visible=True, value="**Error:** Please select a valid space name."), None
23
+ try:
24
+ interface = gr.load(space, src="spaces")
25
+ except Exception as e:
26
+ return gr.update(visible=True, value=f"**Error loading space:** {e}"), None
27
+ return gr.update(visible=False), interface
28
+
29
+ load_btn.click(
30
+ fn=load_space,
31
+ inputs=space_dropdown,
32
+ outputs=[error_box, loaded_interface]
33
+ )
34
+
35
+ def iframe_loader_tab():
36
+ gr.Markdown("## Load Any Hugging Face Space (iframe)")
37
+ with gr.Row():
38
+ space_name = gr.Textbox(label="Space Name", placeholder="e.g. gradio/calculator")
39
+ space_dropdown = gr.Dropdown(POPULAR_SPACES, label="Popular Spaces", interactive=True)
40
+ load_btn = gr.Button("Load Space")
41
+ error_box = gr.Markdown(visible=False)
42
+ with gr.Column():
43
+ gr.Markdown("### Space IFrame")
44
+ iframe_html = gr.HTML("")
45
+
46
+ def get_space_name(text, dropdown):
47
+ return text if text else dropdown
48
+
49
+ def load_space(space):
50
+ if not space or "/" not in space:
51
+ return gr.update(visible=True, value="**Error:** Please enter a valid space name (e.g. gradio/calculator)."), ""
52
+ space_id = space.replace("/", "-")
53
+ iframe_url = f"https://{space_id}.hf.space?__theme=dark"
54
+ iframe = f'<iframe src="{iframe_url}" width="100%" height="600" style="border:none;"></iframe>'
55
+ return gr.update(visible=False), iframe
56
+
57
+ load_btn.click(
58
+ fn=get_space_name,
59
+ inputs=[space_name, space_dropdown],
60
+ outputs=space_name
61
+ ).then(
62
+ fn=load_space,
63
+ inputs=space_name,
64
+ outputs=[error_box, iframe_html]
65
+ )