The c{id} DOM ID pattern was wrong. Use document.querySelector with
the timeline-graph class instead, with retries until g.node elements
are present in the DOM.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
splines=ortho triggers a trapezoid-table overflow assertion in
graphviz's dot layout engine on complex graphs. polyline gives
similar angled edges without the crash.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move JS back to ui.run_javascript() with retry-based DOM lookup
using NiceGUI's element ID (c{id}). CSS stays inline via style tag.
Retries up to 10 times at 50ms intervals to handle Vue async render.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previous approach used ui.run_javascript with getElement() which
failed due to Vue rendering timing. Now embeds the script and style
directly inside the HTML content so there are no DOM lookup or
timing issues — the script runs inline when parsed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The click handlers weren't attaching because getElementById couldn't
find the container — Python's id() generated IDs that didn't survive
NiceGUI's DOM rendering. Now uses getElement() with the NiceGUI
element ID and defers JS via requestAnimationFrame to ensure the
DOM is ready.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stop replacing the SVG's width/height attributes — this was shrinking
the graph to fit the container. Instead keep graphviz's native pt
dimensions and let the scroll container handle overflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Drop the fixed height attribute entirely instead of setting it to
"auto", which SVGs don't support. The viewBox attribute handles
proportional scaling when only width="100%" is set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add click-to-select functionality to the graphviz SVG timeline graph.
Clicking a node highlights it with an amber border, auto-switches the
branch selector, and updates the node manager panel. The SVG is now
responsive (100% width, scroll container) instead of fixed-size.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace flat dropdown with branch selector showing node counts,
scrollable node list with HEAD/tip badges, and inline actions panel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Deep-copy node data on restore to prevent edits from mutating
stored history snapshots
- Guard glob calls against non-existent current_dir
- Read current selection at delete time instead of using stale
render-time capture
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sync dict_input/dict_textarea/LoRA inputs on update:model-value
(not just blur) to prevent silent data loss on quick saves
- Split LoRA into name + strength fields, default strength to 1.0
- Stack LoRAs one per line instead of 3-card row
- Collapse "Add New Sequence from Source File" into expansion
- Add file selector to Pane A in dual-pane mode
- Clear secondary pane state on directory change
- Fix file radio resetting to first file on refresh
- Handle bare-list JSON files and inf/nan edge cases
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dict_number() only wrote to seq[key] on blur, so changing a value
(e.g. via spinner arrows) and immediately clicking Save could race
the save ahead of the blur on the server. Now also syncs on
update:model-value so the dict is always current.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace red accent with amber, add Inter font, introduce 4-level depth
palette via CSS variables, expand padding/gaps, wrap sidebar and content
sections in cards, add section/subsection header typography classes, and
style scrollbars for dark theme. Pure visual changes — no functional or
data-flow modifications.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dict_number() defaulted to 0 while mode_label used default of 1,
causing visual inconsistency when 'vace schedule' key is missing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
NiceGUI's ui.number returns float values, so seeds, steps, dimensions
etc. were being stored as floats (e.g. 42.0) instead of integers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update badge, installation instructions, port references, and file
structure to reflect the migration from Streamlit to NiceGUI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use set_options() instead of direct .options assignment (3 locations)
so dropdown changes actually reach the browser
- Wrap res.json() in try/except for non-JSON server responses
- Deep copy in create_batch and promote to match rest of codebase
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- save_config calls now pass full config to preserve comfy settings
- Mass update section moved inside refreshable to stay in sync
- Deep copy source data to prevent shared mutable references
- Clipboard copy uses json.dumps instead of repr() for safe JS
- Comfy monitor uses async IO (run_in_executor) to avoid blocking
- Auto-timeout now updates checkbox and refreshes live view UI
- Image URLs properly URL-encoded with urllib.parse.urlencode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces row/col grid with a resizable splitter at 66/34 ratio,
matching the original Streamlit st.columns([2, 1]) layout. Removes
extra card wrapper from sequences to maximize content width.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add page/sidebar background contrast, wrap action button rows,
ensure dark text in inputs, and improve timeline card highlight colors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The recovery formula now matches the storage formula per mode:
End Extend subtracts only A, Pre Extend subtracts only B.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Formula changes per VACE schedule: End Extend uses base+A,
Pre Extend uses base+B, others use base+A+B
- Snap total to 4n+1 to match VACE sampler
- Show mode name label next to schedule number
- Add mode reference popover with all formulas
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unused `random` import and `KEY_PROMPT_HISTORY` from app.py
- Remove dead session state keys: edit_history_idx, append_prompt, rand_seed
- Clean up extra blank lines in json_loader.py
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
UI shows the base value (vace_length - input_a - input_b) for editing,
saves the computed total back to the JSON.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Types were lost on workflow reload because only key names were stored.
Now both keys and types are saved in hidden widgets and restored by
onConfigure, so colored connector dots persist without needing Refresh.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API route now returns types alongside keys. JS sets output slot type
accordingly, giving correct colored dots and type-safe connections.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>