Spaces:
Sleeping
Sleeping
Download frontend/src/components/AdvancedOptions.tsx from Hamza4100/cookie-har-analyzer: direct link, hf CLI and curl.
- Browser
- Download file 5.25 kB
-
https://huggingface.co/spaces/Hamza4100/cookie-har-analyzer/resolve/main/frontend/src/components/AdvancedOptions.tsx
- Command line
-
hf download hf://spaces/Hamza4100/cookie-har-analyzer/frontend/src/components/AdvancedOptions.tsx
-
curl -L -o AdvancedOptions.tsx https://huggingface.co/spaces/Hamza4100/cookie-har-analyzer/resolve/main/frontend/src/components/AdvancedOptions.tsx
5.25 kB
| import { useState } from 'react'; | |
| import { ChevronDown, ChevronUp, Settings2 } from 'lucide-react'; | |
| import { AnalysisOptions } from '../types'; | |
| interface AdvancedOptionsProps { | |
| options: AnalysisOptions; | |
| onChange: (opts: Partial<AnalysisOptions>) => void; | |
| } | |
| function Toggle({ | |
| id, | |
| label, | |
| description, | |
| checked, | |
| onChange, | |
| }: { | |
| id: string; | |
| label: string; | |
| description?: string; | |
| checked: boolean; | |
| onChange: (v: boolean) => void; | |
| }) { | |
| return ( | |
| <label | |
| htmlFor={id} | |
| className="flex items-start gap-3 cursor-pointer group" | |
| > | |
| <div className="relative flex-shrink-0 mt-0.5"> | |
| <input | |
| type="checkbox" | |
| id={id} | |
| checked={checked} | |
| onChange={e => onChange(e.target.checked)} | |
| className="sr-only" | |
| /> | |
| <div | |
| className={`w-9 h-5 rounded-full border transition-all duration-200 ${ | |
| checked | |
| ? 'bg-blue-600 border-blue-500' | |
| : 'bg-white/5 border-white/15 group-hover:border-white/25' | |
| }`} | |
| > | |
| <div | |
| className={`absolute top-0.5 w-4 h-4 rounded-full bg-white shadow transition-all duration-200 ${ | |
| checked ? 'translate-x-4' : 'translate-x-0.5' | |
| }`} | |
| /> | |
| </div> | |
| </div> | |
| <div> | |
| <p className="text-sm font-medium text-gray-200">{label}</p> | |
| {description && <p className="text-xs text-gray-500 mt-0.5">{description}</p>} | |
| </div> | |
| </label> | |
| ); | |
| } | |
| function NumberInput({ | |
| id, | |
| label, | |
| value, | |
| min, | |
| max, | |
| onChange, | |
| }: { | |
| id: string; | |
| label: string; | |
| value: number; | |
| min: number; | |
| max: number; | |
| onChange: (v: number) => void; | |
| }) { | |
| return ( | |
| <div className="flex items-center justify-between gap-4"> | |
| <label htmlFor={id} className="text-sm text-gray-300 flex-1">{label}</label> | |
| <input | |
| type="number" | |
| id={id} | |
| value={value} | |
| min={min} | |
| max={max} | |
| onChange={e => onChange(Number(e.target.value))} | |
| className="w-20 input-field text-center py-1" | |
| /> | |
| </div> | |
| ); | |
| } | |
| export function AdvancedOptions({ options, onChange }: AdvancedOptionsProps) { | |
| const [open, setOpen] = useState(false); | |
| return ( | |
| <div className="card overflow-hidden"> | |
| <button | |
| id="advanced-options-toggle" | |
| className="w-full flex items-center justify-between px-4 py-3 text-left hover:bg-white/[0.02] transition-colors" | |
| onClick={() => setOpen(o => !o)} | |
| > | |
| <span className="flex items-center gap-2 text-sm font-medium text-gray-300"> | |
| <Settings2 className="w-4 h-4 text-gray-500" /> | |
| Advanced Options | |
| </span> | |
| {open ? ( | |
| <ChevronUp className="w-4 h-4 text-gray-500" /> | |
| ) : ( | |
| <ChevronDown className="w-4 h-4 text-gray-500" /> | |
| )} | |
| </button> | |
| {open && ( | |
| <div className="px-4 pb-4 divider border-t pt-4 space-y-4 animate-fade-in"> | |
| <div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> | |
| <Toggle | |
| id="opt-case-sensitive" | |
| label="Case-sensitive matching" | |
| description="Disable to also find case-insensitive matches" | |
| checked={options.case_sensitive} | |
| onChange={v => onChange({ case_sensitive: v })} | |
| /> | |
| <Toggle | |
| id="opt-url-decoded" | |
| label="Search URL-decoded values" | |
| description="Matches percent-encoded representations" | |
| checked={options.search_url_decoded} | |
| onChange={v => onChange({ search_url_decoded: v })} | |
| /> | |
| <Toggle | |
| id="opt-include-req-bodies" | |
| label="Include request bodies" | |
| description="Search POST/PUT body content" | |
| checked={options.include_request_bodies} | |
| onChange={v => onChange({ include_request_bodies: v })} | |
| /> | |
| <Toggle | |
| id="opt-include-resp-bodies" | |
| label="Include response bodies" | |
| description="Search response content (slower for large HAR)" | |
| checked={options.include_response_bodies} | |
| onChange={v => onChange({ include_response_bodies: v })} | |
| /> | |
| </div> | |
| <div className="space-y-3 pt-2 border-t border-white/[0.06]"> | |
| <NumberInput | |
| id="opt-min-snippet" | |
| label="Minimum snippet length" | |
| value={options.min_snippet_length} | |
| min={2} | |
| max={20} | |
| onChange={v => onChange({ min_snippet_length: v })} | |
| /> | |
| <NumberInput | |
| id="opt-max-results" | |
| label="Max results per cookie" | |
| value={options.max_results_per_cookie} | |
| min={10} | |
| max={1000} | |
| onChange={v => onChange({ max_results_per_cookie: v })} | |
| /> | |
| <NumberInput | |
| id="opt-context-chars" | |
| label="Context window (chars)" | |
| value={options.context_chars} | |
| min={20} | |
| max={300} | |
| onChange={v => onChange({ context_chars: v })} | |
| /> | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |