diff --git a/docs/concepts/prompt-variant-timeline.html b/docs/concepts/prompt-variant-timeline.html index 097c25c..e177be0 100644 --- a/docs/concepts/prompt-variant-timeline.html +++ b/docs/concepts/prompt-variant-timeline.html @@ -7,8 +7,8 @@ Prompt history · ComfyAssets prototype @@ -17,7 +17,7 @@

Prompt history

One positive prompt. Every negative experiment.

Sample data and illustrative previews.
Everything here stays in this browser tab.

-
Positive prompt · unchanged

A remote alpine observatory at blue hour, warm light through glass, dramatic mountain peaks, cinematic composition, atmospheric mist, fine detail

Landscapes
+
Positive prompt · unchanged

A remote alpine observatory at blue hour, warm light through glass, dramatic mountain peaks, cinematic composition, atmospheric mist, fine detail

Landscapes

Negative variants

Click a red dot to inspect a negative. Small dots are repeat runs. Select a variant for its full run history.
+ Positive− Negative variantRunSaved, not run
@@ -76,6 +76,14 @@ function renderGraph(){ } function termDiff(a,b){const before=a.split(',').map(s=>s.trim()).filter(Boolean),after=b.split(',').map(s=>s.trim()).filter(Boolean);const root=el('div','diff-terms');for(const term of before){const node=el(after.includes(term)?'span':'del','',after.includes(term)?term:`− ${term}`);root.append(node,document.createTextNode(', '));}for(const term of after.filter(term=>!before.includes(term)))root.append(el('ins','',`+ ${term}`),document.createTextNode(', '));if(!before.length&&!after.length)root.textContent='Both negatives are explicitly empty.';return root;} function simulate(id){const minute=clock;clock+=4;runs.push({id:`r${runs.length+1}`,variant:id,minute,seed:42001+runs.length*3});const variant=getVariant(id);if(variantRuns(id).length===1)variant.created=minute;selected=id;selectedRun=null;render();announce(`Simulated one run of ${variant.name}: 3 images added. The positive prompt is unchanged.`);} +function renderSelectedNegative(){ + const target=$('selected-negative');target.replaceChildren(); + const ids=comparing?comparison:selected?[selected]:[]; + function row(label,text){const item=el('div','prompt-summary-row'),symbol=el('span','role-symbol negative-symbol','−');symbol.setAttribute('aria-hidden','true');const content=el('div','content');content.append(el('div','eyebrow',label),el('p','negative-text',text));item.append(symbol,content);target.append(item);} + if(!ids.length){row(comparing?'Negative prompts · comparison':'Negative prompts · all variants',comparing?'Select two red dots to compare their negative prompts.':'Multiple negative variants are included. Select a red dot to see its negative prompt here.');return;} + ids.forEach((id,index)=>{const variant=getVariant(id);row(`Negative prompt · ${comparing?(index===0?'From':'To')+' · ':''}${variant.name}${selectedRun?` · Run #${selectedRun.slice(1)}`:''}`,variant.text||'No negative prompt (explicitly empty)');}); + if(comparing&&ids.length===1)target.append(el('p','hint','Select another red dot to show the second negative below.')); +} function renderInspector(){ const target=$('inspector');target.replaceChildren(); if(comparing){target.append(el('div','eyebrow overview','Compare negatives'),el('h3','',comparison.length===2?'What changed?':'Pick two red dots'),el('p','',comparison.length===2?'Changes are shown by comma-separated term. Blue is added; struck-through red is removed.':'Select two different negative variants in the timeline or filters.')); @@ -97,7 +105,7 @@ function renderGallery(){ const grid=$('images');grid.replaceChildren();if(!shown.length)grid.append(el('div','empty','Saved for later. Simulate a run to add images to this gallery.')); shown.forEach(image=>{const v=getVariant(image.run.variant),b=createButton('','image-card');b.setAttribute('aria-label',`Open ${v.name}, run ${image.run.id.slice(1)}, seed ${image.seed}`);const img=el('img');img.src=scene(image);img.alt='';img.loading='lazy';const info=el('span','image-info');info.append(el('span','image-title',`Observatory · ${image.seed}`));const meta=el('span','image-meta');meta.append(el('span','negative-badge',`− ${v.name}`),el('span','',`Run #${image.run.id.slice(1)}`));info.append(meta);b.append(img,info);b.addEventListener('click',()=>openImage(image));grid.append(b);}); } -function render(){const focusKey=document.activeElement?.dataset.focusKey,focusId=document.activeElement?.id;const used=variants.filter(v=>variantRuns(v.id).length).length;const stats=$('stats');stats.replaceChildren();for(const [count,label]of[[runs.length,'tracked runs'],[sampleImages().length,'images'],[used,'used negatives'],[variants.length-used,'saved idea'+(variants.length-used===1?'':'s')]]){const span=el('span');span.append(el('strong','',String(count)),document.createTextNode(` ${label}`));stats.append(span);}const compare=$('compare');compare.setAttribute('aria-pressed',String(comparing));compare.textContent=comparing?'Exit comparison':'Compare negatives';renderGraph();renderInspector();renderGallery();if(focusKey)document.querySelector(`[data-focus-key="${focusKey}"]`)?.focus({preventScroll:true});else if(focusId)$(focusId)?.focus({preventScroll:true});} +function render(){const focusKey=document.activeElement?.dataset.focusKey,focusId=document.activeElement?.id;const used=variants.filter(v=>variantRuns(v.id).length).length;const stats=$('stats');stats.replaceChildren();for(const [count,label]of[[runs.length,'tracked runs'],[sampleImages().length,'images'],[used,'used negatives'],[variants.length-used,'saved idea'+(variants.length-used===1?'':'s')]]){const span=el('span');span.append(el('strong','',String(count)),document.createTextNode(` ${label}`));stats.append(span);}const compare=$('compare');compare.setAttribute('aria-pressed',String(comparing));compare.textContent=comparing?'Exit comparison':'Compare negatives';renderSelectedNegative();renderGraph();renderInspector();renderGallery();if(focusKey)document.querySelector(`[data-focus-key="${focusKey}"]`)?.focus({preventScroll:true});else if(focusId)$(focusId)?.focus({preventScroll:true});} scope.listen($('compare'),'click',()=>{comparing=!comparing;comparison=comparing&&selected?[selected]:[];selectedRun=null;if(!comparing)selected=null;render();announce(comparing?'Choose two negative variants to compare.':'Showing all variants.');}); scope.listen($('new-variant'),'click',()=>{$('add-form').reset();$('add-dialog').showModal();}); for(const id of['close-add','cancel-add'])scope.listen($(id),'click',()=>$('add-dialog').close());scope.listen($('close-image'),'click',()=>$('image-dialog').close());