This commit is contained in:
2026-03-03 16:43:30 +00:00
commit 03452517b5
58 changed files with 13181 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
import { useState } from 'react'
import { VARIABLES, CATEGORIES } from '../engine/variables.js'
import { PaletteCard } from './VariableCard.jsx'
export function VariablePalette({ workspaceVarIds, onAddVariable }) {
const [search, setSearch] = useState('')
const [collapsed, setCollapsed] = useState({})
const toggleCategory = (cat) =>
setCollapsed(prev => ({ ...prev, [cat]: !prev[cat] }))
const q = search.toLowerCase()
const filtered = (varIds) =>
varIds.filter(id => {
if (!q) return true
const v = VARIABLES[id]
return (
v.name.toLowerCase().includes(q) ||
v.symbol.toLowerCase().includes(q) ||
v.id.toLowerCase().includes(q)
)
})
// Group vars by category
const byCategory = {}
for (const [id, v] of Object.entries(VARIABLES)) {
if (!byCategory[v.category]) byCategory[v.category] = []
byCategory[v.category].push(id)
}
return (
<aside className="flex flex-col h-full bg-slate-900 border-r border-slate-700 w-64 shrink-0">
<div className="p-3 border-b border-slate-700">
<h2 className="text-slate-300 font-semibold text-sm mb-2 tracking-wide uppercase">Variables</h2>
<input
type="text"
value={search}
onChange={e => setSearch(e.target.value)}
placeholder="Search…"
className="w-full bg-slate-800 border border-slate-600 rounded-md px-2 py-1.5 text-sm text-slate-200 placeholder-slate-500 outline-none focus:border-blue-500"
/>
</div>
<div className="flex-1 overflow-y-auto p-2 space-y-1">
{CATEGORIES.map(cat => {
const ids = filtered(byCategory[cat] ?? [])
if (ids.length === 0) return null
const isCollapsed = collapsed[cat]
return (
<div key={cat}>
<button
onClick={() => toggleCategory(cat)}
className="w-full flex items-center justify-between px-2 py-1.5 rounded-md text-xs font-semibold text-slate-400 uppercase tracking-wider hover:text-slate-200 hover:bg-slate-800 transition-colors"
>
<span>{cat}</span>
<span>{isCollapsed ? '▶' : '▼'}</span>
</button>
{!isCollapsed && (
<div className="space-y-1 mt-1 ml-1">
{ids.map(id => (
<div
key={id}
onDoubleClick={() => !workspaceVarIds.includes(id) && onAddVariable(id)}
title={VARIABLES[id].description}
>
<PaletteCard varId={id} isInWorkspace={workspaceVarIds.includes(id)} />
</div>
))}
</div>
)}
</div>
)
})}
</div>
<div className="p-2 border-t border-slate-700 text-xs text-slate-500 text-center">
Drag or double-click to add
</div>
</aside>
)
}