Spaces:
Sleeping
Sleeping
| import React, { useState, useEffect, useRef } from 'react'; | |
| import { Settings } from 'lucide-react'; | |
| import { LAYOUT_MODES, PANEL_KEYS, PANEL_LABELS } from '../utils/settings'; | |
| const LAYOUT_OPTIONS = [ | |
| { id: LAYOUT_MODES.RANDOM, label: 'Random seed (default)', hint: 'Layout may shift on each run' }, | |
| { id: LAYOUT_MODES.FIXED_SEED, label: 'Fixed seed', hint: 'Same layout every run unless topology changes' }, | |
| { id: LAYOUT_MODES.EXPLICIT, label: 'Explicit coordinates', hint: 'Fixed positions; physics off' }, | |
| ]; | |
| export default function SettingsMenu({ settings, onChange }) { | |
| const [open, setOpen] = useState(false); | |
| const wrapRef = useRef(null); | |
| useEffect(() => { | |
| if (!open) return undefined; | |
| const onDocClick = (e) => { | |
| if (wrapRef.current && !wrapRef.current.contains(e.target)) { | |
| setOpen(false); | |
| } | |
| }; | |
| document.addEventListener('mousedown', onDocClick); | |
| return () => document.removeEventListener('mousedown', onDocClick); | |
| }, [open]); | |
| const setLayoutMode = (layoutMode) => { | |
| onChange({ ...settings, layoutMode }); | |
| }; | |
| const togglePanel = (key) => { | |
| onChange({ | |
| ...settings, | |
| panels: { ...settings.panels, [key]: !settings.panels[key] }, | |
| }); | |
| }; | |
| return ( | |
| <div className="ccai-dropdown-wrap decidron-settings-wrap" ref={wrapRef}> | |
| <button | |
| type="button" | |
| className="btn-sm btn-outline icon-btn decidron-settings-trigger" | |
| onClick={() => setOpen((v) => !v)} | |
| title="Settings" | |
| aria-expanded={open} | |
| aria-haspopup="true" | |
| > | |
| <Settings size={16} /> | |
| </button> | |
| {open && ( | |
| <div className="ccai-dropdown-panel decidron-settings-panel" role="menu"> | |
| <div className="ccai-dropdown-section"> | |
| <div className="ccai-dropdown-section-title">Diagram node placement</div> | |
| {LAYOUT_OPTIONS.map((opt) => ( | |
| <label key={opt.id} className="decidron-settings-radio"> | |
| <input | |
| type="radio" | |
| name="layoutMode" | |
| checked={settings.layoutMode === opt.id} | |
| onChange={() => setLayoutMode(opt.id)} | |
| /> | |
| <span> | |
| <strong>{opt.label}</strong> | |
| <span className="decidron-settings-hint">{opt.hint}</span> | |
| </span> | |
| </label> | |
| ))} | |
| </div> | |
| <div className="ccai-dropdown-divider" /> | |
| <div className="ccai-dropdown-section"> | |
| <div className="ccai-dropdown-section-title">Right-side panels</div> | |
| {PANEL_KEYS.map((key) => ( | |
| <label key={key} className="ccai-dropdown-item decidron-settings-check"> | |
| <input | |
| type="checkbox" | |
| checked={!!settings.panels[key]} | |
| onChange={() => togglePanel(key)} | |
| /> | |
| <span className="ccai-dropdown-item-text"> | |
| <span className="ccai-dropdown-item-name">{PANEL_LABELS[key]}</span> | |
| </span> | |
| </label> | |
| ))} | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |