| """ |
| HF-Master Shared Components |
| Reusable Gradio components for all projects |
| """ |
|
|
| import html |
| from pathlib import Path |
| import gradio as gr |
| from typing import List, Tuple, Optional, Dict, Any |
|
|
|
|
| class SharedComponents: |
| """Shared UI components for all HF-Master projects""" |
|
|
| @staticmethod |
| def _esc(value: Any) -> str: |
| """Escape text before placing it inside shared HTML components.""" |
| return html.escape(str(value), quote=True) |
|
|
| @staticmethod |
| def _style_tag() -> str: |
| """Inline the shared stylesheet for Gradio Spaces that do not pass css=.""" |
| style_path = Path(__file__).with_name("styles.css") |
| try: |
| return f"<style>{style_path.read_text(encoding='utf-8')}</style>" |
| except OSError: |
| return "" |
|
|
| @staticmethod |
| def create_header(title: str, description: str, emoji: str = "π") -> gr.Markdown: |
| """Create standardized project header""" |
| return SharedComponents.create_premium_hero( |
| title=title, |
| description=description, |
| emoji=emoji, |
| badge="AI/ML Space", |
| highlights=["Interactive demo", "Explainable workflow", "HF-ready"], |
| ) |
|
|
| @staticmethod |
| def create_footer(version: str = "1.0.0") -> gr.Markdown: |
| """Create standardized project footer""" |
| return gr.Markdown(f""" |
| <div class="hf-footer"> |
| <strong>{SharedComponents._esc(version)}</strong> Β· Built as a practical AI/ML learning Space for the Hugging Face community. |
| </div> |
| """) |
|
|
| @staticmethod |
| def create_premium_hero( |
| title: str, |
| description: str, |
| emoji: str = "π", |
| badge: str = "Featured Space", |
| highlights: Optional[List[str]] = None, |
| ) -> gr.HTML: |
| """Create a richer landing-page hero for Spaces.""" |
| highlights = highlights or [] |
| esc = SharedComponents._esc |
| chips = "".join( |
| f""" |
| <span class="hf-chip">{esc(item)}</span> |
| """ |
| for item in highlights |
| ) |
|
|
| return gr.HTML(f""" |
| {SharedComponents._style_tag()} |
| <div class="hf-hero"> |
| <div class="hf-hero-grid"> |
| <div class="hf-hero-copy"> |
| <div class="hf-icon">{esc(emoji)}</div> |
| <div> |
| <div class="hf-badge">{esc(badge)}</div> |
| <h1>{esc(title)}</h1> |
| <p>{esc(description)}</p> |
| </div> |
| </div> |
| </div> |
| <div class="hf-chip-row"> |
| {chips} |
| </div> |
| </div> |
| """) |
|
|
| @staticmethod |
| def create_method_panel(items: Dict[str, str]) -> gr.HTML: |
| """Create a compact method/pipeline explainer panel.""" |
| esc = SharedComponents._esc |
| cards = "".join( |
| f""" |
| <div class="hf-method-card"> |
| <span>{esc(label)}</span> |
| <p>{esc(text)}</p> |
| </div> |
| """ |
| for label, text in items.items() |
| ) |
| return gr.HTML(f"""{SharedComponents._style_tag()}<div class="hf-method-grid">{cards}</div>""") |
|
|
| @staticmethod |
| def create_status_badge(status: str) -> str: |
| """Create status badge""" |
| colors = { |
| "complete": "π’", |
| "in-progress": "π‘", |
| "planned": "βͺ", |
| "experimental": "π΄" |
| } |
| return colors.get(status.lower(), "βͺ") |
|
|
| @staticmethod |
| def create_project_card( |
| title: str, |
| description: str, |
| tech_stack: List[str], |
| difficulty: str, |
| viral_potential: str |
| ) -> str: |
| """Create markdown project card""" |
| tech_badges = " ".join([f"`{t}`" for t in tech_stack]) |
|
|
| return f""" |
| ## {title} |
| |
| {description} |
| |
| **Tech Stack:** {tech_badges} |
| |
| **Difficulty:** {difficulty} | **Viral Potential:** {viral_potential} |
| """ |
|
|
| @staticmethod |
| def create_risk_chart(risk_factors: Dict[str, float]) -> Any: |
| """Create risk factor visualization""" |
| import plotly.graph_objects as go |
|
|
| factors = list(risk_factors.keys()) |
| scores = [risk_factors[f] * 100 for f in factors] |
|
|
| fig = go.Figure(data=[ |
| go.Bar( |
| x=scores, |
| y=[f.replace('_', ' ').title() for f in factors], |
| orientation='h', |
| marker=dict( |
| color=scores, |
| colorscale='RdYlGn_r', |
| cmin=0, |
| cmax=100 |
| ) |
| ) |
| ]) |
|
|
| fig.update_layout( |
| title="Risk Factor Breakdown", |
| xaxis_title="Risk Score", |
| yaxis_title="Factor", |
| height=400, |
| template="plotly_white" |
| ) |
|
|
| return fig |
|
|
| @staticmethod |
| def create_comparison_chart(items: List[Dict], keys: List[str]) -> Any: |
| """Create comparison visualization""" |
| import plotly.graph_objects as go |
|
|
| fig = go.Figure() |
|
|
| for i, item in enumerate(items): |
| fig.add_trace(go.Bar( |
| name=item.get('name', f'Item {i+1}'), |
| x=keys, |
| y=[item.get(k, 0) for k in keys] |
| )) |
|
|
| fig.update_layout( |
| barmode='group', |
| height=400 |
| ) |
|
|
| return fig |
|
|
| @staticmethod |
| def create_metric_card(label: str, value: str, emoji: str = "π") -> gr.Markdown: |
| """Create metric display card""" |
| return gr.Markdown(f""" |
| ### {emoji} {label} |
| |
| **{value}** |
| """) |
|
|
| @staticmethod |
| def create_error_display(error: str) -> gr.Markdown: |
| """Create error message display""" |
| return gr.Markdown(f""" |
| β **Error** |
| |
| {error} |
| """) |
|
|
| @staticmethod |
| def create_success_display(message: str) -> gr.Markdown: |
| """Create success message display""" |
| return gr.Markdown(f""" |
| β
**Success** |
| |
| {message} |
| """) |
|
|
|
|
| class LoadingSpinner: |
| """Loading state display""" |
|
|
| @staticmethod |
| def create_spinner(message: str = "Loading...") -> gr.Markdown: |
| """Create loading spinner""" |
| return gr.Markdown(f""" |
| β³ **{message}** |
| |
| _This may take a moment..._ |
| """) |
|
|
| @staticmethod |
| def create_progress_bar(initial: float = 0) -> gr.Markdown: |
| """Create progress display""" |
| return gr.Markdown(f""" |
| βββββββββ **{initial}%** |
| """) |
|
|
|
|
| class TableFormatter: |
| """Format data as tables""" |
|
|
| @staticmethod |
| def format_dict_table(data: Dict[str, Any], headers: List[str] = None) -> List: |
| """Format dictionary as table rows""" |
| if not headers: |
| headers = ["Key", "Value"] |
|
|
| rows = [] |
| for key, value in data.items(): |
| rows.append([key, str(value)]) |
|
|
| return [headers] + rows |
|
|
| @staticmethod |
| def create_dataframe(data: List[Dict], columns: List[str] = None) -> List: |
| """Create dataframe-compatible data structure""" |
| if not data: |
| return [] |
|
|
| if columns: |
| headers = columns |
| else: |
| headers = list(data[0].keys()) if data else [] |
|
|
| rows = [[row.get(h, "") for h in headers] for row in data] |
|
|
| return [headers] + rows |
|
|
|
|
| class CodeHighlighter: |
| """Code display and highlighting""" |
|
|
| @staticmethod |
| def create_code_display(code: str, language: str = "python") -> gr.Code: |
| """Create code display block""" |
| return gr.Code( |
| value=code, |
| language=language, |
| lines=20 |
| ) |
|
|
| @staticmethod |
| def create_copy_button(code: str) -> gr.Button: |
| """Create copy-to-clipboard button""" |
| return gr.Button("π Copy Code") |
|
|
| @staticmethod |
| def create_diff_view(old_code: str, new_code: str) -> Tuple[gr.Code, gr.Code]: |
| """Create side-by-side diff view""" |
| return ( |
| gr.Code(value=old_code, language="python", lines=15, label="Before"), |
| gr.Code(value=new_code, language="python", lines=15, label="After") |
| ) |
|
|
|
|
| def create_header(title: str, description: str, emoji: str = "π") -> gr.Markdown: |
| return SharedComponents.create_header(title, description, emoji) |
|
|
|
|
| def create_footer(version: str = "1.0.0") -> gr.Markdown: |
| return SharedComponents.create_footer(version) |
|
|
|
|
| def create_premium_hero( |
| title: str, |
| description: str, |
| emoji: str = "π", |
| badge: str = "Featured Space", |
| highlights: Optional[List[str]] = None, |
| ) -> gr.HTML: |
| return SharedComponents.create_premium_hero(title, description, emoji, badge, highlights) |
|
|
|
|
| def create_method_panel(items: Dict[str, str]) -> gr.HTML: |
| return SharedComponents.create_method_panel(items) |
|
|
|
|
| class ProgressTracker: |
| """Track multi-step progress""" |
|
|
| def __init__(self, steps: List[str]): |
| self.steps = steps |
| self.current = 0 |
|
|
| def get_status(self) -> str: |
| """Get current status""" |
| completed = "β
" + "\n".join(self.steps[:self.current]) |
| current = f"π {self.steps[self.current]}" if self.current < len(self.steps) else "" |
| remaining = "\n".join([f"β¬ {s}" for s in self.steps[self.current+1:]]) |
|
|
| return f""" |
| ## Progress |
| |
| {completed} |
| {current} |
| {remaining} |
| """ |
|
|
| def advance(self) -> bool: |
| """Move to next step""" |
| if self.current < len(self.steps): |
| self.current += 1 |
| return True |
| return False |
|
|
| def reset(self): |
| """Reset progress""" |
| self.current = 0 |
|
|
|
|
| def create_tabbed_interface(tabs: Dict[str, Any]) -> gr.Blocks: |
| """Create tabbed interface helper""" |
| with gr.Blocks() as demo: |
| with gr.Tabs(): |
| for tab_name, tab_content in tabs.items(): |
| with gr.Tab(tab_name): |
| tab_content |
|
|
| return demo |
|
|
|
|
| def create_side_by_side(left_content: Any, right_content: Any) -> Tuple[gr.Column, gr.Column]: |
| """Create side-by-side layout""" |
| with gr.Row(): |
| with gr.Column(): |
| left_content |
| with gr.Column(): |
| right_content |
|
|
| return left_content, right_content |
|
|
|
|
| def create_accordion(items: List[Tuple[str, Any]]) -> gr.Accordion: |
| """Create accordion-style expandable sections""" |
| with gr.Accordion("Click to expand") as accordion: |
| for title, content in items: |
| gr.Markdown(f"### {title}") |
| content |
|
|
| return accordion |
|
|