Spaces:
Running
Running
| import { ALL_STEMS, STEM_CONFIG } from "../types"; | |
| interface StemCheckboxesProps { | |
| selected: string[]; | |
| onChange: (stems: string[]) => void; | |
| disabled?: boolean; | |
| } | |
| export function StemCheckboxes({ | |
| selected, | |
| onChange, | |
| disabled, | |
| }: StemCheckboxesProps) { | |
| const toggle = (stem: string) => { | |
| if (selected.includes(stem)) { | |
| onChange(selected.filter((s) => s !== stem)); | |
| } else { | |
| onChange([...selected, stem]); | |
| } | |
| }; | |
| const allSelected = selected.length === ALL_STEMS.length; | |
| const toggleAll = () => { | |
| onChange(allSelected ? [] : [...ALL_STEMS]); | |
| }; | |
| return ( | |
| <div className="space-y-3"> | |
| <div className="flex items-center justify-between"> | |
| <span className="text-sm font-medium text-text-secondary"> | |
| Select stems to separate | |
| </span> | |
| <button | |
| onClick={toggleAll} | |
| disabled={disabled} | |
| className="text-xs text-text-secondary hover:text-text-primary transition-colors disabled:opacity-50" | |
| > | |
| {allSelected ? "Deselect All" : "Select All"} | |
| </button> | |
| </div> | |
| <div className="grid grid-cols-2 md:grid-cols-3 gap-2"> | |
| {ALL_STEMS.map((stem) => { | |
| const config = STEM_CONFIG[stem]; | |
| const checked = selected.includes(stem); | |
| return ( | |
| <button | |
| key={stem} | |
| onClick={() => toggle(stem)} | |
| disabled={disabled} | |
| className={` | |
| flex items-center gap-2 px-3 py-2.5 rounded-lg border transition-all text-sm | |
| ${ | |
| checked | |
| ? "border-transparent" | |
| : "border-border hover:border-text-secondary" | |
| } | |
| disabled:opacity-50 | |
| `} | |
| style={ | |
| checked | |
| ? { | |
| backgroundColor: config.color + "15", | |
| borderColor: config.color + "40", | |
| } | |
| : undefined | |
| } | |
| > | |
| <span | |
| className="w-3 h-3 rounded-full flex-shrink-0" | |
| style={{ backgroundColor: checked ? config.color : "#4a4a5a" }} | |
| /> | |
| <span | |
| className="font-medium" | |
| style={{ color: checked ? config.color : undefined }} | |
| > | |
| {config.label} | |
| </span> | |
| </button> | |
| ); | |
| })} | |
| </div> | |
| </div> | |
| ); | |
| } | |