@epic-web/workshop-app 6.72.1 → 6.74.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 (63) hide show
  1. package/build/client/assets/_exerciseNumber-jokuvO2V.js +2 -0
  2. package/build/client/assets/{_exerciseNumber-DUwXPNgl.js.map → _exerciseNumber-jokuvO2V.js.map} +1 -1
  3. package/build/client/assets/_exerciseNumber_.finished-BaC--Y5p.js +2 -0
  4. package/build/client/assets/_exerciseNumber_.finished-BaC--Y5p.js.map +1 -0
  5. package/build/client/assets/_extra-DXypL1sc.js +2 -0
  6. package/build/client/assets/{_extra-DkiDFYVP.js.map → _extra-DXypL1sc.js.map} +1 -1
  7. package/build/client/assets/_layout-_Aw6qzZC.js +2 -0
  8. package/build/client/assets/{_layout-DDTXkx2z.js.map → _layout-_Aw6qzZC.js.map} +1 -1
  9. package/build/client/assets/diff-DfWBhj2O.js +2 -0
  10. package/build/client/assets/{diff-DwJn8fSQ.js.map → diff-DfWBhj2O.js.map} +1 -1
  11. package/build/client/assets/{diff-HIgoC1PO.js → diff-Dng5ItOr.js} +2 -2
  12. package/build/client/assets/{diff-HIgoC1PO.js.map → diff-Dng5ItOr.js.map} +1 -1
  13. package/build/client/assets/epic-video-C1_HSISA.js +2 -0
  14. package/build/client/assets/{epic-video-DEq93iL_.js.map → epic-video-C1_HSISA.js.map} +1 -1
  15. package/build/client/assets/{epic-video-DnXXh6qE.js → epic-video-CC0372g5.js} +164 -164
  16. package/build/client/assets/{epic-video-DnXXh6qE.js.map → epic-video-CC0372g5.js.map} +1 -1
  17. package/build/client/assets/finished-BbEk1NdF.js +2 -0
  18. package/build/client/assets/finished-BbEk1NdF.js.map +1 -0
  19. package/build/client/assets/format-CZ5n8p10.js +2 -0
  20. package/build/client/assets/format-CZ5n8p10.js.map +1 -0
  21. package/build/client/assets/index-CFM_ffAh.js +2 -0
  22. package/build/client/assets/{index-IgBUhsxX.js.map → index-CFM_ffAh.js.map} +1 -1
  23. package/build/client/assets/index-CfU0fdf7.js +2 -0
  24. package/build/client/assets/{index-PKjGT1Rp.js.map → index-CfU0fdf7.js.map} +1 -1
  25. package/build/client/assets/index-Pxi8WjFA.js +2 -0
  26. package/build/client/assets/{index-BgExztV_.js.map → index-Pxi8WjFA.js.map} +1 -1
  27. package/build/client/assets/manifest-835c6db1.js +1 -0
  28. package/build/client/assets/{mdx-Dun3ONG_.js → mdx-vy-1-0a3.js} +2 -2
  29. package/build/client/assets/{mdx-Dun3ONG_.js.map → mdx-vy-1-0a3.js.map} +1 -1
  30. package/build/client/assets/{offline-videos-BP7_xJkO.js → offline-videos-DAsuWMco.js} +2 -2
  31. package/build/client/assets/offline-videos-DAsuWMco.js.map +1 -0
  32. package/build/client/assets/preferences-B7ND1VS9.js +2 -0
  33. package/build/client/assets/preferences-B7ND1VS9.js.map +1 -0
  34. package/build/client/assets/retrieval-practice-BOku32wW.js +2 -0
  35. package/build/client/assets/retrieval-practice-BOku32wW.js.map +1 -0
  36. package/build/client/assets/{root-CKcj2hDc.js → root-BwYDIUyI.js} +2 -2
  37. package/build/client/assets/{root-CKcj2hDc.js.map → root-BwYDIUyI.js.map} +1 -1
  38. package/build/client/assets/tailwind-C8PqsZFp.css +1 -0
  39. package/build/client/assets/test-Ciw2aKZE.js +2 -0
  40. package/build/client/assets/{test-BU7jE-eU.js.map → test-Ciw2aKZE.js.map} +1 -1
  41. package/build/client/assets/{tests-1-kVRtTc.js → tests-CZ2AhDKA.js} +2 -2
  42. package/build/client/assets/{tests-1-kVRtTc.js.map → tests-CZ2AhDKA.js.map} +1 -1
  43. package/build/server/index.js +110 -25
  44. package/build/server/index.js.map +1 -1
  45. package/package.json +3 -3
  46. package/build/client/assets/_exerciseNumber-DUwXPNgl.js +0 -2
  47. package/build/client/assets/_exerciseNumber_.finished-C4sVkuEq.js +0 -2
  48. package/build/client/assets/_exerciseNumber_.finished-C4sVkuEq.js.map +0 -1
  49. package/build/client/assets/_extra-DkiDFYVP.js +0 -2
  50. package/build/client/assets/_layout-DDTXkx2z.js +0 -2
  51. package/build/client/assets/diff-DwJn8fSQ.js +0 -2
  52. package/build/client/assets/epic-video-DEq93iL_.js +0 -2
  53. package/build/client/assets/finished-BW_4ow3n.js +0 -2
  54. package/build/client/assets/finished-BW_4ow3n.js.map +0 -1
  55. package/build/client/assets/index-BgExztV_.js +0 -2
  56. package/build/client/assets/index-IgBUhsxX.js +0 -2
  57. package/build/client/assets/index-PKjGT1Rp.js +0 -2
  58. package/build/client/assets/manifest-9e0c0428.js +0 -1
  59. package/build/client/assets/offline-videos-BP7_xJkO.js.map +0 -1
  60. package/build/client/assets/preferences-D6HQ5bK1.js +0 -2
  61. package/build/client/assets/preferences-D6HQ5bK1.js.map +0 -1
  62. package/build/client/assets/tailwind-C1_1LEqo.css +0 -1
  63. package/build/client/assets/test-BU7jE-eU.js +0 -2
