[{"data":1,"prerenderedAt":1373},["ShallowReactive",2],{"navigation_docs":3,"-adapters-vue-router":115,"-adapters-vue-router-surround":1368},[4,55,73,87,105],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":54},"Guides","i-lucide-book-open","\u002Fguides","1.guides",[10,14,18,22,26,30,34,38,42,46,50],{"title":11,"path":12,"stem":13},"Introduction","\u002Fguides\u002Fintroduction","1.guides\u002F0.introduction",{"title":15,"path":16,"stem":17},"Data","\u002Fguides\u002Fdata","1.guides\u002F1.data",{"title":19,"path":20,"stem":21},"Forms","\u002Fguides\u002Fform","1.guides\u002F2.form",{"title":23,"path":24,"stem":25},"List","\u002Fguides\u002Flist","1.guides\u002F3.list",{"title":27,"path":28,"stem":29},"Authentication","\u002Fguides\u002Fauthentication","1.guides\u002F4.authentication",{"title":31,"path":32,"stem":33},"Authorization","\u002Fguides\u002Fauthorization","1.guides\u002F5.authorization",{"title":35,"path":36,"stem":37},"Notifications","\u002Fguides\u002Fnotifications","1.guides\u002F6.notifications",{"title":39,"path":40,"stem":41},"Realtime","\u002Fguides\u002Frealtime","1.guides\u002F7.realtime",{"title":43,"path":44,"stem":45},"Router","\u002Fguides\u002Frouter","1.guides\u002F8.router",{"title":47,"path":48,"stem":49},"I18n","\u002Fguides\u002Fi18n","1.guides\u002F9.i18n",{"title":51,"path":52,"stem":53},"Controller","\u002Fguides\u002Fcontroller","1.guides\u002F99.controller",false,{"title":56,"icon":57,"path":58,"stem":59,"children":60,"page":54},"Integrations","i-lucide-blocks","\u002Fintegrations","2.integrations",[61,65,69],{"title":62,"path":63,"stem":64},"Vue","\u002Fintegrations\u002Fvue","2.integrations\u002F0.vue",{"title":66,"path":67,"stem":68},"Nuxt","\u002Fintegrations\u002Fnuxt","2.integrations\u002F1.nuxt",{"title":70,"path":71,"stem":72},"Svelte","\u002Fintegrations\u002Fsvelte","2.integrations\u002F2.svelte",{"title":74,"icon":75,"path":76,"stem":77,"children":78,"page":54},"Adapters","i-lucide-plug","\u002Fadapters","3.adapters",[79,83],{"title":80,"path":81,"stem":82},"Vue Router","\u002Fadapters\u002Fvue-router","3.adapters\u002F0.vue-router",{"title":84,"path":85,"stem":86},"Svelte SPA Router","\u002Fadapters\u002Fsvelte-spa-router","3.adapters\u002F1.svelte-spa-router",{"title":88,"icon":89,"path":90,"stem":91,"children":92,"page":54},"Backend","i-lucide-server","\u002Fbackend","4.backend",[93,97,101],{"title":94,"path":95,"stem":96},"Directus","\u002Fbackend\u002Fdirectus","4.backend\u002F0.directus",{"title":98,"path":99,"stem":100},"Supabase","\u002Fbackend\u002Fsupabase","4.backend\u002F1.supabase",{"title":102,"path":103,"stem":104},"RESTful API","\u002Fbackend\u002Frest-api","4.backend\u002F9.rest-api",{"title":106,"icon":107,"path":108,"stem":109,"children":110,"page":54},"AI","i-lucide-sparkles","\u002Fai","5.ai",[111],{"title":112,"path":113,"stem":114},"Agent Skills","\u002Fai\u002Fskills","5.ai\u002F0.skills",{"id":116,"title":80,"body":117,"description":1362,"extension":1363,"links":1364,"meta":1365,"navigation":343,"path":81,"seo":1366,"stem":82,"__hash__":1367},"docs\u002F3.adapters\u002F0.vue-router.md",{"type":118,"value":119,"toc":1352},"minimark",[120,132,147,152,224,231,235,249,407,410,414,417,422,435,528,541,545,551,623,641,645,656,728,737,761,1310,1322,1332,1336,1339,1348],[121,122,123,127,128,131],"p",{},[124,125,126],"code",{},"@ginjou\u002Fwith-vue-router"," implements Ginjou's ",[129,130,43],"a",{"href":44}," contract on top of Vue Router.",[121,133,134,135,138,139,142,143,146],{},"It covers the whole contract, including the optional ",[124,136,137],{},"blocker",", so ",[124,140,141],{},"useRouteBlocker"," and ",[124,144,145],{},"useWarnUnsaved"," work with nothing extra to wire up.",[148,149,151],"h2",{"id":150},"installation","Installation",[153,154,156,181,195,210],"code-group",{"sync":155},"package-manager",[157,158,164],"pre",{"className":159,"code":160,"filename":161,"language":162,"meta":163,"style":163},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark monokai","pnpm add @ginjou\u002Fwith-vue-router\n","pnpm","bash","",[124,165,166],{"__ignoreMap":163},[167,168,171,174,178],"span",{"class":169,"line":170},"line",1,[167,172,161],{"class":173},"sR7ES",[167,175,177],{"class":176},"sLACW"," add",[167,179,180],{"class":176}," @ginjou\u002Fwith-vue-router\n",[157,182,185],{"className":159,"code":183,"filename":184,"language":162,"meta":163,"style":163},"yarn add @ginjou\u002Fwith-vue-router\n","yarn",[124,186,187],{"__ignoreMap":163},[167,188,189,191,193],{"class":169,"line":170},[167,190,184],{"class":173},[167,192,177],{"class":176},[167,194,180],{"class":176},[157,196,199],{"className":159,"code":197,"filename":198,"language":162,"meta":163,"style":163},"npm install @ginjou\u002Fwith-vue-router\n","npm",[124,200,201],{"__ignoreMap":163},[167,202,203,205,208],{"class":169,"line":170},[167,204,198],{"class":173},[167,206,207],{"class":176}," install",[167,209,180],{"class":176},[157,211,214],{"className":159,"code":212,"filename":213,"language":162,"meta":163,"style":163},"bun add @ginjou\u002Fwith-vue-router\n","bun",[124,215,216],{"__ignoreMap":163},[167,217,218,220,222],{"class":169,"line":170},[167,219,213],{"class":173},[167,221,177],{"class":176},[167,223,180],{"class":176},[121,225,226,227,230],{},"Vue Router is a peer dependency. The package works with Vue 2.7 and Vue 3 through ",[124,228,229],{},"vue-demi",".",[148,232,234],{"id":233},"setup","Setup",[121,236,237,238,241,242,244,245,248],{},"Call ",[124,239,240],{},"createRouter()"," inside ",[124,243,233],{},", once, near the app root. It reads the active Vue Router instance with ",[124,246,247],{},"useRouter()"," and subscribes to it, so everything it sets up is cleaned up with the scope it was created in.",[157,250,255],{"className":251,"code":252,"filename":253,"language":254,"meta":163,"style":163},"language-vue shiki shiki-themes material-theme-lighter github-light github-dark monokai","\u003Cscript setup lang=\"ts\">\nimport { defineRouterContext } from '@ginjou\u002Fvue'\nimport { createRouter } from '@ginjou\u002Fwith-vue-router'\n\ndefineRouterContext(createRouter())\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n    \u003CRouterView \u002F>\n\u003C\u002Ftemplate>\n","App.vue","vue",[124,256,257,289,318,338,345,361,371,376,386,398],{"__ignoreMap":163},[167,258,259,263,267,271,274,277,281,284,286],{"class":169,"line":170},[167,260,262],{"class":261},"swvn1","\u003C",[167,264,266],{"class":265},"sHsBP","script",[167,268,270],{"class":269},"s_lYk"," setup",[167,272,273],{"class":269}," lang",[167,275,276],{"class":261},"=",[167,278,280],{"class":279},"siCPE","\"",[167,282,283],{"class":176},"ts",[167,285,280],{"class":279},[167,287,288],{"class":261},">\n",[167,290,292,296,299,303,306,309,312,315],{"class":169,"line":291},2,[167,293,295],{"class":294},"sRxSC","import",[167,297,298],{"class":261}," {",[167,300,302],{"class":301},"ss--_"," defineRouterContext",[167,304,305],{"class":261}," }",[167,307,308],{"class":294}," from",[167,310,311],{"class":279}," '",[167,313,314],{"class":176},"@ginjou\u002Fvue",[167,316,317],{"class":279},"'\n",[167,319,321,323,325,328,330,332,334,336],{"class":169,"line":320},3,[167,322,295],{"class":294},[167,324,298],{"class":261},[167,326,327],{"class":301}," createRouter",[167,329,305],{"class":261},[167,331,308],{"class":294},[167,333,311],{"class":279},[167,335,126],{"class":176},[167,337,317],{"class":279},[167,339,341],{"class":169,"line":340},4,[167,342,344],{"emptyLinePlaceholder":343},true,"\n",[167,346,348,352,355,358],{"class":169,"line":347},5,[167,349,351],{"class":350},"sD0ED","defineRouterContext",[167,353,354],{"class":301},"(",[167,356,357],{"class":350},"createRouter",[167,359,360],{"class":301},"())\n",[167,362,364,367,369],{"class":169,"line":363},6,[167,365,366],{"class":261},"\u003C\u002F",[167,368,266],{"class":265},[167,370,288],{"class":261},[167,372,374],{"class":169,"line":373},7,[167,375,344],{"emptyLinePlaceholder":343},[167,377,379,381,384],{"class":169,"line":378},8,[167,380,262],{"class":261},[167,382,383],{"class":265},"template",[167,385,288],{"class":261},[167,387,389,392,395],{"class":169,"line":388},9,[167,390,391],{"class":261},"    \u003C",[167,393,394],{"class":265},"RouterView",[167,396,397],{"class":261}," \u002F>\n",[167,399,401,403,405],{"class":169,"line":400},10,[167,402,366],{"class":261},[167,404,383],{"class":265},[167,406,288],{"class":261},[121,408,409],{},"That is everything. Navigation, location state, route sync, and the blocker all work from here.",[148,411,413],{"id":412},"advanced-usage","Advanced usage",[121,415,416],{},"Nothing below is required. Each part is for a case the shared contract cannot express on its own.",[418,419,421],"h3",{"id":420},"navigate-by-route-name","Navigate by route name",[121,423,424,142,427,430,431,434],{},[124,425,426],{},"go",[124,428,429],{},"resolve"," pass ",[124,432,433],{},"meta"," straight to Vue Router, so anything Vue Router's own options accept works:",[157,436,439],{"className":437,"code":438,"language":283,"meta":163,"style":163},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark monokai","router.go({\n    type: 'push',\n    meta: { name: 'post-edit', params: { id: 1 } },\n})\n",[124,440,441,455,475,520],{"__ignoreMap":163},[167,442,443,446,448,450,452],{"class":169,"line":170},[167,444,445],{"class":301},"router",[167,447,230],{"class":261},[167,449,426],{"class":350},[167,451,354],{"class":301},[167,453,454],{"class":261},"{\n",[167,456,457,461,464,466,469,472],{"class":169,"line":291},[167,458,460],{"class":459},"squCx","    type",[167,462,463],{"class":261},":",[167,465,311],{"class":279},[167,467,468],{"class":176},"push",[167,470,471],{"class":279},"'",[167,473,474],{"class":261},",\n",[167,476,477,480,482,484,487,489,491,494,496,499,502,504,506,509,511,515,517],{"class":169,"line":320},[167,478,479],{"class":459},"    meta",[167,481,463],{"class":261},[167,483,298],{"class":261},[167,485,486],{"class":459}," name",[167,488,463],{"class":261},[167,490,311],{"class":279},[167,492,493],{"class":176},"post-edit",[167,495,471],{"class":279},[167,497,498],{"class":261},",",[167,500,501],{"class":459}," params",[167,503,463],{"class":261},[167,505,298],{"class":261},[167,507,508],{"class":459}," id",[167,510,463],{"class":261},[167,512,514],{"class":513},"sYThS"," 1",[167,516,305],{"class":261},[167,518,519],{"class":261}," },\n",[167,521,522,525],{"class":169,"line":340},[167,523,524],{"class":261},"}",[167,526,527],{"class":301},")\n",[121,529,530,532,533,536,537,540],{},[124,531,429],{}," returns Vue Router's ",[124,534,535],{},"href",", not a bare path, so it is ready for an ",[124,538,539],{},"\u003Ca href>"," and already carries whatever your history mode adds.",[418,542,544],{"id":543},"read-vue-routers-own-location","Read Vue Router's own location",[121,546,547,548,463],{},"Locations coming back carry Vue Router's normalized location under ",[124,549,550],{},"meta.location",[157,552,554],{"className":437,"code":553,"language":283,"meta":163,"style":163},"const location = router.getLocation()\nlocation.meta.location.matched \u002F\u002F the matched route records\nlocation.meta.location.name \u002F\u002F the route name\n",[124,555,556,581,603],{"__ignoreMap":163},[167,557,558,562,566,570,573,575,578],{"class":169,"line":170},[167,559,561],{"class":560},"srJo8","const",[167,563,565],{"class":564},"s91G_"," location",[167,567,569],{"class":568},"sGXK2"," =",[167,571,572],{"class":301}," router",[167,574,230],{"class":261},[167,576,577],{"class":350},"getLocation",[167,579,580],{"class":301},"()\n",[167,582,583,586,588,590,592,594,596,599],{"class":169,"line":291},[167,584,585],{"class":301},"location",[167,587,230],{"class":261},[167,589,433],{"class":301},[167,591,230],{"class":261},[167,593,585],{"class":301},[167,595,230],{"class":261},[167,597,598],{"class":301},"matched ",[167,600,602],{"class":601},"ss7Ak","\u002F\u002F the matched route records\n",[167,604,605,607,609,611,613,615,617,620],{"class":169,"line":320},[167,606,585],{"class":301},[167,608,230],{"class":261},[167,610,433],{"class":301},[167,612,230],{"class":261},[167,614,585],{"class":301},[167,616,230],{"class":261},[167,618,619],{"class":301},"name ",[167,621,622],{"class":601},"\u002F\u002F the route name\n",[121,624,625,626,629,630,629,633,636,637,640],{},"Use it for anything ",[124,627,628],{},"path",", ",[124,631,632],{},"params",[124,634,635],{},"query",", and ",[124,638,639],{},"hash"," cannot express. The blocker below is the main reason to reach for it.",[418,642,644],{"id":643},"decide-when-the-blocker-holds","Decide when the blocker holds",[121,646,647,648,651,652,655],{},"The blocker runs as a ",[124,649,650],{},"beforeEach"," guard, next to your own. ",[124,653,654],{},"shouldBlock"," sees every navigation, and comparing paths is not enough to tell them apart. The path changes in all three of these, and only the first takes the page away:",[657,658,659,675],"table",{},[660,661,662],"thead",{},[663,664,665,669,672],"tr",{},[666,667,668],"th",{},"Navigation",[666,670,671],{},"What Vue Router does",[666,673,674],{},"Hold it?",[676,677,678,696,711],"tbody",{},[663,679,680,690,693],{},[681,682,683,686,687],"td",{},[124,684,685],{},"\u002Fposts\u002F1\u002Fedit"," → ",[124,688,689],{},"\u002Fposts\u002F2\u002Fedit",[681,691,692],{},"Reuses the component, but everything derived from the id refetches and refills the form.",[681,694,695],{},"Yes",[663,697,698,705,708],{},[681,699,700,686,702],{},[124,701,685],{},[124,703,704],{},"\u002Fposts\u002F1\u002Fedit\u002Fpreview",[681,706,707],{},"Enters a child route. The form stays mounted.",[681,709,710],{},"No, it is a tab switch",[663,712,713,722,725],{},[681,714,715,686,718,721],{},[124,716,717],{},"\u002Fposts\u002F1",[124,719,720],{},"\u002Fp\u002F1"," (alias)",[681,723,724],{},"Same record and same params under a second path.",[681,726,727],{},"No",[121,729,730,732,733,736],{},[124,731,550],{}," tells them apart with two things a ",[124,734,735],{},"RouterLocation"," does not carry:",[738,739,740,754],"ul",{},[741,742,743,749,750,753],"li",{},[744,745,746],"strong",{},[124,747,748],{},"matched"," — the route records Vue Router resolved. Going deeper still matches everything the current route matches. An alias resolves to its own record, with the original under ",[124,751,752],{},"aliasOf",", so compare through that.",[741,755,756,760],{},[744,757,758],{},[124,759,632],{}," — the records can stay the same while the record you show changes, which is the first row.",[157,762,764],{"className":437,"code":763,"language":283,"meta":163,"style":163},"import type { RouterBlockShouldInput } from '@ginjou\u002Fcore'\nimport type { RouteParsedMeta } from '@ginjou\u002Fwith-vue-router'\nimport type { RouteRecordNormalized } from 'vue-router'\nimport { useRouteBlocker } from '@ginjou\u002Fvue'\n\nconst origin = (record: RouteRecordNormalized): RouteRecordNormalized => record.aliasOf ?? record\n\nfunction isLeavingRoute(\n    { currentLocation, nextLocation }: RouterBlockShouldInput\u003CRouteParsedMeta>,\n): boolean {\n    \u002F\u002F An unload has no next location to compare, and leaving the site loses the work either way.\n    if (nextLocation == null)\n        return true\n\n    const current = currentLocation.meta.location\n    const next = nextLocation.meta.location\n\n    const nextRecords = next.matched.map(origin)\n    const stays = current.matched.map(origin).every(record => nextRecords.includes(record))\n    if (!stays)\n        return true\n\n    \u002F\u002F Only the params this location already has: a child route introducing a new one is not a leave.\n    return Object.keys(current.params).some(\n        key => String(current.params[key]) !== String(next.params[key]),\n    )\n}\n\nconst blocker = useRouteBlocker({\n    shouldBlock: input => isDirty.value && isLeavingRoute(input),\n})\n",[124,765,766,789,810,832,851,855,901,905,916,943,956,962,982,992,997,1019,1039,1044,1072,1123,1138,1145,1150,1156,1188,1239,1245,1251,1256,1272,1303],{"__ignoreMap":163},[167,767,768,770,773,775,778,780,782,784,787],{"class":169,"line":170},[167,769,295],{"class":294},[167,771,772],{"class":294}," type",[167,774,298],{"class":261},[167,776,777],{"class":301}," RouterBlockShouldInput",[167,779,305],{"class":261},[167,781,308],{"class":294},[167,783,311],{"class":279},[167,785,786],{"class":176},"@ginjou\u002Fcore",[167,788,317],{"class":279},[167,790,791,793,795,797,800,802,804,806,808],{"class":169,"line":291},[167,792,295],{"class":294},[167,794,772],{"class":294},[167,796,298],{"class":261},[167,798,799],{"class":301}," RouteParsedMeta",[167,801,305],{"class":261},[167,803,308],{"class":294},[167,805,311],{"class":279},[167,807,126],{"class":176},[167,809,317],{"class":279},[167,811,812,814,816,818,821,823,825,827,830],{"class":169,"line":320},[167,813,295],{"class":294},[167,815,772],{"class":294},[167,817,298],{"class":261},[167,819,820],{"class":301}," RouteRecordNormalized",[167,822,305],{"class":261},[167,824,308],{"class":294},[167,826,311],{"class":279},[167,828,829],{"class":176},"vue-router",[167,831,317],{"class":279},[167,833,834,836,838,841,843,845,847,849],{"class":169,"line":340},[167,835,295],{"class":294},[167,837,298],{"class":261},[167,839,840],{"class":301}," useRouteBlocker",[167,842,305],{"class":261},[167,844,308],{"class":294},[167,846,311],{"class":279},[167,848,314],{"class":176},[167,850,317],{"class":279},[167,852,853],{"class":169,"line":347},[167,854,344],{"emptyLinePlaceholder":343},[167,856,857,859,863,865,868,872,874,877,880,882,884,887,890,892,895,898],{"class":169,"line":363},[167,858,561],{"class":560},[167,860,862],{"class":861},"sh7YU"," origin",[167,864,569],{"class":568},[167,866,867],{"class":261}," (",[167,869,871],{"class":870},"sQgqH","record",[167,873,463],{"class":568},[167,875,820],{"class":876},"sKvfc",[167,878,879],{"class":261},")",[167,881,463],{"class":568},[167,883,820],{"class":876},[167,885,886],{"class":560}," =>",[167,888,889],{"class":301}," record",[167,891,230],{"class":261},[167,893,894],{"class":301},"aliasOf ",[167,896,897],{"class":568},"??",[167,899,900],{"class":301}," record\n",[167,902,903],{"class":169,"line":373},[167,904,344],{"emptyLinePlaceholder":343},[167,906,907,910,913],{"class":169,"line":378},[167,908,909],{"class":560},"function",[167,911,912],{"class":350}," isLeavingRoute",[167,914,915],{"class":261},"(\n",[167,917,918,921,924,926,929,931,933,935,937,940],{"class":169,"line":388},[167,919,920],{"class":261},"    {",[167,922,923],{"class":870}," currentLocation",[167,925,498],{"class":261},[167,927,928],{"class":870}," nextLocation",[167,930,305],{"class":261},[167,932,463],{"class":568},[167,934,777],{"class":876},[167,936,262],{"class":261},[167,938,939],{"class":876},"RouteParsedMeta",[167,941,942],{"class":261},">,\n",[167,944,945,947,949,953],{"class":169,"line":400},[167,946,879],{"class":261},[167,948,463],{"class":568},[167,950,952],{"class":951},"s_MOj"," boolean",[167,954,955],{"class":261}," {\n",[167,957,959],{"class":169,"line":958},11,[167,960,961],{"class":601},"    \u002F\u002F An unload has no next location to compare, and leaving the site loses the work either way.\n",[167,963,965,968,970,973,976,980],{"class":169,"line":964},12,[167,966,967],{"class":294},"    if",[167,969,867],{"class":459},[167,971,972],{"class":301},"nextLocation",[167,974,975],{"class":568}," ==",[167,977,979],{"class":978},"sMTiH"," null",[167,981,527],{"class":459},[167,983,985,988],{"class":169,"line":984},13,[167,986,987],{"class":294},"        return",[167,989,991],{"class":990},"s8HiA"," true\n",[167,993,995],{"class":169,"line":994},14,[167,996,344],{"emptyLinePlaceholder":343},[167,998,1000,1003,1006,1008,1010,1012,1014,1016],{"class":169,"line":999},15,[167,1001,1002],{"class":560},"    const",[167,1004,1005],{"class":564}," current",[167,1007,569],{"class":568},[167,1009,923],{"class":301},[167,1011,230],{"class":261},[167,1013,433],{"class":301},[167,1015,230],{"class":261},[167,1017,1018],{"class":301},"location\n",[167,1020,1022,1024,1027,1029,1031,1033,1035,1037],{"class":169,"line":1021},16,[167,1023,1002],{"class":560},[167,1025,1026],{"class":564}," next",[167,1028,569],{"class":568},[167,1030,928],{"class":301},[167,1032,230],{"class":261},[167,1034,433],{"class":301},[167,1036,230],{"class":261},[167,1038,1018],{"class":301},[167,1040,1042],{"class":169,"line":1041},17,[167,1043,344],{"emptyLinePlaceholder":343},[167,1045,1047,1049,1052,1054,1056,1058,1060,1062,1065,1067,1070],{"class":169,"line":1046},18,[167,1048,1002],{"class":560},[167,1050,1051],{"class":564}," nextRecords",[167,1053,569],{"class":568},[167,1055,1026],{"class":301},[167,1057,230],{"class":261},[167,1059,748],{"class":301},[167,1061,230],{"class":261},[167,1063,1064],{"class":350},"map",[167,1066,354],{"class":459},[167,1068,1069],{"class":301},"origin",[167,1071,527],{"class":459},[167,1073,1075,1077,1080,1082,1084,1086,1088,1090,1092,1094,1096,1098,1100,1103,1105,1107,1109,1111,1113,1116,1118,1120],{"class":169,"line":1074},19,[167,1076,1002],{"class":560},[167,1078,1079],{"class":564}," stays",[167,1081,569],{"class":568},[167,1083,1005],{"class":301},[167,1085,230],{"class":261},[167,1087,748],{"class":301},[167,1089,230],{"class":261},[167,1091,1064],{"class":350},[167,1093,354],{"class":459},[167,1095,1069],{"class":301},[167,1097,879],{"class":459},[167,1099,230],{"class":261},[167,1101,1102],{"class":350},"every",[167,1104,354],{"class":459},[167,1106,871],{"class":870},[167,1108,886],{"class":560},[167,1110,1051],{"class":301},[167,1112,230],{"class":261},[167,1114,1115],{"class":350},"includes",[167,1117,354],{"class":459},[167,1119,871],{"class":301},[167,1121,1122],{"class":459},"))\n",[167,1124,1126,1128,1130,1133,1136],{"class":169,"line":1125},20,[167,1127,967],{"class":294},[167,1129,867],{"class":459},[167,1131,1132],{"class":568},"!",[167,1134,1135],{"class":301},"stays",[167,1137,527],{"class":459},[167,1139,1141,1143],{"class":169,"line":1140},21,[167,1142,987],{"class":294},[167,1144,991],{"class":990},[167,1146,1148],{"class":169,"line":1147},22,[167,1149,344],{"emptyLinePlaceholder":343},[167,1151,1153],{"class":169,"line":1152},23,[167,1154,1155],{"class":601},"    \u002F\u002F Only the params this location already has: a child route introducing a new one is not a leave.\n",[167,1157,1159,1162,1165,1167,1170,1172,1175,1177,1179,1181,1183,1186],{"class":169,"line":1158},24,[167,1160,1161],{"class":294},"    return",[167,1163,1164],{"class":301}," Object",[167,1166,230],{"class":261},[167,1168,1169],{"class":350},"keys",[167,1171,354],{"class":459},[167,1173,1174],{"class":301},"current",[167,1176,230],{"class":261},[167,1178,632],{"class":301},[167,1180,879],{"class":459},[167,1182,230],{"class":261},[167,1184,1185],{"class":350},"some",[167,1187,915],{"class":459},[167,1189,1191,1194,1196,1199,1201,1203,1205,1207,1210,1213,1216,1219,1221,1223,1226,1228,1230,1232,1234,1237],{"class":169,"line":1190},25,[167,1192,1193],{"class":870},"        key",[167,1195,886],{"class":560},[167,1197,1198],{"class":350}," String",[167,1200,354],{"class":459},[167,1202,1174],{"class":301},[167,1204,230],{"class":261},[167,1206,632],{"class":301},[167,1208,1209],{"class":459},"[",[167,1211,1212],{"class":301},"key",[167,1214,1215],{"class":459},"]) ",[167,1217,1218],{"class":568},"!==",[167,1220,1198],{"class":350},[167,1222,354],{"class":459},[167,1224,1225],{"class":301},"next",[167,1227,230],{"class":261},[167,1229,632],{"class":301},[167,1231,1209],{"class":459},[167,1233,1212],{"class":301},[167,1235,1236],{"class":459},"])",[167,1238,474],{"class":261},[167,1240,1242],{"class":169,"line":1241},26,[167,1243,1244],{"class":459},"    )\n",[167,1246,1248],{"class":169,"line":1247},27,[167,1249,1250],{"class":261},"}\n",[167,1252,1254],{"class":169,"line":1253},28,[167,1255,344],{"emptyLinePlaceholder":343},[167,1257,1259,1261,1264,1266,1268,1270],{"class":169,"line":1258},29,[167,1260,561],{"class":560},[167,1262,1263],{"class":564}," blocker",[167,1265,569],{"class":568},[167,1267,840],{"class":350},[167,1269,354],{"class":301},[167,1271,454],{"class":261},[167,1273,1275,1278,1280,1283,1285,1288,1290,1293,1296,1298,1301],{"class":169,"line":1274},30,[167,1276,1277],{"class":350},"    shouldBlock",[167,1279,463],{"class":261},[167,1281,1282],{"class":870}," input",[167,1284,886],{"class":560},[167,1286,1287],{"class":301}," isDirty",[167,1289,230],{"class":261},[167,1291,1292],{"class":301},"value ",[167,1294,1295],{"class":568},"&&",[167,1297,912],{"class":350},[167,1299,1300],{"class":301},"(input)",[167,1302,474],{"class":261},[167,1304,1306,1308],{"class":169,"line":1305},31,[167,1307,524],{"class":261},[167,1309,527],{"class":301},[1311,1312,1313,1318,1319,1321],"note",{},[129,1314,1316],{"href":1315},"\u002Fguides\u002Fform#warn-about-unsaved-changes",[124,1317,145],{}," compares paths only. It gets the first row right and the other two wrong, so a form with nested tabs or an aliased record wants its own ",[124,1320,141],{}," with a check like the one above.",[121,1323,1324,1325,1327,1328,1331],{},"Closing or reloading the tab is a leave too. While any enabled ",[124,1326,654],{}," returns ",[124,1329,1330],{},"true",", the browser shows its own confirmation.",[418,1333,1335],{"id":1334},"blocker-inside-keepalive","Blocker inside KeepAlive",[121,1337,1338],{},"A cached component is deactivated, not unmounted, so it never gets a chance to clean up on the way out. The adapter handles this for you: a blocker inside a deactivated component is not asked, and is asked again once the component is activated.",[121,1340,1341,1342,1344,1345,1347],{},"The one thing to get right is where you call it. ",[124,1343,141],{}," has to run during ",[124,1346,233],{},", not later, so the adapter can follow the component's activation.",[1349,1350,1351],"style",{},"html pre.shiki code .sR7ES, html code.shiki .sR7ES{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sLACW, html code.shiki .sLACW{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .swvn1, html code.shiki .swvn1{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sHsBP, html code.shiki .sHsBP{--shiki-light:#E53935;--shiki-default:#22863A;--shiki-dark:#85E89D;--shiki-sepia:#F92672}html pre.shiki code .s_lYk, html code.shiki .s_lYk{--shiki-light:#9C3EDA;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .siCPE, html code.shiki .siCPE{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sRxSC, html code.shiki .sRxSC{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#F92672;--shiki-sepia-font-style:inherit}html pre.shiki code .ss--_, html code.shiki .ss--_{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sD0ED, html code.shiki .sD0ED{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .squCx, html code.shiki .squCx{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sYThS, html code.shiki .sYThS{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .srJo8, html code.shiki .srJo8{--shiki-light:#9C3EDA;--shiki-light-font-style:inherit;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .s91G_, html code.shiki .s91G_{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#F8F8F2}html pre.shiki code .sGXK2, html code.shiki .sGXK2{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .ss7Ak, html code.shiki .ss7Ak{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit;--shiki-sepia:#88846F;--shiki-sepia-font-style:inherit}html pre.shiki code .sh7YU, html code.shiki .sh7YU{--shiki-light:#90A4AE;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sQgqH, html code.shiki .sQgqH{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit;--shiki-sepia:#FD971F;--shiki-sepia-font-style:italic}html pre.shiki code .sKvfc, html code.shiki .sKvfc{--shiki-light:#E2931D;--shiki-light-text-decoration:inherit;--shiki-default:#6F42C1;--shiki-default-text-decoration:inherit;--shiki-dark:#B392F0;--shiki-dark-text-decoration:inherit;--shiki-sepia:#A6E22E;--shiki-sepia-text-decoration:underline}html pre.shiki code .s_MOj, html code.shiki .s_MOj{--shiki-light:#E2931D;--shiki-light-font-style:inherit;--shiki-default:#005CC5;--shiki-default-font-style:inherit;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .sMTiH, html code.shiki .sMTiH{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .s8HiA, html code.shiki .s8HiA{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}",{"title":163,"searchDepth":291,"depth":291,"links":1353},[1354,1355,1356],{"id":150,"depth":291,"text":151},{"id":233,"depth":291,"text":234},{"id":412,"depth":291,"text":413,"children":1357},[1358,1359,1360,1361],{"id":420,"depth":320,"text":421},{"id":543,"depth":320,"text":544},{"id":643,"depth":320,"text":644},{"id":1334,"depth":320,"text":1335},"Connect Vue Router to Ginjou's router contract, and how the route blocker behaves with nested routes, aliases, and KeepAlive.","md",null,{},{"title":80,"description":1362},"LDMT8k46-f5oePbQtFBMZauFLVcTLgiQOb5nubRH6-c",[1369,1371],{"title":70,"path":71,"stem":72,"description":1370,"children":-1},"Explain the minimal setup, provider registration, and Svelte-specific patterns in @ginjou\u002Fsvelte.",{"title":84,"path":85,"stem":86,"description":1372,"children":-1},"Connect svelte-spa-router to Ginjou's router contract, including the three pieces the route blocker needs wired into your own Router component.",1789837337525]