[{"data":1,"prerenderedAt":1043},["ShallowReactive",2],{"content-\u002Fdocs\u002Fwriting-and-mutating\u002Funset":3},{"id":4,"title":5,"body":6,"description":1022,"extension":1023,"meta":1024,"metaRows":1025,"navigation":204,"path":1038,"seo":1039,"source":1040,"stem":1041,"__hash__":1042},"docs\u002Fdocs\u002Fwriting-and-mutating\u002Funset.md","unset (the blank-anywhere sentinel)",{"type":7,"value":8,"toc":1010},"minimark",[9,16,27,30,61,65,73,90,153,160,167,170,451,454,505,519,523,634,644,648,657,687,714,721,730,799,823,827,853,946,969,973,1006],[10,11,13],"h1",{"id":12},"unset",[14,15,12],"code",{},[17,18,19],"blockquote",{},[20,21,22,23,26],"p",{},"A consumer-side shorthand for \"this path starts blank.\" The runtime writes the schema's slim value at that path, joins every primitive descendant to ",[14,24,25],{},"form.blankPaths",", and the bound input renders empty until the user types.",[28,29],"docs-meta-table",{},[20,31,32,33,36,37,40,41,44,45,48,49,52,53,56,57,60],{},"The demo carries a primitive leaf (",[14,34,35],{},"email",") and a container (",[14,38,39],{},"profile"," with ",[14,42,43],{},"name"," + ",[14,46,47],{},"age","). Click ",[14,50,51],{},"setValue('email', unset)"," to flag the leaf blank, or ",[14,54,55],{},"setValue('profile', unset)"," to flag the whole container blank. The panel shows storage (always concrete, never the sentinel) and the live ",[14,58,59],{},"blankPaths"," set.",[62,63],"docs-demo",{"label":64,"slug":12},"Unset Demo",[66,67,69,70,72],"h2",{"id":68},"what-unset-does","What ",[14,71,12],{}," does",[20,74,75,77,78,81,82,85,86,89],{},[14,76,12],{}," is a sentinel symbol exported from every entry point. Pass it as a value in ",[14,79,80],{},"defaultValues",", ",[14,83,84],{},"setValue",", or ",[14,87,88],{},"reset",". The runtime translates it into two effects at the targeted path:",[91,92,93,142],"ol",{},[94,95,96,100,101,81,104,81,107,81,110,113,114,117,118,121,122,125,126,129,130,133,134,137,138,141],"li",{},[97,98,99],"strong",{},"Storage"," receives the schema's slim concrete. For primitive leaves that's ",[14,102,103],{},"''",[14,105,106],{},"0",[14,108,109],{},"0n",[14,111,112],{},"false",". For ",[14,115,116],{},".optional()"," wrappers it's ",[14,119,120],{},"undefined","; for ",[14,123,124],{},".nullable()"," it's ",[14,127,128],{},"null",". For container paths the runtime recurses: an object writes a shape with every leaf at its slim, an array writes ",[14,131,132],{},"[]",", a tuple writes its slim positions, a record writes ",[14,135,136],{},"{}",", a discriminated union writes ",[14,139,140],{},"{ \u003CdiscriminatorKey>: '' }"," with no variant body.",[94,143,144,148,149,152],{},[97,145,146],{},[14,147,25],{}," gains every primitive descendant under the target. The ",[14,150,151],{},"v-register"," directive reads from the same set when binding the DOM input, so the field renders empty even though storage holds a concrete value.",[20,154,155,156,159],{},"Reads through ",[14,157,158],{},"form.values.\u003Cpath>"," always see the slim value. Storage never holds the sentinel symbol.",[66,161,163,164,166],{"id":162},"where-unset-can-land","Where ",[14,165,12],{}," can land",[20,168,169],{},"The sentinel works at every position the consumer can address:",[171,172,177],"pre",{"className":173,"code":174,"language":175,"meta":176,"style":176},"language-ts shiki shiki-themes github-light github-dark","import { unset, useForm } from 'attaform\u002Fzod'\n\nconst schema = z.object({\n  email: z.string(),\n  profile: z.object({ name: z.string(), age: z.number() }),\n  tags: z.array(z.string()),\n  cargo: z.discriminatedUnion('kind', [\n    z.object({ kind: z.literal('boat'), length: z.number() }),\n    z.object({ kind: z.literal('truck'), payload: z.number() }),\n  ]),\n})\n\nconst form = useForm({\n  schema,\n  defaultValues: {\n    email: unset, \u002F\u002F primitive leaf\n    profile: unset, \u002F\u002F container, marks profile.name and profile.age\n    tags: unset, \u002F\u002F array, writes []\n    cargo: unset, \u002F\u002F DU, writes { kind: '' } stub, no variant body\n  },\n  key: 'demo',\n})\n","ts","",[14,178,179,199,206,229,241,263,280,298,324,347,353,359,364,379,385,391,401,410,419,428,434,446],{"__ignoreMap":176},[180,181,184,188,192,195],"span",{"class":182,"line":183},"line",1,[180,185,187],{"class":186},"szBVR","import",[180,189,191],{"class":190},"sVt8B"," { unset, useForm } ",[180,193,194],{"class":186},"from",[180,196,198],{"class":197},"sZZnC"," 'attaform\u002Fzod'\n",[180,200,202],{"class":182,"line":201},2,[180,203,205],{"emptyLinePlaceholder":204},true,"\n",[180,207,209,212,216,219,222,226],{"class":182,"line":208},3,[180,210,211],{"class":186},"const",[180,213,215],{"class":214},"sj4cs"," schema",[180,217,218],{"class":186}," =",[180,220,221],{"class":190}," z.",[180,223,225],{"class":224},"sScJk","object",[180,227,228],{"class":190},"({\n",[180,230,232,235,238],{"class":182,"line":231},4,[180,233,234],{"class":190},"  email: z.",[180,236,237],{"class":224},"string",[180,239,240],{"class":190},"(),\n",[180,242,244,247,249,252,254,257,260],{"class":182,"line":243},5,[180,245,246],{"class":190},"  profile: z.",[180,248,225],{"class":224},[180,250,251],{"class":190},"({ name: z.",[180,253,237],{"class":224},[180,255,256],{"class":190},"(), age: z.",[180,258,259],{"class":224},"number",[180,261,262],{"class":190},"() }),\n",[180,264,266,269,272,275,277],{"class":182,"line":265},6,[180,267,268],{"class":190},"  tags: z.",[180,270,271],{"class":224},"array",[180,273,274],{"class":190},"(z.",[180,276,237],{"class":224},[180,278,279],{"class":190},"()),\n",[180,281,283,286,289,292,295],{"class":182,"line":282},7,[180,284,285],{"class":190},"  cargo: z.",[180,287,288],{"class":224},"discriminatedUnion",[180,290,291],{"class":190},"(",[180,293,294],{"class":197},"'kind'",[180,296,297],{"class":190},", [\n",[180,299,301,304,306,309,312,314,317,320,322],{"class":182,"line":300},8,[180,302,303],{"class":190},"    z.",[180,305,225],{"class":224},[180,307,308],{"class":190},"({ kind: z.",[180,310,311],{"class":224},"literal",[180,313,291],{"class":190},[180,315,316],{"class":197},"'boat'",[180,318,319],{"class":190},"), length: z.",[180,321,259],{"class":224},[180,323,262],{"class":190},[180,325,327,329,331,333,335,337,340,343,345],{"class":182,"line":326},9,[180,328,303],{"class":190},[180,330,225],{"class":224},[180,332,308],{"class":190},[180,334,311],{"class":224},[180,336,291],{"class":190},[180,338,339],{"class":197},"'truck'",[180,341,342],{"class":190},"), payload: z.",[180,344,259],{"class":224},[180,346,262],{"class":190},[180,348,350],{"class":182,"line":349},10,[180,351,352],{"class":190},"  ]),\n",[180,354,356],{"class":182,"line":355},11,[180,357,358],{"class":190},"})\n",[180,360,362],{"class":182,"line":361},12,[180,363,205],{"emptyLinePlaceholder":204},[180,365,367,369,372,374,377],{"class":182,"line":366},13,[180,368,211],{"class":186},[180,370,371],{"class":214}," form",[180,373,218],{"class":186},[180,375,376],{"class":224}," useForm",[180,378,228],{"class":190},[180,380,382],{"class":182,"line":381},14,[180,383,384],{"class":190},"  schema,\n",[180,386,388],{"class":182,"line":387},15,[180,389,390],{"class":190},"  defaultValues: {\n",[180,392,394,397],{"class":182,"line":393},16,[180,395,396],{"class":190},"    email: unset, ",[180,398,400],{"class":399},"sJ8bj","\u002F\u002F primitive leaf\n",[180,402,404,407],{"class":182,"line":403},17,[180,405,406],{"class":190},"    profile: unset, ",[180,408,409],{"class":399},"\u002F\u002F container, marks profile.name and profile.age\n",[180,411,413,416],{"class":182,"line":412},18,[180,414,415],{"class":190},"    tags: unset, ",[180,417,418],{"class":399},"\u002F\u002F array, writes []\n",[180,420,422,425],{"class":182,"line":421},19,[180,423,424],{"class":190},"    cargo: unset, ",[180,426,427],{"class":399},"\u002F\u002F DU, writes { kind: '' } stub, no variant body\n",[180,429,431],{"class":182,"line":430},20,[180,432,433],{"class":190},"  },\n",[180,435,437,440,443],{"class":182,"line":436},21,[180,438,439],{"class":190},"  key: ",[180,441,442],{"class":197},"'demo'",[180,444,445],{"class":190},",\n",[180,447,449],{"class":182,"line":448},22,[180,450,358],{"class":190},[20,452,453],{},"The same value works on every imperative write:",[171,455,457],{"className":173,"code":456,"language":175,"meta":176,"style":176},"form.setValue('profile', unset) \u002F\u002F re-blank the whole profile sub-tree\nform.setValue('cargo', unset) \u002F\u002F reset cargo to a no-variant-selected state\nform.reset({ tags: unset, email: unset }) \u002F\u002F baseline that re-applies on reset()\n",[14,458,459,477,493],{"__ignoreMap":176},[180,460,461,464,466,468,471,474],{"class":182,"line":183},[180,462,463],{"class":190},"form.",[180,465,84],{"class":224},[180,467,291],{"class":190},[180,469,470],{"class":197},"'profile'",[180,472,473],{"class":190},", unset) ",[180,475,476],{"class":399},"\u002F\u002F re-blank the whole profile sub-tree\n",[180,478,479,481,483,485,488,490],{"class":182,"line":201},[180,480,463],{"class":190},[180,482,84],{"class":224},[180,484,291],{"class":190},[180,486,487],{"class":197},"'cargo'",[180,489,473],{"class":190},[180,491,492],{"class":399},"\u002F\u002F reset cargo to a no-variant-selected state\n",[180,494,495,497,499,502],{"class":182,"line":208},[180,496,463],{"class":190},[180,498,88],{"class":224},[180,500,501],{"class":190},"({ tags: unset, email: unset }) ",[180,503,504],{"class":399},"\u002F\u002F baseline that re-applies on reset()\n",[20,506,507,508,510,511,514,515,518],{},"Root-level ",[14,509,12],{}," is admitted too. ",[14,512,513],{},"defaultValues: unset"," or ",[14,516,517],{},"form.reset(unset)"," walks the whole schema, marking every primitive descendant blank. Useful for \"the user must touch every field\" workflows where presence carries audit weight: a housing application form that needs to record \"client manually set income to 0\" separately from \"income defaulted to 0.\"",[66,520,522],{"id":521},"container-behavior-in-detail","Container behavior, in detail",[524,525,526,544],"table",{},[527,528,529],"thead",{},[530,531,532,536,539],"tr",{},[533,534,535],"th",{},"Position",[533,537,538],{},"Storage write",[533,540,541,543],{},[14,542,59],{}," adds",[545,546,547,559,570,585,598,612,624],"tbody",{},[530,548,549,553,556],{},[550,551,552],"td",{},"Primitive leaf",[550,554,555],{},"Schema's slim primitive",[550,557,558],{},"The leaf path",[530,560,561,564,567],{},[550,562,563],{},"Bare object",[550,565,566],{},"Recursive slim subtree",[550,568,569],{},"Every primitive descendant under the path",[530,571,572,575,582],{},[550,573,574],{},"Array \u002F tuple \u002F record",[550,576,577,579,580],{},[14,578,132],{}," \u002F slim tuple \u002F ",[14,581,136],{},[550,583,584],{},"The container path itself",[530,586,587,590,595],{},[550,588,589],{},"Discriminated union container",[550,591,592],{},[14,593,594],{},"{ \u003CdiscriminatorKey>: \u003Ckind-blank> }",[550,596,597],{},"The discriminator's path",[530,599,600,605,609],{},[550,601,602,604],{},[14,603,116],{}," wrapper",[550,606,607],{},[14,608,120],{},[550,610,611],{},"The wrapper path",[530,613,614,618,622],{},[550,615,616,604],{},[14,617,124],{},[550,619,620],{},[14,621,128],{},[550,623,611],{},[530,625,626,629,632],{},[550,627,628],{},"Date \u002F RegExp \u002F Map \u002F Set leaf",[550,630,631],{},"The schema's slim concrete",[550,633,558],{},[20,635,636,637,639,640,643],{},"The container path itself does NOT enter ",[14,638,25],{},". ",[14,641,642],{},"form.fields('profile').blank"," derives reactively from the conjunction \"every primitive descendant is blank,\" so an empty container reads blank by vacuous truth, and one descendant filled flips the container's blank false automatically.",[66,645,647],{"id":646},"reading-the-blank-state","Reading the blank state",[20,649,650,652,653,656],{},[14,651,158],{}," returns concrete storage. Read the displayed-empty state through ",[14,654,655],{},"form.fields",":",[171,658,660],{"className":173,"code":659,"language":175,"meta":176,"style":176},"form.fields.email.blank \u002F\u002F true after setValue('email', unset)\nform.fields('profile').blank \u002F\u002F true when every descendant of profile is blank\n",[14,661,662,670],{"__ignoreMap":176},[180,663,664,667],{"class":182,"line":183},[180,665,666],{"class":190},"form.fields.email.blank ",[180,668,669],{"class":399},"\u002F\u002F true after setValue('email', unset)\n",[180,671,672,674,677,679,681,684],{"class":182,"line":201},[180,673,463],{"class":190},[180,675,676],{"class":224},"fields",[180,678,291],{"class":190},[180,680,470],{"class":197},[180,682,683],{"class":190},").blank ",[180,685,686],{"class":399},"\u002F\u002F true when every descendant of profile is blank\n",[20,688,689,692,693,696,697,81,700,81,703,706,707,710,711,713],{},[14,690,691],{},"form.blankPaths.value"," exposes a ",[14,694,695],{},"BlankPathsView"," (Set-like: ",[14,698,699],{},"size",[14,701,702],{},"has(input)",[14,704,705],{},"values()",", plus a ",[14,708,709],{},"Symbol.iterator",") for callers that want the whole list (persistence, debug overlays). The ",[14,712,151],{}," directive reads the same signals and renders the DOM empty.",[66,715,717,718],{"id":716},"required-schemas-raise-no-value-supplied","Required schemas raise ",[14,719,720],{},"no-value-supplied",[20,722,723,724,726,727,656],{},"A required leaf sitting in ",[14,725,25],{}," surfaces an error in ",[14,728,729],{},"form.errors",[171,731,733],{"className":173,"code":732,"language":175,"meta":176,"style":176},"const schema = z.object({ income: z.number() }) \u002F\u002F required\nconst form = useForm({ schema, defaultValues: { income: unset } })\n\nform.errors.income \u002F\u002F [{ code: 'atta:no-value-supplied', … }]\nform.fields('income').blank \u002F\u002F true\n",[14,734,735,758,771,775,783],{"__ignoreMap":176},[180,736,737,739,741,743,745,747,750,752,755],{"class":182,"line":183},[180,738,211],{"class":186},[180,740,215],{"class":214},[180,742,218],{"class":186},[180,744,221],{"class":190},[180,746,225],{"class":224},[180,748,749],{"class":190},"({ income: z.",[180,751,259],{"class":224},[180,753,754],{"class":190},"() }) ",[180,756,757],{"class":399},"\u002F\u002F required\n",[180,759,760,762,764,766,768],{"class":182,"line":201},[180,761,211],{"class":186},[180,763,371],{"class":214},[180,765,218],{"class":186},[180,767,376],{"class":224},[180,769,770],{"class":190},"({ schema, defaultValues: { income: unset } })\n",[180,772,773],{"class":182,"line":208},[180,774,205],{"emptyLinePlaceholder":204},[180,776,777,780],{"class":182,"line":231},[180,778,779],{"class":190},"form.errors.income ",[180,781,782],{"class":399},"\u002F\u002F [{ code: 'atta:no-value-supplied', … }]\n",[180,784,785,787,789,791,794,796],{"class":182,"line":243},[180,786,463],{"class":190},[180,788,676],{"class":224},[180,790,291],{"class":190},[180,792,793],{"class":197},"'income'",[180,795,683],{"class":190},[180,797,798],{"class":399},"\u002F\u002F true\n",[20,800,801,81,803,805,806,809,810,812,813,822],{},[14,802,116],{},[14,804,124],{},", and ",[14,807,808],{},".default(N)"," schemas accept the empty case. Those leaves still sit in ",[14,811,25],{}," (the directive needs the signal to render the input empty), but no error fires. See ",[814,815,817,818,821],"a",{"href":816},"\u002Fdocs\u002Fvalidation\u002Fblank","the ",[14,819,820],{},"blank"," field-state bit"," for the full lifecycle.",[66,824,826],{"id":825},"cross-entry-availability","Cross-entry availability",[20,828,829,831,832,835,836,81,839,81,842,81,845,848,849,852],{},[14,830,12],{}," and ",[14,833,834],{},"isUnset"," ship from every entry point: ",[14,837,838],{},"attaform",[14,840,841],{},"attaform\u002Fzod",[14,843,844],{},"attaform\u002Fzod-v3",[14,846,847],{},"attaform\u002Fzod-v4",". The ",[14,850,851],{},"Unset"," type is exported alongside for explicit type annotations:",[171,854,856],{"className":173,"code":855,"language":175,"meta":176,"style":176},"import { unset, isUnset, type Unset } from 'attaform\u002Fzod'\n\nfunction maybeBlank(v: string | Unset): string | undefined {\n  return isUnset(v) ? undefined : v\n}\n",[14,857,858,875,879,919,941],{"__ignoreMap":176},[180,859,860,862,865,868,871,873],{"class":182,"line":183},[180,861,187],{"class":186},[180,863,864],{"class":190}," { unset, isUnset, ",[180,866,867],{"class":186},"type",[180,869,870],{"class":190}," Unset } ",[180,872,194],{"class":186},[180,874,198],{"class":197},[180,876,877],{"class":182,"line":201},[180,878,205],{"emptyLinePlaceholder":204},[180,880,881,884,887,889,893,895,898,901,904,907,909,911,913,916],{"class":182,"line":208},[180,882,883],{"class":186},"function",[180,885,886],{"class":224}," maybeBlank",[180,888,291],{"class":190},[180,890,892],{"class":891},"s4XuR","v",[180,894,656],{"class":186},[180,896,897],{"class":214}," string",[180,899,900],{"class":186}," |",[180,902,903],{"class":224}," Unset",[180,905,906],{"class":190},")",[180,908,656],{"class":186},[180,910,897],{"class":214},[180,912,900],{"class":186},[180,914,915],{"class":214}," undefined",[180,917,918],{"class":190}," {\n",[180,920,921,924,927,930,933,935,938],{"class":182,"line":231},[180,922,923],{"class":186},"  return",[180,925,926],{"class":224}," isUnset",[180,928,929],{"class":190},"(v) ",[180,931,932],{"class":186},"?",[180,934,915],{"class":214},[180,936,937],{"class":186}," :",[180,939,940],{"class":190}," v\n",[180,942,943],{"class":182,"line":243},[180,944,945],{"class":190},"}\n",[20,947,948,950,951,954,955,957,958,961,962,965,966,968],{},[14,949,834],{}," is a type guard for explicit narrowing of ",[14,952,953],{},"value: T | Unset"," payloads (input parameters, ",[14,956,84],{}," callbacks). It is NOT a ",[14,959,960],{},"form.values"," check: storage never holds the symbol, so ",[14,963,964],{},"isUnset(form.values.\u003Cpath>)"," always returns ",[14,967,112],{},".",[66,970,972],{"id":971},"where-to-next","Where to next",[974,975,976,987,996],"ul",{},[94,977,978,983,984,986],{},[814,979,980,981,821],{"href":816},"The ",[14,982,820],{},": the storage \u002F display side-channel ",[14,985,12],{}," plugs into.",[94,988,989,995],{},[814,990,992,994],{"href":991},"\u002Fdocs\u002Fwriting-and-mutating\u002Fset-value",[14,993,84],{}," patterns",": the imperative write surface.",[94,997,998,1002,1003,1005],{},[814,999,1001],{"href":1000},"\u002Fdocs\u002Fschemas\u002Fdefaults","Defaults from the schema",": how schema-declared defaults and ",[14,1004,12],{}," interact at mount time.",[1007,1008,1009],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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 .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 .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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":176,"searchDepth":201,"depth":201,"links":1011},[1012,1014,1016,1017,1018,1020,1021],{"id":68,"depth":201,"text":1013},"What unset does",{"id":162,"depth":201,"text":1015},"Where unset can land",{"id":521,"depth":201,"text":522},{"id":646,"depth":201,"text":647},{"id":716,"depth":201,"text":1019},"Required schemas raise no-value-supplied",{"id":825,"depth":201,"text":826},{"id":971,"depth":201,"text":972},"Pass the unset sentinel at any path in defaultValues, setValue, or reset. The runtime writes the schema's slim value (recursively for containers) and joins every primitive descendant to form.blankPaths, so the bound input renders empty.","md",{},[1026,1029,1032,1035],{"label":1027,"value":1028},"Category","Export",{"label":1030,"value":1031,"kind":14},"From","attaform · attaform\u002Fzod · attaform\u002Fzod-v3 · attaform\u002Fzod-v4",{"label":1033,"value":1034,"kind":14},"Use","defaultValues, setValue, reset",{"label":1036,"value":1037,"kind":14},"Read state","form.blankPaths, form.fields(path).blank","\u002Fdocs\u002Fwriting-and-mutating\u002Funset",{"title":5,"description":1022},null,"docs\u002Fwriting-and-mutating\u002Funset","llx--VLXwojzkKxF0_AdxJ4_vmVKbKfhJuEB_w_TWKw",1780949759940]