@epic-web/workshop-app 4.26.1 → 4.27.0

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 (52) hide show
  1. package/build/client/assets/{_exerciseNumber-B_1LTOMl.js → _exerciseNumber-DeMmiDU5.js} +2 -2
  2. package/build/client/assets/{_exerciseNumber-B_1LTOMl.js.map → _exerciseNumber-DeMmiDU5.js.map} +1 -1
  3. package/build/client/assets/{_exerciseNumber_.finished-DHl9ou1s.js → _exerciseNumber_.finished-DM5HZX6r.js} +2 -2
  4. package/build/client/assets/{_exerciseNumber_.finished-DHl9ou1s.js.map → _exerciseNumber_.finished-DM5HZX6r.js.map} +1 -1
  5. package/build/client/assets/{_layout-TpI4uc69.js → _layout-5idP3Bqx.js} +2 -2
  6. package/build/client/assets/{_layout-TpI4uc69.js.map → _layout-5idP3Bqx.js.map} +1 -1
  7. package/build/client/assets/{_layout-CksyTzND.js → _layout-DkGEbcMk.js} +2 -2
  8. package/build/client/assets/{_layout-CksyTzND.js.map → _layout-DkGEbcMk.js.map} +1 -1
  9. package/build/client/assets/{account-DWhUP9x5.js → account-D1DCJCnR.js} +2 -2
  10. package/build/client/assets/{account-DWhUP9x5.js.map → account-D1DCJCnR.js.map} +1 -1
  11. package/build/client/assets/{diff-CKxYA_sC.js → diff-CU8At1c4.js} +2 -2
  12. package/build/client/assets/{diff-CKxYA_sC.js.map → diff-CU8At1c4.js.map} +1 -1
  13. package/build/client/assets/diff-hoOood-9.js +2 -0
  14. package/build/client/assets/diff-hoOood-9.js.map +1 -0
  15. package/build/client/assets/discord-BBRM_H3g.js +2 -0
  16. package/build/client/assets/discord-BBRM_H3g.js.map +1 -0
  17. package/build/client/assets/{discord-OBIm1mMI.js → discord-CgdmSzxV.js} +2 -2
  18. package/build/client/assets/{discord-OBIm1mMI.js.map → discord-CgdmSzxV.js.map} +1 -1
  19. package/build/client/assets/{epic-video-CzGRLoYH.js → epic-video-BFcdejfC.js} +2 -2
  20. package/build/client/assets/{epic-video-CzGRLoYH.js.map → epic-video-BFcdejfC.js.map} +1 -1
  21. package/build/client/assets/{finished-Bb9g_iPq.js → finished-C_v7hO19.js} +2 -2
  22. package/build/client/assets/{finished-Bb9g_iPq.js.map → finished-C_v7hO19.js.map} +1 -1
  23. package/build/client/assets/{index-C-VazAW9.js → index-BHeB-0xq.js} +2 -2
  24. package/build/client/assets/{index-C-VazAW9.js.map → index-BHeB-0xq.js.map} +1 -1
  25. package/build/client/assets/{index-DoUR7StN.js → index-CsPok4Mn.js} +2 -2
  26. package/build/client/assets/{index-DoUR7StN.js.map → index-CsPok4Mn.js.map} +1 -1
  27. package/build/client/assets/login-Ca9EDpZj.js +2 -0
  28. package/build/client/assets/{login-L4mUv67t.js.map → login-Ca9EDpZj.js.map} +1 -1
  29. package/build/client/assets/manifest-93b38e47.js +1 -0
  30. package/build/client/assets/{mdx-CGcvotZI.js → mdx-DvqHp8UI.js} +2 -2
  31. package/build/client/assets/{mdx-CGcvotZI.js.map → mdx-DvqHp8UI.js.map} +1 -1
  32. package/build/client/assets/{onboarding-Ci4QCevA.js → onboarding-Dc2TmI9y.js} +2 -2
  33. package/build/client/assets/{onboarding-Ci4QCevA.js.map → onboarding-Dc2TmI9y.js.map} +1 -1
  34. package/build/client/assets/test-Cy-fo6gv.js +2 -0
  35. package/build/client/assets/{test-CxCjtGOl.js.map → test-Cy-fo6gv.js.map} +1 -1
  36. package/build/client/assets/tests-DmimqC1q.js +4 -0
  37. package/build/client/assets/tests-DmimqC1q.js.map +1 -0
  38. package/build/client/assets/user-DvujSs-t.js +2 -0
  39. package/build/client/assets/{user-D6tTg1yS.js.map → user-DvujSs-t.js.map} +1 -1
  40. package/build/server/index.js +47 -21
  41. package/build/server/index.js.map +1 -1
  42. package/package.json +3 -3
  43. package/build/client/assets/diff-B5EME8RQ.js +0 -2
  44. package/build/client/assets/diff-B5EME8RQ.js.map +0 -1
  45. package/build/client/assets/discord-pvbkb0tl.js +0 -2
  46. package/build/client/assets/discord-pvbkb0tl.js.map +0 -1
  47. package/build/client/assets/login-L4mUv67t.js +0 -2
  48. package/build/client/assets/manifest-afe7bbfb.js +0 -1
  49. package/build/client/assets/test-CxCjtGOl.js +0 -2
  50. package/build/client/assets/tests-DWqwnWIn.js +0 -4
  51. package/build/client/assets/tests-DWqwnWIn.js.map +0 -1
  52. package/build/client/assets/user-D6tTg1yS.js +0 -2
