@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.
Files changed (56) hide show
  1. package/build/client/assets/{_exerciseNumber-CcPKmB4n.js → _exerciseNumber-D3f2-zl6.js} +2 -2
  2. package/build/client/assets/{_exerciseNumber-CcPKmB4n.js.map → _exerciseNumber-D3f2-zl6.js.map} +1 -1
  3. package/build/client/assets/{_exerciseNumber_.finished-knzx8riV.js → _exerciseNumber_.finished-DBaOwcf2.js} +2 -2
  4. package/build/client/assets/{_exerciseNumber_.finished-knzx8riV.js.map → _exerciseNumber_.finished-DBaOwcf2.js.map} +1 -1
  5. package/build/client/assets/{_extra-DB6-IJuV.js → _extra-B4vZXPjV.js} +2 -2
  6. package/build/client/assets/{_extra-DB6-IJuV.js.map → _extra-B4vZXPjV.js.map} +1 -1
  7. package/build/client/assets/{_layout-Be0gsSoP.js → _layout-C6NSVF79.js} +2 -2
  8. package/build/client/assets/{_layout-Be0gsSoP.js.map → _layout-C6NSVF79.js.map} +1 -1
  9. package/build/client/assets/{_layout-D05w5xUz.js → _layout-oPmquiOE.js} +2 -2
  10. package/build/client/assets/{_layout-D05w5xUz.js.map → _layout-oPmquiOE.js.map} +1 -1
  11. package/build/client/assets/app-BcJkSksP.js +2 -0
  12. package/build/client/assets/{app-rrQthl25.js.map → app-BcJkSksP.js.map} +1 -1
  13. package/build/client/assets/{diff-De24Mp-s.js → diff-Ba99U4EI.js} +2 -2
  14. package/build/client/assets/{diff-De24Mp-s.js.map → diff-Ba99U4EI.js.map} +1 -1
  15. package/build/client/assets/{diff-Bd9VlQ-I.js → diff-DmmI9IU6.js} +2 -2
  16. package/build/client/assets/{diff-Bd9VlQ-I.js.map → diff-DmmI9IU6.js.map} +1 -1
  17. package/build/client/assets/{epic-video-DdpYdAlg.js → epic-video-5HutgMR0.js} +2 -2
  18. package/build/client/assets/{epic-video-DdpYdAlg.js.map → epic-video-5HutgMR0.js.map} +1 -1
  19. package/build/client/assets/{epic-video-Bndfj6GR.js → epic-video-BX2A437e.js} +2 -2
  20. package/build/client/assets/{epic-video-Bndfj6GR.js.map → epic-video-BX2A437e.js.map} +1 -1
  21. package/build/client/assets/{finished-HnwwiFtu.js → finished-BLRyuOTb.js} +2 -2
  22. package/build/client/assets/{finished-HnwwiFtu.js.map → finished-BLRyuOTb.js.map} +1 -1
  23. package/build/client/assets/index-DVd41HZN.js +68 -0
  24. package/build/client/assets/index-DVd41HZN.js.map +1 -0
  25. package/build/client/assets/{index-CvFJy3s8.js → index-Dt_ngnka.js} +2 -2
  26. package/build/client/assets/{index-CvFJy3s8.js.map → index-Dt_ngnka.js.map} +1 -1
  27. package/build/client/assets/{index-BL399UJV.js → index-InnNe6aG.js} +2 -2
  28. package/build/client/assets/{index-BL399UJV.js.map → index-InnNe6aG.js.map} +1 -1
  29. package/build/client/assets/{index-B1TztMYA.js → index-T3LlCTSm.js} +2 -2
  30. package/build/client/assets/{index-B1TztMYA.js.map → index-T3LlCTSm.js.map} +1 -1
  31. package/build/client/assets/{loading-IJRzD1mm.js → loading-BiVU3Oa8.js} +2 -2
  32. package/build/client/assets/{loading-IJRzD1mm.js.map → loading-BiVU3Oa8.js.map} +1 -1
  33. package/build/client/assets/{login-VlyrGJvd.js → login-Ej63Q5LC.js} +2 -2
  34. package/build/client/assets/{login-VlyrGJvd.js.map → login-Ej63Q5LC.js.map} +1 -1
  35. package/build/client/assets/manifest-9482f5db.js +1 -0
  36. package/build/client/assets/{mdx-CbaVHkqG.js → mdx-BlaeOyqK.js} +2 -2
  37. package/build/client/assets/{mdx-CbaVHkqG.js.map → mdx-BlaeOyqK.js.map} +1 -1
  38. package/build/client/assets/{playground-xNPUi1cK.js → playground-DIm_r4fy.js} +2 -2
  39. package/build/client/assets/{playground-xNPUi1cK.js.map → playground-DIm_r4fy.js.map} +1 -1
  40. package/build/client/assets/{preview-DUByetdK.js → preview-D11Pscbe.js} +2 -2
  41. package/build/client/assets/{preview-DUByetdK.js.map → preview-D11Pscbe.js.map} +1 -1
  42. package/build/client/assets/{product-DlgtjMXY.js → product-CNG57fZy.js} +2 -2
  43. package/build/client/assets/{product-DlgtjMXY.js.map → product-CNG57fZy.js.map} +1 -1
  44. package/build/client/assets/{root-B-fnUAyN.js → root-hU3hrO-C.js} +2 -2
  45. package/build/client/assets/{root-B-fnUAyN.js.map → root-hU3hrO-C.js.map} +1 -1
  46. package/build/client/assets/{test-wFDk9A6D.js → test-CpoHBC_8.js} +2 -2
  47. package/build/client/assets/{test-wFDk9A6D.js.map → test-CpoHBC_8.js.map} +1 -1
  48. package/build/client/assets/{tests-BldZ_klJ.js → tests-CITG_DX3.js} +2 -2
  49. package/build/client/assets/{tests-BldZ_klJ.js.map → tests-CITG_DX3.js.map} +1 -1
  50. package/build/server/index.js +22 -23
  51. package/build/server/index.js.map +1 -1
  52. package/package.json +3 -3
  53. package/build/client/assets/app-rrQthl25.js +0 -2
  54. package/build/client/assets/index-Cg-9mI3Y.js +0 -68
  55. package/build/client/assets/index-Cg-9mI3Y.js.map +0 -1
  56. 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-Bndfj6GR.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-CbaVHkqG.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-Cg-9mI3Y.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-IJRzD1mm.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-CvFJy3s8.js.map
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-CvFJy3s8.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
+ {"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-xNPUi1cK.js";import{U as I}from"./diff-De24Mp-s.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-DUByetdK.js";import{T as k}from"./tests-BldZ_klJ.js";import"./index-CqIc3cxq.js";import"./loading-IJRzD1mm.js";import"./index-Cg-9mI3Y.js";import"./tooltip-f3C9W-4C.js";import"./index-vDCSPjrM.js";import"./root-loader-BObzljW3.js";import"./pe-UQCAhDPv.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-CbaVHkqG.js";import"./epic-video-Bndfj6GR.js";import"./use-event-source-BuD4_2SF.js";import"./schemas-Uj5SZtvt.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-BL399UJV.js.map
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-Bndfj6GR.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-CbaVHkqG.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-Cg-9mI3Y.js";import"./tooltip-f3C9W-4C.js";import"./pe-UQCAhDPv.js";import"./schemas-Uj5SZtvt.js";import"./online-D6QnZT5V.js";import"./loading-IJRzD1mm.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-B1TztMYA.js.map
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-B1TztMYA.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
+ {"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":"w6BAgCO,MAAMA,EAAqCC,GAAS,CAC1D,MAAMC,EAAaD,EAAKE,KAClBC,EAAWC,EAAuBJ,EAAKK,OAAO,EACpD,MAAI,CAACJ,GAAc,CAACE,EAAiB,CAAC,CAAEG,MAAO,YAAa,CAAC,EAEtDC,EAAe,CACrBD,MAAO,QAAQL,EAAWK,KAAK,MAAMH,EAASK,aAAa,GAC3DC,YAAa,cAAcN,EAASK,aAAa,GACjDE,QAAST,EAAWK,MACpBK,cAAe,cAAcR,EAASK,aAAa,GACnDI,WAAYT,EAASS,WACrBC,YAAaV,EAASU,WACvB,CAAC,CACF,EAiEA,SAASC,EAAc,CACtBC,MAAAA,CACD,EAEG,CACF,aACE,KAAA,CACAC,SAAAC,EAAAA,KAACC,EAAA,CACAC,UAAWC,EACV,8EACA,qCACD,EACAC,SAAS,SACTC,GAAIP,EAAMQ,QAEVP,SAAA,CAAAQ,EAAAA,IAAC,OAAA,CAAKL,UAAU,yDAAyDH,SAAA,GAAA,CAEzE,EACAQ,EAAAA,IAAC,OAAA,CAAKL,UAAU,WAAYH,WAAMV,KAAA,CAAM,CAAA,EACzC,CAAA,CACD,CAEF,CAEA,MAAMmB,EAAgB,CAAEC,GAAIA,IAAM,IAAK,EAEvCC,EAAAC,EAAA,UAAsC,CACrC,MAAM1B,EAAO2B,EAAA,EACbC,OAAAA,EAAkB,CAAEC,WAAY,CAAC,UAAW,YAAa,YAAY,CAAE,CAAC,EAGvEd,EAAAA,KAAC,OAAA,CAAKE,UAAU,4FACfH,SAAA,CAAAC,EAAAA,KAAC,UAAA,CACAe,GAAI9B,EAAK+B,UACTd,UAAU,8JAEVH,SAAA,CAAAQ,EAAAA,IAAC,MAAA,CACAR,eAAC,KAAA,CAAGG,UAAU,4DACZH,SAAAd,EAAKI,MACP,CAAA,CACD,EACAkB,EAAAA,IAAC,MAAA,CACCR,SAAAd,EAAKgC,aAAaC,SAASC,SAAW,WACvClC,EAAKgC,aAAaC,SAASE,KAC1Bb,EAAAA,IAACc,EAAA,CACAC,sBAAuBrC,EAAKqC,sBAE5BvB,SAAAQ,EAAAA,IAAC,MAAA,CAAIL,UAAU,sCACdH,SAAAQ,EAAAA,IAACgB,EAAA,CACAH,KAAMnC,EAAKgC,aAAaC,SAASE,KACjCI,WAAYhB,EACb,EACD,CAAA,CACD,EACGvB,EAAKgC,aAAaC,SAASC,SAAW,QACzCnB,EAAAA,KAAC,MAAA,CAAIE,UAAU,8BAA8BH,SAAA,CAAA,4BAE3C,MAAA,CAAKA,SAAAd,EAAKgC,aAAaC,SAASO,KAAA,CAAM,CAAA,CAAA,CACxC,EAEA,2BAAA,CAEF,EACAzB,EAAAA,KAAC,MAAA,CAAIE,UAAU,OACdH,SAAA,CAAAQ,EAAAA,IAAC,KAAA,CAAGL,UAAU,iDAAiDH,SAAA,QAAA,CAE/D,EACCd,EAAKyC,OAAOC,OACZpB,EAAAA,IAAC,KAAA,CAAGL,UAAU,6DACZH,SAAAd,EAAKyC,OAAOE,IAAK9B,GACjBS,EAAAA,IAACV,EAAA,CAAkCC,MAAAA,CAAA,EAAfA,EAAMQ,OAAuB,CACjD,CAAA,CACF,EAEAC,EAAAA,IAAC,IAAA,CAAEL,UAAU,wBAAwBH,SAAA,wCAAA,CAErC,CAAA,CAAA,CAEF,CAAA,CAAA,CACD,QACC8B,EAAA,CAAyBC,aAAc,IAAI7C,EAAK+B,SAAS,EAAA,CAAI,EAC9DT,EAAAA,IAAC,MAAA,CAAIL,UAAU,+CACdH,SAAAQ,EAAAA,IAACwB,EAAA,CACAC,KAAM/C,EAAKgC,aAAae,KACxBC,aAAchD,EAAKgC,aAAagB,aACjC,CAAA,CACD,CAAA,CAAA,CACD,CAEF,CAAA,EAEOC,EAAAC,EAAA,UAAyB,CAC/B,aAAQC,EAAA,EAAqB,CAC9B,CAAA"}
@@ -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-Cg-9mI3Y.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-IJRzD1mm.js.map
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-IJRzD1mm.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
+ {"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-IJRzD1mm.js";import{L as _}from"./product-DlgtjMXY.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-Cg-9mI3Y.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-VlyrGJvd.js.map
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"};