@epic-web/workshop-app 6.64.0 → 6.64.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/client/assets/{_exerciseNumber-CcPKmB4n.js → _exerciseNumber-D3f2-zl6.js} +2 -2
- package/build/client/assets/{_exerciseNumber-CcPKmB4n.js.map → _exerciseNumber-D3f2-zl6.js.map} +1 -1
- package/build/client/assets/{_exerciseNumber_.finished-knzx8riV.js → _exerciseNumber_.finished-DBaOwcf2.js} +2 -2
- package/build/client/assets/{_exerciseNumber_.finished-knzx8riV.js.map → _exerciseNumber_.finished-DBaOwcf2.js.map} +1 -1
- package/build/client/assets/{_extra-DB6-IJuV.js → _extra-B4vZXPjV.js} +2 -2
- package/build/client/assets/{_extra-DB6-IJuV.js.map → _extra-B4vZXPjV.js.map} +1 -1
- package/build/client/assets/{_layout-Be0gsSoP.js → _layout-C6NSVF79.js} +2 -2
- package/build/client/assets/{_layout-Be0gsSoP.js.map → _layout-C6NSVF79.js.map} +1 -1
- package/build/client/assets/{_layout-D05w5xUz.js → _layout-oPmquiOE.js} +2 -2
- package/build/client/assets/{_layout-D05w5xUz.js.map → _layout-oPmquiOE.js.map} +1 -1
- package/build/client/assets/app-BcJkSksP.js +2 -0
- package/build/client/assets/{app-rrQthl25.js.map → app-BcJkSksP.js.map} +1 -1
- package/build/client/assets/{diff-De24Mp-s.js → diff-Ba99U4EI.js} +2 -2
- package/build/client/assets/{diff-De24Mp-s.js.map → diff-Ba99U4EI.js.map} +1 -1
- package/build/client/assets/{diff-Bd9VlQ-I.js → diff-DmmI9IU6.js} +2 -2
- package/build/client/assets/{diff-Bd9VlQ-I.js.map → diff-DmmI9IU6.js.map} +1 -1
- package/build/client/assets/{epic-video-DdpYdAlg.js → epic-video-5HutgMR0.js} +2 -2
- package/build/client/assets/{epic-video-DdpYdAlg.js.map → epic-video-5HutgMR0.js.map} +1 -1
- package/build/client/assets/{epic-video-Bndfj6GR.js → epic-video-BX2A437e.js} +2 -2
- package/build/client/assets/{epic-video-Bndfj6GR.js.map → epic-video-BX2A437e.js.map} +1 -1
- package/build/client/assets/{finished-HnwwiFtu.js → finished-BLRyuOTb.js} +2 -2
- package/build/client/assets/{finished-HnwwiFtu.js.map → finished-BLRyuOTb.js.map} +1 -1
- package/build/client/assets/index-DVd41HZN.js +68 -0
- package/build/client/assets/index-DVd41HZN.js.map +1 -0
- package/build/client/assets/{index-CvFJy3s8.js → index-Dt_ngnka.js} +2 -2
- package/build/client/assets/{index-CvFJy3s8.js.map → index-Dt_ngnka.js.map} +1 -1
- package/build/client/assets/{index-BL399UJV.js → index-InnNe6aG.js} +2 -2
- package/build/client/assets/{index-BL399UJV.js.map → index-InnNe6aG.js.map} +1 -1
- package/build/client/assets/{index-B1TztMYA.js → index-T3LlCTSm.js} +2 -2
- package/build/client/assets/{index-B1TztMYA.js.map → index-T3LlCTSm.js.map} +1 -1
- package/build/client/assets/{loading-IJRzD1mm.js → loading-BiVU3Oa8.js} +2 -2
- package/build/client/assets/{loading-IJRzD1mm.js.map → loading-BiVU3Oa8.js.map} +1 -1
- package/build/client/assets/{login-VlyrGJvd.js → login-Ej63Q5LC.js} +2 -2
- package/build/client/assets/{login-VlyrGJvd.js.map → login-Ej63Q5LC.js.map} +1 -1
- package/build/client/assets/manifest-9482f5db.js +1 -0
- package/build/client/assets/{mdx-CbaVHkqG.js → mdx-BlaeOyqK.js} +2 -2
- package/build/client/assets/{mdx-CbaVHkqG.js.map → mdx-BlaeOyqK.js.map} +1 -1
- package/build/client/assets/{playground-xNPUi1cK.js → playground-DIm_r4fy.js} +2 -2
- package/build/client/assets/{playground-xNPUi1cK.js.map → playground-DIm_r4fy.js.map} +1 -1
- package/build/client/assets/{preview-DUByetdK.js → preview-D11Pscbe.js} +2 -2
- package/build/client/assets/{preview-DUByetdK.js.map → preview-D11Pscbe.js.map} +1 -1
- package/build/client/assets/{product-DlgtjMXY.js → product-CNG57fZy.js} +2 -2
- package/build/client/assets/{product-DlgtjMXY.js.map → product-CNG57fZy.js.map} +1 -1
- package/build/client/assets/{root-B-fnUAyN.js → root-hU3hrO-C.js} +2 -2
- package/build/client/assets/{root-B-fnUAyN.js.map → root-hU3hrO-C.js.map} +1 -1
- package/build/client/assets/{test-wFDk9A6D.js → test-CpoHBC_8.js} +2 -2
- package/build/client/assets/{test-wFDk9A6D.js.map → test-CpoHBC_8.js.map} +1 -1
- package/build/client/assets/{tests-BldZ_klJ.js → tests-CITG_DX3.js} +2 -2
- package/build/client/assets/{tests-BldZ_klJ.js.map → tests-CITG_DX3.js.map} +1 -1
- package/build/server/index.js +22 -23
- package/build/server/index.js.map +1 -1
- package/package.json +3 -3
- package/build/client/assets/app-rrQthl25.js +0 -2
- package/build/client/assets/index-Cg-9mI3Y.js +0 -68
- package/build/client/assets/index-Cg-9mI3Y.js.map +0 -1
- package/build/client/assets/manifest-3610e2d1.js +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{w as l,a as m,L as n}from"./chunk-EPOLDU6W-C4NOdiis.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{E as a}from"./index-BrUCi_AK.js";import{E as c}from"./epic-video-
|
|
2
|
-
//# sourceMappingURL=index-
|
|
1
|
+
import{w as l,a as m,L as n}from"./chunk-EPOLDU6W-C4NOdiis.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{E as a}from"./index-BrUCi_AK.js";import{E as c}from"./epic-video-BX2A437e.js";import{G as p}from"./error-boundary-B_ltT-yo.js";import{E as d}from"./launch-editor-D_PbWy0b.js";import{M as x}from"./mdx-BlaeOyqK.js";import{c as f}from"./misc-CRhJChs6.js";import{P as h,u}from"./progress-Hpjbz7E6.js";import"./index-CqIc3cxq.js";import"./use-event-source-BuD4_2SF.js";import"./index-DzdDahau.js";import"./index-vDCSPjrM.js";import"./index-DVd41HZN.js";import"./tooltip-f3C9W-4C.js";import"./root-loader-BObzljW3.js";import"./pe-UQCAhDPv.js";import"./schemas-Uj5SZtvt.js";import"./online-D6QnZT5V.js";import"./loading-BiVU3Oa8.js";import"./user-CFfhNfdz.js";import"./workshop-config-BP-vDuRo.js";import"./preload-helper-BXl3LOEh.js";import"./progress-bar-Cxy0ZpqZ.js";function b({index:o,exercise:r}){const s=u(r.exerciseNumber);return e.jsx("li",{children:e.jsxs(n,{className:f("hover:bg-muted/60 relative flex items-center gap-4 px-4 py-3 text-lg font-semibold transition after:absolute after:right-10 after:-translate-x-2 after:opacity-0 after:transition after:content-['→'] hover:after:translate-x-0 hover:after:opacity-100",s),to:`${r.exerciseNumber.toString().padStart(2,"0")}`,"data-keyboard-action":o===0?"g+n":void 0,children:[e.jsx("span",{className:"text-xs font-normal tabular-nums opacity-50",children:r.exerciseNumber}),e.jsx("span",{children:r.title})]})},r.exerciseNumber)}const j={h1:()=>null},q=l(function({loaderData:r}){const s=e.jsxs("ul",{className:"divide-border dark:divide-border/50 flex flex-col divide-y",children:[e.jsx("strong",{className:"px-10 pb-3 font-mono text-xs uppercase",children:"Exercises"}),r.exercises.map((t,i)=>e.jsx(b,{index:i,exercise:t},t.exerciseNumber))]});return e.jsxs("main",{className:"relative flex h-full w-full max-w-5xl flex-col justify-between border-r md:w-3/4 xl:w-2/3",children:[e.jsxs("article",{id:r.articleId,className:"shadow-on-scrollbox scrollbar-thin scrollbar-thumb-scrollbar flex w-full flex-1 flex-col gap-12 overflow-y-scroll px-3 py-4 pt-6 md:px-10 md:py-12 md:pt-16",children:[e.jsx("div",{children:e.jsx("h1",{className:"px-10 text-[clamp(3rem,6vw,7.5rem)] leading-none font-extrabold",children:r.title})}),e.jsxs("div",{className:"w-full max-w-none scroll-pt-6 border-t px-3 pt-3 md:px-10 md:pt-8",children:[e.jsx("h2",{className:"pb-5 font-mono text-xs font-semibold uppercase",children:"Intro"}),r.workshopReadme.compiled.status==="success"&&r.workshopReadme.compiled.code?e.jsx(c,{epicVideoInfosPromise:r.epicVideoInfosPromise,children:e.jsx("div",{className:"prose dark:prose-invert sm:prose-lg",children:e.jsx(x,{code:r.workshopReadme.compiled.code,components:j})})}):r.workshopReadme.compiled.status==="error"?e.jsxs("div",{className:"text-foreground-destructive",children:["There was an error:",e.jsx("pre",{children:r.workshopReadme.compiled.error})]}):"No instructions yet..."]}),e.jsx("div",{className:"pt-10 pb-5",children:r.workshopReadme.compiled.status==="success"&&r.workshopReadme.compiled.code&&r.workshopReadme.compiled.code.length>500?s:null})]}),e.jsx(a,{elementQuery:`#${r.articleId}`}),e.jsx(h,{type:"workshop-instructions",className:"h-14 border-t px-6"}),e.jsx("div",{className:"@container flex h-16 justify-center border-t",children:e.jsx(d,{file:r.workshopReadme.file,relativePath:r.workshopReadme.relativePath})})]})}),z=m(function(){return e.jsx(p,{})});export{z as ErrorBoundary,q as default};
|
|
2
|
+
//# sourceMappingURL=index-Dt_ngnka.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-Dt_ngnka.js","sources":["../../../app/routes/_app+/index.tsx"],"sourcesContent":["import { ElementScrollRestoration } from '@epic-web/restore-scroll'\nimport {\n\tgetExercises,\n\tgetWorkshopInstructions,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport { getEpicVideoInfos } from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n\ttime,\n} from '@epic-web/workshop-utils/timing.server'\nimport slugify from '@sindresorhus/slugify'\nimport { data, type HeadersFunction, Link } from 'react-router'\nimport { EpicVideoInfoProvider } from '#app/components/epic-video.tsx'\nimport { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'\nimport { EditFileOnGitHub } from '#app/routes/launch-editor.tsx'\nimport { Mdx } from '#app/utils/mdx.tsx'\nimport { cn } from '#app/utils/misc.tsx'\nimport { ProgressToggle, useExerciseProgressClassName } from '../progress.tsx'\nimport { type Route } from './+types/index.tsx'\n\nexport async function loader({ request }: Route.LoaderArgs) {\n\tconst timings = makeTimings('indexLoader')\n\tconst { title } = getWorkshopConfig()\n\tconst [exercises, workshopReadme] = await Promise.all([\n\t\ttime(() => getExercises({ request, timings }), {\n\t\t\ttimings,\n\t\t\ttype: 'getExercises',\n\t\t\tdesc: 'getExercises in index',\n\t\t}),\n\t\ttime(() => getWorkshopInstructions({ request }), {\n\t\t\ttimings,\n\t\t\ttype: 'compileMdx',\n\t\t\tdesc: 'compileMdx in index',\n\t\t}),\n\t])\n\n\treturn data(\n\t\t{\n\t\t\tarticleId: `workshop-${slugify(title)}-instructions`,\n\t\t\ttitle:\n\t\t\t\tworkshopReadme.compiled.status === 'success'\n\t\t\t\t\t? workshopReadme.compiled.title\n\t\t\t\t\t: title,\n\t\t\texercises: exercises.map((e) => ({\n\t\t\t\texerciseNumber: e.exerciseNumber,\n\t\t\t\ttitle: e.title,\n\t\t\t})),\n\t\t\tworkshopReadme,\n\t\t\tepicVideoInfosPromise:\n\t\t\t\tworkshopReadme.compiled.status === 'success'\n\t\t\t\t\t? getEpicVideoInfos(workshopReadme.compiled.epicVideoEmbeds, {\n\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t})\n\t\t\t\t\t: null,\n\t\t},\n\t\t{\n\t\t\theaders: {\n\t\t\t\t'Server-Timing': getServerTimeHeader(timings),\n\t\t\t},\n\t\t},\n\t)\n}\n\nexport const headers: HeadersFunction = ({ loaderHeaders, parentHeaders }) => {\n\tconst headers = {\n\t\t'Cache-Control': loaderHeaders.get('Cache-Control') ?? '',\n\t\t'Server-Timing': combineServerTimings(loaderHeaders, parentHeaders),\n\t}\n\treturn headers\n}\n\nfunction ExerciseListItem({\n\tindex,\n\texercise,\n}: {\n\tindex: number\n\texercise: Awaited<Route.ComponentProps['loaderData']>['exercises'][number]\n}) {\n\tconst progressClassName = useExerciseProgressClassName(\n\t\texercise.exerciseNumber,\n\t)\n\treturn (\n\t\t<li key={exercise.exerciseNumber}>\n\t\t\t<Link\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"hover:bg-muted/60 relative flex items-center gap-4 px-4 py-3 text-lg font-semibold transition after:absolute after:right-10 after:-translate-x-2 after:opacity-0 after:transition after:content-['→'] hover:after:translate-x-0 hover:after:opacity-100\",\n\t\t\t\t\tprogressClassName,\n\t\t\t\t)}\n\t\t\t\tto={`${exercise.exerciseNumber.toString().padStart(2, '0')}`}\n\t\t\t\tdata-keyboard-action={index === 0 ? 'g+n' : undefined}\n\t\t\t>\n\t\t\t\t<span className=\"text-xs font-normal tabular-nums opacity-50\">\n\t\t\t\t\t{exercise.exerciseNumber}\n\t\t\t\t</span>\n\t\t\t\t<span>{exercise.title}</span>\n\t\t\t</Link>\n\t\t</li>\n\t)\n}\n\nconst mdxComponents = { h1: () => null }\n\nexport default function Index({ loaderData: data }: Route.ComponentProps) {\n\tconst exerciseLinks = (\n\t\t<ul className=\"divide-border dark:divide-border/50 flex flex-col divide-y\">\n\t\t\t<strong className=\"px-10 pb-3 font-mono text-xs uppercase\">\n\t\t\t\tExercises\n\t\t\t</strong>\n\t\t\t{data.exercises.map((exercise, index) => (\n\t\t\t\t<ExerciseListItem\n\t\t\t\t\tkey={exercise.exerciseNumber}\n\t\t\t\t\tindex={index}\n\t\t\t\t\texercise={exercise}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</ul>\n\t)\n\treturn (\n\t\t<main className=\"relative flex h-full w-full max-w-5xl flex-col justify-between border-r md:w-3/4 xl:w-2/3\">\n\t\t\t<article\n\t\t\t\tid={data.articleId}\n\t\t\t\tclassName=\"shadow-on-scrollbox scrollbar-thin scrollbar-thumb-scrollbar flex w-full flex-1 flex-col gap-12 overflow-y-scroll px-3 py-4 pt-6 md:px-10 md:py-12 md:pt-16\"\n\t\t\t>\n\t\t\t\t<div>\n\t\t\t\t\t<h1 className=\"px-10 text-[clamp(3rem,6vw,7.5rem)] leading-none font-extrabold\">\n\t\t\t\t\t\t{data.title}\n\t\t\t\t\t</h1>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"w-full max-w-none scroll-pt-6 border-t px-3 pt-3 md:px-10 md:pt-8\">\n\t\t\t\t\t<h2 className=\"pb-5 font-mono text-xs font-semibold uppercase\">\n\t\t\t\t\t\tIntro\n\t\t\t\t\t</h2>\n\t\t\t\t\t{data.workshopReadme.compiled.status === 'success' &&\n\t\t\t\t\tdata.workshopReadme.compiled.code ? (\n\t\t\t\t\t\t<EpicVideoInfoProvider\n\t\t\t\t\t\t\tepicVideoInfosPromise={data.epicVideoInfosPromise}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className=\"prose dark:prose-invert sm:prose-lg\">\n\t\t\t\t\t\t\t\t<Mdx\n\t\t\t\t\t\t\t\t\tcode={data.workshopReadme.compiled.code}\n\t\t\t\t\t\t\t\t\tcomponents={mdxComponents}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</EpicVideoInfoProvider>\n\t\t\t\t\t) : data.workshopReadme.compiled.status === 'error' ? (\n\t\t\t\t\t\t<div className=\"text-foreground-destructive\">\n\t\t\t\t\t\t\tThere was an error:\n\t\t\t\t\t\t\t<pre>{data.workshopReadme.compiled.error}</pre>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t'No instructions yet...'\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"pt-10 pb-5\">\n\t\t\t\t\t{data.workshopReadme.compiled.status === 'success' &&\n\t\t\t\t\tdata.workshopReadme.compiled.code &&\n\t\t\t\t\tdata.workshopReadme.compiled.code.length > 500\n\t\t\t\t\t\t? exerciseLinks\n\t\t\t\t\t\t: null}\n\t\t\t\t</div>\n\t\t\t</article>\n\t\t\t<ElementScrollRestoration elementQuery={`#${data.articleId}`} />\n\t\t\t<ProgressToggle\n\t\t\t\ttype=\"workshop-instructions\"\n\t\t\t\tclassName=\"h-14 border-t px-6\"\n\t\t\t/>\n\t\t\t<div className=\"@container flex h-16 justify-center border-t\">\n\t\t\t\t<EditFileOnGitHub\n\t\t\t\t\tfile={data.workshopReadme.file}\n\t\t\t\t\trelativePath={data.workshopReadme.relativePath}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</main>\n\t)\n}\n\nexport function ErrorBoundary() {\n\treturn <GeneralErrorBoundary />\n}\n"],"names":["ExerciseListItem","index","exercise","progressClassName","useExerciseProgressClassName","exerciseNumber","children","jsxs","Link","className","cn","to","toString","padStart","jsx","title","mdxComponents","h1","_UNSAFE_withComponentProps","loaderData","data","exerciseLinks","exercises","map","id","articleId","workshopReadme","compiled","status","code","EpicVideoInfoProvider","epicVideoInfosPromise","Mdx","components","error","length","ElementScrollRestoration","elementQuery","ProgressToggle","type","EditFileOnGitHub","file","relativePath","ErrorBoundary","_UNSAFE_withErrorBoundaryProps","GeneralErrorBoundary"],"mappings":"+2BA0EA,SAASA,EAAiB,CACzBC,MAAAA,EACAC,SAAAA,CACD,EAGG,CACF,MAAMC,EAAoBC,EACzBF,EAASG,cACV,EACA,aACE,KAAA,CACAC,SAAAC,EAAAA,KAACC,EAAA,CACAC,UAAWC,EACV,0PACAP,CACD,EACAQ,GAAI,GAAGT,EAASG,eAAeO,WAAWC,SAAS,EAAG,GAAG,CAAC,GAC1D,uBAAsBZ,IAAU,EAAI,MAAQ,OAE5CK,SAAA,CAAAQ,EAAAA,IAAC,OAAA,CAAKL,UAAU,8CACdH,SAAAJ,EAASG,cAAA,CACX,EACAS,EAAAA,IAAC,OAAA,CAAMR,SAAAJ,EAASa,KAAA,CAAM,CAAA,EACvB,CAAA,EAbQb,EAASG,cAclB,CAEF,CAEA,MAAMW,EAAgB,CAAEC,GAAIA,IAAM,IAAK,EAEvChB,EAAAiB,EAAA,SAA8B,CAAEC,WAAYC,CAAK,EAAyB,CACzE,MAAMC,EACLd,EAAAA,KAAC,KAAA,CAAGE,UAAU,6DACbH,SAAA,CAAAQ,EAAAA,IAAC,SAAA,CAAOL,UAAU,yCAAyCH,SAAA,WAAA,CAE3D,EACCc,EAAKE,UAAUC,IAAI,CAACrB,EAAUD,IAC9Ba,EAAAA,IAACd,EAAA,CAEAC,MAAAA,EACAC,SAAAA,CAAA,EAFKA,EAASG,cAGf,CACA,CAAA,CAAA,CACF,EAED,OACCE,EAAAA,KAAC,OAAA,CAAKE,UAAU,4FACfH,SAAA,CAAAC,EAAAA,KAAC,UAAA,CACAiB,GAAIJ,EAAKK,UACThB,UAAU,8JAEVH,SAAA,CAAAQ,EAAAA,IAAC,MAAA,CACAR,eAAC,KAAA,CAAGG,UAAU,kEACZH,SAAAc,EAAKL,MACP,CAAA,CACD,EACAR,EAAAA,KAAC,MAAA,CAAIE,UAAU,oEACdH,SAAA,CAAAQ,EAAAA,IAAC,KAAA,CAAGL,UAAU,iDAAiDH,SAAA,QAE/D,EACCc,EAAKM,eAAeC,SAASC,SAAW,WACzCR,EAAKM,eAAeC,SAASE,KAC5Bf,EAAAA,IAACgB,EAAA,CACAC,sBAAuBX,EAAKW,sBAE5BzB,SAAAQ,EAAAA,IAAC,MAAA,CAAIL,UAAU,sCACdH,SAAAQ,EAAAA,IAACkB,EAAA,CACAH,KAAMT,EAAKM,eAAeC,SAASE,KACnCI,WAAYjB,EACb,EACD,CAAA,CACD,EACGI,EAAKM,eAAeC,SAASC,SAAW,QAC3CrB,EAAAA,KAAC,MAAA,CAAIE,UAAU,8BAA8BH,SAAA,CAAA,4BAE3C,MAAA,CAAKA,SAAAc,EAAKM,eAAeC,SAASO,KAAA,CAAM,CAAA,EAC1C,EAEA,wBAAA,CAAA,CAEF,EACApB,EAAAA,IAAC,OAAIL,UAAU,aACbH,SAAAc,EAAKM,eAAeC,SAASC,SAAW,WACzCR,EAAKM,eAAeC,SAASE,MAC7BT,EAAKM,eAAeC,SAASE,KAAKM,OAAS,IACxCd,EACA,IAAA,CACJ,CAAA,CAAA,CACD,QACCe,EAAA,CAAyBC,aAAc,IAAIjB,EAAKK,SAAS,EAAA,CAAI,EAC9DX,EAAAA,IAACwB,EAAA,CACAC,KAAK,wBACL9B,UAAU,oBAAA,CACX,EACAK,EAAAA,IAAC,MAAA,CAAIL,UAAU,+CACdH,SAAAQ,EAAAA,IAAC0B,EAAA,CACAC,KAAMrB,EAAKM,eAAee,KAC1BC,aAActB,EAAKM,eAAegB,aACnC,CAAA,CACD,CAAA,CAAA,CACD,CAEF,CAAA,EAEOC,EAAAC,EAAA,UAAyB,CAC/B,aAAQC,EAAA,EAAqB,CAC9B,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{w as j,a as E,c as A,d as C,e as N}from"./chunk-EPOLDU6W-C4NOdiis.js";import{j as r}from"./jsx-runtime-C5WNSv3b.js";import{g as T,R as H,P as U,C as t,a as b,D as B}from"./playground-
|
|
2
|
-
//# sourceMappingURL=index-
|
|
1
|
+
import{w as j,a as E,c as A,d as C,e as N}from"./chunk-EPOLDU6W-C4NOdiis.js";import{j as r}from"./jsx-runtime-C5WNSv3b.js";import{g as T,R as H,P as U,C as t,a as b,D as B}from"./playground-DIm_r4fy.js";import{U as I}from"./diff-Ba99U4EI.js";import{G as R}from"./error-boundary-B_ltT-yo.js";import{u as S}from"./workshop-config-BP-vDuRo.js";import{u as O}from"./misc-CRhJChs6.js";import{P as a}from"./preview-D11Pscbe.js";import{T as k}from"./tests-CITG_DX3.js";import"./index-CqIc3cxq.js";import"./loading-BiVU3Oa8.js";import"./index-DVd41HZN.js";import"./tooltip-f3C9W-4C.js";import"./index-vDCSPjrM.js";import"./root-loader-BObzljW3.js";import"./pe-UQCAhDPv.js";import"./schemas-Uj5SZtvt.js";import"./discord-C9e3SYlE.js";import"./user-CFfhNfdz.js";import"./online-D6QnZT5V.js";import"./index-D9Wd20Hl.js";import"./index-C4pHU_n3.js";import"./index-DzdDahau.js";import"./set-playground-DaRl3X5k.js";import"./button-CVorsvM4.js";import"./onboarding-indicator-Bd1aYrgA.js";import"./progress-bar-Cxy0ZpqZ.js";import"./dialog-C_JrUgnb.js";import"./playground-window-BnU6LeUy.js";import"./accordion-DGNDc7Bw.js";import"./mdx-BlaeOyqK.js";import"./epic-video-BX2A437e.js";import"./use-event-source-BuD4_2SF.js";import"./preload-helper-BXl3LOEh.js";import"./launch-editor-D_PbWy0b.js";import"./revalidation-ws-Dcs0B3Rw.js";const p=["playground","problem","solution","tests","diff","chat"],L=n=>!!(n&&p.includes(n)),vs=j(function({loaderData:e}){const{inBrowserBrowserRef:l}=A(),d=S(),[u]=C(),f=u.get("preview"),h=O(),x=N();function m(s){if(s==="tests")return ENV.EPICSHOP_DEPLOYED||!e.playground||e.playground.test.type==="none";if(s==="problem"||s==="solution"){if(e[s]?.dev.type==="none")return!0;if(ENV.EPICSHOP_DEPLOYED){const i=e[s]?.dev.type;return i!=="browser"&&i!=="export"&&!e[s]?.stackBlitzUrl}}return s==="playground"&&ENV.EPICSHOP_DEPLOYED?!0:s==="chat"?!d.product.discordChannelId:!1}function w(s){if(s==="tests"){if(!e.playground)return null;const{isTestRunning:i,testExitCode:o}=e.playground;return i?"running":o===0?"passed":o!==null&&o!==0?"failed":null}return(s==="problem"||s==="solution"||s==="playground")&&(s==="playground"?e.playground:e[s])?.isRunning?"running":null}const y=L(f)?f:p.find(s=>!m(s)),c=`/diff?${new URLSearchParams({app1:e.problem?.name??"",app2:e.solution?.name??""})}`;function g(s){s.altKey&&!s.ctrlKey&&!s.shiftKey&&!s.metaKey&&(s.preventDefault(),x(c))}const v=p.map(s=>{const i=m(s),o=w(s),P=s==="diff"&&h?c:`?${T(u,s,"playground")}`;return{id:s,label:s,hidden:i,status:o,to:P,onClick:s==="diff"?g:void 0}});return r.jsxs(H,{className:"relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden sm:col-span-1 sm:row-span-1",value:y,children:[r.jsx(U,{tabs:v}),r.jsxs("div",{className:"relative z-10 flex min-h-0 flex-1 flex-col overflow-hidden",children:[r.jsx(t,{value:"playground",className:"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start",forceMount:!0,children:r.jsx(b,{appInfo:e.playground,problemAppName:e.problem?.name,inBrowserBrowserRef:l,allApps:e.allApps,isUpToDate:e.playground?.isUpToDate??!1})}),r.jsx(t,{value:"problem",className:"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start",forceMount:!0,children:r.jsx(a,{appInfo:e.problem,inBrowserBrowserRef:l})}),r.jsx(t,{value:"solution",className:"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start",forceMount:!0,children:r.jsx(a,{appInfo:e.solution,inBrowserBrowserRef:l})}),r.jsx(t,{value:"tests",className:"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start overflow-hidden",children:r.jsx(k,{appInfo:e.playground,problemAppName:e.problem?.name,allApps:e.allApps,isUpToDate:e.playground?.isUpToDate??!1,userHasAccessPromise:e.userHasAccessPromise})}),r.jsx(t,{value:"diff",className:"radix-state-inactive:hidden flex h-full min-h-0 w-full grow basis-0 items-stretch justify-center self-start",children:r.jsx(I,{diff:e.diff,allApps:e.allApps,userHasAccessPromise:e.userHasAccessPromise})}),r.jsx(t,{value:"chat",className:"radix-state-inactive:hidden flex h-full min-h-0 w-full grow basis-0 items-stretch justify-center self-start",children:r.jsx(B,{discordPostsPromise:e.discordPostsPromise})})]})]})}),Ps=E(function(){return r.jsx(R,{statusHandlers:{404:()=>r.jsx("p",{children:"Sorry, we couldn't find an app here."})}})});export{Ps as ErrorBoundary,vs as default};
|
|
2
|
+
//# sourceMappingURL=index-InnNe6aG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-BL399UJV.js","sources":["../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index.tsx"],"sourcesContent":["import {\n\tgetAppByName,\n\tgetAppDisplayName,\n\tgetApps,\n\tgetExerciseApp,\n\tisExerciseStepApp,\n\tisPlaygroundApp,\n\trequireExerciseApp,\n\ttype App,\n\ttype ExerciseStepApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getDiffCode } from '@epic-web/workshop-utils/diff.server'\nimport { userHasAccessToExerciseStep } from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n} from '@epic-web/workshop-utils/timing.server'\nimport * as Tabs from '@radix-ui/react-tabs'\nimport * as React from 'react'\nimport {\n\tuseNavigate,\n\tuseSearchParams,\n\tdata,\n\tredirect,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n\tuseOutletContext,\n} from 'react-router'\nimport { Diff } from '#app/components/diff.tsx'\nimport { DiscordChat } from '#app/components/discord-chat.tsx'\nimport { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser.tsx'\nimport {\n\tgetPreviewSearchParams,\n\tPreviewTabsList,\n} from '#app/components/preview-tabs.tsx'\nimport { useWorkshopConfig } from '#app/components/workshop-config.tsx'\nimport { fetchDiscordPosts } from '#app/utils/discord.server.ts'\nimport { useAltDown } from '#app/utils/misc.tsx'\nimport { type Route } from './+types/index.ts'\nimport { Playground } from './__shared/playground.tsx'\nimport { Preview } from './__shared/preview.tsx'\nimport { Tests } from './__shared/tests.tsx'\nimport { getAppRunningState, getTestState } from './__shared/utils.tsx'\n\nexport async function loader({ request, params }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('exerciseStepTypeIndexLoader')\n\tconst searchParams = new URL(request.url).searchParams\n\tconst cacheOptions = { request, timings }\n\n\tconst [exerciseStepApp, allAppsFull, problemApp, solutionApp] =\n\t\tawait Promise.all([\n\t\t\trequireExerciseApp(params, cacheOptions),\n\t\t\tgetApps(cacheOptions),\n\t\t\tgetExerciseApp({ ...params, type: 'problem' }, cacheOptions),\n\t\t\tgetExerciseApp({ ...params, type: 'solution' }, cacheOptions),\n\t\t])\n\n\tconst playgroundApp = allAppsFull.find(isPlaygroundApp)\n\tconst reqUrl = new URL(request.url)\n\n\tconst pathnameParam = reqUrl.searchParams.get('pathname')\n\tif (pathnameParam === '' || pathnameParam === '/') {\n\t\treqUrl.searchParams.delete('pathname')\n\t\tthrow redirect(reqUrl.toString())\n\t}\n\n\tconst app1Name = reqUrl.searchParams.get('app1')\n\tconst app2Name = reqUrl.searchParams.get('app2')\n\tconst app1 = app1Name\n\t\t? await getAppByName(app1Name)\n\t\t: playgroundApp || problemApp\n\tconst app2 = app2Name ? await getAppByName(app2Name) : solutionApp\n\n\tfunction getStepId(a: ExerciseStepApp) {\n\t\treturn (\n\t\t\ta.exerciseNumber * 1000 +\n\t\t\ta.stepNumber * 10 +\n\t\t\t(a.type === 'problem' ? 0 : 1)\n\t\t)\n\t}\n\n\tfunction getStepNameAndId(a: App) {\n\t\tif (isExerciseStepApp(a)) {\n\t\t\tconst exerciseNumberStr = String(a.exerciseNumber).padStart(2, '0')\n\t\t\tconst stepNumberStr = String(a.stepNumber).padStart(2, '0')\n\n\t\t\treturn {\n\t\t\t\tstepName: `${exerciseNumberStr}/${stepNumberStr}.${a.type}`,\n\t\t\t\tstepId: getStepId(a),\n\t\t\t}\n\t\t}\n\t\treturn { stepName: '', stepId: -1 }\n\t}\n\n\tconst allApps = allAppsFull\n\t\t.filter((a, i, ar) => ar.findIndex((b) => a.name === b.name) === i)\n\t\t.map((a) => ({\n\t\t\tdisplayName: getAppDisplayName(a, allAppsFull),\n\t\t\tname: a.name,\n\t\t\ttitle: a.title,\n\t\t\ttype: a.type,\n\t\t\t...getStepNameAndId(a),\n\t\t}))\n\n\tallApps.sort((a, b) => {\n\t\t// order them by their stepId\n\t\tif (a.stepId > 0 && b.stepId > 0) return a.stepId - b.stepId\n\n\t\t// non-step apps should come after step apps\n\t\tif (a.stepId > 0) return -1\n\t\tif (b.stepId > 0) return 1\n\n\t\treturn 0\n\t})\n\n\tasync function getDiffProp() {\n\t\tif (!app1 || !app2) {\n\t\t\treturn {\n\t\t\t\tapp1: app1?.name,\n\t\t\t\tapp2: app2?.name,\n\t\t\t\tdiffCode: null,\n\t\t\t}\n\t\t}\n\t\tconst diffCode = await getDiffCode(app1, app2, {\n\t\t\t...cacheOptions,\n\t\t\tforceFresh: searchParams.get('forceFresh') === 'diff',\n\t\t}).catch((e) => {\n\t\t\tconsole.error(e)\n\t\t\treturn null\n\t\t})\n\t\treturn {\n\t\t\tapp1: app1.name,\n\t\t\tapp2: app2.name,\n\t\t\tdiffCode,\n\t\t}\n\t}\n\n\treturn data(\n\t\t{\n\t\t\ttype: params.type as 'problem' | 'solution',\n\t\t\texerciseStepApp,\n\t\t\tallApps,\n\t\t\t// defer this promise so that we don't block the response from being sent\n\t\t\tdiscordPostsPromise: fetchDiscordPosts({ request }),\n\t\t\tuserHasAccessPromise: userHasAccessToExerciseStep({\n\t\t\t\texerciseNumber: Number(params.exerciseNumber),\n\t\t\t\tstepNumber: Number(params.stepNumber),\n\t\t\t\trequest,\n\t\t\t\ttimings,\n\t\t\t}),\n\t\t\tplayground: playgroundApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'playground',\n\t\t\t\t\t\tfullPath: playgroundApp.fullPath,\n\t\t\t\t\t\tdev: playgroundApp.dev,\n\t\t\t\t\t\ttest: playgroundApp.test,\n\t\t\t\t\t\ttitle: playgroundApp.title,\n\t\t\t\t\t\tname: playgroundApp.name,\n\t\t\t\t\t\tappName: playgroundApp.appName,\n\t\t\t\t\t\tisUpToDate: playgroundApp.isUpToDate,\n\t\t\t\t\t\tstackBlitzUrl: playgroundApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(playgroundApp)),\n\t\t\t\t\t\t...getTestState(playgroundApp),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tproblem: problemApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'problem',\n\t\t\t\t\t\tfullPath: problemApp.fullPath,\n\t\t\t\t\t\tdev: problemApp.dev,\n\t\t\t\t\t\ttest: problemApp.test,\n\t\t\t\t\t\ttitle: problemApp.title,\n\t\t\t\t\t\tname: problemApp.name,\n\t\t\t\t\t\tstackBlitzUrl: problemApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(problemApp)),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tsolution: solutionApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'solution',\n\t\t\t\t\t\tfullPath: solutionApp.fullPath,\n\t\t\t\t\t\tdev: solutionApp.dev,\n\t\t\t\t\t\ttest: solutionApp.test,\n\t\t\t\t\t\ttitle: solutionApp.title,\n\t\t\t\t\t\tname: solutionApp.name,\n\t\t\t\t\t\tstackBlitzUrl: solutionApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(solutionApp)),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tdiff: getDiffProp(),\n\t\t} as const,\n\t\t{\n\t\t\theaders: {\n\t\t\t\t'Server-Timing': getServerTimeHeader(timings),\n\t\t\t},\n\t\t},\n\t)\n}\n\nexport const headers: HeadersFunction = ({ loaderHeaders, parentHeaders }) => {\n\tconst headers = {\n\t\t'Server-Timing': combineServerTimings(loaderHeaders, parentHeaders),\n\t}\n\treturn headers\n}\n\nconst tabs = [\n\t'playground',\n\t'problem',\n\t'solution',\n\t'tests',\n\t'diff',\n\t'chat',\n] as const\nconst isValidPreview = (s: string | null): s is (typeof tabs)[number] =>\n\tBoolean(s && tabs.includes(s as (typeof tabs)[number]))\n\nexport default function ExercisePartRoute({\n\tloaderData,\n}: Route.ComponentProps) {\n\tconst { inBrowserBrowserRef } = useOutletContext<{\n\t\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n\t}>()\n\tconst workshopConfig = useWorkshopConfig()\n\tconst [searchParams] = useSearchParams()\n\n\tconst preview = searchParams.get('preview')\n\n\tconst altDown = useAltDown()\n\tconst navigate = useNavigate()\n\n\tfunction shouldHideTab(tab: (typeof tabs)[number]) {\n\t\tif (tab === 'tests') {\n\t\t\treturn (\n\t\t\t\tENV.EPICSHOP_DEPLOYED ||\n\t\t\t\t!loaderData.playground ||\n\t\t\t\tloaderData.playground.test.type === 'none'\n\t\t\t)\n\t\t}\n\t\tif (tab === 'problem' || tab === 'solution') {\n\t\t\tif (loaderData[tab]?.dev.type === 'none') return true\n\t\t\tif (ENV.EPICSHOP_DEPLOYED) {\n\t\t\t\tconst devType = loaderData[tab]?.dev.type\n\t\t\t\treturn (\n\t\t\t\t\tdevType !== 'browser' &&\n\t\t\t\t\tdevType !== 'export' &&\n\t\t\t\t\t!loaderData[tab]?.stackBlitzUrl\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tif (tab === 'playground' && ENV.EPICSHOP_DEPLOYED) return true\n\n\t\tif (tab === 'chat') {\n\t\t\treturn !workshopConfig.product.discordChannelId\n\t\t}\n\t\treturn false\n\t}\n\n\tfunction getTabStatus(\n\t\ttab: (typeof tabs)[number],\n\t): 'running' | 'passed' | 'failed' | null {\n\t\tif (tab === 'tests') {\n\t\t\tif (!loaderData.playground) return null\n\t\t\tconst { isTestRunning, testExitCode } = loaderData.playground\n\t\t\tif (isTestRunning) return 'running'\n\t\t\tif (testExitCode === 0) return 'passed'\n\t\t\tif (testExitCode !== null && testExitCode !== 0) return 'failed'\n\t\t\treturn null\n\t\t}\n\t\tif (tab === 'problem' || tab === 'solution' || tab === 'playground') {\n\t\t\tconst appData =\n\t\t\t\ttab === 'playground' ? loaderData.playground : loaderData[tab]\n\t\t\tif (appData?.isRunning) return 'running'\n\t\t}\n\t\treturn null\n\t}\n\n\tconst activeTab = isValidPreview(preview)\n\t\t? preview\n\t\t: tabs.find((t) => !shouldHideTab(t))\n\n\t// when alt is held down, the diff tab should open to the full-page diff view\n\t// between the problem and solution (this is more for the instructor than the student)\n\tconst altDiffUrl = `/diff?${new URLSearchParams({\n\t\tapp1: loaderData.problem?.name ?? '',\n\t\tapp2: loaderData.solution?.name ?? '',\n\t})}`\n\n\tfunction handleDiffTabClick(event: React.MouseEvent<HTMLAnchorElement>) {\n\t\tif (event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey) {\n\t\t\tevent.preventDefault()\n\t\t\tvoid navigate(altDiffUrl)\n\t\t}\n\t}\n\n\tconst previewTabs = tabs.map((tab) => {\n\t\tconst hidden = shouldHideTab(tab)\n\t\tconst status = getTabStatus(tab)\n\t\tconst to =\n\t\t\ttab === 'diff' && altDown\n\t\t\t\t? altDiffUrl\n\t\t\t\t: `?${getPreviewSearchParams(searchParams, tab, 'playground')}`\n\t\treturn {\n\t\t\tid: tab,\n\t\t\tlabel: tab,\n\t\t\thidden,\n\t\t\tstatus,\n\t\t\tto,\n\t\t\tonClick: tab === 'diff' ? handleDiffTabClick : undefined,\n\t\t}\n\t})\n\n\treturn (\n\t\t<Tabs.Root\n\t\t\tclassName=\"relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden sm:col-span-1 sm:row-span-1\"\n\t\t\tvalue={activeTab}\n\t\t\t// intentionally no onValueChange here because the Link will trigger the\n\t\t\t// change.\n\t\t>\n\t\t\t<PreviewTabsList tabs={previewTabs} />\n\t\t\t<div className=\"relative z-10 flex min-h-0 flex-1 flex-col overflow-hidden\">\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"playground\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Playground\n\t\t\t\t\t\tappInfo={loaderData.playground}\n\t\t\t\t\t\tproblemAppName={loaderData.problem?.name}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t\tallApps={loaderData.allApps}\n\t\t\t\t\t\tisUpToDate={loaderData.playground?.isUpToDate ?? false}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"problem\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={loaderData.problem}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"solution\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={loaderData.solution}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"tests\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start overflow-hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Tests\n\t\t\t\t\t\tappInfo={loaderData.playground}\n\t\t\t\t\t\tproblemAppName={loaderData.problem?.name}\n\t\t\t\t\t\tallApps={loaderData.allApps}\n\t\t\t\t\t\tisUpToDate={loaderData.playground?.isUpToDate ?? false}\n\t\t\t\t\t\tuserHasAccessPromise={loaderData.userHasAccessPromise}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"diff\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex h-full min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t>\n\t\t\t\t\t<Diff\n\t\t\t\t\t\tdiff={loaderData.diff}\n\t\t\t\t\t\tallApps={loaderData.allApps}\n\t\t\t\t\t\tuserHasAccessPromise={loaderData.userHasAccessPromise}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"chat\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex h-full min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t>\n\t\t\t\t\t<DiscordChat discordPostsPromise={loaderData.discordPostsPromise} />\n\t\t\t\t</Tabs.Content>\n\t\t\t</div>\n\t\t</Tabs.Root>\n\t)\n}\n\nexport function ErrorBoundary() {\n\treturn (\n\t\t<GeneralErrorBoundary\n\t\t\tstatusHandlers={{\n\t\t\t\t404: () => <p>Sorry, we couldn't find an app here.</p>,\n\t\t\t}}\n\t\t/>\n\t)\n}\n"],"names":["tabs","isValidPreview","s","Boolean","includes","index","_UNSAFE_withComponentProps","loaderData","inBrowserBrowserRef","useOutletContext","workshopConfig","useWorkshopConfig","searchParams","useSearchParams","preview","get","altDown","useAltDown","navigate","useNavigate","shouldHideTab","tab","ENV","EPICSHOP_DEPLOYED","playground","test","type","dev","devType","stackBlitzUrl","product","discordChannelId","getTabStatus","isTestRunning","testExitCode","isRunning","activeTab","find","t","altDiffUrl","URLSearchParams","app1","problem","name","app2","solution","handleDiffTabClick","event","altKey","ctrlKey","shiftKey","metaKey","preventDefault","previewTabs","map","hidden","status","to","getPreviewSearchParams","id","label","onClick","jsxs","Tabs","className","value","children","jsx","PreviewTabsList","forceMount","Playground","appInfo","problemAppName","allApps","isUpToDate","Preview","Tests","userHasAccessPromise","Diff","diff","DiscordChat","discordPostsPromise","ErrorBoundary","_UNSAFE_withErrorBoundaryProps","GeneralErrorBoundary","statusHandlers"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-InnNe6aG.js","sources":["../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index.tsx"],"sourcesContent":["import {\n\tgetAppByName,\n\tgetAppDisplayName,\n\tgetApps,\n\tgetExerciseApp,\n\tisExerciseStepApp,\n\tisPlaygroundApp,\n\trequireExerciseApp,\n\ttype App,\n\ttype ExerciseStepApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getDiffCode } from '@epic-web/workshop-utils/diff.server'\nimport { userHasAccessToExerciseStep } from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n} from '@epic-web/workshop-utils/timing.server'\nimport * as Tabs from '@radix-ui/react-tabs'\nimport * as React from 'react'\nimport {\n\tuseNavigate,\n\tuseSearchParams,\n\tdata,\n\tredirect,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n\tuseOutletContext,\n} from 'react-router'\nimport { Diff } from '#app/components/diff.tsx'\nimport { DiscordChat } from '#app/components/discord-chat.tsx'\nimport { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser.tsx'\nimport {\n\tgetPreviewSearchParams,\n\tPreviewTabsList,\n} from '#app/components/preview-tabs.tsx'\nimport { useWorkshopConfig } from '#app/components/workshop-config.tsx'\nimport { fetchDiscordPosts } from '#app/utils/discord.server.ts'\nimport { useAltDown } from '#app/utils/misc.tsx'\nimport { type Route } from './+types/index.ts'\nimport { Playground } from './__shared/playground.tsx'\nimport { Preview } from './__shared/preview.tsx'\nimport { Tests } from './__shared/tests.tsx'\nimport { getAppRunningState, getTestState } from './__shared/utils.tsx'\n\nexport async function loader({ request, params }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('exerciseStepTypeIndexLoader')\n\tconst searchParams = new URL(request.url).searchParams\n\tconst cacheOptions = { request, timings }\n\n\tconst [exerciseStepApp, allAppsFull, problemApp, solutionApp] =\n\t\tawait Promise.all([\n\t\t\trequireExerciseApp(params, cacheOptions),\n\t\t\tgetApps(cacheOptions),\n\t\t\tgetExerciseApp({ ...params, type: 'problem' }, cacheOptions),\n\t\t\tgetExerciseApp({ ...params, type: 'solution' }, cacheOptions),\n\t\t])\n\n\tconst playgroundApp = allAppsFull.find(isPlaygroundApp)\n\tconst reqUrl = new URL(request.url)\n\n\tconst pathnameParam = reqUrl.searchParams.get('pathname')\n\tif (pathnameParam === '' || pathnameParam === '/') {\n\t\treqUrl.searchParams.delete('pathname')\n\t\tthrow redirect(reqUrl.toString())\n\t}\n\n\tconst app1Name = reqUrl.searchParams.get('app1')\n\tconst app2Name = reqUrl.searchParams.get('app2')\n\tconst app1 = app1Name\n\t\t? await getAppByName(app1Name)\n\t\t: playgroundApp || problemApp\n\tconst app2 = app2Name ? await getAppByName(app2Name) : solutionApp\n\n\tfunction getStepId(a: ExerciseStepApp) {\n\t\treturn (\n\t\t\ta.exerciseNumber * 1000 +\n\t\t\ta.stepNumber * 10 +\n\t\t\t(a.type === 'problem' ? 0 : 1)\n\t\t)\n\t}\n\n\tfunction getStepNameAndId(a: App) {\n\t\tif (isExerciseStepApp(a)) {\n\t\t\tconst exerciseNumberStr = String(a.exerciseNumber).padStart(2, '0')\n\t\t\tconst stepNumberStr = String(a.stepNumber).padStart(2, '0')\n\n\t\t\treturn {\n\t\t\t\tstepName: `${exerciseNumberStr}/${stepNumberStr}.${a.type}`,\n\t\t\t\tstepId: getStepId(a),\n\t\t\t}\n\t\t}\n\t\treturn { stepName: '', stepId: -1 }\n\t}\n\n\tconst allApps = allAppsFull\n\t\t.filter((a, i, ar) => ar.findIndex((b) => a.name === b.name) === i)\n\t\t.map((a) => ({\n\t\t\tdisplayName: getAppDisplayName(a, allAppsFull),\n\t\t\tname: a.name,\n\t\t\ttitle: a.title,\n\t\t\ttype: a.type,\n\t\t\t...getStepNameAndId(a),\n\t\t}))\n\n\tallApps.sort((a, b) => {\n\t\t// order them by their stepId\n\t\tif (a.stepId > 0 && b.stepId > 0) return a.stepId - b.stepId\n\n\t\t// non-step apps should come after step apps\n\t\tif (a.stepId > 0) return -1\n\t\tif (b.stepId > 0) return 1\n\n\t\treturn 0\n\t})\n\n\tasync function getDiffProp() {\n\t\tif (!app1 || !app2) {\n\t\t\treturn {\n\t\t\t\tapp1: app1?.name,\n\t\t\t\tapp2: app2?.name,\n\t\t\t\tdiffCode: null,\n\t\t\t}\n\t\t}\n\t\tconst diffCode = await getDiffCode(app1, app2, {\n\t\t\t...cacheOptions,\n\t\t\tforceFresh: searchParams.get('forceFresh') === 'diff',\n\t\t}).catch((e) => {\n\t\t\tconsole.error(e)\n\t\t\treturn null\n\t\t})\n\t\treturn {\n\t\t\tapp1: app1.name,\n\t\t\tapp2: app2.name,\n\t\t\tdiffCode,\n\t\t}\n\t}\n\n\treturn data(\n\t\t{\n\t\t\ttype: params.type as 'problem' | 'solution',\n\t\t\texerciseStepApp,\n\t\t\tallApps,\n\t\t\t// defer this promise so that we don't block the response from being sent\n\t\t\tdiscordPostsPromise: fetchDiscordPosts({ request }),\n\t\t\tuserHasAccessPromise: userHasAccessToExerciseStep({\n\t\t\t\texerciseNumber: Number(params.exerciseNumber),\n\t\t\t\tstepNumber: Number(params.stepNumber),\n\t\t\t\trequest,\n\t\t\t\ttimings,\n\t\t\t}),\n\t\t\tplayground: playgroundApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'playground',\n\t\t\t\t\t\tfullPath: playgroundApp.fullPath,\n\t\t\t\t\t\tdev: playgroundApp.dev,\n\t\t\t\t\t\ttest: playgroundApp.test,\n\t\t\t\t\t\ttitle: playgroundApp.title,\n\t\t\t\t\t\tname: playgroundApp.name,\n\t\t\t\t\t\tappName: playgroundApp.appName,\n\t\t\t\t\t\tisUpToDate: playgroundApp.isUpToDate,\n\t\t\t\t\t\tstackBlitzUrl: playgroundApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(playgroundApp)),\n\t\t\t\t\t\t...getTestState(playgroundApp),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tproblem: problemApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'problem',\n\t\t\t\t\t\tfullPath: problemApp.fullPath,\n\t\t\t\t\t\tdev: problemApp.dev,\n\t\t\t\t\t\ttest: problemApp.test,\n\t\t\t\t\t\ttitle: problemApp.title,\n\t\t\t\t\t\tname: problemApp.name,\n\t\t\t\t\t\tstackBlitzUrl: problemApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(problemApp)),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tsolution: solutionApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'solution',\n\t\t\t\t\t\tfullPath: solutionApp.fullPath,\n\t\t\t\t\t\tdev: solutionApp.dev,\n\t\t\t\t\t\ttest: solutionApp.test,\n\t\t\t\t\t\ttitle: solutionApp.title,\n\t\t\t\t\t\tname: solutionApp.name,\n\t\t\t\t\t\tstackBlitzUrl: solutionApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(solutionApp)),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tdiff: getDiffProp(),\n\t\t} as const,\n\t\t{\n\t\t\theaders: {\n\t\t\t\t'Server-Timing': getServerTimeHeader(timings),\n\t\t\t},\n\t\t},\n\t)\n}\n\nexport const headers: HeadersFunction = ({ loaderHeaders, parentHeaders }) => {\n\tconst headers = {\n\t\t'Server-Timing': combineServerTimings(loaderHeaders, parentHeaders),\n\t}\n\treturn headers\n}\n\nconst tabs = [\n\t'playground',\n\t'problem',\n\t'solution',\n\t'tests',\n\t'diff',\n\t'chat',\n] as const\nconst isValidPreview = (s: string | null): s is (typeof tabs)[number] =>\n\tBoolean(s && tabs.includes(s as (typeof tabs)[number]))\n\nexport default function ExercisePartRoute({\n\tloaderData,\n}: Route.ComponentProps) {\n\tconst { inBrowserBrowserRef } = useOutletContext<{\n\t\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n\t}>()\n\tconst workshopConfig = useWorkshopConfig()\n\tconst [searchParams] = useSearchParams()\n\n\tconst preview = searchParams.get('preview')\n\n\tconst altDown = useAltDown()\n\tconst navigate = useNavigate()\n\n\tfunction shouldHideTab(tab: (typeof tabs)[number]) {\n\t\tif (tab === 'tests') {\n\t\t\treturn (\n\t\t\t\tENV.EPICSHOP_DEPLOYED ||\n\t\t\t\t!loaderData.playground ||\n\t\t\t\tloaderData.playground.test.type === 'none'\n\t\t\t)\n\t\t}\n\t\tif (tab === 'problem' || tab === 'solution') {\n\t\t\tif (loaderData[tab]?.dev.type === 'none') return true\n\t\t\tif (ENV.EPICSHOP_DEPLOYED) {\n\t\t\t\tconst devType = loaderData[tab]?.dev.type\n\t\t\t\treturn (\n\t\t\t\t\tdevType !== 'browser' &&\n\t\t\t\t\tdevType !== 'export' &&\n\t\t\t\t\t!loaderData[tab]?.stackBlitzUrl\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tif (tab === 'playground' && ENV.EPICSHOP_DEPLOYED) return true\n\n\t\tif (tab === 'chat') {\n\t\t\treturn !workshopConfig.product.discordChannelId\n\t\t}\n\t\treturn false\n\t}\n\n\tfunction getTabStatus(\n\t\ttab: (typeof tabs)[number],\n\t): 'running' | 'passed' | 'failed' | null {\n\t\tif (tab === 'tests') {\n\t\t\tif (!loaderData.playground) return null\n\t\t\tconst { isTestRunning, testExitCode } = loaderData.playground\n\t\t\tif (isTestRunning) return 'running'\n\t\t\tif (testExitCode === 0) return 'passed'\n\t\t\tif (testExitCode !== null && testExitCode !== 0) return 'failed'\n\t\t\treturn null\n\t\t}\n\t\tif (tab === 'problem' || tab === 'solution' || tab === 'playground') {\n\t\t\tconst appData =\n\t\t\t\ttab === 'playground' ? loaderData.playground : loaderData[tab]\n\t\t\tif (appData?.isRunning) return 'running'\n\t\t}\n\t\treturn null\n\t}\n\n\tconst activeTab = isValidPreview(preview)\n\t\t? preview\n\t\t: tabs.find((t) => !shouldHideTab(t))\n\n\t// when alt is held down, the diff tab should open to the full-page diff view\n\t// between the problem and solution (this is more for the instructor than the student)\n\tconst altDiffUrl = `/diff?${new URLSearchParams({\n\t\tapp1: loaderData.problem?.name ?? '',\n\t\tapp2: loaderData.solution?.name ?? '',\n\t})}`\n\n\tfunction handleDiffTabClick(event: React.MouseEvent<HTMLAnchorElement>) {\n\t\tif (event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey) {\n\t\t\tevent.preventDefault()\n\t\t\tvoid navigate(altDiffUrl)\n\t\t}\n\t}\n\n\tconst previewTabs = tabs.map((tab) => {\n\t\tconst hidden = shouldHideTab(tab)\n\t\tconst status = getTabStatus(tab)\n\t\tconst to =\n\t\t\ttab === 'diff' && altDown\n\t\t\t\t? altDiffUrl\n\t\t\t\t: `?${getPreviewSearchParams(searchParams, tab, 'playground')}`\n\t\treturn {\n\t\t\tid: tab,\n\t\t\tlabel: tab,\n\t\t\thidden,\n\t\t\tstatus,\n\t\t\tto,\n\t\t\tonClick: tab === 'diff' ? handleDiffTabClick : undefined,\n\t\t}\n\t})\n\n\treturn (\n\t\t<Tabs.Root\n\t\t\tclassName=\"relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden sm:col-span-1 sm:row-span-1\"\n\t\t\tvalue={activeTab}\n\t\t\t// intentionally no onValueChange here because the Link will trigger the\n\t\t\t// change.\n\t\t>\n\t\t\t<PreviewTabsList tabs={previewTabs} />\n\t\t\t<div className=\"relative z-10 flex min-h-0 flex-1 flex-col overflow-hidden\">\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"playground\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Playground\n\t\t\t\t\t\tappInfo={loaderData.playground}\n\t\t\t\t\t\tproblemAppName={loaderData.problem?.name}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t\tallApps={loaderData.allApps}\n\t\t\t\t\t\tisUpToDate={loaderData.playground?.isUpToDate ?? false}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"problem\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={loaderData.problem}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"solution\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={loaderData.solution}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"tests\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex min-h-0 w-full grow basis-0 items-stretch justify-center self-start overflow-hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Tests\n\t\t\t\t\t\tappInfo={loaderData.playground}\n\t\t\t\t\t\tproblemAppName={loaderData.problem?.name}\n\t\t\t\t\t\tallApps={loaderData.allApps}\n\t\t\t\t\t\tisUpToDate={loaderData.playground?.isUpToDate ?? false}\n\t\t\t\t\t\tuserHasAccessPromise={loaderData.userHasAccessPromise}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"diff\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex h-full min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t>\n\t\t\t\t\t<Diff\n\t\t\t\t\t\tdiff={loaderData.diff}\n\t\t\t\t\t\tallApps={loaderData.allApps}\n\t\t\t\t\t\tuserHasAccessPromise={loaderData.userHasAccessPromise}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"chat\"\n\t\t\t\t\tclassName=\"radix-state-inactive:hidden flex h-full min-h-0 w-full grow basis-0 items-stretch justify-center self-start\"\n\t\t\t\t>\n\t\t\t\t\t<DiscordChat discordPostsPromise={loaderData.discordPostsPromise} />\n\t\t\t\t</Tabs.Content>\n\t\t\t</div>\n\t\t</Tabs.Root>\n\t)\n}\n\nexport function ErrorBoundary() {\n\treturn (\n\t\t<GeneralErrorBoundary\n\t\t\tstatusHandlers={{\n\t\t\t\t404: () => <p>Sorry, we couldn't find an app here.</p>,\n\t\t\t}}\n\t\t/>\n\t)\n}\n"],"names":["tabs","isValidPreview","s","Boolean","includes","index","_UNSAFE_withComponentProps","loaderData","inBrowserBrowserRef","useOutletContext","workshopConfig","useWorkshopConfig","searchParams","useSearchParams","preview","get","altDown","useAltDown","navigate","useNavigate","shouldHideTab","tab","ENV","EPICSHOP_DEPLOYED","playground","test","type","dev","devType","stackBlitzUrl","product","discordChannelId","getTabStatus","isTestRunning","testExitCode","isRunning","activeTab","find","t","altDiffUrl","URLSearchParams","app1","problem","name","app2","solution","handleDiffTabClick","event","altKey","ctrlKey","shiftKey","metaKey","preventDefault","previewTabs","map","hidden","status","to","getPreviewSearchParams","id","label","onClick","jsxs","Tabs","className","value","children","jsx","PreviewTabsList","forceMount","Playground","appInfo","problemAppName","allApps","isUpToDate","Preview","Tests","userHasAccessPromise","Diff","diff","DiscordChat","discordPostsPromise","ErrorBoundary","_UNSAFE_withErrorBoundaryProps","GeneralErrorBoundary","statusHandlers"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{w as s,a,b as i,L as l}from"./chunk-EPOLDU6W-C4NOdiis.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{E as n}from"./index-BrUCi_AK.js";import{E as m}from"./epic-video-
|
|
2
|
-
//# sourceMappingURL=index-
|
|
1
|
+
import{w as s,a,b as i,L as l}from"./chunk-EPOLDU6W-C4NOdiis.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{E as n}from"./index-BrUCi_AK.js";import{E as m}from"./epic-video-BX2A437e.js";import{G as d}from"./error-boundary-B_ltT-yo.js";import{u as c}from"./revalidation-ws-Dcs0B3Rw.js";import{E as x}from"./launch-editor-D_PbWy0b.js";import{M as p}from"./mdx-BlaeOyqK.js";import{c as f}from"./misc-CRhJChs6.js";import{g as u}from"./root-loader-BObzljW3.js";import{g as h}from"./seo-t5J-DRxw.js";import"./index-CqIc3cxq.js";import"./use-event-source-BuD4_2SF.js";import"./index-DzdDahau.js";import"./index-vDCSPjrM.js";import"./index-DVd41HZN.js";import"./tooltip-f3C9W-4C.js";import"./pe-UQCAhDPv.js";import"./schemas-Uj5SZtvt.js";import"./online-D6QnZT5V.js";import"./loading-BiVU3Oa8.js";import"./user-CFfhNfdz.js";import"./workshop-config-BP-vDuRo.js";import"./preload-helper-BXl3LOEh.js";import"./progress-bar-Cxy0ZpqZ.js";const Q=o=>{const r=o.data,t=u(o.matches);return!r||!t?[{title:"🦉 | Error"}]:h({title:`📚 | ${r.title} | ${t.workshopTitle}`,description:`Extras for ${t.workshopTitle}`,ogTitle:r.title,ogDescription:`Extras for ${t.workshopTitle}`,instructor:t.instructor,requestInfo:t.requestInfo})};function j({extra:o}){return e.jsx("li",{children:e.jsxs(l,{className:f("relative flex items-center gap-4 px-4 py-3 text-lg font-semibold transition","hover:bg-muted/60 focus:bg-muted/60"),prefetch:"intent",to:o.dirName,children:[e.jsx("span",{className:"text-muted-foreground text-xs font-normal tabular-nums",children:"•"}),e.jsx("span",{className:"truncate",children:o.title})]})})}const v={h1:()=>null},W=s(function(){const r=i();return c({watchPaths:["./extra","./example","./examples"]}),e.jsxs("main",{className:"relative flex h-full w-full max-w-5xl flex-col justify-between border-r md:w-3/4 xl:w-2/3",children:[e.jsxs("article",{id:r.articleId,className:"shadow-on-scrollbox scrollbar-thin scrollbar-thumb-scrollbar flex w-full flex-1 flex-col gap-12 overflow-y-scroll px-3 py-4 pt-6 md:px-10 md:py-12 md:pt-16",children:[e.jsx("div",{children:e.jsx("h1",{className:"text-[clamp(3rem,6vw,7.5rem)] leading-none font-extrabold",children:r.title})}),e.jsx("div",{children:r.extrasReadme.compiled.status==="success"&&r.extrasReadme.compiled.code?e.jsx(m,{epicVideoInfosPromise:r.epicVideoInfosPromise,children:e.jsx("div",{className:"prose dark:prose-invert sm:prose-lg",children:e.jsx(p,{code:r.extrasReadme.compiled.code,components:v})})}):r.extrasReadme.compiled.status==="error"?e.jsxs("div",{className:"text-foreground-destructive",children:["There was an error:",e.jsx("pre",{children:r.extrasReadme.compiled.error})]}):"No extras overview yet..."}),e.jsxs("div",{className:"pt-6",children:[e.jsx("h2",{className:"pb-4 font-mono text-xs font-semibold uppercase",children:"Extras"}),r.extras.length?e.jsx("ul",{className:"divide-border dark:divide-border/50 flex flex-col divide-y",children:r.extras.map(t=>e.jsx(j,{extra:t},t.dirName))}):e.jsx("p",{className:"text-muted-foreground",children:"No extras yet. Add one to get started."})]})]}),e.jsx(n,{elementQuery:`#${r.articleId}`}),e.jsx("div",{className:"@container flex h-16 justify-center border-t",children:e.jsx(x,{file:r.extrasReadme.file,relativePath:r.extrasReadme.relativePath})})]})}),z=a(function(){return e.jsx(d,{})});export{z as ErrorBoundary,W as default,Q as meta};
|
|
2
|
+
//# sourceMappingURL=index-T3LlCTSm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-T3LlCTSm.js","sources":["../../../app/routes/_app+/extra+/index.tsx"],"sourcesContent":["import { ElementScrollRestoration } from '@epic-web/restore-scroll'\nimport {\n\tgetApps,\n\tgetExtrasInstructions,\n\tisExtraApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport { getEpicVideoInfos } from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n\ttime,\n} from '@epic-web/workshop-utils/timing.server'\nimport slugify from '@sindresorhus/slugify'\nimport {\n\tdata,\n\ttype HeadersFunction,\n\tLink,\n\ttype LoaderFunctionArgs,\n\ttype MetaFunction,\n\tuseLoaderData,\n} from 'react-router'\nimport { EpicVideoInfoProvider } from '#app/components/epic-video.tsx'\nimport { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'\nimport { useRevalidationWS } from '#app/components/revalidation-ws.tsx'\nimport { EditFileOnGitHub } from '#app/routes/launch-editor.tsx'\nimport { Mdx } from '#app/utils/mdx.tsx'\nimport { cn } from '#app/utils/misc.tsx'\nimport { getRootMatchLoaderData } from '#app/utils/root-loader.ts'\nimport { getSeoMetaTags } from '#app/utils/seo.ts'\n\nexport const meta: MetaFunction<typeof loader> = (args) => {\n\tconst loaderData = args.data\n\tconst rootData = getRootMatchLoaderData(args.matches)\n\tif (!loaderData || !rootData) return [{ title: '🦉 | Error' }]\n\n\treturn getSeoMetaTags({\n\t\ttitle: `📚 | ${loaderData.title} | ${rootData.workshopTitle}`,\n\t\tdescription: `Extras for ${rootData.workshopTitle}`,\n\t\togTitle: loaderData.title,\n\t\togDescription: `Extras for ${rootData.workshopTitle}`,\n\t\tinstructor: rootData.instructor,\n\t\trequestInfo: rootData.requestInfo,\n\t})\n}\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('extrasIndexLoader')\n\tconst { title: workshopTitle } = getWorkshopConfig()\n\tconst [extrasReadme, apps] = await Promise.all([\n\t\ttime(() => getExtrasInstructions({ request }), {\n\t\t\ttimings,\n\t\t\ttype: 'compileMdx',\n\t\t\tdesc: 'compileMdx in extras index',\n\t\t}),\n\t\ttime(() => getApps({ request, timings }), {\n\t\t\ttimings,\n\t\t\ttype: 'getApps',\n\t\t\tdesc: 'getApps in extras index',\n\t\t}),\n\t])\n\n\tconst extras = apps\n\t\t.filter(isExtraApp)\n\t\t.sort((a, b) =>\n\t\t\ta.title.localeCompare(b.title, undefined, {\n\t\t\t\tnumeric: true,\n\t\t\t\tsensitivity: 'base',\n\t\t\t}),\n\t\t)\n\t\t.map((extra) => ({\n\t\t\tdirName: extra.dirName,\n\t\t\ttitle: extra.title,\n\t\t}))\n\n\tconst title =\n\t\textrasReadme.compiled.status === 'success'\n\t\t\t? (extrasReadme.compiled.title ?? 'Extras')\n\t\t\t: 'Extras'\n\n\treturn data(\n\t\t{\n\t\t\tarticleId: `workshop-${slugify(workshopTitle)}-extras`,\n\t\t\ttitle,\n\t\t\textras,\n\t\t\textrasReadme,\n\t\t\tepicVideoInfosPromise:\n\t\t\t\textrasReadme.compiled.status === 'success'\n\t\t\t\t\t? getEpicVideoInfos(extrasReadme.compiled.epicVideoEmbeds, {\n\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t})\n\t\t\t\t\t: null,\n\t\t},\n\t\t{\n\t\t\theaders: {\n\t\t\t\t'Server-Timing': getServerTimeHeader(timings),\n\t\t\t},\n\t\t},\n\t)\n}\n\nexport const headers: HeadersFunction = ({ loaderHeaders, parentHeaders }) => {\n\tconst headers = {\n\t\t'Cache-Control': loaderHeaders.get('Cache-Control') ?? '',\n\t\t'Server-Timing': combineServerTimings(loaderHeaders, parentHeaders),\n\t}\n\treturn headers\n}\n\nfunction ExtraListItem({\n\textra,\n}: {\n\textra: { dirName: string; title: string }\n}) {\n\treturn (\n\t\t<li>\n\t\t\t<Link\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'relative flex items-center gap-4 px-4 py-3 text-lg font-semibold transition',\n\t\t\t\t\t'hover:bg-muted/60 focus:bg-muted/60',\n\t\t\t\t)}\n\t\t\t\tprefetch=\"intent\"\n\t\t\t\tto={extra.dirName}\n\t\t\t>\n\t\t\t\t<span className=\"text-muted-foreground text-xs font-normal tabular-nums\">\n\t\t\t\t\t•\n\t\t\t\t</span>\n\t\t\t\t<span className=\"truncate\">{extra.title}</span>\n\t\t\t</Link>\n\t\t</li>\n\t)\n}\n\nconst mdxComponents = { h1: () => null }\n\nexport default function ExtrasIndex() {\n\tconst data = useLoaderData<typeof loader>()\n\tuseRevalidationWS({ watchPaths: ['./extra', './example', './examples'] })\n\n\treturn (\n\t\t<main className=\"relative flex h-full w-full max-w-5xl flex-col justify-between border-r md:w-3/4 xl:w-2/3\">\n\t\t\t<article\n\t\t\t\tid={data.articleId}\n\t\t\t\tclassName=\"shadow-on-scrollbox scrollbar-thin scrollbar-thumb-scrollbar flex w-full flex-1 flex-col gap-12 overflow-y-scroll px-3 py-4 pt-6 md:px-10 md:py-12 md:pt-16\"\n\t\t\t>\n\t\t\t\t<div>\n\t\t\t\t\t<h1 className=\"text-[clamp(3rem,6vw,7.5rem)] leading-none font-extrabold\">\n\t\t\t\t\t\t{data.title}\n\t\t\t\t\t</h1>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t{data.extrasReadme.compiled.status === 'success' &&\n\t\t\t\t\tdata.extrasReadme.compiled.code ? (\n\t\t\t\t\t\t<EpicVideoInfoProvider\n\t\t\t\t\t\t\tepicVideoInfosPromise={data.epicVideoInfosPromise}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className=\"prose dark:prose-invert sm:prose-lg\">\n\t\t\t\t\t\t\t\t<Mdx\n\t\t\t\t\t\t\t\t\tcode={data.extrasReadme.compiled.code}\n\t\t\t\t\t\t\t\t\tcomponents={mdxComponents}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</EpicVideoInfoProvider>\n\t\t\t\t\t) : data.extrasReadme.compiled.status === 'error' ? (\n\t\t\t\t\t\t<div className=\"text-foreground-destructive\">\n\t\t\t\t\t\t\tThere was an error:\n\t\t\t\t\t\t\t<pre>{data.extrasReadme.compiled.error}</pre>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t'No extras overview yet...'\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"pt-6\">\n\t\t\t\t\t<h2 className=\"pb-4 font-mono text-xs font-semibold uppercase\">\n\t\t\t\t\t\tExtras\n\t\t\t\t\t</h2>\n\t\t\t\t\t{data.extras.length ? (\n\t\t\t\t\t\t<ul className=\"divide-border dark:divide-border/50 flex flex-col divide-y\">\n\t\t\t\t\t\t\t{data.extras.map((extra) => (\n\t\t\t\t\t\t\t\t<ExtraListItem key={extra.dirName} extra={extra} />\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<p className=\"text-muted-foreground\">\n\t\t\t\t\t\t\tNo extras yet. Add one to get started.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</article>\n\t\t\t<ElementScrollRestoration elementQuery={`#${data.articleId}`} />\n\t\t\t<div className=\"@container flex h-16 justify-center border-t\">\n\t\t\t\t<EditFileOnGitHub\n\t\t\t\t\tfile={data.extrasReadme.file}\n\t\t\t\t\trelativePath={data.extrasReadme.relativePath}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</main>\n\t)\n}\n\nexport function ErrorBoundary() {\n\treturn <GeneralErrorBoundary />\n}\n"],"names":["meta","args","loaderData","data","rootData","getRootMatchLoaderData","matches","title","getSeoMetaTags","workshopTitle","description","ogTitle","ogDescription","instructor","requestInfo","ExtraListItem","extra","children","jsxs","Link","className","cn","prefetch","to","dirName","jsx","mdxComponents","h1","index","_UNSAFE_withComponentProps","useLoaderData","useRevalidationWS","watchPaths","id","articleId","extrasReadme","compiled","status","code","EpicVideoInfoProvider","epicVideoInfosPromise","Mdx","components","error","extras","length","map","ElementScrollRestoration","elementQuery","EditFileOnGitHub","file","relativePath","ErrorBoundary","_UNSAFE_withErrorBoundaryProps","GeneralErrorBoundary"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{r as n}from"./index-CqIc3cxq.js";import{a as d}from"./index-
|
|
2
|
-
//# sourceMappingURL=loading-
|
|
1
|
+
import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{r as n}from"./index-CqIc3cxq.js";import{a as d}from"./index-DVd41HZN.js";import{c as f}from"./misc-CRhJChs6.js";function j({className:r,children:t="Loading"}){const{reducedMotion:s}=d();return s==="reduce"?e.jsx("div",{className:"animate-pulse",children:t}):e.jsxs("div",{className:f("flex items-center gap-2 font-mono text-sm font-medium uppercase",r),role:"status",children:[e.jsx("div",{"aria-hidden":"true",children:e.jsx(i,{})}),t,e.jsx("div",{"aria-hidden":"true",children:e.jsx(i,{})})]})}const a="█<▓█ ▒░/▒░ █░>▒▓/ █▒▒ ▓▒▓/█<░▒ ▓/░>",c=()=>a[Math.floor(Math.random()*a.length)];function i(){const[r,t]=n.useState(a[0]),[s,o]=n.useState(a[1]);return m(()=>{t(c()),o(c())},80),e.jsxs("span",{children:[r,s]})}function m(r,t=1e3){const s=n.useRef(null);n.useEffect(()=>{s.current=r},[r]),n.useEffect(()=>{function o(){s.current?.()}if(t!==null){const u=setInterval(o,t);return()=>clearInterval(u)}},[t])}export{j as L};
|
|
2
|
+
//# sourceMappingURL=loading-BiVU3Oa8.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loading-
|
|
1
|
+
{"version":3,"file":"loading-BiVU3Oa8.js","sources":["../../../app/components/loading.tsx"],"sourcesContent":["// originally this was based on baffle-react, but it was unnecessarily bloated\n// and very out-dated. I've replaced it with a simple Characters component that\n// does the same thing we were using baffle-react for\nimport { useEffect, useRef, useState } from 'react'\nimport { useHints } from '#app/utils/client-hints.tsx'\nimport { cn } from '#app/utils/misc.tsx'\n\nexport function Loading({\n\tclassName,\n\tchildren = 'Loading',\n}: {\n\tclassName?: string\n\tchildren?: React.ReactNode\n}) {\n\tconst { reducedMotion } = useHints()\n\tif (reducedMotion === 'reduce') {\n\t\treturn <div className=\"animate-pulse\">{children}</div>\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-center gap-2 font-mono text-sm font-medium uppercase',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\trole=\"status\"\n\t\t>\n\t\t\t<div aria-hidden=\"true\">\n\t\t\t\t<Characters />\n\t\t\t</div>\n\t\t\t{children}\n\t\t\t<div aria-hidden=\"true\">\n\t\t\t\t<Characters />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nconst characters = '█<▓█ ▒░/▒░ █░>▒▓/ █▒▒ ▓▒▓/█<░▒ ▓/░>'\nconst randomCharacter = () =>\n\tcharacters[Math.floor(Math.random() * characters.length)]\nexport function Characters() {\n\tconst [char1, setChar1] = useState(characters[0])\n\tconst [char2, setChar2] = useState(characters[1])\n\n\tuseInterval(() => {\n\t\tsetChar1(randomCharacter())\n\t\tsetChar2(randomCharacter())\n\t}, 80)\n\n\treturn (\n\t\t<span>\n\t\t\t{char1}\n\t\t\t{char2}\n\t\t</span>\n\t)\n}\n\nfunction useInterval(callback: () => void, delay: number | null = 1000) {\n\tconst savedCallback = useRef<() => void>(null)\n\n\t// Remember the latest function.\n\tuseEffect(() => {\n\t\tsavedCallback.current = callback\n\t}, [callback])\n\n\t// Set up the interval.\n\tuseEffect(() => {\n\t\tfunction tick() {\n\t\t\tsavedCallback.current?.()\n\t\t}\n\t\tif (delay !== null) {\n\t\t\tconst id = setInterval(tick, delay)\n\t\t\treturn () => clearInterval(id)\n\t\t}\n\t}, [delay])\n}\n"],"names":["Loading","className","children","reducedMotion","useHints","jsx","jsxs","cn","Characters","characters","randomCharacter","char1","setChar1","useState","char2","setChar2","useInterval","callback","delay","savedCallback","useRef","useEffect","tick","id"],"mappings":"qKAOO,SAASA,EAAQ,CACvB,UAAAC,EACA,SAAAC,EAAW,SACZ,EAGG,CACF,KAAM,CAAE,cAAAC,CAAA,EAAkBC,EAAA,EAC1B,OAAID,IAAkB,SACdE,EAAAA,IAAC,MAAA,CAAI,UAAU,gBAAiB,SAAAH,CAAA,CAAS,EAIhDI,EAAAA,KAAC,MAAA,CACA,UAAWC,EACV,kEACAN,CAAA,EAED,KAAK,SAEL,SAAA,CAAAI,MAAC,MAAA,CAAI,cAAY,OAChB,SAAAA,MAACG,IAAW,EACb,EACCN,QACA,MAAA,CAAI,cAAY,OAChB,SAAAG,EAAAA,IAACG,IAAW,CAAA,CACb,CAAA,CAAA,CAAA,CAGH,CAEA,MAAMC,EAAa,sCACbC,EAAkB,IACvBD,EAAW,KAAK,MAAM,KAAK,OAAA,EAAWA,EAAW,MAAM,CAAC,EAClD,SAASD,GAAa,CAC5B,KAAM,CAACG,EAAOC,CAAQ,EAAIC,EAAAA,SAASJ,EAAW,CAAC,CAAC,EAC1C,CAACK,EAAOC,CAAQ,EAAIF,EAAAA,SAASJ,EAAW,CAAC,CAAC,EAEhD,OAAAO,EAAY,IAAM,CACjBJ,EAASF,GAAiB,EAC1BK,EAASL,GAAiB,CAC3B,EAAG,EAAE,SAGH,OAAA,CACC,SAAA,CAAAC,EACAG,CAAA,EACF,CAEF,CAEA,SAASE,EAAYC,EAAsBC,EAAuB,IAAM,CACvE,MAAMC,EAAgBC,EAAAA,OAAmB,IAAI,EAG7CC,EAAAA,UAAU,IAAM,CACfF,EAAc,QAAUF,CACzB,EAAG,CAACA,CAAQ,CAAC,EAGbI,EAAAA,UAAU,IAAM,CACf,SAASC,GAAO,CACfH,EAAc,UAAA,CACf,CACA,GAAID,IAAU,KAAM,CACnB,MAAMK,EAAK,YAAYD,EAAMJ,CAAK,EAClC,MAAO,IAAM,cAAcK,CAAE,CAC9B,CACD,EAAG,CAACL,CAAK,CAAC,CACX"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{w as g,f as j,e as y,l as C,L as N}from"./chunk-EPOLDU6W-C4NOdiis.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{r as a}from"./index-CqIc3cxq.js";import{u as R}from"./use-event-source-BuD4_2SF.js";import{a as S,B as b}from"./button-CVorsvM4.js";import{L as w}from"./loading-
|
|
2
|
-
//# sourceMappingURL=login-
|
|
1
|
+
import{w as g,f as j,e as y,l as C,L as N}from"./chunk-EPOLDU6W-C4NOdiis.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{r as a}from"./index-CqIc3cxq.js";import{u as R}from"./use-event-source-BuD4_2SF.js";import{a as S,B as b}from"./button-CVorsvM4.js";import{L as w}from"./loading-BiVU3Oa8.js";import{L as _}from"./product-CNG57fZy.js";import{u as k}from"./workshop-config-BP-vDuRo.js";import{u as D,o as c,s as l,l as d}from"./schemas-Uj5SZtvt.js";import"./misc-CRhJChs6.js";import"./index-DVd41HZN.js";import"./tooltip-f3C9W-4C.js";import"./index-vDCSPjrM.js";import"./root-loader-BObzljW3.js";import"./pe-UQCAhDPv.js";const t={USER_CODE_RECEIVED:"USER_CODE_RECEIVED",AUTH_RESOLVED:"AUTH_RESOLVED",AUTH_REJECTED:"AUTH_REJECTED"},L=c({type:d(t.USER_CODE_RECEIVED),code:l(),url:l()}),T=c({type:d(t.AUTH_RESOLVED)}),A=c({type:d(t.AUTH_REJECTED),error:l().optional().default("Unknown error")}),U=D([L,T,A]),X={getSitemapEntries:()=>null},Z=g(function(){const{product:{displayName:r}}=k(),i=j(),[p,x]=a.useState(!1),[u,h]=a.useState(null),[o,E]=a.useState(null),m=y(),f=C(),n=R("/login-sse");return a.useEffect(()=>{if(!n)return;const v=JSON.parse(n),s=U.safeParse(v);if(!s.success){console.error(s.error.flatten());return}switch(s.data.type){case t.USER_CODE_RECEIVED:{E(s.data);break}case t.AUTH_RESOLVED:{f.revalidate().then(()=>m("/"));break}case t.AUTH_REJECTED:{h(s.data.error);break}}},[n,m,f]),e.jsx("main",{className:"flex h-full w-full grow flex-col items-center justify-center p-10",children:e.jsxs("div",{className:"flex flex-col items-center",children:[e.jsx(_,{className:"h-16 w-16"}),e.jsxs("h1",{className:"pt-5 text-2xl font-semibold md:text-3xl",children:["Login to ",r]}),e.jsxs("div",{className:"flex w-full flex-col items-center pt-5",children:[o?e.jsxs("div",{className:"flex w-full max-w-md flex-col items-center gap-3",children:[e.jsxs("div",{className:"my-2 flex w-full flex-col items-center gap-2",children:[e.jsx("p",{className:"text-lg",children:"Your verification code is: "}),e.jsx("div",{className:"bg-muted mb-3 w-full px-5 py-3 text-center text-lg font-bold",children:e.jsx("code",{children:o.code})}),e.jsxs("p",{className:"text-base",children:["You'll use this to verify your device on ",r,". Click verify code below to open the verification page."]})]}),e.jsx(S,{varient:"primary",to:o.url,target:"_blank",rel:"noreferrer",onClick:()=>x(!0),children:"Verify Auth Code"}),p?e.jsxs("div",{className:"justify-center pt-5 text-center opacity-60",children:[e.jsx(w,{className:"justify-center",children:"Waiting for confirmation"}),e.jsxs("p",{className:"pt-2",children:["Please open"," ",e.jsx("a",{href:o.url,target:"_blank",className:"underline",children:"your auth page"})," ","in a new tab to continue."]})]}):null]}):e.jsxs("div",{className:"flex flex-col items-center gap-8",children:[e.jsxs("div",{className:"text-muted-foreground flex max-w-lg flex-col gap-3 pt-3 text-base",children:[e.jsxs("p",{children:["If you have access to this workshop on ",r,", you'll be able to watch videos, track progress, run tests, view the diffs, and more!"]}),e.jsxs("p",{children:["First you need to authenticate your device by requesting an access code and verifying on ",r,"."]})]}),e.jsx(i.Form,{method:"POST",children:e.jsx(b,{varient:"primary",type:"submit",children:i.state==="idle"&&i.data?.status!=="pending"?"Retrieve Auth Code":"Retrieving Auth Code..."})})]}),u?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"text-foreground-destructive mt-4",children:["There was an error: ",e.jsx("pre",{children:u})]}),e.jsxs("div",{className:"text-foreground-destructive mt-4",children:["Please try again or"," ",e.jsx(N,{to:"/support",className:"underline",children:"contact support"})," ","if the problem persists."]})]}):null]})]})})});export{Z as default,X as handle};
|
|
2
|
+
//# sourceMappingURL=login-Ej63Q5LC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-VlyrGJvd.js","sources":["../../../app/utils/auth-events.ts","../../../app/routes/login-sse.tsx","../../../app/routes/_app+/login.tsx"],"sourcesContent":["export const EVENTS = {\n\tUSER_CODE_RECEIVED: 'USER_CODE_RECEIVED',\n\tAUTH_RESOLVED: 'AUTH_RESOLVED',\n\tAUTH_REJECTED: 'AUTH_REJECTED',\n} as const\nexport type EventTypes = keyof typeof EVENTS\n","import { type LoaderFunctionArgs } from 'react-router'\nimport { eventStream } from 'remix-utils/sse/server'\nimport { z } from 'zod'\nimport { EVENTS } from '#app/utils/auth-events.ts'\nimport { authEmitter } from '#app/utils/auth.server.ts'\nimport { ensureUndeployed } from '#app/utils/misc.tsx'\n\nconst CodeReceivedEventSchema = z.object({\n\ttype: z.literal(EVENTS.USER_CODE_RECEIVED),\n\tcode: z.string(),\n\turl: z.string(),\n})\nconst AuthResolvedEventSchema = z.object({\n\ttype: z.literal(EVENTS.AUTH_RESOLVED),\n})\nconst AuthRejectedEventSchema = z.object({\n\ttype: z.literal(EVENTS.AUTH_REJECTED),\n\terror: z.string().optional().default('Unknown error'),\n})\nexport const EventSchema = z.union([\n\tCodeReceivedEventSchema,\n\tAuthResolvedEventSchema,\n\tAuthRejectedEventSchema,\n])\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tensureUndeployed()\n\treturn eventStream(request.signal, function setup(send) {\n\t\tfunction handleCodeReceived(data: any) {\n\t\t\tsend({\n\t\t\t\tdata: JSON.stringify(\n\t\t\t\t\tCodeReceivedEventSchema.parse({\n\t\t\t\t\t\ttype: EVENTS.USER_CODE_RECEIVED,\n\t\t\t\t\t\t...data,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t})\n\t\t}\n\t\tfunction handleAuthResolved() {\n\t\t\tsend({ data: JSON.stringify({ type: EVENTS.AUTH_RESOLVED }) })\n\t\t}\n\t\tfunction handleAuthRejected(data: any) {\n\t\t\tconst result = AuthRejectedEventSchema.safeParse({\n\t\t\t\ttype: EVENTS.AUTH_REJECTED,\n\t\t\t\t...data,\n\t\t\t})\n\t\t\tif (result.success) {\n\t\t\t\tsend({ data: JSON.stringify(result.data) })\n\t\t\t} else {\n\t\t\t\tconsole.error('Error parsing auth rejected event', result.error, data)\n\t\t\t}\n\t\t}\n\t\tauthEmitter.on(EVENTS.USER_CODE_RECEIVED, handleCodeReceived)\n\t\tauthEmitter.on(EVENTS.AUTH_RESOLVED, handleAuthResolved)\n\t\tauthEmitter.on(EVENTS.AUTH_REJECTED, handleAuthRejected)\n\t\treturn () => {\n\t\t\tauthEmitter.off(EVENTS.USER_CODE_RECEIVED, handleCodeReceived)\n\t\t\tauthEmitter.off(EVENTS.AUTH_RESOLVED, handleAuthResolved)\n\t\t\tauthEmitter.off(EVENTS.AUTH_REJECTED, handleAuthRejected)\n\t\t}\n\t})\n}\n","import { getAuthInfo } from '@epic-web/workshop-utils/db.server'\nimport { type SEOHandle } from '@nasa-gcn/remix-seo'\nimport { useEffect, useState } from 'react'\nimport {\n\tredirect,\n\tLink,\n\tuseFetcher,\n\tuseNavigate,\n\tuseRevalidator,\n} from 'react-router'\nimport { useEventSource } from 'remix-utils/sse/react'\nimport { Button, ButtonLink } from '#app/components/button.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { Logo } from '#app/components/product.tsx'\nimport { useWorkshopConfig } from '#app/components/workshop-config.tsx'\nimport { EVENTS } from '#app/utils/auth-events.ts'\nimport { registerDevice } from '#app/utils/auth.server.ts'\nimport { ensureUndeployed } from '#app/utils/misc.tsx'\nimport { EventSchema } from '../login-sse.tsx'\n\nexport const handle: SEOHandle = {\n\tgetSitemapEntries: () => null,\n}\n\nexport async function loader() {\n\tensureUndeployed()\n\tconst isAuthenticated = Boolean(await getAuthInfo())\n\tif (isAuthenticated) throw redirect('/account')\n\treturn {}\n}\n\nexport async function action() {\n\tensureUndeployed()\n\tvoid registerDevice()\n\treturn { status: 'pending' } as const\n}\n\nexport default function Login() {\n\tconst {\n\t\tproduct: { displayName },\n\t} = useWorkshopConfig()\n\tconst loginFetcher = useFetcher<typeof action>()\n\tconst [clickedVerificationLink, setClickedVerificationLink] = useState(false)\n\tconst [authError, setAuthError] = useState<null | string>(null)\n\tconst [userCodeInfo, setUserCodeInfo] = useState<null | {\n\t\tcode: string\n\t\turl: string\n\t}>(null)\n\tconst navigate = useNavigate()\n\tconst revalidator = useRevalidator()\n\tconst lastMessage = useEventSource(`/login-sse`)\n\tuseEffect(() => {\n\t\tif (!lastMessage) return\n\n\t\tconst parsed = JSON.parse(lastMessage)\n\t\tconst result = EventSchema.safeParse(parsed)\n\t\tif (!result.success) {\n\t\t\tconsole.error(result.error.flatten())\n\t\t\treturn\n\t\t}\n\t\tswitch (result.data.type) {\n\t\t\tcase EVENTS.USER_CODE_RECEIVED: {\n\t\t\t\tsetUserCodeInfo(result.data)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase EVENTS.AUTH_RESOLVED: {\n\t\t\t\tvoid revalidator.revalidate().then(() => navigate('/'))\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase EVENTS.AUTH_REJECTED: {\n\t\t\t\tsetAuthError(result.data.error)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}, [lastMessage, navigate, revalidator])\n\n\treturn (\n\t\t<main className=\"flex h-full w-full grow flex-col items-center justify-center p-10\">\n\t\t\t<div className=\"flex flex-col items-center\">\n\t\t\t\t<Logo className=\"h-16 w-16\" />\n\t\t\t\t<h1 className=\"pt-5 text-2xl font-semibold md:text-3xl\">\n\t\t\t\t\tLogin to {displayName}\n\t\t\t\t</h1>\n\t\t\t\t<div className=\"flex w-full flex-col items-center pt-5\">\n\t\t\t\t\t{userCodeInfo ? (\n\t\t\t\t\t\t<div className=\"flex w-full max-w-md flex-col items-center gap-3\">\n\t\t\t\t\t\t\t<div className=\"my-2 flex w-full flex-col items-center gap-2\">\n\t\t\t\t\t\t\t\t<p className=\"text-lg\">Your verification code is: </p>\n\t\t\t\t\t\t\t\t<div className=\"bg-muted mb-3 w-full px-5 py-3 text-center text-lg font-bold\">\n\t\t\t\t\t\t\t\t\t<code>{userCodeInfo.code}</code>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<p className=\"text-base\">\n\t\t\t\t\t\t\t\t\tYou'll use this to verify your device on {displayName}. Click\n\t\t\t\t\t\t\t\t\tverify code below to open the verification page.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<ButtonLink\n\t\t\t\t\t\t\t\tvarient=\"primary\"\n\t\t\t\t\t\t\t\tto={userCodeInfo.url}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\tonClick={() => setClickedVerificationLink(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tVerify Auth Code\n\t\t\t\t\t\t\t</ButtonLink>\n\t\t\t\t\t\t\t{clickedVerificationLink ? (\n\t\t\t\t\t\t\t\t<div className=\"justify-center pt-5 text-center opacity-60\">\n\t\t\t\t\t\t\t\t\t<Loading className=\"justify-center\">\n\t\t\t\t\t\t\t\t\t\tWaiting for confirmation\n\t\t\t\t\t\t\t\t\t</Loading>\n\t\t\t\t\t\t\t\t\t<p className=\"pt-2\">\n\t\t\t\t\t\t\t\t\t\tPlease open{' '}\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\thref={userCodeInfo.url}\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tyour auth page\n\t\t\t\t\t\t\t\t\t\t</a>{' '}\n\t\t\t\t\t\t\t\t\t\tin a new tab to continue.\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"flex flex-col items-center gap-8\">\n\t\t\t\t\t\t\t<div className=\"text-muted-foreground flex max-w-lg flex-col gap-3 pt-3 text-base\">\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tIf you have access to this workshop on {displayName}, you'll\n\t\t\t\t\t\t\t\t\tbe able to watch videos, track progress, run tests, view the\n\t\t\t\t\t\t\t\t\tdiffs, and more!\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tFirst you need to authenticate your device by requesting an\n\t\t\t\t\t\t\t\t\taccess code and verifying on {displayName}.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<loginFetcher.Form method=\"POST\">\n\t\t\t\t\t\t\t\t<Button varient=\"primary\" type=\"submit\">\n\t\t\t\t\t\t\t\t\t{loginFetcher.state === 'idle' &&\n\t\t\t\t\t\t\t\t\tloginFetcher.data?.status !== 'pending'\n\t\t\t\t\t\t\t\t\t\t? `Retrieve Auth Code`\n\t\t\t\t\t\t\t\t\t\t: `Retrieving Auth Code...`}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</loginFetcher.Form>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{authError ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div className=\"text-foreground-destructive mt-4\">\n\t\t\t\t\t\t\t\tThere was an error: <pre>{authError}</pre>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"text-foreground-destructive mt-4\">\n\t\t\t\t\t\t\t\tPlease try again or{' '}\n\t\t\t\t\t\t\t\t<Link to=\"/support\" className=\"underline\">\n\t\t\t\t\t\t\t\t\tcontact support\n\t\t\t\t\t\t\t\t</Link>{' '}\n\t\t\t\t\t\t\t\tif the problem persists.\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</main>\n\t)\n}\n"],"names":["EVENTS","CodeReceivedEventSchema","z","type","USER_CODE_RECEIVED","code","url","AuthResolvedEventSchema","AUTH_RESOLVED","AuthRejectedEventSchema","AUTH_REJECTED","error","optional","default","EventSchema","handle","getSitemapEntries","login","_UNSAFE_withComponentProps","product","displayName","useWorkshopConfig","loginFetcher","useFetcher","clickedVerificationLink","setClickedVerificationLink","useState","authError","setAuthError","userCodeInfo","setUserCodeInfo","navigate","useNavigate","revalidator","useRevalidator","lastMessage","useEventSource","useEffect","parsed","JSON","parse","result","safeParse","success","console","flatten","data","revalidate","then","className","children","jsxs","jsx","Logo","ButtonLink","varient","to","target","rel","onClick","Loading","href","Form","method","Button","state","status","Fragment","Link"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"login-Ej63Q5LC.js","sources":["../../../app/utils/auth-events.ts","../../../app/routes/login-sse.tsx","../../../app/routes/_app+/login.tsx"],"sourcesContent":["export const EVENTS = {\n\tUSER_CODE_RECEIVED: 'USER_CODE_RECEIVED',\n\tAUTH_RESOLVED: 'AUTH_RESOLVED',\n\tAUTH_REJECTED: 'AUTH_REJECTED',\n} as const\nexport type EventTypes = keyof typeof EVENTS\n","import { type LoaderFunctionArgs } from 'react-router'\nimport { eventStream } from 'remix-utils/sse/server'\nimport { z } from 'zod'\nimport { EVENTS } from '#app/utils/auth-events.ts'\nimport { authEmitter } from '#app/utils/auth.server.ts'\nimport { ensureUndeployed } from '#app/utils/misc.tsx'\n\nconst CodeReceivedEventSchema = z.object({\n\ttype: z.literal(EVENTS.USER_CODE_RECEIVED),\n\tcode: z.string(),\n\turl: z.string(),\n})\nconst AuthResolvedEventSchema = z.object({\n\ttype: z.literal(EVENTS.AUTH_RESOLVED),\n})\nconst AuthRejectedEventSchema = z.object({\n\ttype: z.literal(EVENTS.AUTH_REJECTED),\n\terror: z.string().optional().default('Unknown error'),\n})\nexport const EventSchema = z.union([\n\tCodeReceivedEventSchema,\n\tAuthResolvedEventSchema,\n\tAuthRejectedEventSchema,\n])\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tensureUndeployed()\n\treturn eventStream(request.signal, function setup(send) {\n\t\tfunction handleCodeReceived(data: any) {\n\t\t\tsend({\n\t\t\t\tdata: JSON.stringify(\n\t\t\t\t\tCodeReceivedEventSchema.parse({\n\t\t\t\t\t\ttype: EVENTS.USER_CODE_RECEIVED,\n\t\t\t\t\t\t...data,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t})\n\t\t}\n\t\tfunction handleAuthResolved() {\n\t\t\tsend({ data: JSON.stringify({ type: EVENTS.AUTH_RESOLVED }) })\n\t\t}\n\t\tfunction handleAuthRejected(data: any) {\n\t\t\tconst result = AuthRejectedEventSchema.safeParse({\n\t\t\t\ttype: EVENTS.AUTH_REJECTED,\n\t\t\t\t...data,\n\t\t\t})\n\t\t\tif (result.success) {\n\t\t\t\tsend({ data: JSON.stringify(result.data) })\n\t\t\t} else {\n\t\t\t\tconsole.error('Error parsing auth rejected event', result.error, data)\n\t\t\t}\n\t\t}\n\t\tauthEmitter.on(EVENTS.USER_CODE_RECEIVED, handleCodeReceived)\n\t\tauthEmitter.on(EVENTS.AUTH_RESOLVED, handleAuthResolved)\n\t\tauthEmitter.on(EVENTS.AUTH_REJECTED, handleAuthRejected)\n\t\treturn () => {\n\t\t\tauthEmitter.off(EVENTS.USER_CODE_RECEIVED, handleCodeReceived)\n\t\t\tauthEmitter.off(EVENTS.AUTH_RESOLVED, handleAuthResolved)\n\t\t\tauthEmitter.off(EVENTS.AUTH_REJECTED, handleAuthRejected)\n\t\t}\n\t})\n}\n","import { getAuthInfo } from '@epic-web/workshop-utils/db.server'\nimport { type SEOHandle } from '@nasa-gcn/remix-seo'\nimport { useEffect, useState } from 'react'\nimport {\n\tredirect,\n\tLink,\n\tuseFetcher,\n\tuseNavigate,\n\tuseRevalidator,\n} from 'react-router'\nimport { useEventSource } from 'remix-utils/sse/react'\nimport { Button, ButtonLink } from '#app/components/button.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { Logo } from '#app/components/product.tsx'\nimport { useWorkshopConfig } from '#app/components/workshop-config.tsx'\nimport { EVENTS } from '#app/utils/auth-events.ts'\nimport { registerDevice } from '#app/utils/auth.server.ts'\nimport { ensureUndeployed } from '#app/utils/misc.tsx'\nimport { EventSchema } from '../login-sse.tsx'\n\nexport const handle: SEOHandle = {\n\tgetSitemapEntries: () => null,\n}\n\nexport async function loader() {\n\tensureUndeployed()\n\tconst isAuthenticated = Boolean(await getAuthInfo())\n\tif (isAuthenticated) throw redirect('/account')\n\treturn {}\n}\n\nexport async function action() {\n\tensureUndeployed()\n\tvoid registerDevice()\n\treturn { status: 'pending' } as const\n}\n\nexport default function Login() {\n\tconst {\n\t\tproduct: { displayName },\n\t} = useWorkshopConfig()\n\tconst loginFetcher = useFetcher<typeof action>()\n\tconst [clickedVerificationLink, setClickedVerificationLink] = useState(false)\n\tconst [authError, setAuthError] = useState<null | string>(null)\n\tconst [userCodeInfo, setUserCodeInfo] = useState<null | {\n\t\tcode: string\n\t\turl: string\n\t}>(null)\n\tconst navigate = useNavigate()\n\tconst revalidator = useRevalidator()\n\tconst lastMessage = useEventSource(`/login-sse`)\n\tuseEffect(() => {\n\t\tif (!lastMessage) return\n\n\t\tconst parsed = JSON.parse(lastMessage)\n\t\tconst result = EventSchema.safeParse(parsed)\n\t\tif (!result.success) {\n\t\t\tconsole.error(result.error.flatten())\n\t\t\treturn\n\t\t}\n\t\tswitch (result.data.type) {\n\t\t\tcase EVENTS.USER_CODE_RECEIVED: {\n\t\t\t\tsetUserCodeInfo(result.data)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase EVENTS.AUTH_RESOLVED: {\n\t\t\t\tvoid revalidator.revalidate().then(() => navigate('/'))\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase EVENTS.AUTH_REJECTED: {\n\t\t\t\tsetAuthError(result.data.error)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}, [lastMessage, navigate, revalidator])\n\n\treturn (\n\t\t<main className=\"flex h-full w-full grow flex-col items-center justify-center p-10\">\n\t\t\t<div className=\"flex flex-col items-center\">\n\t\t\t\t<Logo className=\"h-16 w-16\" />\n\t\t\t\t<h1 className=\"pt-5 text-2xl font-semibold md:text-3xl\">\n\t\t\t\t\tLogin to {displayName}\n\t\t\t\t</h1>\n\t\t\t\t<div className=\"flex w-full flex-col items-center pt-5\">\n\t\t\t\t\t{userCodeInfo ? (\n\t\t\t\t\t\t<div className=\"flex w-full max-w-md flex-col items-center gap-3\">\n\t\t\t\t\t\t\t<div className=\"my-2 flex w-full flex-col items-center gap-2\">\n\t\t\t\t\t\t\t\t<p className=\"text-lg\">Your verification code is: </p>\n\t\t\t\t\t\t\t\t<div className=\"bg-muted mb-3 w-full px-5 py-3 text-center text-lg font-bold\">\n\t\t\t\t\t\t\t\t\t<code>{userCodeInfo.code}</code>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<p className=\"text-base\">\n\t\t\t\t\t\t\t\t\tYou'll use this to verify your device on {displayName}. Click\n\t\t\t\t\t\t\t\t\tverify code below to open the verification page.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<ButtonLink\n\t\t\t\t\t\t\t\tvarient=\"primary\"\n\t\t\t\t\t\t\t\tto={userCodeInfo.url}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\tonClick={() => setClickedVerificationLink(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tVerify Auth Code\n\t\t\t\t\t\t\t</ButtonLink>\n\t\t\t\t\t\t\t{clickedVerificationLink ? (\n\t\t\t\t\t\t\t\t<div className=\"justify-center pt-5 text-center opacity-60\">\n\t\t\t\t\t\t\t\t\t<Loading className=\"justify-center\">\n\t\t\t\t\t\t\t\t\t\tWaiting for confirmation\n\t\t\t\t\t\t\t\t\t</Loading>\n\t\t\t\t\t\t\t\t\t<p className=\"pt-2\">\n\t\t\t\t\t\t\t\t\t\tPlease open{' '}\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\thref={userCodeInfo.url}\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tyour auth page\n\t\t\t\t\t\t\t\t\t\t</a>{' '}\n\t\t\t\t\t\t\t\t\t\tin a new tab to continue.\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"flex flex-col items-center gap-8\">\n\t\t\t\t\t\t\t<div className=\"text-muted-foreground flex max-w-lg flex-col gap-3 pt-3 text-base\">\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tIf you have access to this workshop on {displayName}, you'll\n\t\t\t\t\t\t\t\t\tbe able to watch videos, track progress, run tests, view the\n\t\t\t\t\t\t\t\t\tdiffs, and more!\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tFirst you need to authenticate your device by requesting an\n\t\t\t\t\t\t\t\t\taccess code and verifying on {displayName}.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<loginFetcher.Form method=\"POST\">\n\t\t\t\t\t\t\t\t<Button varient=\"primary\" type=\"submit\">\n\t\t\t\t\t\t\t\t\t{loginFetcher.state === 'idle' &&\n\t\t\t\t\t\t\t\t\tloginFetcher.data?.status !== 'pending'\n\t\t\t\t\t\t\t\t\t\t? `Retrieve Auth Code`\n\t\t\t\t\t\t\t\t\t\t: `Retrieving Auth Code...`}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</loginFetcher.Form>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{authError ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div className=\"text-foreground-destructive mt-4\">\n\t\t\t\t\t\t\t\tThere was an error: <pre>{authError}</pre>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"text-foreground-destructive mt-4\">\n\t\t\t\t\t\t\t\tPlease try again or{' '}\n\t\t\t\t\t\t\t\t<Link to=\"/support\" className=\"underline\">\n\t\t\t\t\t\t\t\t\tcontact support\n\t\t\t\t\t\t\t\t</Link>{' '}\n\t\t\t\t\t\t\t\tif the problem persists.\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</main>\n\t)\n}\n"],"names":["EVENTS","CodeReceivedEventSchema","z","type","USER_CODE_RECEIVED","code","url","AuthResolvedEventSchema","AUTH_RESOLVED","AuthRejectedEventSchema","AUTH_REJECTED","error","optional","default","EventSchema","handle","getSitemapEntries","login","_UNSAFE_withComponentProps","product","displayName","useWorkshopConfig","loginFetcher","useFetcher","clickedVerificationLink","setClickedVerificationLink","useState","authError","setAuthError","userCodeInfo","setUserCodeInfo","navigate","useNavigate","revalidator","useRevalidator","lastMessage","useEventSource","useEffect","parsed","JSON","parse","result","safeParse","success","console","flatten","data","revalidate","then","className","children","jsxs","jsx","Logo","ButtonLink","varient","to","target","rel","onClick","Loading","href","Form","method","Button","state","status","Fragment","Link"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.__reactRouterManifest={"entry":{"module":"/assets/entry.client-Bc9ceZPe.js","imports":["/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js","/assets/index-vDCSPjrM.js","/assets/chunk-FNSCYPCZ-CXmv6S8d.js","/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/preload-helper-BXl3LOEh.js"],"css":[]},"routes":{"root":{"id":"root","path":"","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/root-hU3hrO-C.js","imports":["/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js","/assets/index-vDCSPjrM.js","/assets/chunk-FNSCYPCZ-CXmv6S8d.js","/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/preload-helper-BXl3LOEh.js","/assets/misc-CRhJChs6.js","/assets/client-only-Dwnpimkx.js","/assets/error-boundary-B_ltT-yo.js","/assets/dialog-C_JrUgnb.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/index-DzdDahau.js","/assets/tooltip-f3C9W-4C.js","/assets/schemas-Uj5SZtvt.js","/assets/index-DVd41HZN.js","/assets/presence-CEaLlpZz.js","/assets/seo-t5J-DRxw.js","/assets/pe-UQCAhDPv.js","/assets/index-C4pHU_n3.js","/assets/root-loader-BObzljW3.js","/assets/online-D6QnZT5V.js","/assets/coerce-CkHW0SMv.js"],"css":[]},"routes/$":{"id":"routes/$","parentId":"root","path":"*","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/_--opxgdQ5.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/error-boundary-B_ltT-yo.js","/assets/misc-CRhJChs6.js","/assets/index-CqIc3cxq.js","/assets/preload-helper-BXl3LOEh.js"],"css":[]},"routes/_app+/_layout":{"id":"routes/_app+/_layout","parentId":"root","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/_layout-C6NSVF79.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/misc-CRhJChs6.js","/assets/index-CqIc3cxq.js","/assets/pe-UQCAhDPv.js","/assets/onboarding-indicator-Bd1aYrgA.js","/assets/product-CNG57fZy.js","/assets/revalidation-ws-Dcs0B3Rw.js","/assets/dialog-C_JrUgnb.js","/assets/tooltip-f3C9W-4C.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/online-D6QnZT5V.js","/assets/presence-CEaLlpZz.js","/assets/root-loader-BObzljW3.js","/assets/progress-Hpjbz7E6.js","/assets/index-DVd41HZN.js","/assets/schemas-Uj5SZtvt.js","/assets/index-C4pHU_n3.js","/assets/index-vDCSPjrM.js","/assets/coerce-CkHW0SMv.js"],"css":[]},"routes/_app+/account":{"id":"routes/_app+/account","parentId":"routes/_app+/_layout","path":"account","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/account-87tfAIZW.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/button-CVorsvM4.js","/assets/misc-CRhJChs6.js","/assets/onboarding-indicator-Bd1aYrgA.js","/assets/tooltip-f3C9W-4C.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/index-CqIc3cxq.js","/assets/root-loader-BObzljW3.js","/assets/index-vDCSPjrM.js"],"css":[]},"routes/_app+/app.$appName+/$":{"id":"routes/_app+/app.$appName+/$","parentId":"routes/_app+/_layout","path":"app/:appName/*","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/_-l0sNRNKZ.js","imports":[],"css":[]},"routes/_app+/app.$appName+/api.$":{"id":"routes/_app+/app.$appName+/api.$","parentId":"routes/_app+/_layout","path":"app/:appName/api/*","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/api._-l0sNRNKZ.js","imports":[],"css":[]},"routes/_app+/app.$appName+/epic_ws[.js]":{"id":"routes/_app+/app.$appName+/epic_ws[.js]","parentId":"routes/_app+/_layout","path":"app/:appName/epic_ws.js","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/epic_ws_.js_-l0sNRNKZ.js","imports":[],"css":[]},"routes/_app+/app.$appName+/index":{"id":"routes/_app+/app.$appName+/index","parentId":"routes/_app+/_layout","path":"app/:appName","index":true,"hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/index-l0sNRNKZ.js","imports":[],"css":[]},"routes/_app+/app.$appName+/test.$testName":{"id":"routes/_app+/app.$appName+/test.$testName","parentId":"routes/_app+/_layout","path":"app/:appName/test/:testName","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/test._testName-l0sNRNKZ.js","imports":[],"css":[]},"routes/_app+/app.$appName+/test.epic_ws[.js]":{"id":"routes/_app+/app.$appName+/test.epic_ws[.js]","parentId":"routes/_app+/_layout","path":"app/:appName/test/epic_ws.js","hasAction":false,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/test.epic_ws_.js_-l0sNRNKZ.js","imports":[],"css":[]},"routes/_app+/app.epic_ws[.js]":{"id":"routes/_app+/app.epic_ws[.js]","parentId":"routes/_app+/_layout","path":"app/epic_ws.js","hasAction":false,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/app.epic_ws_.js_-l0sNRNKZ.js","imports":[],"css":[]},"routes/_app+/discord":{"id":"routes/_app+/discord","parentId":"routes/_app+/_layout","path":"discord","hasAction":false,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/discord-BRmbT9rX.js","imports":["/assets/discord-C9e3SYlE.js","/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/index-CqIc3cxq.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/misc-CRhJChs6.js","/assets/user-CFfhNfdz.js","/assets/root-loader-BObzljW3.js","/assets/workshop-config-BP-vDuRo.js"],"css":[]},"routes/_app+/exercise+/_layout":{"id":"routes/_app+/exercise+/_layout","parentId":"routes/_app+/_layout","path":"exercise","hasAction":false,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/_layout-CFKs8QZJ.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js"],"css":[]},"routes/_app+/exercise+/$exerciseNumber":{"id":"routes/_app+/exercise+/$exerciseNumber","parentId":"routes/_app+/exercise+/_layout","path":":exerciseNumber","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/_exerciseNumber-D3f2-zl6.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-BrUCi_AK.js","/assets/epic-video-BX2A437e.js","/assets/error-boundary-B_ltT-yo.js","/assets/revalidation-ws-Dcs0B3Rw.js","/assets/launch-editor-D_PbWy0b.js","/assets/progress-Hpjbz7E6.js","/assets/mdx-BlaeOyqK.js","/assets/root-loader-BObzljW3.js","/assets/seo-t5J-DRxw.js","/assets/error-boundary-DdQE-4kH.js","/assets/index-CqIc3cxq.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DzdDahau.js","/assets/index-vDCSPjrM.js","/assets/index-DVd41HZN.js","/assets/misc-CRhJChs6.js","/assets/tooltip-f3C9W-4C.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/online-D6QnZT5V.js","/assets/loading-BiVU3Oa8.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/preload-helper-BXl3LOEh.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/chunk-FNSCYPCZ-CXmv6S8d.js","/assets/coerce-CkHW0SMv.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout":{"id":"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout","parentId":"routes/_app+/exercise+/_layout","path":":exerciseNumber/:stepNumber/:type","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/_layout-oPmquiOE.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-BrUCi_AK.js","/assets/index-CqIc3cxq.js","/assets/error-boundary-B_ltT-yo.js","/assets/nav-chevrons-VqiZYYFr.js","/assets/revalidation-ws-Dcs0B3Rw.js","/assets/launch-editor-D_PbWy0b.js","/assets/progress-Hpjbz7E6.js","/assets/set-playground-DaRl3X5k.js","/assets/misc-CRhJChs6.js","/assets/root-loader-BObzljW3.js","/assets/seo-t5J-DRxw.js","/assets/split-layout-DnRER1bP.js","/assets/error-boundary-DdQE-4kH.js","/assets/epic-video-BX2A437e.js","/assets/tooltip-f3C9W-4C.js","/assets/mdx-BlaeOyqK.js","/assets/index-C4pHU_n3.js","/assets/onboarding-indicator-Bd1aYrgA.js","/assets/preload-helper-BXl3LOEh.js","/assets/schemas-Uj5SZtvt.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/pe-UQCAhDPv.js","/assets/index-D9Wd20Hl.js","/assets/index-vDCSPjrM.js","/assets/button-CVorsvM4.js","/assets/dialog-C_JrUgnb.js","/assets/chunk-FNSCYPCZ-CXmv6S8d.js","/assets/coerce-CkHW0SMv.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DzdDahau.js","/assets/index-DVd41HZN.js","/assets/online-D6QnZT5V.js","/assets/loading-BiVU3Oa8.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app":{"id":"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app","parentId":"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout","path":"app","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/app-BcJkSksP.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js","/assets/preview-D11Pscbe.js","/assets/misc-CRhJChs6.js","/assets/button-CVorsvM4.js","/assets/loading-BiVU3Oa8.js","/assets/index-DVd41HZN.js","/assets/tooltip-f3C9W-4C.js","/assets/index-vDCSPjrM.js","/assets/root-loader-BObzljW3.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/progress-bar-Cxy0ZpqZ.js"],"css":[]},"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index":{"id":"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index","parentId":"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout","index":true,"hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/index-InnNe6aG.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/playground-DIm_r4fy.js","/assets/diff-Ba99U4EI.js","/assets/error-boundary-B_ltT-yo.js","/assets/workshop-config-BP-vDuRo.js","/assets/misc-CRhJChs6.js","/assets/preview-D11Pscbe.js","/assets/tests-CITG_DX3.js","/assets/index-CqIc3cxq.js","/assets/loading-BiVU3Oa8.js","/assets/index-DVd41HZN.js","/assets/tooltip-f3C9W-4C.js","/assets/index-vDCSPjrM.js","/assets/root-loader-BObzljW3.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/discord-C9e3SYlE.js","/assets/user-CFfhNfdz.js","/assets/online-D6QnZT5V.js","/assets/index-D9Wd20Hl.js","/assets/index-C4pHU_n3.js","/assets/index-DzdDahau.js","/assets/set-playground-DaRl3X5k.js","/assets/button-CVorsvM4.js","/assets/onboarding-indicator-Bd1aYrgA.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/dialog-C_JrUgnb.js","/assets/playground-window-BnU6LeUy.js","/assets/accordion-DGNDc7Bw.js","/assets/mdx-BlaeOyqK.js","/assets/epic-video-BX2A437e.js","/assets/use-event-source-BuD4_2SF.js","/assets/preload-helper-BXl3LOEh.js","/assets/launch-editor-D_PbWy0b.js","/assets/revalidation-ws-Dcs0B3Rw.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test":{"id":"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test","parentId":"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout","path":"test","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/test-CpoHBC_8.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/tests-CITG_DX3.js","/assets/index-CqIc3cxq.js","/assets/accordion-DGNDc7Bw.js","/assets/tooltip-f3C9W-4C.js","/assets/index-vDCSPjrM.js","/assets/misc-CRhJChs6.js","/assets/index-D9Wd20Hl.js","/assets/index-C4pHU_n3.js","/assets/epic-video-BX2A437e.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DzdDahau.js","/assets/index-DVd41HZN.js","/assets/root-loader-BObzljW3.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/online-D6QnZT5V.js","/assets/loading-BiVU3Oa8.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/playground-window-BnU6LeUy.js","/assets/set-playground-DaRl3X5k.js","/assets/button-CVorsvM4.js","/assets/onboarding-indicator-Bd1aYrgA.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/dialog-C_JrUgnb.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index":{"id":"routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index","parentId":"routes/_app+/exercise+/_layout","path":":exerciseNumber/:stepNumber","index":true,"hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/_exerciseNumber_._stepNumber.index-swnTvl8f.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/error-boundary-B_ltT-yo.js","/assets/error-boundary-DdQE-4kH.js","/assets/index-CqIc3cxq.js","/assets/preload-helper-BXl3LOEh.js","/assets/misc-CRhJChs6.js","/assets/chunk-FNSCYPCZ-CXmv6S8d.js","/assets/schemas-Uj5SZtvt.js","/assets/coerce-CkHW0SMv.js"],"css":[]},"routes/_app+/exercise+/$exerciseNumber_.finished":{"id":"routes/_app+/exercise+/$exerciseNumber_.finished","parentId":"routes/_app+/exercise+/_layout","path":":exerciseNumber/finished","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/_exerciseNumber_.finished-DBaOwcf2.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-BrUCi_AK.js","/assets/index-CqIc3cxq.js","/assets/epic-video-BX2A437e.js","/assets/misc-CRhJChs6.js","/assets/loading-BiVU3Oa8.js","/assets/nav-chevrons-VqiZYYFr.js","/assets/revalidation-ws-Dcs0B3Rw.js","/assets/launch-editor-D_PbWy0b.js","/assets/progress-Hpjbz7E6.js","/assets/index-DVd41HZN.js","/assets/mdx-BlaeOyqK.js","/assets/online-D6QnZT5V.js","/assets/root-loader-BObzljW3.js","/assets/seo-t5J-DRxw.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DzdDahau.js","/assets/index-vDCSPjrM.js","/assets/schemas-Uj5SZtvt.js","/assets/tooltip-f3C9W-4C.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/pe-UQCAhDPv.js","/assets/preload-helper-BXl3LOEh.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/extra+/_layout":{"id":"routes/_app+/extra+/_layout","parentId":"routes/_app+/_layout","path":"extra","hasAction":false,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/_layout-X8qM3FXy.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js"],"css":[]},"routes/_app+/extra+/$extra":{"id":"routes/_app+/extra+/$extra","parentId":"routes/_app+/extra+/_layout","path":":extra","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/_extra-B4vZXPjV.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-BrUCi_AK.js","/assets/playground-DIm_r4fy.js","/assets/index-CqIc3cxq.js","/assets/diff-Ba99U4EI.js","/assets/epic-video-BX2A437e.js","/assets/error-boundary-B_ltT-yo.js","/assets/nav-chevrons-VqiZYYFr.js","/assets/revalidation-ws-Dcs0B3Rw.js","/assets/workshop-config-BP-vDuRo.js","/assets/preview-D11Pscbe.js","/assets/launch-editor-D_PbWy0b.js","/assets/set-playground-DaRl3X5k.js","/assets/mdx-BlaeOyqK.js","/assets/root-loader-BObzljW3.js","/assets/seo-t5J-DRxw.js","/assets/split-layout-DnRER1bP.js","/assets/misc-CRhJChs6.js","/assets/loading-BiVU3Oa8.js","/assets/index-DVd41HZN.js","/assets/tooltip-f3C9W-4C.js","/assets/index-vDCSPjrM.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/discord-C9e3SYlE.js","/assets/user-CFfhNfdz.js","/assets/online-D6QnZT5V.js","/assets/index-D9Wd20Hl.js","/assets/index-C4pHU_n3.js","/assets/index-DzdDahau.js","/assets/playground-window-BnU6LeUy.js","/assets/accordion-DGNDc7Bw.js","/assets/use-event-source-BuD4_2SF.js","/assets/preload-helper-BXl3LOEh.js","/assets/button-CVorsvM4.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/onboarding-indicator-Bd1aYrgA.js","/assets/dialog-C_JrUgnb.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/extra+/index":{"id":"routes/_app+/extra+/index","parentId":"routes/_app+/extra+/_layout","index":true,"hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/index-T3LlCTSm.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-BrUCi_AK.js","/assets/epic-video-BX2A437e.js","/assets/error-boundary-B_ltT-yo.js","/assets/revalidation-ws-Dcs0B3Rw.js","/assets/launch-editor-D_PbWy0b.js","/assets/mdx-BlaeOyqK.js","/assets/misc-CRhJChs6.js","/assets/root-loader-BObzljW3.js","/assets/seo-t5J-DRxw.js","/assets/index-CqIc3cxq.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DzdDahau.js","/assets/index-vDCSPjrM.js","/assets/index-DVd41HZN.js","/assets/tooltip-f3C9W-4C.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/online-D6QnZT5V.js","/assets/loading-BiVU3Oa8.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/preload-helper-BXl3LOEh.js","/assets/progress-bar-Cxy0ZpqZ.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/finished":{"id":"routes/_app+/finished","parentId":"routes/_app+/_layout","path":"finished","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/finished-BLRyuOTb.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-BrUCi_AK.js","/assets/index-CqIc3cxq.js","/assets/epic-video-BX2A437e.js","/assets/misc-CRhJChs6.js","/assets/loading-BiVU3Oa8.js","/assets/nav-chevrons-VqiZYYFr.js","/assets/revalidation-ws-Dcs0B3Rw.js","/assets/mdx-BlaeOyqK.js","/assets/online-D6QnZT5V.js","/assets/root-loader-BObzljW3.js","/assets/seo-t5J-DRxw.js","/assets/launch-editor-D_PbWy0b.js","/assets/progress-Hpjbz7E6.js","/assets/index-DVd41HZN.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DzdDahau.js","/assets/index-vDCSPjrM.js","/assets/schemas-Uj5SZtvt.js","/assets/tooltip-f3C9W-4C.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/preload-helper-BXl3LOEh.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/pe-UQCAhDPv.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/guide":{"id":"routes/_app+/guide","parentId":"routes/_app+/_layout","path":"guide","hasAction":false,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/guide-B0V9gK-M.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js"],"css":[]},"routes/_app+/index":{"id":"routes/_app+/index","parentId":"routes/_app+/_layout","index":true,"hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":true,"module":"/assets/index-Dt_ngnka.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-BrUCi_AK.js","/assets/epic-video-BX2A437e.js","/assets/error-boundary-B_ltT-yo.js","/assets/launch-editor-D_PbWy0b.js","/assets/mdx-BlaeOyqK.js","/assets/misc-CRhJChs6.js","/assets/progress-Hpjbz7E6.js","/assets/index-CqIc3cxq.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DzdDahau.js","/assets/index-vDCSPjrM.js","/assets/index-DVd41HZN.js","/assets/tooltip-f3C9W-4C.js","/assets/root-loader-BObzljW3.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/online-D6QnZT5V.js","/assets/loading-BiVU3Oa8.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/preload-helper-BXl3LOEh.js","/assets/progress-bar-Cxy0ZpqZ.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/_app+/l":{"id":"routes/_app+/l","parentId":"routes/_app+/_layout","path":"l","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/l-BnufyNX8.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/index-CqIc3cxq.js"],"css":[]},"routes/_app+/login":{"id":"routes/_app+/login","parentId":"routes/_app+/_layout","path":"login","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/login-Ej63Q5LC.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js","/assets/use-event-source-BuD4_2SF.js","/assets/button-CVorsvM4.js","/assets/loading-BiVU3Oa8.js","/assets/product-CNG57fZy.js","/assets/workshop-config-BP-vDuRo.js","/assets/schemas-Uj5SZtvt.js","/assets/misc-CRhJChs6.js","/assets/index-DVd41HZN.js","/assets/tooltip-f3C9W-4C.js","/assets/index-vDCSPjrM.js","/assets/root-loader-BObzljW3.js","/assets/pe-UQCAhDPv.js"],"css":[]},"routes/_app+/preferences":{"id":"routes/_app+/preferences","parentId":"routes/_app+/_layout","path":"preferences","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/preferences-CgqvqSwL.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/button-CVorsvM4.js","/assets/misc-CRhJChs6.js","/assets/tooltip-f3C9W-4C.js","/assets/root-loader-BObzljW3.js","/assets/index-CqIc3cxq.js","/assets/index-vDCSPjrM.js"],"css":[]},"routes/_app+/support":{"id":"routes/_app+/support","parentId":"routes/_app+/_layout","path":"support","hasAction":false,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/support--bbGxhiZ.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js"],"css":[]},"routes/_app+/workspace-structure":{"id":"routes/_app+/workspace-structure","parentId":"routes/_app+/_layout","path":"workspace-structure","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/workspace-structure-0lIVnQRW.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/button-CVorsvM4.js","/assets/index-CqIc3cxq.js","/assets/misc-CRhJChs6.js"],"css":[]},"routes/admin+/_layout":{"id":"routes/admin+/_layout","parentId":"root","path":"admin","hasAction":false,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/_layout-DO9ALrzd.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/root-loader-BObzljW3.js","/assets/index-CqIc3cxq.js"],"css":[]},"routes/admin+/apps":{"id":"routes/admin+/apps","parentId":"routes/admin+/_layout","path":"apps","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/apps-l0sNRNKZ.js","imports":[],"css":[]},"routes/admin+/cache":{"id":"routes/admin+/cache","parentId":"routes/admin+/_layout","path":"cache","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/cache-DHTBTFeR.js","imports":["/assets/chunk-FNSCYPCZ-CXmv6S8d.js","/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js","/assets/client-only-Dwnpimkx.js","/assets/button-CVorsvM4.js","/assets/misc-CRhJChs6.js","/assets/launch-editor-D_PbWy0b.js","/assets/pe-UQCAhDPv.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/root-loader-BObzljW3.js"],"css":[]},"routes/admin+/cache.$":{"id":"routes/admin+/cache.$","parentId":"routes/admin+/cache","path":"*","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/cache._-l0sNRNKZ.js","imports":[],"css":[]},"routes/admin+/db":{"id":"routes/admin+/db","parentId":"routes/admin+/_layout","path":"db","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/db-CsJwieeN.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/misc-CRhJChs6.js","/assets/tooltip-f3C9W-4C.js","/assets/launch-editor-D_PbWy0b.js","/assets/index-CqIc3cxq.js","/assets/index-vDCSPjrM.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/pe-UQCAhDPv.js","/assets/root-loader-BObzljW3.js"],"css":[]},"routes/admin+/index":{"id":"routes/admin+/index","parentId":"routes/admin+/_layout","index":true,"hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/index-C4dXZZAD.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/misc-CRhJChs6.js","/assets/tooltip-f3C9W-4C.js","/assets/progress-Hpjbz7E6.js","/assets/root-loader-BObzljW3.js","/assets/index-CqIc3cxq.js","/assets/index-vDCSPjrM.js","/assets/pe-UQCAhDPv.js"],"css":[]},"routes/admin+/notifications":{"id":"routes/admin+/notifications","parentId":"routes/admin+/_layout","path":"notifications","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/notifications-l0sNRNKZ.js","imports":[],"css":[]},"routes/admin+/offline-videos":{"id":"routes/admin+/offline-videos","parentId":"routes/admin+/_layout","path":"offline-videos","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/offline-videos-BYFoMLsP.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/misc-CRhJChs6.js","/assets/index-CqIc3cxq.js"],"css":[]},"routes/admin+/version":{"id":"routes/admin+/version","parentId":"routes/admin+/_layout","path":"version","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/version-Tq4ozvBN.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/workshop-config-BP-vDuRo.js","/assets/index-CqIc3cxq.js","/assets/root-loader-BObzljW3.js"],"css":[]},"routes/admin+/version[.json]":{"id":"routes/admin+/version[.json]","parentId":"routes/admin+/_layout","path":"version.json","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/version_.json_-l0sNRNKZ.js","imports":[],"css":[]},"routes/apps":{"id":"routes/apps","parentId":"root","path":"apps","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/apps-DP2rzg_V.js","imports":[],"css":[]},"routes/diff":{"id":"routes/diff","parentId":"root","path":"diff","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/diff-DmmI9IU6.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/misc-CRhJChs6.js","/assets/diff-Ba99U4EI.js","/assets/nav-chevrons-VqiZYYFr.js","/assets/index-CqIc3cxq.js","/assets/accordion-DGNDc7Bw.js","/assets/tooltip-f3C9W-4C.js","/assets/index-vDCSPjrM.js","/assets/index-D9Wd20Hl.js","/assets/index-C4pHU_n3.js","/assets/mdx-BlaeOyqK.js","/assets/index-DzdDahau.js","/assets/epic-video-BX2A437e.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DVd41HZN.js","/assets/root-loader-BObzljW3.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/online-D6QnZT5V.js","/assets/loading-BiVU3Oa8.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js","/assets/preload-helper-BXl3LOEh.js","/assets/launch-editor-D_PbWy0b.js","/assets/progress-bar-Cxy0ZpqZ.js","/assets/revalidation-ws-Dcs0B3Rw.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/diff.$shortcut":{"id":"routes/diff.$shortcut","parentId":"routes/diff","path":":shortcut","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/diff._shortcut-l0sNRNKZ.js","imports":[],"css":[]},"routes/exercises":{"id":"routes/exercises","parentId":"root","path":"exercises","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/exercises-l0sNRNKZ.js","imports":[],"css":[]},"routes/launch-editor":{"id":"routes/launch-editor","parentId":"root","path":"launch-editor","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/launch-editor-l0sNRNKZ.js","imports":[],"css":[]},"routes/login-sse":{"id":"routes/login-sse","parentId":"root","path":"login-sse","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/login-sse-l0sNRNKZ.js","imports":[],"css":[]},"routes/mark-onboarding-complete":{"id":"routes/mark-onboarding-complete","parentId":"root","path":"mark-onboarding-complete","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/mark-onboarding-complete-l0sNRNKZ.js","imports":[],"css":[]},"routes/mcp-ui+/epic-video":{"id":"routes/mcp-ui+/epic-video","parentId":"root","path":"mcp-ui/epic-video","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/epic-video-5HutgMR0.js","imports":["/assets/chunk-EPOLDU6W-C4NOdiis.js","/assets/jsx-runtime-C5WNSv3b.js","/assets/index-CqIc3cxq.js","/assets/epic-video-BX2A437e.js","/assets/use-event-source-BuD4_2SF.js","/assets/index-DzdDahau.js","/assets/index-vDCSPjrM.js","/assets/index-DVd41HZN.js","/assets/misc-CRhJChs6.js","/assets/tooltip-f3C9W-4C.js","/assets/root-loader-BObzljW3.js","/assets/pe-UQCAhDPv.js","/assets/schemas-Uj5SZtvt.js","/assets/online-D6QnZT5V.js","/assets/loading-BiVU3Oa8.js","/assets/user-CFfhNfdz.js","/assets/workshop-config-BP-vDuRo.js"],"css":["/assets/epic-video-irT-uesJ.css"]},"routes/og":{"id":"routes/og","parentId":"root","path":"og","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/og-l0sNRNKZ.js","imports":[],"css":[]},"routes/persist-playground":{"id":"routes/persist-playground","parentId":"root","path":"persist-playground","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/persist-playground-l0sNRNKZ.js","imports":[],"css":[]},"routes/processes":{"id":"routes/processes","parentId":"root","path":"processes","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/processes-l0sNRNKZ.js","imports":[],"css":[]},"routes/progress":{"id":"routes/progress","parentId":"root","path":"progress","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/progress-l0sNRNKZ.js","imports":[],"css":[]},"routes/resources+/healthcheck":{"id":"routes/resources+/healthcheck","parentId":"root","path":"resources/healthcheck","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/healthcheck-l0sNRNKZ.js","imports":[],"css":[]},"routes/resources+/lookout":{"id":"routes/resources+/lookout","parentId":"root","path":"resources/lookout","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/lookout-l0sNRNKZ.js","imports":[],"css":[]},"routes/resources+/offline-video-progress.$playbackId":{"id":"routes/resources+/offline-video-progress.$playbackId","parentId":"root","path":"resources/offline-video-progress/:playbackId","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/offline-video-progress._playbackId-l0sNRNKZ.js","imports":[],"css":[]},"routes/resources+/offline-videos":{"id":"routes/resources+/offline-videos","parentId":"root","path":"resources/offline-videos","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/offline-videos-l0sNRNKZ.js","imports":[],"css":[]},"routes/resources+/offline-videos.$playbackId":{"id":"routes/resources+/offline-videos.$playbackId","parentId":"routes/resources+/offline-videos","path":":playbackId","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/offline-videos._playbackId-l0sNRNKZ.js","imports":[],"css":[]},"routes/robots[.]txt":{"id":"routes/robots[.]txt","parentId":"root","path":"robots.txt","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/robots_._txt-l0sNRNKZ.js","imports":[],"css":[]},"routes/saved-playgrounds":{"id":"routes/saved-playgrounds","parentId":"root","path":"saved-playgrounds","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/saved-playgrounds-l0sNRNKZ.js","imports":[],"css":[]},"routes/set-playground":{"id":"routes/set-playground","parentId":"root","path":"set-playground","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/set-playground-l0sNRNKZ.js","imports":[],"css":[]},"routes/sitemap[.]xml":{"id":"routes/sitemap[.]xml","parentId":"root","path":"sitemap.xml","hasAction":false,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/sitemap_._xml-l0sNRNKZ.js","imports":[],"css":[]},"routes/start":{"id":"routes/start","parentId":"root","path":"start","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/start-l0sNRNKZ.js","imports":[],"css":[]},"routes/test":{"id":"routes/test","parentId":"root","path":"test","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/test-l0sNRNKZ.js","imports":[],"css":[]},"routes/theme/index":{"id":"routes/theme/index","parentId":"root","path":"theme","hasAction":true,"hasLoader":true,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/index-DP2rzg_V.js","imports":[],"css":[]},"routes/video-player/index":{"id":"routes/video-player/index","parentId":"root","path":"video-player","hasAction":true,"hasLoader":false,"hasClientAction":false,"hasClientLoader":false,"hasClientMiddleware":false,"hasErrorBoundary":false,"module":"/assets/index-K6Dvbx-E.js","imports":[],"css":[]}},"url":"/assets/manifest-9482f5db.js","version":"9482f5db"};
|