WalisonCruz/function-gemma
0
1import gradio as gr2 3 4class ColoredCheckboxGroup(gr.HTML):5 def __init__(6 self,7 choices: list[str] | None = None,8 *,9 value: list[str] | None = None,10 colors: list[str] | None = None,11 label: str | None = None,12 **kwargs,13 ):14 html_template = """15 <div class="colored-checkbox-container">16 <div class="header-row">17 <label class="checkbox-label select-all-label">18 <input type="checkbox" class="select-all-input">19 </label>20 ${label ? `<span class="container-label">${label}</span>` : ''}21 </div>22 <div class="colored-checkbox-group">23 ${choices.map((choice, i) => `24 <label class="checkbox-label item-checkbox">25 <input type="checkbox" value="${choice}" ${(value || []).includes(choice) ? 'checked' : ''}>26 <span class="color-dot" style="background: ${colors[i]};"></span>27 ${choice}28 </label>29 `).join('')}30 </div>31 </div>32 """33 34 css_template = """35 .colored-checkbox-container {36 border: 1px solid var(--border-color-primary);37 border-radius: var(--radius-lg);38 padding: var(--spacing-lg);39 background-color: var(--block-background-fill);40 }41 .header-row {42 display: flex;43 align-items: center;44 margin-bottom: var(--spacing-md);45 }46 .container-label {47 color: var(--block-title-text-color);48 }49 .colored-checkbox-group {50 display: flex;51 flex-direction: column;52 gap: 6px;53 max-height: 280px;54 overflow-y: auto;55 }56 .checkbox-label { display: flex; align-items: center; cursor: pointer; }57 .checkbox-label input { margin-right: 8px; }58 .color-dot {59 width: 10px;60 height: 10px;61 border-radius: 50%;62 margin-right: 6px;63 flex-shrink: 0;64 }65 """66 67 js_on_load = """68 function getCheckboxes() {69 return element.querySelectorAll('.item-checkbox input[type="checkbox"]');70 }71 72 function getSelectAllInput() {73 return element.querySelector('.select-all-input');74 }75 76 function updateSelectAllState() {77 const checkboxes = getCheckboxes();78 const selectAllInput = getSelectAllInput();79 if (!selectAllInput) return;80 const total = checkboxes.length;81 const checked = Array.from(checkboxes).filter(cb => cb.checked).length;82 if (checked === total && total > 0) {83 selectAllInput.checked = true;84 selectAllInput.indeterminate = false;85 } else if (checked > 0) {86 selectAllInput.checked = false;87 selectAllInput.indeterminate = true;88 } else {89 selectAllInput.checked = false;90 selectAllInput.indeterminate = false;91 }92 }93 94 function updateValue() {95 const checkboxes = getCheckboxes();96 props.value = Array.from(checkboxes)97 .filter(cb => cb.checked)98 .map(cb => cb.value);99 updateSelectAllState();100 trigger('input');101 }102 103 element.addEventListener('change', (e) => {104 if (e.target.classList.contains('select-all-input')) {105 const shouldCheck = e.target.checked;106 getCheckboxes().forEach(cb => { cb.checked = shouldCheck; });107 updateValue();108 } else if (e.target.closest('.item-checkbox')) {109 updateValue();110 }111 });112 113 const observer = new MutationObserver(() => {114 updateSelectAllState();115 });116 observer.observe(element, { childList: true, subtree: true, attributes: true });117 118 updateSelectAllState();119 """120 121 super().__init__(122 value=value or [],123 html_template=html_template,124 css_template=css_template,125 js_on_load=js_on_load,126 choices=choices,127 colors=colors,128 label=label,129 **kwargs,130 )131 132 def api_info(self):133 return {134 "items": {"enum": self.props["choices"], "type": "string"},135 "title": "Checkbox Group",136 "type": "array",137 }138 139 140if __name__ == "__main__":141 142 def generate_color_variants(color: str, count: int):143 if color.startswith("rgb"):144 rgb_values = (145 color.replace("rgba", "").replace("rgb", "").strip("()").split(",")146 )147 r, g, b = (148 int(float(rgb_values[0])),149 int(float(rgb_values[1])),150 int(float(rgb_values[2])),151 )152 else:153 r = int(color[1:3], 16)154 g = int(color[3:5], 16)155 b = int(color[5:7], 16)156 157 colors = []158 for i in range(count):159 factor = 0.3 + (0.7 * i / max(count - 1, 1))160 nr = int(r * factor + (255 - r * factor) * (1 - factor) * 0.3)161 ng = int(g * factor + (255 - g * factor) * (1 - factor) * 0.3)162 nb = int(b * factor + (255 - b * factor) * (1 - factor) * 0.3)163 nr, ng, nb = min(255, nr), min(255, ng), min(255, nb)164 colors.append(f"#{nr:02x}{ng:02x}{nb:02x}")165 return colors166 167 def update_colors(color: str, s: int):168 items = [f"Item {i + 1} ({s + 1})" for i in range(12)]169 colors = generate_color_variants(color, len(items))170 return ColoredCheckboxGroup(171 choices=items,172 colors=colors,173 label=f"Runs ({s + 1})",174 ), s + 1175 176 with gr.Blocks() as demo:177 s = gr.State(0)178 with gr.Row():179 with gr.Column():180 cp = gr.ColorPicker(value="#FF0000")181 with gr.Column(scale=2):182 items = [f"Item {i + 1}" for i in range(15)]183 colors = generate_color_variants("#FF0000", len(items))184 cg = ColoredCheckboxGroup(185 choices=items,186 colors=colors,187 label="Runs",188 )189 gr.Interface(190 fn=lambda x: " ".join(x),191 inputs=cg,192 outputs=gr.Textbox(label="output"),193 )194 cp.change(195 update_colors, inputs=[cp, s], outputs=[cg, s], show_progress="hidden"196 )197 demo.launch()198 