@@ -0,0 +1,2 @@
1
+ import{w as y,b as N,k as V,f as D,F as r,L as P}from"./chunk-EPOLDU6W-BCLmut3y.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{B as m}from"./button-Cd-ekki5.js";import{b as R,I as o}from"./misc-W4055b-0.js";import{S as l}from"./tooltip-Tlsyx2YO.js";import{f as u}from"./format-CZ5n8p10.js";import{u as S}from"./root-loader-BOzEMapJ.js";import"./index-CqIc3cxq.js";import"./index-vDCSPjrM.js";const k=[{value:"best",label:"Best available"},{value:"high",label:"High"},{value:"medium",label:"Medium"},{value:"low",label:"Low"}],A=y(function(){const h=N(),n=S(),c=n.preferences?.player,p=n.preferences?.offlineVideo,f=n.preferences?.fontSize,b=n.preferences?.presence,j=n.preferences?.playground,g=n.preferences?.exerciseWarning,v=V(),i=D(),s=i.data?.offlineVideos??h.offlineVideos,t=s.downloadState.status==="running",x=[s.unavailableVideos>0?`${s.unavailableVideos} unavailable`:null,s.notDownloadableVideos>0?`${s.notDownloadableVideos} not downloadable`:null].filter(Boolean).join(", "),w=s.totalVideos>0&&s.downloadedVideos<s.totalVideos&&s.remainingDownloadBytes>0,a=v.state==="submitting";return R(()=>{i.state==="idle"&&i.load("/resources/offline-videos")},t?2e3:null),e.jsx("div",{className:"h-full w-full overflow-y-auto",children:e.jsxs("main",{className:"container mt-12 flex w-full max-w-3xl grow flex-col gap-4 pb-24",children:[e.jsx("h1",{className:"text-h1 mb-4",children:"Preferences"}),e.jsxs(r,{method:"post",className:"flex w-full max-w-sm flex-col gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-body-xl mb-2",children:"Video Player Preferences"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{htmlFor:"minResolution",children:"Minimum Resolution:"}),e.jsxs("select",{id:"minResolution",name:"minResolution",defaultValue:c?.minResolution,className:"border-border bg-background text-foreground rounded-md border px-2 py-1",children:[e.jsx("option",{value:"",children:"Auto"}),e.jsx("option",{value:"480",children:"480p"}),e.jsx("option",{value:"720",children:"720p"}),e.jsx("option",{value:"1080",children:"1080p"}),e.jsx("option",{value:"1440",children:"1440p"}),e.jsx("option",{value:"2160",children:"2160p (4K)"})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{htmlFor:"maxResolution",children:"Maximum Resolution:"}),e.jsxs("select",{id:"maxResolution",name:"maxResolution",defaultValue:c?.maxResolution,className:"border-border bg-background text-foreground rounded-md border px-2 py-1",children:[e.jsx("option",{value:"",children:"Auto"}),e.jsx("option",{value:"720",children:"720p"}),e.jsx("option",{value:"1080",children:"1080p"}),e.jsx("option",{value:"1440",children:"1440p"}),e.jsx("option",{value:"2160",children:"2160p (4K)"})]})]})]}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-body-xl mb-2",children:"Offline Video Downloads"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{htmlFor:"downloadResolution",children:"Download Resolution:"}),e.jsx("select",{id:"downloadResolution",name:"downloadResolution",defaultValue:p?.downloadResolution??"best",className:"border-border bg-background text-foreground rounded-md border px-2 py-1",children:k.map(d=>e.jsx("option",{value:d.value,children:d.label},d.value))})]}),e.jsx("p",{className:"text-muted-foreground text-sm",children:"Defaults to the best available resolution."})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[e.jsx("h2",{className:"text-body-xl",children:"Font Size Preference"}),e.jsx(l,{content:"Defaults to 16px",children:e.jsx(o,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{htmlFor:"fontSize",children:"Font Size"}),e.jsx("input",{type:"number",id:"fontSize",name:"fontSize",defaultValue:f??16,step:"1",min:"12",max:"26",className:"border-border bg-background text-foreground rounded-md border px-2 py-1"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[e.jsx("h2",{className:"text-body-xl",children:"Presence Preference"}),e.jsx(l,{content:"This controls whether your name and avatar are displayed in the pile of faces in navigation",children:e.jsx(o,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",id:"optOutPresence",name:"optOutPresence",defaultChecked:b?.optOut}),e.jsx("label",{htmlFor:"optOutPresence",children:"Opt out of presence features"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[e.jsx("h2",{className:"text-body-xl",children:"Persist Playground"}),e.jsx(l,{content:'When enabled, clicking "Set to Playground" will save the current playground in the "saved-playgrounds" directory.',children:e.jsx(o,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",id:"persistPlayground",name:"persistPlayground",defaultChecked:j?.persist}),e.jsx("label",{htmlFor:"persistPlayground",children:"Enable saving playground"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[e.jsx("h2",{className:"text-body-xl",children:"Exercise Directory Warning"}),e.jsx(l,{content:"When enabled, you'll see a warning banner when you have changes in the exercises directory. This helps remind you to work in the playground directory instead.",children:e.jsx(o,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",id:"dismissExerciseWarning",name:"dismissExerciseWarning",defaultChecked:g?.dismissed}),e.jsx("label",{htmlFor:"dismissExerciseWarning",children:"Dismiss exercise directory warnings"})]})]}),e.jsx("div",{className:"h-4"}),e.jsx(m,{varient:"primary",type:"submit",name:"intent",value:"update-preferences",disabled:a,children:a?"Updating...":"Update Preferences"})]}),e.jsxs("section",{className:"border-border mt-6 flex w-full max-w-xl flex-col gap-3 border-t pt-6",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h2",{className:"text-body-xl",children:"Offline videos"}),e.jsx(l,{content:"Keep videos ready to watch when you're offline.",children:e.jsx(o,{name:"Question",tabIndex:0})})]}),e.jsx("p",{className:"text-muted-foreground text-sm",children:"Download all workshop videos so you can watch them when offline."}),e.jsxs("p",{className:"text-muted-foreground text-sm",children:["Admins can manage all downloaded videos on the"," ",e.jsx(P,{className:"text-foreground underline",to:"/admin/offline-videos",children:"Offline videos admin page"}),"."]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx(r,{method:"post",children:e.jsx(m,{varient:"primary",type:"submit",name:"intent",value:"download-offline-videos",disabled:t||a||s.totalVideos===0,children:t?"Downloading...":"Download all videos"})}),e.jsx(r,{method:"post",children:e.jsx("button",{type:"submit",name:"intent",value:"delete-offline-videos",disabled:a||s.downloadedVideos===0,className:"border-border text-foreground hover:bg-muted inline-flex items-center gap-2 rounded border px-3 py-2 text-sm disabled:cursor-not-allowed disabled:opacity-50",children:"Delete offline videos"})}),e.jsxs("span",{className:"text-muted-foreground text-sm",children:[s.downloadedVideos," of ",s.totalVideos," ","downloaded",x?` (${x})`:null]})]}),e.jsxs("div",{className:"text-muted-foreground text-sm",children:[s.downloadedVideos>0?e.jsxs("p",{children:["Downloaded size: ",u(s.totalBytes)]}):null,w?e.jsxs("p",{children:["Download all size:"," ",u(s.remainingDownloadBytes)]}):null]}),t?e.jsxs("div",{className:"text-muted-foreground text-sm",children:[e.jsxs("p",{children:["Downloading ",s.downloadState.completed," of"," ",s.downloadState.total," videos"]}),s.downloadState.current?e.jsxs("p",{className:"truncate",children:["Current: ",s.downloadState.current.title]}):null]}):null]})]})})});export{A as default};
2
+ //# sourceMappingURL=preferences-B7ND1VS9.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferences-B7ND1VS9.js","sources":["../../../app/routes/_app+/preferences.tsx"],"sourcesContent":["import {\n\tgetPreferences,\n\tsetPreferences,\n} from '@epic-web/workshop-utils/db.server'\nimport {\n\tgetOfflineVideoSummary,\n\tstartOfflineVideoDownload,\n\tdeleteOfflineVideosForWorkshop,\n} from '@epic-web/workshop-utils/offline-videos.server'\nimport {\n\tForm,\n\tLink,\n\tuseFetcher,\n\tuseLoaderData,\n\tuseNavigation,\n} from 'react-router'\nimport { Button } from '#app/components/button.tsx'\nimport { Icon } from '#app/components/icons.tsx'\nimport { SimpleTooltip } from '#app/components/ui/tooltip.tsx'\nimport { formatBytes } from '#app/utils/format.ts'\nimport { ensureUndeployed, useInterval } from '#app/utils/misc.tsx'\nimport { useRootLoaderData } from '#app/utils/root-loader.ts'\nimport { redirectWithToast } from '#app/utils/toast.server.ts'\nimport { type Route } from './+types/preferences.tsx'\n\nconst downloadResolutionOptions = [\n\t{ value: 'best', label: 'Best available' },\n\t{ value: 'high', label: 'High' },\n\t{ value: 'medium', label: 'Medium' },\n\t{ value: 'low', label: 'Low' },\n] as const\ntype DownloadResolutionOption =\n\t(typeof downloadResolutionOptions)[number]['value']\n\nfunction isDownloadResolutionOption(\n\tvalue: FormDataEntryValue | null,\n): value is DownloadResolutionOption {\n\treturn (\n\t\ttypeof value === 'string' &&\n\t\tdownloadResolutionOptions.some((option) => option.value === value)\n\t)\n}\n\nexport async function loader({ request }: Route.LoaderArgs) {\n\tensureUndeployed()\n\tconst [preferences, offlineVideos] = await Promise.all([\n\t\tgetPreferences(),\n\t\tgetOfflineVideoSummary({ request }),\n\t])\n\treturn { preferences, offlineVideos }\n}\n\nexport async function action({ request }: Route.ActionArgs) {\n\tensureUndeployed()\n\tconst formData = await request.formData()\n\tconst intent = formData.get('intent')\n\n\tif (intent === 'download-offline-videos') {\n\t\tconst result = await startOfflineVideoDownload({ request })\n\t\tif (result.queued === 0) {\n\t\t\tconst description =\n\t\t\t\tresult.available === 0\n\t\t\t\t\t? 'No downloadable videos were found for this workshop.'\n\t\t\t\t\t: result.unavailable > 0\n\t\t\t\t\t\t? 'All available videos are already downloaded. Some videos require access to download.'\n\t\t\t\t\t\t: 'All available videos are already downloaded.'\n\t\t\treturn redirectWithToast('/preferences', {\n\t\t\t\ttitle: 'Offline videos are ready',\n\t\t\t\tdescription,\n\t\t\t\ttype: 'success',\n\t\t\t})\n\t\t}\n\n\t\treturn redirectWithToast('/preferences', {\n\t\t\ttitle: 'Offline downloads started',\n\t\t\tdescription: `Queued ${result.queued} video${result.queued === 1 ? '' : 's'} for download.`,\n\t\t\ttype: 'success',\n\t\t})\n\t}\n\n\tif (intent === 'delete-offline-videos') {\n\t\tconst result = await deleteOfflineVideosForWorkshop()\n\t\tconst description =\n\t\t\tresult.deletedFiles === 0\n\t\t\t\t? 'No offline videos were removed.'\n\t\t\t\t: `Removed ${result.deletedFiles} offline video${\n\t\t\t\t\t\tresult.deletedFiles === 1 ? '' : 's'\n\t\t\t\t\t}.`\n\t\treturn redirectWithToast('/preferences', {\n\t\t\ttitle: 'Offline videos cleared',\n\t\t\tdescription,\n\t\t\ttype: 'success',\n\t\t})\n\t}\n\n\tconst minResolution = formData.get('minResolution')\n\tconst maxResolution = formData.get('maxResolution')\n\tconst downloadResolution = formData.get('downloadResolution')\n\tconst fontSize = formData.get('fontSize')\n\tconst optOutPresence = formData.get('optOutPresence') === 'on'\n\tconst persistPlayground = formData.get('persistPlayground') === 'on'\n\tconst dismissExerciseWarning = formData.get('dismissExerciseWarning') === 'on'\n\tconst downloadResolutionValue = isDownloadResolutionOption(downloadResolution)\n\t\t? downloadResolution\n\t\t: undefined\n\n\tawait setPreferences({\n\t\tplayer: {\n\t\t\tminResolution: minResolution ? Number(minResolution) : undefined,\n\t\t\tmaxResolution: maxResolution ? Number(maxResolution) : undefined,\n\t\t},\n\t\tofflineVideo: {\n\t\t\tdownloadResolution: downloadResolutionValue,\n\t\t},\n\t\tfontSize: fontSize ? Number(fontSize) : undefined,\n\t\tpresence: { optOut: optOutPresence },\n\t\tplayground: { persist: persistPlayground },\n\t\texerciseWarning: { dismissed: dismissExerciseWarning },\n\t})\n\n\treturn redirectWithToast('/preferences', {\n\t\ttitle: 'Preferences updated',\n\t\tdescription: 'Your preferences have been updated.',\n\t\ttype: 'success',\n\t})\n}\n\nexport default function AccountSettings() {\n\tconst loaderData = useLoaderData<typeof loader>()\n\tconst rootData = useRootLoaderData()\n\tconst playerPreferences = rootData.preferences?.player\n\tconst offlineVideoPreferences = rootData.preferences?.offlineVideo\n\tconst fontSizePreference = rootData.preferences?.fontSize\n\tconst presencePreferences = rootData.preferences?.presence\n\tconst playgroundPreferences = rootData.preferences?.playground\n\tconst exerciseWarningPreferences = rootData.preferences?.exerciseWarning\n\tconst navigation = useNavigation()\n\tconst offlineVideosFetcher = useFetcher<typeof loader>()\n\tconst offlineVideos =\n\t\tofflineVideosFetcher.data?.offlineVideos ?? loaderData.offlineVideos\n\tconst isDownloading = offlineVideos.downloadState.status === 'running'\n\tconst offlineVideoNotes = [\n\t\tofflineVideos.unavailableVideos > 0\n\t\t\t? `${offlineVideos.unavailableVideos} unavailable`\n\t\t\t: null,\n\t\tofflineVideos.notDownloadableVideos > 0\n\t\t\t? `${offlineVideos.notDownloadableVideos} not downloadable`\n\t\t\t: null,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(', ')\n\tconst showRemainingDownloadSize =\n\t\tofflineVideos.totalVideos > 0 &&\n\t\tofflineVideos.downloadedVideos < offlineVideos.totalVideos &&\n\t\tofflineVideos.remainingDownloadBytes > 0\n\n\tconst isSubmitting = navigation.state === 'submitting'\n\n\tuseInterval(\n\t\t() => {\n\t\t\tif (offlineVideosFetcher.state === 'idle') {\n\t\t\t\tvoid offlineVideosFetcher.load('/resources/offline-videos')\n\t\t\t}\n\t\t},\n\t\tisDownloading ? 2000 : null,\n\t)\n\n\treturn (\n\t\t<div className=\"h-full w-full overflow-y-auto\">\n\t\t\t<main className=\"container mt-12 flex w-full max-w-3xl grow flex-col gap-4 pb-24\">\n\t\t\t\t<h1 className=\"text-h1 mb-4\">Preferences</h1>\n\t\t\t\t<Form method=\"post\" className=\"flex w-full max-w-sm flex-col gap-4\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2 className=\"text-body-xl mb-2\">Video Player Preferences</h2>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<label htmlFor=\"minResolution\">Minimum Resolution:</label>\n\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\tid=\"minResolution\"\n\t\t\t\t\t\t\t\tname=\"minResolution\"\n\t\t\t\t\t\t\t\tdefaultValue={playerPreferences?.minResolution}\n\t\t\t\t\t\t\t\tclassName=\"border-border bg-background text-foreground rounded-md border px-2 py-1\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<option value=\"\">Auto</option>\n\t\t\t\t\t\t\t\t<option value=\"480\">480p</option>\n\t\t\t\t\t\t\t\t<option value=\"720\">720p</option>\n\t\t\t\t\t\t\t\t<option value=\"1080\">1080p</option>\n\t\t\t\t\t\t\t\t<option value=\"1440\">1440p</option>\n\t\t\t\t\t\t\t\t<option value=\"2160\">2160p (4K)</option>\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<label htmlFor=\"maxResolution\">Maximum Resolution:</label>\n\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\tid=\"maxResolution\"\n\t\t\t\t\t\t\t\tname=\"maxResolution\"\n\t\t\t\t\t\t\t\tdefaultValue={playerPreferences?.maxResolution}\n\t\t\t\t\t\t\t\tclassName=\"border-border bg-background text-foreground rounded-md border px-2 py-1\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<option value=\"\">Auto</option>\n\t\t\t\t\t\t\t\t<option value=\"720\">720p</option>\n\t\t\t\t\t\t\t\t<option value=\"1080\">1080p</option>\n\t\t\t\t\t\t\t\t<option value=\"1440\">1440p</option>\n\t\t\t\t\t\t\t\t<option value=\"2160\">2160p (4K)</option>\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h2 className=\"text-body-xl mb-2\">Offline Video Downloads</h2>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<label htmlFor=\"downloadResolution\">Download Resolution:</label>\n\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\tid=\"downloadResolution\"\n\t\t\t\t\t\t\t\tname=\"downloadResolution\"\n\t\t\t\t\t\t\t\tdefaultValue={\n\t\t\t\t\t\t\t\t\tofflineVideoPreferences?.downloadResolution ?? 'best'\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tclassName=\"border-border bg-background text-foreground rounded-md border px-2 py-1\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{downloadResolutionOptions.map((option) => (\n\t\t\t\t\t\t\t\t\t<option key={option.value} value={option.value}>\n\t\t\t\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p className=\"text-muted-foreground text-sm\">\n\t\t\t\t\t\t\tDefaults to the best available resolution.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"mb-2 flex items-center gap-2\">\n\t\t\t\t\t\t\t<h2 className=\"text-body-xl\">Font Size Preference</h2>\n\t\t\t\t\t\t\t<SimpleTooltip content=\"Defaults to 16px\">\n\t\t\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<label htmlFor=\"fontSize\">Font Size</label>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\t\tid=\"fontSize\"\n\t\t\t\t\t\t\t\tname=\"fontSize\"\n\t\t\t\t\t\t\t\tdefaultValue={fontSizePreference ?? 16}\n\t\t\t\t\t\t\t\tstep=\"1\"\n\t\t\t\t\t\t\t\tmin=\"12\"\n\t\t\t\t\t\t\t\tmax=\"26\"\n\t\t\t\t\t\t\t\tclassName=\"border-border bg-background text-foreground rounded-md border px-2 py-1\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"mb-2 flex items-center gap-2\">\n\t\t\t\t\t\t\t<h2 className=\"text-body-xl\">Presence Preference</h2>\n\n\t\t\t\t\t\t\t<SimpleTooltip content=\"This controls whether your name and avatar are displayed in the pile of faces in navigation\">\n\t\t\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tid=\"optOutPresence\"\n\t\t\t\t\t\t\t\tname=\"optOutPresence\"\n\t\t\t\t\t\t\t\tdefaultChecked={presencePreferences?.optOut}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<label htmlFor=\"optOutPresence\">\n\t\t\t\t\t\t\t\tOpt out of presence features\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"mb-2 flex items-center gap-2\">\n\t\t\t\t\t\t\t<h2 className=\"text-body-xl\">Persist Playground</h2>\n\n\t\t\t\t\t\t\t<SimpleTooltip\n\t\t\t\t\t\t\t\tcontent={`When enabled, clicking \"Set to Playground\" will save the current playground in the \"saved-playgrounds\" directory.`}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tid=\"persistPlayground\"\n\t\t\t\t\t\t\t\tname=\"persistPlayground\"\n\t\t\t\t\t\t\t\tdefaultChecked={playgroundPreferences?.persist}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<label htmlFor=\"persistPlayground\">\n\t\t\t\t\t\t\t\tEnable saving playground\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"mb-2 flex items-center gap-2\">\n\t\t\t\t\t\t\t<h2 className=\"text-body-xl\">Exercise Directory Warning</h2>\n\n\t\t\t\t\t\t\t<SimpleTooltip\n\t\t\t\t\t\t\t\tcontent={`When enabled, you'll see a warning banner when you have changes in the exercises directory. This helps remind you to work in the playground directory instead.`}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tid=\"dismissExerciseWarning\"\n\t\t\t\t\t\t\t\tname=\"dismissExerciseWarning\"\n\t\t\t\t\t\t\t\tdefaultChecked={exerciseWarningPreferences?.dismissed}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<label htmlFor=\"dismissExerciseWarning\">\n\t\t\t\t\t\t\t\tDismiss exercise directory warnings\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div className=\"h-4\" />\n\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvarient=\"primary\"\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tname=\"intent\"\n\t\t\t\t\t\tvalue=\"update-preferences\"\n\t\t\t\t\t\tdisabled={isSubmitting}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isSubmitting ? 'Updating...' : 'Update Preferences'}\n\t\t\t\t\t</Button>\n\t\t\t\t</Form>\n\n\t\t\t\t<section className=\"border-border mt-6 flex w-full max-w-xl flex-col gap-3 border-t pt-6\">\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<h2 className=\"text-body-xl\">Offline videos</h2>\n\t\t\t\t\t\t<SimpleTooltip content=\"Keep videos ready to watch when you're offline.\">\n\t\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t</div>\n\t\t\t\t\t<p className=\"text-muted-foreground text-sm\">\n\t\t\t\t\t\tDownload all workshop videos so you can watch them when offline.\n\t\t\t\t\t</p>\n\t\t\t\t\t<p className=\"text-muted-foreground text-sm\">\n\t\t\t\t\t\tAdmins can manage all downloaded videos on the{' '}\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tclassName=\"text-foreground underline\"\n\t\t\t\t\t\t\tto=\"/admin/offline-videos\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tOffline videos admin page\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t.\n\t\t\t\t\t</p>\n\t\t\t\t\t<div className=\"flex flex-wrap items-center gap-3\">\n\t\t\t\t\t\t<Form method=\"post\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvarient=\"primary\"\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tname=\"intent\"\n\t\t\t\t\t\t\t\tvalue=\"download-offline-videos\"\n\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\tisDownloading ||\n\t\t\t\t\t\t\t\t\tisSubmitting ||\n\t\t\t\t\t\t\t\t\tofflineVideos.totalVideos === 0\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{isDownloading ? 'Downloading...' : 'Download all videos'}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</Form>\n\t\t\t\t\t\t<Form method=\"post\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tname=\"intent\"\n\t\t\t\t\t\t\t\tvalue=\"delete-offline-videos\"\n\t\t\t\t\t\t\t\tdisabled={isSubmitting || offlineVideos.downloadedVideos === 0}\n\t\t\t\t\t\t\t\tclassName=\"border-border text-foreground hover:bg-muted inline-flex items-center gap-2 rounded border px-3 py-2 text-sm disabled:cursor-not-allowed disabled:opacity-50\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tDelete offline videos\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</Form>\n\t\t\t\t\t\t<span className=\"text-muted-foreground text-sm\">\n\t\t\t\t\t\t\t{offlineVideos.downloadedVideos} of {offlineVideos.totalVideos}{' '}\n\t\t\t\t\t\t\tdownloaded\n\t\t\t\t\t\t\t{offlineVideoNotes ? ` (${offlineVideoNotes})` : null}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"text-muted-foreground text-sm\">\n\t\t\t\t\t\t{offlineVideos.downloadedVideos > 0 ? (\n\t\t\t\t\t\t\t<p>Downloaded size: {formatBytes(offlineVideos.totalBytes)}</p>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{showRemainingDownloadSize ? (\n\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\tDownload all size:{' '}\n\t\t\t\t\t\t\t\t{formatBytes(offlineVideos.remainingDownloadBytes)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t\t{isDownloading ? (\n\t\t\t\t\t\t<div className=\"text-muted-foreground text-sm\">\n\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\tDownloading {offlineVideos.downloadState.completed} of{' '}\n\t\t\t\t\t\t\t\t{offlineVideos.downloadState.total} videos\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t{offlineVideos.downloadState.current ? (\n\t\t\t\t\t\t\t\t<p className=\"truncate\">\n\t\t\t\t\t\t\t\t\tCurrent: {offlineVideos.downloadState.current.title}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : null}\n\t\t\t\t</section>\n\t\t\t</main>\n\t\t</div>\n\t)\n}\n"],"names":["downloadResolutionOptions","value","label","preferences","_UNSAFE_withComponentProps","loaderData","useLoaderData","rootData","useRootLoaderData","playerPreferences","player","offlineVideoPreferences","offlineVideo","fontSizePreference","fontSize","presencePreferences","presence","playgroundPreferences","playground","exerciseWarningPreferences","exerciseWarning","navigation","useNavigation","offlineVideosFetcher","useFetcher","offlineVideos","data","isDownloading","downloadState","status","offlineVideoNotes","unavailableVideos","notDownloadableVideos","filter","Boolean","join","showRemainingDownloadSize","totalVideos","downloadedVideos","remainingDownloadBytes","isSubmitting","state","useInterval","load","className","children","jsxs","jsx","Form","method","htmlFor","id","name","defaultValue","minResolution","maxResolution","downloadResolution","map","option","SimpleTooltip","content","Icon","tabIndex","type","step","min","max","defaultChecked","optOut","persist","dismissed","Button","varient","disabled","Link","to","formatBytes","totalBytes","completed","total","current","title"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{r as a}from"./index-CqIc3cxq.js";import{I as n}from"./misc-W4055b-0.js";function d({exerciseNumber:r}){const[t,s]=a.useState(!1),i=r?`Please quiz me on exercise ${r} using the epicshop MCP server. Call the get_quiz_instructions tool with exerciseNumber "${r}" to get the quiz instructions, then quiz me one question at a time.`:"Please quiz me on this workshop using the epicshop MCP server. Call the get_quiz_instructions tool to get the quiz instructions, then quiz me one question at a time.";a.useEffect(()=>{if(t){const o=setTimeout(()=>s(!1),1e3);return()=>clearTimeout(o)}},[t]);const l=async()=>{try{await navigator.clipboard.writeText(i),s(!0)}catch(o){console.error("Failed to copy to clipboard:",o)}};return e.jsxs("div",{className:"border-border mt-6 border-t pt-6",children:[e.jsx("h2",{className:"text-foreground mb-3 text-xl font-semibold",children:"Test Your Knowledge"}),e.jsx("p",{className:"text-muted-foreground mb-4",children:"Retrieval practice helps solidify learning by actively recalling information. Use this prompt with your AI assistant to quiz yourself on what you've learned."}),e.jsxs("div",{className:"bg-background border-border relative mb-4 rounded-lg border p-4",children:[e.jsx("pre",{className:"text-foreground pr-10 text-sm break-words whitespace-pre-wrap",children:i}),e.jsx("button",{onClick:l,className:"text-muted-foreground hover:text-foreground absolute top-4 right-4 transition-colors","aria-label":t?"Copied!":"Copy prompt to clipboard",children:e.jsx(n,{name:t?"CheckSmall":"Copy",size:"sm"})})]}),e.jsx("p",{className:"text-muted-foreground text-sm",children:e.jsxs("a",{href:"https://www.epicai.pro/your-ai-assistant-instructor-the-epicshop-mcp-server-0eazr",target:"_blank",rel:"noopener noreferrer",className:"text-foreground inline-flex items-center gap-1.5 hover:underline",children:["Learn how to set up the epicshop MCP server",e.jsx(n,{name:"ExternalLink",size:"sm"})]})})]})}export{d as R};
2
+ //# sourceMappingURL=retrieval-practice-BOku32wW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieval-practice-BOku32wW.js","sources":["../../../app/components/retrieval-practice.tsx"],"sourcesContent":["import * as React from 'react'\nimport { Icon } from '#app/components/icons.tsx'\n\nexport function RetrievalPractice({\n\texerciseNumber,\n}: {\n\texerciseNumber?: number\n}) {\n\tconst [copied, setCopied] = React.useState(false)\n\n\tconst prompt = exerciseNumber\n\t\t? `Please quiz me on exercise ${exerciseNumber} using the epicshop MCP server. Call the get_quiz_instructions tool with exerciseNumber \"${exerciseNumber}\" to get the quiz instructions, then quiz me one question at a time.`\n\t\t: `Please quiz me on this workshop using the epicshop MCP server. Call the get_quiz_instructions tool to get the quiz instructions, then quiz me one question at a time.`\n\n\tReact.useEffect(() => {\n\t\tif (copied) {\n\t\t\tconst timeoutId = setTimeout(() => setCopied(false), 1000)\n\t\t\treturn () => clearTimeout(timeoutId)\n\t\t}\n\t}, [copied])\n\n\tconst handleCopy = async () => {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(prompt)\n\t\t\tsetCopied(true)\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to copy to clipboard:', error)\n\t\t}\n\t}\n\n\treturn (\n\t\t<div className=\"border-border mt-6 border-t pt-6\">\n\t\t\t<h2 className=\"text-foreground mb-3 text-xl font-semibold\">\n\t\t\t\tTest Your Knowledge\n\t\t\t</h2>\n\t\t\t<p className=\"text-muted-foreground mb-4\">\n\t\t\t\tRetrieval practice helps solidify learning by actively recalling\n\t\t\t\tinformation. Use this prompt with your AI assistant to quiz yourself on\n\t\t\t\twhat you've learned.\n\t\t\t</p>\n\t\t\t<div className=\"bg-background border-border relative mb-4 rounded-lg border p-4\">\n\t\t\t\t<pre className=\"text-foreground pr-10 text-sm break-words whitespace-pre-wrap\">\n\t\t\t\t\t{prompt}\n\t\t\t\t</pre>\n\t\t\t\t<button\n\t\t\t\t\tonClick={handleCopy}\n\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground absolute top-4 right-4 transition-colors\"\n\t\t\t\t\taria-label={copied ? 'Copied!' : 'Copy prompt to clipboard'}\n\t\t\t\t>\n\t\t\t\t\t<Icon name={copied ? 'CheckSmall' : 'Copy'} size=\"sm\" />\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<p className=\"text-muted-foreground text-sm\">\n\t\t\t\t<a\n\t\t\t\t\thref=\"https://www.epicai.pro/your-ai-assistant-instructor-the-epicshop-mcp-server-0eazr\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\tclassName=\"text-foreground inline-flex items-center gap-1.5 hover:underline\"\n\t\t\t\t>\n\t\t\t\t\tLearn how to set up the epicshop MCP server\n\t\t\t\t\t<Icon name=\"ExternalLink\" size=\"sm\" />\n\t\t\t\t</a>\n\t\t\t</p>\n\t\t</div>\n\t)\n}\n"],"names":["RetrievalPractice","exerciseNumber","copied","setCopied","React.useState","prompt","React.useEffect","timeoutId","handleCopy","error","jsxs","jsx","Icon"],"mappings":"6HAGO,SAASA,EAAkB,CACjC,eAAAC,CACD,EAEG,CACF,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAe,EAAK,EAE1CC,EAASJ,EACZ,8BAA8BA,CAAc,4FAA4FA,CAAc,uEACtJ,wKAEHK,EAAAA,UAAgB,IAAM,CACrB,GAAIJ,EAAQ,CACX,MAAMK,EAAY,WAAW,IAAMJ,EAAU,EAAK,EAAG,GAAI,EACzD,MAAO,IAAM,aAAaI,CAAS,CACpC,CACD,EAAG,CAACL,CAAM,CAAC,EAEX,MAAMM,EAAa,SAAY,CAC9B,GAAI,CACH,MAAM,UAAU,UAAU,UAAUH,CAAM,EAC1CF,EAAU,EAAI,CACf,OAASM,EAAO,CACf,QAAQ,MAAM,+BAAgCA,CAAK,CACpD,CACD,EAEA,OACCC,EAAAA,KAAC,MAAA,CAAI,UAAU,mCACd,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAG,UAAU,6CAA6C,SAAA,sBAE3D,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA6B,SAAA,gKAI1C,EACAD,EAAAA,KAAC,MAAA,CAAI,UAAU,kEACd,SAAA,CAAAC,EAAAA,IAAC,MAAA,CAAI,UAAU,gEACb,SAAAN,EACF,EACAM,EAAAA,IAAC,SAAA,CACA,QAASH,EACT,UAAU,uFACV,aAAYN,EAAS,UAAY,2BAEjC,eAACU,EAAA,CAAK,KAAMV,EAAS,aAAe,OAAQ,KAAK,IAAA,CAAK,CAAA,CAAA,CACvD,EACD,EACAS,EAAAA,IAAC,IAAA,CAAE,UAAU,gCACZ,SAAAD,EAAAA,KAAC,IAAA,CACA,KAAK,oFACL,OAAO,SACP,IAAI,sBACJ,UAAU,mEACV,SAAA,CAAA,8CAEAC,EAAAA,IAACC,EAAA,CAAK,KAAK,eAAe,KAAK,IAAA,CAAK,CAAA,CAAA,CAAA,CACrC,CACD,CAAA,EACD,CAEF"}
@@ -1,3 +1,3 @@
1
1
  const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index.client-CsIUPfXc.js","assets/index-CqIc3cxq.js"])))=>i.map(i=>d[i]);
