init
This commit is contained in:
79
src/components/VariablePalette.jsx
Normal file
79
src/components/VariablePalette.jsx
Normal 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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user