@@ -1,2 +1,2 @@
1
- import{j as e,r as t}from"./index-1cKOJFpX.js";import{E as l}from"./index-Dx5GmdYq.js";import{E as n}from"./epic-video-CzGRLoYH.js";import{L as a}from"./loading-CF7oQHQf.js";import{N as d}from"./nav-chevrons-Cbc1bd_j.js";import{M as c,E as m}from"./mdx-CGcvotZI.js";import{a as p}from"./misc-Txs7O6JX.js";import{g as f}from"./seo-pBpFCWsy.js";import{P as h}from"./progress-C7kc6YXZ.js";import{u as x,L as u}from"./components-CME-nGId.js";import"./index-DlJAkutV.js";import"./request-info-CEhUGODY.js";import"./tooltip-DTFU8ajx.js";import"./pe-CUZaIcdt.js";import"./user-D6tTg1yS.js";import"./workshop-config-CL4F08kr.js";import"./progress-bar-bUuKn1Q8.js";const q={getSitemapEntries:()=>[{route:"/finished"}]},R=({matches:s})=>{var o;const r=(o=s.find(i=>i.id==="root"))==null?void 0:o.data;return r?f({title:`🎉 ${r==null?void 0:r.workshopTitle}`,description:`Elaboration for ${r==null?void 0:r.workshopTitle}`,ogTitle:`Finished ${r==null?void 0:r.workshopTitle}`,ogDescription:"You finished! Time to submit feedback.",instructor:r.instructor,requestInfo:r.requestInfo}):[]},j={h1:()=>null};function U(){const s=x();return e.jsx("div",{className:"flex h-full flex-grow flex-col",children:e.jsxs("main",{className:"grid h-full flex-grow grid-cols-1 grid-rows-2 lg:grid-cols-2 lg:grid-rows-1",children:[e.jsxs("div",{className:"relative col-span-1 row-span-1 flex h-full flex-col lg:border-r",children:[e.jsx("h1",{className:"h-14 border-b pl-10 pr-5 text-sm font-medium uppercase leading-none",children:e.jsx("div",{className:"flex h-14 flex-wrap items-center justify-between gap-x-2 py-2",children:e.jsxs("div",{className:"flex items-center justify-start gap-x-2",children:[e.jsx(u,{to:"/",className:"hover:underline",children:s.workshopTitle}),e.jsx("span",{children:"/"}),e.jsx("span",{children:"Elaboration"})]})})}),e.jsx("article",{className:"shadow-on-scrollbox h-full w-full max-w-none flex-1 scroll-pt-6 space-y-6 overflow-y-auto p-2 scrollbar-thin scrollbar-thumb-scrollbar sm:p-10 sm:pt-8",id:s.articleId,children:s.finishedCode?e.jsx(n,{epicVideoInfosPromise:s.epicVideoInfosPromise,children:e.jsx("div",{className:"prose dark:prose-invert sm:prose-lg",children:e.jsx(c,{code:s.finishedCode,components:j})})}):"No finished instructions yet..."}),e.jsx(l,{elementQuery:`#${s.articleId}`}),e.jsx(h,{type:"workshop-finished",className:"h-14 border-t px-6"}),e.jsxs("div",{className:"flex h-16 justify-between border-b-4 border-t lg:border-b-0",children:[e.jsx("div",{}),s.workshopFinished.status==="success"?e.jsx(m,{file:s.workshopFinished.file,relativePath:s.workshopFinished.relativePath}):null,e.jsx(d,{prev:s.prevStepLink,next:{to:"/"}})]})]}),e.jsx(b,{workshopTitle:s.workshopTitle,workshopFormEmbedUrl:s.workshopFormEmbedUrl})]})})}function b({workshopTitle:s,workshopFormEmbedUrl:r}){const[o,i]=t.useState(!1);return e.jsxs("div",{className:"relative flex-shrink-0",children:[o?null:e.jsx("div",{className:"absolute inset-0 z-10 flex items-center justify-center",children:e.jsx(a,{children:e.jsxs("span",{children:["Loading ",s," Elaboration form"]})})}),e.jsx("iframe",{onLoad:()=>i(!0),onError:()=>i(!0),title:"Elaboration",src:r,className:p("absolute inset-0 flex h-full w-full transition-opacity duration-300",o?"opacity-100":"opacity-0")})]})}export{U as default,q as handle,R as meta};
2
- //# sourceMappingURL=finished-Bb9g_iPq.js.map
1
+ import{j as e,r as t}from"./index-1cKOJFpX.js";import{E as l}from"./index-Dx5GmdYq.js";import{E as n}from"./epic-video-BFcdejfC.js";import{L as a}from"./loading-CF7oQHQf.js";import{N as d}from"./nav-chevrons-Cbc1bd_j.js";import{M as c,E as m}from"./mdx-DvqHp8UI.js";import{a as p}from"./misc-Txs7O6JX.js";import{g as f}from"./seo-pBpFCWsy.js";import{P as h}from"./progress-C7kc6YXZ.js";import{u as x,L as u}from"./components-CME-nGId.js";import"./index-DlJAkutV.js";import"./request-info-CEhUGODY.js";import"./tooltip-DTFU8ajx.js";import"./pe-CUZaIcdt.js";import"./user-DvujSs-t.js";import"./workshop-config-CL4F08kr.js";import"./progress-bar-bUuKn1Q8.js";const q={getSitemapEntries:()=>[{route:"/finished"}]},R=({matches:s})=>{var o;const r=(o=s.find(i=>i.id==="root"))==null?void 0:o.data;return r?f({title:`🎉 ${r==null?void 0:r.workshopTitle}`,description:`Elaboration for ${r==null?void 0:r.workshopTitle}`,ogTitle:`Finished ${r==null?void 0:r.workshopTitle}`,ogDescription:"You finished! Time to submit feedback.",instructor:r.instructor,requestInfo:r.requestInfo}):[]},j={h1:()=>null};function U(){const s=x();return e.jsx("div",{className:"flex h-full flex-grow flex-col",children:e.jsxs("main",{className:"grid h-full flex-grow grid-cols-1 grid-rows-2 lg:grid-cols-2 lg:grid-rows-1",children:[e.jsxs("div",{className:"relative col-span-1 row-span-1 flex h-full flex-col lg:border-r",children:[e.jsx("h1",{className:"h-14 border-b pl-10 pr-5 text-sm font-medium uppercase leading-none",children:e.jsx("div",{className:"flex h-14 flex-wrap items-center justify-between gap-x-2 py-2",children:e.jsxs("div",{className:"flex items-center justify-start gap-x-2",children:[e.jsx(u,{to:"/",className:"hover:underline",children:s.workshopTitle}),e.jsx("span",{children:"/"}),e.jsx("span",{children:"Elaboration"})]})})}),e.jsx("article",{className:"shadow-on-scrollbox h-full w-full max-w-none flex-1 scroll-pt-6 space-y-6 overflow-y-auto p-2 scrollbar-thin scrollbar-thumb-scrollbar sm:p-10 sm:pt-8",id:s.articleId,children:s.finishedCode?e.jsx(n,{epicVideoInfosPromise:s.epicVideoInfosPromise,children:e.jsx("div",{className:"prose dark:prose-invert sm:prose-lg",children:e.jsx(c,{code:s.finishedCode,components:j})})}):"No finished instructions yet..."}),e.jsx(l,{elementQuery:`#${s.articleId}`}),e.jsx(h,{type:"workshop-finished",className:"h-14 border-t px-6"}),e.jsxs("div",{className:"flex h-16 justify-between border-b-4 border-t lg:border-b-0",children:[e.jsx("div",{}),s.workshopFinished.status==="success"?e.jsx(m,{file:s.workshopFinished.file,relativePath:s.workshopFinished.relativePath}):null,e.jsx(d,{prev:s.prevStepLink,next:{to:"/"}})]})]}),e.jsx(b,{workshopTitle:s.workshopTitle,workshopFormEmbedUrl:s.workshopFormEmbedUrl})]})})}function b({workshopTitle:s,workshopFormEmbedUrl:r}){const[o,i]=t.useState(!1);return e.jsxs("div",{className:"relative flex-shrink-0",children:[o?null:e.jsx("div",{className:"absolute inset-0 z-10 flex items-center justify-center",children:e.jsx(a,{children:e.jsxs("span",{children:["Loading ",s," Elaboration form"]})})}),e.jsx("iframe",{onLoad:()=>i(!0),onError:()=>i(!0),title:"Elaboration",src:r,className:p("absolute inset-0 flex h-full w-full transition-opacity duration-300",o?"opacity-100":"opacity-0")})]})}export{U as default,q as handle,R as meta};
2
+ //# sourceMappingURL=finished-C_v7hO19.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"finished-Bb9g_iPq.js","sources":["../../../app/routes/_app+/finished.tsx"],"sourcesContent":["import { ElementScrollRestoration } from '@epic-web/restore-scroll'\nimport {\n\tgetExercises,\n\tgetWorkshopFinished,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n\ttime,\n} from '@epic-web/workshop-utils/timing.server'\nimport { type SEOHandle } from '@nasa-gcn/remix-seo'\nimport {\n\tdefer,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n\ttype MetaFunction,\n} from '@remix-run/node'\nimport { Link, useLoaderData } from '@remix-run/react'\nimport slugify from '@sindresorhus/slugify'\nimport * as React from 'react'\nimport { EpicVideoInfoProvider } from '#app/components/epic-video.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { NavChevrons } from '#app/components/nav-chevrons.tsx'\nimport { type loader as rootLoader } from '#app/root.tsx'\nimport { getEpicVideoInfos } from '#app/utils/epic-api.ts'\nimport { Mdx } from '#app/utils/mdx.tsx'\nimport { cn } from '#app/utils/misc.tsx'\nimport { getSeoMetaTags } from '#app/utils/seo.js'\nimport { EditFileOnGitHub } from '../launch-editor.tsx'\nimport { ProgressToggle } from '../progress.tsx'\n\nexport const handle: SEOHandle = {\n\tgetSitemapEntries: () => [{ route: '/finished' }],\n}\n\nexport const meta: MetaFunction<typeof loader, { root: typeof rootLoader }> = ({\n\tmatches,\n}) => {\n\tconst rootData = matches.find((m) => m.id === 'root')?.data\n\tif (!rootData) return []\n\n\treturn getSeoMetaTags({\n\t\ttitle: `🎉 ${rootData?.workshopTitle}`,\n\t\tdescription: `Elaboration for ${rootData?.workshopTitle}`,\n\t\togTitle: `Finished ${rootData?.workshopTitle}`,\n\t\togDescription: `You finished! Time to submit feedback.`,\n\t\tinstructor: rootData.instructor,\n\t\trequestInfo: rootData.requestInfo,\n\t})\n}\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('finishedLoader')\n\tconst exercises = await getExercises({ request, timings })\n\tconst compiledFinished = await time(() => getWorkshopFinished({ request }), {\n\t\ttimings,\n\t\ttype: 'compileMdx',\n\t\tdesc: 'compileMdx in finished',\n\t})\n\n\tconst lastExercises = exercises[exercises.length - 1]\n\tconst workshopConfig = getWorkshopConfig()\n\tconst workshopTitle = workshopConfig.title\n\tconst workshopFormTemplate = workshopConfig.forms.workshop\n\tconst workshopFormEmbedUrl = workshopFormTemplate.replace(\n\t\t'{workshopTitle}',\n\t\tencodeURIComponent(workshopTitle),\n\t)\n\treturn defer(\n\t\t{\n\t\t\tarticleId: `workshop-${slugify(workshopTitle)}-finished`,\n\t\t\tworkshopTitle,\n\t\t\tworkshopFormEmbedUrl,\n\t\t\tfinishedCode:\n\t\t\t\tcompiledFinished.compiled.status === 'success'\n\t\t\t\t\t? compiledFinished.compiled.code\n\t\t\t\t\t: null,\n\t\t\tepicVideoInfosPromise:\n\t\t\t\tcompiledFinished.compiled.status === 'success'\n\t\t\t\t\t? getEpicVideoInfos(compiledFinished.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\tworkshopFinished: {\n\t\t\t\tstatus: compiledFinished.compiled.status,\n\t\t\t\tfile: compiledFinished.file,\n\t\t\t\trelativePath: compiledFinished.relativePath,\n\t\t\t},\n\t\t\tprevStepLink: lastExercises\n\t\t\t\t? {\n\t\t\t\t\t\tto: `/${lastExercises.exerciseNumber}/finished`,\n\t\t\t\t\t}\n\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\nconst mdxComponents = { h1: () => null }\n\nexport default function ExerciseFinished() {\n\tconst data = useLoaderData<typeof loader>()\n\treturn (\n\t\t<div className=\"flex h-full flex-grow flex-col\">\n\t\t\t<main className=\"grid h-full flex-grow grid-cols-1 grid-rows-2 lg:grid-cols-2 lg:grid-rows-1\">\n\t\t\t\t<div className=\"relative col-span-1 row-span-1 flex h-full flex-col lg:border-r\">\n\t\t\t\t\t<h1 className=\"h-14 border-b pl-10 pr-5 text-sm font-medium uppercase leading-none\">\n\t\t\t\t\t\t<div className=\"flex h-14 flex-wrap items-center justify-between gap-x-2 py-2\">\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-start gap-x-2\">\n\t\t\t\t\t\t\t\t<Link to=\"/\" className=\"hover:underline\">\n\t\t\t\t\t\t\t\t\t{data.workshopTitle}\n\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t<span>/</span>\n\t\t\t\t\t\t\t\t<span>Elaboration</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</h1>\n\t\t\t\t\t<article\n\t\t\t\t\t\tclassName=\"shadow-on-scrollbox h-full w-full max-w-none flex-1 scroll-pt-6 space-y-6 overflow-y-auto p-2 scrollbar-thin scrollbar-thumb-scrollbar sm:p-10 sm:pt-8\"\n\t\t\t\t\t\tid={data.articleId}\n\t\t\t\t\t>\n\t\t\t\t\t\t{data.finishedCode ? (\n\t\t\t\t\t\t\t<EpicVideoInfoProvider\n\t\t\t\t\t\t\t\tepicVideoInfosPromise={data.epicVideoInfosPromise}\n\t\t\t\t\t\t\t>\n\t\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\t<Mdx code={data.finishedCode} components={mdxComponents} />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</EpicVideoInfoProvider>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t// TODO: render a random dad joke...\n\t\t\t\t\t\t\t'No finished instructions yet...'\n\t\t\t\t\t\t)}\n\t\t\t\t\t</article>\n\t\t\t\t\t<ElementScrollRestoration elementQuery={`#${data.articleId}`} />\n\t\t\t\t\t<ProgressToggle\n\t\t\t\t\t\ttype=\"workshop-finished\"\n\t\t\t\t\t\tclassName=\"h-14 border-t px-6\"\n\t\t\t\t\t/>\n\t\t\t\t\t<div className=\"flex h-16 justify-between border-b-4 border-t lg:border-b-0\">\n\t\t\t\t\t\t<div />\n\t\t\t\t\t\t{data.workshopFinished.status === 'success' ? (\n\t\t\t\t\t\t\t<EditFileOnGitHub\n\t\t\t\t\t\t\t\tfile={data.workshopFinished.file}\n\t\t\t\t\t\t\t\trelativePath={data.workshopFinished.relativePath}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t<NavChevrons prev={data.prevStepLink} next={{ to: '/' }} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<Survey\n\t\t\t\t\tworkshopTitle={data.workshopTitle}\n\t\t\t\t\tworkshopFormEmbedUrl={data.workshopFormEmbedUrl}\n\t\t\t\t/>\n\t\t\t</main>\n\t\t</div>\n\t)\n}\n\nfunction Survey({\n\tworkshopTitle,\n\tworkshopFormEmbedUrl,\n}: {\n\tworkshopTitle: string\n\tworkshopFormEmbedUrl: string\n}) {\n\tconst [iframeLoaded, setIframeLoaded] = React.useState(false)\n\treturn (\n\t\t<div className=\"relative flex-shrink-0\">\n\t\t\t{!iframeLoaded ? (\n\t\t\t\t<div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n\t\t\t\t\t<Loading>\n\t\t\t\t\t\t<span>Loading {workshopTitle} Elaboration form</span>\n\t\t\t\t\t</Loading>\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t<iframe\n\t\t\t\tonLoad={() => setIframeLoaded(true)}\n\t\t\t\t// show what would have shown if there is an error\n\t\t\t\tonError={() => setIframeLoaded(true)}\n\t\t\t\ttitle=\"Elaboration\"\n\t\t\t\tsrc={workshopFormEmbedUrl}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'absolute inset-0 flex h-full w-full transition-opacity duration-300',\n\t\t\t\t\tiframeLoaded ? 'opacity-100' : 'opacity-0',\n\t\t\t\t)}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n"],"names":["handle","getSitemapEntries","route","meta","matches","rootData","find","m","id","data","getSeoMetaTags","title","workshopTitle","description","ogTitle","ogDescription","instructor","requestInfo","mdxComponents","h1","ExerciseFinished","useLoaderData","className","children","jsxs","jsx","Link","to","articleId","finishedCode","EpicVideoInfoProvider","epicVideoInfosPromise","Mdx","code","components","ElementScrollRestoration","elementQuery","ProgressToggle","type","workshopFinished","status","EditFileOnGitHub","file","relativePath","NavChevrons","prev","prevStepLink","next","Survey","workshopFormEmbedUrl","iframeLoaded","setIframeLoaded","React","Loading","onLoad","onError","src","cn"],"mappings":"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"}
1
+ {"version":3,"file":"finished-C_v7hO19.js","sources":["../../../app/routes/_app+/finished.tsx"],"sourcesContent":["import { ElementScrollRestoration } from '@epic-web/restore-scroll'\nimport {\n\tgetExercises,\n\tgetWorkshopFinished,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n\ttime,\n} from '@epic-web/workshop-utils/timing.server'\nimport { type SEOHandle } from '@nasa-gcn/remix-seo'\nimport {\n\tdefer,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n\ttype MetaFunction,\n} from '@remix-run/node'\nimport { Link, useLoaderData } from '@remix-run/react'\nimport slugify from '@sindresorhus/slugify'\nimport * as React from 'react'\nimport { EpicVideoInfoProvider } from '#app/components/epic-video.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { NavChevrons } from '#app/components/nav-chevrons.tsx'\nimport { type loader as rootLoader } from '#app/root.tsx'\nimport { getEpicVideoInfos } from '#app/utils/epic-api.ts'\nimport { Mdx } from '#app/utils/mdx.tsx'\nimport { cn } from '#app/utils/misc.tsx'\nimport { getSeoMetaTags } from '#app/utils/seo.js'\nimport { EditFileOnGitHub } from '../launch-editor.tsx'\nimport { ProgressToggle } from '../progress.tsx'\n\nexport const handle: SEOHandle = {\n\tgetSitemapEntries: () => [{ route: '/finished' }],\n}\n\nexport const meta: MetaFunction<typeof loader, { root: typeof rootLoader }> = ({\n\tmatches,\n}) => {\n\tconst rootData = matches.find((m) => m.id === 'root')?.data\n\tif (!rootData) return []\n\n\treturn getSeoMetaTags({\n\t\ttitle: `🎉 ${rootData?.workshopTitle}`,\n\t\tdescription: `Elaboration for ${rootData?.workshopTitle}`,\n\t\togTitle: `Finished ${rootData?.workshopTitle}`,\n\t\togDescription: `You finished! Time to submit feedback.`,\n\t\tinstructor: rootData.instructor,\n\t\trequestInfo: rootData.requestInfo,\n\t})\n}\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('finishedLoader')\n\tconst exercises = await getExercises({ request, timings })\n\tconst compiledFinished = await time(() => getWorkshopFinished({ request }), {\n\t\ttimings,\n\t\ttype: 'compileMdx',\n\t\tdesc: 'compileMdx in finished',\n\t})\n\n\tconst lastExercises = exercises[exercises.length - 1]\n\tconst workshopConfig = getWorkshopConfig()\n\tconst workshopTitle = workshopConfig.title\n\tconst workshopFormTemplate = workshopConfig.forms.workshop\n\tconst workshopFormEmbedUrl = workshopFormTemplate.replace(\n\t\t'{workshopTitle}',\n\t\tencodeURIComponent(workshopTitle),\n\t)\n\treturn defer(\n\t\t{\n\t\t\tarticleId: `workshop-${slugify(workshopTitle)}-finished`,\n\t\t\tworkshopTitle,\n\t\t\tworkshopFormEmbedUrl,\n\t\t\tfinishedCode:\n\t\t\t\tcompiledFinished.compiled.status === 'success'\n\t\t\t\t\t? compiledFinished.compiled.code\n\t\t\t\t\t: null,\n\t\t\tepicVideoInfosPromise:\n\t\t\t\tcompiledFinished.compiled.status === 'success'\n\t\t\t\t\t? getEpicVideoInfos(compiledFinished.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\tworkshopFinished: {\n\t\t\t\tstatus: compiledFinished.compiled.status,\n\t\t\t\tfile: compiledFinished.file,\n\t\t\t\trelativePath: compiledFinished.relativePath,\n\t\t\t},\n\t\t\tprevStepLink: lastExercises\n\t\t\t\t? {\n\t\t\t\t\t\tto: `/${lastExercises.exerciseNumber}/finished`,\n\t\t\t\t\t}\n\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\nconst mdxComponents = { h1: () => null }\n\nexport default function ExerciseFinished() {\n\tconst data = useLoaderData<typeof loader>()\n\treturn (\n\t\t<div className=\"flex h-full flex-grow flex-col\">\n\t\t\t<main className=\"grid h-full flex-grow grid-cols-1 grid-rows-2 lg:grid-cols-2 lg:grid-rows-1\">\n\t\t\t\t<div className=\"relative col-span-1 row-span-1 flex h-full flex-col lg:border-r\">\n\t\t\t\t\t<h1 className=\"h-14 border-b pl-10 pr-5 text-sm font-medium uppercase leading-none\">\n\t\t\t\t\t\t<div className=\"flex h-14 flex-wrap items-center justify-between gap-x-2 py-2\">\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-start gap-x-2\">\n\t\t\t\t\t\t\t\t<Link to=\"/\" className=\"hover:underline\">\n\t\t\t\t\t\t\t\t\t{data.workshopTitle}\n\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t<span>/</span>\n\t\t\t\t\t\t\t\t<span>Elaboration</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</h1>\n\t\t\t\t\t<article\n\t\t\t\t\t\tclassName=\"shadow-on-scrollbox h-full w-full max-w-none flex-1 scroll-pt-6 space-y-6 overflow-y-auto p-2 scrollbar-thin scrollbar-thumb-scrollbar sm:p-10 sm:pt-8\"\n\t\t\t\t\t\tid={data.articleId}\n\t\t\t\t\t>\n\t\t\t\t\t\t{data.finishedCode ? (\n\t\t\t\t\t\t\t<EpicVideoInfoProvider\n\t\t\t\t\t\t\t\tepicVideoInfosPromise={data.epicVideoInfosPromise}\n\t\t\t\t\t\t\t>\n\t\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\t<Mdx code={data.finishedCode} components={mdxComponents} />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</EpicVideoInfoProvider>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t// TODO: render a random dad joke...\n\t\t\t\t\t\t\t'No finished instructions yet...'\n\t\t\t\t\t\t)}\n\t\t\t\t\t</article>\n\t\t\t\t\t<ElementScrollRestoration elementQuery={`#${data.articleId}`} />\n\t\t\t\t\t<ProgressToggle\n\t\t\t\t\t\ttype=\"workshop-finished\"\n\t\t\t\t\t\tclassName=\"h-14 border-t px-6\"\n\t\t\t\t\t/>\n\t\t\t\t\t<div className=\"flex h-16 justify-between border-b-4 border-t lg:border-b-0\">\n\t\t\t\t\t\t<div />\n\t\t\t\t\t\t{data.workshopFinished.status === 'success' ? (\n\t\t\t\t\t\t\t<EditFileOnGitHub\n\t\t\t\t\t\t\t\tfile={data.workshopFinished.file}\n\t\t\t\t\t\t\t\trelativePath={data.workshopFinished.relativePath}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t<NavChevrons prev={data.prevStepLink} next={{ to: '/' }} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<Survey\n\t\t\t\t\tworkshopTitle={data.workshopTitle}\n\t\t\t\t\tworkshopFormEmbedUrl={data.workshopFormEmbedUrl}\n\t\t\t\t/>\n\t\t\t</main>\n\t\t</div>\n\t)\n}\n\nfunction Survey({\n\tworkshopTitle,\n\tworkshopFormEmbedUrl,\n}: {\n\tworkshopTitle: string\n\tworkshopFormEmbedUrl: string\n}) {\n\tconst [iframeLoaded, setIframeLoaded] = React.useState(false)\n\treturn (\n\t\t<div className=\"relative flex-shrink-0\">\n\t\t\t{!iframeLoaded ? (\n\t\t\t\t<div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n\t\t\t\t\t<Loading>\n\t\t\t\t\t\t<span>Loading {workshopTitle} Elaboration form</span>\n\t\t\t\t\t</Loading>\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t<iframe\n\t\t\t\tonLoad={() => setIframeLoaded(true)}\n\t\t\t\t// show what would have shown if there is an error\n\t\t\t\tonError={() => setIframeLoaded(true)}\n\t\t\t\ttitle=\"Elaboration\"\n\t\t\t\tsrc={workshopFormEmbedUrl}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'absolute inset-0 flex h-full w-full transition-opacity duration-300',\n\t\t\t\t\tiframeLoaded ? 'opacity-100' : 'opacity-0',\n\t\t\t\t)}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n"],"names":["handle","getSitemapEntries","route","meta","matches","rootData","find","m","id","data","getSeoMetaTags","title","workshopTitle","description","ogTitle","ogDescription","instructor","requestInfo","mdxComponents","h1","ExerciseFinished","useLoaderData","className","children","jsxs","jsx","Link","to","articleId","finishedCode","EpicVideoInfoProvider","epicVideoInfosPromise","Mdx","code","components","ElementScrollRestoration","elementQuery","ProgressToggle","type","workshopFinished","status","EditFileOnGitHub","file","relativePath","NavChevrons","prev","prevStepLink","next","Survey","workshopFormEmbedUrl","iframeLoaded","setIframeLoaded","React","Loading","onLoad","onError","src","cn"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{j as e}from"./index-1cKOJFpX.js";import{E as t}from"./index-Dx5GmdYq.js";import{E as a}from"./epic-video-CzGRLoYH.js";import{G as i}from"./error-boundary-CqgVAFiu.js";import{M as l,E as m}from"./mdx-CGcvotZI.js";import{a as n}from"./misc-Txs7O6JX.js";import{P as d,u as c}from"./progress-C7kc6YXZ.js";import{u as p,L as x}from"./components-CME-nGId.js";import"./index-DlJAkutV.js";import"./request-info-CEhUGODY.js";import"./tooltip-DTFU8ajx.js";import"./pe-CUZaIcdt.js";import"./loading-CF7oQHQf.js";import"./user-D6tTg1yS.js";import"./workshop-config-CL4F08kr.js";import"./progress-bar-bUuKn1Q8.js";function h({exercise:r}){const s=c(r.exerciseNumber);return e.jsx("li",{children:e.jsxs(x,{className:n("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:bg-gray-50 hover:after:translate-x-0 hover:after:opacity-100 dark:hover:bg-white/5",s),to:`${r.exerciseNumber.toString().padStart(2,"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 f={h1:()=>null};function S(){const r=p(),s=e.jsxs("ul",{className:"flex flex-col divide-y divide-border dark:divide-border/50",children:[e.jsx("strong",{className:"px-10 pb-3 font-mono text-xs uppercase",children:"Exercises"}),r.exercises.map(o=>e.jsx(h,{exercise:o},o.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 flex w-full flex-1 flex-col gap-12 overflow-y-scroll px-3 py-4 pt-6 scrollbar-thin scrollbar-thumb-scrollbar 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)] font-extrabold leading-none",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(a,{epicVideoInfosPromise:r.epicVideoInfosPromise,children:e.jsx("div",{className:"prose dark:prose-invert sm:prose-lg",children:e.jsx(l,{code:r.workshopReadme.compiled.code,components:f})})}):r.workshopReadme.compiled.status==="error"?e.jsxs("div",{className:"text-red-500",children:["There was an error:",e.jsx("pre",{children:r.workshopReadme.compiled.error})]}):"No instructions yet..."]}),e.jsx("div",{className:"pb-5 pt-10",children:r.workshopReadme.compiled.status==="success"&&r.workshopReadme.compiled.code&&r.workshopReadme.compiled.code.length>500?s:null})]}),e.jsx(t,{elementQuery:`#${r.articleId}`}),e.jsx(d,{type:"workshop-instructions",className:"h-14 border-t px-6"}),e.jsx("div",{className:"flex h-16 justify-center border-t",children:e.jsx(m,{file:r.workshopReadme.file,relativePath:r.workshopReadme.relativePath})})]})}function V(){return e.jsx(i,{})}export{V as ErrorBoundary,S as default};
2
- //# sourceMappingURL=index-C-VazAW9.js.map
1
+ import{j as e}from"./index-1cKOJFpX.js";import{E as t}from"./index-Dx5GmdYq.js";import{E as a}from"./epic-video-BFcdejfC.js";import{G as i}from"./error-boundary-CqgVAFiu.js";import{M as l,E as m}from"./mdx-DvqHp8UI.js";import{a as n}from"./misc-Txs7O6JX.js";import{P as d,u as c}from"./progress-C7kc6YXZ.js";import{u as p,L as x}from"./components-CME-nGId.js";import"./index-DlJAkutV.js";import"./request-info-CEhUGODY.js";import"./tooltip-DTFU8ajx.js";import"./pe-CUZaIcdt.js";import"./loading-CF7oQHQf.js";import"./user-DvujSs-t.js";import"./workshop-config-CL4F08kr.js";import"./progress-bar-bUuKn1Q8.js";function h({exercise:r}){const s=c(r.exerciseNumber);return e.jsx("li",{children:e.jsxs(x,{className:n("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:bg-gray-50 hover:after:translate-x-0 hover:after:opacity-100 dark:hover:bg-white/5",s),to:`${r.exerciseNumber.toString().padStart(2,"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 f={h1:()=>null};function S(){const r=p(),s=e.jsxs("ul",{className:"flex flex-col divide-y divide-border dark:divide-border/50",children:[e.jsx("strong",{className:"px-10 pb-3 font-mono text-xs uppercase",children:"Exercises"}),r.exercises.map(o=>e.jsx(h,{exercise:o},o.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 flex w-full flex-1 flex-col gap-12 overflow-y-scroll px-3 py-4 pt-6 scrollbar-thin scrollbar-thumb-scrollbar 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)] font-extrabold leading-none",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(a,{epicVideoInfosPromise:r.epicVideoInfosPromise,children:e.jsx("div",{className:"prose dark:prose-invert sm:prose-lg",children:e.jsx(l,{code:r.workshopReadme.compiled.code,components:f})})}):r.workshopReadme.compiled.status==="error"?e.jsxs("div",{className:"text-red-500",children:["There was an error:",e.jsx("pre",{children:r.workshopReadme.compiled.error})]}):"No instructions yet..."]}),e.jsx("div",{className:"pb-5 pt-10",children:r.workshopReadme.compiled.status==="success"&&r.workshopReadme.compiled.code&&r.workshopReadme.compiled.code.length>500?s:null})]}),e.jsx(t,{elementQuery:`#${r.articleId}`}),e.jsx(d,{type:"workshop-instructions",className:"h-14 border-t px-6"}),e.jsx("div",{className:"flex h-16 justify-center border-t",children:e.jsx(m,{file:r.workshopReadme.file,relativePath:r.workshopReadme.relativePath})})]})}function V(){return e.jsx(i,{})}export{V as ErrorBoundary,S as default};
2
+ //# sourceMappingURL=index-BHeB-0xq.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-C-VazAW9.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 {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n\ttime,\n} from '@epic-web/workshop-utils/timing.server'\nimport {\n\tdefer,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n\ttype SerializeFrom,\n} from '@remix-run/node'\nimport { Link, useLoaderData } from '@remix-run/react'\nimport slugify from '@sindresorhus/slugify'\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 { getEpicVideoInfos } from '#app/utils/epic-api.ts'\nimport { Mdx } from '#app/utils/mdx.tsx'\nimport { cn } from '#app/utils/misc.tsx'\nimport { ProgressToggle, useExerciseProgressClassName } from '../progress.tsx'\n\nexport async function loader({ request }: LoaderFunctionArgs) {\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 defer(\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\texercise,\n}: {\n\texercise: SerializeFrom<typeof loader>['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\"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:bg-gray-50 hover:after:translate-x-0 hover:after:opacity-100 dark:hover:bg-white/5\",\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>\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() {\n\tconst data = useLoaderData<typeof loader>()\n\n\tconst exerciseLinks = (\n\t\t<ul className=\"flex flex-col divide-y divide-border dark:divide-border/50\">\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) => (\n\t\t\t\t<ExerciseListItem key={exercise.exerciseNumber} exercise={exercise} />\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 flex w-full flex-1 flex-col gap-12 overflow-y-scroll px-3 py-4 pt-6 scrollbar-thin scrollbar-thumb-scrollbar 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)] font-extrabold leading-none\">\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-red-500\">\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=\"pb-5 pt-10\">\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=\"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","exercise","progressClassName","useExerciseProgressClassName","exerciseNumber","children","jsxs","Link","className","cn","to","toString","padStart","jsx","title","mdxComponents","h1","Index","data","useLoaderData","exerciseLinks","exercises","map","id","articleId","workshopReadme","compiled","status","code","EpicVideoInfoProvider","epicVideoInfosPromise","Mdx","components","error","length","ElementScrollRestoration","elementQuery","ProgressToggle","type","EditFileOnGitHub","file","relativePath","ErrorBoundary","GeneralErrorBoundary"],"mappings":"gmBA+EA,SAASA,EAAiB,CACzBC,SAAAA,CACD,EAEG,CACF,MAAMC,EAAoBC,EACzBF,EAASG,cACV,EACA,aACE,KACA,CAAAC,SAAAC,EAAA,KAACC,EAAA,CACAC,UAAWC,EACV,+QACAP,CACD,EACAQ,GAAI,GAAGT,EAASG,eAAeO,SAAW,EAAAC,SAAS,EAAG,GAAG,CAAC,GAE1DP,SAAA,CAAAQ,EAAA,IAAC,OAAK,CAAAL,UAAU,8CACdH,SAAAJ,EAASG,cACX,CAAA,EACAS,EAAA,IAAC,OAAM,CAAAR,SAAAJ,EAASa,KAAM,CAAA,CAAA,EACvB,CAAA,EAZQb,EAASG,cAalB,CAEF,CAEA,MAAMW,EAAgB,CAAEC,GAAIA,IAAM,IAAK,EAEvC,SAAwBC,GAAQ,CAC/B,MAAMC,EAAOC,IAEPC,EACLd,EAAA,KAAC,KAAG,CAAAE,UAAU,6DACbH,SAAA,CAACQ,EAAA,IAAA,SAAA,CAAOL,UAAU,yCAAyCH,SAE3D,WAAA,CAAA,EACCa,EAAKG,UAAUC,IAAKrB,SACnBD,EAA+C,CAAAC,SAAAA,CAAA,EAAzBA,EAASG,cAAoC,CACpE,CAAA,CACF,CAAA,EAGA,OAAAE,EAAAA,KAAC,OAAK,CAAAE,UAAU,4FACfH,SAAA,CAAAC,EAAA,KAAC,UAAA,CACAiB,GAAIL,EAAKM,UACThB,UAAU,8JAEVH,SAAA,CAAAQ,EAAA,IAAC,OACAR,SAACQ,EAAA,IAAA,KAAA,CAAGL,UAAU,kEACZH,SAAAa,EAAKJ,MACP,CACD,CAAA,EACAR,EAAA,KAAC,MAAI,CAAAE,UAAU,oEACdH,SAAA,CAACQ,EAAA,IAAA,KAAA,CAAGL,UAAU,iDAAiDH,SAE/D,OAAA,CAAA,EACCa,EAAKO,eAAeC,SAASC,SAAW,WACzCT,EAAKO,eAAeC,SAASE,KAC5Bf,EAAAA,IAACgB,EAAA,CACAC,sBAAuBZ,EAAKY,sBAE5BzB,SAAAQ,EAAA,IAAC,MAAI,CAAAL,UAAU,sCACdH,SAAAQ,EAAA,IAACkB,EAAA,CACAH,KAAMV,EAAKO,eAAeC,SAASE,KACnCI,WAAYjB,EACb,EACD,CAAA,CACD,EACGG,EAAKO,eAAeC,SAASC,SAAW,QAC3CrB,EAAA,KAAC,MAAI,CAAAE,UAAU,eAAeH,SAAA,CAAA,sBAE5BQ,EAAA,IAAA,MAAA,CAAKR,SAAKa,EAAAO,eAAeC,SAASO,KAAM,CAAA,CAAA,CAC1C,CAAA,EAEA,wBAAA,CAEF,CAAA,EACApB,EAAA,IAAC,OAAIL,UAAU,aACbH,WAAKoB,eAAeC,SAASC,SAAW,WACzCT,EAAKO,eAAeC,SAASE,MAC7BV,EAAKO,eAAeC,SAASE,KAAKM,OAAS,IACxCd,EACA,IACJ,CAAA,CAAA,CAAA,CACD,QACCe,EAAyB,CAAAC,aAAc,IAAIlB,EAAKM,SAAS,EAAI,CAAA,EAC9DX,EAAA,IAACwB,EAAA,CACAC,KAAK,wBACL9B,UAAU,oBAAA,CACX,EACAK,EAAA,IAAC,MAAI,CAAAL,UAAU,oCACdH,SAAAQ,EAAA,IAAC0B,EAAA,CACAC,KAAMtB,EAAKO,eAAee,KAC1BC,aAAcvB,EAAKO,eAAegB,aACnC,CACD,CAAA,CAAA,CACD,CAAA,CAEF,CAEO,SAASC,GAAgB,CAC/B,aAAQC,EAAqB,CAAA,CAAA,CAC9B"}
1
+ {"version":3,"file":"index-BHeB-0xq.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 {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n\ttime,\n} from '@epic-web/workshop-utils/timing.server'\nimport {\n\tdefer,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n\ttype SerializeFrom,\n} from '@remix-run/node'\nimport { Link, useLoaderData } from '@remix-run/react'\nimport slugify from '@sindresorhus/slugify'\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 { getEpicVideoInfos } from '#app/utils/epic-api.ts'\nimport { Mdx } from '#app/utils/mdx.tsx'\nimport { cn } from '#app/utils/misc.tsx'\nimport { ProgressToggle, useExerciseProgressClassName } from '../progress.tsx'\n\nexport async function loader({ request }: LoaderFunctionArgs) {\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 defer(\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\texercise,\n}: {\n\texercise: SerializeFrom<typeof loader>['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\"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:bg-gray-50 hover:after:translate-x-0 hover:after:opacity-100 dark:hover:bg-white/5\",\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>\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() {\n\tconst data = useLoaderData<typeof loader>()\n\n\tconst exerciseLinks = (\n\t\t<ul className=\"flex flex-col divide-y divide-border dark:divide-border/50\">\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) => (\n\t\t\t\t<ExerciseListItem key={exercise.exerciseNumber} exercise={exercise} />\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 flex w-full flex-1 flex-col gap-12 overflow-y-scroll px-3 py-4 pt-6 scrollbar-thin scrollbar-thumb-scrollbar 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)] font-extrabold leading-none\">\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-red-500\">\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=\"pb-5 pt-10\">\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=\"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","exercise","progressClassName","useExerciseProgressClassName","exerciseNumber","children","jsxs","Link","className","cn","to","toString","padStart","jsx","title","mdxComponents","h1","Index","data","useLoaderData","exerciseLinks","exercises","map","id","articleId","workshopReadme","compiled","status","code","EpicVideoInfoProvider","epicVideoInfosPromise","Mdx","components","error","length","ElementScrollRestoration","elementQuery","ProgressToggle","type","EditFileOnGitHub","file","relativePath","ErrorBoundary","GeneralErrorBoundary"],"mappings":"gmBA+EA,SAASA,EAAiB,CACzBC,SAAAA,CACD,EAEG,CACF,MAAMC,EAAoBC,EACzBF,EAASG,cACV,EACA,aACE,KACA,CAAAC,SAAAC,EAAA,KAACC,EAAA,CACAC,UAAWC,EACV,+QACAP,CACD,EACAQ,GAAI,GAAGT,EAASG,eAAeO,SAAW,EAAAC,SAAS,EAAG,GAAG,CAAC,GAE1DP,SAAA,CAAAQ,EAAA,IAAC,OAAK,CAAAL,UAAU,8CACdH,SAAAJ,EAASG,cACX,CAAA,EACAS,EAAA,IAAC,OAAM,CAAAR,SAAAJ,EAASa,KAAM,CAAA,CAAA,EACvB,CAAA,EAZQb,EAASG,cAalB,CAEF,CAEA,MAAMW,EAAgB,CAAEC,GAAIA,IAAM,IAAK,EAEvC,SAAwBC,GAAQ,CAC/B,MAAMC,EAAOC,IAEPC,EACLd,EAAA,KAAC,KAAG,CAAAE,UAAU,6DACbH,SAAA,CAACQ,EAAA,IAAA,SAAA,CAAOL,UAAU,yCAAyCH,SAE3D,WAAA,CAAA,EACCa,EAAKG,UAAUC,IAAKrB,SACnBD,EAA+C,CAAAC,SAAAA,CAAA,EAAzBA,EAASG,cAAoC,CACpE,CAAA,CACF,CAAA,EAGA,OAAAE,EAAAA,KAAC,OAAK,CAAAE,UAAU,4FACfH,SAAA,CAAAC,EAAA,KAAC,UAAA,CACAiB,GAAIL,EAAKM,UACThB,UAAU,8JAEVH,SAAA,CAAAQ,EAAA,IAAC,OACAR,SAACQ,EAAA,IAAA,KAAA,CAAGL,UAAU,kEACZH,SAAAa,EAAKJ,MACP,CACD,CAAA,EACAR,EAAA,KAAC,MAAI,CAAAE,UAAU,oEACdH,SAAA,CAACQ,EAAA,IAAA,KAAA,CAAGL,UAAU,iDAAiDH,SAE/D,OAAA,CAAA,EACCa,EAAKO,eAAeC,SAASC,SAAW,WACzCT,EAAKO,eAAeC,SAASE,KAC5Bf,EAAAA,IAACgB,EAAA,CACAC,sBAAuBZ,EAAKY,sBAE5BzB,SAAAQ,EAAA,IAAC,MAAI,CAAAL,UAAU,sCACdH,SAAAQ,EAAA,IAACkB,EAAA,CACAH,KAAMV,EAAKO,eAAeC,SAASE,KACnCI,WAAYjB,EACb,EACD,CAAA,CACD,EACGG,EAAKO,eAAeC,SAASC,SAAW,QAC3CrB,EAAA,KAAC,MAAI,CAAAE,UAAU,eAAeH,SAAA,CAAA,sBAE5BQ,EAAA,IAAA,MAAA,CAAKR,SAAKa,EAAAO,eAAeC,SAASO,KAAM,CAAA,CAAA,CAC1C,CAAA,EAEA,wBAAA,CAEF,CAAA,EACApB,EAAA,IAAC,OAAIL,UAAU,aACbH,WAAKoB,eAAeC,SAASC,SAAW,WACzCT,EAAKO,eAAeC,SAASE,MAC7BV,EAAKO,eAAeC,SAASE,KAAKM,OAAS,IACxCd,EACA,IACJ,CAAA,CAAA,CAAA,CACD,QACCe,EAAyB,CAAAC,aAAc,IAAIlB,EAAKM,SAAS,EAAI,CAAA,EAC9DX,EAAA,IAACwB,EAAA,CACAC,KAAK,wBACL9B,UAAU,oBAAA,CACX,EACAK,EAAA,IAAC,MAAI,CAAAL,UAAU,oCACdH,SAAAQ,EAAA,IAAC0B,EAAA,CACAC,KAAMtB,EAAKO,eAAee,KAC1BC,aAAcvB,EAAKO,eAAegB,aACnC,CACD,CAAA,CAAA,CACD,CAAA,CAEF,CAEO,SAASC,GAAgB,CAC/B,aAAQC,EAAqB,CAAA,CAAA,CAC9B"}
@@ -1,2 +1,2 @@
1
- import{r as l,j as t,d as pe}from"./index-1cKOJFpX.js";import{d as K,h as ve,u as B,m as he,P as E,f as w,e as V,g as ge,S as je}from"./tooltip-DTFU8ajx.js";import{f as be,u as H}from"./index-9dWszLxO.js";import{u as $,I as P,c as we}from"./misc-Txs7O6JX.js";import{D as Ne}from"./diff-B5EME8RQ.js";import{G as ye}from"./error-boundary-CqgVAFiu.js";import{L as Te}from"./loading-CF7oQHQf.js";import{D as Ce,u as Ee}from"./discord-OBIm1mMI.js";import{u as k,A as Pe,L as Y,b as Ie}from"./components-CME-nGId.js";import{J as De}from"./index-B-hHvmeV.js";import{S as Re}from"./set-playground-Cr0qL9N9.js";import{P as Se,a as Fe}from"./tests-DWqwnWIn.js";import{P as F}from"./preview-WJ-QYhx8.js";import"./index-j_VpxCZh.js";import"./accordion-CKwXYK9L.js";import"./mdx-CGcvotZI.js";import"./epic-video-CzGRLoYH.js";import"./index-DlJAkutV.js";import"./request-info-CEhUGODY.js";import"./pe-CUZaIcdt.js";import"./user-D6tTg1yS.js";import"./workshop-config-CL4F08kr.js";import"./progress-bar-bUuKn1Q8.js";import"./use-event-source-A_0lEOPX.js";import"./button-CQ6cnotS.js";var S="rovingFocusGroup.onEntryFocus",Ae={bubbles:!1,cancelable:!0},I="RovingFocusGroup",[A,z,_e]=be(I),[ke,J]=K(I,[_e]),[Ue,Le]=ke(I),W=l.forwardRef((e,a)=>t.jsx(A.Provider,{scope:e.__scopeRovingFocusGroup,children:t.jsx(A.Slot,{scope:e.__scopeRovingFocusGroup,children:t.jsx(Ge,{...e,ref:a})})}));W.displayName=I;var Ge=l.forwardRef((e,a)=>{const{__scopeRovingFocusGroup:s,orientation:r,loop:n=!1,dir:x,currentTabStopId:i,defaultCurrentTabStopId:h,onCurrentTabStopIdChange:p,onEntryFocus:c,preventScrollOnEntryFocus:d=!1,...u}=e,v=l.useRef(null),N=ve(a,v),f=H(x),[b=null,o]=B({prop:i,defaultProp:h,onChange:p}),[m,j]=l.useState(!1),T=he(c),ce=z(s),D=l.useRef(!1),[ue,G]=l.useState(0);return l.useEffect(()=>{const g=v.current;if(g)return g.addEventListener(S,T),()=>g.removeEventListener(S,T)},[T]),t.jsx(Ue,{scope:s,orientation:r,dir:f,loop:n,currentTabStopId:b,onItemFocus:l.useCallback(g=>o(g),[o]),onItemShiftTab:l.useCallback(()=>j(!0),[]),onFocusableItemAdd:l.useCallback(()=>G(g=>g+1),[]),onFocusableItemRemove:l.useCallback(()=>G(g=>g-1),[]),children:t.jsx(E.div,{tabIndex:m||ue===0?-1:0,"data-orientation":r,...u,ref:N,style:{outline:"none",...e.style},onMouseDown:w(e.onMouseDown,()=>{D.current=!0}),onFocus:w(e.onFocus,g=>{const de=!D.current;if(g.target===g.currentTarget&&de&&!m){const M=new CustomEvent(S,Ae);if(g.currentTarget.dispatchEvent(M),!M.defaultPrevented){const R=ce().filter(y=>y.focusable),fe=R.find(y=>y.active),me=R.find(y=>y.id===b),xe=[fe,me,...R].filter(Boolean).map(y=>y.ref.current);X(xe,d)}}D.current=!1}),onBlur:w(e.onBlur,()=>j(!1))})})}),q="RovingFocusGroupItem",Q=l.forwardRef((e,a)=>{const{__scopeRovingFocusGroup:s,focusable:r=!0,active:n=!1,tabStopId:x,...i}=e,h=V(),p=x||h,c=Le(q,s),d=c.currentTabStopId===p,u=z(s),{onFocusableItemAdd:v,onFocusableItemRemove:N}=c;return l.useEffect(()=>{if(r)return v(),()=>N()},[r,v,N]),t.jsx(A.ItemSlot,{scope:s,id:p,focusable:r,active:n,children:t.jsx(E.span,{tabIndex:d?0:-1,"data-orientation":c.orientation,...i,ref:a,onMouseDown:w(e.onMouseDown,f=>{r?c.onItemFocus(p):f.preventDefault()}),onFocus:w(e.onFocus,()=>c.onItemFocus(p)),onKeyDown:w(e.onKeyDown,f=>{if(f.key==="Tab"&&f.shiftKey){c.onItemShiftTab();return}if(f.target!==f.currentTarget)return;const b=Ke(f,c.orientation,c.dir);if(b!==void 0){if(f.metaKey||f.ctrlKey||f.altKey||f.shiftKey)return;f.preventDefault();let m=u().filter(j=>j.focusable).map(j=>j.ref.current);if(b==="last")m.reverse();else if(b==="prev"||b==="next"){b==="prev"&&m.reverse();const j=m.indexOf(f.currentTarget);m=c.loop?Be(m,j+1):m.slice(j+1)}setTimeout(()=>X(m))}})})})});Q.displayName=q;var Me={ArrowLeft:"prev",ArrowUp:"prev",ArrowRight:"next",ArrowDown:"next",PageUp:"first",Home:"first",PageDown:"last",End:"last"};function Oe(e,a){return a!=="rtl"?e:e==="ArrowLeft"?"ArrowRight":e==="ArrowRight"?"ArrowLeft":e}function Ke(e,a,s){const r=Oe(e.key,s);if(!(a==="vertical"&&["ArrowLeft","ArrowRight"].includes(r))&&!(a==="horizontal"&&["ArrowUp","ArrowDown"].includes(r)))return Me[r]}function X(e,a=!1){const s=document.activeElement;for(const r of e)if(r===s||(r.focus({preventScroll:a}),document.activeElement!==s))return}function Be(e,a){return e.map((s,r)=>e[(a+r)%e.length])}var Ve=W,He=Q,U="Tabs",[$e,It]=K(U,[J]),Z=J(),[Ye,L]=$e(U),ee=l.forwardRef((e,a)=>{const{__scopeTabs:s,value:r,onValueChange:n,defaultValue:x,orientation:i="horizontal",dir:h,activationMode:p="automatic",...c}=e,d=H(h),[u,v]=B({prop:r,onChange:n,defaultProp:x});return t.jsx(Ye,{scope:s,baseId:V(),value:u,onValueChange:v,orientation:i,dir:d,activationMode:p,children:t.jsx(E.div,{dir:d,"data-orientation":i,...c,ref:a})})});ee.displayName=U;var te="TabsList",re=l.forwardRef((e,a)=>{const{__scopeTabs:s,loop:r=!0,...n}=e,x=L(te,s),i=Z(s);return t.jsx(Ve,{asChild:!0,...i,orientation:x.orientation,dir:x.dir,loop:r,children:t.jsx(E.div,{role:"tablist","aria-orientation":x.orientation,...n,ref:a})})});re.displayName=te;var se="TabsTrigger",ae=l.forwardRef((e,a)=>{const{__scopeTabs:s,value:r,disabled:n=!1,...x}=e,i=L(se,s),h=Z(s),p=ie(i.baseId,r),c=le(i.baseId,r),d=r===i.value;return t.jsx(He,{asChild:!0,...h,focusable:!n,active:d,children:t.jsx(E.button,{type:"button",role:"tab","aria-selected":d,"aria-controls":c,"data-state":d?"active":"inactive","data-disabled":n?"":void 0,disabled:n,id:p,...x,ref:a,onMouseDown:w(e.onMouseDown,u=>{!n&&u.button===0&&u.ctrlKey===!1?i.onValueChange(r):u.preventDefault()}),onKeyDown:w(e.onKeyDown,u=>{[" ","Enter"].includes(u.key)&&i.onValueChange(r)}),onFocus:w(e.onFocus,()=>{const u=i.activationMode!=="manual";!d&&!n&&u&&i.onValueChange(r)})})})});ae.displayName=se;var oe="TabsContent",ne=l.forwardRef((e,a)=>{const{__scopeTabs:s,value:r,forceMount:n,children:x,...i}=e,h=L(oe,s),p=ie(h.baseId,r),c=le(h.baseId,r),d=r===h.value,u=l.useRef(d);return l.useEffect(()=>{const v=requestAnimationFrame(()=>u.current=!1);return()=>cancelAnimationFrame(v)},[]),t.jsx(ge,{present:n||d,children:({present:v})=>t.jsx(E.div,{"data-state":d?"active":"inactive","data-orientation":h.orientation,role:"tabpanel","aria-labelledby":p,hidden:!v,id:c,tabIndex:0,...i,ref:a,style:{...e.style,animationDuration:u.current?"0s":void 0},children:v&&x})})});ne.displayName=oe;function ie(e,a){return`${e}-trigger-${a}`}function le(e,a){return`${e}-content-${a}`}var ze=ee,Je=re,We=ae,C=ne;function qe(){const e=k();return t.jsxs("div",{className:"flex h-full w-full flex-col gap-4 pt-4",children:[t.jsx("div",{className:"text-center",children:t.jsx(Ce,{discordAuthUrl:e.discordAuthUrl})}),t.jsx("div",{className:"flex-1 overflow-y-scroll bg-accent pb-4 scrollbar-thin scrollbar-thumb-scrollbar",children:t.jsx(Qe,{})})]})}function Qe(){const e=k(),a=Ee({discordAuthUrl:e.discordAuthUrl}),s=$();return t.jsxs("div",{className:"flex h-full flex-col items-center justify-between",children:[t.jsx(l.Suspense,{fallback:t.jsx("div",{className:"flex h-full w-full flex-col items-center justify-center",children:t.jsx(Te,{children:"Loading Discord Posts"})}),children:t.jsx(Pe,{resolve:e.discordPostsPromise,errorElement:t.jsx("div",{className:"text-red-500",children:"There was a problem loading the discord posts"}),children:r=>t.jsx("ul",{className:"flex w-full flex-col gap-4 p-3 xl:p-12",children:r.map(n=>t.jsx("li",{className:"rounded-xl border bg-background transition-all duration-200 focus-within:-translate-y-1 focus-within:shadow-lg hover:-translate-y-1 hover:shadow-lg",children:t.jsx(Xe,{thread:n})},n.id))})})}),t.jsx("div",{children:t.jsxs(Y,{to:s&&!a.includes("oauth")?a.replace(/^https/,"discord"):a,target:a.includes("oauth")?void 0:"_blank",rel:"noreferrer noopener",onClick:s?r=>{r.preventDefault(),window.open(r.currentTarget.href,"_blank","noreferrer noopener")}:void 0,className:"flex items-center gap-2 p-2 text-xl hover:underline",children:["Create Post ",t.jsx(P,{name:"ExternalLink"})]})})]})}function Xe({thread:e}){const a=e.reactions.filter(s=>s.count);return t.jsx("div",{children:t.jsxs("div",{className:"flex flex-col gap-2 p-4",children:[t.jsxs("div",{className:"flex gap-4",children:[t.jsxs("div",{className:"flex flex-col gap-1",children:[e.tags.length?t.jsx("div",{className:"flex gap-2",children:e.tags.map(s=>t.jsxs("div",{className:"flex items-center justify-center gap-1 rounded-full bg-accent px-2 py-1 text-sm",children:[t.jsx("span",{className:"h-3 w-3 leading-3",children:t.jsx(O,{name:s.emojiName,url:s.emojiUrl})}),t.jsx("span",{children:s.name})]},s.name))}):null,t.jsx("strong",{className:"text-xl font-bold",children:e.name}),t.jsxs("div",{className:"flex items-start gap-1",children:[t.jsxs("div",{className:"flex items-center gap-1",children:[e.authorAvatarUrl?t.jsx("img",{src:e.authorAvatarUrl,alt:"",className:"h-6 w-6 rounded-full"}):null,t.jsxs("span",{children:[t.jsx("span",{className:"font-bold",style:e.authorHexAccentColor?{color:e.authorHexAccentColor}:{},children:e.authorDisplayName}),":"," "]})]}),t.jsx("span",{className:"flex-1 overflow-ellipsis text-muted-foreground",children:e.messagePreview})]})]}),e.previewImageUrl?t.jsx("img",{src:e.previewImageUrl,alt:"",className:"h-28 w-28 rounded-lg object-cover"}):null]}),t.jsxs("div",{className:"flex justify-between",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("span",{children:a.length?t.jsx("ul",{className:"flex items-center gap-2",children:a.map((s,r)=>t.jsxs("li",{className:"flex items-center gap-1 rounded-md border border-blue-600 bg-blue-500/20 px-[5px] py-[0.5px] text-sm",children:[t.jsx("span",{className:"h-3 w-3 leading-3",children:t.jsx(O,{name:s.emojiName,url:s.emojiUrl})}),t.jsx("span",{children:s.count})]},r))}):null}),t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.jsx(P,{name:"Chat"})," ",e.messageCount]}),` · ${e.lastUpdatedDisplay}`]})]}),t.jsxs("span",{className:"flex items-center gap-4",children:[t.jsx("a",{href:e.link.replace(/^https/,"discord"),children:t.jsx(P,{name:"Discord"})}),t.jsx("a",{href:e.link,target:"_blank",rel:"noreferrer noopener",children:t.jsx(P,{name:"ExternalLink"})})]})]})]})})}function O({name:e,url:a}){return a?t.jsx("img",{src:a,alt:e,className:"h-full w-full"}):e||null}function Ze({appInfo:e,inBrowserBrowserRef:a,problemAppName:s,allApps:r,isUpToDate:n}){return t.jsx(Se,{playgroundAppName:e==null?void 0:e.appName,problemAppName:s,allApps:r,isUpToDate:n,children:(e==null?void 0:e.dev.type)==="none"?t.jsxs("div",{children:[t.jsx("div",{className:"text-foreground-secondary flex h-full items-center justify-center text-2xl",children:"Non-UI playground"}),t.jsx("div",{children:t.jsxs("div",{className:"text-foreground-secondary flex flex-wrap gap-1 text-center",children:["Navigate to"," ",t.jsx(je,{content:e.fullPath,children:t.jsx("span",{className:"underline",onClick:()=>{navigator.clipboard.writeText(e.fullPath),De.success("Copied playground path to clipboard")},children:"the playground directory"})})," ","in your editor and terminal to work on this exercise!"]})})]}):e?t.jsx(F,{id:e.appName,appInfo:e,inBrowserBrowserRef:a}):t.jsxs("div",{className:"flex flex-col justify-center gap-2",children:[t.jsx("p",{children:"Please set the playground first"}),s?t.jsx(Re,{appName:s}):null]})})}const _=["playground","problem","solution","tests","diff","chat"],et=e=>!!(e&&_.includes(e));function tt(e,a,s){const r=new URLSearchParams(e);return s===null?r.delete(a):r.set(a,s),r}function Dt(){var d,u,v,N,f,b;const e=k(),[a]=Ie(),s=a.get("preview"),r=l.useRef(null),n=$(),x=pe();function i(o){var m,j,T;if(o==="tests")return ENV.EPICSHOP_DEPLOYED||!e.playground||e.playground.test.type==="none";if(o==="problem"||o==="solution"){if(((m=e[o])==null?void 0:m.dev.type)==="none")return!0;if(ENV.EPICSHOP_DEPLOYED)return((j=e[o])==null?void 0:j.dev.type)!=="browser"&&!((T=e[o])!=null&&T.stackBlitzUrl)}return!!(o==="playground"&&ENV.EPICSHOP_DEPLOYED)}const h=et(s)?s:_.find(o=>!i(o)),p=`/diff?${new URLSearchParams({app1:((d=e.problem)==null?void 0:d.name)??"",app2:((u=e.solution)==null?void 0:u.name)??""})}`;function c(o){o.altKey&&!o.ctrlKey&&!o.shiftKey&&!o.metaKey&&(o.preventDefault(),x(p))}return t.jsxs(ze,{className:"relative flex flex-col overflow-y-auto sm:col-span-1 sm:row-span-1",value:h,children:[t.jsx(Je,{className:"h-14 min-h-14 overflow-x-hidden border-b scrollbar-thin scrollbar-thumb-scrollbar",children:_.map(o=>{const m=i(o);return t.jsx(We,{value:o,hidden:m,asChild:!0,children:t.jsx(Y,{id:`${o}-tab`,className:we("clip-path-button relative h-full px-6 py-4 font-mono text-sm uppercase outline-none radix-state-active:z-10 radix-state-active:bg-foreground radix-state-active:text-background radix-state-active:hover:bg-foreground/80 radix-state-active:hover:text-background/80 radix-state-inactive:hover:bg-foreground/20 radix-state-inactive:hover:text-foreground/80 focus:bg-foreground/80 focus:text-background/80",m?"hidden":"inline-block"),preventScrollReset:!0,prefetch:"intent",onClick:c,to:o==="diff"&&n?p:`?${tt(a,"preview",o==="playground"?null:o)}`,children:o})},o)})}),t.jsxs("div",{className:"relative z-10 flex min-h-96 flex-grow flex-col overflow-y-auto",children:[t.jsx(C,{value:"playground",className:"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden",children:t.jsx(Ze,{appInfo:e.playground,problemAppName:(v=e.problem)==null?void 0:v.name,inBrowserBrowserRef:r,allApps:e.allApps,isUpToDate:((N=e.playground)==null?void 0:N.isUpToDate)??!1})}),t.jsx(C,{value:"problem",className:"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden",children:t.jsx(F,{appInfo:e.problem,inBrowserBrowserRef:r})}),t.jsx(C,{value:"solution",className:"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden",children:t.jsx(F,{appInfo:e.solution,inBrowserBrowserRef:r})}),t.jsx(C,{value:"tests",className:"flex w-full flex-grow items-start justify-center self-start overflow-hidden radix-state-inactive:hidden",children:t.jsx(Fe,{appInfo:e.playground,problemAppName:(f=e.problem)==null?void 0:f.name,allApps:e.allApps,isUpToDate:((b=e.playground)==null?void 0:b.isUpToDate)??!1})}),t.jsx(C,{value:"diff",className:"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden",children:t.jsx(Ne,{diff:e.diff,allApps:e.allApps})}),t.jsx(C,{value:"chat",className:"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden",children:t.jsx(qe,{})})]})]})}function Rt(){return t.jsx(ye,{statusHandlers:{404:()=>t.jsx("p",{children:"Sorry, we couldn't find an app here."})}})}export{Rt as ErrorBoundary,Dt as default};
2
- //# sourceMappingURL=index-DoUR7StN.js.map
1
+ import{r as l,j as t,d as pe}from"./index-1cKOJFpX.js";import{d as K,h as ve,u as B,m as he,P as E,f as w,e as V,g as ge,S as je}from"./tooltip-DTFU8ajx.js";import{f as be,u as H}from"./index-9dWszLxO.js";import{u as $,I as P,c as we}from"./misc-Txs7O6JX.js";import{D as Ne}from"./diff-hoOood-9.js";import{G as ye}from"./error-boundary-CqgVAFiu.js";import{L as Te}from"./loading-CF7oQHQf.js";import{D as Ce,u as Ee}from"./discord-CgdmSzxV.js";import{u as k,A as Pe,L as Y,b as Ie}from"./components-CME-nGId.js";import{J as De}from"./index-B-hHvmeV.js";import{S as Re}from"./set-playground-Cr0qL9N9.js";import{P as Se,a as Fe}from"./tests-DmimqC1q.js";import{P as F}from"./preview-WJ-QYhx8.js";import"./index-j_VpxCZh.js";import"./accordion-CKwXYK9L.js";import"./mdx-DvqHp8UI.js";import"./epic-video-BFcdejfC.js";import"./index-DlJAkutV.js";import"./request-info-CEhUGODY.js";import"./pe-CUZaIcdt.js";import"./user-DvujSs-t.js";import"./workshop-config-CL4F08kr.js";import"./progress-bar-bUuKn1Q8.js";import"./use-event-source-A_0lEOPX.js";import"./button-CQ6cnotS.js";var S="rovingFocusGroup.onEntryFocus",Ae={bubbles:!1,cancelable:!0},I="RovingFocusGroup",[A,z,_e]=be(I),[ke,J]=K(I,[_e]),[Ue,Le]=ke(I),W=l.forwardRef((e,a)=>t.jsx(A.Provider,{scope:e.__scopeRovingFocusGroup,children:t.jsx(A.Slot,{scope:e.__scopeRovingFocusGroup,children:t.jsx(Ge,{...e,ref:a})})}));W.displayName=I;var Ge=l.forwardRef((e,a)=>{const{__scopeRovingFocusGroup:s,orientation:r,loop:n=!1,dir:x,currentTabStopId:i,defaultCurrentTabStopId:h,onCurrentTabStopIdChange:p,onEntryFocus:c,preventScrollOnEntryFocus:d=!1,...u}=e,v=l.useRef(null),N=ve(a,v),f=H(x),[b=null,o]=B({prop:i,defaultProp:h,onChange:p}),[m,j]=l.useState(!1),T=he(c),ce=z(s),D=l.useRef(!1),[ue,G]=l.useState(0);return l.useEffect(()=>{const g=v.current;if(g)return g.addEventListener(S,T),()=>g.removeEventListener(S,T)},[T]),t.jsx(Ue,{scope:s,orientation:r,dir:f,loop:n,currentTabStopId:b,onItemFocus:l.useCallback(g=>o(g),[o]),onItemShiftTab:l.useCallback(()=>j(!0),[]),onFocusableItemAdd:l.useCallback(()=>G(g=>g+1),[]),onFocusableItemRemove:l.useCallback(()=>G(g=>g-1),[]),children:t.jsx(E.div,{tabIndex:m||ue===0?-1:0,"data-orientation":r,...u,ref:N,style:{outline:"none",...e.style},onMouseDown:w(e.onMouseDown,()=>{D.current=!0}),onFocus:w(e.onFocus,g=>{const de=!D.current;if(g.target===g.currentTarget&&de&&!m){const M=new CustomEvent(S,Ae);if(g.currentTarget.dispatchEvent(M),!M.defaultPrevented){const R=ce().filter(y=>y.focusable),fe=R.find(y=>y.active),me=R.find(y=>y.id===b),xe=[fe,me,...R].filter(Boolean).map(y=>y.ref.current);X(xe,d)}}D.current=!1}),onBlur:w(e.onBlur,()=>j(!1))})})}),q="RovingFocusGroupItem",Q=l.forwardRef((e,a)=>{const{__scopeRovingFocusGroup:s,focusable:r=!0,active:n=!1,tabStopId:x,...i}=e,h=V(),p=x||h,c=Le(q,s),d=c.currentTabStopId===p,u=z(s),{onFocusableItemAdd:v,onFocusableItemRemove:N}=c;return l.useEffect(()=>{if(r)return v(),()=>N()},[r,v,N]),t.jsx(A.ItemSlot,{scope:s,id:p,focusable:r,active:n,children:t.jsx(E.span,{tabIndex:d?0:-1,"data-orientation":c.orientation,...i,ref:a,onMouseDown:w(e.onMouseDown,f=>{r?c.onItemFocus(p):f.preventDefault()}),onFocus:w(e.onFocus,()=>c.onItemFocus(p)),onKeyDown:w(e.onKeyDown,f=>{if(f.key==="Tab"&&f.shiftKey){c.onItemShiftTab();return}if(f.target!==f.currentTarget)return;const b=Ke(f,c.orientation,c.dir);if(b!==void 0){if(f.metaKey||f.ctrlKey||f.altKey||f.shiftKey)return;f.preventDefault();let m=u().filter(j=>j.focusable).map(j=>j.ref.current);if(b==="last")m.reverse();else if(b==="prev"||b==="next"){b==="prev"&&m.reverse();const j=m.indexOf(f.currentTarget);m=c.loop?Be(m,j+1):m.slice(j+1)}setTimeout(()=>X(m))}})})})});Q.displayName=q;var Me={ArrowLeft:"prev",ArrowUp:"prev",ArrowRight:"next",ArrowDown:"next",PageUp:"first",Home:"first",PageDown:"last",End:"last"};function Oe(e,a){return a!=="rtl"?e:e==="ArrowLeft"?"ArrowRight":e==="ArrowRight"?"ArrowLeft":e}function Ke(e,a,s){const r=Oe(e.key,s);if(!(a==="vertical"&&["ArrowLeft","ArrowRight"].includes(r))&&!(a==="horizontal"&&["ArrowUp","ArrowDown"].includes(r)))return Me[r]}function X(e,a=!1){const s=document.activeElement;for(const r of e)if(r===s||(r.focus({preventScroll:a}),document.activeElement!==s))return}function Be(e,a){return e.map((s,r)=>e[(a+r)%e.length])}var Ve=W,He=Q,U="Tabs",[$e,It]=K(U,[J]),Z=J(),[Ye,L]=$e(U),ee=l.forwardRef((e,a)=>{const{__scopeTabs:s,value:r,onValueChange:n,defaultValue:x,orientation:i="horizontal",dir:h,activationMode:p="automatic",...c}=e,d=H(h),[u,v]=B({prop:r,onChange:n,defaultProp:x});return t.jsx(Ye,{scope:s,baseId:V(),value:u,onValueChange:v,orientation:i,dir:d,activationMode:p,children:t.jsx(E.div,{dir:d,"data-orientation":i,...c,ref:a})})});ee.displayName=U;var te="TabsList",re=l.forwardRef((e,a)=>{const{__scopeTabs:s,loop:r=!0,...n}=e,x=L(te,s),i=Z(s);return t.jsx(Ve,{asChild:!0,...i,orientation:x.orientation,dir:x.dir,loop:r,children:t.jsx(E.div,{role:"tablist","aria-orientation":x.orientation,...n,ref:a})})});re.displayName=te;var se="TabsTrigger",ae=l.forwardRef((e,a)=>{const{__scopeTabs:s,value:r,disabled:n=!1,...x}=e,i=L(se,s),h=Z(s),p=ie(i.baseId,r),c=le(i.baseId,r),d=r===i.value;return t.jsx(He,{asChild:!0,...h,focusable:!n,active:d,children:t.jsx(E.button,{type:"button",role:"tab","aria-selected":d,"aria-controls":c,"data-state":d?"active":"inactive","data-disabled":n?"":void 0,disabled:n,id:p,...x,ref:a,onMouseDown:w(e.onMouseDown,u=>{!n&&u.button===0&&u.ctrlKey===!1?i.onValueChange(r):u.preventDefault()}),onKeyDown:w(e.onKeyDown,u=>{[" ","Enter"].includes(u.key)&&i.onValueChange(r)}),onFocus:w(e.onFocus,()=>{const u=i.activationMode!=="manual";!d&&!n&&u&&i.onValueChange(r)})})})});ae.displayName=se;var oe="TabsContent",ne=l.forwardRef((e,a)=>{const{__scopeTabs:s,value:r,forceMount:n,children:x,...i}=e,h=L(oe,s),p=ie(h.baseId,r),c=le(h.baseId,r),d=r===h.value,u=l.useRef(d);return l.useEffect(()=>{const v=requestAnimationFrame(()=>u.current=!1);return()=>cancelAnimationFrame(v)},[]),t.jsx(ge,{present:n||d,children:({present:v})=>t.jsx(E.div,{"data-state":d?"active":"inactive","data-orientation":h.orientation,role:"tabpanel","aria-labelledby":p,hidden:!v,id:c,tabIndex:0,...i,ref:a,style:{...e.style,animationDuration:u.current?"0s":void 0},children:v&&x})})});ne.displayName=oe;function ie(e,a){return`${e}-trigger-${a}`}function le(e,a){return`${e}-content-${a}`}var ze=ee,Je=re,We=ae,C=ne;function qe(){const e=k();return t.jsxs("div",{className:"flex h-full w-full flex-col gap-4 pt-4",children:[t.jsx("div",{className:"text-center",children:t.jsx(Ce,{discordAuthUrl:e.discordAuthUrl})}),t.jsx("div",{className:"flex-1 overflow-y-scroll bg-accent pb-4 scrollbar-thin scrollbar-thumb-scrollbar",children:t.jsx(Qe,{})})]})}function Qe(){const e=k(),a=Ee({discordAuthUrl:e.discordAuthUrl}),s=$();return t.jsxs("div",{className:"flex h-full flex-col items-center justify-between",children:[t.jsx(l.Suspense,{fallback:t.jsx("div",{className:"flex h-full w-full flex-col items-center justify-center",children:t.jsx(Te,{children:"Loading Discord Posts"})}),children:t.jsx(Pe,{resolve:e.discordPostsPromise,errorElement:t.jsx("div",{className:"text-red-500",children:"There was a problem loading the discord posts"}),children:r=>t.jsx("ul",{className:"flex w-full flex-col gap-4 p-3 xl:p-12",children:r.map(n=>t.jsx("li",{className:"rounded-xl border bg-background transition-all duration-200 focus-within:-translate-y-1 focus-within:shadow-lg hover:-translate-y-1 hover:shadow-lg",children:t.jsx(Xe,{thread:n})},n.id))})})}),t.jsx("div",{children:t.jsxs(Y,{to:s&&!a.includes("oauth")?a.replace(/^https/,"discord"):a,target:a.includes("oauth")?void 0:"_blank",rel:"noreferrer noopener",onClick:s?r=>{r.preventDefault(),window.open(r.currentTarget.href,"_blank","noreferrer noopener")}:void 0,className:"flex items-center gap-2 p-2 text-xl hover:underline",children:["Create Post ",t.jsx(P,{name:"ExternalLink"})]})})]})}function Xe({thread:e}){const a=e.reactions.filter(s=>s.count);return t.jsx("div",{children:t.jsxs("div",{className:"flex flex-col gap-2 p-4",children:[t.jsxs("div",{className:"flex gap-4",children:[t.jsxs("div",{className:"flex flex-col gap-1",children:[e.tags.length?t.jsx("div",{className:"flex gap-2",children:e.tags.map(s=>t.jsxs("div",{className:"flex items-center justify-center gap-1 rounded-full bg-accent px-2 py-1 text-sm",children:[t.jsx("span",{className:"h-3 w-3 leading-3",children:t.jsx(O,{name:s.emojiName,url:s.emojiUrl})}),t.jsx("span",{children:s.name})]},s.name))}):null,t.jsx("strong",{className:"text-xl font-bold",children:e.name}),t.jsxs("div",{className:"flex items-start gap-1",children:[t.jsxs("div",{className:"flex items-center gap-1",children:[e.authorAvatarUrl?t.jsx("img",{src:e.authorAvatarUrl,alt:"",className:"h-6 w-6 rounded-full"}):null,t.jsxs("span",{children:[t.jsx("span",{className:"font-bold",style:e.authorHexAccentColor?{color:e.authorHexAccentColor}:{},children:e.authorDisplayName}),":"," "]})]}),t.jsx("span",{className:"flex-1 overflow-ellipsis text-muted-foreground",children:e.messagePreview})]})]}),e.previewImageUrl?t.jsx("img",{src:e.previewImageUrl,alt:"",className:"h-28 w-28 rounded-lg object-cover"}):null]}),t.jsxs("div",{className:"flex justify-between",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("span",{children:a.length?t.jsx("ul",{className:"flex items-center gap-2",children:a.map((s,r)=>t.jsxs("li",{className:"flex items-center gap-1 rounded-md border border-blue-600 bg-blue-500/20 px-[5px] py-[0.5px] text-sm",children:[t.jsx("span",{className:"h-3 w-3 leading-3",children:t.jsx(O,{name:s.emojiName,url:s.emojiUrl})}),t.jsx("span",{children:s.count})]},r))}):null}),t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.jsx(P,{name:"Chat"})," ",e.messageCount]}),` · ${e.lastUpdatedDisplay}`]})]}),t.jsxs("span",{className:"flex items-center gap-4",children:[t.jsx("a",{href:e.link.replace(/^https/,"discord"),children:t.jsx(P,{name:"Discord"})}),t.jsx("a",{href:e.link,target:"_blank",rel:"noreferrer noopener",children:t.jsx(P,{name:"ExternalLink"})})]})]})]})})}function O({name:e,url:a}){return a?t.jsx("img",{src:a,alt:e,className:"h-full w-full"}):e||null}function Ze({appInfo:e,inBrowserBrowserRef:a,problemAppName:s,allApps:r,isUpToDate:n}){return t.jsx(Se,{playgroundAppName:e==null?void 0:e.appName,problemAppName:s,allApps:r,isUpToDate:n,children:(e==null?void 0:e.dev.type)==="none"?t.jsxs("div",{children:[t.jsx("div",{className:"text-foreground-secondary flex h-full items-center justify-center text-2xl",children:"Non-UI playground"}),t.jsx("div",{children:t.jsxs("div",{className:"text-foreground-secondary flex flex-wrap gap-1 text-center",children:["Navigate to"," ",t.jsx(je,{content:e.fullPath,children:t.jsx("span",{className:"underline",onClick:()=>{navigator.clipboard.writeText(e.fullPath),De.success("Copied playground path to clipboard")},children:"the playground directory"})})," ","in your editor and terminal to work on this exercise!"]})})]}):e?t.jsx(F,{id:e.appName,appInfo:e,inBrowserBrowserRef:a}):t.jsxs("div",{className:"flex flex-col justify-center gap-2",children:[t.jsx("p",{children:"Please set the playground first"}),s?t.jsx(Re,{appName:s}):null]})})}const _=["playground","problem","solution","tests","diff","chat"],et=e=>!!(e&&_.includes(e));function tt(e,a,s){const r=new URLSearchParams(e);return s===null?r.delete(a):r.set(a,s),r}function Dt(){var d,u,v,N,f,b;const e=k(),[a]=Ie(),s=a.get("preview"),r=l.useRef(null),n=$(),x=pe();function i(o){var m,j,T;if(o==="tests")return ENV.EPICSHOP_DEPLOYED||!e.playground||e.playground.test.type==="none";if(o==="problem"||o==="solution"){if(((m=e[o])==null?void 0:m.dev.type)==="none")return!0;if(ENV.EPICSHOP_DEPLOYED)return((j=e[o])==null?void 0:j.dev.type)!=="browser"&&!((T=e[o])!=null&&T.stackBlitzUrl)}return!!(o==="playground"&&ENV.EPICSHOP_DEPLOYED)}const h=et(s)?s:_.find(o=>!i(o)),p=`/diff?${new URLSearchParams({app1:((d=e.problem)==null?void 0:d.name)??"",app2:((u=e.solution)==null?void 0:u.name)??""})}`;function c(o){o.altKey&&!o.ctrlKey&&!o.shiftKey&&!o.metaKey&&(o.preventDefault(),x(p))}return t.jsxs(ze,{className:"relative flex flex-col overflow-y-auto sm:col-span-1 sm:row-span-1",value:h,children:[t.jsx(Je,{className:"h-14 min-h-14 overflow-x-hidden border-b scrollbar-thin scrollbar-thumb-scrollbar",children:_.map(o=>{const m=i(o);return t.jsx(We,{value:o,hidden:m,asChild:!0,children:t.jsx(Y,{id:`${o}-tab`,className:we("clip-path-button relative h-full px-6 py-4 font-mono text-sm uppercase outline-none radix-state-active:z-10 radix-state-active:bg-foreground radix-state-active:text-background radix-state-active:hover:bg-foreground/80 radix-state-active:hover:text-background/80 radix-state-inactive:hover:bg-foreground/20 radix-state-inactive:hover:text-foreground/80 focus:bg-foreground/80 focus:text-background/80",m?"hidden":"inline-block"),preventScrollReset:!0,prefetch:"intent",onClick:c,to:o==="diff"&&n?p:`?${tt(a,"preview",o==="playground"?null:o)}`,children:o})},o)})}),t.jsxs("div",{className:"relative z-10 flex min-h-96 flex-grow flex-col overflow-y-auto",children:[t.jsx(C,{value:"playground",className:"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden",children:t.jsx(Ze,{appInfo:e.playground,problemAppName:(v=e.problem)==null?void 0:v.name,inBrowserBrowserRef:r,allApps:e.allApps,isUpToDate:((N=e.playground)==null?void 0:N.isUpToDate)??!1})}),t.jsx(C,{value:"problem",className:"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden",children:t.jsx(F,{appInfo:e.problem,inBrowserBrowserRef:r})}),t.jsx(C,{value:"solution",className:"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden",children:t.jsx(F,{appInfo:e.solution,inBrowserBrowserRef:r})}),t.jsx(C,{value:"tests",className:"flex w-full flex-grow items-start justify-center self-start overflow-hidden radix-state-inactive:hidden",children:t.jsx(Fe,{appInfo:e.playground,problemAppName:(f=e.problem)==null?void 0:f.name,allApps:e.allApps,isUpToDate:((b=e.playground)==null?void 0:b.isUpToDate)??!1})}),t.jsx(C,{value:"diff",className:"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden",children:t.jsx(Ne,{diff:e.diff,allApps:e.allApps})}),t.jsx(C,{value:"chat",className:"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden",children:t.jsx(qe,{})})]})]})}function Rt(){return t.jsx(ye,{statusHandlers:{404:()=>t.jsx("p",{children:"Sorry, we couldn't find an app here."})}})}export{Rt as ErrorBoundary,Dt as default};
2
+ //# sourceMappingURL=index-CsPok4Mn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-DoUR7StN.js","sources":["../../../../../node_modules/@radix-ui/react-roving-focus/dist/index.mjs","../../../../../node_modules/@radix-ui/react-tabs/dist/index.mjs","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/discord.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/playground.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index.tsx"],"sourcesContent":["\"use client\";\n\n// packages/react/roving-focus/src/RovingFocusGroup.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { createCollection } from \"@radix-ui/react-collection\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { jsx } from \"react/jsx-runtime\";\nvar ENTRY_FOCUS = \"rovingFocusGroup.onEntryFocus\";\nvar EVENT_OPTIONS = { bubbles: false, cancelable: true };\nvar GROUP_NAME = \"RovingFocusGroup\";\nvar [Collection, useCollection, createCollectionScope] = createCollection(GROUP_NAME);\nvar [createRovingFocusGroupContext, createRovingFocusGroupScope] = createContextScope(\n GROUP_NAME,\n [createCollectionScope]\n);\nvar [RovingFocusProvider, useRovingFocusContext] = createRovingFocusGroupContext(GROUP_NAME);\nvar RovingFocusGroup = React.forwardRef(\n (props, forwardedRef) => {\n return /* @__PURE__ */ jsx(Collection.Provider, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx(Collection.Slot, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx(RovingFocusGroupImpl, { ...props, ref: forwardedRef }) }) });\n }\n);\nRovingFocusGroup.displayName = GROUP_NAME;\nvar RovingFocusGroupImpl = React.forwardRef((props, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n orientation,\n loop = false,\n dir,\n currentTabStopId: currentTabStopIdProp,\n defaultCurrentTabStopId,\n onCurrentTabStopIdChange,\n onEntryFocus,\n preventScrollOnEntryFocus = false,\n ...groupProps\n } = props;\n const ref = React.useRef(null);\n const composedRefs = useComposedRefs(forwardedRef, ref);\n const direction = useDirection(dir);\n const [currentTabStopId = null, setCurrentTabStopId] = useControllableState({\n prop: currentTabStopIdProp,\n defaultProp: defaultCurrentTabStopId,\n onChange: onCurrentTabStopIdChange\n });\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const handleEntryFocus = useCallbackRef(onEntryFocus);\n const getItems = useCollection(__scopeRovingFocusGroup);\n const isClickFocusRef = React.useRef(false);\n const [focusableItemsCount, setFocusableItemsCount] = React.useState(0);\n React.useEffect(() => {\n const node = ref.current;\n if (node) {\n node.addEventListener(ENTRY_FOCUS, handleEntryFocus);\n return () => node.removeEventListener(ENTRY_FOCUS, handleEntryFocus);\n }\n }, [handleEntryFocus]);\n return /* @__PURE__ */ jsx(\n RovingFocusProvider,\n {\n scope: __scopeRovingFocusGroup,\n orientation,\n dir: direction,\n loop,\n currentTabStopId,\n onItemFocus: React.useCallback(\n (tabStopId) => setCurrentTabStopId(tabStopId),\n [setCurrentTabStopId]\n ),\n onItemShiftTab: React.useCallback(() => setIsTabbingBackOut(true), []),\n onFocusableItemAdd: React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount + 1),\n []\n ),\n onFocusableItemRemove: React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount - 1),\n []\n ),\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n tabIndex: isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0,\n \"data-orientation\": orientation,\n ...groupProps,\n ref: composedRefs,\n style: { outline: \"none\", ...props.style },\n onMouseDown: composeEventHandlers(props.onMouseDown, () => {\n isClickFocusRef.current = true;\n }),\n onFocus: composeEventHandlers(props.onFocus, (event) => {\n const isKeyboardFocus = !isClickFocusRef.current;\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n if (!entryFocusEvent.defaultPrevented) {\n const items = getItems().filter((item) => item.focusable);\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === currentTabStopId);\n const candidateItems = [activeItem, currentItem, ...items].filter(\n Boolean\n );\n const candidateNodes = candidateItems.map((item) => item.ref.current);\n focusFirst(candidateNodes, preventScrollOnEntryFocus);\n }\n }\n isClickFocusRef.current = false;\n }),\n onBlur: composeEventHandlers(props.onBlur, () => setIsTabbingBackOut(false))\n }\n )\n }\n );\n});\nvar ITEM_NAME = \"RovingFocusGroupItem\";\nvar RovingFocusGroupItem = React.forwardRef(\n (props, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n focusable = true,\n active = false,\n tabStopId,\n ...itemProps\n } = props;\n const autoId = useId();\n const id = tabStopId || autoId;\n const context = useRovingFocusContext(ITEM_NAME, __scopeRovingFocusGroup);\n const isCurrentTabStop = context.currentTabStopId === id;\n const getItems = useCollection(__scopeRovingFocusGroup);\n const { onFocusableItemAdd, onFocusableItemRemove } = context;\n React.useEffect(() => {\n if (focusable) {\n onFocusableItemAdd();\n return () => onFocusableItemRemove();\n }\n }, [focusable, onFocusableItemAdd, onFocusableItemRemove]);\n return /* @__PURE__ */ jsx(\n Collection.ItemSlot,\n {\n scope: __scopeRovingFocusGroup,\n id,\n focusable,\n active,\n children: /* @__PURE__ */ jsx(\n Primitive.span,\n {\n tabIndex: isCurrentTabStop ? 0 : -1,\n \"data-orientation\": context.orientation,\n ...itemProps,\n ref: forwardedRef,\n onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {\n if (!focusable) event.preventDefault();\n else context.onItemFocus(id);\n }),\n onFocus: composeEventHandlers(props.onFocus, () => context.onItemFocus(id)),\n onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {\n if (event.key === \"Tab\" && event.shiftKey) {\n context.onItemShiftTab();\n return;\n }\n if (event.target !== event.currentTarget) return;\n const focusIntent = getFocusIntent(event, context.orientation, context.dir);\n if (focusIntent !== void 0) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n const items = getItems().filter((item) => item.focusable);\n let candidateNodes = items.map((item) => item.ref.current);\n if (focusIntent === \"last\") candidateNodes.reverse();\n else if (focusIntent === \"prev\" || focusIntent === \"next\") {\n if (focusIntent === \"prev\") candidateNodes.reverse();\n const currentIndex = candidateNodes.indexOf(event.currentTarget);\n candidateNodes = context.loop ? wrapArray(candidateNodes, currentIndex + 1) : candidateNodes.slice(currentIndex + 1);\n }\n setTimeout(() => focusFirst(candidateNodes));\n }\n })\n }\n )\n }\n );\n }\n);\nRovingFocusGroupItem.displayName = ITEM_NAME;\nvar MAP_KEY_TO_FOCUS_INTENT = {\n ArrowLeft: \"prev\",\n ArrowUp: \"prev\",\n ArrowRight: \"next\",\n ArrowDown: \"next\",\n PageUp: \"first\",\n Home: \"first\",\n PageDown: \"last\",\n End: \"last\"\n};\nfunction getDirectionAwareKey(key, dir) {\n if (dir !== \"rtl\") return key;\n return key === \"ArrowLeft\" ? \"ArrowRight\" : key === \"ArrowRight\" ? \"ArrowLeft\" : key;\n}\nfunction getFocusIntent(event, orientation, dir) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === \"vertical\" && [\"ArrowLeft\", \"ArrowRight\"].includes(key)) return void 0;\n if (orientation === \"horizontal\" && [\"ArrowUp\", \"ArrowDown\"].includes(key)) return void 0;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\nfunction focusFirst(candidates, preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidate of candidates) {\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\nfunction wrapArray(array, startIndex) {\n return array.map((_, index) => array[(startIndex + index) % array.length]);\n}\nvar Root = RovingFocusGroup;\nvar Item = RovingFocusGroupItem;\nexport {\n Item,\n Root,\n RovingFocusGroup,\n RovingFocusGroupItem,\n createRovingFocusGroupScope\n};\n//# sourceMappingURL=index.mjs.map\n","\"use client\";\n\n// packages/react/tabs/src/Tabs.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { createRovingFocusGroupScope } from \"@radix-ui/react-roving-focus\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as RovingFocusGroup from \"@radix-ui/react-roving-focus\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { jsx } from \"react/jsx-runtime\";\nvar TABS_NAME = \"Tabs\";\nvar [createTabsContext, createTabsScope] = createContextScope(TABS_NAME, [\n createRovingFocusGroupScope\n]);\nvar useRovingFocusGroupScope = createRovingFocusGroupScope();\nvar [TabsProvider, useTabsContext] = createTabsContext(TABS_NAME);\nvar Tabs = React.forwardRef(\n (props, forwardedRef) => {\n const {\n __scopeTabs,\n value: valueProp,\n onValueChange,\n defaultValue,\n orientation = \"horizontal\",\n dir,\n activationMode = \"automatic\",\n ...tabsProps\n } = props;\n const direction = useDirection(dir);\n const [value, setValue] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n defaultProp: defaultValue\n });\n return /* @__PURE__ */ jsx(\n TabsProvider,\n {\n scope: __scopeTabs,\n baseId: useId(),\n value,\n onValueChange: setValue,\n orientation,\n dir: direction,\n activationMode,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n dir: direction,\n \"data-orientation\": orientation,\n ...tabsProps,\n ref: forwardedRef\n }\n )\n }\n );\n }\n);\nTabs.displayName = TABS_NAME;\nvar TAB_LIST_NAME = \"TabsList\";\nvar TabsList = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, loop = true, ...listProps } = props;\n const context = useTabsContext(TAB_LIST_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Root,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n orientation: context.orientation,\n dir: context.dir,\n loop,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n role: \"tablist\",\n \"aria-orientation\": context.orientation,\n ...listProps,\n ref: forwardedRef\n }\n )\n }\n );\n }\n);\nTabsList.displayName = TAB_LIST_NAME;\nvar TRIGGER_NAME = \"TabsTrigger\";\nvar TabsTrigger = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, value, disabled = false, ...triggerProps } = props;\n const context = useTabsContext(TRIGGER_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Item,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n focusable: !disabled,\n active: isSelected,\n children: /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n role: \"tab\",\n \"aria-selected\": isSelected,\n \"aria-controls\": contentId,\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-disabled\": disabled ? \"\" : void 0,\n disabled,\n id: triggerId,\n ...triggerProps,\n ref: forwardedRef,\n onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {\n if (!disabled && event.button === 0 && event.ctrlKey === false) {\n context.onValueChange(value);\n } else {\n event.preventDefault();\n }\n }),\n onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {\n if ([\" \", \"Enter\"].includes(event.key)) context.onValueChange(value);\n }),\n onFocus: composeEventHandlers(props.onFocus, () => {\n const isAutomaticActivation = context.activationMode !== \"manual\";\n if (!isSelected && !disabled && isAutomaticActivation) {\n context.onValueChange(value);\n }\n })\n }\n )\n }\n );\n }\n);\nTabsTrigger.displayName = TRIGGER_NAME;\nvar CONTENT_NAME = \"TabsContent\";\nvar TabsContent = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, value, forceMount, children, ...contentProps } = props;\n const context = useTabsContext(CONTENT_NAME, __scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n const isMountAnimationPreventedRef = React.useRef(isSelected);\n React.useEffect(() => {\n const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);\n return () => cancelAnimationFrame(rAF);\n }, []);\n return /* @__PURE__ */ jsx(Presence, { present: forceMount || isSelected, children: ({ present }) => /* @__PURE__ */ jsx(\n Primitive.div,\n {\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-orientation\": context.orientation,\n role: \"tabpanel\",\n \"aria-labelledby\": triggerId,\n hidden: !present,\n id: contentId,\n tabIndex: 0,\n ...contentProps,\n ref: forwardedRef,\n style: {\n ...props.style,\n animationDuration: isMountAnimationPreventedRef.current ? \"0s\" : void 0\n },\n children: present && children\n }\n ) });\n }\n);\nTabsContent.displayName = CONTENT_NAME;\nfunction makeTriggerId(baseId, value) {\n return `${baseId}-trigger-${value}`;\n}\nfunction makeContentId(baseId, value) {\n return `${baseId}-content-${value}`;\n}\nvar Root2 = Tabs;\nvar List = TabsList;\nvar Trigger = TabsTrigger;\nvar Content = TabsContent;\nexport {\n Content,\n List,\n Root2 as Root,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Trigger,\n createTabsScope\n};\n//# sourceMappingURL=index.mjs.map\n","import { type SerializeFrom } from '@remix-run/node'\nimport { Await, Link, useLoaderData } from '@remix-run/react'\nimport * as React from 'react'\nimport { Icon } from '#app/components/icons.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { useAltDown } from '#app/utils/misc.tsx'\nimport { DiscordCTA, useDiscordCTALink } from '../../../discord.tsx'\nimport { type loader } from '../index.tsx'\n\nexport function DiscordChat() {\n\tconst data = useLoaderData<typeof loader>()\n\treturn (\n\t\t<div className=\"flex h-full w-full flex-col gap-4 pt-4\">\n\t\t\t<div className=\"text-center\">\n\t\t\t\t<DiscordCTA discordAuthUrl={data.discordAuthUrl} />\n\t\t\t</div>\n\t\t\t<div className=\"flex-1 overflow-y-scroll bg-accent pb-4 scrollbar-thin scrollbar-thumb-scrollbar\">\n\t\t\t\t<DiscordPosts />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction DiscordPosts() {\n\tconst data = useLoaderData<typeof loader>()\n\tconst ctaLink = useDiscordCTALink({ discordAuthUrl: data.discordAuthUrl })\n\tconst altDown = useAltDown()\n\treturn (\n\t\t<div className=\"flex h-full flex-col items-center justify-between\">\n\t\t\t<React.Suspense\n\t\t\t\tfallback={\n\t\t\t\t\t<div className=\"flex h-full w-full flex-col items-center justify-center\">\n\t\t\t\t\t\t<Loading>Loading Discord Posts</Loading>\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t<Await\n\t\t\t\t\tresolve={data.discordPostsPromise}\n\t\t\t\t\terrorElement={\n\t\t\t\t\t\t<div className=\"text-red-500\">\n\t\t\t\t\t\t\tThere was a problem loading the discord posts\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t{(posts) => (\n\t\t\t\t\t\t<ul className=\"flex w-full flex-col gap-4 p-3 xl:p-12\">\n\t\t\t\t\t\t\t{posts.map((post) => (\n\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\tkey={post.id}\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-xl border bg-background transition-all duration-200 focus-within:-translate-y-1 focus-within:shadow-lg hover:-translate-y-1 hover:shadow-lg\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<DiscordPost thread={post} />\n\t\t\t\t\t\t\t\t</li>\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</Await>\n\t\t\t</React.Suspense>\n\t\t\t<div>\n\t\t\t\t<Link\n\t\t\t\t\tto={\n\t\t\t\t\t\taltDown && !ctaLink.includes('oauth')\n\t\t\t\t\t\t\t? ctaLink.replace(/^https/, 'discord')\n\t\t\t\t\t\t\t: ctaLink\n\t\t\t\t\t}\n\t\t\t\t\ttarget={ctaLink.includes('oauth') ? undefined : '_blank'}\n\t\t\t\t\trel=\"noreferrer noopener\"\n\t\t\t\t\tonClick={\n\t\t\t\t\t\taltDown\n\t\t\t\t\t\t\t? (e) => {\n\t\t\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\t\t\twindow.open(\n\t\t\t\t\t\t\t\t\t\te.currentTarget.href,\n\t\t\t\t\t\t\t\t\t\t'_blank',\n\t\t\t\t\t\t\t\t\t\t'noreferrer noopener',\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tclassName=\"flex items-center gap-2 p-2 text-xl hover:underline\"\n\t\t\t\t>\n\t\t\t\t\tCreate Post <Icon name=\"ExternalLink\" />\n\t\t\t\t</Link>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction DiscordPost({\n\tthread,\n}: {\n\tthread: Awaited<SerializeFrom<typeof loader>['discordPostsPromise']>[number]\n}) {\n\tconst reactionsWithCounts = thread.reactions.filter((r) => r.count)\n\n\treturn (\n\t\t<div>\n\t\t\t<div className=\"flex flex-col gap-2 p-4\">\n\t\t\t\t<div className=\"flex gap-4\">\n\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t{thread.tags.length ? (\n\t\t\t\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t\t\t\t{thread.tags.map((t) => (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tkey={t.name}\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-center gap-1 rounded-full bg-accent px-2 py-1 text-sm\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span className=\"h-3 w-3 leading-3\">\n\t\t\t\t\t\t\t\t\t\t\t{/* not sure how to fix this one... */}\n\t\t\t\t\t\t\t\t\t\t\t{/* @ts-expect-error */}\n\t\t\t\t\t\t\t\t\t\t\t<Emoji name={t.emojiName} url={t.emojiUrl} />\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t<span>{t.name}</span>\n\t\t\t\t\t\t\t\t\t</div>\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) : null}\n\t\t\t\t\t\t<strong className=\"text-xl font-bold\">{thread.name}</strong>\n\t\t\t\t\t\t<div className=\"flex items-start gap-1\">\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t\t{thread.authorAvatarUrl ? (\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tsrc={thread.authorAvatarUrl}\n\t\t\t\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6 rounded-full\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclassName=\"font-bold\"\n\t\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\t\tthread.authorHexAccentColor\n\t\t\t\t\t\t\t\t\t\t\t\t? { color: thread.authorHexAccentColor }\n\t\t\t\t\t\t\t\t\t\t\t\t: {}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{thread.authorDisplayName}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t:{' '}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<span className=\"flex-1 overflow-ellipsis text-muted-foreground\">\n\t\t\t\t\t\t\t\t{thread.messagePreview}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{thread.previewImageUrl ? (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={thread.previewImageUrl}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tclassName=\"h-28 w-28 rounded-lg object-cover\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"flex justify-between\">\n\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t{reactionsWithCounts.length ? (\n\t\t\t\t\t\t\t\t<ul className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t{reactionsWithCounts.map((r, i) => (\n\t\t\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center gap-1 rounded-md border border-blue-600 bg-blue-500/20 px-[5px] py-[0.5px] text-sm\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"h-3 w-3 leading-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t{/* not sure how to fix this one... */}\n\t\t\t\t\t\t\t\t\t\t\t\t{/* @ts-expect-error */}\n\t\t\t\t\t\t\t\t\t\t\t\t<Emoji name={r.emojiName} url={r.emojiUrl} />\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t<span>{r.count}</span>\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t<span className=\"inline-flex items-center gap-1\">\n\t\t\t\t\t\t\t\t<Icon name=\"Chat\" /> {thread.messageCount}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{` · ${thread.lastUpdatedDisplay}`}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span className=\"flex items-center gap-4\">\n\t\t\t\t\t\t<a href={thread.link.replace(/^https/, 'discord')}>\n\t\t\t\t\t\t\t<Icon name=\"Discord\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<a href={thread.link} target=\"_blank\" rel=\"noreferrer noopener\">\n\t\t\t\t\t\t\t<Icon name=\"ExternalLink\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction Emoji({ name, url }: { name?: string; url?: string }) {\n\treturn url ? (\n\t\t<img src={url} alt={name} className=\"h-full w-full\" />\n\t) : name ? (\n\t\tname\n\t) : null\n}\n","import { toast as showToast } from 'sonner'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser'\nimport { SimpleTooltip } from '#app/components/ui/tooltip'\nimport { SetAppToPlayground } from '#app/routes/set-playground'\nimport { PlaygroundWindow } from './playground-window'\nimport { Preview } from './preview'\n\nexport function Playground({\n\tappInfo: playgroundAppInfo,\n\tinBrowserBrowserRef,\n\tproblemAppName,\n\tallApps,\n\tisUpToDate,\n}: {\n\tappInfo: Parameters<typeof Preview>['0']['appInfo'] | null\n\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n\tproblemAppName?: string\n\tallApps: Array<{ name: string; displayName: string }>\n\tisUpToDate: boolean\n}) {\n\treturn (\n\t\t<PlaygroundWindow\n\t\t\tplaygroundAppName={playgroundAppInfo?.appName}\n\t\t\tproblemAppName={problemAppName}\n\t\t\tallApps={allApps}\n\t\t\tisUpToDate={isUpToDate}\n\t\t>\n\t\t\t{playgroundAppInfo?.dev.type === 'none' ? (\n\t\t\t\t<div>\n\t\t\t\t\t<div className=\"text-foreground-secondary flex h-full items-center justify-center text-2xl\">\n\t\t\t\t\t\tNon-UI playground\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"text-foreground-secondary flex flex-wrap gap-1 text-center\">\n\t\t\t\t\t\t\tNavigate to{' '}\n\t\t\t\t\t\t\t<SimpleTooltip content={playgroundAppInfo.fullPath}>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tvoid navigator.clipboard.writeText(\n\t\t\t\t\t\t\t\t\t\t\tplaygroundAppInfo.fullPath,\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\tshowToast.success('Copied playground path to clipboard')\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tthe playground directory\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</SimpleTooltip>{' '}\n\t\t\t\t\t\t\tin your editor and terminal to work on this exercise!\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : playgroundAppInfo ? (\n\t\t\t\t<Preview\n\t\t\t\t\tid={playgroundAppInfo.appName}\n\t\t\t\t\tappInfo={playgroundAppInfo}\n\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex flex-col justify-center gap-2\">\n\t\t\t\t\t<p>Please set the playground first</p>\n\t\t\t\t\t{problemAppName ? (\n\t\t\t\t\t\t<SetAppToPlayground appName={problemAppName} />\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</PlaygroundWindow>\n\t)\n}\n","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 { compileMarkdownString } from '@epic-web/workshop-utils/compile-mdx.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 {\n\tdefer,\n\tredirect,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n} from '@remix-run/node'\nimport {\n\tLink,\n\tuseLoaderData,\n\tuseNavigate,\n\tuseSearchParams,\n} from '@remix-run/react'\nimport { clsx } from 'clsx'\nimport * as React from 'react'\nimport { useRef } from 'react'\nimport { Diff } from '#app/components/diff.tsx'\nimport { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser.tsx'\nimport { getDiscordAuthURL } from '#app/routes/discord.callback.ts'\nimport { getDiffCode } from '#app/utils/diff.server.ts'\nimport { userHasAccessToWorkshop } from '#app/utils/epic-api.js'\nimport { useAltDown } from '#app/utils/misc.tsx'\nimport { fetchDiscordPosts } from './__shared/discord.server.ts'\nimport { DiscordChat } from './__shared/discord.tsx'\nimport { Playground } from './__shared/playground.tsx'\nimport { Preview } from './__shared/preview.tsx'\nimport { Tests } from './__shared/tests.tsx'\nimport { getAppRunningState } from './__shared/utils.tsx'\n\nexport async function loader({ request, params }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('exerciseStepTypeLoader')\n\tconst userHasAccess = await userHasAccessToWorkshop({\n\t\trequest,\n\t\ttimings,\n\t})\n\tconst searchParams = new URL(request.url).searchParams\n\tconst cacheOptions = { request, timings }\n\tconst exerciseStepApp = await requireExerciseApp(params, cacheOptions)\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 problemApp = await getExerciseApp(\n\t\t{ ...params, type: 'problem' },\n\t\tcacheOptions,\n\t)\n\tconst solutionApp = await getExerciseApp(\n\t\t{ ...params, type: 'solution' },\n\t\tcacheOptions,\n\t)\n\n\tif (!problemApp && !solutionApp) {\n\t\tthrow new Response('Not found', { status: 404 })\n\t}\n\n\tconst allAppsFull = await getApps(cacheOptions)\n\tconst playgroundApp = allAppsFull.find(isPlaygroundApp)\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\tif (!userHasAccess) {\n\t\t\treturn {\n\t\t\t\tapp1: app1?.name,\n\t\t\t\tapp2: app2?.name,\n\t\t\t\tdiffCode: await compileMarkdownString(\n\t\t\t\t\t`\n\t\t\t\t\t<div className=\"flex flex-col items-center justify-center p-4\">\n\t\t\t\t\t\t<p className=\"text-2xl font-bold\">Purchase Required</p>\n\t\t\t\t\t\t<p>You must purchase the workshop to view the diff.</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t`,\n\t\t\t\t\t// TODO: add a video demonstrating the diff feature\n\t\t\t\t),\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 defer(\n\t\t{\n\t\t\ttype: params.type as 'problem' | 'solution',\n\t\t\texerciseStepApp,\n\t\t\tallApps,\n\t\t\tdiscordAuthUrl: getDiscordAuthURL(),\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\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} 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\nfunction withParam(\n\tsearchParams: URLSearchParams,\n\tkey: string,\n\tvalue: string | null,\n) {\n\tconst newSearchParams = new URLSearchParams(searchParams)\n\tif (value === null) {\n\t\tnewSearchParams.delete(key)\n\t} else {\n\t\tnewSearchParams.set(key, value)\n\t}\n\treturn newSearchParams\n}\n\nexport default function ExercisePartRoute() {\n\tconst data = useLoaderData<typeof loader>()\n\tconst [searchParams] = useSearchParams()\n\n\tconst preview = searchParams.get('preview')\n\tconst inBrowserBrowserRef = useRef<InBrowserBrowserRef>(null)\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!data.playground ||\n\t\t\t\tdata.playground.test.type === 'none'\n\t\t\t)\n\t\t}\n\t\tif (tab === 'problem' || tab === 'solution') {\n\t\t\tif (data[tab]?.dev.type === 'none') return true\n\t\t\tif (ENV.EPICSHOP_DEPLOYED) {\n\t\t\t\treturn data[tab]?.dev.type !== 'browser' && !data[tab]?.stackBlitzUrl\n\t\t\t}\n\t\t}\n\t\tif (tab === 'playground' && ENV.EPICSHOP_DEPLOYED) return true\n\t\treturn false\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: data.problem?.name ?? '',\n\t\tapp2: data.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\tnavigate(altDiffUrl)\n\t\t}\n\t}\n\n\treturn (\n\t\t<Tabs.Root\n\t\t\tclassName=\"relative flex flex-col overflow-y-auto 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<Tabs.List className=\"h-14 min-h-14 overflow-x-hidden border-b scrollbar-thin scrollbar-thumb-scrollbar\">\n\t\t\t\t{tabs.map((tab) => {\n\t\t\t\t\tconst hidden = shouldHideTab(tab)\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Tabs.Trigger key={tab} value={tab} hidden={hidden} asChild>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tid={`${tab}-tab`}\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'clip-path-button relative h-full px-6 py-4 font-mono text-sm uppercase outline-none radix-state-active:z-10 radix-state-active:bg-foreground radix-state-active:text-background radix-state-active:hover:bg-foreground/80 radix-state-active:hover:text-background/80 radix-state-inactive:hover:bg-foreground/20 radix-state-inactive:hover:text-foreground/80 focus:bg-foreground/80 focus:text-background/80',\n\t\t\t\t\t\t\t\t\thidden ? 'hidden' : 'inline-block',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tpreventScrollReset\n\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\tonClick={handleDiffTabClick}\n\t\t\t\t\t\t\t\tto={\n\t\t\t\t\t\t\t\t\ttab === 'diff' && altDown\n\t\t\t\t\t\t\t\t\t\t? altDiffUrl\n\t\t\t\t\t\t\t\t\t\t: `?${withParam(\n\t\t\t\t\t\t\t\t\t\t\t\tsearchParams,\n\t\t\t\t\t\t\t\t\t\t\t\t'preview',\n\t\t\t\t\t\t\t\t\t\t\t\ttab === 'playground' ? null : tab,\n\t\t\t\t\t\t\t\t\t\t\t)}`\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{tab}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t)\n\t\t\t\t})}\n\t\t\t</Tabs.List>\n\t\t\t<div className=\"relative z-10 flex min-h-96 flex-grow flex-col overflow-y-auto\">\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"playground\"\n\t\t\t\t\tclassName=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Playground\n\t\t\t\t\t\tappInfo={data.playground}\n\t\t\t\t\t\tproblemAppName={data.problem?.name}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t\tallApps={data.allApps}\n\t\t\t\t\t\tisUpToDate={data.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=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={data.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=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={data.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=\"flex w-full flex-grow items-start justify-center self-start overflow-hidden radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Tests\n\t\t\t\t\t\tappInfo={data.playground}\n\t\t\t\t\t\tproblemAppName={data.problem?.name}\n\t\t\t\t\t\tallApps={data.allApps}\n\t\t\t\t\t\tisUpToDate={data.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=\"diff\"\n\t\t\t\t\tclassName=\"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Diff diff={data.diff} allApps={data.allApps} />\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=\"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<DiscordChat />\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":["ENTRY_FOCUS","EVENT_OPTIONS","GROUP_NAME","Collection","useCollection","createCollectionScope","createCollection","createRovingFocusGroupContext","createRovingFocusGroupScope","createContextScope","RovingFocusProvider","useRovingFocusContext","RovingFocusGroup","React.forwardRef","props","forwardedRef","jsx","RovingFocusGroupImpl","__scopeRovingFocusGroup","orientation","loop","dir","currentTabStopIdProp","defaultCurrentTabStopId","onCurrentTabStopIdChange","onEntryFocus","preventScrollOnEntryFocus","groupProps","ref","React.useRef","composedRefs","useComposedRefs","direction","useDirection","currentTabStopId","setCurrentTabStopId","useControllableState","isTabbingBackOut","setIsTabbingBackOut","React.useState","handleEntryFocus","useCallbackRef","getItems","isClickFocusRef","focusableItemsCount","setFocusableItemsCount","React.useEffect","node","React.useCallback","tabStopId","prevCount","Primitive","composeEventHandlers","event","isKeyboardFocus","entryFocusEvent","items","item","activeItem","currentItem","candidateNodes","focusFirst","ITEM_NAME","RovingFocusGroupItem","focusable","active","itemProps","autoId","useId","id","context","isCurrentTabStop","onFocusableItemAdd","onFocusableItemRemove","focusIntent","getFocusIntent","currentIndex","wrapArray","MAP_KEY_TO_FOCUS_INTENT","getDirectionAwareKey","key","candidates","preventScroll","PREVIOUSLY_FOCUSED_ELEMENT","candidate","array","startIndex","_","index","Root","Item","TABS_NAME","createTabsContext","createTabsScope","useRovingFocusGroupScope","TabsProvider","useTabsContext","Tabs","__scopeTabs","valueProp","onValueChange","defaultValue","activationMode","tabsProps","value","setValue","TAB_LIST_NAME","TabsList","listProps","rovingFocusGroupScope","RovingFocusGroup.Root","TRIGGER_NAME","TabsTrigger","disabled","triggerProps","triggerId","makeTriggerId","contentId","makeContentId","isSelected","RovingFocusGroup.Item","isAutomaticActivation","CONTENT_NAME","TabsContent","forceMount","children","contentProps","isMountAnimationPreventedRef","rAF","Presence","present","baseId","Root2","List","Trigger","Content","DiscordChat","data","useLoaderData","jsxs","DiscordCTA","DiscordPosts","ctaLink","useDiscordCTALink","altDown","useAltDown","React.Suspense","Loading","Await","posts","post","DiscordPost","Link","e","Icon","thread","reactionsWithCounts","r","t","Emoji","i","name","url","Playground","playgroundAppInfo","inBrowserBrowserRef","problemAppName","allApps","isUpToDate","PlaygroundWindow","SimpleTooltip","showToast","Preview","SetAppToPlayground","tabs","isValidPreview","s","Boolean","includes","withParam","searchParams","newSearchParams","URLSearchParams","delete","set","ExercisePartRoute","useSearchParams","preview","get","useRef","navigate","useNavigate","shouldHideTab","tab","ENV","EPICSHOP_DEPLOYED","playground","test","type","dev","stackBlitzUrl","activeTab","find","altDiffUrl","app1","problem","app2","solution","handleDiffTabClick","altKey","ctrlKey","shiftKey","metaKey","preventDefault","className","map","hidden","asChild","clsx","preventScrollReset","prefetch","onClick","to","appInfo","Tests","Diff","diff","ErrorBoundary","GeneralErrorBoundary","statusHandlers"],"mappings":"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","x_google_ignoreList":[0,1]}
1
+ {"version":3,"file":"index-CsPok4Mn.js","sources":["../../../../../node_modules/@radix-ui/react-roving-focus/dist/index.mjs","../../../../../node_modules/@radix-ui/react-tabs/dist/index.mjs","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/discord.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/playground.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index.tsx"],"sourcesContent":["\"use client\";\n\n// packages/react/roving-focus/src/RovingFocusGroup.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { createCollection } from \"@radix-ui/react-collection\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { jsx } from \"react/jsx-runtime\";\nvar ENTRY_FOCUS = \"rovingFocusGroup.onEntryFocus\";\nvar EVENT_OPTIONS = { bubbles: false, cancelable: true };\nvar GROUP_NAME = \"RovingFocusGroup\";\nvar [Collection, useCollection, createCollectionScope] = createCollection(GROUP_NAME);\nvar [createRovingFocusGroupContext, createRovingFocusGroupScope] = createContextScope(\n GROUP_NAME,\n [createCollectionScope]\n);\nvar [RovingFocusProvider, useRovingFocusContext] = createRovingFocusGroupContext(GROUP_NAME);\nvar RovingFocusGroup = React.forwardRef(\n (props, forwardedRef) => {\n return /* @__PURE__ */ jsx(Collection.Provider, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx(Collection.Slot, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx(RovingFocusGroupImpl, { ...props, ref: forwardedRef }) }) });\n }\n);\nRovingFocusGroup.displayName = GROUP_NAME;\nvar RovingFocusGroupImpl = React.forwardRef((props, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n orientation,\n loop = false,\n dir,\n currentTabStopId: currentTabStopIdProp,\n defaultCurrentTabStopId,\n onCurrentTabStopIdChange,\n onEntryFocus,\n preventScrollOnEntryFocus = false,\n ...groupProps\n } = props;\n const ref = React.useRef(null);\n const composedRefs = useComposedRefs(forwardedRef, ref);\n const direction = useDirection(dir);\n const [currentTabStopId = null, setCurrentTabStopId] = useControllableState({\n prop: currentTabStopIdProp,\n defaultProp: defaultCurrentTabStopId,\n onChange: onCurrentTabStopIdChange\n });\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const handleEntryFocus = useCallbackRef(onEntryFocus);\n const getItems = useCollection(__scopeRovingFocusGroup);\n const isClickFocusRef = React.useRef(false);\n const [focusableItemsCount, setFocusableItemsCount] = React.useState(0);\n React.useEffect(() => {\n const node = ref.current;\n if (node) {\n node.addEventListener(ENTRY_FOCUS, handleEntryFocus);\n return () => node.removeEventListener(ENTRY_FOCUS, handleEntryFocus);\n }\n }, [handleEntryFocus]);\n return /* @__PURE__ */ jsx(\n RovingFocusProvider,\n {\n scope: __scopeRovingFocusGroup,\n orientation,\n dir: direction,\n loop,\n currentTabStopId,\n onItemFocus: React.useCallback(\n (tabStopId) => setCurrentTabStopId(tabStopId),\n [setCurrentTabStopId]\n ),\n onItemShiftTab: React.useCallback(() => setIsTabbingBackOut(true), []),\n onFocusableItemAdd: React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount + 1),\n []\n ),\n onFocusableItemRemove: React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount - 1),\n []\n ),\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n tabIndex: isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0,\n \"data-orientation\": orientation,\n ...groupProps,\n ref: composedRefs,\n style: { outline: \"none\", ...props.style },\n onMouseDown: composeEventHandlers(props.onMouseDown, () => {\n isClickFocusRef.current = true;\n }),\n onFocus: composeEventHandlers(props.onFocus, (event) => {\n const isKeyboardFocus = !isClickFocusRef.current;\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n if (!entryFocusEvent.defaultPrevented) {\n const items = getItems().filter((item) => item.focusable);\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === currentTabStopId);\n const candidateItems = [activeItem, currentItem, ...items].filter(\n Boolean\n );\n const candidateNodes = candidateItems.map((item) => item.ref.current);\n focusFirst(candidateNodes, preventScrollOnEntryFocus);\n }\n }\n isClickFocusRef.current = false;\n }),\n onBlur: composeEventHandlers(props.onBlur, () => setIsTabbingBackOut(false))\n }\n )\n }\n );\n});\nvar ITEM_NAME = \"RovingFocusGroupItem\";\nvar RovingFocusGroupItem = React.forwardRef(\n (props, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n focusable = true,\n active = false,\n tabStopId,\n ...itemProps\n } = props;\n const autoId = useId();\n const id = tabStopId || autoId;\n const context = useRovingFocusContext(ITEM_NAME, __scopeRovingFocusGroup);\n const isCurrentTabStop = context.currentTabStopId === id;\n const getItems = useCollection(__scopeRovingFocusGroup);\n const { onFocusableItemAdd, onFocusableItemRemove } = context;\n React.useEffect(() => {\n if (focusable) {\n onFocusableItemAdd();\n return () => onFocusableItemRemove();\n }\n }, [focusable, onFocusableItemAdd, onFocusableItemRemove]);\n return /* @__PURE__ */ jsx(\n Collection.ItemSlot,\n {\n scope: __scopeRovingFocusGroup,\n id,\n focusable,\n active,\n children: /* @__PURE__ */ jsx(\n Primitive.span,\n {\n tabIndex: isCurrentTabStop ? 0 : -1,\n \"data-orientation\": context.orientation,\n ...itemProps,\n ref: forwardedRef,\n onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {\n if (!focusable) event.preventDefault();\n else context.onItemFocus(id);\n }),\n onFocus: composeEventHandlers(props.onFocus, () => context.onItemFocus(id)),\n onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {\n if (event.key === \"Tab\" && event.shiftKey) {\n context.onItemShiftTab();\n return;\n }\n if (event.target !== event.currentTarget) return;\n const focusIntent = getFocusIntent(event, context.orientation, context.dir);\n if (focusIntent !== void 0) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n const items = getItems().filter((item) => item.focusable);\n let candidateNodes = items.map((item) => item.ref.current);\n if (focusIntent === \"last\") candidateNodes.reverse();\n else if (focusIntent === \"prev\" || focusIntent === \"next\") {\n if (focusIntent === \"prev\") candidateNodes.reverse();\n const currentIndex = candidateNodes.indexOf(event.currentTarget);\n candidateNodes = context.loop ? wrapArray(candidateNodes, currentIndex + 1) : candidateNodes.slice(currentIndex + 1);\n }\n setTimeout(() => focusFirst(candidateNodes));\n }\n })\n }\n )\n }\n );\n }\n);\nRovingFocusGroupItem.displayName = ITEM_NAME;\nvar MAP_KEY_TO_FOCUS_INTENT = {\n ArrowLeft: \"prev\",\n ArrowUp: \"prev\",\n ArrowRight: \"next\",\n ArrowDown: \"next\",\n PageUp: \"first\",\n Home: \"first\",\n PageDown: \"last\",\n End: \"last\"\n};\nfunction getDirectionAwareKey(key, dir) {\n if (dir !== \"rtl\") return key;\n return key === \"ArrowLeft\" ? \"ArrowRight\" : key === \"ArrowRight\" ? \"ArrowLeft\" : key;\n}\nfunction getFocusIntent(event, orientation, dir) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === \"vertical\" && [\"ArrowLeft\", \"ArrowRight\"].includes(key)) return void 0;\n if (orientation === \"horizontal\" && [\"ArrowUp\", \"ArrowDown\"].includes(key)) return void 0;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\nfunction focusFirst(candidates, preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidate of candidates) {\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\nfunction wrapArray(array, startIndex) {\n return array.map((_, index) => array[(startIndex + index) % array.length]);\n}\nvar Root = RovingFocusGroup;\nvar Item = RovingFocusGroupItem;\nexport {\n Item,\n Root,\n RovingFocusGroup,\n RovingFocusGroupItem,\n createRovingFocusGroupScope\n};\n//# sourceMappingURL=index.mjs.map\n","\"use client\";\n\n// packages/react/tabs/src/Tabs.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { createRovingFocusGroupScope } from \"@radix-ui/react-roving-focus\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as RovingFocusGroup from \"@radix-ui/react-roving-focus\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { jsx } from \"react/jsx-runtime\";\nvar TABS_NAME = \"Tabs\";\nvar [createTabsContext, createTabsScope] = createContextScope(TABS_NAME, [\n createRovingFocusGroupScope\n]);\nvar useRovingFocusGroupScope = createRovingFocusGroupScope();\nvar [TabsProvider, useTabsContext] = createTabsContext(TABS_NAME);\nvar Tabs = React.forwardRef(\n (props, forwardedRef) => {\n const {\n __scopeTabs,\n value: valueProp,\n onValueChange,\n defaultValue,\n orientation = \"horizontal\",\n dir,\n activationMode = \"automatic\",\n ...tabsProps\n } = props;\n const direction = useDirection(dir);\n const [value, setValue] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n defaultProp: defaultValue\n });\n return /* @__PURE__ */ jsx(\n TabsProvider,\n {\n scope: __scopeTabs,\n baseId: useId(),\n value,\n onValueChange: setValue,\n orientation,\n dir: direction,\n activationMode,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n dir: direction,\n \"data-orientation\": orientation,\n ...tabsProps,\n ref: forwardedRef\n }\n )\n }\n );\n }\n);\nTabs.displayName = TABS_NAME;\nvar TAB_LIST_NAME = \"TabsList\";\nvar TabsList = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, loop = true, ...listProps } = props;\n const context = useTabsContext(TAB_LIST_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Root,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n orientation: context.orientation,\n dir: context.dir,\n loop,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n role: \"tablist\",\n \"aria-orientation\": context.orientation,\n ...listProps,\n ref: forwardedRef\n }\n )\n }\n );\n }\n);\nTabsList.displayName = TAB_LIST_NAME;\nvar TRIGGER_NAME = \"TabsTrigger\";\nvar TabsTrigger = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, value, disabled = false, ...triggerProps } = props;\n const context = useTabsContext(TRIGGER_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Item,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n focusable: !disabled,\n active: isSelected,\n children: /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n role: \"tab\",\n \"aria-selected\": isSelected,\n \"aria-controls\": contentId,\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-disabled\": disabled ? \"\" : void 0,\n disabled,\n id: triggerId,\n ...triggerProps,\n ref: forwardedRef,\n onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {\n if (!disabled && event.button === 0 && event.ctrlKey === false) {\n context.onValueChange(value);\n } else {\n event.preventDefault();\n }\n }),\n onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {\n if ([\" \", \"Enter\"].includes(event.key)) context.onValueChange(value);\n }),\n onFocus: composeEventHandlers(props.onFocus, () => {\n const isAutomaticActivation = context.activationMode !== \"manual\";\n if (!isSelected && !disabled && isAutomaticActivation) {\n context.onValueChange(value);\n }\n })\n }\n )\n }\n );\n }\n);\nTabsTrigger.displayName = TRIGGER_NAME;\nvar CONTENT_NAME = \"TabsContent\";\nvar TabsContent = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, value, forceMount, children, ...contentProps } = props;\n const context = useTabsContext(CONTENT_NAME, __scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n const isMountAnimationPreventedRef = React.useRef(isSelected);\n React.useEffect(() => {\n const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);\n return () => cancelAnimationFrame(rAF);\n }, []);\n return /* @__PURE__ */ jsx(Presence, { present: forceMount || isSelected, children: ({ present }) => /* @__PURE__ */ jsx(\n Primitive.div,\n {\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-orientation\": context.orientation,\n role: \"tabpanel\",\n \"aria-labelledby\": triggerId,\n hidden: !present,\n id: contentId,\n tabIndex: 0,\n ...contentProps,\n ref: forwardedRef,\n style: {\n ...props.style,\n animationDuration: isMountAnimationPreventedRef.current ? \"0s\" : void 0\n },\n children: present && children\n }\n ) });\n }\n);\nTabsContent.displayName = CONTENT_NAME;\nfunction makeTriggerId(baseId, value) {\n return `${baseId}-trigger-${value}`;\n}\nfunction makeContentId(baseId, value) {\n return `${baseId}-content-${value}`;\n}\nvar Root2 = Tabs;\nvar List = TabsList;\nvar Trigger = TabsTrigger;\nvar Content = TabsContent;\nexport {\n Content,\n List,\n Root2 as Root,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Trigger,\n createTabsScope\n};\n//# sourceMappingURL=index.mjs.map\n","import { type SerializeFrom } from '@remix-run/node'\nimport { Await, Link, useLoaderData } from '@remix-run/react'\nimport * as React from 'react'\nimport { Icon } from '#app/components/icons.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { useAltDown } from '#app/utils/misc.tsx'\nimport { DiscordCTA, useDiscordCTALink } from '../../../discord.tsx'\nimport { type loader } from '../index.tsx'\n\nexport function DiscordChat() {\n\tconst data = useLoaderData<typeof loader>()\n\treturn (\n\t\t<div className=\"flex h-full w-full flex-col gap-4 pt-4\">\n\t\t\t<div className=\"text-center\">\n\t\t\t\t<DiscordCTA discordAuthUrl={data.discordAuthUrl} />\n\t\t\t</div>\n\t\t\t<div className=\"flex-1 overflow-y-scroll bg-accent pb-4 scrollbar-thin scrollbar-thumb-scrollbar\">\n\t\t\t\t<DiscordPosts />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction DiscordPosts() {\n\tconst data = useLoaderData<typeof loader>()\n\tconst ctaLink = useDiscordCTALink({ discordAuthUrl: data.discordAuthUrl })\n\tconst altDown = useAltDown()\n\treturn (\n\t\t<div className=\"flex h-full flex-col items-center justify-between\">\n\t\t\t<React.Suspense\n\t\t\t\tfallback={\n\t\t\t\t\t<div className=\"flex h-full w-full flex-col items-center justify-center\">\n\t\t\t\t\t\t<Loading>Loading Discord Posts</Loading>\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t<Await\n\t\t\t\t\tresolve={data.discordPostsPromise}\n\t\t\t\t\terrorElement={\n\t\t\t\t\t\t<div className=\"text-red-500\">\n\t\t\t\t\t\t\tThere was a problem loading the discord posts\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t{(posts) => (\n\t\t\t\t\t\t<ul className=\"flex w-full flex-col gap-4 p-3 xl:p-12\">\n\t\t\t\t\t\t\t{posts.map((post) => (\n\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\tkey={post.id}\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-xl border bg-background transition-all duration-200 focus-within:-translate-y-1 focus-within:shadow-lg hover:-translate-y-1 hover:shadow-lg\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<DiscordPost thread={post} />\n\t\t\t\t\t\t\t\t</li>\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</Await>\n\t\t\t</React.Suspense>\n\t\t\t<div>\n\t\t\t\t<Link\n\t\t\t\t\tto={\n\t\t\t\t\t\taltDown && !ctaLink.includes('oauth')\n\t\t\t\t\t\t\t? ctaLink.replace(/^https/, 'discord')\n\t\t\t\t\t\t\t: ctaLink\n\t\t\t\t\t}\n\t\t\t\t\ttarget={ctaLink.includes('oauth') ? undefined : '_blank'}\n\t\t\t\t\trel=\"noreferrer noopener\"\n\t\t\t\t\tonClick={\n\t\t\t\t\t\taltDown\n\t\t\t\t\t\t\t? (e) => {\n\t\t\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\t\t\twindow.open(\n\t\t\t\t\t\t\t\t\t\te.currentTarget.href,\n\t\t\t\t\t\t\t\t\t\t'_blank',\n\t\t\t\t\t\t\t\t\t\t'noreferrer noopener',\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tclassName=\"flex items-center gap-2 p-2 text-xl hover:underline\"\n\t\t\t\t>\n\t\t\t\t\tCreate Post <Icon name=\"ExternalLink\" />\n\t\t\t\t</Link>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction DiscordPost({\n\tthread,\n}: {\n\tthread: Awaited<SerializeFrom<typeof loader>['discordPostsPromise']>[number]\n}) {\n\tconst reactionsWithCounts = thread.reactions.filter((r) => r.count)\n\n\treturn (\n\t\t<div>\n\t\t\t<div className=\"flex flex-col gap-2 p-4\">\n\t\t\t\t<div className=\"flex gap-4\">\n\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t{thread.tags.length ? (\n\t\t\t\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t\t\t\t{thread.tags.map((t) => (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tkey={t.name}\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-center gap-1 rounded-full bg-accent px-2 py-1 text-sm\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span className=\"h-3 w-3 leading-3\">\n\t\t\t\t\t\t\t\t\t\t\t{/* not sure how to fix this one... */}\n\t\t\t\t\t\t\t\t\t\t\t{/* @ts-expect-error */}\n\t\t\t\t\t\t\t\t\t\t\t<Emoji name={t.emojiName} url={t.emojiUrl} />\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t<span>{t.name}</span>\n\t\t\t\t\t\t\t\t\t</div>\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) : null}\n\t\t\t\t\t\t<strong className=\"text-xl font-bold\">{thread.name}</strong>\n\t\t\t\t\t\t<div className=\"flex items-start gap-1\">\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t\t{thread.authorAvatarUrl ? (\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tsrc={thread.authorAvatarUrl}\n\t\t\t\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6 rounded-full\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclassName=\"font-bold\"\n\t\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\t\tthread.authorHexAccentColor\n\t\t\t\t\t\t\t\t\t\t\t\t? { color: thread.authorHexAccentColor }\n\t\t\t\t\t\t\t\t\t\t\t\t: {}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{thread.authorDisplayName}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t:{' '}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<span className=\"flex-1 overflow-ellipsis text-muted-foreground\">\n\t\t\t\t\t\t\t\t{thread.messagePreview}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{thread.previewImageUrl ? (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={thread.previewImageUrl}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tclassName=\"h-28 w-28 rounded-lg object-cover\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"flex justify-between\">\n\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t{reactionsWithCounts.length ? (\n\t\t\t\t\t\t\t\t<ul className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t{reactionsWithCounts.map((r, i) => (\n\t\t\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center gap-1 rounded-md border border-blue-600 bg-blue-500/20 px-[5px] py-[0.5px] text-sm\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"h-3 w-3 leading-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t{/* not sure how to fix this one... */}\n\t\t\t\t\t\t\t\t\t\t\t\t{/* @ts-expect-error */}\n\t\t\t\t\t\t\t\t\t\t\t\t<Emoji name={r.emojiName} url={r.emojiUrl} />\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t<span>{r.count}</span>\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t<span className=\"inline-flex items-center gap-1\">\n\t\t\t\t\t\t\t\t<Icon name=\"Chat\" /> {thread.messageCount}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{` · ${thread.lastUpdatedDisplay}`}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span className=\"flex items-center gap-4\">\n\t\t\t\t\t\t<a href={thread.link.replace(/^https/, 'discord')}>\n\t\t\t\t\t\t\t<Icon name=\"Discord\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<a href={thread.link} target=\"_blank\" rel=\"noreferrer noopener\">\n\t\t\t\t\t\t\t<Icon name=\"ExternalLink\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction Emoji({ name, url }: { name?: string; url?: string }) {\n\treturn url ? (\n\t\t<img src={url} alt={name} className=\"h-full w-full\" />\n\t) : name ? (\n\t\tname\n\t) : null\n}\n","import { toast as showToast } from 'sonner'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser'\nimport { SimpleTooltip } from '#app/components/ui/tooltip'\nimport { SetAppToPlayground } from '#app/routes/set-playground'\nimport { PlaygroundWindow } from './playground-window'\nimport { Preview } from './preview'\n\nexport function Playground({\n\tappInfo: playgroundAppInfo,\n\tinBrowserBrowserRef,\n\tproblemAppName,\n\tallApps,\n\tisUpToDate,\n}: {\n\tappInfo: Parameters<typeof Preview>['0']['appInfo'] | null\n\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n\tproblemAppName?: string\n\tallApps: Array<{ name: string; displayName: string }>\n\tisUpToDate: boolean\n}) {\n\treturn (\n\t\t<PlaygroundWindow\n\t\t\tplaygroundAppName={playgroundAppInfo?.appName}\n\t\t\tproblemAppName={problemAppName}\n\t\t\tallApps={allApps}\n\t\t\tisUpToDate={isUpToDate}\n\t\t>\n\t\t\t{playgroundAppInfo?.dev.type === 'none' ? (\n\t\t\t\t<div>\n\t\t\t\t\t<div className=\"text-foreground-secondary flex h-full items-center justify-center text-2xl\">\n\t\t\t\t\t\tNon-UI playground\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"text-foreground-secondary flex flex-wrap gap-1 text-center\">\n\t\t\t\t\t\t\tNavigate to{' '}\n\t\t\t\t\t\t\t<SimpleTooltip content={playgroundAppInfo.fullPath}>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tvoid navigator.clipboard.writeText(\n\t\t\t\t\t\t\t\t\t\t\tplaygroundAppInfo.fullPath,\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\tshowToast.success('Copied playground path to clipboard')\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tthe playground directory\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</SimpleTooltip>{' '}\n\t\t\t\t\t\t\tin your editor and terminal to work on this exercise!\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : playgroundAppInfo ? (\n\t\t\t\t<Preview\n\t\t\t\t\tid={playgroundAppInfo.appName}\n\t\t\t\t\tappInfo={playgroundAppInfo}\n\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex flex-col justify-center gap-2\">\n\t\t\t\t\t<p>Please set the playground first</p>\n\t\t\t\t\t{problemAppName ? (\n\t\t\t\t\t\t<SetAppToPlayground appName={problemAppName} />\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</PlaygroundWindow>\n\t)\n}\n","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 { compileMarkdownString } from '@epic-web/workshop-utils/compile-mdx.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 {\n\tdefer,\n\tredirect,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n} from '@remix-run/node'\nimport {\n\tLink,\n\tuseLoaderData,\n\tuseNavigate,\n\tuseSearchParams,\n} from '@remix-run/react'\nimport { clsx } from 'clsx'\nimport * as React from 'react'\nimport { useRef } from 'react'\nimport { Diff } from '#app/components/diff.tsx'\nimport { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser.tsx'\nimport { getDiscordAuthURL } from '#app/routes/discord.callback.ts'\nimport { getDiffCode } from '#app/utils/diff.server.ts'\nimport { userHasAccessToWorkshop } from '#app/utils/epic-api.js'\nimport { useAltDown } from '#app/utils/misc.tsx'\nimport { fetchDiscordPosts } from './__shared/discord.server.ts'\nimport { DiscordChat } from './__shared/discord.tsx'\nimport { Playground } from './__shared/playground.tsx'\nimport { Preview } from './__shared/preview.tsx'\nimport { Tests } from './__shared/tests.tsx'\nimport { getAppRunningState } from './__shared/utils.tsx'\n\nexport async function loader({ request, params }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('exerciseStepTypeLoader')\n\tconst userHasAccess = await userHasAccessToWorkshop({\n\t\trequest,\n\t\ttimings,\n\t})\n\tconst searchParams = new URL(request.url).searchParams\n\tconst cacheOptions = { request, timings }\n\tconst exerciseStepApp = await requireExerciseApp(params, cacheOptions)\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 problemApp = await getExerciseApp(\n\t\t{ ...params, type: 'problem' },\n\t\tcacheOptions,\n\t)\n\tconst solutionApp = await getExerciseApp(\n\t\t{ ...params, type: 'solution' },\n\t\tcacheOptions,\n\t)\n\n\tif (!problemApp && !solutionApp) {\n\t\tthrow new Response('Not found', { status: 404 })\n\t}\n\n\tconst allAppsFull = await getApps(cacheOptions)\n\tconst playgroundApp = allAppsFull.find(isPlaygroundApp)\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\tif (!userHasAccess) {\n\t\t\treturn {\n\t\t\t\tapp1: app1?.name,\n\t\t\t\tapp2: app2?.name,\n\t\t\t\tdiffCode: await compileMarkdownString(\n\t\t\t\t\t`<h1>Access Denied</h1><p>You must login or register for the workshop to view the diff</p>`,\n\t\t\t\t),\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 defer(\n\t\t{\n\t\t\ttype: params.type as 'problem' | 'solution',\n\t\t\texerciseStepApp,\n\t\t\tallApps,\n\t\t\tdiscordAuthUrl: getDiscordAuthURL(),\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\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} 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\nfunction withParam(\n\tsearchParams: URLSearchParams,\n\tkey: string,\n\tvalue: string | null,\n) {\n\tconst newSearchParams = new URLSearchParams(searchParams)\n\tif (value === null) {\n\t\tnewSearchParams.delete(key)\n\t} else {\n\t\tnewSearchParams.set(key, value)\n\t}\n\treturn newSearchParams\n}\n\nexport default function ExercisePartRoute() {\n\tconst data = useLoaderData<typeof loader>()\n\tconst [searchParams] = useSearchParams()\n\n\tconst preview = searchParams.get('preview')\n\tconst inBrowserBrowserRef = useRef<InBrowserBrowserRef>(null)\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!data.playground ||\n\t\t\t\tdata.playground.test.type === 'none'\n\t\t\t)\n\t\t}\n\t\tif (tab === 'problem' || tab === 'solution') {\n\t\t\tif (data[tab]?.dev.type === 'none') return true\n\t\t\tif (ENV.EPICSHOP_DEPLOYED) {\n\t\t\t\treturn data[tab]?.dev.type !== 'browser' && !data[tab]?.stackBlitzUrl\n\t\t\t}\n\t\t}\n\t\tif (tab === 'playground' && ENV.EPICSHOP_DEPLOYED) return true\n\t\treturn false\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: data.problem?.name ?? '',\n\t\tapp2: data.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\tnavigate(altDiffUrl)\n\t\t}\n\t}\n\n\treturn (\n\t\t<Tabs.Root\n\t\t\tclassName=\"relative flex flex-col overflow-y-auto 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<Tabs.List className=\"h-14 min-h-14 overflow-x-hidden border-b scrollbar-thin scrollbar-thumb-scrollbar\">\n\t\t\t\t{tabs.map((tab) => {\n\t\t\t\t\tconst hidden = shouldHideTab(tab)\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Tabs.Trigger key={tab} value={tab} hidden={hidden} asChild>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tid={`${tab}-tab`}\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'clip-path-button relative h-full px-6 py-4 font-mono text-sm uppercase outline-none radix-state-active:z-10 radix-state-active:bg-foreground radix-state-active:text-background radix-state-active:hover:bg-foreground/80 radix-state-active:hover:text-background/80 radix-state-inactive:hover:bg-foreground/20 radix-state-inactive:hover:text-foreground/80 focus:bg-foreground/80 focus:text-background/80',\n\t\t\t\t\t\t\t\t\thidden ? 'hidden' : 'inline-block',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tpreventScrollReset\n\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\tonClick={handleDiffTabClick}\n\t\t\t\t\t\t\t\tto={\n\t\t\t\t\t\t\t\t\ttab === 'diff' && altDown\n\t\t\t\t\t\t\t\t\t\t? altDiffUrl\n\t\t\t\t\t\t\t\t\t\t: `?${withParam(\n\t\t\t\t\t\t\t\t\t\t\t\tsearchParams,\n\t\t\t\t\t\t\t\t\t\t\t\t'preview',\n\t\t\t\t\t\t\t\t\t\t\t\ttab === 'playground' ? null : tab,\n\t\t\t\t\t\t\t\t\t\t\t)}`\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{tab}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t)\n\t\t\t\t})}\n\t\t\t</Tabs.List>\n\t\t\t<div className=\"relative z-10 flex min-h-96 flex-grow flex-col overflow-y-auto\">\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"playground\"\n\t\t\t\t\tclassName=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Playground\n\t\t\t\t\t\tappInfo={data.playground}\n\t\t\t\t\t\tproblemAppName={data.problem?.name}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t\tallApps={data.allApps}\n\t\t\t\t\t\tisUpToDate={data.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=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={data.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=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={data.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=\"flex w-full flex-grow items-start justify-center self-start overflow-hidden radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Tests\n\t\t\t\t\t\tappInfo={data.playground}\n\t\t\t\t\t\tproblemAppName={data.problem?.name}\n\t\t\t\t\t\tallApps={data.allApps}\n\t\t\t\t\t\tisUpToDate={data.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=\"diff\"\n\t\t\t\t\tclassName=\"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Diff diff={data.diff} allApps={data.allApps} />\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=\"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<DiscordChat />\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":["ENTRY_FOCUS","EVENT_OPTIONS","GROUP_NAME","Collection","useCollection","createCollectionScope","createCollection","createRovingFocusGroupContext","createRovingFocusGroupScope","createContextScope","RovingFocusProvider","useRovingFocusContext","RovingFocusGroup","React.forwardRef","props","forwardedRef","jsx","RovingFocusGroupImpl","__scopeRovingFocusGroup","orientation","loop","dir","currentTabStopIdProp","defaultCurrentTabStopId","onCurrentTabStopIdChange","onEntryFocus","preventScrollOnEntryFocus","groupProps","ref","React.useRef","composedRefs","useComposedRefs","direction","useDirection","currentTabStopId","setCurrentTabStopId","useControllableState","isTabbingBackOut","setIsTabbingBackOut","React.useState","handleEntryFocus","useCallbackRef","getItems","isClickFocusRef","focusableItemsCount","setFocusableItemsCount","React.useEffect","node","React.useCallback","tabStopId","prevCount","Primitive","composeEventHandlers","event","isKeyboardFocus","entryFocusEvent","items","item","activeItem","currentItem","candidateNodes","focusFirst","ITEM_NAME","RovingFocusGroupItem","focusable","active","itemProps","autoId","useId","id","context","isCurrentTabStop","onFocusableItemAdd","onFocusableItemRemove","focusIntent","getFocusIntent","currentIndex","wrapArray","MAP_KEY_TO_FOCUS_INTENT","getDirectionAwareKey","key","candidates","preventScroll","PREVIOUSLY_FOCUSED_ELEMENT","candidate","array","startIndex","_","index","Root","Item","TABS_NAME","createTabsContext","createTabsScope","useRovingFocusGroupScope","TabsProvider","useTabsContext","Tabs","__scopeTabs","valueProp","onValueChange","defaultValue","activationMode","tabsProps","value","setValue","TAB_LIST_NAME","TabsList","listProps","rovingFocusGroupScope","RovingFocusGroup.Root","TRIGGER_NAME","TabsTrigger","disabled","triggerProps","triggerId","makeTriggerId","contentId","makeContentId","isSelected","RovingFocusGroup.Item","isAutomaticActivation","CONTENT_NAME","TabsContent","forceMount","children","contentProps","isMountAnimationPreventedRef","rAF","Presence","present","baseId","Root2","List","Trigger","Content","DiscordChat","data","useLoaderData","jsxs","DiscordCTA","DiscordPosts","ctaLink","useDiscordCTALink","altDown","useAltDown","React.Suspense","Loading","Await","posts","post","DiscordPost","Link","e","Icon","thread","reactionsWithCounts","r","t","Emoji","i","name","url","Playground","playgroundAppInfo","inBrowserBrowserRef","problemAppName","allApps","isUpToDate","PlaygroundWindow","SimpleTooltip","showToast","Preview","SetAppToPlayground","tabs","isValidPreview","s","Boolean","includes","withParam","searchParams","newSearchParams","URLSearchParams","delete","set","ExercisePartRoute","useSearchParams","preview","get","useRef","navigate","useNavigate","shouldHideTab","tab","ENV","EPICSHOP_DEPLOYED","playground","test","type","dev","stackBlitzUrl","activeTab","find","altDiffUrl","app1","problem","app2","solution","handleDiffTabClick","altKey","ctrlKey","shiftKey","metaKey","preventDefault","className","map","hidden","asChild","clsx","preventScrollReset","prefetch","onClick","to","appInfo","Tests","Diff","diff","ErrorBoundary","GeneralErrorBoundary","statusHandlers"],"mappings":"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","x_google_ignoreList":[0,1]}
@@ -0,0 +1,2 @@
1
+ import{r as a,d as g,e as v,j as e}from"./index-1cKOJFpX.js";import{u as j}from"./use-event-source-A_0lEOPX.js";import{a as R,B as C}from"./button-CQ6cnotS.js";import{L as S}from"./loading-CF7oQHQf.js";import{L as b}from"./product-f8Gd2MQ6.js";import{u as k}from"./workshop-config-CL4F08kr.js";import{z as t}from"./request-info-CEhUGODY.js";import{a as y}from"./components-CME-nGId.js";import"./misc-Txs7O6JX.js";import"./index-DlJAkutV.js";import"./tooltip-DTFU8ajx.js";import"./pe-CUZaIcdt.js";const r={USER_CODE_RECEIVED:"USER_CODE_RECEIVED",AUTH_RESOLVED:"AUTH_RESOLVED",AUTH_REJECTED:"AUTH_REJECTED"},_=t.object({type:t.literal(r.USER_CODE_RECEIVED),code:t.string(),url:t.string()}),D=t.object({type:t.literal(r.AUTH_RESOLVED)}),N=t.object({type:t.literal(r.AUTH_REJECTED),error:t.string().optional().default("Unknown error")}),T=t.union([_,D,N]),W={getSitemapEntries:()=>null};function z(){var E;const{product:{displayName:n}}=k(),o=y(),[u,f]=a.useState(!1),[c,x]=a.useState(null),[i,p]=a.useState(null),d=g(),m=v(),l=j("/login-sse");return a.useEffect(()=>{if(!l)return;const h=JSON.parse(l),s=T.safeParse(h);if(!s.success){console.error(s.error.flatten());return}switch(s.data.type){case r.USER_CODE_RECEIVED:{p(s.data);break}case r.AUTH_RESOLVED:{m.revalidate(),d("/");break}case r.AUTH_REJECTED:{x(s.data.error);break}}},[l,d,m]),e.jsx("main",{className:"flex h-full w-full flex-grow flex-col items-center justify-center p-10 text-center",children:e.jsxs("div",{className:"flex flex-col items-center",children:[e.jsx(b,{className:"h-16 w-16"}),e.jsxs("h1",{className:"pt-5 text-2xl font-semibold md:text-3xl",children:["Authenticate with ",n]}),e.jsxs("h2",{className:"max-w-sm pt-3 text-base text-gray-700 dark:text-gray-300",children:["If you have access to this workshop on ",n,", you'll be able to watch videos, track progress, and more!"]}),e.jsxs("div",{className:"flex w-full flex-col items-center pt-5",children:[i?e.jsxs("div",{className:"flex w-full 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:"mb-3 w-full bg-gray-100 px-5 py-3 text-lg font-bold dark:bg-black/40",children:e.jsx("code",{children:i.code})})]}),e.jsx(R,{varient:"primary",to:i.url,target:"_blank",rel:"noreferrer",onClick:()=>f(!0),children:"Continue"}),u?e.jsx("div",{className:"pt-5 opacity-60",children:e.jsx(S,{children:"Waiting for confirmation"})}):null]}):e.jsx(o.Form,{method:"POST",children:e.jsx(C,{varient:"primary",type:"submit",children:o.state==="idle"&&((E=o.data)==null?void 0:E.status)!=="pending"?"Retrieve Code":"Retrieving Code..."})}),c?e.jsxs("div",{className:"mt-4 text-red-500",children:["There was an error: ",e.jsx("pre",{children:c})]}):null]})]})})}export{z as default,W as handle};
2
+ //# sourceMappingURL=login-Ca9EDpZj.js.map