2
- import{_ as Y}from"./preload-helper-BXl3LOEh.js";import{L as Q,f as L,w as H,a as $,b as q,k as z,O as K,M as X,P as J,S as Z,Q as ee}from"./chunk-EPOLDU6W-BCLmut3y.js";import{j as a}from"./jsx-runtime-C5WNSv3b.js";import{g as te,R as O,r as f}from"./index-CqIc3cxq.js";import{I as B,d as ne,u as re,c as ie}from"./misc-W4055b-0.js";import{C as se}from"./client-only-BeMV-Wuv.js";import{G as oe}from"./error-boundary-DxHqAEHX.js";import{D as ae,a as ce,b as ue,c as le,d as fe}from"./dialog-CzO65Z5w.js";import{E as he}from"./progress-bar-DpWhcyhC.js";import{T as de,t as h}from"./index-DzdDahau.js";import{m as pe}from"./tooltip-Tlsyx2YO.js";import{o as me,s as ve,j as xe}from"./schemas-Uj5SZtvt.js";import{u as ge,C as ye}from"./index-CdzVFL-Z.js";import{P as we}from"./presence-VCvV2mg7.js";import{g as ke}from"./seo-t5J-DRxw.js";import"./pe-CIZUOJMr.js";import"./index-ynYvVAOK.js";import"./index-vDCSPjrM.js";import"./root-loader-BOzEMapJ.js";import"./online-DiNLkgTC.js";import"./coerce-CkHW0SMv.js";var _,A;function je(){if(A)return _;A=1;var s={linear:function(e,n,t,i){var r=t-n;return r*e/i+n},easeInQuad:function(e,n,t,i){var r=t-n;return r*(e/=i)*e+n},easeOutQuad:function(e,n,t,i){var r=t-n;return-r*(e/=i)*(e-2)+n},easeInOutQuad:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?r/2*e*e+n:-r/2*(--e*(e-2)-1)+n},easeInCubic:function(e,n,t,i){var r=t-n;return r*(e/=i)*e*e+n},easeOutCubic:function(e,n,t,i){var r=t-n;return r*((e=e/i-1)*e*e+1)+n},easeInOutCubic:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?r/2*e*e*e+n:r/2*((e-=2)*e*e+2)+n},easeInQuart:function(e,n,t,i){var r=t-n;return r*(e/=i)*e*e*e+n},easeOutQuart:function(e,n,t,i){var r=t-n;return-r*((e=e/i-1)*e*e*e-1)+n},easeInOutQuart:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?r/2*e*e*e*e+n:-r/2*((e-=2)*e*e*e-2)+n},easeInQuint:function(e,n,t,i){var r=t-n;return r*(e/=i)*e*e*e*e+n},easeOutQuint:function(e,n,t,i){var r=t-n;return r*((e=e/i-1)*e*e*e*e+1)+n},easeInOutQuint:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?r/2*e*e*e*e*e+n:r/2*((e-=2)*e*e*e*e+2)+n},easeInSine:function(e,n,t,i){var r=t-n;return-r*Math.cos(e/i*(Math.PI/2))+r+n},easeOutSine:function(e,n,t,i){var r=t-n;return r*Math.sin(e/i*(Math.PI/2))+n},easeInOutSine:function(e,n,t,i){var r=t-n;return-r/2*(Math.cos(Math.PI*e/i)-1)+n},easeInExpo:function(e,n,t,i){var r=t-n;return e==0?n:r*Math.pow(2,10*(e/i-1))+n},easeOutExpo:function(e,n,t,i){var r=t-n;return e==i?n+r:r*(-Math.pow(2,-10*e/i)+1)+n},easeInOutExpo:function(e,n,t,i){var r=t-n;return e===0?n:e===i?n+r:(e/=i/2)<1?r/2*Math.pow(2,10*(e-1))+n:r/2*(-Math.pow(2,-10*--e)+2)+n},easeInCirc:function(e,n,t,i){var r=t-n;return-r*(Math.sqrt(1-(e/=i)*e)-1)+n},easeOutCirc:function(e,n,t,i){var r=t-n;return r*Math.sqrt(1-(e=e/i-1)*e)+n},easeInOutCirc:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?-r/2*(Math.sqrt(1-e*e)-1)+n:r/2*(Math.sqrt(1-(e-=2)*e)+1)+n},easeInElastic:function(e,n,t,i){var r=t-n,o,c,u;return u=1.70158,c=0,o=r,e===0?n:(e/=i)===1?n+r:(c||(c=i*.3),o<Math.abs(r)?(o=r,u=c/4):u=c/(2*Math.PI)*Math.asin(r/o),-(o*Math.pow(2,10*(e-=1))*Math.sin((e*i-u)*(2*Math.PI)/c))+n)},easeOutElastic:function(e,n,t,i){var r=t-n,o,c,u;return u=1.70158,c=0,o=r,e===0?n:(e/=i)===1?n+r:(c||(c=i*.3),o<Math.abs(r)?(o=r,u=c/4):u=c/(2*Math.PI)*Math.asin(r/o),o*Math.pow(2,-10*e)*Math.sin((e*i-u)*(2*Math.PI)/c)+r+n)},easeInOutElastic:function(e,n,t,i){var r=t-n,o,c,u;return u=1.70158,c=0,o=r,e===0?n:(e/=i/2)===2?n+r:(c||(c=i*(.3*1.5)),o<Math.abs(r)?(o=r,u=c/4):u=c/(2*Math.PI)*Math.asin(r/o),e<1?-.5*(o*Math.pow(2,10*(e-=1))*Math.sin((e*i-u)*(2*Math.PI)/c))+n:o*Math.pow(2,-10*(e-=1))*Math.sin((e*i-u)*(2*Math.PI)/c)*.5+r+n)},easeInBack:function(e,n,t,i,r){var o=t-n;return r===void 0&&(r=1.70158),o*(e/=i)*e*((r+1)*e-r)+n},easeOutBack:function(e,n,t,i,r){var o=t-n;return r===void 0&&(r=1.70158),o*((e=e/i-1)*e*((r+1)*e+r)+1)+n},easeInOutBack:function(e,n,t,i,r){var o=t-n;return r===void 0&&(r=1.70158),(e/=i/2)<1?o/2*(e*e*(((r*=1.525)+1)*e-r))+n:o/2*((e-=2)*e*(((r*=1.525)+1)*e+r)+2)+n},easeInBounce:function(e,n,t,i){var r=t-n,o;return o=s.easeOutBounce(i-e,0,r,i),r-o+n},easeOutBounce:function(e,n,t,i){var r=t-n;return(e/=i)<1/2.75?r*(7.5625*e*e)+n:e<2/2.75?r*(7.5625*(e-=1.5/2.75)*e+.75)+n:e<2.5/2.75?r*(7.5625*(e-=2.25/2.75)*e+.9375)+n:r*(7.5625*(e-=2.625/2.75)*e+.984375)+n},easeInOutBounce:function(e,n,t,i){var r=t-n,o;return e<i/2?(o=s.easeInBounce(e*2,0,r,i),o*.5+n):(o=s.easeOutBounce(e*2-i,0,r,i),o*.5+r*.5+n)}};return _=s,_}var Pe=je();const Ie=te(Pe);function Oe(s,e){for(var n=0;n<e.length;n++){var t=e[n];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(s,t.key,t)}}function be(s,e,n){return e&&Oe(s.prototype,e),s}function b(){return b=Object.assign||function(s){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&(s[t]=n[t])}return s},b.apply(this,arguments)}function Se(s,e){s.prototype=Object.create(e.prototype),s.prototype.constructor=s,R(s,e)}function R(s,e){return R=Object.setPrototypeOf||function(t,i){return t.__proto__=i,t},R(s,e)}function Ne(s){return s*Math.PI/180}function d(s,e){return s+Math.random()*(e-s)}function Ce(s,e){return Math.floor(s+Math.random()*(e-s+1))}var I;(function(s){s[s.Circle=0]="Circle",s[s.Square=1]="Square",s[s.Strip=2]="Strip"})(I||(I={}));var x;(function(s){s[s.Positive=1]="Positive",s[s.Negative=-1]="Negative"})(x||(x={}));var Ee=(function(){function s(n,t,i,r){this.getOptions=t;var o=this.getOptions(),c=o.colors,u=o.initialVelocityX,l=o.initialVelocityY;this.context=n,this.x=i,this.y=r,this.w=d(5,20),this.h=d(5,20),this.radius=d(5,10),this.vx=d(-u,u),this.vy=d(-l,0),this.shape=Ce(0,2),this.angle=Ne(d(0,360)),this.angularSpin=d(-.2,.2),this.color=c[Math.floor(Math.random()*c.length)],this.rotateY=d(0,1),this.rotationDirection=d(0,1)?x.Positive:x.Negative}var e=s.prototype;return e.update=function(){var t=this.getOptions(),i=t.gravity,r=t.wind,o=t.friction,c=t.opacity,u=t.drawShape;this.x+=this.vx,this.y+=this.vy,this.vy+=i,this.vx+=r,this.vx*=o,this.vy*=o,this.rotateY>=1&&this.rotationDirection===x.Positive?this.rotationDirection=x.Negative:this.rotateY<=-1&&this.rotationDirection===x.Negative&&(this.rotationDirection=x.Positive);var l=.1*this.rotationDirection;if(this.rotateY+=l,this.angle+=this.angularSpin,this.context.save(),this.context.translate(this.x,this.y),this.context.rotate(this.angle),this.context.scale(1,this.rotateY),this.context.rotate(this.angle),this.context.beginPath(),this.context.fillStyle=this.color,this.context.strokeStyle=this.color,this.context.globalAlpha=c,this.context.lineCap="round",this.context.lineWidth=2,u&&typeof u=="function")u.call(this,this.context);else switch(this.shape){case I.Circle:{this.context.beginPath(),this.context.arc(0,0,this.radius,0,2*Math.PI),this.context.fill();break}case I.Square:{this.context.fillRect(-this.w/2,-this.h/2,this.w,this.h);break}case I.Strip:{this.context.fillRect(-this.w/6,-this.h/2,this.w/3,this.h);break}default:throw new Error("Unknown type in Particle.ts")}this.context.closePath(),this.context.restore()},s})(),Me=function(e,n){var t=this;this.x=0,this.y=0,this.w=0,this.h=0,this.lastNumberOfPieces=0,this.tweenInitTime=Date.now(),this.particles=[],this.particlesGenerated=0,this.removeParticleAt=function(r){t.particles.splice(r,1)},this.getParticle=function(){var r=d(t.x,t.w+t.x),o=d(t.y,t.h+t.y);return new Ee(t.context,t.getOptions,r,o)},this.animate=function(){var r=t.canvas,o=t.context,c=t.particlesGenerated,u=t.lastNumberOfPieces,l=t.getOptions(),w=l.run,S=l.recycle,p=l.numberOfPieces,C=l.debug,m=l.tweenFunction,y=l.tweenDuration;if(!w)return!1;var g=t.particles.length,v=S?g:c,N=Date.now();if(v<p){u!==p&&(t.tweenInitTime=N,t.lastNumberOfPieces=p);for(var k=t.tweenInitTime,E=N-k>y?y:Math.max(0,N-k),M=m(E,v,p,y),j=Math.round(M-v),G=0;G<j;G+=1)t.particles.push(t.getParticle());t.particlesGenerated+=j}return C&&(o.font="12px sans-serif",o.fillStyle="#333",o.textAlign="right",o.fillText("Particles: "+g,r.width-10,r.height-20)),t.particles.forEach(function(P,U){P.update(),(P.y>r.height||P.y<-100||P.x>r.width+100||P.x<-100)&&(S&&v<=p?t.particles[U]=t.getParticle():t.removeParticleAt(U))}),g>0||v<p},this.canvas=e;var i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get canvas context");this.context=i,this.getOptions=n},T={width:typeof window<"u"?window.innerWidth:300,height:typeof window<"u"?window.innerHeight:200,numberOfPieces:200,friction:.99,wind:0,gravity:.1,initialVelocityX:4,initialVelocityY:10,colors:["#f44336","#e91e63","#9c27b0","#673ab7","#3f51b5","#2196f3","#03a9f4","#00bcd4","#009688","#4CAF50","#8BC34A","#CDDC39","#FFEB3B","#FFC107","#FF9800","#FF5722","#795548"],opacity:1,debug:!1,tweenFunction:Ie.easeInOutQuad,tweenDuration:5e3,recycle:!0,run:!0},_e=(function(){function s(e,n){var t=this;this.setOptionsWithDefaults=function(r){var o={confettiSource:{x:0,y:0,w:t.canvas.width,h:0}};t._options=b({},o,T,r),Object.assign(t,r.confettiSource)},this.update=function(){var r=t.options,o=r.run,c=r.onConfettiComplete,u=t.canvas,l=t.context;o&&(l.fillStyle="white",l.clearRect(0,0,u.width,u.height)),t.generator.animate()?t.rafId=requestAnimationFrame(t.update):(c&&typeof c=="function"&&t.generator.particlesGenerated>0&&c.call(t,t),t._options.run=!1)},this.reset=function(){t.generator&&t.generator.particlesGenerated>0&&(t.generator.particlesGenerated=0,t.generator.particles=[],t.generator.lastNumberOfPieces=0)},this.stop=function(){t.options={run:!1},t.rafId&&(cancelAnimationFrame(t.rafId),t.rafId=void 0)},this.canvas=e;var i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get canvas context");this.context=i,this.generator=new Me(this.canvas,function(){return t.options}),this.options=n,this.update()}return be(s,[{key:"options",get:function(){return this._options},set:function(n){var t=this._options&&this._options.run,i=this._options&&this._options.recycle;this.setOptionsWithDefaults(n),this.generator&&(Object.assign(this.generator,this.options.confettiSource),typeof n.recycle=="boolean"&&n.recycle&&i===!1&&(this.generator.lastNumberOfPieces=this.generator.particles.length)),typeof n.run=="boolean"&&n.run&&t===!1&&this.update()}}]),s})(),W=O.createRef();function D(s){var e={},n={},t={},i=[].concat(Object.keys(T),["confettiSource","drawShape","onConfettiComplete"]),r=["canvasRef"];return Object.keys(s).forEach(function(o){var c=s[o];i.includes(o)?e[o]=c:r.includes(o)?r[o]=c:t[o]=c}),[e,t,n]}var F=(function(s){Se(e,s);function e(t){var i;return i=s.call(this,t)||this,i.canvas=O.createRef(),i.canvas=t.canvasRef||W,i}var n=e.prototype;return n.componentDidMount=function(){if(this.canvas.current){var i=D(this.props)[0];this.confetti=new _e(this.canvas.current,i)}},n.componentDidUpdate=function(){var i=D(this.props)[0];this.confetti&&(this.confetti.options=i)},n.componentWillUnmount=function(){this.confetti&&this.confetti.stop(),this.confetti=void 0},n.render=function(){var i=D(this.props),r=i[0],o=i[1],c=b({zIndex:2,position:"absolute",pointerEvents:"none",top:0,left:0,bottom:0,right:0},o.style);return O.createElement("canvas",Object.assign({width:r.width,height:r.height,ref:this.canvas},o,{style:c}))},e})(f.Component);F.defaultProps=b({},T);F.displayName="ConfettiReact";var De=O.forwardRef(function(s,e){return O.createElement(F,Object.assign({canvasRef:W},s))});function Re({id:s}){return s?a.jsx(se,{children:()=>a.jsx(De,{run:!!s,recycle:!1,numberOfPieces:800,width:window.innerWidth,height:window.innerHeight},s)}):null}function Te(){return a.jsx("div",{className:"border-destructive bg-destructive fixed top-0 right-0 left-0 z-50 border-b",children:a.jsxs("div",{className:"relative w-full p-4",children:[a.jsx(Q,{to:"/workspace-structure",className:"absolute inset-0 z-10 block h-full w-full","aria-label":"Learn more about workspace structure"}),a.jsxs("div",{className:"relative z-0 container flex items-center justify-between",children:[a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsx(B,{name:"Error",className:"text-destructive-foreground h-5 w-5"}),a.jsxs("div",{children:[a.jsx("h3",{className:"text-destructive-foreground text-sm font-semibold",children:"Warning: Changes detected in exercises directory"}),a.jsx("p",{className:"text-destructive-foreground/80 text-xs",children:"You should typically work in the playground directory, not the exercises directory."})]})]}),a.jsxs("div",{className:"text-destructive-foreground flex items-center gap-2 text-xs",children:[a.jsx("span",{children:"Learn more"}),a.jsx(B,{name:"ArrowRight",className:"h-3 w-3"})]})]})]})})}const Fe=[{title:"Navigation",shortcuts:[{keys:["g","h"],description:"Go to home"},{keys:["g","1-9"],description:"Go to exercise (e.g., g+1 → /exercise/01)"},{keys:["g","1-9",".","1-9"],description:"Go to exercise step (e.g., g+1+.+2 → /exercise/01/02/problem)"},{keys:["g","1-9",".","f"],description:"Go to exercise finished page (e.g., g+1+.+f → /exercise/01/finished)"},{keys:["g","p"],description:"Go to previous step/page"},{keys:["g","n"],description:"Go to next step/page"},{keys:["g","a"],description:"Go to account page"},{keys:["g","d"],description:"Go to admin page"},{keys:["g","l"],description:"Go to last exercise solution"},{keys:["Escape"],description:"Close sidebar navigation (when open)"}]},{title:"Playback Controls",shortcuts:[{keys:["Space","k"],description:"Play/pause video"},{keys:["j"],description:"Seek backward 10 seconds"},{keys:["l"],description:"Seek forward 10 seconds"},{keys:["←"],description:"Seek backward 10 seconds"},{keys:["→"],description:"Seek forward 10 seconds"}]},{title:"Frame-by-Frame Navigation",shortcuts:[{keys:[","],description:"Go to previous frame (when paused)"},{keys:["."],description:"Go to next frame (when paused)"}]},{title:"Volume Control",shortcuts:[{keys:["↑"],description:"Increase volume by 10%"},{keys:["↓"],description:"Decrease volume by 10%"}]},{title:"Playback Speed",shortcuts:[{keys:["Shift",">"],description:"Increase playback speed"},{keys:["Shift","<"],description:"Decrease playback speed"}]},{title:"Fullscreen and Picture-in-Picture",shortcuts:[{keys:["f"],description:"Toggle fullscreen mode"},{keys:["i"],description:"Toggle picture-in-picture mode"}]},{title:"Captions",shortcuts:[{keys:["c"],description:"Toggle captions/subtitles"}]},{title:"Quick Seek",shortcuts:[{keys:["0-9"],description:"Seek to percentage of video (0 = 0%, 1 = 10%, ..., 9 = 90%)"}]}];function Ge({open:s,onOpenChange:e}){return a.jsx(ae,{open:s,onOpenChange:e,children:a.jsxs(ce,{className:"max-h-[80vh] max-w-2xl overflow-y-auto",children:[a.jsxs(ue,{children:[a.jsx(le,{children:"Keyboard Shortcuts"}),a.jsxs(fe,{children:["Use these keyboard shortcuts to navigate and control the video player. Press"," ",a.jsx("kbd",{className:"border-border bg-muted rounded border px-1.5 py-0.5 font-mono text-xs",children:"?"})," ","or select the question mark icon in the navigation to open this list."]})]}),a.jsx("div",{className:"space-y-6",children:Fe.map(n=>a.jsxs("div",{children:[a.jsx("h3",{className:"text-foreground mb-3 text-sm font-semibold",children:n.title}),a.jsx("div",{className:"space-y-2",children:n.shortcuts.map((t,i)=>a.jsxs("div",{className:"flex items-center justify-between gap-4",children:[a.jsx("span",{className:"text-muted-foreground flex-1 text-sm",children:t.description}),a.jsx("div",{className:"flex shrink-0 items-center gap-1",children:t.keys.map((r,o)=>a.jsxs(f.Fragment,{children:[a.jsx("kbd",{className:"border-border bg-muted rounded border px-2 py-1 font-mono text-xs",children:r}),o<t.keys.length-1&&a.jsx("span",{className:"text-muted-foreground",children:"+"})]},o))})]},i))})]},n.title))}),a.jsx("div",{className:"border-border mt-4 border-t pt-4",children:a.jsxs("p",{className:"text-muted-foreground text-xs",children:[a.jsx("strong",{children:"Note:"})," Shortcuts are ignored when focus is on interactive elements (inputs, buttons, etc.). Press"," ",a.jsx("kbd",{className:"border-border bg-muted rounded border px-1.5 py-0.5 font-mono text-xs",children:"?"})," ","to toggle this dialog."]})})]})})}function Ue({toast:s}){return a.jsxs(a.Fragment,{children:[a.jsx(de,{closeButton:!0,position:"top-center"}),s?a.jsx(Be,{toast:s}):null]})}function Be({toast:s}){const{id:e,type:n,title:t,description:i}=s;return f.useEffect(()=>{setTimeout(()=>{h[n](t,{id:e,description:i})},0)},[i,e,t,n]),null}function Ae({repoUpdates:s}){const{updatesAvailable:e,repoUpdatesAvailable:n,dependenciesNeedInstall:t,updateNotificationId:i,diffLink:r}=s,o=L(),c=f.useRef(o);f.useEffect(()=>{c.current=o},[o]);const u=f.useRef(null),l=f.useRef(null),w=f.useRef(!1);return f.useEffect(()=>{if(e&&i){l.current&&(h.dismiss(l.current),l.current=null);const S=n?"New workshop updates available":"Dependencies out of date",p=n?a.jsxs("div",{children:[t?"Get the latest updates and reinstall dependencies by clicking the update button. ":"Get the latest updates by clicking the update button. ",r?a.jsx("a",{href:r,target:"_blank",rel:"noreferrer",className:"text-xs underline",children:"View changes"}):null]}):a.jsxs("div",{children:["Your installed packages don't match package.json. ","Click the update button to reinstall dependencies."]}),C=h.info(S,{duration:1/0,description:p,onDismiss:()=>{},action:{label:"Update",onClick:async()=>{if(l.current&&(h.dismiss(l.current),l.current=null),u.current||(u.current=h.loading("Update in progress...")),!w.current){w.current=!0;try{const{EPICSHOP_PARENT_PORT:m,EPICSHOP_PARENT_TOKEN:y}=window.ENV||{};if(!m||!y)throw new Error("Update API not available");const g=await fetch(`http://localhost:${m}/__epicshop-restart`,{method:"POST",headers:{"x-epicshop-token":y}});if(!g.ok)throw new Error(`Request to update workshop failed: ${g.statusText}`);const v=await g.json().catch(()=>({})),k=me({status:xe(["ok","error"]),message:ve().optional()}).safeParse(v);if(!k.success)throw console.error("Invalid response from update API",v),new Error("Invalid response from update API");const{status:E,message:M}=k.data;if(E==="ok"){let j=!1;h.success("Workshop updated",{description:"Reloading in 2 seconds... You can reload now if you prefer.",duration:2e3,action:{label:"Reload now",onClick:()=>{j=!0,window.location.reload()}},onAutoClose:()=>{j||window.location.reload()}})}else h.error("Failed to update workshop",{description:M||"Unknown error"})}catch(m){h.error("Failed to update workshop",{description:m instanceof Error?m.message:String(m)})}finally{w.current=!1,u.current&&(h.dismiss(u.current),u.current=null)}}}},cancel:{label:"Dismiss",onClick:()=>{l.current&&(h.dismiss(l.current),l.current=null),c.current.submit({intent:"mute",id:i},{method:"post",action:"/admin/notifications"})}}});l.current=C}},[e,i,n,t,r]),null}function Le({unmutedNotifications:s}){const e=L(),n=f.useRef(e),t=f.useRef(new Set);return f.useEffect(()=>{for(const i of s)t.current.has(i.id)||(t.current.add(i.id),h.info(i.title,{id:i.id,description:a.jsxs("div",{children:[a.jsx("p",{children:i.message}),i.link&&a.jsx("a",{href:i.link,target:"_blank",className:"text-xs underline",children:"Learn more"})]}),duration:1/0,action:{label:"Dismiss",onClick:()=>{n.current.submit({intent:"mute",id:i.id},{method:"post",action:"/admin/notifications"})}}}))},[s]),null}const qe="/assets/app-BUxWY8xC.css",We="/assets/tailwind-C1_1LEqo.css",Ve="unknown@example.com";function Ye({user:s,userId:e}){const n=s?.id??e?.id??void 0,t=s?.email&&s.email!==Ve?s.email:void 0;if(!n&&!t)return null;const i={};return n&&(i.id=n),t&&(i.email=t),i}const pt=()=>[{rel:"stylesheet",href:"/neogrotesk-font.css"},{rel:"stylesheet",href:"https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,200;0,300;0,400;0,500;0,600;1,700&display=swap"},{rel:"stylesheet",href:We},{rel:"stylesheet",href:qe},{rel:"icon",href:"/favicon.ico",sizes:"48x48"},{rel:"icon",type:"image/svg+xml",href:"/favicon.svg"}],mt=({loaderData:s})=>s?ke({instructor:s.instructor,title:s.workshopTitle,description:s.workshopSubtitle,requestInfo:s.requestInfo}):[];function V({children:s,env:e={},className:n,style:t}){return a.jsxs("html",{lang:"en",className:n,style:t,children:[a.jsxs("head",{children:[a.jsx(ye,{}),a.jsx(X,{}),a.jsx("meta",{charSet:"utf-8"}),a.jsx("meta",{name:"viewport",content:"width=device-width,initial-scale=1"}),a.jsx(J,{}),a.jsx("script",{dangerouslySetInnerHTML:{__html:`window.ENV = ${JSON.stringify(e)}`}})]}),a.jsxs("body",{className:"bg-background text-foreground scrollbar-thin scrollbar-thumb-scrollbar h-screen-safe",children:[s,a.jsx(Z,{}),a.jsx(ee,{})]})]})}function Qe(){const s=q(),e=z(),n=ne.useSpinDelay(e.state!=="idle",{delay:400,minDuration:200}),t=re(),[i,r]=f.useState(!1);f.useEffect(()=>{const c=()=>{r(u=>!u)};return window.addEventListener("toggle-keyboard-shortcuts",c),()=>{window.removeEventListener("toggle-keyboard-shortcuts",c)}},[]),f.useEffect(()=>{if(!ENV.EPICSHOP_IS_PUBLISHED)return;const c=Ye({user:s.user,userId:s.userId});Y(()=>import("./index.client-CsIUPfXc.js"),__vite__mapDeps([0,1])).then(u=>{c?u.setUser(c):u.setUser(null)}).catch(()=>{})},[s.user,s.userId]);const o=ge();return a.jsxs(V,{style:s.preferences?.fontSize?{fontSize:`${s.preferences?.fontSize}px`}:{},className:ie("h-screen-safe antialiased",o,{"cursor-progress":n},t?"alt-down":null),env:s.ENV,children:[s.exerciseChanges&&!s.preferences?.exerciseWarning?.dismissed&&a.jsx(Te,{}),a.jsx(K,{}),a.jsx(Re,{id:s.confettiId}),a.jsx(Ue,{toast:s.toast}),a.jsx(Ae,{repoUpdates:s.repoUpdates}),a.jsx(he,{}),a.jsx(Le,{unmutedNotifications:s.unmutedNotifications}),a.jsx(Ge,{open:i,onOpenChange:r})]})}const vt=H(function(){const{user:e}=q();return a.jsx(we,{user:e,children:a.jsx(pe,{children:a.jsx(Qe,{})})})}),xt=$(function(){return a.jsx(V,{className:"h-screen-safe",children:a.jsx(oe,{})})});export{xt as ErrorBoundary,vt as default,pt as links,mt as meta};
3
- //# sourceMappingURL=root-CKcj2hDc.js.map
2
+ import{_ as Y}from"./preload-helper-BXl3LOEh.js";import{L as Q,f as q,w as H,a as $,b as L,k as z,O as K,M as X,P as J,S as Z,Q as ee}from"./chunk-EPOLDU6W-BCLmut3y.js";import{j as a}from"./jsx-runtime-C5WNSv3b.js";import{g as te,R as O,r as f}from"./index-CqIc3cxq.js";import{I as B,d as ne,u as re,c as ie}from"./misc-W4055b-0.js";import{C as se}from"./client-only-BeMV-Wuv.js";import{G as oe}from"./error-boundary-DxHqAEHX.js";import{D as ae,a as ce,b as ue,c as le,d as fe}from"./dialog-CzO65Z5w.js";import{E as he}from"./progress-bar-DpWhcyhC.js";import{T as de,t as h}from"./index-DzdDahau.js";import{m as pe}from"./tooltip-Tlsyx2YO.js";import{o as me,s as ve,j as xe}from"./schemas-Uj5SZtvt.js";import{u as ge,C as ye}from"./index-CdzVFL-Z.js";import{P as we}from"./presence-VCvV2mg7.js";import{g as ke}from"./seo-t5J-DRxw.js";import"./pe-CIZUOJMr.js";import"./index-ynYvVAOK.js";import"./index-vDCSPjrM.js";import"./root-loader-BOzEMapJ.js";import"./online-DiNLkgTC.js";import"./coerce-CkHW0SMv.js";var _,A;function je(){if(A)return _;A=1;var s={linear:function(e,n,t,i){var r=t-n;return r*e/i+n},easeInQuad:function(e,n,t,i){var r=t-n;return r*(e/=i)*e+n},easeOutQuad:function(e,n,t,i){var r=t-n;return-r*(e/=i)*(e-2)+n},easeInOutQuad:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?r/2*e*e+n:-r/2*(--e*(e-2)-1)+n},easeInCubic:function(e,n,t,i){var r=t-n;return r*(e/=i)*e*e+n},easeOutCubic:function(e,n,t,i){var r=t-n;return r*((e=e/i-1)*e*e+1)+n},easeInOutCubic:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?r/2*e*e*e+n:r/2*((e-=2)*e*e+2)+n},easeInQuart:function(e,n,t,i){var r=t-n;return r*(e/=i)*e*e*e+n},easeOutQuart:function(e,n,t,i){var r=t-n;return-r*((e=e/i-1)*e*e*e-1)+n},easeInOutQuart:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?r/2*e*e*e*e+n:-r/2*((e-=2)*e*e*e-2)+n},easeInQuint:function(e,n,t,i){var r=t-n;return r*(e/=i)*e*e*e*e+n},easeOutQuint:function(e,n,t,i){var r=t-n;return r*((e=e/i-1)*e*e*e*e+1)+n},easeInOutQuint:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?r/2*e*e*e*e*e+n:r/2*((e-=2)*e*e*e*e+2)+n},easeInSine:function(e,n,t,i){var r=t-n;return-r*Math.cos(e/i*(Math.PI/2))+r+n},easeOutSine:function(e,n,t,i){var r=t-n;return r*Math.sin(e/i*(Math.PI/2))+n},easeInOutSine:function(e,n,t,i){var r=t-n;return-r/2*(Math.cos(Math.PI*e/i)-1)+n},easeInExpo:function(e,n,t,i){var r=t-n;return e==0?n:r*Math.pow(2,10*(e/i-1))+n},easeOutExpo:function(e,n,t,i){var r=t-n;return e==i?n+r:r*(-Math.pow(2,-10*e/i)+1)+n},easeInOutExpo:function(e,n,t,i){var r=t-n;return e===0?n:e===i?n+r:(e/=i/2)<1?r/2*Math.pow(2,10*(e-1))+n:r/2*(-Math.pow(2,-10*--e)+2)+n},easeInCirc:function(e,n,t,i){var r=t-n;return-r*(Math.sqrt(1-(e/=i)*e)-1)+n},easeOutCirc:function(e,n,t,i){var r=t-n;return r*Math.sqrt(1-(e=e/i-1)*e)+n},easeInOutCirc:function(e,n,t,i){var r=t-n;return(e/=i/2)<1?-r/2*(Math.sqrt(1-e*e)-1)+n:r/2*(Math.sqrt(1-(e-=2)*e)+1)+n},easeInElastic:function(e,n,t,i){var r=t-n,o,c,u;return u=1.70158,c=0,o=r,e===0?n:(e/=i)===1?n+r:(c||(c=i*.3),o<Math.abs(r)?(o=r,u=c/4):u=c/(2*Math.PI)*Math.asin(r/o),-(o*Math.pow(2,10*(e-=1))*Math.sin((e*i-u)*(2*Math.PI)/c))+n)},easeOutElastic:function(e,n,t,i){var r=t-n,o,c,u;return u=1.70158,c=0,o=r,e===0?n:(e/=i)===1?n+r:(c||(c=i*.3),o<Math.abs(r)?(o=r,u=c/4):u=c/(2*Math.PI)*Math.asin(r/o),o*Math.pow(2,-10*e)*Math.sin((e*i-u)*(2*Math.PI)/c)+r+n)},easeInOutElastic:function(e,n,t,i){var r=t-n,o,c,u;return u=1.70158,c=0,o=r,e===0?n:(e/=i/2)===2?n+r:(c||(c=i*(.3*1.5)),o<Math.abs(r)?(o=r,u=c/4):u=c/(2*Math.PI)*Math.asin(r/o),e<1?-.5*(o*Math.pow(2,10*(e-=1))*Math.sin((e*i-u)*(2*Math.PI)/c))+n:o*Math.pow(2,-10*(e-=1))*Math.sin((e*i-u)*(2*Math.PI)/c)*.5+r+n)},easeInBack:function(e,n,t,i,r){var o=t-n;return r===void 0&&(r=1.70158),o*(e/=i)*e*((r+1)*e-r)+n},easeOutBack:function(e,n,t,i,r){var o=t-n;return r===void 0&&(r=1.70158),o*((e=e/i-1)*e*((r+1)*e+r)+1)+n},easeInOutBack:function(e,n,t,i,r){var o=t-n;return r===void 0&&(r=1.70158),(e/=i/2)<1?o/2*(e*e*(((r*=1.525)+1)*e-r))+n:o/2*((e-=2)*e*(((r*=1.525)+1)*e+r)+2)+n},easeInBounce:function(e,n,t,i){var r=t-n,o;return o=s.easeOutBounce(i-e,0,r,i),r-o+n},easeOutBounce:function(e,n,t,i){var r=t-n;return(e/=i)<1/2.75?r*(7.5625*e*e)+n:e<2/2.75?r*(7.5625*(e-=1.5/2.75)*e+.75)+n:e<2.5/2.75?r*(7.5625*(e-=2.25/2.75)*e+.9375)+n:r*(7.5625*(e-=2.625/2.75)*e+.984375)+n},easeInOutBounce:function(e,n,t,i){var r=t-n,o;return e<i/2?(o=s.easeInBounce(e*2,0,r,i),o*.5+n):(o=s.easeOutBounce(e*2-i,0,r,i),o*.5+r*.5+n)}};return _=s,_}var Pe=je();const Ie=te(Pe);function Oe(s,e){for(var n=0;n<e.length;n++){var t=e[n];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(s,t.key,t)}}function be(s,e,n){return e&&Oe(s.prototype,e),s}function b(){return b=Object.assign||function(s){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&(s[t]=n[t])}return s},b.apply(this,arguments)}function Se(s,e){s.prototype=Object.create(e.prototype),s.prototype.constructor=s,R(s,e)}function R(s,e){return R=Object.setPrototypeOf||function(t,i){return t.__proto__=i,t},R(s,e)}function Ne(s){return s*Math.PI/180}function d(s,e){return s+Math.random()*(e-s)}function Ce(s,e){return Math.floor(s+Math.random()*(e-s+1))}var I;(function(s){s[s.Circle=0]="Circle",s[s.Square=1]="Square",s[s.Strip=2]="Strip"})(I||(I={}));var x;(function(s){s[s.Positive=1]="Positive",s[s.Negative=-1]="Negative"})(x||(x={}));var Ee=(function(){function s(n,t,i,r){this.getOptions=t;var o=this.getOptions(),c=o.colors,u=o.initialVelocityX,l=o.initialVelocityY;this.context=n,this.x=i,this.y=r,this.w=d(5,20),this.h=d(5,20),this.radius=d(5,10),this.vx=d(-u,u),this.vy=d(-l,0),this.shape=Ce(0,2),this.angle=Ne(d(0,360)),this.angularSpin=d(-.2,.2),this.color=c[Math.floor(Math.random()*c.length)],this.rotateY=d(0,1),this.rotationDirection=d(0,1)?x.Positive:x.Negative}var e=s.prototype;return e.update=function(){var t=this.getOptions(),i=t.gravity,r=t.wind,o=t.friction,c=t.opacity,u=t.drawShape;this.x+=this.vx,this.y+=this.vy,this.vy+=i,this.vx+=r,this.vx*=o,this.vy*=o,this.rotateY>=1&&this.rotationDirection===x.Positive?this.rotationDirection=x.Negative:this.rotateY<=-1&&this.rotationDirection===x.Negative&&(this.rotationDirection=x.Positive);var l=.1*this.rotationDirection;if(this.rotateY+=l,this.angle+=this.angularSpin,this.context.save(),this.context.translate(this.x,this.y),this.context.rotate(this.angle),this.context.scale(1,this.rotateY),this.context.rotate(this.angle),this.context.beginPath(),this.context.fillStyle=this.color,this.context.strokeStyle=this.color,this.context.globalAlpha=c,this.context.lineCap="round",this.context.lineWidth=2,u&&typeof u=="function")u.call(this,this.context);else switch(this.shape){case I.Circle:{this.context.beginPath(),this.context.arc(0,0,this.radius,0,2*Math.PI),this.context.fill();break}case I.Square:{this.context.fillRect(-this.w/2,-this.h/2,this.w,this.h);break}case I.Strip:{this.context.fillRect(-this.w/6,-this.h/2,this.w/3,this.h);break}default:throw new Error("Unknown type in Particle.ts")}this.context.closePath(),this.context.restore()},s})(),Me=function(e,n){var t=this;this.x=0,this.y=0,this.w=0,this.h=0,this.lastNumberOfPieces=0,this.tweenInitTime=Date.now(),this.particles=[],this.particlesGenerated=0,this.removeParticleAt=function(r){t.particles.splice(r,1)},this.getParticle=function(){var r=d(t.x,t.w+t.x),o=d(t.y,t.h+t.y);return new Ee(t.context,t.getOptions,r,o)},this.animate=function(){var r=t.canvas,o=t.context,c=t.particlesGenerated,u=t.lastNumberOfPieces,l=t.getOptions(),w=l.run,S=l.recycle,p=l.numberOfPieces,C=l.debug,m=l.tweenFunction,y=l.tweenDuration;if(!w)return!1;var g=t.particles.length,v=S?g:c,N=Date.now();if(v<p){u!==p&&(t.tweenInitTime=N,t.lastNumberOfPieces=p);for(var k=t.tweenInitTime,E=N-k>y?y:Math.max(0,N-k),M=m(E,v,p,y),j=Math.round(M-v),G=0;G<j;G+=1)t.particles.push(t.getParticle());t.particlesGenerated+=j}return C&&(o.font="12px sans-serif",o.fillStyle="#333",o.textAlign="right",o.fillText("Particles: "+g,r.width-10,r.height-20)),t.particles.forEach(function(P,U){P.update(),(P.y>r.height||P.y<-100||P.x>r.width+100||P.x<-100)&&(S&&v<=p?t.particles[U]=t.getParticle():t.removeParticleAt(U))}),g>0||v<p},this.canvas=e;var i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get canvas context");this.context=i,this.getOptions=n},T={width:typeof window<"u"?window.innerWidth:300,height:typeof window<"u"?window.innerHeight:200,numberOfPieces:200,friction:.99,wind:0,gravity:.1,initialVelocityX:4,initialVelocityY:10,colors:["#f44336","#e91e63","#9c27b0","#673ab7","#3f51b5","#2196f3","#03a9f4","#00bcd4","#009688","#4CAF50","#8BC34A","#CDDC39","#FFEB3B","#FFC107","#FF9800","#FF5722","#795548"],opacity:1,debug:!1,tweenFunction:Ie.easeInOutQuad,tweenDuration:5e3,recycle:!0,run:!0},_e=(function(){function s(e,n){var t=this;this.setOptionsWithDefaults=function(r){var o={confettiSource:{x:0,y:0,w:t.canvas.width,h:0}};t._options=b({},o,T,r),Object.assign(t,r.confettiSource)},this.update=function(){var r=t.options,o=r.run,c=r.onConfettiComplete,u=t.canvas,l=t.context;o&&(l.fillStyle="white",l.clearRect(0,0,u.width,u.height)),t.generator.animate()?t.rafId=requestAnimationFrame(t.update):(c&&typeof c=="function"&&t.generator.particlesGenerated>0&&c.call(t,t),t._options.run=!1)},this.reset=function(){t.generator&&t.generator.particlesGenerated>0&&(t.generator.particlesGenerated=0,t.generator.particles=[],t.generator.lastNumberOfPieces=0)},this.stop=function(){t.options={run:!1},t.rafId&&(cancelAnimationFrame(t.rafId),t.rafId=void 0)},this.canvas=e;var i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get canvas context");this.context=i,this.generator=new Me(this.canvas,function(){return t.options}),this.options=n,this.update()}return be(s,[{key:"options",get:function(){return this._options},set:function(n){var t=this._options&&this._options.run,i=this._options&&this._options.recycle;this.setOptionsWithDefaults(n),this.generator&&(Object.assign(this.generator,this.options.confettiSource),typeof n.recycle=="boolean"&&n.recycle&&i===!1&&(this.generator.lastNumberOfPieces=this.generator.particles.length)),typeof n.run=="boolean"&&n.run&&t===!1&&this.update()}}]),s})(),W=O.createRef();function D(s){var e={},n={},t={},i=[].concat(Object.keys(T),["confettiSource","drawShape","onConfettiComplete"]),r=["canvasRef"];return Object.keys(s).forEach(function(o){var c=s[o];i.includes(o)?e[o]=c:r.includes(o)?r[o]=c:t[o]=c}),[e,t,n]}var F=(function(s){Se(e,s);function e(t){var i;return i=s.call(this,t)||this,i.canvas=O.createRef(),i.canvas=t.canvasRef||W,i}var n=e.prototype;return n.componentDidMount=function(){if(this.canvas.current){var i=D(this.props)[0];this.confetti=new _e(this.canvas.current,i)}},n.componentDidUpdate=function(){var i=D(this.props)[0];this.confetti&&(this.confetti.options=i)},n.componentWillUnmount=function(){this.confetti&&this.confetti.stop(),this.confetti=void 0},n.render=function(){var i=D(this.props),r=i[0],o=i[1],c=b({zIndex:2,position:"absolute",pointerEvents:"none",top:0,left:0,bottom:0,right:0},o.style);return O.createElement("canvas",Object.assign({width:r.width,height:r.height,ref:this.canvas},o,{style:c}))},e})(f.Component);F.defaultProps=b({},T);F.displayName="ConfettiReact";var De=O.forwardRef(function(s,e){return O.createElement(F,Object.assign({canvasRef:W},s))});function Re({id:s}){return s?a.jsx(se,{children:()=>a.jsx(De,{run:!!s,recycle:!1,numberOfPieces:800,width:window.innerWidth,height:window.innerHeight},s)}):null}function Te(){return a.jsx("div",{className:"border-destructive bg-destructive fixed top-0 right-0 left-0 z-50 border-b",children:a.jsxs("div",{className:"relative w-full p-4",children:[a.jsx(Q,{to:"/workspace-structure",className:"absolute inset-0 z-10 block h-full w-full","aria-label":"Learn more about workspace structure"}),a.jsxs("div",{className:"relative z-0 container flex items-center justify-between",children:[a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsx(B,{name:"Error",className:"text-destructive-foreground h-5 w-5"}),a.jsxs("div",{children:[a.jsx("h3",{className:"text-destructive-foreground text-sm font-semibold",children:"Warning: Changes detected in exercises directory"}),a.jsx("p",{className:"text-destructive-foreground/80 text-xs",children:"You should typically work in the playground directory, not the exercises directory."})]})]}),a.jsxs("div",{className:"text-destructive-foreground flex items-center gap-2 text-xs",children:[a.jsx("span",{children:"Learn more"}),a.jsx(B,{name:"ArrowRight",className:"h-3 w-3"})]})]})]})})}const Fe=[{title:"Navigation",shortcuts:[{keys:["g","h"],description:"Go to home"},{keys:["g","1-9"],description:"Go to exercise (e.g., g+1 → /exercise/01)"},{keys:["g","1-9",".","1-9"],description:"Go to exercise step (e.g., g+1+.+2 → /exercise/01/02/problem)"},{keys:["g","1-9",".","f"],description:"Go to exercise finished page (e.g., g+1+.+f → /exercise/01/finished)"},{keys:["g","p"],description:"Go to previous step/page"},{keys:["g","n"],description:"Go to next step/page"},{keys:["g","a"],description:"Go to account page"},{keys:["g","d"],description:"Go to admin page"},{keys:["g","l"],description:"Go to last exercise solution"},{keys:["Escape"],description:"Close sidebar navigation (when open)"}]},{title:"Playback Controls",shortcuts:[{keys:["Space","k"],description:"Play/pause video"},{keys:["j"],description:"Seek backward 10 seconds"},{keys:["l"],description:"Seek forward 10 seconds"},{keys:["←"],description:"Seek backward 10 seconds"},{keys:["→"],description:"Seek forward 10 seconds"}]},{title:"Frame-by-Frame Navigation",shortcuts:[{keys:[","],description:"Go to previous frame (when paused)"},{keys:["."],description:"Go to next frame (when paused)"}]},{title:"Volume Control",shortcuts:[{keys:["↑"],description:"Increase volume by 10%"},{keys:["↓"],description:"Decrease volume by 10%"}]},{title:"Playback Speed",shortcuts:[{keys:["Shift",">"],description:"Increase playback speed"},{keys:["Shift","<"],description:"Decrease playback speed"}]},{title:"Fullscreen and Picture-in-Picture",shortcuts:[{keys:["f"],description:"Toggle fullscreen mode"},{keys:["i"],description:"Toggle picture-in-picture mode"}]},{title:"Captions",shortcuts:[{keys:["c"],description:"Toggle captions/subtitles"}]},{title:"Quick Seek",shortcuts:[{keys:["0-9"],description:"Seek to percentage of video (0 = 0%, 1 = 10%, ..., 9 = 90%)"}]}];function Ge({open:s,onOpenChange:e}){return a.jsx(ae,{open:s,onOpenChange:e,children:a.jsxs(ce,{className:"max-h-[80vh] max-w-2xl overflow-y-auto",children:[a.jsxs(ue,{children:[a.jsx(le,{children:"Keyboard Shortcuts"}),a.jsxs(fe,{children:["Use these keyboard shortcuts to navigate and control the video player. Press"," ",a.jsx("kbd",{className:"border-border bg-muted rounded border px-1.5 py-0.5 font-mono text-xs",children:"?"})," ","or select the question mark icon in the navigation to open this list."]})]}),a.jsx("div",{className:"space-y-6",children:Fe.map(n=>a.jsxs("div",{children:[a.jsx("h3",{className:"text-foreground mb-3 text-sm font-semibold",children:n.title}),a.jsx("div",{className:"space-y-2",children:n.shortcuts.map((t,i)=>a.jsxs("div",{className:"flex items-center justify-between gap-4",children:[a.jsx("span",{className:"text-muted-foreground flex-1 text-sm",children:t.description}),a.jsx("div",{className:"flex shrink-0 items-center gap-1",children:t.keys.map((r,o)=>a.jsxs(f.Fragment,{children:[a.jsx("kbd",{className:"border-border bg-muted rounded border px-2 py-1 font-mono text-xs",children:r}),o<t.keys.length-1&&a.jsx("span",{className:"text-muted-foreground",children:"+"})]},o))})]},i))})]},n.title))}),a.jsx("div",{className:"border-border mt-4 border-t pt-4",children:a.jsxs("p",{className:"text-muted-foreground text-xs",children:[a.jsx("strong",{children:"Note:"})," Shortcuts are ignored when focus is on interactive elements (inputs, buttons, etc.). Press"," ",a.jsx("kbd",{className:"border-border bg-muted rounded border px-1.5 py-0.5 font-mono text-xs",children:"?"})," ","to toggle this dialog."]})})]})})}function Ue({toast:s}){return a.jsxs(a.Fragment,{children:[a.jsx(de,{closeButton:!0,position:"top-center"}),s?a.jsx(Be,{toast:s}):null]})}function Be({toast:s}){const{id:e,type:n,title:t,description:i}=s;return f.useEffect(()=>{setTimeout(()=>{h[n](t,{id:e,description:i})},0)},[i,e,t,n]),null}function Ae({repoUpdates:s}){const{updatesAvailable:e,repoUpdatesAvailable:n,dependenciesNeedInstall:t,updateNotificationId:i,diffLink:r}=s,o=q(),c=f.useRef(o);f.useEffect(()=>{c.current=o},[o]);const u=f.useRef(null),l=f.useRef(null),w=f.useRef(!1);return f.useEffect(()=>{if(e&&i){l.current&&(h.dismiss(l.current),l.current=null);const S=n?"New workshop updates available":"Dependencies out of date",p=n?a.jsxs("div",{children:[t?"Get the latest updates and reinstall dependencies by clicking the update button. ":"Get the latest updates by clicking the update button. ",r?a.jsx("a",{href:r,target:"_blank",rel:"noreferrer",className:"text-xs underline",children:"View changes"}):null]}):a.jsxs("div",{children:["Your installed packages don't match package.json. ","Click the update button to reinstall dependencies."]}),C=h.info(S,{duration:1/0,description:p,onDismiss:()=>{},action:{label:"Update",onClick:async()=>{if(l.current&&(h.dismiss(l.current),l.current=null),u.current||(u.current=h.loading("Update in progress...")),!w.current){w.current=!0;try{const{EPICSHOP_PARENT_PORT:m,EPICSHOP_PARENT_TOKEN:y}=window.ENV||{};if(!m||!y)throw new Error("Update API not available");const g=await fetch(`http://localhost:${m}/__epicshop-restart`,{method:"POST",headers:{"x-epicshop-token":y}});if(!g.ok)throw new Error(`Request to update workshop failed: ${g.statusText}`);const v=await g.json().catch(()=>({})),k=me({status:xe(["ok","error"]),message:ve().optional()}).safeParse(v);if(!k.success)throw console.error("Invalid response from update API",v),new Error("Invalid response from update API");const{status:E,message:M}=k.data;if(E==="ok"){let j=!1;h.success("Workshop updated",{description:"Reloading in 2 seconds... You can reload now if you prefer.",duration:2e3,action:{label:"Reload now",onClick:()=>{j=!0,window.location.reload()}},onAutoClose:()=>{j||window.location.reload()}})}else h.error("Failed to update workshop",{description:M||"Unknown error"})}catch(m){h.error("Failed to update workshop",{description:m instanceof Error?m.message:String(m)})}finally{w.current=!1,u.current&&(h.dismiss(u.current),u.current=null)}}}},cancel:{label:"Dismiss",onClick:()=>{l.current&&(h.dismiss(l.current),l.current=null),c.current.submit({intent:"mute",id:i},{method:"post",action:"/admin/notifications"})}}});l.current=C}},[e,i,n,t,r]),null}function qe({unmutedNotifications:s}){const e=q(),n=f.useRef(e),t=f.useRef(new Set);return f.useEffect(()=>{for(const i of s)t.current.has(i.id)||(t.current.add(i.id),h.info(i.title,{id:i.id,description:a.jsxs("div",{children:[a.jsx("p",{children:i.message}),i.link&&a.jsx("a",{href:i.link,target:"_blank",className:"text-xs underline",children:"Learn more"})]}),duration:1/0,action:{label:"Dismiss",onClick:()=>{n.current.submit({intent:"mute",id:i.id},{method:"post",action:"/admin/notifications"})}}}))},[s]),null}const Le="/assets/app-BUxWY8xC.css",We="/assets/tailwind-C8PqsZFp.css",Ve="unknown@example.com";function Ye({user:s,userId:e}){const n=s?.id??e?.id??void 0,t=s?.email&&s.email!==Ve?s.email:void 0;if(!n&&!t)return null;const i={};return n&&(i.id=n),t&&(i.email=t),i}const pt=()=>[{rel:"stylesheet",href:"/neogrotesk-font.css"},{rel:"stylesheet",href:"https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,200;0,300;0,400;0,500;0,600;1,700&display=swap"},{rel:"stylesheet",href:We},{rel:"stylesheet",href:Le},{rel:"icon",href:"/favicon.ico",sizes:"48x48"},{rel:"icon",type:"image/svg+xml",href:"/favicon.svg"}],mt=({loaderData:s})=>s?ke({instructor:s.instructor,title:s.workshopTitle,description:s.workshopSubtitle,requestInfo:s.requestInfo}):[];function V({children:s,env:e={},className:n,style:t}){return a.jsxs("html",{lang:"en",className:n,style:t,children:[a.jsxs("head",{children:[a.jsx(ye,{}),a.jsx(X,{}),a.jsx("meta",{charSet:"utf-8"}),a.jsx("meta",{name:"viewport",content:"width=device-width,initial-scale=1"}),a.jsx(J,{}),a.jsx("script",{dangerouslySetInnerHTML:{__html:`window.ENV = ${JSON.stringify(e)}`}})]}),a.jsxs("body",{className:"bg-background text-foreground scrollbar-thin scrollbar-thumb-scrollbar h-screen-safe",children:[s,a.jsx(Z,{}),a.jsx(ee,{})]})]})}function Qe(){const s=L(),e=z(),n=ne.useSpinDelay(e.state!=="idle",{delay:400,minDuration:200}),t=re(),[i,r]=f.useState(!1);f.useEffect(()=>{const c=()=>{r(u=>!u)};return window.addEventListener("toggle-keyboard-shortcuts",c),()=>{window.removeEventListener("toggle-keyboard-shortcuts",c)}},[]),f.useEffect(()=>{if(!ENV.EPICSHOP_IS_PUBLISHED)return;const c=Ye({user:s.user,userId:s.userId});Y(()=>import("./index.client-CsIUPfXc.js"),__vite__mapDeps([0,1])).then(u=>{c?u.setUser(c):u.setUser(null)}).catch(()=>{})},[s.user,s.userId]);const o=ge();return a.jsxs(V,{style:s.preferences?.fontSize?{fontSize:`${s.preferences?.fontSize}px`}:{},className:ie("h-screen-safe antialiased",o,{"cursor-progress":n},t?"alt-down":null),env:s.ENV,children:[s.exerciseChanges&&!s.preferences?.exerciseWarning?.dismissed&&a.jsx(Te,{}),a.jsx(K,{}),a.jsx(Re,{id:s.confettiId}),a.jsx(Ue,{toast:s.toast}),a.jsx(Ae,{repoUpdates:s.repoUpdates}),a.jsx(he,{}),a.jsx(qe,{unmutedNotifications:s.unmutedNotifications}),a.jsx(Ge,{open:i,onOpenChange:r})]})}const vt=H(function(){const{user:e}=L();return a.jsx(we,{user:e,children:a.jsx(pe,{children:a.jsx(Qe,{})})})}),xt=$(function(){return a.jsx(V,{className:"h-screen-safe",children:a.jsx(oe,{})})});export{xt as ErrorBoundary,vt as default,pt as links,mt as meta};
3
+ //# sourceMappingURL=root-BwYDIUyI.js.map