87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
/**
|
|
* CAD-14 Phase 4a - Werkzeug-Optionen-Panel.
|
|
*
|
|
* Rendert das optionsSchema des aktiven V2-Werkzeugs und bindet
|
|
* die Werte an den toolOptionsService (Quelle fuer den Dispatcher).
|
|
*/
|
|
import React, { useState, useEffect, useMemo } from 'react';
|
|
import { pluginRegistry } from '../plugins';
|
|
import { getToolOption, setToolOption, subscribeToolOptions } from '../services/toolOptionsService';
|
|
|
|
interface ToolOptionsPanelProps {
|
|
activeToolId: string | null | undefined;
|
|
}
|
|
|
|
const ToolOptionsPanel: React.FC<ToolOptionsPanelProps> = ({ activeToolId }) => {
|
|
const [, forceRender] = useState(0);
|
|
|
|
// Store-Abonnement: Panel bei Optionsaenderung neu rendern
|
|
React.useEffect(() => {
|
|
return subscribeToolOptions(() => forceRender((n) => n + 1));
|
|
}, []);
|
|
|
|
const tool = useMemo(() => {
|
|
if (!activeToolId) return null;
|
|
return pluginRegistry.getToolV2(activeToolId) ?? null;
|
|
}, [activeToolId]);
|
|
|
|
const schema = tool?.optionsSchema ?? [];
|
|
if (!tool || schema.length === 0) return null;
|
|
|
|
const renderField = (field: { key: string; label: string; type: string; min?: number; max?: number; options?: Array<{ value: string; label: string }> }) => {
|
|
const value = getToolOption(tool.manifest.id, field.key);
|
|
const onChange = (v: unknown) => setToolOption(tool.manifest.id, field.key, v);
|
|
if (field.type === 'number') {
|
|
return (
|
|
<label key={field.key} className="toolopt-row">
|
|
<span>{field.label}</span>
|
|
<input
|
|
type="number"
|
|
value={typeof value === 'number' ? value : Number(value) || 0}
|
|
min={field.min}
|
|
onChange={(e) => onChange(Number(e.target.value))}
|
|
/>
|
|
</label>
|
|
);
|
|
}
|
|
if (field.type === 'color') {
|
|
return (
|
|
<label key={field.key} className="toolopt-row">
|
|
<span>{field.label}</span>
|
|
<input type="color" value={String(value ?? '#9aa0a6')} onChange={(e) => onChange(e.target.value)} />
|
|
</label>
|
|
);
|
|
}
|
|
if (field.type === 'select' && field.options) {
|
|
return (
|
|
<label key={field.key} className="toolopt-row">
|
|
<span>{field.label}</span>
|
|
<select value={String(value ?? '')} onChange={(e) => onChange(e.target.value)}>
|
|
{field.options.map((o) => (
|
|
<option key={o.value} value={o.value}>{o.label}</option>
|
|
))}
|
|
</select>
|
|
</label>
|
|
);
|
|
}
|
|
if (field.type === 'boolean') {
|
|
return (
|
|
<label key={field.key} className="toolopt-row toolopt-check">
|
|
<input type="checkbox" checked={value === true} onChange={(e) => onChange(e.target.checked)} />
|
|
<span>{field.label}</span>
|
|
</label>
|
|
);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
return (
|
|
<div className="tool-options-panel">
|
|
<div className="toolopt-title">Werkzeug-Optionen: {tool.manifest.label}</div>
|
|
{schema.map((f) => renderField(f as never))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ToolOptionsPanel;
|