@epic-web/workshop-app 6.76.7 → 6.77.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/build/client/assets/{_exerciseNumber-C1aZpAWV.js → _exerciseNumber-JuXb6JTN.js} +2 -2
  2. package/build/client/assets/{_exerciseNumber-C1aZpAWV.js.map → _exerciseNumber-JuXb6JTN.js.map} +1 -1
  3. package/build/client/assets/{_exerciseNumber_.finished-BICggZV1.js → _exerciseNumber_.finished-DD-1txyR.js} +2 -2
  4. package/build/client/assets/{_exerciseNumber_.finished-BICggZV1.js.map → _exerciseNumber_.finished-DD-1txyR.js.map} +1 -1
  5. package/build/client/assets/_extra-BfK-kKBL.js +2 -0
  6. package/build/client/assets/_extra-BfK-kKBL.js.map +1 -0
  7. package/build/client/assets/_layout-BsHVX3B_.js +2 -0
  8. package/build/client/assets/_layout-BsHVX3B_.js.map +1 -0
  9. package/build/client/assets/{_layout-CunOyAg4.js → _layout-CDyeQVKG.js} +2 -2
  10. package/build/client/assets/{_layout-CunOyAg4.js.map → _layout-CDyeQVKG.js.map} +1 -1
  11. package/build/client/assets/_layout-mVyOtxmC.js +2 -0
  12. package/build/client/assets/_layout-mVyOtxmC.js.map +1 -0
  13. package/build/client/assets/{account-C96cpeZR.js → account-BKXMYhfO.js} +2 -2
  14. package/build/client/assets/{account-C96cpeZR.js.map → account-BKXMYhfO.js.map} +1 -1
  15. package/build/client/assets/{app-CJniokic.js → app-AWsnszeo.js} +2 -2
  16. package/build/client/assets/{app-CJniokic.js.map → app-AWsnszeo.js.map} +1 -1
  17. package/build/client/assets/{cache-CAr50MIB.js → cache-CxMFS2A_.js} +2 -2
  18. package/build/client/assets/{cache-CAr50MIB.js.map → cache-CxMFS2A_.js.map} +1 -1
  19. package/build/client/assets/{db-DAnX-T3_.js → db-BZ-tFzMp.js} +2 -2
  20. package/build/client/assets/{db-DAnX-T3_.js.map → db-BZ-tFzMp.js.map} +1 -1
  21. package/build/client/assets/{diff-D8TUonC2.js → diff-0VO9C_Sf.js} +2 -2
  22. package/build/client/assets/{diff-D8TUonC2.js.map → diff-0VO9C_Sf.js.map} +1 -1
  23. package/build/client/assets/{diff-Col_iM3X.js → diff-CC_jaH50.js} +2 -2
  24. package/build/client/assets/{diff-Col_iM3X.js.map → diff-CC_jaH50.js.map} +1 -1
  25. package/build/client/assets/discord-BVfxP4Rd.js +2 -0
  26. package/build/client/assets/discord-BVfxP4Rd.js.map +1 -0
  27. package/build/client/assets/{discord-BJkw0IrB.js → discord-XhHqPI49.js} +2 -2
  28. package/build/client/assets/{discord-BJkw0IrB.js.map → discord-XhHqPI49.js.map} +1 -1
  29. package/build/client/assets/{epic-video-BJW6MU1i.js → epic-video-D4jBdSKs.js} +2 -2
  30. package/build/client/assets/{epic-video-BJW6MU1i.js.map → epic-video-D4jBdSKs.js.map} +1 -1
  31. package/build/client/assets/{epic-video-jtxu_0bl.js → epic-video-Ddc9rYLT.js} +2 -2
  32. package/build/client/assets/{epic-video-jtxu_0bl.js.map → epic-video-Ddc9rYLT.js.map} +1 -1
  33. package/build/client/assets/{finished-C2jP5uE7.js → finished-BSfM_f4M.js} +2 -2
  34. package/build/client/assets/{finished-C2jP5uE7.js.map → finished-BSfM_f4M.js.map} +1 -1
  35. package/build/client/assets/{index-CdzVFL-Z.js → index-BrVvTrwg.js} +2 -2
  36. package/build/client/assets/{index-CdzVFL-Z.js.map → index-BrVvTrwg.js.map} +1 -1
  37. package/build/client/assets/{index-Dpyv8N6m.js → index-CfPaTqRT.js} +2 -2
  38. package/build/client/assets/{index-Dpyv8N6m.js.map → index-CfPaTqRT.js.map} +1 -1
  39. package/build/client/assets/{index-X8or9u7t.js → index-CuCZuiBp.js} +2 -2
  40. package/build/client/assets/{index-X8or9u7t.js.map → index-CuCZuiBp.js.map} +1 -1
  41. package/build/client/assets/{index-KRgoKRWG.js → index-D0vH1MiQ.js} +2 -2
  42. package/build/client/assets/{index-KRgoKRWG.js.map → index-D0vH1MiQ.js.map} +1 -1
  43. package/build/client/assets/{index-BCQgVrao.js → index-DTC_5pri.js} +2 -2
  44. package/build/client/assets/{index-BCQgVrao.js.map → index-DTC_5pri.js.map} +1 -1
  45. package/build/client/assets/{launch-editor-D2exGfVu.js → launch-editor-0oPpbFQe.js} +2 -2
  46. package/build/client/assets/{launch-editor-D2exGfVu.js.map → launch-editor-0oPpbFQe.js.map} +1 -1
  47. package/build/client/assets/{loading-CDNzW5oO.js → loading-CaCCsk9k.js} +2 -2
  48. package/build/client/assets/{loading-CDNzW5oO.js.map → loading-CaCCsk9k.js.map} +1 -1
  49. package/build/client/assets/{login-mWjVXGbJ.js → login-w4y7RVYa.js} +2 -2
  50. package/build/client/assets/{login-mWjVXGbJ.js.map → login-w4y7RVYa.js.map} +1 -1
  51. package/build/client/assets/{manifest-7ac2a8d8.js → manifest-a63db2d2.js} +1 -1
  52. package/build/client/assets/{mdx-DdpoOTHm.js → mdx-DwvWT4Ou.js} +2 -2
  53. package/build/client/assets/{mdx-DdpoOTHm.js.map → mdx-DwvWT4Ou.js.map} +1 -1
  54. package/build/client/assets/{onboarding-indicator-B-XR90_G.js → onboarding-indicator-BkeHYs2C.js} +2 -2
  55. package/build/client/assets/{onboarding-indicator-B-XR90_G.js.map → onboarding-indicator-BkeHYs2C.js.map} +1 -1
  56. package/build/client/assets/{online-DiNLkgTC.js → online-DVk-W8Cr.js} +2 -2
  57. package/build/client/assets/{online-DiNLkgTC.js.map → online-DVk-W8Cr.js.map} +1 -1
  58. package/build/client/assets/{playground-DmEAkxG1.js → playground-DG4B62WX.js} +2 -2
  59. package/build/client/assets/{playground-DmEAkxG1.js.map → playground-DG4B62WX.js.map} +1 -1
  60. package/build/client/assets/{playground-window-x2mQ5o1O.js → playground-window-CF8lTXXI.js} +2 -2
  61. package/build/client/assets/{playground-window-x2mQ5o1O.js.map → playground-window-CF8lTXXI.js.map} +1 -1
  62. package/build/client/assets/{preferences-B7ND1VS9.js → preferences-Czy5oqWs.js} +2 -2
  63. package/build/client/assets/{preferences-B7ND1VS9.js.map → preferences-Czy5oqWs.js.map} +1 -1
  64. package/build/client/assets/{presence-VCvV2mg7.js → presence-Brtc_BN7.js} +2 -2
  65. package/build/client/assets/{presence-VCvV2mg7.js.map → presence-Brtc_BN7.js.map} +1 -1
  66. package/build/client/assets/{preview-fhmjENlm.js → preview-Be-plbPz.js} +2 -2
  67. package/build/client/assets/{preview-fhmjENlm.js.map → preview-Be-plbPz.js.map} +1 -1
  68. package/build/client/assets/{product-CvyMpYD_.js → product-D4IgPJN5.js} +2 -2
  69. package/build/client/assets/{product-CvyMpYD_.js.map → product-D4IgPJN5.js.map} +1 -1
  70. package/build/client/assets/{progress-Bby-ybMA.js → progress-JDMkfyr3.js} +2 -2
  71. package/build/client/assets/{progress-Bby-ybMA.js.map → progress-JDMkfyr3.js.map} +1 -1
  72. package/build/client/assets/{revalidation-ws-BJWJviUX.js → revalidation-ws-iocj9Mrl.js} +2 -2
  73. package/build/client/assets/{revalidation-ws-BJWJviUX.js.map → revalidation-ws-iocj9Mrl.js.map} +1 -1
  74. package/build/client/assets/{root-B-MkiU1r.js → root-IJJBVEoj.js} +2 -2
  75. package/build/client/assets/{root-B-MkiU1r.js.map → root-IJJBVEoj.js.map} +1 -1
  76. package/build/client/assets/{root-loader-BOzEMapJ.js → root-loader-BmUqzUDN.js} +2 -2
  77. package/build/client/assets/{root-loader-BOzEMapJ.js.map → root-loader-BmUqzUDN.js.map} +1 -1
  78. package/build/client/assets/{set-playground-BSGwH9dH.js → set-playground-DO5tJu4h.js} +2 -2
  79. package/build/client/assets/{set-playground-BSGwH9dH.js.map → set-playground-DO5tJu4h.js.map} +1 -1
  80. package/build/client/assets/{test-BeEphi7e.js → test-C8NrA0Ls.js} +2 -2
  81. package/build/client/assets/{test-BeEphi7e.js.map → test-C8NrA0Ls.js.map} +1 -1
  82. package/build/client/assets/{tests-RWSslYc0.js → tests-Bko6qhsh.js} +2 -2
  83. package/build/client/assets/{tests-RWSslYc0.js.map → tests-Bko6qhsh.js.map} +1 -1
  84. package/build/client/assets/{user-BsPobzjB.js → user-CYXKquT7.js} +2 -2
  85. package/build/client/assets/{user-BsPobzjB.js.map → user-CYXKquT7.js.map} +1 -1
  86. package/build/client/assets/{version-f8qqYbyU.js → version-CwWSRwe5.js} +2 -2
  87. package/build/client/assets/{version-f8qqYbyU.js.map → version-CwWSRwe5.js.map} +1 -1
  88. package/build/client/assets/{workshop-config-Zfc8zU0x.js → workshop-config-BMWaKPZT.js} +2 -2
  89. package/build/client/assets/{workshop-config-Zfc8zU0x.js.map → workshop-config-BMWaKPZT.js.map} +1 -1
  90. package/build/server/index.js +102 -10
  91. package/build/server/index.js.map +1 -1
  92. package/package.json +3 -3
  93. package/build/client/assets/_extra-Dki7HdFp.js +0 -2
  94. package/build/client/assets/_extra-Dki7HdFp.js.map +0 -1
  95. package/build/client/assets/_layout-DTrIGRDO.js +0 -2
  96. package/build/client/assets/_layout-DTrIGRDO.js.map +0 -1
  97. package/build/client/assets/_layout-Dkl36Skj.js +0 -2
  98. package/build/client/assets/_layout-Dkl36Skj.js.map +0 -1
  99. package/build/client/assets/discord-r3m19sUM.js +0 -2
  100. package/build/client/assets/discord-r3m19sUM.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_layout-BsHVX3B_.js","sources":["../../../../../node_modules/framer-motion/dist/es/animation/hooks/animation-controls.mjs","../../../../../node_modules/framer-motion/dist/es/animation/hooks/use-animation.mjs","../../../app/components/media-query.ts","../../../app/components/ui/popover.tsx","../../../app/utils/server-status.ts","../../../app/routes/_app+/_layout.tsx"],"sourcesContent":["import { animateVisualElement, setTarget } from 'motion-dom';\nimport { invariant } from 'motion-utils';\n\nfunction stopAnimation(visualElement) {\n visualElement.values.forEach((value) => value.stop());\n}\nfunction setVariants(visualElement, variantLabels) {\n const reversedLabels = [...variantLabels].reverse();\n reversedLabels.forEach((key) => {\n const variant = visualElement.getVariant(key);\n variant && setTarget(visualElement, variant);\n if (visualElement.variantChildren) {\n visualElement.variantChildren.forEach((child) => {\n setVariants(child, variantLabels);\n });\n }\n });\n}\nfunction setValues(visualElement, definition) {\n if (Array.isArray(definition)) {\n return setVariants(visualElement, definition);\n }\n else if (typeof definition === \"string\") {\n return setVariants(visualElement, [definition]);\n }\n else {\n setTarget(visualElement, definition);\n }\n}\n/**\n * @public\n */\nfunction animationControls() {\n /**\n * Track whether the host component has mounted.\n */\n let hasMounted = false;\n /**\n * A collection of linked component animation controls.\n */\n const subscribers = new Set();\n const controls = {\n subscribe(visualElement) {\n subscribers.add(visualElement);\n return () => void subscribers.delete(visualElement);\n },\n start(definition, transitionOverride) {\n invariant(hasMounted, \"controls.start() should only be called after a component has mounted. Consider calling within a useEffect hook.\");\n const animations = [];\n subscribers.forEach((visualElement) => {\n animations.push(animateVisualElement(visualElement, definition, {\n transitionOverride,\n }));\n });\n return Promise.all(animations);\n },\n set(definition) {\n invariant(hasMounted, \"controls.set() should only be called after a component has mounted. Consider calling within a useEffect hook.\");\n return subscribers.forEach((visualElement) => {\n setValues(visualElement, definition);\n });\n },\n stop() {\n subscribers.forEach((visualElement) => {\n stopAnimation(visualElement);\n });\n },\n mount() {\n hasMounted = true;\n return () => {\n hasMounted = false;\n controls.stop();\n };\n },\n };\n return controls;\n}\n\nexport { animationControls, setValues };\n//# sourceMappingURL=animation-controls.mjs.map\n","\"use client\";\nimport { useConstant } from '../../utils/use-constant.mjs';\nimport { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';\nimport { animationControls } from './animation-controls.mjs';\n\n/**\n * Creates `LegacyAnimationControls`, which can be used to manually start, stop\n * and sequence animations on one or more components.\n *\n * The returned `LegacyAnimationControls` should be passed to the `animate` property\n * of the components you want to animate.\n *\n * These components can then be animated with the `start` method.\n *\n * ```jsx\n * import * as React from 'react'\n * import { motion, useAnimation } from 'framer-motion'\n *\n * export function MyComponent(props) {\n * const controls = useAnimation()\n *\n * controls.start({\n * x: 100,\n * transition: { duration: 0.5 },\n * })\n *\n * return <motion.div animate={controls} />\n * }\n * ```\n *\n * @returns Animation controller with `start` and `stop` methods\n *\n * @public\n */\nfunction useAnimationControls() {\n const controls = useConstant(animationControls);\n useIsomorphicLayoutEffect(controls.mount, []);\n return controls;\n}\nconst useAnimation = useAnimationControls;\n\nexport { useAnimation, useAnimationControls };\n//# sourceMappingURL=use-animation.mjs.map\n","import { useSyncExternalStore } from 'react'\n\nexport function makeMediaQueryStore(\n\tmediaQuery: string,\n\tserverSnapshot: boolean,\n) {\n\tfunction getSnapshot() {\n\t\treturn window.matchMedia(mediaQuery).matches\n\t}\n\n\tfunction subscribe(callback: () => void) {\n\t\tconst mediaQueryList = window.matchMedia(mediaQuery)\n\t\tmediaQueryList.addEventListener('change', callback)\n\t\treturn () => {\n\t\t\tmediaQueryList.removeEventListener('change', callback)\n\t\t}\n\t}\n\n\treturn function useMediaQuery() {\n\t\treturn useSyncExternalStore(subscribe, getSnapshot, () => serverSnapshot)\n\t}\n}\n","import * as PopoverPrimitive from '@radix-ui/react-popover'\nimport * as React from 'react'\nimport { cn } from '#app/utils/misc.tsx'\n\nfunction Popover({\n\t...props\n}: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n\treturn <PopoverPrimitive.Root {...props} />\n}\n\nfunction PopoverTrigger({\n\t...props\n}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n\treturn <PopoverPrimitive.Trigger {...props} />\n}\n\nfunction PopoverContent({\n\tclassName,\n\talign = 'center',\n\tsideOffset = 4,\n\t...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n\treturn (\n\t\t<PopoverPrimitive.Portal>\n\t\t\t<PopoverPrimitive.Content\n\t\t\t\talign={align}\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 rounded-md border p-2 shadow-md outline-none',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</PopoverPrimitive.Portal>\n\t)\n}\n\nexport { Popover, PopoverContent, PopoverTrigger }\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport { useInterval } from './misc.tsx'\nimport { useIsOnline } from './online.ts'\n\nconst healthcheckPath = '/resources/healthcheck'\nconst healthcheckIntervalMs = 15000\n\nexport function useServerStatus() {\n\tconst isOnline = useIsOnline()\n\tconst [isServerDown, setIsServerDown] = useState(false)\n\tconst isCancelledRef = useRef(false)\n\tconst isOnlineRef = useRef(isOnline)\n\n\tuseEffect(() => {\n\t\tisOnlineRef.current = isOnline\n\t}, [isOnline])\n\n\tuseEffect(() => {\n\t\tisCancelledRef.current = false\n\t\treturn () => {\n\t\t\tisCancelledRef.current = true\n\t\t}\n\t}, [])\n\n\tuseEffect(() => {\n\t\tif (ENV.EPICSHOP_DEPLOYED) {\n\t\t\tsetIsServerDown(false)\n\t\t\treturn\n\t\t}\n\t\tif (!isOnline) {\n\t\t\tsetIsServerDown(false)\n\t\t\treturn\n\t\t}\n\t}, [isOnline])\n\n\tconst checkHealth = useCallback(async () => {\n\t\tif (ENV.EPICSHOP_DEPLOYED || !isOnline) {\n\t\t\treturn\n\t\t}\n\t\ttry {\n\t\t\tconst response = await fetch(healthcheckPath, {\n\t\t\t\tcache: 'no-store',\n\t\t\t\theaders: { 'x-healthcheck': 'true' },\n\t\t\t})\n\t\t\tif (!isCancelledRef.current && isOnlineRef.current) {\n\t\t\t\tsetIsServerDown(!response.ok)\n\t\t\t}\n\t\t} catch {\n\t\t\tif (!isCancelledRef.current && isOnlineRef.current) {\n\t\t\t\tsetIsServerDown(true)\n\t\t\t}\n\t\t}\n\t}, [isOnline])\n\n\tuseEffect(() => {\n\t\tif (ENV.EPICSHOP_DEPLOYED || !isOnline) return\n\t\tvoid checkHealth()\n\t}, [checkHealth, isOnline])\n\n\tuseInterval(\n\t\t() => {\n\t\t\tvoid checkHealth()\n\t\t},\n\t\tENV.EPICSHOP_DEPLOYED || !isOnline ? null : healthcheckIntervalMs,\n\t)\n\n\treturn { isServerDown }\n}\n","import {\n\textractNumbersAndTypeFromAppNameOrPath,\n\tgetApps,\n\tgetExercises,\n\tgetPlaygroundAppName,\n\tisExtraApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport { getProcesses } from '@epic-web/workshop-utils/process-manager.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n} from '@epic-web/workshop-utils/timing.server'\nimport { clsx } from 'clsx'\nimport { motion, useAnimationControls } from 'framer-motion'\nimport * as React from 'react'\nimport {\n\tLink,\n\tNavLink,\n\tOutlet,\n\tuseLoaderData,\n\tuseLocation,\n\tuseParams,\n\tdata,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n} from 'react-router'\nimport { useHydrated } from 'remix-utils/use-hydrated'\nimport { Icon } from '#app/components/icons.tsx'\nimport { makeMediaQueryStore } from '#app/components/media-query.ts'\nimport {\n\tOnboardingBadge,\n\tuseOnboardingIndicator,\n} from '#app/components/onboarding-indicator.tsx'\nimport { Logo } from '#app/components/product.tsx'\nimport { useRevalidationWS } from '#app/components/revalidation-ws.tsx'\nimport { StatusIndicator } from '#app/components/status-indicator.tsx'\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogHeader,\n\tDialogTrigger,\n} from '#app/components/ui/dialog.tsx'\nimport {\n\tPopover,\n\tPopoverContent,\n\tPopoverTrigger,\n} from '#app/components/ui/popover.tsx'\nimport {\n\tSimpleTooltip,\n\tTooltip,\n\tTooltipContent,\n\tTooltipProvider,\n\tTooltipTrigger,\n} from '#app/components/ui/tooltip.tsx'\nimport { useOptionalUser, useUserHasAccess } from '#app/components/user.tsx'\nimport { useWorkshopConfig } from '#app/components/workshop-config.tsx'\nimport { cn, getExercisePath, getExerciseStepPath } from '#app/utils/misc.tsx'\nimport { useIsOnline } from '#app/utils/online.ts'\nimport {\n\tgetProductHostEmoji,\n\tproductHostEmojis,\n\tusePresence,\n\ttype Location,\n\ttype User,\n} from '#app/utils/presence.tsx'\nimport { useRequestInfo, useApps } from '#app/utils/root-loader.ts'\nimport { useServerStatus } from '#app/utils/server-status.ts'\nimport {\n\tuseExerciseProgressClassName,\n\tuseNextExerciseRoute,\n\tuseProgressItemClassName,\n\tuseRandomCompletedExerciseRoute,\n\ttype ProgressItemSearch,\n} from '../progress.tsx'\nimport { ThemeSwitch } from '../theme/index.tsx'\n\nfunction getSidecarStatus() {\n\tconst { sidecarProcesses } = getProcesses()\n\tif (sidecarProcesses.size === 0) return null\n\n\tconst processes = Array.from(sidecarProcesses.entries()).map(\n\t\t([name, { process }]) => ({\n\t\t\tname,\n\t\t\trunning: process.exitCode === null,\n\t\t}),\n\t)\n\n\tconst hasFailure = processes.some((p) => !p.running)\n\tconst failureCount = processes.filter((p) => !p.running).length\n\treturn { processes, hasFailure, count: processes.length, failureCount }\n}\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('appLayoutLoader')\n\tconst { title: workshopTitle } = getWorkshopConfig()\n\tconst [exercises, playgroundAppName, apps] = await Promise.all([\n\t\tgetExercises({ request, timings }),\n\t\tgetPlaygroundAppName(),\n\t\tgetApps({ request, timings }),\n\t])\n\n\tconst playgroundNumbersAndType = extractNumbersAndTypeFromAppNameOrPath(\n\t\tplaygroundAppName ?? '',\n\t)\n\tconst playground = {\n\t\tappName: playgroundAppName,\n\t\texerciseNumber: Number(playgroundNumbersAndType?.exerciseNumber),\n\t\tstepNumber: Number(playgroundNumbersAndType?.stepNumber),\n\t\ttype: playgroundNumbersAndType?.type,\n\t}\n\n\tconst sidecarStatus = getSidecarStatus()\n\n\tconst result = data(\n\t\t{\n\t\t\tworkshopTitle,\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\tsolutions: e.solutions.map(({ stepNumber, title, name }) => ({\n\t\t\t\t\tstepNumber,\n\t\t\t\t\ttitle,\n\t\t\t\t\tname,\n\t\t\t\t})),\n\t\t\t\tproblems: e.problems.map(({ stepNumber, title, name }) => ({\n\t\t\t\t\tstepNumber,\n\t\t\t\t\ttitle,\n\t\t\t\t\tname,\n\t\t\t\t})),\n\t\t\t\tsteps: e.steps.map(({ stepNumber, problem, solution }) => ({\n\t\t\t\t\tstepNumber,\n\t\t\t\t\ttitle: problem?.title ?? solution?.title ?? 'Unknown',\n\t\t\t\t\tname: problem?.name ?? solution?.name ?? 'Unknown',\n\t\t\t\t\tproblem: problem\n\t\t\t\t\t\t? { name: problem.name, title: problem.title }\n\t\t\t\t\t\t: null,\n\t\t\t\t\tsolution: solution\n\t\t\t\t\t\t? { name: solution.name, title: solution.title }\n\t\t\t\t\t\t: null,\n\t\t\t\t})),\n\t\t\t})),\n\t\t\textras: apps\n\t\t\t\t.filter(isExtraApp)\n\t\t\t\t.sort((a, b) =>\n\t\t\t\t\ta.title.localeCompare(b.title, undefined, {\n\t\t\t\t\t\tnumeric: true,\n\t\t\t\t\t\tsensitivity: 'base',\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.map((extra) => ({\n\t\t\t\t\tdirName: extra.dirName,\n\t\t\t\t\ttitle: extra.title,\n\t\t\t\t\tname: extra.name,\n\t\t\t\t})),\n\t\t\tplayground,\n\t\t\tisMenuOpened:\n\t\t\t\trequest.headers.get('cookie')?.includes('es_menu_open=true') ?? false,\n\t\t\tsidecarStatus,\n\t\t},\n\t\t{\n\t\t\theaders: {\n\t\t\t\tVary: 'Cookie',\n\t\t\t\t'Server-Timing': getServerTimeHeader(timings),\n\t\t\t},\n\t\t},\n\t)\n\treturn result\n}\n\nexport const headers: HeadersFunction = ({ loaderHeaders, parentHeaders }) => {\n\tconst headers = {\n\t\t'Cache-Control': loaderHeaders.get('Cache-Control') ?? '',\n\t\tVary: 'Cookie',\n\t\t'Server-Timing': combineServerTimings(loaderHeaders, parentHeaders),\n\t}\n\treturn headers\n}\n\nconst opacities = ['opacity-70', 'opacity-80', 'opacity-90', 'opacity-100']\nconst shadows = [\n\t'shadow-[0_0_2px_0_rgba(0,0,0,0.3)]',\n\t'shadow-[0_0_4px_0_rgba(0,0,0,0.3)]',\n\t'shadow-[0_0_7px_0_rgba(0,0,0,0.3)]',\n\t'shadow-[0_0_10px_0_rgba(0,0,0,0.3)]',\n]\nconst serverShutdownTooltip =\n\t'Local workshop server shut down. Restart the workshop app to reconnect.'\nconst serverShutdownLabel = 'Server shut down'\nfunction getScoreClassNames(score: number) {\n\tconst opacityNumber = Math.round(score * opacities.length - 1)\n\tconst shadowNumber = Math.round(score * shadows.length - 1)\n\treturn cn(\n\t\t'shadow-highlight hover:opacity-100 focus:opacity-100',\n\t\topacities[opacityNumber] ?? 'opacity-60',\n\t\tshadows[shadowNumber] ?? 'shadow-none',\n\t\tscore === 1 ? 'animate-pulse hover:animate-none focus:animate-none' : null,\n\t)\n}\n\nfunction FacePile({ isMenuOpened }: { isMenuOpened: boolean }) {\n\tconst loggedInUser = useOptionalUser()\n\tconst { users } = usePresence()\n\tconst {\n\t\tproduct: { displayNameShort },\n\t} = useWorkshopConfig()\n\tconst limit = isMenuOpened ? 17 : 0\n\tconst numberOverLimit = users.length - limit\n\tconst shouldShowNumberOverLimit = numberOverLimit > (isMenuOpened ? 1 : 0)\n\n\tif (!users.length) return null\n\n\tconst tiffany =\n\t\tisMenuOpened && users.length === 1 ? (\n\t\t\t<Link\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\tto=\"https://www.youtube.com/watch?v=w6Q3mHyzn78\"\n\t\t\t>\n\t\t\t\t<img\n\t\t\t\t\talt=\"Tiffany Tunes\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'h-8 w-8 rounded-full border object-cover',\n\t\t\t\t\t\tgetScoreClassNames(1),\n\t\t\t\t\t)}\n\t\t\t\t\tsrc=\"/img/tiffany.png\"\n\t\t\t\t/>\n\t\t\t</Link>\n\t\t) : null\n\tconst overLimitLabel = `${numberOverLimit}${\n\t\tisMenuOpened ? ' more ' : ' '\n\t}${displayNameShort} Dev${numberOverLimit === 1 ? '' : 's'} working now`\n\treturn (\n\t\t<div className=\"flex flex-wrap items-center gap-2\">\n\t\t\t<TooltipProvider>\n\t\t\t\t{(shouldShowNumberOverLimit ? users.slice(0, limit) : users).map(\n\t\t\t\t\t({ user, score }) => {\n\t\t\t\t\t\tconst scoreClassNames = getScoreClassNames(score)\n\t\t\t\t\t\tconst locations = getUserLocations(user)\n\t\t\t\t\t\tconst imageUrl = user.imageUrlSmall || user.avatarUrl\n\t\t\t\t\t\tconst hasAccess = user.hasAccess\n\t\t\t\t\t\tconst local = locations.some((loc) =>\n\t\t\t\t\t\t\tloc.origin?.includes('localhost'),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tconst productHostEmojis = getUniqueProductHostEmojis(locations)\n\t\t\t\t\t\tconst loggedInEmojis = getLoggedInProductEmojis(\n\t\t\t\t\t\t\tuser.loggedInProductHosts,\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\t// Handle opted-out users\n\t\t\t\t\t\tif (user.optOut) {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<Tooltip key={user.id}>\n\t\t\t\t\t\t\t\t\t<TooltipTrigger asChild tabIndex={0}>\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"relative\"\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Anonymous user (opted out)\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'bg-muted flex h-8 w-8 items-center justify-center rounded-full border opacity-50',\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<Icon name=\"User\" />\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t\t\t\t\t<span className=\"flex flex-col items-center justify-center gap-1\">\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-1.5\">\n\t\t\t\t\t\t\t\t\t\t\t\t{loggedInEmojis ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-xs\">{loggedInEmojis}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t\t\tAnonymous (opted out of sharing)\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet doingLabel: string\n\t\t\t\t\t\tif (hasAccess) {\n\t\t\t\t\t\t\tdoingLabel = local ? 'working' : 'referencing'\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdoingLabel = local ? 'previewing' : 'reviewing'\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Tooltip key={user.id}>\n\t\t\t\t\t\t\t\t<TooltipTrigger asChild tabIndex={0}>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName=\"relative\"\n\t\t\t\t\t\t\t\t\t\taria-label={user.name || `${displayNameShort} Dev`}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{imageUrl ? (\n\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\talt={user.name || displayNameShort}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'h-8 w-8 rounded-full border object-cover',\n\t\t\t\t\t\t\t\t\t\t\t\t\tscoreClassNames,\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\tsrc={imageUrl}\n\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\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'flex h-8 w-8 items-center justify-center rounded-full border',\n\t\t\t\t\t\t\t\t\t\t\t\t\tscoreClassNames,\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<Icon name=\"User\" />\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{productHostEmojis ? (\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\tclassName=\"absolute -top-1 -left-1 text-xs leading-none\"\n\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Workshop products\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{productHostEmojis}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t\t\t\t<span className=\"flex flex-col items-center justify-center gap-1\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-1.5\">\n\t\t\t\t\t\t\t\t\t\t\t{loggedInEmojis ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-xs\">{loggedInEmojis}</span>\n\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t\t{user.name || `${displayNameShort} Dev`}\n\t\t\t\t\t\t\t\t\t\t\t{locations.length > 0\n\t\t\t\t\t\t\t\t\t\t\t\t? ` is ${doingLabel} ${\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tscore === 1 && loggedInUser?.id !== user.id\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 'with you'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t\t\t\t\t\t\t} on`\n\t\t\t\t\t\t\t\t\t\t\t\t: null}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t{locations.map((loc, index) => {\n\t\t\t\t\t\t\t\t\t\t\tconst locationLabel = getLocationLabel(loc)\n\t\t\t\t\t\t\t\t\t\t\tif (!locationLabel) return null\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={`${loc.workshopTitle}-${index}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'flex flex-col items-center',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tlocations.length > 1\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 'border-border mt-1 border-t pt-1 first:mt-0 first:border-t-0 first:pt-0'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: '',\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{locationLabel.line1 ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{getProductHostEmoji(loc.productHost)}{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{locationLabel.line1}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{locationLabel.line2 ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground text-xs\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{locationLabel.line2}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\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</span>\n\t\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t)\n\t\t\t\t\t},\n\t\t\t\t)}\n\t\t\t\t{tiffany}\n\t\t\t\t{shouldShowNumberOverLimit ? (\n\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t<TooltipTrigger asChild tabIndex={0}>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\taria-label={overLimitLabel}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'bg-accent text-accent-foreground flex items-center justify-center rounded-full border text-xs',\n\t\t\t\t\t\t\t\t\tisMenuOpened ? 'h-8 w-8' : 'h-6 w-6',\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<span\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t'pointer-events-none truncate text-center',\n\t\t\t\t\t\t\t\t\t\tisMenuOpened ? 'w-8' : 'w-6',\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\t{isMenuOpened ? `+${numberOverLimit}` : numberOverLimit}\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</TooltipTrigger>\n\t\t\t\t\t\t<TooltipContent>{overLimitLabel}</TooltipContent>\n\t\t\t\t\t</Tooltip>\n\t\t\t\t) : null}\n\t\t\t</TooltipProvider>\n\t\t</div>\n\t)\n}\n\nfunction getLoggedInProductEmojis(\n\thosts: string[] | null | undefined,\n): string | null {\n\tif (!hosts || hosts.length === 0) return null\n\treturn hosts\n\t\t.map((host) => productHostEmojis[host])\n\t\t.filter(Boolean)\n\t\t.join(' ')\n}\n\nfunction getUserLocations(user: User): Location[] {\n\tif (user.locations && user.locations.length > 0) {\n\t\treturn user.locations.filter(Boolean) as Location[]\n\t}\n\tif (user.location) {\n\t\treturn [user.location]\n\t}\n\treturn []\n}\n\nfunction getUniqueProductHostEmojis(locations: Location[]): string | null {\n\tconst uniqueHosts = new Set<string>()\n\tfor (const loc of locations) {\n\t\tif (loc.productHost) {\n\t\t\tuniqueHosts.add(loc.productHost)\n\t\t}\n\t}\n\tif (uniqueHosts.size === 0) return null\n\treturn Array.from(uniqueHosts)\n\t\t.map((host) => getProductHostEmoji(host))\n\t\t.filter(Boolean)\n\t\t.join('')\n}\n\nfunction hasExtras(apps: Array<{ relativePath: string }>) {\n\treturn apps.some((app) => {\n\t\tconst rootDir = app.relativePath.split(/[\\\\/]/)[0]\n\t\treturn (\n\t\t\trootDir === 'extra' || rootDir === 'example' || rootDir === 'examples'\n\t\t)\n\t})\n}\n\nconst useIsWide = makeMediaQueryStore('(min-width: 640px)', true)\n\nexport default function App() {\n\tconst data = useLoaderData<typeof loader>()\n\tconst user = useOptionalUser()\n\tconst isWide = useIsWide()\n\tconst isHydrated = useHydrated()\n\tconst { isServerDown } = useServerStatus()\n\n\tconst [isMenuOpened, setMenuOpenedState] = React.useState(data.isMenuOpened)\n\tuseRevalidationWS({\n\t\twatchPaths: [\n\t\t\t'./exercises/README.mdx',\n\t\t\t'./extra',\n\t\t\t'./example',\n\t\t\t'./examples',\n\t\t],\n\t})\n\n\tfunction setMenuOpened(value: boolean) {\n\t\tsetMenuOpenedState(value)\n\t\tdocument.cookie = `es_menu_open=${value.toString()}; path=/; SameSite=Lax;`\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\t\t\t{user ? null : <NoUserBanner />}\n\t\t\t{/*\n\t\t\t\tthis isn't placed in a conditional with isWide because the server render\n\t\t\t\tdoesn't know whether it should be around or not so we just use CSS to hide it\n\t\t\t\tif it's not supposed to show up.\n\n\t\t\t\tWe don't just use media queries for the wider screen nav because we want\n\t\t\t\tto avoid running all the logic in there unnecessarily.\n\t\t\t*/}\n\t\t\t{isHydrated && isWide ? null : (\n\t\t\t\t<MobileNavigation\n\t\t\t\t\tisMenuOpened={isMenuOpened}\n\t\t\t\t\tonMenuOpenChange={setMenuOpened}\n\t\t\t\t\tisServerDown={isServerDown}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<div\n\t\t\t\t// this nonsense is here because we want the panels to be scrollable rather\n\t\t\t\t// than having the entire page be scrollable (at least on wider screens)\n\t\t\t\tclassName={cn('flex grow flex-col sm:flex-row', {\n\t\t\t\t\t'h-[calc(100vh-128px-env(safe-area-inset-top)-env(safe-area-inset-bottom))] sm:h-[calc(100vh-64px-env(safe-area-inset-top)-env(safe-area-inset-bottom))]':\n\t\t\t\t\t\t!user,\n\t\t\t\t\t'h-[calc(100vh-64px-env(safe-area-inset-top)-env(safe-area-inset-bottom))] sm:h-[calc(100vh-env(safe-area-inset-top)-env(safe-area-inset-bottom))]':\n\t\t\t\t\t\tuser,\n\t\t\t\t\t'h-[unset]': !isWide && isMenuOpened,\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t{isWide ? (\n\t\t\t\t\t<Navigation\n\t\t\t\t\t\tisMenuOpened={isMenuOpened}\n\t\t\t\t\t\tonMenuOpenChange={setMenuOpened}\n\t\t\t\t\t\tisServerDown={isServerDown}\n\t\t\t\t\t/>\n\t\t\t\t) : null}\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'h-full w-full max-w-full sm:max-w-[calc(100%-56px)]',\n\t\t\t\t\t\tisMenuOpened ? 'hidden md:block' : '',\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Outlet />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction getLocationLabel(location: User['location']) {\n\tif (!location) return null\n\n\tconst { exercise } = location\n\n\tconst exercisePortion = [\n\t\texercise\n\t\t\t? [exercise.exerciseNumber, exercise.stepNumber]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.map((s) => s.toString().padStart(2, '0'))\n\t\t\t\t\t.join('/')\n\t\t\t: null,\n\t\texercise?.type,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(' - ')\n\treturn { line1: location.workshopTitle, line2: exercisePortion }\n}\n\nfunction NoUserBanner() {\n\tconst isWide = useIsWide()\n\tconst {\n\t\tproduct: { host, displayName },\n\t} = useWorkshopConfig()\n\tconst userHasAccess = useUserHasAccess()\n\tconst [showLoginBadge, dismissLoginBadge] =\n\t\tuseOnboardingIndicator('login-button')\n\tconst details = (\n\t\t<div>\n\t\t\t{ENV.EPICSHOP_DEPLOYED ? (\n\t\t\t\t<div>\n\t\t\t\t\t{`This is the deployed version. `}\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\tto={ENV.EPICSHOP_GITHUB_REPO}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tRun locally\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t{` for full experience.`}\n\t\t\t\t\t</>{' '}\n\t\t\t\t</div>\n\t\t\t) : userHasAccess ? (\n\t\t\t\t<div>\n\t\t\t\t\t<Link to=\"/login\" className=\"underline\">\n\t\t\t\t\t\tLogin\n\t\t\t\t\t</Link>{' '}\n\t\t\t\t\tor{' '}\n\t\t\t\t\t<a href={`https://${host}/login`} className=\"underline\">\n\t\t\t\t\t\tjoin for free\n\t\t\t\t\t</a>{' '}\n\t\t\t\t\tfor the full experience.\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t)\n\treturn (\n\t\t<div className=\"from-highlight to-info text-info-foreground z-10 flex h-16 items-center justify-between border-b bg-linear-to-tr pl-4\">\n\t\t\t{isWide ? (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"hidden flex-1 flex-wrap items-center gap-4 sm:flex\">\n\t\t\t\t\t\t<Logo size=\"lg\" style=\"monochrome\" />\n\t\t\t\t\t\t<div className=\"flex flex-1 flex-wrap items-center\">\n\t\t\t\t\t\t\t<p className=\"mr-2\">\n\t\t\t\t\t\t\t\tWelcome to the{' '}\n\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\tto={`https://${host}`}\n\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{displayName}\n\t\t\t\t\t\t\t\t</Link>{' '}\n\t\t\t\t\t\t\t\tWorkshop app!\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t{details}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{userHasAccess ? null : (\n\t\t\t\t\t\t<div className=\"hidden h-full flex-col items-center sm:flex md:flex-row\">\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto={`https://${host}`}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\tclassName=\"flex h-full items-center justify-center space-x-1.5 px-5 text-sm font-semibold\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Join {displayName}</span>\n\t\t\t\t\t\t\t\t<span>↗︎</span>\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto={ENV.EPICSHOP_DEPLOYED ? `https://${host}/login` : '/login'}\n\t\t\t\t\t\t\t\tclassName=\"bg-info-foreground/20 hover:bg-info-foreground/30 relative flex h-full items-center justify-center space-x-1.5 px-5 text-sm font-semibold shadow-md transition\"\n\t\t\t\t\t\t\t\tonClick={dismissLoginBadge}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon name=\"User\" size=\"lg\" />\n\t\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Login</span>\n\t\t\t\t\t\t\t\t{showLoginBadge ? (\n\t\t\t\t\t\t\t\t\t<OnboardingBadge\n\t\t\t\t\t\t\t\t\t\ttooltip=\"Login for the full experience!\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\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</Link>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"flex flex-1 flex-wrap items-center gap-4 sm:hidden\">\n\t\t\t\t\t\t<a href={`https://${host}`}>\n\t\t\t\t\t\t\t<Logo size=\"lg\" style=\"monochrome\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<Dialog>\n\t\t\t\t\t\t\t<DialogTrigger>\n\t\t\t\t\t\t\t\t<Icon name=\"Question\" size=\"lg\" className=\"animate-pulse\" />\n\t\t\t\t\t\t\t</DialogTrigger>\n\t\t\t\t\t\t\t<DialogContent>\n\t\t\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t\t\t<Logo size=\"lg\" style=\"monochrome\" />\n\t\t\t\t\t\t\t\t\t<span className=\"text-lg font-semibold\">{displayName}</span>\n\t\t\t\t\t\t\t\t</DialogHeader>\n\t\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\t\tWelcome to the{' '}\n\t\t\t\t\t\t\t\t\t<Link to={`https://${host}`} className=\"underline\">\n\t\t\t\t\t\t\t\t\t\t{displayName}\n\t\t\t\t\t\t\t\t\t</Link>{' '}\n\t\t\t\t\t\t\t\t\tWorkshop app!\n\t\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t\t\t{details}\n\t\t\t\t\t\t\t</DialogContent>\n\t\t\t\t\t\t</Dialog>\n\t\t\t\t\t</div>\n\t\t\t\t\t{userHasAccess ? null : (\n\t\t\t\t\t\t<div className=\"flex h-full items-center\">\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto={`https://${host}`}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\tclassName=\"flex h-full items-center justify-center space-x-1.5 px-5 text-sm font-semibold\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Join</span>\n\t\t\t\t\t\t\t\t<span>↗︎</span>\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto={ENV.EPICSHOP_DEPLOYED ? `https://${host}/login` : '/login'}\n\t\t\t\t\t\t\t\tclassName=\"bg-info-foreground/20 hover:bg-info-foreground/30 relative flex h-full items-center justify-center space-x-1.5 px-5 text-sm font-semibold shadow-md transition\"\n\t\t\t\t\t\t\t\tonClick={dismissLoginBadge}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon name=\"User\" size=\"lg\" />\n\t\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Login</span>\n\t\t\t\t\t\t\t\t{showLoginBadge ? (\n\t\t\t\t\t\t\t\t\t<OnboardingBadge\n\t\t\t\t\t\t\t\t\t\ttooltip=\"Login for the full experience!\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\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</Link>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\nconst itemVariants = {\n\thidden: { opacity: 0, x: -20 },\n\tvisible: { opacity: 1, x: 0 },\n}\nfunction NavigationExerciseListItem({\n\texerciseNumber,\n\tchildren,\n}: {\n\texerciseNumber: number\n\tchildren: React.ReactNode\n}) {\n\tconst progressClassName = useExerciseProgressClassName(exerciseNumber)\n\treturn (\n\t\t<motion.li\n\t\t\tvariants={itemVariants}\n\t\t\tclassName={cn(\n\t\t\t\t// add gap of 3 to children, but using padding so the progress extends through the whole height\n\t\t\t\t'py-[6px] first:pt-3 last:pb-3',\n\t\t\t\tprogressClassName ? `${progressClassName} before:border-t` : null,\n\t\t\t)}\n\t\t>\n\t\t\t<span className=\"inline-block pl-2\">{children}</span>\n\t\t</motion.li>\n\t)\n}\n\nfunction NavigationExerciseStepListItem({\n\tchildren,\n\t...progressItemSearch\n}: {\n\tchildren: React.ReactNode\n} & ProgressItemSearch) {\n\tconst progressClassName = useProgressItemClassName(progressItemSearch)\n\treturn (\n\t\t<motion.li\n\t\t\tvariants={itemVariants}\n\t\t\tclassName={cn(\n\t\t\t\t// add gap of 3 to children, but using padding so the progress extends through the whole height\n\t\t\t\t'py-[6px] first:pt-3 last:pb-3',\n\t\t\t\tprogressClassName ? `${progressClassName} before:border-t` : null,\n\t\t\t)}\n\t\t>\n\t\t\t<span className=\"inline-block pl-2\">{children}</span>\n\t\t</motion.li>\n\t)\n}\n\nfunction NavigationExtrasListItem({ children }: { children: React.ReactNode }) {\n\treturn (\n\t\t<motion.li\n\t\t\tvariants={itemVariants}\n\t\t\tclassName=\"py-[6px] first:pt-3 last:pb-3\"\n\t\t>\n\t\t\t<span className=\"inline-block pl-2\">{children}</span>\n\t\t</motion.li>\n\t)\n}\n\nconst navHighlightBaseClassName =\n\t'relative px-2 py-0.5 pr-3 whitespace-nowrap outline-none hover:underline focus:underline after:bg-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"]'\n\nfunction getNavHighlightClassName(\n\tisActive: boolean,\n\tclassName?: string | null,\n) {\n\treturn clsx(navHighlightBaseClassName, className, {\n\t\t'bg-foreground text-background': isActive,\n\t})\n}\n\nfunction ExerciseNumberLabel({\n\tlabel,\n\tisActive,\n}: {\n\tlabel: string\n\tisActive: boolean\n}) {\n\treturn (\n\t\t<span\n\t\t\tclassName={clsx('mr-1 align-super text-xs tabular-nums', {\n\t\t\t\t'text-background': isActive,\n\t\t\t\t'text-muted-foreground': !isActive,\n\t\t\t})}\n\t\t>\n\t\t\t{label}.\n\t\t</span>\n\t)\n}\n\nfunction MobileNavigation({\n\tisMenuOpened,\n\tonMenuOpenChange: setMenuOpened,\n\tisServerDown,\n}: {\n\tisMenuOpened: boolean\n\tonMenuOpenChange: (change: boolean) => void\n\tisServerDown: boolean\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tconst apps = useApps()\n\tconst user = useOptionalUser()\n\tconst nextExerciseRoute = useNextExerciseRoute()\n\tconst randomExerciseRoute = useRandomCompletedExerciseRoute()\n\tconst params = useParams()\n\tconst location = useLocation()\n\tconst isOnline = useIsOnline()\n\tconst { users } = usePresence()\n\n\t// Onboarding indicators\n\tconst [showAccountBadge, dismissAccountBadge] =\n\t\tuseOnboardingIndicator('account-link')\n\tconst showExtrasLink = hasExtras(apps)\n\tconst playgroundExtra = data.extras.find(\n\t\t(extra) => extra.name === data.playground.appName,\n\t)\n\tconst isExtrasActive =\n\t\tlocation.pathname === '/extra' || location.pathname.startsWith('/extra/')\n\tconst showExtrasPlaygroundLink = Boolean(playgroundExtra) && !isExtrasActive\n\n\t// items\n\tconst listVariants = {\n\t\tvisible: {\n\t\t\topacity: 1,\n\t\t\ttransition: {\n\t\t\t\tduration: 0.05,\n\t\t\t\twhen: 'beforeChildren',\n\t\t\t\tstaggerChildren: 0.03,\n\t\t\t},\n\t\t},\n\t\thidden: {\n\t\t\topacity: 0,\n\t\t},\n\t}\n\n\tconst requestInfo = useRequestInfo()\n\tconst currentTheme = requestInfo.session.theme ?? 'system'\n\tconst themeLabel = {\n\t\tlight: 'Light',\n\t\tdark: 'Dark',\n\t\tsystem: 'System',\n\t}[currentTheme]\n\tconst [isMobilePopoverOpen, setIsMobilePopoverOpen] = React.useState(false)\n\tconst showMobilePopover = Boolean(data.sidecarStatus)\n\n\t// Reset popover state when it should not be shown to prevent stale state\n\tReact.useEffect(() => {\n\t\tif (!showMobilePopover) {\n\t\t\tsetIsMobilePopoverOpen(false)\n\t\t}\n\t}, [showMobilePopover])\n\n\treturn (\n\t\t<nav className=\"flex w-full border-b sm:hidden\">\n\t\t\t<div className=\"w-full\">\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn('flex items-center', {\n\t\t\t\t\t\t'flex-col': isMenuOpened,\n\t\t\t\t\t\t'h-14': !isMenuOpened,\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<NavToggle\n\t\t\t\t\t\ttitle={data.workshopTitle}\n\t\t\t\t\t\tisMenuOpened={isMenuOpened}\n\t\t\t\t\t\tsetMenuOpened={setMenuOpened}\n\t\t\t\t\t/>\n\t\t\t\t\t{isMenuOpened && (\n\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\tclassName=\"scrollbar-thin scrollbar-thumb-scrollbar flex w-full grow flex-col justify-between overflow-x-auto p-6\"\n\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<motion.ul\n\t\t\t\t\t\t\t\tvariants={listVariants}\n\t\t\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\t\t\tclassName=\"flex flex-col\"\n\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\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\tto=\"/\"\n\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\tclsx(\n\t\t\t\t\t\t\t\t\t\t\t\t'relative px-2 py-0.5 pr-3 text-2xl font-bold whitespace-nowrap outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t{ 'bg-foreground text-background': isActive },\n\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\tHome\n\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{data.exercises.map(({ exerciseNumber, title, steps }) => {\n\t\t\t\t\t\t\t\t\tconst exerciseNumberLabel = exerciseNumber\n\t\t\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t\t\t.padStart(2, '0')\n\t\t\t\t\t\t\t\t\tconst isActive =\n\t\t\t\t\t\t\t\t\t\tNumber(params.exerciseNumber) === exerciseNumber\n\t\t\t\t\t\t\t\t\tconst showPlayground =\n\t\t\t\t\t\t\t\t\t\t!isActive &&\n\t\t\t\t\t\t\t\t\t\tdata.playground.exerciseNumber === exerciseNumber\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<NavigationExerciseListItem\n\t\t\t\t\t\t\t\t\t\t\tkey={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\texerciseNumber={exerciseNumber}\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=\"flex items-center gap-1 text-2xl font-bold\">\n\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExercisePath(exerciseNumber)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative px-2 py-0.5 pr-3 whitespace-nowrap outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ 'bg-foreground text-background': isActive },\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ExerciseNumberLabel\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel={exerciseNumberLabel}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tisActive={isActive}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span>{title}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t\t{showPlayground ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.exerciseNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.stepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.type,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t🛝\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t\t) : null}\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{isActive ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<motion.ul\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariants={listVariants}\n\t\t\t\t\t\t\t\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"mt-2 ml-4 flex flex-col\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<NavigationExerciseStepListItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"instructions\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExercisePath(exerciseNumber)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background relative px-2 py-0.5 pr-3 text-xl font-medium whitespace-nowrap outline-none after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'bg-foreground text-background':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t!params.stepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tIntro\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</NavigationExerciseStepListItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{steps\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.map(({ stepNumber, title, problem, solution }) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavigationExerciseStepListItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={stepNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"step\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstepNumber={stepNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"leading-tight font-semibold\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{stepNumber.toString().padStart(2, '0')}.{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"mt-0.5 ml-3 flex gap-1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{problem && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'problem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetNavHighlightClassName(isActive)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tProblem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{problem.name ===\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.appName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ' 🛝'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{solution && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'solution',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetNavHighlightClassName(isActive)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSolution\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{solution.name ===\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.appName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ' 🛝'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavigationExerciseStepListItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<NavigationExerciseStepListItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"finished\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExercisePath(exerciseNumber, 'finished')}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background relative px-2 py-0.5 pr-3 text-base font-medium whitespace-nowrap outline-none after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'bg-foreground text-background': isActive,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t📝 Elaboration\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</NavigationExerciseStepListItem>\n\t\t\t\t\t\t\t\t\t\t\t\t</motion.ul>\n\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t</NavigationExerciseListItem>\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{showExtrasLink ? (\n\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-1 text-2xl font-bold\">\n\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\tto=\"/extra\"\n\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tclsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative px-2 py-0.5 pr-3 whitespace-nowrap outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ 'bg-foreground text-background': isActive },\n\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t📚 Extras\n\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t{showExtrasPlaygroundLink && playgroundExtra ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\tto={`/extra/${playgroundExtra.dirName}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t🛝\n\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t{isExtrasActive && data.extras.length ? (\n\t\t\t\t\t\t\t\t\t\t\t<motion.ul\n\t\t\t\t\t\t\t\t\t\t\t\tvariants={listVariants}\n\t\t\t\t\t\t\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\t\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"mt-2 ml-4 flex flex-col\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{data.extras.map((extra) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<NavigationExtrasListItem key={extra.dirName}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={`/extra/${extra.dirName}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetNavHighlightClassName(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisActive,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'leading-tight font-semibold',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{extra.title}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{extra.name === data.playground.appName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ' 🛝'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</NavigationExtrasListItem>\n\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t</motion.ul>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</motion.ul>\n\t\t\t\t\t\t\t<div className=\"mt-6\">\n\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\tto=\"/finished\"\n\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\tclsx(\n\t\t\t\t\t\t\t\t\t\t\t'relative text-lg font-bold whitespace-nowrap outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background bg-foreground text-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"]':\n\t\t\t\t\t\t\t\t\t\t\t\t\tisActive,\n\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>\n\t\t\t\t\t\t\t\t\t📝 Workshop Feedback\n\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t)}\n\t\t\t\t\t<div className=\"grow\" />\n\t\t\t\t\t{isOnline ? null : (\n\t\t\t\t\t\t<SimpleTooltip content={isMenuOpened ? null : 'You are offline'}>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex h-14 animate-pulse items-center justify-start p-4',\n\t\t\t\t\t\t\t\t\tisMenuOpened ? 'w-full border-t' : 'border-l',\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<Icon\n\t\t\t\t\t\t\t\t\tname=\"WifiNoConnection\"\n\t\t\t\t\t\t\t\t\tclassName=\"text-foreground-destructive\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isMenuOpened ? 'You are offline' : null}\n\t\t\t\t\t\t\t\t</Icon>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t)}\n\t\t\t\t\t{isServerDown && isOnline ? (\n\t\t\t\t\t\t<SimpleTooltip\n\t\t\t\t\t\t\tcontent={isMenuOpened ? null : serverShutdownTooltip}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex h-14 items-center justify-start p-4',\n\t\t\t\t\t\t\t\t\tisMenuOpened ? 'w-full border-t' : 'border-l',\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<Icon\n\t\t\t\t\t\t\t\t\tname=\"TriangleAlert\"\n\t\t\t\t\t\t\t\t\tclassName=\"text-foreground-destructive\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isMenuOpened ? serverShutdownLabel : null}\n\t\t\t\t\t\t\t\t</Icon>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex items-center justify-start p-4',\n\t\t\t\t\t\t\tisMenuOpened && users.length > 4 ? 'min-h-14' : 'h-14',\n\t\t\t\t\t\t\tisMenuOpened ? 'w-full border-t' : 'border-l',\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<FacePile isMenuOpened={isMenuOpened} />\n\t\t\t\t\t</div>\n\t\t\t\t\t{ENV.EPICSHOP_DEPLOYED ? null : user ? (\n\t\t\t\t\t\t<SimpleTooltip content={isMenuOpened ? null : 'Your account'}>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'relative flex h-14 shrink-0 items-center justify-start space-x-3 px-4 py-4 text-center no-underline hover:underline',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t'border-l': !isMenuOpened,\n\t\t\t\t\t\t\t\t\t\t'w-full border-t': isMenuOpened,\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\tto=\"/account\"\n\t\t\t\t\t\t\t\tonClick={dismissAccountBadge}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{user.imageUrlSmall ? (\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\talt={user.name ?? user.email}\n\t\t\t\t\t\t\t\t\t\tsrc={user.imageUrlSmall}\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-full rounded-full\"\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\t<Icon name=\"User\" className=\"shrink-0\" size=\"lg\" />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tYour Account\n\t\t\t\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Your account</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{showAccountBadge ? (\n\t\t\t\t\t\t\t\t\t<OnboardingBadge\n\t\t\t\t\t\t\t\t\t\ttooltip=\"View your account and preferences\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\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</Link>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{ENV.EPICSHOP_DEPLOYED ? null : user && nextExerciseRoute ? (\n\t\t\t\t\t\t<SimpleTooltip\n\t\t\t\t\t\t\tcontent={isMenuOpened ? null : 'Continue to next lesson'}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto={nextExerciseRoute}\n\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'flex h-14 w-full items-center space-x-3 border-l px-4 py-4 pl-[18px] no-underline hover:underline',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tstate={{ from: 'continue next lesson button' }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon name=\"FastForward\" className=\"shrink-0\" size=\"md\" />\n\t\t\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tContinue to next lesson\n\t\t\t\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Continue to next lesson</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{ENV.EPICSHOP_DEPLOYED ? null : user && randomExerciseRoute ? (\n\t\t\t\t\t\t<SimpleTooltip\n\t\t\t\t\t\t\tcontent={isMenuOpened ? null : 'Practice a past lesson'}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto={randomExerciseRoute}\n\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'flex h-14 w-full items-center space-x-3 border-l px-4 py-4 pl-[18px] no-underline hover:underline',\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<Icon name=\"Refresh\" className=\"shrink-0\" size=\"md\" />\n\t\t\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tPractice a past lesson\n\t\t\t\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Practice a past lesson</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-14 items-center justify-center gap-2 self-start p-4 sm:mb-4',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t'w-full border-t': isMenuOpened,\n\t\t\t\t\t\t\t\t'w-14 border-l': !isMenuOpened,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<ThemeSwitch />\n\t\t\t\t\t\t\t\t<SidecarStatusIndicator status={data.sidecarStatus} />\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : showMobilePopover ? (\n\t\t\t\t\t\t\t<Popover\n\t\t\t\t\t\t\t\topen={isMobilePopoverOpen}\n\t\t\t\t\t\t\t\tonOpenChange={setIsMobilePopoverOpen}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{data.sidecarStatus?.hasFailure ? (\n\t\t\t\t\t\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Process error - click to see details\"\n\t\t\t\t\t\t\t\t\t\t\ttitle={\n\t\t\t\t\t\t\t\t\t\t\t\tisMobilePopoverOpen\n\t\t\t\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'Process error - click to see details'\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md transition-colors\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<StatusIndicator status=\"failed\" />\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</PopoverTrigger>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"More options\"\n\t\t\t\t\t\t\t\t\t\t\ttitle={isMobilePopoverOpen ? undefined : 'More options'}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md transition-colors\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\t\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\t\t\t\t\t\t\tviewBox=\"0 0 20 20\"\n\t\t\t\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<circle cx=\"5\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<circle cx=\"10\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<circle cx=\"15\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" />\n\t\t\t\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</PopoverTrigger>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<PopoverContent\n\t\t\t\t\t\t\t\t\tside=\"top\"\n\t\t\t\t\t\t\t\t\talign=\"start\"\n\t\t\t\t\t\t\t\t\tclassName=\"flex flex-col gap-1 p-2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ThemeSwitchRow\n\t\t\t\t\t\t\t\t\t\tthemeLabel={themeLabel}\n\t\t\t\t\t\t\t\t\t\tdisableTooltip={isMobilePopoverOpen}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t{data.sidecarStatus ? (\n\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\tto=\"/admin\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"hover:bg-muted flex items-center gap-3 rounded-md px-2 py-1.5 text-sm transition-colors\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex h-5 w-5 items-center justify-center\">\n\t\t\t\t\t\t\t\t\t\t\t\t<StatusIndicator\n\t\t\t\t\t\t\t\t\t\t\t\t\tstatus={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.sidecarStatus.hasFailure ? 'failed' : 'running'\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"flex-1 text-left\">\n\t\t\t\t\t\t\t\t\t\t\t\tSidecar process{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t{data.sidecarStatus.hasFailure ? 'error' : 'running'}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t</PopoverContent>\n\t\t\t\t\t\t\t</Popover>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<ThemeSwitch />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</nav>\n\t)\n}\n\nconst OPENED_MENU_WIDTH = 400\n\nfunction SidecarStatusIndicator({\n\tstatus,\n}: {\n\tstatus: { hasFailure: boolean; count: number; failureCount: number } | null\n}) {\n\tif (!status) return null\n\n\treturn (\n\t\t<SimpleTooltip\n\t\t\tcontent={\n\t\t\t\tstatus.hasFailure\n\t\t\t\t\t? `${status.failureCount} sidecar${status.failureCount === 1 ? '' : 's'} failed`\n\t\t\t\t\t: 'All sidecars running'\n\t\t\t}\n\t\t>\n\t\t\t<Link\n\t\t\t\tto=\"/admin\"\n\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md transition-colors\"\n\t\t\t>\n\t\t\t\t<StatusIndicator status={status.hasFailure ? 'failed' : 'running'} />\n\t\t\t</Link>\n\t\t</SimpleTooltip>\n\t)\n}\n\nfunction Navigation({\n\tisMenuOpened,\n\tonMenuOpenChange: setMenuOpened,\n\tisServerDown,\n}: {\n\tisMenuOpened: boolean\n\tonMenuOpenChange: (change: boolean) => void\n\tisServerDown: boolean\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tconst apps = useApps()\n\tconst user = useOptionalUser()\n\tconst nextExerciseRoute = useNextExerciseRoute()\n\tconst randomExerciseRoute = useRandomCompletedExerciseRoute()\n\tconst params = useParams()\n\tconst location = useLocation()\n\tconst isOnline = useIsOnline()\n\tconst { users } = usePresence()\n\n\t// Onboarding indicators\n\tconst [showAccountBadge, dismissAccountBadge] =\n\t\tuseOnboardingIndicator('account-link')\n\tconst showExtrasLink = hasExtras(apps)\n\tconst playgroundExtra = data.extras.find(\n\t\t(extra) => extra.name === data.playground.appName,\n\t)\n\tconst isExtrasActive =\n\t\tlocation.pathname === '/extra' || location.pathname.startsWith('/extra/')\n\tconst showExtrasPlaygroundLink = Boolean(playgroundExtra) && !isExtrasActive\n\n\tconst exercise = data.exercises.find(\n\t\t(e) => e.exerciseNumber === Number(params.exerciseNumber),\n\t)\n\tconst app =\n\t\tparams.type === 'solution'\n\t\t\t? exercise?.solutions.find(\n\t\t\t\t\t(s) => s.stepNumber === Number(params.stepNumber),\n\t\t\t\t)\n\t\t\t: params.type === 'problem'\n\t\t\t\t? exercise?.problems.find(\n\t\t\t\t\t\t(p) => p.stepNumber === Number(params.stepNumber),\n\t\t\t\t\t)\n\t\t\t\t: null\n\n\t// container\n\tconst menuControls = useAnimationControls()\n\tconst menuVariants = {\n\t\tclose: { width: 56 },\n\t\topen: { width: OPENED_MENU_WIDTH },\n\t}\n\n\t// items\n\tconst listVariants = {\n\t\tvisible: {\n\t\t\topacity: 1,\n\t\t\ttransition: {\n\t\t\t\tduration: 0.05,\n\t\t\t\twhen: 'beforeChildren',\n\t\t\t\tstaggerChildren: 0.03,\n\t\t\t},\n\t\t},\n\t\thidden: {\n\t\t\topacity: 0,\n\t\t},\n\t}\n\n\tconst handleOpenShortcuts = React.useCallback(() => {\n\t\tif (typeof window === 'undefined') return\n\t\twindow.dispatchEvent(new CustomEvent('toggle-keyboard-shortcuts'))\n\t}, [])\n\n\tconst requestInfo = useRequestInfo()\n\tconst currentTheme = requestInfo.session.theme ?? 'system'\n\tconst themeLabel = {\n\t\tlight: 'Light',\n\t\tdark: 'Dark',\n\t\tsystem: 'System',\n\t}[currentTheme]\n\tconst [isPopoverOpen, setIsPopoverOpen] = React.useState(false)\n\n\treturn (\n\t\t<nav className=\"hidden border-r sm:flex\">\n\t\t\t<motion.div\n\t\t\t\tinitial={isMenuOpened ? 'open' : 'close'}\n\t\t\t\tvariants={menuVariants}\n\t\t\t\tanimate={menuControls}\n\t\t\t>\n\t\t\t\t<div className=\"flex h-full flex-col items-center justify-between\">\n\t\t\t\t\t<NavToggle\n\t\t\t\t\t\ttitle={data.workshopTitle}\n\t\t\t\t\t\tmenuControls={menuControls}\n\t\t\t\t\t\tisMenuOpened={isMenuOpened}\n\t\t\t\t\t\tsetMenuOpened={setMenuOpened}\n\t\t\t\t\t/>\n\t\t\t\t\t{isMenuOpened && (\n\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\tstyle={{ width: OPENED_MENU_WIDTH }}\n\t\t\t\t\t\t\tclassName=\"scrollbar-thin scrollbar-thumb-scrollbar flex grow flex-col justify-between overflow-y-auto p-6\"\n\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<motion.ul\n\t\t\t\t\t\t\t\tvariants={listVariants}\n\t\t\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\t\t\tclassName=\"flex flex-col\"\n\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\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\tto=\"/\"\n\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\tclsx(\n\t\t\t\t\t\t\t\t\t\t\t\t'relative px-2 py-0.5 pr-3 text-2xl font-bold whitespace-nowrap outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t{ 'bg-foreground text-background': isActive },\n\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\tHome\n\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{data.exercises.map(({ exerciseNumber, title, steps }) => {\n\t\t\t\t\t\t\t\t\tconst exerciseNumberLabel = exerciseNumber\n\t\t\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t\t\t.padStart(2, '0')\n\t\t\t\t\t\t\t\t\tconst isActive =\n\t\t\t\t\t\t\t\t\t\tNumber(params.exerciseNumber) === exerciseNumber\n\t\t\t\t\t\t\t\t\tconst showPlayground =\n\t\t\t\t\t\t\t\t\t\t!isActive &&\n\t\t\t\t\t\t\t\t\t\tdata.playground.exerciseNumber === exerciseNumber\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<NavigationExerciseListItem\n\t\t\t\t\t\t\t\t\t\t\tkey={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\texerciseNumber={exerciseNumber}\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=\"flex items-center gap-1 text-2xl font-bold\">\n\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExercisePath(exerciseNumber)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative px-2 py-0.5 pr-3 whitespace-nowrap outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ 'bg-foreground text-background': isActive },\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ExerciseNumberLabel\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel={exerciseNumberLabel}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tisActive={isActive}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span>{title}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t\t{showPlayground ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.exerciseNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.stepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.type,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t🛝\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t\t) : null}\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{isActive ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<motion.ul\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariants={listVariants}\n\t\t\t\t\t\t\t\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"mt-2 ml-4 flex flex-col\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<NavigationExerciseStepListItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"instructions\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExercisePath(exerciseNumber)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background relative px-2 py-0.5 pr-3 text-xl font-medium whitespace-nowrap outline-none after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'bg-foreground text-background':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t!params.stepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tIntro\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</NavigationExerciseStepListItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{steps\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.map(({ stepNumber, title, problem, solution }) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavigationExerciseStepListItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={stepNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"step\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstepNumber={stepNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"leading-tight font-semibold\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{stepNumber.toString().padStart(2, '0')}.{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"mt-0.5 ml-3 flex gap-1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{problem && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'problem',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetNavHighlightClassName(isActive)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tProblem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{problem.name ===\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.appName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ' 🛝'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{solution && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstepNumber,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'solution',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetNavHighlightClassName(isActive)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSolution\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{solution.name ===\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.playground.appName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ' 🛝'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavigationExerciseStepListItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<NavigationExerciseStepListItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"finished\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\texerciseNumber={exerciseNumber}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={getExercisePath(exerciseNumber, 'finished')}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background relative px-2 py-0.5 pr-3 text-base font-medium whitespace-nowrap outline-none after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'bg-foreground text-background': isActive,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t📝 Elaboration\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</NavigationExerciseStepListItem>\n\t\t\t\t\t\t\t\t\t\t\t\t</motion.ul>\n\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t</NavigationExerciseListItem>\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{showExtrasLink ? (\n\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-1 text-2xl font-bold\">\n\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\tto=\"/extra\"\n\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tclsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative px-2 py-0.5 pr-3 whitespace-nowrap outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"] hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ 'bg-foreground text-background': isActive },\n\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t📚 Extras\n\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t{showExtrasPlaygroundLink && playgroundExtra ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\tto={`/extra/${playgroundExtra.dirName}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t🛝\n\t\t\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t{isExtrasActive && data.extras.length ? (\n\t\t\t\t\t\t\t\t\t\t\t<motion.ul\n\t\t\t\t\t\t\t\t\t\t\t\tvariants={listVariants}\n\t\t\t\t\t\t\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\t\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"mt-2 ml-4 flex flex-col\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{data.extras.map((extra) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<NavigationExtrasListItem key={extra.dirName}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={`/extra/${extra.dirName}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgetNavHighlightClassName(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisActive,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'leading-tight font-semibold',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{extra.title}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{extra.name === data.playground.appName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ' 🛝'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</NavigationExtrasListItem>\n\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t</motion.ul>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</motion.ul>\n\t\t\t\t\t\t\t<div className=\"mt-6\">\n\t\t\t\t\t\t\t\t<NavLink\n\t\t\t\t\t\t\t\t\tto=\"/finished\"\n\t\t\t\t\t\t\t\t\tclassName={({ isActive }) =>\n\t\t\t\t\t\t\t\t\t\tclsx(\n\t\t\t\t\t\t\t\t\t\t\t'relative text-lg font-bold whitespace-nowrap outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t'after:bg-background bg-foreground text-background after:absolute after:-right-2.5 after:-bottom-2.5 after:h-5 after:w-5 after:scale-75 after:rotate-45 after:content-[\"\"]':\n\t\t\t\t\t\t\t\t\t\t\t\t\tisActive,\n\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>\n\t\t\t\t\t\t\t\t\t📝 Workshop Feedback\n\t\t\t\t\t\t\t\t</NavLink>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t)}\n\t\t\t\t\t{!isMenuOpened && (\n\t\t\t\t\t\t<div className=\"flex grow flex-col justify-center\">\n\t\t\t\t\t\t\t<div className=\"orientation-sideways w-full font-mono text-sm leading-none font-medium uppercase\">\n\t\t\t\t\t\t\t\t{exercise?.title ? (\n\t\t\t\t\t\t\t\t\t<Link to={getExercisePath(Number(params.exerciseNumber))}>\n\t\t\t\t\t\t\t\t\t\t{exercise.title}\n\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t{exercise?.title && app?.title ? ' — ' : null}\n\t\t\t\t\t\t\t\t{app?.title ? (\n\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\tto={getExerciseStepPath(\n\t\t\t\t\t\t\t\t\t\t\tNumber(params.exerciseNumber),\n\t\t\t\t\t\t\t\t\t\t\tapp.stepNumber,\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{app.title}\n\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{isOnline ? null : (\n\t\t\t\t\t\t<SimpleTooltip content={isMenuOpened ? null : 'You are offline'}>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex w-full animate-pulse items-center border-t p-4',\n\t\t\t\t\t\t\t\t\tisMenuOpened ? 'justify-start' : 'justify-center',\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<Icon\n\t\t\t\t\t\t\t\t\tname=\"WifiNoConnection\"\n\t\t\t\t\t\t\t\t\tclassName=\"text-foreground-destructive\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t\t\t\t<span className=\"whitespace-nowrap\">You are offline</span>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t</Icon>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t)}\n\t\t\t\t\t{isServerDown && isOnline ? (\n\t\t\t\t\t\t<SimpleTooltip\n\t\t\t\t\t\t\tcontent={isMenuOpened ? null : serverShutdownTooltip}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex w-full items-center border-t p-4',\n\t\t\t\t\t\t\t\t\tisMenuOpened ? 'justify-start' : 'justify-center',\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<Icon\n\t\t\t\t\t\t\t\t\tname=\"TriangleAlert\"\n\t\t\t\t\t\t\t\t\tclassName=\"text-foreground-destructive\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t\t\t\t<span className=\"whitespace-nowrap\">\n\t\t\t\t\t\t\t\t\t\t\t{serverShutdownLabel}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t</Icon>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex w-full items-center justify-start border-t p-4 transition-[height]',\n\t\t\t\t\t\t\tisMenuOpened && users.length > 4 ? 'h-28' : 'h-14',\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={isMenuOpened ? { width: OPENED_MENU_WIDTH } : {}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<FacePile isMenuOpened={isMenuOpened} />\n\t\t\t\t\t</div>\n\t\t\t\t\t{ENV.EPICSHOP_DEPLOYED ? null : user ? (\n\t\t\t\t\t\t<SimpleTooltip content={isMenuOpened ? null : 'Your account'}>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tclassName=\"relative flex h-14 w-full shrink-0 items-center justify-start space-x-3 border-t px-4 py-4 text-center no-underline hover:underline\"\n\t\t\t\t\t\t\t\tto=\"/account\"\n\t\t\t\t\t\t\t\tonClick={dismissAccountBadge}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{user.imageUrlSmall ? (\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\talt={user.name ?? user.email}\n\t\t\t\t\t\t\t\t\t\tsrc={user.imageUrlSmall}\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-full rounded-full\"\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\t<Icon name=\"User\" className=\"shrink-0\" size=\"lg\" />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tYour Account\n\t\t\t\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Your account</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{showAccountBadge ? (\n\t\t\t\t\t\t\t\t\t<OnboardingBadge\n\t\t\t\t\t\t\t\t\t\ttooltip=\"View your account and preferences\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\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</Link>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{ENV.EPICSHOP_DEPLOYED ? null : user && nextExerciseRoute ? (\n\t\t\t\t\t\t<SimpleTooltip\n\t\t\t\t\t\t\tcontent={isMenuOpened ? null : 'Continue to next lesson'}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto={nextExerciseRoute}\n\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'flex h-14 w-full items-center space-x-3 border-t px-4 py-4 pl-[18px] no-underline hover:underline',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tstate={{ from: 'continue next lesson button' }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon name=\"FastForward\" className=\"shrink-0\" size=\"md\" />\n\t\t\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tContinue to next lesson\n\t\t\t\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Continue to next lesson</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{ENV.EPICSHOP_DEPLOYED ? null : user && randomExerciseRoute ? (\n\t\t\t\t\t\t<SimpleTooltip\n\t\t\t\t\t\t\tcontent={isMenuOpened ? null : 'Practice a past lesson'}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tto={randomExerciseRoute}\n\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'flex h-14 w-full items-center space-x-3 border-t px-4 py-4 pl-[18px] no-underline hover:underline',\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<Icon name=\"Refresh\" className=\"shrink-0\" size=\"md\" />\n\t\t\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center whitespace-nowrap\"\n\t\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tPractice a past lesson\n\t\t\t\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Practice a past lesson</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<div className=\"mb-4 w-full self-start border-t pt-[15px] pl-3\">\n\t\t\t\t\t\t{isMenuOpened ? (\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t<ThemeSwitch />\n\t\t\t\t\t\t\t\t<SimpleTooltip content=\"Keyboard shortcuts (press ?)\">\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\taria-label=\"Keyboard shortcuts\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleOpenShortcuts}\n\t\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring flex h-8 w-8 items-center justify-center rounded-md transition-colors focus-visible:ring-2 focus-visible:ring-offset-2\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Icon name=\"Question\" size=\"md\" />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t\t\t\t<SidecarStatusIndicator status={data.sidecarStatus} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>\n\t\t\t\t\t\t\t\t{data.sidecarStatus?.hasFailure ? (\n\t\t\t\t\t\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Process error - click to see details\"\n\t\t\t\t\t\t\t\t\t\t\ttitle={\n\t\t\t\t\t\t\t\t\t\t\t\tisPopoverOpen\n\t\t\t\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'Process error - click to see details'\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md transition-colors\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<StatusIndicator status=\"failed\" />\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</PopoverTrigger>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"More options\"\n\t\t\t\t\t\t\t\t\t\t\ttitle={isPopoverOpen ? undefined : 'More options'}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md transition-colors\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\t\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\t\t\t\t\t\t\tviewBox=\"0 0 20 20\"\n\t\t\t\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<circle cx=\"5\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<circle cx=\"10\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<circle cx=\"15\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" />\n\t\t\t\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</PopoverTrigger>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<PopoverContent\n\t\t\t\t\t\t\t\t\tside=\"top\"\n\t\t\t\t\t\t\t\t\talign=\"start\"\n\t\t\t\t\t\t\t\t\tclassName=\"flex flex-col gap-1 p-2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ThemeSwitchRow\n\t\t\t\t\t\t\t\t\t\tthemeLabel={themeLabel}\n\t\t\t\t\t\t\t\t\t\tdisableTooltip={isPopoverOpen}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\taria-label=\"Keyboard shortcuts\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleOpenShortcuts}\n\t\t\t\t\t\t\t\t\t\tclassName=\"hover:bg-muted flex items-center gap-3 rounded-md px-2 py-1.5 text-sm transition-colors\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex h-5 w-5 items-center justify-center\">\n\t\t\t\t\t\t\t\t\t\t\t<Icon name=\"Question\" size=\"md\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<span className=\"flex-1 text-left\">Keyboard shortcuts</span>\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t{data.sidecarStatus ? (\n\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\tto=\"/admin\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"hover:bg-muted flex items-center gap-3 rounded-md px-2 py-1.5 text-sm transition-colors\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex h-5 w-5 items-center justify-center\">\n\t\t\t\t\t\t\t\t\t\t\t\t<StatusIndicator\n\t\t\t\t\t\t\t\t\t\t\t\t\tstatus={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.sidecarStatus.hasFailure ? 'failed' : 'running'\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"flex-1 text-left\">\n\t\t\t\t\t\t\t\t\t\t\t\tSidecar process{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t{data.sidecarStatus.hasFailure ? 'error' : 'running'}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t</PopoverContent>\n\t\t\t\t\t\t\t</Popover>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</motion.div>\n\t\t</nav>\n\t)\n}\n\nfunction ThemeSwitchRow({\n\tthemeLabel,\n\tdisableTooltip,\n}: {\n\tthemeLabel: string\n\tdisableTooltip?: boolean\n}) {\n\tconst wrapperRef = React.useRef<HTMLDivElement>(null)\n\n\tconst handleClick = (event: React.MouseEvent<HTMLDivElement>) => {\n\t\tconst form = wrapperRef.current?.querySelector<HTMLFormElement>('form')\n\t\tif (!form) return\n\t\tconst submitButton = form.querySelector<HTMLButtonElement>(\n\t\t\t'button[type=\"submit\"]',\n\t\t)\n\t\t// Don't trigger click if the event originated from the submit button itself\n\t\tif (submitButton?.contains(event.target as Node)) {\n\t\t\treturn\n\t\t}\n\t\tsubmitButton?.click()\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={wrapperRef}\n\t\t\tonClick={handleClick}\n\t\t\tclassName=\"hover:bg-muted flex cursor-pointer items-center gap-3 rounded-md px-2 py-1.5 text-sm transition-colors\"\n\t\t>\n\t\t\t<div className=\"flex h-5 w-5 items-center justify-center\">\n\t\t\t\t<ThemeSwitch disableTooltip={disableTooltip} />\n\t\t\t</div>\n\t\t\t<span className=\"flex-1 text-left\">{themeLabel} theme</span>\n\t\t</div>\n\t)\n}\n\nfunction NavToggle({\n\ttitle,\n\tisMenuOpened,\n\tsetMenuOpened,\n\tmenuControls,\n}: {\n\ttitle: string\n\tisMenuOpened: boolean\n\tsetMenuOpened: (value: boolean) => void\n\tmenuControls?: ReturnType<typeof useAnimationControls>\n}) {\n\tconst initialOpenRef = React.useRef(isMenuOpened)\n\tconst menuButtonRef = React.useRef<HTMLButtonElement>(null)\n\tconst path01Variants = {\n\t\topen: { d: 'M3.06061 2.99999L21.0606 21' },\n\t\tclosed: { d: 'M0 9.5L24 9.5' },\n\t}\n\tconst path02Variants = {\n\t\topen: { d: 'M3.00006 21.0607L21 3.06064' },\n\t\tmoving: { d: 'M0 14.5L24 14.5' },\n\t\tclosed: { d: 'M0 14.5L15 14.5' },\n\t}\n\tconst path01Controls = useAnimationControls()\n\tconst path02Controls = useAnimationControls()\n\n\tasync function toggleMenu() {\n\t\tvoid menuControls?.start(isMenuOpened ? 'close' : 'open')\n\t\tsetMenuOpened(!isMenuOpened)\n\t\tif (isMenuOpened) {\n\t\t\tvoid path01Controls.start(path01Variants.closed)\n\t\t\tawait path02Controls.start(path02Variants.moving)\n\t\t\tvoid path02Controls.start(path02Variants.closed)\n\t\t} else {\n\t\t\tawait path02Controls.start(path02Variants.moving)\n\t\t\tvoid path01Controls.start(path01Variants.open)\n\t\t\tvoid path02Controls.start(path02Variants.open)\n\t\t}\n\t}\n\n\tReact.useEffect(() => {\n\t\tif (!isMenuOpened) return\n\n\t\tfunction handleKeyDown(event: KeyboardEvent) {\n\t\t\tif (event.key !== 'Escape' || event.defaultPrevented) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst hasOpenDialog = Boolean(\n\t\t\t\tdocument.querySelector(\n\t\t\t\t\t'[role=\"dialog\"][data-state=\"open\"], [role=\"alertdialog\"][data-state=\"open\"]',\n\t\t\t\t),\n\t\t\t)\n\n\t\t\tif (!hasOpenDialog) {\n\t\t\t\tmenuButtonRef.current?.click()\n\t\t\t}\n\t\t}\n\t\tdocument.addEventListener('keydown', handleKeyDown)\n\t\treturn () => document.removeEventListener('keydown', handleKeyDown)\n\t}, [isMenuOpened])\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'relative inline-flex h-14 shrink-0 items-center justify-between overflow-hidden border-r sm:w-full sm:border-r-0 sm:border-b',\n\t\t\t\t{\n\t\t\t\t\t'w-full': isMenuOpened,\n\t\t\t\t},\n\t\t\t)}\n\t\t>\n\t\t\t<button\n\t\t\t\tref={menuButtonRef}\n\t\t\t\tclassName=\"flex h-14 w-14 items-center justify-center\"\n\t\t\t\taria-label=\"Open Navigation menu\"\n\t\t\t\tonClick={toggleMenu}\n\t\t\t>\n\t\t\t\t<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n\t\t\t\t\t<motion.path\n\t\t\t\t\t\t{...path01Variants[initialOpenRef.current ? 'open' : 'closed']}\n\t\t\t\t\t\tanimate={path01Controls}\n\t\t\t\t\t\ttransition={{ duration: 0.2 }}\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t/>\n\t\t\t\t\t<motion.path\n\t\t\t\t\t\t{...path02Variants[initialOpenRef.current ? 'open' : 'closed']}\n\t\t\t\t\t\tanimate={path02Controls}\n\t\t\t\t\t\ttransition={{ duration: 0.2 }}\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t</button>\n\t\t\t{isMenuOpened && (\n\t\t\t\t<motion.p\n\t\t\t\t\ttransition={{ delay: 0.2 }}\n\t\t\t\t\tinitial={{ opacity: 0, y: 5 }}\n\t\t\t\t\tanimate={{ opacity: 1, y: 0 }}\n\t\t\t\t\tclassName=\"absolute right-5 font-mono text-sm whitespace-nowrap uppercase\"\n\t\t\t\t>\n\t\t\t\t\t<Link to=\"/\">{title}</Link>\n\t\t\t\t</motion.p>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n"],"names":["stopAnimation","visualElement","value","setVariants","variantLabels","key","variant","setTarget","child","setValues","definition","animationControls","subscribers","controls","transitionOverride","animations","animateVisualElement","useAnimationControls","useConstant","useIsomorphicLayoutEffect","makeMediaQueryStore","mediaQuery","serverSnapshot","getSnapshot","subscribe","callback","mediaQueryList","useSyncExternalStore","Popover","props","jsx","PopoverPrimitive.Root","PopoverTrigger","PopoverPrimitive.Trigger","PopoverContent","className","align","sideOffset","PopoverPrimitive.Portal","PopoverPrimitive.Content","cn","healthcheckPath","healthcheckIntervalMs","useServerStatus","isOnline","useIsOnline","isServerDown","setIsServerDown","useState","isCancelledRef","useRef","isOnlineRef","useEffect","checkHealth","useCallback","response","useInterval","opacities","shadows","serverShutdownTooltip","serverShutdownLabel","getScoreClassNames","score","opacityNumber","Math","round","length","shadowNumber","FacePile","isMenuOpened","loggedInUser","useOptionalUser","users","usePresence","product","displayNameShort","useWorkshopConfig","limit","numberOverLimit","shouldShowNumberOverLimit","tiffany","Link","target","rel","to","children","alt","src","overLimitLabel","TooltipProvider","slice","map","user","scoreClassNames","locations","getUserLocations","imageUrl","imageUrlSmall","avatarUrl","hasAccess","local","some","loc","origin","includes","productHostEmojis","getUniqueProductHostEmojis","loggedInEmojis","getLoggedInProductEmojis","loggedInProductHosts","optOut","Tooltip","TooltipTrigger","asChild","tabIndex","Icon","name","TooltipContent","jsxs","id","doingLabel","index","locationLabel","getLocationLabel","line1","getProductHostEmoji","productHost","line2","workshopTitle","hosts","host","filter","Boolean","join","location","uniqueHosts","Set","add","size","Array","from","hasExtras","apps","app","rootDir","relativePath","split","useIsWide","_layout","_UNSAFE_withComponentProps","data","useLoaderData","isWide","isHydrated","useHydrated","setMenuOpenedState","React","useRevalidationWS","watchPaths","setMenuOpened","document","cookie","toString","NoUserBanner","MobileNavigation","onMenuOpenChange","Navigation","Outlet","exercise","exercisePortion","exerciseNumber","stepNumber","s","padStart","type","displayName","userHasAccess","useUserHasAccess","showLoginBadge","dismissLoginBadge","useOnboardingIndicator","details","ENV","EPICSHOP_DEPLOYED","Fragment","EPICSHOP_GITHUB_REPO","href","Logo","style","onClick","OnboardingBadge","tooltip","Dialog","DialogTrigger","DialogContent","DialogHeader","DialogDescription","itemVariants","hidden","opacity","x","visible","NavigationExerciseListItem","progressClassName","useExerciseProgressClassName","motion","li","variants","NavigationExerciseStepListItem","progressItemSearch","useProgressItemClassName","NavigationExtrasListItem","navHighlightBaseClassName","getNavHighlightClassName","isActive","clsx","ExerciseNumberLabel","label","useApps","nextExerciseRoute","useNextExerciseRoute","randomExerciseRoute","useRandomCompletedExerciseRoute","params","useParams","useLocation","showAccountBadge","dismissAccountBadge","showExtrasLink","playgroundExtra","extras","find","extra","playground","appName","isExtrasActive","pathname","startsWith","showExtrasPlaygroundLink","listVariants","transition","duration","when","staggerChildren","currentTheme","useRequestInfo","session","theme","themeLabel","light","dark","system","isMobilePopoverOpen","setIsMobilePopoverOpen","showMobilePopover","sidecarStatus","NavToggle","title","div","initial","animate","ul","NavLink","prefetch","exercises","steps","exerciseNumberLabel","Number","showPlayground","getExercisePath","getExerciseStepPath","problem","solution","dirName","SimpleTooltip","content","email","state","ThemeSwitch","SidecarStatusIndicator","status","open","onOpenChange","hasFailure","StatusIndicator","width","height","viewBox","fill","xmlns","cx","cy","r","side","ThemeSwitchRow","disableTooltip","OPENED_MENU_WIDTH","failureCount","e","solutions","problems","p","menuControls","menuVariants","close","handleOpenShortcuts","window","dispatchEvent","CustomEvent","isPopoverOpen","setIsPopoverOpen","wrapperRef","handleClick","event","form","current","querySelector","submitButton","contains","click","ref","initialOpenRef","menuButtonRef","path01Variants","d","closed","path02Variants","moving","path01Controls","path02Controls","toggleMenu","start","handleKeyDown","defaultPrevented","addEventListener","removeEventListener","path","stroke","strokeWidth","delay","y"],"mappings":"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","x_google_ignoreList":[0,1]}
@@ -1,2 +1,2 @@
1
- import{w as i,L as s,O as l}from"./chunk-EPOLDU6W-BCLmut3y.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{g as a}from"./root-loader-BOzEMapJ.js";import"./index-CqIc3cxq.js";const m={getSitemapEntries:()=>null},x=({matches:n})=>[{title:`👷 | ${a(n)?.workshopTitle}`}],h=i(function(){return e.jsxs("main",{className:"container mx-auto mt-8",children:[e.jsx("h1",{className:"text-4xl font-bold",children:"Admin"}),e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("nav",{children:e.jsxs("ul",{className:"flex gap-3",children:[e.jsx("li",{children:e.jsx(s,{className:"underline",to:"/",children:"Home"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"/admin",children:"Admin"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"/diff",children:"Diff Viewer"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"db",children:"Database"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"cache",children:"Cache Management"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"offline-videos",children:"Offline Videos"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"version",children:"Version"})})]})}),e.jsx(l,{})]})]})});export{h as default,m as handle,x as meta};
2
- //# sourceMappingURL=_layout-CunOyAg4.js.map
1
+ import{w as i,L as s,O as l}from"./chunk-EPOLDU6W-BCLmut3y.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{g as a}from"./root-loader-BmUqzUDN.js";import"./index-CqIc3cxq.js";const m={getSitemapEntries:()=>null},x=({matches:n})=>[{title:`👷 | ${a(n)?.workshopTitle}`}],h=i(function(){return e.jsxs("main",{className:"container mx-auto mt-8",children:[e.jsx("h1",{className:"text-4xl font-bold",children:"Admin"}),e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("nav",{children:e.jsxs("ul",{className:"flex gap-3",children:[e.jsx("li",{children:e.jsx(s,{className:"underline",to:"/",children:"Home"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"/admin",children:"Admin"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"/diff",children:"Diff Viewer"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"db",children:"Database"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"cache",children:"Cache Management"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"offline-videos",children:"Offline Videos"})}),e.jsx("li",{children:e.jsx(s,{className:"underline",to:"version",children:"Version"})})]})}),e.jsx(l,{})]})]})});export{h as default,m as handle,x as meta};
2
+ //# sourceMappingURL=_layout-CDyeQVKG.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"_layout-CunOyAg4.js","sources":["../../../app/routes/admin+/_layout.tsx"],"sourcesContent":["import { type SEOHandle } from '@nasa-gcn/remix-seo'\nimport { Link, Outlet } from 'react-router'\nimport { getRootMatchLoaderData } from '#app/utils/root-loader.ts'\nimport { type Route } from './+types/_layout.tsx'\n\nexport const handle: SEOHandle = {\n\tgetSitemapEntries: () => null,\n}\n\nexport const meta: Route.MetaFunction = ({ matches }) => {\n\tconst rootData = getRootMatchLoaderData(matches)\n\treturn [{ title: `👷 | ${rootData?.workshopTitle}` }]\n}\n\nexport default function AdminLayout() {\n\treturn (\n\t\t<main className=\"container mx-auto mt-8\">\n\t\t\t<h1 className=\"text-4xl font-bold\">Admin</h1>\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t<nav>\n\t\t\t\t\t<ul className=\"flex gap-3\">\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"/\">\n\t\t\t\t\t\t\t\tHome\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"/admin\">\n\t\t\t\t\t\t\t\tAdmin\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"/diff\">\n\t\t\t\t\t\t\t\tDiff Viewer\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"db\">\n\t\t\t\t\t\t\t\tDatabase\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"cache\">\n\t\t\t\t\t\t\t\tCache Management\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"offline-videos\">\n\t\t\t\t\t\t\t\tOffline Videos\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"version\">\n\t\t\t\t\t\t\t\tVersion\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</nav>\n\t\t\t\t<Outlet />\n\t\t\t</div>\n\t\t</main>\n\t)\n}\n"],"names":["handle","getSitemapEntries","meta","matches","title","getRootMatchLoaderData","workshopTitle","_layout","_UNSAFE_withComponentProps","jsxs","className","children","jsx","Link","to","Outlet"],"mappings":"uLAKO,MAAMA,EAAoB,CAChCC,kBAAmBA,IAAM,IAC1B,EAEaC,EAA2BA,CAAC,CAAEC,QAAAA,CAAQ,IAE3C,CAAC,CAAEC,MAAO,QADAC,EAAuBF,CAAO,GACZG,aAAa,EAAG,CAAC,EAGrDC,EAAAC,EAAA,UAAsC,CACrC,OACCC,EAAAA,KAAC,OAAA,CAAKC,UAAU,yBACfC,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAGF,UAAU,qBAAqBC,SAAA,OAAA,CAAK,EACxCF,EAAAA,KAAC,MAAA,CAAIC,UAAU,sBACdC,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACAD,SAAAF,EAAAA,KAAC,KAAA,CAAGC,UAAU,aACbC,SAAA,CAAAC,EAAAA,IAAC,KAAA,CACAD,eAACE,EAAA,CAAKH,UAAU,YAAYI,GAAG,IAAIH,gBAEnC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,SAASH,SAAA,QAExC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,QAAQH,SAAA,cAEvC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,KAAKH,SAAA,WAEpC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,QAAQH,SAAA,mBAEvC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,iBAAiBH,SAAA,iBAEhD,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,UAAUH,SAAA,UAEzC,CAAA,CACD,CAAA,EACD,EACD,QACCI,EAAA,EAAO,CAAA,CAAA,CACT,CAAA,CAAA,CACD,CAEF,CAAA"}
1
+ {"version":3,"file":"_layout-CDyeQVKG.js","sources":["../../../app/routes/admin+/_layout.tsx"],"sourcesContent":["import { type SEOHandle } from '@nasa-gcn/remix-seo'\nimport { Link, Outlet } from 'react-router'\nimport { getRootMatchLoaderData } from '#app/utils/root-loader.ts'\nimport { type Route } from './+types/_layout.tsx'\n\nexport const handle: SEOHandle = {\n\tgetSitemapEntries: () => null,\n}\n\nexport const meta: Route.MetaFunction = ({ matches }) => {\n\tconst rootData = getRootMatchLoaderData(matches)\n\treturn [{ title: `👷 | ${rootData?.workshopTitle}` }]\n}\n\nexport default function AdminLayout() {\n\treturn (\n\t\t<main className=\"container mx-auto mt-8\">\n\t\t\t<h1 className=\"text-4xl font-bold\">Admin</h1>\n\t\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t\t<nav>\n\t\t\t\t\t<ul className=\"flex gap-3\">\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"/\">\n\t\t\t\t\t\t\t\tHome\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"/admin\">\n\t\t\t\t\t\t\t\tAdmin\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"/diff\">\n\t\t\t\t\t\t\t\tDiff Viewer\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"db\">\n\t\t\t\t\t\t\t\tDatabase\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"cache\">\n\t\t\t\t\t\t\t\tCache Management\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"offline-videos\">\n\t\t\t\t\t\t\t\tOffline Videos\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<Link className=\"underline\" to=\"version\">\n\t\t\t\t\t\t\t\tVersion\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</nav>\n\t\t\t\t<Outlet />\n\t\t\t</div>\n\t\t</main>\n\t)\n}\n"],"names":["handle","getSitemapEntries","meta","matches","title","getRootMatchLoaderData","workshopTitle","_layout","_UNSAFE_withComponentProps","jsxs","className","children","jsx","Link","to","Outlet"],"mappings":"uLAKO,MAAMA,EAAoB,CAChCC,kBAAmBA,IAAM,IAC1B,EAEaC,EAA2BA,CAAC,CAAEC,QAAAA,CAAQ,IAE3C,CAAC,CAAEC,MAAO,QADAC,EAAuBF,CAAO,GACZG,aAAa,EAAG,CAAC,EAGrDC,EAAAC,EAAA,UAAsC,CACrC,OACCC,EAAAA,KAAC,OAAA,CAAKC,UAAU,yBACfC,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAGF,UAAU,qBAAqBC,SAAA,OAAA,CAAK,EACxCF,EAAAA,KAAC,MAAA,CAAIC,UAAU,sBACdC,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACAD,SAAAF,EAAAA,KAAC,KAAA,CAAGC,UAAU,aACbC,SAAA,CAAAC,EAAAA,IAAC,KAAA,CACAD,eAACE,EAAA,CAAKH,UAAU,YAAYI,GAAG,IAAIH,gBAEnC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,SAASH,SAAA,QAExC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,QAAQH,SAAA,cAEvC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,KAAKH,SAAA,WAEpC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,QAAQH,SAAA,mBAEvC,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,iBAAiBH,SAAA,iBAEhD,CAAA,CACD,EACAC,EAAAA,IAAC,MACAD,SAAAC,EAAAA,IAACC,EAAA,CAAKH,UAAU,YAAYI,GAAG,UAAUH,SAAA,UAEzC,CAAA,CACD,CAAA,EACD,EACD,QACCI,EAAA,EAAO,CAAA,CAAA,CACT,CAAA,CAAA,CACD,CAEF,CAAA"}
@@ -0,0 +1,2 @@
1
+ import{b as h,d as C,L as f,A as k,w as D,a as L,O}from"./chunk-EPOLDU6W-BCLmut3y.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{E as I}from"./index-CEVyDj51.js";import{r as u}from"./index-CqIc3cxq.js";import{G as R}from"./error-boundary-DxHqAEHX.js";import{N as $}from"./nav-chevrons-Dk4GtZwQ.js";import{u as A}from"./revalidation-ws-iocj9Mrl.js";import{L as j,E as T}from"./launch-editor-0oPpbFQe.js";import{P as B}from"./progress-JDMkfyr3.js";import{S}from"./set-playground-DO5tJu4h.js";import{l as U,c as v,I as g,m as H,n as V}from"./misc-W4055b-0.js";import{b as _,g as F,a as Y}from"./root-loader-BmUqzUDN.js";import{g as M}from"./seo-t5J-DRxw.js";import{s as y,a as q}from"./split-layout-DnRER1bP.js";import{E as G}from"./error-boundary-BDqWjIFP.js";import{E as X}from"./epic-video-D4jBdSKs.js";import{S as N}from"./tooltip-Tlsyx2YO.js";import{M as z}from"./mdx-DwvWT4Ou.js";import{R as K,T as Q,P as W,C as J}from"./index-CmflCPTU.js";import{u as Z,O as ee}from"./onboarding-indicator-BkeHYs2C.js";import"./preload-helper-BXl3LOEh.js";import"./schemas-Uj5SZtvt.js";import"./progress-bar-DpWhcyhC.js";import"./pe-CIZUOJMr.js";import"./index-CJDOQ1bl.js";import"./index-vDCSPjrM.js";import"./index-ynYvVAOK.js";import"./button-Cd-ekki5.js";import"./dialog-CzO65Z5w.js";import"./chunk-FNSCYPCZ-BHgC5cdx.js";import"./coerce-CkHW0SMv.js";import"./use-event-source-BuD4_2SF.js";import"./index-DzdDahau.js";import"./index-BrVvTrwg.js";import"./online-DVk-W8Cr.js";import"./loading-CaCCsk9k.js";import"./format-CZ5n8p10.js";import"./user-CYXKquT7.js";import"./workshop-config-BMWaKPZT.js";const P=u.createContext(null);function ne(){const r=u.useContext(P);if(!r)throw new Error("useStepContext must be used within a StepContextProvider");return r}function re({children:r,inBrowserBrowserRef:n}){return e.jsx(P,{value:{inBrowserBrowserRef:n},children:r})}const te={DiffLink:b,PrevDiffLink:oe,NextDiffLink:ie,InlineFile:le,LinkToApp:ce};function se({inBrowserBrowserRef:r}){const n=h();return n.exerciseStepApp.instructionsCode?e.jsx(re,{inBrowserBrowserRef:r,children:e.jsx(X,{epicVideoInfosPromise:n.epicVideoInfosPromise,children:e.jsx("div",{className:"prose dark:prose-invert sm:prose-lg",children:e.jsx(z,{code:n.exerciseStepApp.instructionsCode,components:te})})})}):null}function w(r,n,t){const s=new URLSearchParams(r);return t===null?s.delete(n):s.set(n,t),s}function ie({app:r=0,fullPage:n=!1,children:t}){return e.jsx(b,{app1:r,app2:r+1,fullPage:n,children:t})}function oe({app:r=-1,fullPage:n=!1,children:t}){return e.jsx(b,{app1:r,app2:r+1,fullPage:n,children:t})}function b({app1:r=0,app2:n=1,children:t,fullPage:s=!1,to:o}){const i=h();if(!o&&!r&&!n)return e.jsx("callout-danger",{className:"notification",children:e.jsx("div",{className:"title",children:"DiffLink Error: invalid input"})});function d(l){if(typeof l=="number"){const p=i.exerciseIndex+l;return i.allApps[p]?.name}if(!l)return null;for(const{name:p,stepName:c}of i.allApps)if(l===p||l===c)return p;return null}if(o){const l=new URLSearchParams(o);r=l.get("app1"),n=l.get("app2")}const m=d(r),a=d(n);if(!m||!a)return e.jsxs("callout-danger",{className:"notification",children:[e.jsx("div",{className:"title",children:"DiffLink Error: invalid input"}),!m&&e.jsxs("div",{children:['app1: "',r,'" is not a valid app name']}),!a&&e.jsxs("div",{children:['app2: "',n,'" is not a valid app name']})]});o||(o=`app1=${m}&app2=${a}`);const x=s?`/diff?${o}`:`?${decodeURIComponent(w(new URLSearchParams,"preview",`diff&${o}`).toString())}`;return t||(t=e.jsxs("span",{children:["Go to Diff ",s?"":"Preview"," from: ",e.jsx("code",{children:m})," to:"," ",e.jsx("code",{children:a})]})),e.jsx(f,{to:x,children:t})}function le({file:r,type:n="playground",children:t=e.jsx("code",{children:r}),...s}){const o=h(),i=o[n]||o[o.type],d=e.jsxs("div",{className:"launch-editor-button-wrapper flex underline underline-offset-4",children:[t," ",e.jsx("svg",{height:24,width:24,children:e.jsx("use",{href:`${H}#Keyboard`})})]});return ENV.EPICSHOP_DEPLOYED&&i?e.jsx("div",{className:"inline-block grow",children:e.jsx(j,{appFile:r,appName:i.name,...s,children:d})}):i?e.jsx("div",{className:"inline-block grow",children:e.jsx(j,{appFile:r,appName:i.name,...s,children:d})}):n==="playground"?e.jsx(N,{content:"You must 'Set to Playground' before opening a file",children:e.jsx("div",{className:"inline-block grow cursor-not-allowed",children:d})}):e.jsx(e.Fragment,{children:"children"})}function ae(r){return r==="problem"?"problem":r==="solution"?"solution":"playground"}function ce({to:r,children:n=e.jsx("code",{children:r.toString()}),...t}){const[s]=C(),o=`?${w(s,"pathname",r.toString()).toString()}`,i=h(),d=ae(s.get("preview")),m=_(),a=i[d],x=a?.dev.type==="script"?U({domain:m.domain,port:a.dev.portNumber}):i.playground?.dev.type==="browser"||i.playground?.dev.type==="export"?i.playground.dev.pathname:null,{inBrowserBrowserRef:l}=ne(),p=x?x.slice(0,-1)+r.toString():null;return e.jsxs("div",{className:"inline-flex items-center justify-between gap-1",children:[e.jsx(f,{to:o,...t,className:v(t.className,{"cursor-not-allowed":ENV.EPICSHOP_DEPLOYED}),title:ENV.EPICSHOP_DEPLOYED?"Cannot link to app in deployed version":void 0,onClick:c=>{ENV.EPICSHOP_DEPLOYED&&c.preventDefault(),t.onClick?.(c),l.current?.handleExtrnalNavigation(r.toString())},children:n}),p?e.jsx(N,{content:"Open in new tab",children:e.jsx("a",{href:p,target:"_blank",rel:"noreferrer",className:v("flex aspect-square items-center justify-center",{"cursor-not-allowed":ENV.EPICSHOP_DEPLOYED}),title:ENV.EPICSHOP_DEPLOYED?"Cannot link to app in deployed version":"Open in new tab",onClick:c=>{ENV.EPICSHOP_DEPLOYED&&c.preventDefault()},children:e.jsx(g,{name:"ExternalLink"})})}):null]})}function pe({diffFilesPromise:r}){const n=h(),[t,s]=Z("files-popover"),[o,i]=u.useState(!1),d=u.useRef(null);function m(l){i(l),l&&s()}function a(){i(!1)}const x=n.playground?.appName;return e.jsx(e.Fragment,{children:e.jsxs(K,{open:o,onOpenChange:m,children:[e.jsx(Q,{asChild:!0,children:e.jsxs("button",{className:"relative flex h-full items-center gap-1 border-r px-6 py-3 font-mono text-sm uppercase","aria-label":"Relevant Files",children:[e.jsx(g,{name:"Files"}),e.jsx("span",{className:"hidden @min-[640px]:inline",children:"Files"}),t?e.jsx(ee,{tooltip:"Click to see which files to edit!"}):null]})}),e.jsx(W,{children:e.jsx(J,{ref:d,className:"slideRightContent lg:slideUpContent invert-theme bg-background text-foreground z-10 rounded px-9 py-8 select-none",align:"start",sideOffset:5,children:e.jsxs("div",{className:"launch-editor-wrapper",children:[e.jsx("strong",{className:"inline-block px-2 pb-2 font-semibold uppercase",children:"Relevant Files"}),e.jsxs("p",{className:"text-muted-foreground mb-4 max-w-2xs px-2 text-sm",children:["These are the files you'll need to modify for this exercise. Click any file to open it directly in your editor at the right location."," ",e.jsx(f,{to:"/guide#file-links",className:"text-highlight underline",onClick:()=>i(!1),children:"Learn more →"})]}),n.problem&&n.playground?.appName!==n.problem.name?e.jsx("div",{className:"mb-2 rounded p-1 font-mono font-medium",children:e.jsx(S,{appName:n.problem.name})}):null,e.jsx("div",{id:"files",children:e.jsx(u.Suspense,{fallback:e.jsx(N,{content:"Loading diff",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(g,{name:"Refresh",className:"h-8 w-8 animate-spin"})})}),children:e.jsx(k,{resolve:r,errorElement:e.jsx("div",{className:"text-foreground-destructive",children:"Something went wrong."}),children:l=>{if(!l)return e.jsx("p",{className:"text-foreground-destructive",children:"Unable to determine diff"});if(typeof l=="string")return e.jsx("p",{className:"text-foreground-destructive",children:l});if(!l.length)return e.jsx("p",{children:"No files changed"});const p=x||ENV.EPICSHOP_GITHUB_ROOT?{}:{title:"You must 'Set to Playground' before opening a file",className:"not-allowed"};return e.jsxs("ul",{...p,children:[l.length>1&&!ENV.EPICSHOP_DEPLOYED?e.jsx("div",{className:"border-opacity-50 mb-2 border-b border-b-gray-50 pb-2 font-sans",children:e.jsx(j,{appFile:l.map(c=>`${c.path},${c.line},1`),appName:"playground",onUpdate:a,children:e.jsx("p",{children:"Open All Files"})})}):null,l.map(c=>e.jsx("li",{"data-state":c.status,children:e.jsx(j,{appFile:`${c.path},${c.line},1`,appName:ENV.EPICSHOP_DEPLOYED?n.problem?.name??"playground":"playground",onUpdate:a,children:e.jsx("code",{children:c.path})})},c.path))]})}})})})]})})})]})})}function E(r,n){const t=r?.exerciseStepApp.exerciseNumber.toString().padStart(2,"0")??"00",s=r?.exerciseStepApp.stepNumber.toString().padStart(2,"0")??"00",o={problem:"💪",solution:"🏁"}[r?.type??"problem"],i=r?.[r.type]?.title??"N/A";return{emoji:o,stepNumber:s,title:i,exerciseNumber:t,exerciseTitle:r?.exerciseTitle??"Unknown exercise",workshopTitle:n,type:r?.type??"problem"}}const Qe=({loaderData:r,matches:n,params:t})=>{const s=F(n);if(!r||!s)return[{title:"🦉 | Error"}];const{emoji:o,stepNumber:i,title:d,exerciseNumber:m,exerciseTitle:a}=E(r);return M({title:`${o} | ${i}. ${d} | ${m}. ${a} | ${s.workshopTitle}`,description:`${t.type} step for exercise ${m}. ${a}`,ogTitle:d,ogDescription:`${a} step ${Number(i)} ${t.type}`,instructor:s.instructor,requestInfo:s.requestInfo})},We=D(function({loaderData:n}){const t=Y(),s=u.useRef(null),o=u.useRef(null),i=u.useRef(null),[d,m]=u.useState(n.splitPercent),a=E(n),x=t.find(p=>p.name===n.playground?.appName)?.fullPath;A({watchPaths:[`${n.exerciseStepApp.relativePath}/README.mdx`,x].filter(p=>!!p)});const l=n.problem?n.playground?.appName!==n.problem.name:!1;return e.jsx("div",{className:"flex max-w-full grow flex-col",children:e.jsxs("main",{ref:o,className:"flex grow flex-col overflow-y-auto sm:h-full sm:min-h-[800px] md:min-h-[unset] lg:flex-row lg:overflow-y-hidden",children:[e.jsxs("div",{className:"relative flex min-w-0 flex-none basis-auto flex-col sm:col-span-1 sm:row-span-1 lg:h-full lg:basis-(--split-pct)",style:{"--split-pct":`${d}%`},ref:i,children:[e.jsx("h1",{className:"@container h-14 border-b pr-5 pl-10 text-sm leading-tight font-medium",children:e.jsxs("div",{className:"flex h-14 items-center justify-between gap-x-2 py-2 whitespace-nowrap",children:[e.jsxs("div",{className:"flex items-center justify-start gap-x-2 uppercase",children:[e.jsxs(f,{to:V(n.exerciseStepApp.exerciseNumber),className:"hover:underline",children:[e.jsxs("span",{children:[a.exerciseNumber,"."]}),e.jsxs("span",{className:"hidden @min-[500px]:inline",children:[" ",a.exerciseTitle]})]}),e.jsx("span",{children:"/"}),e.jsxs(f,{to:".",className:"hover:underline",children:[e.jsxs("span",{children:[a.stepNumber,"."]}),e.jsxs("span",{className:"hidden @min-[300px]:inline",children:[" ",a.title]}),e.jsxs("span",{children:[" (",a.emoji]}),e.jsxs("span",{className:"hidden @min-[400px]:inline",children:[" ",a.type]}),e.jsx("span",{children:")"})]})]}),n.problem&&(n.playground?.appName!==n.problem.name||!n.playground?.isUpToDate)?e.jsx(S,{appName:n.problem.name,isOutdated:n.playground?.isUpToDate===!1,hideTextOnNarrow:!0,showOnboardingIndicator:l}):null]})}),e.jsxs("article",{id:n.articleId,className:"shadow-on-scrollbox scrollbar-thin scrollbar-thumb-scrollbar flex w-full max-w-none scroll-pt-6 flex-col justify-between space-y-6 p-2 sm:p-10 sm:pt-8 lg:h-full lg:flex-1 lg:overflow-y-auto",children:[n.exerciseStepApp.instructionsCode?e.jsx(se,{inBrowserBrowserRef:s}):e.jsx("div",{className:"flex h-full items-center justify-center text-lg",children:e.jsx("p",{children:"No instructions yet..."})}),e.jsxs("div",{className:"mt-auto flex justify-between",children:[n.prevStepLink?e.jsxs(f,{to:n.prevStepLink.to,"aria-label":"Previous Step","data-keyboard-action":"g+p",prefetch:"intent",children:[e.jsx("span",{"aria-hidden":!0,children:"←"}),e.jsx("span",{className:"hidden xl:inline",children:" Previous"})]}):e.jsx("span",{}),n.nextStepLink?e.jsxs(f,{to:n.nextStepLink.to,"aria-label":"Next Step","data-keyboard-action":"g+n",prefetch:"intent",children:[e.jsx("span",{className:"hidden xl:inline",children:"Next "}),e.jsx("span",{"aria-hidden":!0,children:"→"})]}):e.jsx("span",{})]})]},n.articleId),e.jsx(I,{elementQuery:`#${n.articleId}`},`scroll-${n.articleId}`),n.type==="solution"?e.jsx(B,{type:"step",exerciseNumber:n.exerciseStepApp.exerciseNumber,stepNumber:n.exerciseStepApp.stepNumber,className:"h-14 border-t px-6"}):null,e.jsxs("div",{className:"@container flex h-16 justify-between border-t border-b-4 lg:border-b-0",children:[e.jsx("div",{children:e.jsx("div",{className:"h-full",children:e.jsx(pe,{diffFilesPromise:n.diffFiles})})}),e.jsx(T,{appName:n.exerciseStepApp.name,relativePath:`${n.exerciseStepApp.relativePath}/README.mdx`}),e.jsx($,{prev:n.prevStepLink?{to:n.prevStepLink.to,"aria-label":"Previous Step"}:null,next:n.nextStepLink?{to:n.nextStepLink.to,"aria-label":"Next Step"}:null})]})]}),e.jsx("div",{role:"separator","aria-orientation":"vertical",title:"Drag to resize",className:"bg-border hover:bg-accent hidden w-1 cursor-col-resize lg:block",onMouseDown:p=>y({container:o.current,initialClientX:p.clientX,setSplitPercent:m}),onDoubleClick:()=>{m(q(50))},onTouchStart:p=>{const c=p.touches?.[0];c&&y({container:o.current,initialClientX:c.clientX,setSplitPercent:m})}}),e.jsx("div",{className:"flex min-h-[50vh] min-w-0 flex-none lg:min-h-0 lg:flex-1",children:e.jsx(O,{context:{inBrowserBrowserRef:s}})})]})})}),Je=L(function(){return e.jsx(R,{className:"container flex items-center justify-center",statusHandlers:{404:G}})});export{Je as ErrorBoundary,We as default,Qe as meta};
2
+ //# sourceMappingURL=_layout-mVyOtxmC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_layout-mVyOtxmC.js","sources":["../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/step-mdx.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/touched-files.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout.tsx"],"sourcesContent":["import * as React from 'react'\nimport { type PropsWithChildren } from 'react'\nimport {\n\tLink,\n\tuseLoaderData,\n\tuseSearchParams,\n\ttype LinkProps,\n} from 'react-router'\nimport iconsSvg from '#app/assets/icons.svg'\nimport { EpicVideoInfoProvider } from '#app/components/epic-video.tsx'\nimport { Icon } from '#app/components/icons.tsx'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser.tsx'\nimport { SimpleTooltip } from '#app/components/ui/tooltip.tsx'\nimport { LaunchEditor } from '#app/routes/launch-editor.tsx'\nimport { Mdx } from '#app/utils/mdx.tsx'\nimport { cn, getBaseUrl } from '#app/utils/misc.tsx'\nimport { useRequestInfo } from '#app/utils/root-loader.ts'\nimport { type loader } from '../_layout.tsx'\n\ntype StepContextType = {\n\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n}\nconst StepContext = React.createContext<StepContextType | null>(null)\n\nfunction useStepContext() {\n\tconst context = React.useContext(StepContext)\n\tif (!context) {\n\t\tthrow new Error('useStepContext must be used within a StepContextProvider')\n\t}\n\treturn context\n}\n\nfunction StepContextProvider({\n\tchildren,\n\tinBrowserBrowserRef,\n}: {\n\tchildren: React.ReactNode\n\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n}) {\n\treturn <StepContext value={{ inBrowserBrowserRef }}>{children}</StepContext>\n}\n\nconst stepMdxComponents = {\n\tDiffLink,\n\tPrevDiffLink,\n\tNextDiffLink,\n\tInlineFile,\n\tLinkToApp,\n}\n\nexport function StepMdx({\n\tinBrowserBrowserRef,\n}: {\n\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tif (!data.exerciseStepApp.instructionsCode) return null\n\treturn (\n\t\t<StepContextProvider inBrowserBrowserRef={inBrowserBrowserRef}>\n\t\t\t<EpicVideoInfoProvider epicVideoInfosPromise={data.epicVideoInfosPromise}>\n\t\t\t\t<div className=\"prose dark:prose-invert sm:prose-lg\">\n\t\t\t\t\t<Mdx\n\t\t\t\t\t\tcode={data.exerciseStepApp.instructionsCode}\n\t\t\t\t\t\tcomponents={stepMdxComponents}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</EpicVideoInfoProvider>\n\t\t</StepContextProvider>\n\t)\n}\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\nfunction NextDiffLink({\n\tapp = 0,\n\tfullPage = false,\n\tchildren,\n}: {\n\tapp: number\n\tfullPage?: boolean\n\tchildren?: React.ReactNode\n}) {\n\treturn (\n\t\t<DiffLink app1={app} app2={app + 1} fullPage={fullPage}>\n\t\t\t{children}\n\t\t</DiffLink>\n\t)\n}\n\nfunction PrevDiffLink({\n\tapp = -1,\n\tfullPage = false,\n\tchildren,\n}: {\n\tapp: number\n\tfullPage?: boolean\n\tchildren?: React.ReactNode\n}) {\n\treturn (\n\t\t<DiffLink app1={app} app2={app + 1} fullPage={fullPage}>\n\t\t\t{children}\n\t\t</DiffLink>\n\t)\n}\n\nfunction DiffLink({\n\tapp1 = 0,\n\tapp2 = 1,\n\tchildren,\n\tfullPage = false,\n\tto,\n}: {\n\tapp1?: string | number | null\n\tapp2?: string | number | null\n\tto?: string\n\tfullPage?: boolean\n\tchildren?: React.ReactNode\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tif (!to && !app1 && !app2) {\n\t\treturn (\n\t\t\t<callout-danger className=\"notification\">\n\t\t\t\t<div className=\"title\">DiffLink Error: invalid input</div>\n\t\t\t</callout-danger>\n\t\t)\n\t}\n\n\tfunction getAppName(input: typeof app1) {\n\t\tif (typeof input === 'number') {\n\t\t\tconst stepIndex = data.exerciseIndex + input\n\t\t\treturn data.allApps[stepIndex]?.name\n\t\t}\n\t\tif (!input) return null\n\t\tfor (const { name, stepName } of data.allApps) {\n\t\t\tif (input === name || input === stepName) {\n\t\t\t\treturn name\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\tif (to) {\n\t\tconst params = new URLSearchParams(to)\n\t\tapp1 = params.get('app1')\n\t\tapp2 = params.get('app2')\n\t}\n\tconst app1Name = getAppName(app1)\n\tconst app2Name = getAppName(app2)\n\tif (!app1Name || !app2Name) {\n\t\treturn (\n\t\t\t<callout-danger className=\"notification\">\n\t\t\t\t<div className=\"title\">DiffLink Error: invalid input</div>\n\t\t\t\t{!app1Name && <div>app1: \"{app1}\" is not a valid app name</div>}\n\t\t\t\t{!app2Name && <div>app2: \"{app2}\" is not a valid app name</div>}\n\t\t\t</callout-danger>\n\t\t)\n\t}\n\n\tif (!to) {\n\t\tto = `app1=${app1Name}&app2=${app2Name}`\n\t}\n\tconst pathToDiff = fullPage\n\t\t? `/diff?${to}`\n\t\t: `?${decodeURIComponent(\n\t\t\t\twithParam(new URLSearchParams(), 'preview', `diff&${to}`).toString(),\n\t\t\t)}`\n\n\tif (!children) {\n\t\tchildren = (\n\t\t\t<span>\n\t\t\t\tGo to Diff {fullPage ? '' : 'Preview'} from: <code>{app1Name}</code> to:{' '}\n\t\t\t\t<code>{app2Name}</code>\n\t\t\t</span>\n\t\t)\n\t}\n\n\treturn <Link to={pathToDiff}>{children}</Link>\n}\n\nfunction InlineFile({\n\tfile,\n\ttype = 'playground',\n\tchildren = <code>{file}</code>,\n\t...props\n}: Omit<PropsWithChildren<typeof LaunchEditor>, 'appName'> & {\n\tfile: string\n\ttype?: 'playground' | 'solution' | 'problem'\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tconst app = data[type] || data[data.type]\n\n\tconst info = (\n\t\t<div className=\"launch-editor-button-wrapper flex underline underline-offset-4\">\n\t\t\t{children}{' '}\n\t\t\t<svg height={24} width={24}>\n\t\t\t\t<use href={`${iconsSvg}#Keyboard`} />\n\t\t\t</svg>\n\t\t</div>\n\t)\n\n\treturn ENV.EPICSHOP_DEPLOYED && app ? (\n\t\t<div className=\"inline-block grow\">\n\t\t\t<LaunchEditor appFile={file} appName={app.name} {...props}>\n\t\t\t\t{info}\n\t\t\t</LaunchEditor>\n\t\t</div>\n\t) : app ? (\n\t\t<div className=\"inline-block grow\">\n\t\t\t<LaunchEditor appFile={file} appName={app.name} {...props}>\n\t\t\t\t{info}\n\t\t\t</LaunchEditor>\n\t\t</div>\n\t) : type === 'playground' ? (\n\t\t// playground does not exist yet\n\t\t<SimpleTooltip content=\"You must 'Set to Playground' before opening a file\">\n\t\t\t<div className=\"inline-block grow cursor-not-allowed\">{info}</div>\n\t\t</SimpleTooltip>\n\t) : (\n\t\t<>children</>\n\t)\n}\n\nfunction getPreviewType(\n\tpreview: string | null,\n): 'playground' | 'problem' | 'solution' {\n\tif (preview === 'problem') return 'problem'\n\tif (preview === 'solution') return 'solution'\n\treturn 'playground'\n}\n\nfunction LinkToApp({\n\tto: appTo,\n\tchildren = <code>{appTo.toString()}</code>,\n\t...props\n}: LinkProps) {\n\tconst [searchParams] = useSearchParams()\n\tconst to = `?${withParam(\n\t\tsearchParams,\n\t\t'pathname',\n\t\tappTo.toString(),\n\t).toString()}`\n\tconst data = useLoaderData<typeof loader>()\n\tconst type = getPreviewType(searchParams.get('preview'))\n\tconst requestInfo = useRequestInfo()\n\tconst app = data[type]\n\tconst previewAppUrl =\n\t\tapp?.dev.type === 'script'\n\t\t\t? getBaseUrl({\n\t\t\t\t\tdomain: requestInfo.domain,\n\t\t\t\t\tport: app.dev.portNumber,\n\t\t\t\t})\n\t\t\t: data.playground?.dev.type === 'browser' ||\n\t\t\t\t data.playground?.dev.type === 'export'\n\t\t\t\t? data.playground.dev.pathname\n\t\t\t\t: null\n\tconst { inBrowserBrowserRef } = useStepContext()\n\tconst href = previewAppUrl\n\t\t? previewAppUrl.slice(0, -1) + appTo.toString()\n\t\t: null\n\treturn (\n\t\t<div className=\"inline-flex items-center justify-between gap-1\">\n\t\t\t<Link\n\t\t\t\tto={to}\n\t\t\t\t{...props}\n\t\t\t\tclassName={cn(props.className, {\n\t\t\t\t\t'cursor-not-allowed': ENV.EPICSHOP_DEPLOYED,\n\t\t\t\t})}\n\t\t\t\ttitle={\n\t\t\t\t\tENV.EPICSHOP_DEPLOYED\n\t\t\t\t\t\t? 'Cannot link to app in deployed version'\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tonClick={(event) => {\n\t\t\t\t\tif (ENV.EPICSHOP_DEPLOYED) event.preventDefault()\n\n\t\t\t\t\tprops.onClick?.(event)\n\t\t\t\t\tinBrowserBrowserRef.current?.handleExtrnalNavigation(appTo.toString())\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Link>\n\t\t\t{href ? (\n\t\t\t\t<SimpleTooltip content=\"Open in new tab\">\n\t\t\t\t\t<a\n\t\t\t\t\t\thref={href}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\tclassName={cn('flex aspect-square items-center justify-center', {\n\t\t\t\t\t\t\t'cursor-not-allowed': ENV.EPICSHOP_DEPLOYED,\n\t\t\t\t\t\t})}\n\t\t\t\t\t\ttitle={\n\t\t\t\t\t\t\tENV.EPICSHOP_DEPLOYED\n\t\t\t\t\t\t\t\t? 'Cannot link to app in deployed version'\n\t\t\t\t\t\t\t\t: 'Open in new tab'\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\tif (ENV.EPICSHOP_DEPLOYED) event.preventDefault()\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon name=\"ExternalLink\" />\n\t\t\t\t\t</a>\n\t\t\t\t</SimpleTooltip>\n\t\t\t) : null}\n\t\t</div>\n\t)\n}\n","import * as Popover from '@radix-ui/react-popover'\nimport * as React from 'react'\nimport { Await, Link, useLoaderData } from 'react-router'\nimport { Icon } from '#app/components/icons.tsx'\nimport {\n\tOnboardingBadge,\n\tuseOnboardingIndicator,\n} from '#app/components/onboarding-indicator.tsx'\nimport { SimpleTooltip } from '#app/components/ui/tooltip.tsx'\nimport { LaunchEditor } from '#app/routes/launch-editor.tsx'\nimport { SetAppToPlayground } from '#app/routes/set-playground.tsx'\nimport { type Route as LayoutRoute } from '../+types/_layout.tsx'\n\nfunction TouchedFiles({\n\tdiffFilesPromise,\n}: {\n\tdiffFilesPromise: LayoutRoute.ComponentProps['loaderData']['diffFiles']\n}) {\n\tconst data = useLoaderData<LayoutRoute.ComponentProps['loaderData']>()\n\tconst [showFilesBadge, dismissFilesBadge] =\n\t\tuseOnboardingIndicator('files-popover')\n\n\tconst [open, setOpen] = React.useState(false)\n\tconst contentRef = React.useRef<HTMLDivElement>(null)\n\n\tfunction handleOpenChange(isOpen: boolean) {\n\t\tsetOpen(isOpen)\n\t\t// Mark as complete when opening the popover for the first time\n\t\tif (isOpen) {\n\t\t\tdismissFilesBadge()\n\t\t}\n\t}\n\n\tfunction handleLaunchUpdate() {\n\t\tsetOpen(false)\n\t}\n\n\tconst appName = data.playground?.appName\n\n\treturn (\n\t\t<>\n\t\t\t<Popover.Root open={open} onOpenChange={handleOpenChange}>\n\t\t\t\t<Popover.Trigger asChild>\n\t\t\t\t\t<button\n\t\t\t\t\t\tclassName=\"relative flex h-full items-center gap-1 border-r px-6 py-3 font-mono text-sm uppercase\"\n\t\t\t\t\t\taria-label=\"Relevant Files\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon name=\"Files\" />\n\t\t\t\t\t\t<span className=\"hidden @min-[640px]:inline\">Files</span>\n\t\t\t\t\t\t{showFilesBadge ? (\n\t\t\t\t\t\t\t<OnboardingBadge tooltip=\"Click to see which files to edit!\" />\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</button>\n\t\t\t\t</Popover.Trigger>\n\t\t\t\t<Popover.Portal>\n\t\t\t\t\t<Popover.Content\n\t\t\t\t\t\tref={contentRef}\n\t\t\t\t\t\tclassName=\"slideRightContent lg:slideUpContent invert-theme bg-background text-foreground z-10 rounded px-9 py-8 select-none\"\n\t\t\t\t\t\talign=\"start\"\n\t\t\t\t\t\tsideOffset={5}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"launch-editor-wrapper\">\n\t\t\t\t\t\t\t<strong className=\"inline-block px-2 pb-2 font-semibold uppercase\">\n\t\t\t\t\t\t\t\tRelevant Files\n\t\t\t\t\t\t\t</strong>\n\t\t\t\t\t\t\t<p className=\"text-muted-foreground mb-4 max-w-2xs px-2 text-sm\">\n\t\t\t\t\t\t\t\tThese are the files you'll need to modify for this exercise.\n\t\t\t\t\t\t\t\tClick any file to open it directly in your editor at the right\n\t\t\t\t\t\t\t\tlocation.{' '}\n\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\tto=\"/guide#file-links\"\n\t\t\t\t\t\t\t\t\tclassName=\"text-highlight underline\"\n\t\t\t\t\t\t\t\t\tonClick={() => setOpen(false)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tLearn more →\n\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t{data.problem &&\n\t\t\t\t\t\t\tdata.playground?.appName !== data.problem.name ? (\n\t\t\t\t\t\t\t\t<div className=\"mb-2 rounded p-1 font-mono font-medium\">\n\t\t\t\t\t\t\t\t\t<SetAppToPlayground appName={data.problem.name} />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t<div id=\"files\">\n\t\t\t\t\t\t\t\t<React.Suspense\n\t\t\t\t\t\t\t\t\tfallback={\n\t\t\t\t\t\t\t\t\t\t<SimpleTooltip content=\"Loading diff\">\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex justify-center\">\n\t\t\t\t\t\t\t\t\t\t\t\t<Icon name=\"Refresh\" className=\"h-8 w-8 animate-spin\" />\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t</SimpleTooltip>\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\t<Await\n\t\t\t\t\t\t\t\t\t\tresolve={diffFilesPromise}\n\t\t\t\t\t\t\t\t\t\terrorElement={\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"text-foreground-destructive\">\n\t\t\t\t\t\t\t\t\t\t\t\tSomething went wrong.\n\t\t\t\t\t\t\t\t\t\t\t</div>\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{(diffFiles) => {\n\t\t\t\t\t\t\t\t\t\t\tif (!diffFiles) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<p className=\"text-foreground-destructive\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tUnable to determine diff\n\t\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif (typeof diffFiles === 'string') {\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<p className=\"text-foreground-destructive\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{diffFiles}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif (!diffFiles.length) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn <p>No files changed</p>\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tconst props =\n\t\t\t\t\t\t\t\t\t\t\t\tappName || ENV.EPICSHOP_GITHUB_ROOT\n\t\t\t\t\t\t\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"You must 'Set to Playground' before opening a file\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName: 'not-allowed',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<ul {...props}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{diffFiles.length > 1 && !ENV.EPICSHOP_DEPLOYED ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"border-opacity-50 mb-2 border-b border-b-gray-50 pb-2 font-sans\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<LaunchEditor\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tappFile={diffFiles.map(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(file) => `${file.path},${file.line},1`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tappName=\"playground\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonUpdate={handleLaunchUpdate}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<p>Open All Files</p>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</LaunchEditor>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{diffFiles.map((file) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<li key={file.path} data-state={file.status}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<LaunchEditor\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tappFile={`${file.path},${file.line},1`}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tappName={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tENV.EPICSHOP_DEPLOYED\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? (data.problem?.name ?? 'playground')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: 'playground'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonUpdate={handleLaunchUpdate}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<code>{file.path}</code>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</LaunchEditor>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t\t</ul>\n\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</Await>\n\t\t\t\t\t\t\t\t</React.Suspense>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</Popover.Content>\n\t\t\t\t</Popover.Portal>\n\t\t\t</Popover.Root>\n\t\t</>\n\t)\n}\n\nexport default TouchedFiles\n","import { ElementScrollRestoration } from '@epic-web/restore-scroll'\nimport {\n\tgetAppDisplayName,\n\tgetAppPageRoute,\n\tgetApps,\n\tgetExerciseApp,\n\tgetNextExerciseApp,\n\tgetPrevExerciseApp,\n\tisExerciseStepApp,\n\tisPlaygroundApp,\n\trequireExercise,\n\trequireExerciseApp,\n\ttype App,\n\ttype ExerciseStepApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport { getDiffFiles } from '@epic-web/workshop-utils/diff.server'\nimport { getEpicVideoInfos } from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n} from '@epic-web/workshop-utils/timing.server'\nimport slugify from '@sindresorhus/slugify'\nimport { useRef, useState } from 'react'\nimport {\n\tLink,\n\tOutlet,\n\tdata,\n\tredirect,\n\ttype HeadersFunction,\n} from 'react-router'\nimport { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser.tsx'\nimport { NavChevrons } from '#app/components/nav-chevrons.tsx'\nimport { useRevalidationWS } from '#app/components/revalidation-ws.tsx'\nimport { EditFileOnGitHub } from '#app/routes/launch-editor.tsx'\nimport { ProgressToggle } from '#app/routes/progress.tsx'\nimport { SetAppToPlayground } from '#app/routes/set-playground.tsx'\nimport { getExercisePath } from '#app/utils/misc.tsx'\nimport { getRootMatchLoaderData, useApps } from '#app/utils/root-loader.ts'\nimport { getSeoMetaTags } from '#app/utils/seo.ts'\nimport {\n\tgetSplitPercentFromRequest,\n\tsetSplitPercentCookie,\n\tstartSplitDrag,\n} from '#app/utils/split-layout.ts'\nimport { getStep404Data } from '../__shared/error-boundary.server.ts'\nimport { Exercise404ErrorBoundary } from '../__shared/error-boundary.tsx'\nimport { type Route } from './+types/_layout.tsx'\nimport { StepMdx } from './__shared/step-mdx.tsx'\nimport TouchedFiles from './__shared/touched-files.tsx'\n\nfunction pageTitle(\n\tdata: Awaited<Route.ComponentProps['loaderData']> | undefined,\n\tworkshopTitle?: string,\n) {\n\tconst exerciseNumber =\n\t\tdata?.exerciseStepApp.exerciseNumber.toString().padStart(2, '0') ?? '00'\n\tconst stepNumber =\n\t\tdata?.exerciseStepApp.stepNumber.toString().padStart(2, '0') ?? '00'\n\tconst emoji = (\n\t\t{\n\t\t\tproblem: '💪',\n\t\t\tsolution: '🏁',\n\t\t} as const\n\t)[data?.type ?? 'problem']\n\tconst title = data?.[data.type]?.title ?? 'N/A'\n\treturn {\n\t\temoji,\n\t\tstepNumber,\n\t\ttitle,\n\t\texerciseNumber,\n\t\texerciseTitle: data?.exerciseTitle ?? 'Unknown exercise',\n\t\tworkshopTitle,\n\t\ttype: data?.type ?? 'problem',\n\t}\n}\n\nexport const meta: Route.MetaFunction = ({ loaderData, matches, params }) => {\n\tconst rootData = getRootMatchLoaderData(matches)\n\tif (!loaderData || !rootData) return [{ title: '🦉 | Error' }]\n\tconst { emoji, stepNumber, title, exerciseNumber, exerciseTitle } =\n\t\tpageTitle(loaderData)\n\n\treturn getSeoMetaTags({\n\t\ttitle: `${emoji} | ${stepNumber}. ${title} | ${exerciseNumber}. ${exerciseTitle} | ${rootData.workshopTitle}`,\n\t\tdescription: `${params.type} step for exercise ${exerciseNumber}. ${exerciseTitle}`,\n\t\togTitle: title,\n\t\togDescription: `${exerciseTitle} step ${Number(stepNumber)} ${params.type}`,\n\t\tinstructor: rootData.instructor,\n\t\trequestInfo: rootData.requestInfo,\n\t})\n}\n\nexport async function loader({ request, params }: Route.LoaderArgs) {\n\tconst timings = makeTimings('exerciseStepTypeLayoutLoader')\n\tconst url = new URL(request.url)\n\tconst { type } = params\n\tconst { title: workshopTitle } = getWorkshopConfig()\n\n\tconst cacheOptions = { request, timings }\n\n\tconst [allAppsFull, problemApp, solutionApp] = await Promise.all([\n\t\tgetApps(cacheOptions),\n\t\tgetExerciseApp({ ...params, type: 'problem' }, cacheOptions),\n\t\tgetExerciseApp({ ...params, type: 'solution' }, cacheOptions),\n\t])\n\n\tconst reqUrl = new URL(request.url)\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\tif (\n\t\t(type === 'problem' && !problemApp) ||\n\t\t(type === 'solution' && !solutionApp)\n\t) {\n\t\tconst errorData = await getStep404Data({\n\t\t\texerciseNumber: params.exerciseNumber,\n\t\t})\n\t\tthrow Response.json(errorData, { status: 404 })\n\t}\n\n\tconst exerciseStepApp = await requireExerciseApp(params, cacheOptions)\n\n\tconst playgroundApp = allAppsFull.find(isPlaygroundApp)\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\tconst exerciseId = getStepId(exerciseStepApp)\n\tconst exerciseIndex = allApps.findIndex((step) => step.stepId === exerciseId)\n\n\t// These depend on exerciseStepApp\n\tconst [exercise, nextApp, prevApp] = await Promise.all([\n\t\trequireExercise(exerciseStepApp.exerciseNumber, cacheOptions),\n\t\tgetNextExerciseApp(exerciseStepApp, cacheOptions),\n\t\tgetPrevExerciseApp(exerciseStepApp, cacheOptions),\n\t])\n\n\tconst exerciseApps = allAppsFull\n\t\t.filter(isExerciseStepApp)\n\t\t.filter((app) => app.exerciseNumber === exerciseStepApp.exerciseNumber)\n\tconst isLastStep =\n\t\texerciseApps[exerciseApps.length - 1]?.name === exerciseStepApp.name\n\tconst isFirstStep = exerciseApps[0]?.name === exerciseStepApp.name\n\n\tconst articleId = `workshop-${slugify(workshopTitle)}-${\n\t\texercise.exerciseNumber\n\t}-${exerciseStepApp.stepNumber}-${exerciseStepApp.type}`\n\n\tconst subroute = url.pathname.split(\n\t\t`/exercise/${params.exerciseNumber}/${params.stepNumber}/${params.type}/`,\n\t)[1]\n\n\t// read persisted split percentage from cookie (10-90, default 50)\n\tconst splitPercent = getSplitPercentFromRequest(request, 50)\n\n\treturn data(\n\t\t{\n\t\t\tarticleId,\n\t\t\ttype: params.type as 'problem' | 'solution',\n\t\t\texerciseStepApp,\n\t\t\texerciseTitle: exercise.title,\n\t\t\tepicVideoInfosPromise: getEpicVideoInfos(exerciseStepApp.epicVideoEmbeds),\n\t\t\texerciseIndex,\n\t\t\tallApps,\n\t\t\tsplitPercent,\n\t\t\tprevStepLink: isFirstStep\n\t\t\t\t? {\n\t\t\t\t\t\tto: `/exercise/${exerciseStepApp.exerciseNumber\n\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t.padStart(2, '0')}`,\n\t\t\t\t\t}\n\t\t\t\t: prevApp\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tto: getAppPageRoute(prevApp, {\n\t\t\t\t\t\t\t\tsubroute,\n\t\t\t\t\t\t\t\tsearchParams: url.searchParams,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t}\n\t\t\t\t\t: null,\n\t\t\tnextStepLink: isLastStep\n\t\t\t\t? {\n\t\t\t\t\t\tto: `/exercise/${exerciseStepApp.exerciseNumber\n\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t.padStart(2, '0')}/finished`,\n\t\t\t\t\t}\n\t\t\t\t: nextApp\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tto: getAppPageRoute(nextApp, {\n\t\t\t\t\t\t\t\tsubroute,\n\t\t\t\t\t\t\t\tsearchParams: url.searchParams,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t}\n\t\t\t\t\t: null,\n\t\t\tplayground: playgroundApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'playground',\n\t\t\t\t\t\tappName: playgroundApp.appName,\n\t\t\t\t\t\tname: playgroundApp.name,\n\t\t\t\t\t\tfullPath: playgroundApp.fullPath,\n\t\t\t\t\t\tdev: playgroundApp.dev,\n\t\t\t\t\t\tisUpToDate: playgroundApp.isUpToDate,\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\ttitle: problemApp.title,\n\t\t\t\t\t\tname: problemApp.name,\n\t\t\t\t\t\tfullPath: problemApp.fullPath,\n\t\t\t\t\t\tdev: problemApp.dev,\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\ttitle: solutionApp.title,\n\t\t\t\t\t\tname: solutionApp.name,\n\t\t\t\t\t\tfullPath: solutionApp.fullPath,\n\t\t\t\t\t\tdev: solutionApp.dev,\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tdiffFiles:\n\t\t\t\tproblemApp && solutionApp\n\t\t\t\t\t? getDiffFiles(problemApp, solutionApp, {\n\t\t\t\t\t\t\t...cacheOptions,\n\t\t\t\t\t\t\tforceFresh: url.searchParams.get('forceFresh') === 'diff',\n\t\t\t\t\t\t}).catch((e) => {\n\t\t\t\t\t\t\tconsole.error(e)\n\t\t\t\t\t\t\treturn 'There was a problem generating the diff (check the terminal output)'\n\t\t\t\t\t\t})\n\t\t\t\t\t: 'No diff available',\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\nexport default function ExercisePartRoute({\n\tloaderData: data,\n}: Route.ComponentProps) {\n\tconst apps = useApps()\n\tconst inBrowserBrowserRef = useRef<InBrowserBrowserRef>(null)\n\tconst containerRef = useRef<HTMLDivElement>(null)\n\tconst leftPaneRef = useRef<HTMLDivElement>(null)\n\tconst [splitPercent, setSplitPercent] = useState<number>(data.splitPercent)\n\n\tconst titleBits = pageTitle(data)\n\n\tconst playgroundBasePath = apps.find(\n\t\t(app) => app.name === data.playground?.appName,\n\t)?.fullPath\n\n\tuseRevalidationWS({\n\t\twatchPaths: [\n\t\t\t`${data.exerciseStepApp.relativePath}/README.mdx`,\n\t\t\tplaygroundBasePath,\n\t\t].filter((path): path is string => Boolean(path)),\n\t})\n\n\tconst showPlaygroundIndicator = data.problem\n\t\t? data.playground?.appName !== data.problem.name\n\t\t: false\n\n\treturn (\n\t\t<div className=\"flex max-w-full grow flex-col\">\n\t\t\t<main\n\t\t\t\tref={containerRef}\n\t\t\t\tclassName=\"flex grow flex-col overflow-y-auto sm:h-full sm:min-h-[800px] md:min-h-[unset] lg:flex-row lg:overflow-y-hidden\"\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"relative flex min-w-0 flex-none basis-auto flex-col sm:col-span-1 sm:row-span-1 lg:h-full lg:basis-(--split-pct)\"\n\t\t\t\t\tstyle={{ ['--split-pct' as any]: `${splitPercent}%` }}\n\t\t\t\t\tref={leftPaneRef}\n\t\t\t\t>\n\t\t\t\t\t<h1 className=\"@container h-14 border-b pr-5 pl-10 text-sm leading-tight font-medium\">\n\t\t\t\t\t\t<div className=\"flex h-14 items-center justify-between gap-x-2 py-2 whitespace-nowrap\">\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-start gap-x-2 uppercase\">\n\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\tto={getExercisePath(data.exerciseStepApp.exerciseNumber)}\n\t\t\t\t\t\t\t\t\tclassName=\"hover:underline\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span>{titleBits.exerciseNumber}.</span>\n\t\t\t\t\t\t\t\t\t<span className=\"hidden @min-[500px]:inline\">\n\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t{titleBits.exerciseTitle}\n\t\t\t\t\t\t\t\t\t</span>\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<Link to=\".\" className=\"hover:underline\">\n\t\t\t\t\t\t\t\t\t<span>{titleBits.stepNumber}.</span>\n\t\t\t\t\t\t\t\t\t<span className=\"hidden @min-[300px]:inline\">\n\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t{titleBits.title}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span> ({titleBits.emoji}</span>\n\t\t\t\t\t\t\t\t\t<span className=\"hidden @min-[400px]:inline\">\n\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t{titleBits.type}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span>)</span>\n\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{data.problem &&\n\t\t\t\t\t\t\t(data.playground?.appName !== data.problem.name ||\n\t\t\t\t\t\t\t\t!data.playground?.isUpToDate) ? (\n\t\t\t\t\t\t\t\t<SetAppToPlayground\n\t\t\t\t\t\t\t\t\tappName={data.problem.name}\n\t\t\t\t\t\t\t\t\tisOutdated={data.playground?.isUpToDate === false}\n\t\t\t\t\t\t\t\t\thideTextOnNarrow\n\t\t\t\t\t\t\t\t\tshowOnboardingIndicator={showPlaygroundIndicator}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : null}\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\tid={data.articleId}\n\t\t\t\t\t\tkey={data.articleId}\n\t\t\t\t\t\tclassName=\"shadow-on-scrollbox scrollbar-thin scrollbar-thumb-scrollbar flex w-full max-w-none scroll-pt-6 flex-col justify-between space-y-6 p-2 sm:p-10 sm:pt-8 lg:h-full lg:flex-1 lg:overflow-y-auto\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{data.exerciseStepApp.instructionsCode ? (\n\t\t\t\t\t\t\t<StepMdx inBrowserBrowserRef={inBrowserBrowserRef} />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"flex h-full items-center justify-center text-lg\">\n\t\t\t\t\t\t\t\t<p>No instructions yet...</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<div className=\"mt-auto flex justify-between\">\n\t\t\t\t\t\t\t{data.prevStepLink ? (\n\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\tto={data.prevStepLink.to}\n\t\t\t\t\t\t\t\t\taria-label=\"Previous Step\"\n\t\t\t\t\t\t\t\t\tdata-keyboard-action=\"g+p\"\n\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span aria-hidden>←</span>\n\t\t\t\t\t\t\t\t\t<span className=\"hidden xl:inline\"> Previous</span>\n\t\t\t\t\t\t\t\t</Link>\n\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)}\n\t\t\t\t\t\t\t{data.nextStepLink ? (\n\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\tto={data.nextStepLink.to}\n\t\t\t\t\t\t\t\t\taria-label=\"Next Step\"\n\t\t\t\t\t\t\t\t\tdata-keyboard-action=\"g+n\"\n\t\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span className=\"hidden xl:inline\">Next </span>\n\t\t\t\t\t\t\t\t\t<span aria-hidden>→</span>\n\t\t\t\t\t\t\t\t</Link>\n\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)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</article>\n\t\t\t\t\t<ElementScrollRestoration\n\t\t\t\t\t\telementQuery={`#${data.articleId}`}\n\t\t\t\t\t\tkey={`scroll-${data.articleId}`}\n\t\t\t\t\t/>\n\t\t\t\t\t{data.type === 'solution' ? (\n\t\t\t\t\t\t<ProgressToggle\n\t\t\t\t\t\t\ttype=\"step\"\n\t\t\t\t\t\t\texerciseNumber={data.exerciseStepApp.exerciseNumber}\n\t\t\t\t\t\t\tstepNumber={data.exerciseStepApp.stepNumber}\n\t\t\t\t\t\t\tclassName=\"h-14 border-t px-6\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<div className=\"@container flex h-16 justify-between border-t border-b-4 lg:border-b-0\">\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div className=\"h-full\">\n\t\t\t\t\t\t\t\t<TouchedFiles diffFilesPromise={data.diffFiles} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<EditFileOnGitHub\n\t\t\t\t\t\t\tappName={data.exerciseStepApp.name}\n\t\t\t\t\t\t\trelativePath={`${data.exerciseStepApp.relativePath}/README.mdx`}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<NavChevrons\n\t\t\t\t\t\t\tprev={\n\t\t\t\t\t\t\t\tdata.prevStepLink\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\tto: data.prevStepLink.to,\n\t\t\t\t\t\t\t\t\t\t\t'aria-label': 'Previous Step',\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnext={\n\t\t\t\t\t\t\t\tdata.nextStepLink\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\tto: data.nextStepLink.to,\n\t\t\t\t\t\t\t\t\t\t\t'aria-label': 'Next Step',\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\trole=\"separator\"\n\t\t\t\t\taria-orientation=\"vertical\"\n\t\t\t\t\ttitle=\"Drag to resize\"\n\t\t\t\t\tclassName=\"bg-border hover:bg-accent hidden w-1 cursor-col-resize lg:block\"\n\t\t\t\t\tonMouseDown={(event) =>\n\t\t\t\t\t\tstartSplitDrag({\n\t\t\t\t\t\t\tcontainer: containerRef.current,\n\t\t\t\t\t\t\tinitialClientX: event.clientX,\n\t\t\t\t\t\t\tsetSplitPercent,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\tonDoubleClick={() => {\n\t\t\t\t\t\tsetSplitPercent(setSplitPercentCookie(50))\n\t\t\t\t\t}}\n\t\t\t\t\tonTouchStart={(event) => {\n\t\t\t\t\t\tconst firstTouch = event.touches?.[0]\n\t\t\t\t\t\tif (!firstTouch) return\n\t\t\t\t\t\tstartSplitDrag({\n\t\t\t\t\t\t\tcontainer: containerRef.current,\n\t\t\t\t\t\t\tinitialClientX: firstTouch.clientX,\n\t\t\t\t\t\t\tsetSplitPercent,\n\t\t\t\t\t\t})\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<div className=\"flex min-h-[50vh] min-w-0 flex-none lg:min-h-0 lg:flex-1\">\n\t\t\t\t\t<Outlet context={{ inBrowserBrowserRef }} />\n\t\t\t\t</div>\n\t\t\t</main>\n\t\t</div>\n\t)\n}\n\nexport function ErrorBoundary() {\n\treturn (\n\t\t<GeneralErrorBoundary\n\t\t\tclassName=\"container flex items-center justify-center\"\n\t\t\tstatusHandlers={{\n\t\t\t\t404: Exercise404ErrorBoundary,\n\t\t\t}}\n\t\t/>\n\t)\n}\n"],"names":["StepContext","React.createContext","useStepContext","context","React.useContext","StepContextProvider","children","inBrowserBrowserRef","stepMdxComponents","DiffLink","PrevDiffLink","NextDiffLink","InlineFile","LinkToApp","StepMdx","data","useLoaderData","jsx","EpicVideoInfoProvider","Mdx","withParam","searchParams","key","value","newSearchParams","app","fullPage","app1","app2","to","getAppName","input","stepIndex","name","stepName","params","app1Name","app2Name","jsxs","pathToDiff","Link","file","type","props","info","iconsSvg","LaunchEditor","SimpleTooltip","getPreviewType","preview","appTo","useSearchParams","requestInfo","useRequestInfo","previewAppUrl","getBaseUrl","href","cn","event","Icon","TouchedFiles","diffFilesPromise","showFilesBadge","dismissFilesBadge","useOnboardingIndicator","open","setOpen","React.useState","contentRef","React.useRef","handleOpenChange","isOpen","handleLaunchUpdate","appName","Popover.Root","Popover.Trigger","OnboardingBadge","Popover.Portal","Popover.Content","SetAppToPlayground","React.Suspense","Await","diffFiles","pageTitle","workshopTitle","exerciseNumber","exerciseStepApp","toString","padStart","stepNumber","emoji","problem","solution","title","exerciseTitle","meta","loaderData","matches","rootData","getRootMatchLoaderData","getSeoMetaTags","description","ogTitle","ogDescription","Number","instructor","_layout","_UNSAFE_withComponentProps","apps","useApps","useRef","containerRef","leftPaneRef","splitPercent","setSplitPercent","useState","titleBits","playgroundBasePath","find","playground","fullPath","useRevalidationWS","watchPaths","relativePath","filter","path","Boolean","showPlaygroundIndicator","className","ref","style","getExercisePath","isUpToDate","isOutdated","hideTextOnNarrow","showOnboardingIndicator","id","articleId","instructionsCode","prevStepLink","prefetch","nextStepLink","ElementScrollRestoration","elementQuery","ProgressToggle","EditFileOnGitHub","NavChevrons","prev","next","role","onMouseDown","startSplitDrag","container","current","initialClientX","clientX","onDoubleClick","setSplitPercentCookie","onTouchStart","firstTouch","touches","Outlet","ErrorBoundary","_UNSAFE_withErrorBoundaryProps","GeneralErrorBoundary","statusHandlers","Exercise404ErrorBoundary"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{w as f,L as t,F as j}from"./chunk-EPOLDU6W-BCLmut3y.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{B as N}from"./button-Cd-ekki5.js";import{I as n,c as w}from"./misc-W4055b-0.js";import{u as l,O as d}from"./onboarding-indicator-B-XR90_G.js";import{S as c}from"./tooltip-Tlsyx2YO.js";import{u as v,a as b,b as k}from"./user-BsPobzjB.js";import{u}from"./workshop-config-Zfc8zU0x.js";import"./index-CqIc3cxq.js";import"./root-loader-BOzEMapJ.js";import"./index-vDCSPjrM.js";const F={getSitemapEntries:()=>null};function y(){const{product:{host:a}}=u();return`https://${a}/discord`}const S=f(function(){const s=v(),o=u(),r=b(),m=y(),i=k(),[h,x]=l("account-guide"),[p,g]=l("account-preferences");return e.jsxs("main",{className:"container flex h-full w-full max-w-3xl grow flex-col items-center justify-center gap-4",children:[e.jsxs("div",{className:"flex flex-col items-center",children:[s.imageUrlLarge?e.jsx("img",{className:"h-36 w-36 rounded-full",alt:r?.displayName??s.name??s.email,src:s.imageUrlLarge}):e.jsx("div",{className:"bg-muted flex h-36 w-36 items-center justify-center rounded-full",children:e.jsx(n,{name:"User",size:"xl"})}),e.jsx("p",{className:"text-muted-foreground mt-2 text-center text-xs",children:r?e.jsxs(e.Fragment,{children:["Photo from"," ",e.jsx("a",{href:"https://discord.com/channels/@me",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"Discord"})]}):e.jsxs(e.Fragment,{children:["Photo from"," ",e.jsx("a",{href:"https://gravatar.com",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"Gravatar"})," ","or connect Discord below"]})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h1",{className:"mb-1 text-2xl",children:"Your Account"}),o.product.slug?e.jsx(c,{content:i?"You have access to this workshop":"You do not have full access to this workshop",children:e.jsx(n,{name:i?"Success":"Error",size:"lg",className:w(i?"bg-success text-success-foreground":"bg-warning text-warning-foreground","rounded-full p-1"),tabIndex:0})}):null]}),!i&&o.product.slug?e.jsx("div",{className:"prose",children:e.jsxs("callout-warning",{className:"notification",children:["Please"," ",e.jsx("a",{href:`https://${o.product.host}/workshops/${o.product.slug}`,className:"underline",children:"upgrade"})," ","your account to get full access to this workshop."]})}):null,e.jsx("p",{className:"text-muted-foreground text-center",children:s.name?`Hi ${r?.displayName??s.name}, your device is logged in with ${s.email}.`:`Your device is logged in with ${s.email}.`}),r?e.jsx(e.Fragment,{children:e.jsxs("p",{className:"text-muted-foreground text-center",children:["And you are connected to discord as"," ",e.jsx("a",{href:`https://discord.com/users/${r.id}`,target:"_blank",rel:"noopener noreferrer",className:"underline",children:r.displayName}),"."]})}):e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(t,{to:m,className:"inline-flex items-center gap-2 underline",children:[e.jsx(n,{name:"Discord",size:"lg"}),"Connect Discord"]}),e.jsx(c,{content:"This will give you access to the exclusive Discord channels for Epic Web",children:e.jsx(n,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(j,{method:"post",children:e.jsx(N,{varient:"mono",name:"intent",value:"logout",children:"Log device out"})}),e.jsx(c,{content:e.jsxs("div",{children:["Note: it is your ",e.jsx("i",{className:"italic",children:"device"})," that's logged in, not your browser.",e.jsx("br",{}),"So all browsers on this device will be logged in with the same account on this device."]}),children:e.jsx(n,{name:"Question",tabIndex:0})})]}),e.jsx("hr",{className:"w-full"}),e.jsxs("ul",{className:"flex list-inside list-disc flex-col gap-2 self-start",children:[e.jsx("li",{children:e.jsxs(t,{to:`https://${o.product.host}/profile`,className:"inline-flex gap-1 underline",children:[e.jsx("span",{children:"Manage your account"}),e.jsx(n,{name:"ExternalLink"})]})}),e.jsx("li",{children:e.jsxs(t,{to:"/preferences",className:"relative underline",onClick:g,children:[p?e.jsx(d,{tooltip:"Customize your workshop experience!",size:"sm",className:"-top-1 -left-4"}):null,"Manage your preferences"]})}),e.jsx("li",{children:e.jsxs(t,{to:"/guide",className:"relative underline",onClick:x,children:[h?e.jsx(d,{tooltip:"Learn how to use the workshop app!",size:"sm",className:"-top-1 -left-4"}):null,"Workshop app guide"]})}),e.jsx("li",{children:e.jsx(t,{to:"/support",className:"underline",children:"Get support"})})]})]})});export{S as default,F as handle};
2
- //# sourceMappingURL=account-C96cpeZR.js.map
1
+ import{w as f,L as t,F as j}from"./chunk-EPOLDU6W-BCLmut3y.js";import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{B as N}from"./button-Cd-ekki5.js";import{I as n,c as w}from"./misc-W4055b-0.js";import{u as l,O as d}from"./onboarding-indicator-BkeHYs2C.js";import{S as c}from"./tooltip-Tlsyx2YO.js";import{u as v,a as b,b as k}from"./user-CYXKquT7.js";import{u}from"./workshop-config-BMWaKPZT.js";import"./index-CqIc3cxq.js";import"./root-loader-BmUqzUDN.js";import"./index-vDCSPjrM.js";const F={getSitemapEntries:()=>null};function y(){const{product:{host:a}}=u();return`https://${a}/discord`}const S=f(function(){const s=v(),o=u(),r=b(),m=y(),i=k(),[h,x]=l("account-guide"),[p,g]=l("account-preferences");return e.jsxs("main",{className:"container flex h-full w-full max-w-3xl grow flex-col items-center justify-center gap-4",children:[e.jsxs("div",{className:"flex flex-col items-center",children:[s.imageUrlLarge?e.jsx("img",{className:"h-36 w-36 rounded-full",alt:r?.displayName??s.name??s.email,src:s.imageUrlLarge}):e.jsx("div",{className:"bg-muted flex h-36 w-36 items-center justify-center rounded-full",children:e.jsx(n,{name:"User",size:"xl"})}),e.jsx("p",{className:"text-muted-foreground mt-2 text-center text-xs",children:r?e.jsxs(e.Fragment,{children:["Photo from"," ",e.jsx("a",{href:"https://discord.com/channels/@me",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"Discord"})]}):e.jsxs(e.Fragment,{children:["Photo from"," ",e.jsx("a",{href:"https://gravatar.com",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"Gravatar"})," ","or connect Discord below"]})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h1",{className:"mb-1 text-2xl",children:"Your Account"}),o.product.slug?e.jsx(c,{content:i?"You have access to this workshop":"You do not have full access to this workshop",children:e.jsx(n,{name:i?"Success":"Error",size:"lg",className:w(i?"bg-success text-success-foreground":"bg-warning text-warning-foreground","rounded-full p-1"),tabIndex:0})}):null]}),!i&&o.product.slug?e.jsx("div",{className:"prose",children:e.jsxs("callout-warning",{className:"notification",children:["Please"," ",e.jsx("a",{href:`https://${o.product.host}/workshops/${o.product.slug}`,className:"underline",children:"upgrade"})," ","your account to get full access to this workshop."]})}):null,e.jsx("p",{className:"text-muted-foreground text-center",children:s.name?`Hi ${r?.displayName??s.name}, your device is logged in with ${s.email}.`:`Your device is logged in with ${s.email}.`}),r?e.jsx(e.Fragment,{children:e.jsxs("p",{className:"text-muted-foreground text-center",children:["And you are connected to discord as"," ",e.jsx("a",{href:`https://discord.com/users/${r.id}`,target:"_blank",rel:"noopener noreferrer",className:"underline",children:r.displayName}),"."]})}):e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(t,{to:m,className:"inline-flex items-center gap-2 underline",children:[e.jsx(n,{name:"Discord",size:"lg"}),"Connect Discord"]}),e.jsx(c,{content:"This will give you access to the exclusive Discord channels for Epic Web",children:e.jsx(n,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(j,{method:"post",children:e.jsx(N,{varient:"mono",name:"intent",value:"logout",children:"Log device out"})}),e.jsx(c,{content:e.jsxs("div",{children:["Note: it is your ",e.jsx("i",{className:"italic",children:"device"})," that's logged in, not your browser.",e.jsx("br",{}),"So all browsers on this device will be logged in with the same account on this device."]}),children:e.jsx(n,{name:"Question",tabIndex:0})})]}),e.jsx("hr",{className:"w-full"}),e.jsxs("ul",{className:"flex list-inside list-disc flex-col gap-2 self-start",children:[e.jsx("li",{children:e.jsxs(t,{to:`https://${o.product.host}/profile`,className:"inline-flex gap-1 underline",children:[e.jsx("span",{children:"Manage your account"}),e.jsx(n,{name:"ExternalLink"})]})}),e.jsx("li",{children:e.jsxs(t,{to:"/preferences",className:"relative underline",onClick:g,children:[p?e.jsx(d,{tooltip:"Customize your workshop experience!",size:"sm",className:"-top-1 -left-4"}):null,"Manage your preferences"]})}),e.jsx("li",{children:e.jsxs(t,{to:"/guide",className:"relative underline",onClick:x,children:[h?e.jsx(d,{tooltip:"Learn how to use the workshop app!",size:"sm",className:"-top-1 -left-4"}):null,"Workshop app guide"]})}),e.jsx("li",{children:e.jsx(t,{to:"/support",className:"underline",children:"Get support"})})]})]})});export{S as default,F as handle};
2
+ //# sourceMappingURL=account-BKXMYhfO.js.map