import { type Component, createSignal } from 'solid-js';
import { saveAsNew } from '~/stores/presetStore';
import { closePanel, requestSnapshot } from '~/stores/uiStore';
import { X } from './icons/Icon';
export const SaveDialog: Component = () => {
const [name, setName] = createSignal('');
let inputRef: HTMLInputElement | undefined;
setTimeout(() => inputRef?.focus(), 50);
const submit = () => {
const n = name().trim();
if (!n) return;
try {
saveAsNew(n);
// Capture the canvas as the new preset's thumbnail immediately —
// saveAsNew triggers a respawn that won't be presented until the
// next RAF, so engine.snapshot() at this point still reads the
// last-rendered frame (which already shows the preset's look,
// since the edited state was running pre-save). Without this the
// new card sits with the gradient placeholder for ~4s until the
// auto-snapshot at frame 240 catches up.
requestSnapshot();
closePanel();
} catch (err) {
// Surface failures instead of swallowing them silently — saving used
// to fail on the reactive proxy without any user-visible signal.
console.error('Save preset failed:', err);
}
};
return (
// biome-ignore lint/a11y/useKeyWithClickEvents: backdrop dismissal — Escape key handled by useHotkeys
<div
style={{
position: 'absolute',
inset: '0',
'z-index': '40',
display: 'grid',
'place-items': 'center',
background: 'color-mix(in oklab, var(--void-000) 60%, transparent)',
'backdrop-filter': 'blur(8px)',
}}
onClick={(e) => {
if (e.currentTarget === e.target) closePanel();
}}
>
<form
onSubmit={(e) => {
e.preventDefault();
submit();
}}
style={{
width: '420px',
background: 'var(--surface-overlay)',
border: '1px solid var(--border-default)',
'border-radius': 'var(--radius-lg)',
'box-shadow': 'var(--shadow-modal)',
padding: '20px',
display: 'flex',
'flex-direction': 'column',
gap: '16px',
}}
>
<div style={{ display: 'flex', 'align-items': 'center' }}>
<div style={{ flex: '1', display: 'flex', 'flex-direction': 'column', gap: '4px' }}>
<span class="phys-eyebrow">Save as new</span>
<span
style={{
'font-family': 'var(--font-display)',
'font-size': '20px',
'font-weight': '600',
color: 'var(--fg-primary)',
}}
>
Name your preset
</span>
</div>
<button type="button" class="phys-iconbtn" onClick={() => closePanel()}>
<X />
</button>
</div>
<input
ref={inputRef}
type="text"
value={name()}
onInput={(e) => setName(e.currentTarget.value)}
placeholder="e.g. Slow Coral"
maxLength={64}
style={{
background: 'var(--surface-inset)',
border: '1px solid var(--border-default)',
'border-radius': 'var(--radius-md)',
color: 'var(--fg-primary)',
'font-family': 'var(--font-body)',
'font-size': '14px',
padding: '10px 12px',
outline: 'none',
}}
/>
<div style={{ display: 'flex', gap: '8px' }}>
<button type="button" class="phys-btn" data-variant="ghost" onClick={() => closePanel()}>
Cancel
</button>
<div style={{ flex: '1' }} />
<button type="submit" class="phys-btn" data-variant="primary" disabled={!name().trim()}>
Save
</button>
</div>
</form>
</div>
);
};