Files
video-shader-toys/ui/src/components/StackPresetToolbar.jsx
Aiden 05d0bcbedd
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 1m35s
CI / Windows Release Package (push) Successful in 2m17s
PNG writer
2026-05-08 15:33:40 +10:00

117 lines
3.8 KiB
JavaScript

import { Camera, FolderOpen, RefreshCw, Save } from "lucide-react";
import { useState } from "react";
import { postJson } from "../api/controlApi";
export function StackPresetToolbar({
presetName,
selectedPresetName,
stackPresets,
onPresetNameChange,
onSelectedPresetNameChange,
}) {
const [screenshotQueued, setScreenshotQueued] = useState(false);
async function requestScreenshot() {
setScreenshotQueued(true);
try {
await postJson("/api/screenshot", {});
} finally {
window.setTimeout(() => setScreenshotQueued(false), 1200);
}
}
return (
<div className="panel stack-panel">
<div className="panel__header stack-panel__header">
<div>
<h3>Stack presets</h3>
<p className="muted">Save or recall the current layer chain.</p>
</div>
<div className="stack-panel__actions">
<button
type="button"
className="button-with-icon stack-panel__screenshot"
onClick={requestScreenshot}
>
<Camera size={16} strokeWidth={1.9} aria-hidden="true" />
<span>{screenshotQueued ? "Queued" : "Screenshot"}</span>
</button>
<button
type="button"
className="button-with-icon stack-panel__reload"
onClick={() => postJson("/api/reload", {})}
>
<RefreshCw size={16} strokeWidth={1.9} aria-hidden="true" />
<span>Reload shader</span>
</button>
</div>
</div>
<div className="stack-panel__grid">
<div className="toolbar__group">
<label htmlFor="preset-name">Save stack</label>
<div className="toolbar__inline">
<input
id="preset-name"
type="text"
placeholder="Preset name"
value={presetName}
onChange={(event) => onPresetNameChange(event.target.value)}
/>
<button
type="button"
className="button-with-icon"
disabled={!presetName.trim()}
onClick={() => {
const trimmedName = presetName.trim();
if (!trimmedName) {
return;
}
postJson("/api/stack-presets/save", { presetName: trimmedName });
onSelectedPresetNameChange(
trimmedName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""),
);
}}
>
<Save size={16} strokeWidth={1.9} aria-hidden="true" />
<span>Save</span>
</button>
</div>
</div>
<div className="toolbar__group">
<label htmlFor="preset-select">Recall stack</label>
<div className="toolbar__inline">
<select
id="preset-select"
value={selectedPresetName}
onChange={(event) => onSelectedPresetNameChange(event.target.value)}
>
{stackPresets.length === 0 ? <option value="">No presets</option> : null}
{stackPresets.map((preset) => (
<option key={preset} value={preset}>
{preset}
</option>
))}
</select>
<button
type="button"
className="button-with-icon"
disabled={!selectedPresetName}
onClick={() => {
if (selectedPresetName) {
postJson("/api/stack-presets/load", { presetName: selectedPresetName });
}
}}
>
<FolderOpen size={16} strokeWidth={1.9} aria-hidden="true" />
<span>Recall</span>
</button>
</div>
</div>
</div>
</div>
);
}