Team Ai
Apppublic

WalisonCruz/function-gemma

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
colored_dropdown.pyi296 linesDownload Raw Back to components
1import gradio as gr2 3from gradio.events import Dependency4 5class ColoredDropdown(gr.HTML):6    def __init__(7        self,8        choices: list[str] | None = None,9        *,10        placeholder: str = "Select...",11        value: str | None = None,12        colors: list[str] | None = None,13        label: str | None = None,14        **kwargs,15    ):16        html_template = """17        <div class="colored-dropdown-container">18            ${label ? `<span class="dropdown-label">${label}</span>` : ''}19            <div class="dropdown-wrapper">20                <button type="button" class="dropdown-trigger">21                    <span class="selected-display">22                        ${value ? `<span class="color-dot" style="background: ${colors[choices.indexOf(value)]};"></span>${value}` : `<span class="placeholder">${placeholder}</span>`}23                    </span>24                    <svg class="dropdown-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">25                        <polyline points="6 9 12 15 18 9"></polyline>26                    </svg>27                </button>28                <div class="dropdown-menu">29                    ${choices.map((choice, i) => `30                        <div class="dropdown-item ${value === choice ? 'selected' : ''}" data-value="${choice}" data-color="${colors[i]}">31                            <span class="color-dot" style="background: ${colors[i]};"></span>32                            <span class="item-text">${choice}</span>33                        </div>34                    `).join('')}35                </div>36            </div>37        </div>38        """39 40        css_template = """41        .colored-dropdown-container {42            display: flex;43            flex-direction: column;44            gap: var(--spacing-sm);45            overflow: visible;46        }47        .dropdown-label {48            color: var(--block-title-text-color);49            font-size: var(--text-sm);50            font-weight: 500;51        }52        .dropdown-wrapper {53            position: relative;54            z-index: 1;55        }56        .dropdown-trigger {57            width: 100%;58            display: flex;59            align-items: center;60            justify-content: space-between;61            padding: 8px 12px;62            border: 1px solid var(--border-color-primary);63            border-radius: var(--radius-md);64            background: var(--input-background-fill);65            color: var(--body-text-color);66            cursor: pointer;67            font-size: var(--text-md);68            text-align: left;69            transition: border-color 0.15s ease;70        }71        .dropdown-trigger:hover {72            border-color: var(--border-color-accent);73        }74        .dropdown-trigger:focus {75            outline: none;76            border-color: var(--color-accent);77            box-shadow: 0 0 0 2px var(--color-accent-soft);78        }79        .selected-display {80            display: flex;81            align-items: center;82            gap: 8px;83            flex: 1;84            overflow: hidden;85            text-overflow: ellipsis;86            white-space: nowrap;87        }88        .placeholder {89            color: var(--input-placeholder-color);90        }91        .dropdown-arrow {92            width: 16px;93            height: 16px;94            flex-shrink: 0;95            transition: transform 0.2s ease;96        }97        .dropdown-wrapper.open .dropdown-arrow {98            transform: rotate(180deg);99        }100        .dropdown-menu {101            position: fixed;102            max-height: 240px;103            overflow-y: auto;104            background: var(--background-fill-primary);105            border: 1px solid var(--border-color-primary);106            border-radius: var(--radius-md);107            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);108            z-index: 9999;109            display: none;110        }111        .dropdown-wrapper.open .dropdown-menu {112            display: block;113        }114        .dropdown-item {115            display: flex;116            align-items: center;117            gap: 8px;118            padding: 8px 12px;119            cursor: pointer;120            transition: background 0.1s ease;121        }122        .dropdown-item:hover {123            background: var(--background-fill-secondary);124        }125        .dropdown-item.selected {126            background: var(--color-accent-soft);127        }128        .item-text {129            overflow: hidden;130            text-overflow: ellipsis;131            white-space: nowrap;132        }133        .color-dot {134            width: 10px;135            height: 10px;136            border-radius: 50%;137            flex-shrink: 0;138        }139        """140 141        js_on_load = """142        const wrapper = element.querySelector('.dropdown-wrapper');143        const triggerButton = element.querySelector('.dropdown-trigger');144        const menu = element.querySelector('.dropdown-menu');145        const selectedDisplay = element.querySelector('.selected-display');146        147        function positionMenu() {148            const rect = triggerButton.getBoundingClientRect();149            menu.style.position = 'fixed';150            menu.style.top = (rect.bottom + 4) + 'px';151            menu.style.left = rect.left + 'px';152            menu.style.width = rect.width + 'px';153            menu.style.right = 'auto';154        }155        156        triggerButton.addEventListener('click', (e) => {157            e.stopPropagation();158            wrapper.classList.toggle('open');159            if (wrapper.classList.contains('open')) {160                positionMenu();161            }162        });163        164        menu.addEventListener('click', (e) => {165            const item = e.target.closest('.dropdown-item');166            if (!item) return;167            168            const value = item.dataset.value;169            const color = item.dataset.color;170            171            menu.querySelectorAll('.dropdown-item').forEach(el => el.classList.remove('selected'));172            item.classList.add('selected');173            174            selectedDisplay.innerHTML = `<span class="color-dot" style="background: ${color};"></span>${value}`;175            176            props.value = value;177            trigger('input');178            179            wrapper.classList.remove('open');180        });181        182        document.addEventListener('click', (e) => {183            if (!element.contains(e.target)) {184                wrapper.classList.remove('open');185            }186        });187        188        window.addEventListener('resize', () => {189            if (wrapper.classList.contains('open')) {190                positionMenu();191            }192        });193        194        window.addEventListener('scroll', () => {195            if (wrapper.classList.contains('open')) {196                positionMenu();197            }198        }, true);199        200        triggerButton.addEventListener('keydown', (e) => {201            if (e.key === 'Enter' || e.key === ' ') {202                e.preventDefault();203                wrapper.classList.toggle('open');204                if (wrapper.classList.contains('open')) {205                    positionMenu();206                }207            } else if (e.key === 'Escape') {208                wrapper.classList.remove('open');209            }210        });211        """212 213        super().__init__(214            value=value,215            html_template=html_template,216            css_template=css_template,217            js_on_load=js_on_load,218            choices=choices,219            colors=colors,220            label=label,221            placeholder=placeholder,222            **kwargs,223        )224 225    def api_info(self):226        return {227            "enum": self.props["choices"],228            "title": "Dropdown",229            "type": "string",230        }231    from typing import Callable, Literal, Sequence, Any, TYPE_CHECKING232    from gradio.blocks import Block233    if TYPE_CHECKING:234        from gradio.components import Timer235        from gradio.components.base import Component236 237 238if __name__ == "__main__":239 240    def generate_color_variants(color: str, count: int):241        if color.startswith("rgb"):242            rgb_values = (243                color.replace("rgba", "").replace("rgb", "").strip("()").split(",")244            )245            r, g, b = (246                int(float(rgb_values[0])),247                int(float(rgb_values[1])),248                int(float(rgb_values[2])),249            )250        else:251            r = int(color[1:3], 16)252            g = int(color[3:5], 16)253            b = int(color[5:7], 16)254 255        colors = []256        for i in range(count):257            factor = 0.3 + (0.7 * i / max(count - 1, 1))258            nr = int(r * factor + (255 - r * factor) * (1 - factor) * 0.3)259            ng = int(g * factor + (255 - g * factor) * (1 - factor) * 0.3)260            nb = int(b * factor + (255 - b * factor) * (1 - factor) * 0.3)261            nr, ng, nb = min(255, nr), min(255, ng), min(255, nb)262            colors.append(f"#{nr:02x}{ng:02x}{nb:02x}")263        return colors264 265    def update_dropdown(color: str, s: int):266        items = [f"Item {i + 1} ({s + 1})" for i in range(12)]267        colors = generate_color_variants(color, len(items))268        return ColoredDropdown(269            choices=items,270            colors=colors,271            label=f"Select Item ({s + 1})",272        ), s + 1273 274    with gr.Blocks() as demo:275        s = gr.State(0)276        with gr.Row():277            with gr.Column():278                cp = gr.ColorPicker(value="#FF0000", label="Base Color")279            with gr.Column(scale=2):280                items = [f"Item {i + 1}" for i in range(15)]281                colors = generate_color_variants("#FF0000", len(items))282                dropdown = ColoredDropdown(283                    choices=items,284                    colors=colors,285                    label="Select Item",286                    value=items[0],287                )288                output = gr.Textbox(label="Selected Value")289                dropdown.input(lambda x: x, inputs=dropdown, outputs=output)290        cp.change(291            update_dropdown,292            inputs=[cp, s],293            outputs=[dropdown, s],294            show_progress="hidden",295        )296    demo.launch()