[{"data":1,"prerenderedAt":736},["ShallowReactive",2],{"content-\u002Fdocs\u002Frecipes\u002Fundo-redo":3},{"id":4,"title":5,"body":6,"description":19,"extension":730,"meta":731,"navigation":352,"path":732,"seo":733,"stem":734,"__hash__":735},"docs\u002Fdocs\u002Frecipes\u002Fundo-redo.md","Undo \u002F redo",{"type":7,"value":8,"toc":722},"minimark",[9,13,88,92,116,121,224,250,254,257,583,587,601,604,632,636,667,681,685,707,711,718],[10,11,5],"h1",{"id":12},"undo-redo",[14,15,20],"pre",{"className":16,"code":17,"language":18,"meta":19,"style":19},"language-ts shiki shiki-themes github-light github-dark","const form = useForm({\n  schema,\n  key: 'signup',\n  history: true, \u002F\u002F default: 50-snapshot bounded stack\n})\n","ts","",[21,22,23,47,53,66,82],"code",{"__ignoreMap":19},[24,25,28,32,36,39,43],"span",{"class":26,"line":27},"line",1,[24,29,31],{"class":30},"szBVR","const",[24,33,35],{"class":34},"sj4cs"," form",[24,37,38],{"class":30}," =",[24,40,42],{"class":41},"sScJk"," useForm",[24,44,46],{"class":45},"sVt8B","({\n",[24,48,50],{"class":26,"line":49},2,[24,51,52],{"class":45},"  schema,\n",[24,54,56,59,63],{"class":26,"line":55},3,[24,57,58],{"class":45},"  key: ",[24,60,62],{"class":61},"sZZnC","'signup'",[24,64,65],{"class":45},",\n",[24,67,69,72,75,78],{"class":26,"line":68},4,[24,70,71],{"class":45},"  history: ",[24,73,74],{"class":34},"true",[24,76,77],{"class":45},", ",[24,79,81],{"class":80},"sJ8bj","\u002F\u002F default: 50-snapshot bounded stack\n",[24,83,85],{"class":26,"line":84},5,[24,86,87],{"class":45},"})\n",[89,90,91],"p",{},"Tune the depth:",[14,93,95],{"className":16,"code":94,"language":18,"meta":19,"style":19},"useForm({ schema, key: 'signup', history: { max: 200 } })\n",[21,96,97],{"__ignoreMap":19},[24,98,99,102,105,107,110,113],{"class":26,"line":27},[24,100,101],{"class":41},"useForm",[24,103,104],{"class":45},"({ schema, key: ",[24,106,62],{"class":61},[24,108,109],{"class":45},", history: { max: ",[24,111,112],{"class":34},"200",[24,114,115],{"class":45}," } })\n",[117,118,120],"h2",{"id":119},"api","API",[122,123,124,140],"table",{},[125,126,127],"thead",{},[128,129,130,134,137],"tr",{},[131,132,133],"th",{},"Member",[131,135,136],{},"Type",[131,138,139],{},"What it does",[141,142,143,163,180,195,209],"tbody",{},[128,144,145,151,156],{},[146,147,148],"td",{},[21,149,150],{},"undo()",[146,152,153],{},[21,154,155],{},"() => boolean",[146,157,158,159,162],{},"Revert to the previous snapshot. ",[21,160,161],{},"false"," at baseline (nothing to undo).",[128,164,165,170,174],{},[146,166,167],{},[21,168,169],{},"redo()",[146,171,172],{},[21,173,155],{},[146,175,176,177,179],{},"Replay a previously-undone snapshot. ",[21,178,161],{}," when nothing's queued.",[128,181,182,187,192],{},[146,183,184],{},[21,185,186],{},"meta.canUndo",[146,188,189],{},[21,190,191],{},"boolean",[146,193,194],{},"Gate an \"Undo\" button on this.",[128,196,197,202,206],{},[146,198,199],{},[21,200,201],{},"meta.canRedo",[146,203,204],{},[21,205,191],{},[146,207,208],{},"Gate a \"Redo\" button on this.",[128,210,211,216,221],{},[146,212,213],{},[21,214,215],{},"meta.historySize",[146,217,218],{},[21,219,220],{},"number",[146,222,223],{},"Total snapshots across both stacks — useful for debug overlays.",[89,225,226,228,229,231,232,235,236,239,240,242,243,245,246,249],{},[21,227,150],{}," and ",[21,230,169],{}," are top-level methods; the three flags live\non the ",[21,233,234],{},"meta"," reactive bundle alongside the rest of the form-level\naggregates. When ",[21,237,238],{},"history"," isn't configured, all five members are\nstill present but inert: methods return ",[21,241,161],{},", flags read ",[21,244,161],{},"\n\u002F ",[21,247,248],{},"0",". Templates don't need conditional logic.",[117,251,253],{"id":252},"keyboard-shortcuts","Keyboard shortcuts",[89,255,256],{},"Not wired by default — do it in a line:",[14,258,262],{"className":259,"code":260,"language":261,"meta":19,"style":19},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript setup lang=\"ts\">\n  const { undo, redo, meta } = useForm({\n    schema,\n    key: 'editor',\n    history: true,\n  })\n\n  function onKeydown(event: KeyboardEvent) {\n    if ((event.metaKey || event.ctrlKey) && event.key === 'z') {\n      event.preventDefault()\n      event.shiftKey ? redo() : undo()\n    }\n  }\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv @keydown=\"onKeydown\">\n    \u003Cbutton :disabled=\"!meta.canUndo\" @click=\"undo\">Undo\u003C\u002Fbutton>\n    \u003Cbutton :disabled=\"!meta.canRedo\" @click=\"redo\">Redo\u003C\u002Fbutton>\n    \u003C!-- …form fields… -->\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n","vue",[21,263,264,288,317,322,332,341,347,354,379,408,420,442,448,454,464,469,479,498,530,558,564,574],{"__ignoreMap":19},[24,265,266,269,273,276,279,282,285],{"class":26,"line":27},[24,267,268],{"class":45},"\u003C",[24,270,272],{"class":271},"s9eBZ","script",[24,274,275],{"class":41}," setup",[24,277,278],{"class":41}," lang",[24,280,281],{"class":45},"=",[24,283,284],{"class":61},"\"ts\"",[24,286,287],{"class":45},">\n",[24,289,290,293,296,299,301,304,306,308,311,313,315],{"class":26,"line":49},[24,291,292],{"class":30},"  const",[24,294,295],{"class":45}," { ",[24,297,298],{"class":34},"undo",[24,300,77],{"class":45},[24,302,303],{"class":34},"redo",[24,305,77],{"class":45},[24,307,234],{"class":34},[24,309,310],{"class":45}," } ",[24,312,281],{"class":30},[24,314,42],{"class":41},[24,316,46],{"class":45},[24,318,319],{"class":26,"line":55},[24,320,321],{"class":45},"    schema,\n",[24,323,324,327,330],{"class":26,"line":68},[24,325,326],{"class":45},"    key: ",[24,328,329],{"class":61},"'editor'",[24,331,65],{"class":45},[24,333,334,337,339],{"class":26,"line":84},[24,335,336],{"class":45},"    history: ",[24,338,74],{"class":34},[24,340,65],{"class":45},[24,342,344],{"class":26,"line":343},6,[24,345,346],{"class":45},"  })\n",[24,348,350],{"class":26,"line":349},7,[24,351,353],{"emptyLinePlaceholder":352},true,"\n",[24,355,357,360,363,366,370,373,376],{"class":26,"line":356},8,[24,358,359],{"class":30},"  function",[24,361,362],{"class":41}," onKeydown",[24,364,365],{"class":45},"(",[24,367,369],{"class":368},"s4XuR","event",[24,371,372],{"class":30},":",[24,374,375],{"class":41}," KeyboardEvent",[24,377,378],{"class":45},") {\n",[24,380,382,385,388,391,394,397,400,403,406],{"class":26,"line":381},9,[24,383,384],{"class":30},"    if",[24,386,387],{"class":45}," ((event.metaKey ",[24,389,390],{"class":30},"||",[24,392,393],{"class":45}," event.ctrlKey) ",[24,395,396],{"class":30},"&&",[24,398,399],{"class":45}," event.key ",[24,401,402],{"class":30},"===",[24,404,405],{"class":61}," 'z'",[24,407,378],{"class":45},[24,409,411,414,417],{"class":26,"line":410},10,[24,412,413],{"class":45},"      event.",[24,415,416],{"class":41},"preventDefault",[24,418,419],{"class":45},"()\n",[24,421,423,426,429,432,435,437,440],{"class":26,"line":422},11,[24,424,425],{"class":45},"      event.shiftKey ",[24,427,428],{"class":30},"?",[24,430,431],{"class":41}," redo",[24,433,434],{"class":45},"() ",[24,436,372],{"class":30},[24,438,439],{"class":41}," undo",[24,441,419],{"class":45},[24,443,445],{"class":26,"line":444},12,[24,446,447],{"class":45},"    }\n",[24,449,451],{"class":26,"line":450},13,[24,452,453],{"class":45},"  }\n",[24,455,457,460,462],{"class":26,"line":456},14,[24,458,459],{"class":45},"\u003C\u002F",[24,461,272],{"class":271},[24,463,287],{"class":45},[24,465,467],{"class":26,"line":466},15,[24,468,353],{"emptyLinePlaceholder":352},[24,470,472,474,477],{"class":26,"line":471},16,[24,473,268],{"class":45},[24,475,476],{"class":271},"template",[24,478,287],{"class":45},[24,480,482,485,488,491,493,496],{"class":26,"line":481},17,[24,483,484],{"class":45},"  \u003C",[24,486,487],{"class":271},"div",[24,489,490],{"class":41}," @keydown",[24,492,281],{"class":45},[24,494,495],{"class":61},"\"onKeydown\"",[24,497,287],{"class":45},[24,499,501,504,507,510,512,515,518,520,523,526,528],{"class":26,"line":500},18,[24,502,503],{"class":45},"    \u003C",[24,505,506],{"class":271},"button",[24,508,509],{"class":41}," :disabled",[24,511,281],{"class":45},[24,513,514],{"class":61},"\"!meta.canUndo\"",[24,516,517],{"class":41}," @click",[24,519,281],{"class":45},[24,521,522],{"class":61},"\"undo\"",[24,524,525],{"class":45},">Undo\u003C\u002F",[24,527,506],{"class":271},[24,529,287],{"class":45},[24,531,533,535,537,539,541,544,546,548,551,554,556],{"class":26,"line":532},19,[24,534,503],{"class":45},[24,536,506],{"class":271},[24,538,509],{"class":41},[24,540,281],{"class":45},[24,542,543],{"class":61},"\"!meta.canRedo\"",[24,545,517],{"class":41},[24,547,281],{"class":45},[24,549,550],{"class":61},"\"redo\"",[24,552,553],{"class":45},">Redo\u003C\u002F",[24,555,506],{"class":271},[24,557,287],{"class":45},[24,559,561],{"class":26,"line":560},20,[24,562,563],{"class":80},"    \u003C!-- …form fields… -->\n",[24,565,567,570,572],{"class":26,"line":566},21,[24,568,569],{"class":45},"  \u003C\u002F",[24,571,487],{"class":271},[24,573,287],{"class":45},[24,575,577,579,581],{"class":26,"line":576},22,[24,578,459],{"class":45},[24,580,476],{"class":271},[24,582,287],{"class":45},[117,584,586],{"id":585},"what-gets-snapshotted","What gets snapshotted",[588,589,590,598],"ul",{},[591,592,593,594,597],"li",{},"Every form value (via ",[21,595,596],{},"setValue",", register inputs, array helpers).",[591,599,600],{},"The error map at the time of the snapshot.",[89,602,603],{},"What's NOT snapshotted:",[588,605,606,613,626],{},[591,607,608,612],{},[609,610,611],"strong",{},"Field records"," (touched \u002F focused \u002F blurred \u002F isConnected) —\nUI interaction history, it shouldn't rewind. A field that was\ntouched stays touched.",[591,614,615,618,619,77,622,625],{},[609,616,617],{},"Submission lifecycle"," (",[21,620,621],{},"meta.submitCount",[21,623,624],{},"meta.submitError",").",[591,627,628,631],{},[609,629,630],{},"Validation in-flight state",".",[117,633,635],{"id":634},"what-pushes-a-snapshot","What pushes a snapshot",[89,637,638,639,77,641,644,645,77,648,77,651,77,654,77,657,65,660,77,663,666],{},"Every form mutation: ",[21,640,596],{},[21,642,643],{},"register","-backed input edits, any\narray helper (",[21,646,647],{},"append",[21,649,650],{},"prepend",[21,652,653],{},"insert",[21,655,656],{},"remove",[21,658,659],{},"swap",[21,661,662],{},"move",[21,664,665],{},"replace","), or a programmatic write.",[89,668,669,670,673,674,673,677,680],{},"Calling ",[21,671,672],{},"setFieldErrors"," \u002F ",[21,675,676],{},"addFieldErrors",[21,678,679],{},"clearFieldErrors","\ndoes NOT push — those only touch the error map.\nWhatever errors are live when the next mutation lands go into that\nmutation's snapshot.",[117,682,684],{"id":683},"interactions","Interactions",[588,686,687,695,701],{},[591,688,689,694],{},[609,690,691],{},[21,692,693],{},"reset()"," clears both stacks and uses the reset state as the\nnew baseline. A reset is a \"new session\".",[591,696,697,700],{},[609,698,699],{},"Live field validation"," still runs on undo \u002F redo — the\nrestored state validates like any other.",[591,702,703,706],{},[609,704,705],{},"Persistence"," picks up each undo \u002F redo as a normal mutation\nand writes the restored state to your chosen backend.",[117,708,710],{"id":709},"memory","Memory",[89,712,713,714,717],{},"Default ",[21,715,716],{},"max: 50"," keeps at most 50 past + 50 redo snapshots. Bump\nit for editors with long histories; drop it for memory-constrained\ntargets. Each snapshot holds a reference to the form value (not a\ndeep copy) plus a shallow copy of the error map — cost scales\nlinearly, not quadratically.",[719,720,721],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":19,"searchDepth":49,"depth":49,"links":723},[724,725,726,727,728,729],{"id":119,"depth":49,"text":120},{"id":252,"depth":49,"text":253},{"id":585,"depth":49,"text":586},{"id":634,"depth":49,"text":635},{"id":683,"depth":49,"text":684},{"id":709,"depth":49,"text":710},"md",{},"\u002Fdocs\u002Frecipes\u002Fundo-redo",{"title":5,"description":19},"docs\u002Frecipes\u002Fundo-redo","Nz8EsOptZ2nuYR0e3hSIgkmPWxwMFDkiGseASmvsbKo",1777934136789]