export const styleGroups={Render:['Photorealistic','Pixar','3D Disney','Comic','Watercolor','Oil painting'],Quality:['Realistic skin','Skin pores','Fine detail','Natural texture'],Lighting:['Golden hour','Soft studio','Window light','Overcast','Cinematic lighting']} export const defaultNegatives=['blurry','deformed','low quality','text','watermark'] export function normalizeStyles(value={}) { const known=[...Object.values(styleGroups).flat(),...defaultNegatives] const positive=[...new Set((value.positive||[]).filter(s=>known.includes(s)))] // Freeform negatives are allowed (sticky custom chips); positives stay on the known style list. const negative=[...new Set((value.negative||[]).map(s=>String(s||'').trim()).filter(s=>s&&!positive.includes(s)))] return {positive,negative} } export function toggleStyle(value,chip,negative=false) { const next=normalizeStyles(value),key=negative?'negative':'positive',other=negative?'positive':'negative';next[other]=next[other].filter(s=>s!==chip);next[key]=next[key].includes(chip)?next[key].filter(s=>s!==chip):[...next[key],chip];return next } export function stylePrompt(value,negative=false){return normalizeStyles(value)[negative?'negative':'positive'].join(', ')} /** Single blank line (mobile / video / edit batchText). */ export function parseBatch(value){return String(value||'').split(/\r?\n\s*\r?\n/).map(s=>s.trim()).filter(Boolean)} /** * Desktop image Batch toggle: split only on a double blank line (two empty lines → \n\n\n+). * A single newline or a single blank line stays inside the same prompt. */ export function parseBatchDoubleBlank(value){ return String(value||'').split(/\r?\n(?:[ \t]*\r?\n){2,}/).map(s=>s.trim()).filter(Boolean) }