@epic-web/workshop-app 4.26.2 → 4.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/build/client/assets/{_exerciseNumber-B_1LTOMl.js → _exerciseNumber-DeMmiDU5.js} +2 -2
  2. package/build/client/assets/{_exerciseNumber-B_1LTOMl.js.map → _exerciseNumber-DeMmiDU5.js.map} +1 -1
  3. package/build/client/assets/{_exerciseNumber_.finished-DHl9ou1s.js → _exerciseNumber_.finished-DM5HZX6r.js} +2 -2
  4. package/build/client/assets/{_exerciseNumber_.finished-DHl9ou1s.js.map → _exerciseNumber_.finished-DM5HZX6r.js.map} +1 -1
  5. package/build/client/assets/{_layout-TpI4uc69.js → _layout-5idP3Bqx.js} +2 -2
  6. package/build/client/assets/{_layout-TpI4uc69.js.map → _layout-5idP3Bqx.js.map} +1 -1
  7. package/build/client/assets/{_layout-CksyTzND.js → _layout-DkGEbcMk.js} +2 -2
  8. package/build/client/assets/{_layout-CksyTzND.js.map → _layout-DkGEbcMk.js.map} +1 -1
  9. package/build/client/assets/{account-DWhUP9x5.js → account-D1DCJCnR.js} +2 -2
  10. package/build/client/assets/{account-DWhUP9x5.js.map → account-D1DCJCnR.js.map} +1 -1
  11. package/build/client/assets/{diff-CKxYA_sC.js → diff-CU8At1c4.js} +2 -2
  12. package/build/client/assets/{diff-CKxYA_sC.js.map → diff-CU8At1c4.js.map} +1 -1
  13. package/build/client/assets/diff-hoOood-9.js +2 -0
  14. package/build/client/assets/diff-hoOood-9.js.map +1 -0
  15. package/build/client/assets/discord-BBRM_H3g.js +2 -0
  16. package/build/client/assets/discord-BBRM_H3g.js.map +1 -0
  17. package/build/client/assets/{discord-OBIm1mMI.js → discord-CgdmSzxV.js} +2 -2
  18. package/build/client/assets/{discord-OBIm1mMI.js.map → discord-CgdmSzxV.js.map} +1 -1
  19. package/build/client/assets/{epic-video-CzGRLoYH.js → epic-video-BFcdejfC.js} +2 -2
  20. package/build/client/assets/{epic-video-CzGRLoYH.js.map → epic-video-BFcdejfC.js.map} +1 -1
  21. package/build/client/assets/{finished-Bb9g_iPq.js → finished-C_v7hO19.js} +2 -2
  22. package/build/client/assets/{finished-Bb9g_iPq.js.map → finished-C_v7hO19.js.map} +1 -1
  23. package/build/client/assets/{index-C-VazAW9.js → index-BHeB-0xq.js} +2 -2
  24. package/build/client/assets/{index-C-VazAW9.js.map → index-BHeB-0xq.js.map} +1 -1
  25. package/build/client/assets/{index-BVys5A_i.js → index-CsPok4Mn.js} +2 -2
  26. package/build/client/assets/{index-BVys5A_i.js.map → index-CsPok4Mn.js.map} +1 -1
  27. package/build/client/assets/login-Ca9EDpZj.js +2 -0
  28. package/build/client/assets/{login-L4mUv67t.js.map → login-Ca9EDpZj.js.map} +1 -1
  29. package/build/client/assets/manifest-93b38e47.js +1 -0
  30. package/build/client/assets/{mdx-CGcvotZI.js → mdx-DvqHp8UI.js} +2 -2
  31. package/build/client/assets/{mdx-CGcvotZI.js.map → mdx-DvqHp8UI.js.map} +1 -1
  32. package/build/client/assets/{onboarding-Ci4QCevA.js → onboarding-Dc2TmI9y.js} +2 -2
  33. package/build/client/assets/{onboarding-Ci4QCevA.js.map → onboarding-Dc2TmI9y.js.map} +1 -1
  34. package/build/client/assets/test-Cy-fo6gv.js +2 -0
  35. package/build/client/assets/{test-DL_jD5Wc.js.map → test-Cy-fo6gv.js.map} +1 -1
  36. package/build/client/assets/tests-DmimqC1q.js +4 -0
  37. package/build/client/assets/{tests-BHsX0R-r.js.map → tests-DmimqC1q.js.map} +1 -1
  38. package/build/client/assets/user-DvujSs-t.js +2 -0
  39. package/build/client/assets/{user-D6tTg1yS.js.map → user-DvujSs-t.js.map} +1 -1
  40. package/build/server/index.js +35 -13
  41. package/build/server/index.js.map +1 -1
  42. package/package.json +3 -3
  43. package/build/client/assets/diff-B5EME8RQ.js +0 -2
  44. package/build/client/assets/diff-B5EME8RQ.js.map +0 -1
  45. package/build/client/assets/discord-pvbkb0tl.js +0 -2
  46. package/build/client/assets/discord-pvbkb0tl.js.map +0 -1
  47. package/build/client/assets/login-L4mUv67t.js +0 -2
  48. package/build/client/assets/manifest-c0629f94.js +0 -1
  49. package/build/client/assets/test-DL_jD5Wc.js +0 -2
  50. package/build/client/assets/tests-BHsX0R-r.js +0 -4
  51. package/build/client/assets/user-D6tTg1yS.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"_layout-CksyTzND.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","../../../../../node_modules/@radix-ui/react-dialog/dist/index.mjs","../../../app/components/ui/dialog.tsx","../../../app/routes/_app+/_layout.tsx"],"sourcesContent":["import { invariant } from '../../utils/errors.mjs';\nimport { setTarget } from '../../render/utils/setters.mjs';\nimport { animateVisualElement } from '../interfaces/visual-element.mjs';\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","import { animationControls } from './animation-controls.mjs';\nimport { useConstant } from '../../utils/use-constant.mjs';\nimport { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';\n\n/**\n * Creates `AnimationControls`, which can be used to manually start, stop\n * and sequence animations on one or more components.\n *\n * The returned `AnimationControls` 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","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","\"use client\";\n\n// packages/react/dialog/src/Dialog.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { createContext, createContextScope } from \"@radix-ui/react-context\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { DismissableLayer } from \"@radix-ui/react-dismissable-layer\";\nimport { FocusScope } from \"@radix-ui/react-focus-scope\";\nimport { Portal as PortalPrimitive } from \"@radix-ui/react-portal\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useFocusGuards } from \"@radix-ui/react-focus-guards\";\nimport { RemoveScroll } from \"react-remove-scroll\";\nimport { hideOthers } from \"aria-hidden\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { Fragment, jsx, jsxs } from \"react/jsx-runtime\";\nvar DIALOG_NAME = \"Dialog\";\nvar [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);\nvar [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);\nvar Dialog = (props) => {\n const {\n __scopeDialog,\n children,\n open: openProp,\n defaultOpen,\n onOpenChange,\n modal = true\n } = props;\n const triggerRef = React.useRef(null);\n const contentRef = React.useRef(null);\n const [open = false, setOpen] = useControllableState({\n prop: openProp,\n defaultProp: defaultOpen,\n onChange: onOpenChange\n });\n return /* @__PURE__ */ jsx(\n DialogProvider,\n {\n scope: __scopeDialog,\n triggerRef,\n contentRef,\n contentId: useId(),\n titleId: useId(),\n descriptionId: useId(),\n open,\n onOpenChange: setOpen,\n onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),\n modal,\n children\n }\n );\n};\nDialog.displayName = DIALOG_NAME;\nvar TRIGGER_NAME = \"DialogTrigger\";\nvar DialogTrigger = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...triggerProps } = props;\n const context = useDialogContext(TRIGGER_NAME, __scopeDialog);\n const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef);\n return /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n \"aria-haspopup\": \"dialog\",\n \"aria-expanded\": context.open,\n \"aria-controls\": context.contentId,\n \"data-state\": getState(context.open),\n ...triggerProps,\n ref: composedTriggerRef,\n onClick: composeEventHandlers(props.onClick, context.onOpenToggle)\n }\n );\n }\n);\nDialogTrigger.displayName = TRIGGER_NAME;\nvar PORTAL_NAME = \"DialogPortal\";\nvar [PortalProvider, usePortalContext] = createDialogContext(PORTAL_NAME, {\n forceMount: void 0\n});\nvar DialogPortal = (props) => {\n const { __scopeDialog, forceMount, children, container } = props;\n const context = useDialogContext(PORTAL_NAME, __scopeDialog);\n return /* @__PURE__ */ jsx(PortalProvider, { scope: __scopeDialog, forceMount, children: React.Children.map(children, (child) => /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(PortalPrimitive, { asChild: true, container, children: child }) })) });\n};\nDialogPortal.displayName = PORTAL_NAME;\nvar OVERLAY_NAME = \"DialogOverlay\";\nvar DialogOverlay = React.forwardRef(\n (props, forwardedRef) => {\n const portalContext = usePortalContext(OVERLAY_NAME, props.__scopeDialog);\n const { forceMount = portalContext.forceMount, ...overlayProps } = props;\n const context = useDialogContext(OVERLAY_NAME, props.__scopeDialog);\n return context.modal ? /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(DialogOverlayImpl, { ...overlayProps, ref: forwardedRef }) }) : null;\n }\n);\nDialogOverlay.displayName = OVERLAY_NAME;\nvar DialogOverlayImpl = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...overlayProps } = props;\n const context = useDialogContext(OVERLAY_NAME, __scopeDialog);\n return (\n // Make sure `Content` is scrollable even when it doesn't live inside `RemoveScroll`\n // ie. when `Overlay` and `Content` are siblings\n /* @__PURE__ */ jsx(RemoveScroll, { as: Slot, allowPinchZoom: true, shards: [context.contentRef], children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n \"data-state\": getState(context.open),\n ...overlayProps,\n ref: forwardedRef,\n style: { pointerEvents: \"auto\", ...overlayProps.style }\n }\n ) })\n );\n }\n);\nvar CONTENT_NAME = \"DialogContent\";\nvar DialogContent = React.forwardRef(\n (props, forwardedRef) => {\n const portalContext = usePortalContext(CONTENT_NAME, props.__scopeDialog);\n const { forceMount = portalContext.forceMount, ...contentProps } = props;\n const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: context.modal ? /* @__PURE__ */ jsx(DialogContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(DialogContentNonModal, { ...contentProps, ref: forwardedRef }) });\n }\n);\nDialogContent.displayName = CONTENT_NAME;\nvar DialogContentModal = React.forwardRef(\n (props, forwardedRef) => {\n const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n const contentRef = React.useRef(null);\n const composedRefs = useComposedRefs(forwardedRef, context.contentRef, contentRef);\n React.useEffect(() => {\n const content = contentRef.current;\n if (content) return hideOthers(content);\n }, []);\n return /* @__PURE__ */ jsx(\n DialogContentImpl,\n {\n ...props,\n ref: composedRefs,\n trapFocus: context.open,\n disableOutsidePointerEvents: true,\n onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {\n event.preventDefault();\n context.triggerRef.current?.focus();\n }),\n onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event) => {\n const originalEvent = event.detail.originalEvent;\n const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;\n const isRightClick = originalEvent.button === 2 || ctrlLeftClick;\n if (isRightClick) event.preventDefault();\n }),\n onFocusOutside: composeEventHandlers(\n props.onFocusOutside,\n (event) => event.preventDefault()\n )\n }\n );\n }\n);\nvar DialogContentNonModal = React.forwardRef(\n (props, forwardedRef) => {\n const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n const hasInteractedOutsideRef = React.useRef(false);\n const hasPointerDownOutsideRef = React.useRef(false);\n return /* @__PURE__ */ jsx(\n DialogContentImpl,\n {\n ...props,\n ref: forwardedRef,\n trapFocus: false,\n disableOutsidePointerEvents: false,\n onCloseAutoFocus: (event) => {\n props.onCloseAutoFocus?.(event);\n if (!event.defaultPrevented) {\n if (!hasInteractedOutsideRef.current) context.triggerRef.current?.focus();\n event.preventDefault();\n }\n hasInteractedOutsideRef.current = false;\n hasPointerDownOutsideRef.current = false;\n },\n onInteractOutside: (event) => {\n props.onInteractOutside?.(event);\n if (!event.defaultPrevented) {\n hasInteractedOutsideRef.current = true;\n if (event.detail.originalEvent.type === \"pointerdown\") {\n hasPointerDownOutsideRef.current = true;\n }\n }\n const target = event.target;\n const targetIsTrigger = context.triggerRef.current?.contains(target);\n if (targetIsTrigger) event.preventDefault();\n if (event.detail.originalEvent.type === \"focusin\" && hasPointerDownOutsideRef.current) {\n event.preventDefault();\n }\n }\n }\n );\n }\n);\nvar DialogContentImpl = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, trapFocus, onOpenAutoFocus, onCloseAutoFocus, ...contentProps } = props;\n const context = useDialogContext(CONTENT_NAME, __scopeDialog);\n const contentRef = React.useRef(null);\n const composedRefs = useComposedRefs(forwardedRef, contentRef);\n useFocusGuards();\n return /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(\n FocusScope,\n {\n asChild: true,\n loop: true,\n trapped: trapFocus,\n onMountAutoFocus: onOpenAutoFocus,\n onUnmountAutoFocus: onCloseAutoFocus,\n children: /* @__PURE__ */ jsx(\n DismissableLayer,\n {\n role: \"dialog\",\n id: context.contentId,\n \"aria-describedby\": context.descriptionId,\n \"aria-labelledby\": context.titleId,\n \"data-state\": getState(context.open),\n ...contentProps,\n ref: composedRefs,\n onDismiss: () => context.onOpenChange(false)\n }\n )\n }\n ),\n /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(TitleWarning, { titleId: context.titleId }),\n /* @__PURE__ */ jsx(DescriptionWarning, { contentRef, descriptionId: context.descriptionId })\n ] })\n ] });\n }\n);\nvar TITLE_NAME = \"DialogTitle\";\nvar DialogTitle = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...titleProps } = props;\n const context = useDialogContext(TITLE_NAME, __scopeDialog);\n return /* @__PURE__ */ jsx(Primitive.h2, { id: context.titleId, ...titleProps, ref: forwardedRef });\n }\n);\nDialogTitle.displayName = TITLE_NAME;\nvar DESCRIPTION_NAME = \"DialogDescription\";\nvar DialogDescription = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...descriptionProps } = props;\n const context = useDialogContext(DESCRIPTION_NAME, __scopeDialog);\n return /* @__PURE__ */ jsx(Primitive.p, { id: context.descriptionId, ...descriptionProps, ref: forwardedRef });\n }\n);\nDialogDescription.displayName = DESCRIPTION_NAME;\nvar CLOSE_NAME = \"DialogClose\";\nvar DialogClose = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...closeProps } = props;\n const context = useDialogContext(CLOSE_NAME, __scopeDialog);\n return /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n ...closeProps,\n ref: forwardedRef,\n onClick: composeEventHandlers(props.onClick, () => context.onOpenChange(false))\n }\n );\n }\n);\nDialogClose.displayName = CLOSE_NAME;\nfunction getState(open) {\n return open ? \"open\" : \"closed\";\n}\nvar TITLE_WARNING_NAME = \"DialogTitleWarning\";\nvar [WarningProvider, useWarningContext] = createContext(TITLE_WARNING_NAME, {\n contentName: CONTENT_NAME,\n titleName: TITLE_NAME,\n docsSlug: \"dialog\"\n});\nvar TitleWarning = ({ titleId }) => {\n const titleWarningContext = useWarningContext(TITLE_WARNING_NAME);\n const MESSAGE = `\\`${titleWarningContext.contentName}\\` requires a \\`${titleWarningContext.titleName}\\` for the component to be accessible for screen reader users.\n\nIf you want to hide the \\`${titleWarningContext.titleName}\\`, you can wrap it with our VisuallyHidden component.\n\nFor more information, see https://radix-ui.com/primitives/docs/components/${titleWarningContext.docsSlug}`;\n React.useEffect(() => {\n if (titleId) {\n const hasTitle = document.getElementById(titleId);\n if (!hasTitle) console.error(MESSAGE);\n }\n }, [MESSAGE, titleId]);\n return null;\n};\nvar DESCRIPTION_WARNING_NAME = \"DialogDescriptionWarning\";\nvar DescriptionWarning = ({ contentRef, descriptionId }) => {\n const descriptionWarningContext = useWarningContext(DESCRIPTION_WARNING_NAME);\n const MESSAGE = `Warning: Missing \\`Description\\` or \\`aria-describedby={undefined}\\` for {${descriptionWarningContext.contentName}}.`;\n React.useEffect(() => {\n const describedById = contentRef.current?.getAttribute(\"aria-describedby\");\n if (descriptionId && describedById) {\n const hasDescription = document.getElementById(descriptionId);\n if (!hasDescription) console.warn(MESSAGE);\n }\n }, [MESSAGE, contentRef, descriptionId]);\n return null;\n};\nvar Root = Dialog;\nvar Trigger = DialogTrigger;\nvar Portal = DialogPortal;\nvar Overlay = DialogOverlay;\nvar Content = DialogContent;\nvar Title = DialogTitle;\nvar Description = DialogDescription;\nvar Close = DialogClose;\nexport {\n Close,\n Content,\n Description,\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n Overlay,\n Portal,\n Root,\n Title,\n Trigger,\n WarningProvider,\n createDialogScope\n};\n//# sourceMappingURL=index.mjs.map\n","import * as DialogPrimitive from '@radix-ui/react-dialog'\nimport * as React from 'react'\nimport { cn } from '#app/utils/misc.tsx'\nimport { Icon } from '../icons'\n\nconst Dialog = DialogPrimitive.Root\n\nconst DialogTrigger = DialogPrimitive.Trigger\n\nconst DialogPortal = DialogPrimitive.Portal\n\nconst DialogClose = DialogPrimitive.Close\n\nfunction DialogOverlay({\n\tclassName,\n\tref,\n\t...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n\treturn (\n\t\t<DialogPrimitive.Overlay\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t'fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName\n\nfunction DialogContent({\n\tclassName,\n\tchildren,\n\tref,\n\t...props\n}: React.ComponentProps<typeof DialogPrimitive.Content>) {\n\treturn (\n\t\t<DialogPortal>\n\t\t\t<DialogOverlay />\n\t\t\t<DialogPrimitive.Content\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\">\n\t\t\t\t\t<Icon name=\"Close\" />\n\t\t\t\t\t<span className=\"sr-only\">Close</span>\n\t\t\t\t</DialogPrimitive.Close>\n\t\t\t</DialogPrimitive.Content>\n\t\t</DialogPortal>\n\t)\n}\nDialogContent.displayName = DialogPrimitive.Content.displayName\n\nfunction DialogHeader({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'flex flex-col space-y-1.5 text-center sm:text-left',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogHeader.displayName = 'DialogHeader'\n\nfunction DialogFooter({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogFooter.displayName = 'DialogFooter'\n\nfunction DialogTitle({\n\tclassName,\n\tref,\n\t...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n\treturn (\n\t\t<DialogPrimitive.Title\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t'text-lg font-semibold leading-none tracking-tight',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogTitle.displayName = DialogPrimitive.Title.displayName\n\nfunction DialogDescription({\n\tclassName,\n\tref,\n\t...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n\treturn (\n\t\t<DialogPrimitive.Description\n\t\t\tref={ref}\n\t\t\tclassName={cn('text-sm text-muted-foreground', className)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogDescription.displayName = DialogPrimitive.Description.displayName\n\nexport {\n\tDialog,\n\tDialogClose,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogOverlay,\n\tDialogPortal,\n\tDialogTitle,\n\tDialogTrigger,\n}\n","import {\n\textractNumbersAndTypeFromAppNameOrPath,\n\tgetExercises,\n\tgetPlaygroundAppName,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n} from '@epic-web/workshop-utils/timing.server'\nimport {\n\tjson,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n} from '@remix-run/node'\nimport {\n\tLink,\n\tNavLink,\n\tOutlet,\n\tuseLoaderData,\n\tuseParams,\n} from '@remix-run/react'\nimport { clsx } from 'clsx'\nimport {\n\tmotion,\n\tuseAnimationControls,\n\ttype AnimationControls,\n} from 'framer-motion'\nimport * as React from 'react'\nimport { useHydrated } from 'remix-utils/use-hydrated'\nimport { Icon } from '#app/components/icons.tsx'\nimport { makeMediaQueryStore } from '#app/components/media-query.ts'\nimport { Logo } from '#app/components/product.tsx'\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogHeader,\n\tDialogTrigger,\n} from '#app/components/ui/dialog.js'\nimport {\n\tSimpleTooltip,\n\tTooltip,\n\tTooltipContent,\n\tTooltipProvider,\n\tTooltipTrigger,\n} from '#app/components/ui/tooltip.tsx'\nimport { useOptionalUser } from '#app/components/user.tsx'\nimport { useWorkshopConfig } from '#app/components/workshop-config.js'\nimport { cn } from '#app/utils/misc.tsx'\nimport { usePresence, type User } from '#app/utils/presence.tsx'\nimport {\n\tuseExerciseProgressClassName,\n\tuseNextExerciseRoute,\n\tuseProgressItemClassName,\n\ttype ProgressItemSearch,\n} from '../progress.tsx'\nimport { ThemeSwitch } from '../theme/index.tsx'\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('appLayoutLoader')\n\tconst { title: workshopTitle } = getWorkshopConfig()\n\tconst [exercises, playgroundAppName] = await Promise.all([\n\t\tgetExercises({ request, timings }),\n\t\tgetPlaygroundAppName(),\n\t])\n\n\tconst playground = {\n\t\tappName: playgroundAppName,\n\t\texerciseNumber: Number(\n\t\t\textractNumbersAndTypeFromAppNameOrPath(playgroundAppName ?? '')\n\t\t\t\t?.exerciseNumber,\n\t\t),\n\t}\n\n\tconst result = json(\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})),\n\t\t\t})),\n\t\t\tplayground,\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]\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-purple-700 hover:opacity-100 focus:opacity-100 dark:shadow-purple-200',\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 locationLabel = getLocationLabel(user.location)\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>\n\t\t\t\t\t\t\t\t\t{user.avatarUrl ? (\n\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\ttabIndex={0}\n\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\tclassName={cn(\n\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\tscoreClassNames,\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\tsrc={user.avatarUrl}\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<div\n\t\t\t\t\t\t\t\t\t\t\ttabIndex={0}\n\t\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\t\tclassName={cn(\n\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\tscoreClassNames,\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<Icon name=\"User\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\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>\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{locationLabel\n\t\t\t\t\t\t\t\t\t\t\t\t? ` is ${user.location?.origin?.includes('localhost') ? 'working' : 'learning'} ${\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{locationLabel?.line1 ? (\n\t\t\t\t\t\t\t\t\t\t\t<span>{locationLabel.line1}</span>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t{locationLabel?.line2 ? (\n\t\t\t\t\t\t\t\t\t\t\t<span>{locationLabel.line2}</span>\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</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>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\ttabIndex={0}\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'flex items-center justify-center rounded-full border bg-accent text-xs text-accent-foreground',\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 overflow-hidden text-ellipsis whitespace-nowrap 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\nconst useIsWide = makeMediaQueryStore('(min-width: 640px)', true)\n\nexport default function App() {\n\tconst user = useOptionalUser()\n\tconst isWide = useIsWide()\n\tconst isHydrated = useHydrated()\n\n\tconst [isMenuOpened, setMenuOpened] = React.useState(false)\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/>\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 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/>\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 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) : (\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)}\n\t\t</div>\n\t)\n\treturn (\n\t\t<div className=\"z-10 flex h-16 items-center justify-between border-b bg-gradient-to-tr from-blue-500 to-indigo-500 pl-4 text-white\">\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<div className=\"hidden h-full flex-col items-center sm:flex md:flex-row\">\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto={`https://${host}`}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\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>\n\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Join {displayName}</span>\n\t\t\t\t\t\t\t<span>↗︎</span>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto={ENV.EPICSHOP_DEPLOYED ? `https://${host}/login` : '/login'}\n\t\t\t\t\t\t\tclassName=\"flex h-full items-center justify-center space-x-1.5 bg-white/20 px-5 text-sm font-semibold shadow-md transition hover:bg-white/30\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon name=\"User\" size=\"lg\" />\n\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Login</span>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t</div>\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<div className=\"flex h-full items-center\">\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto={`https://${host}`}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\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>\n\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Join</span>\n\t\t\t\t\t\t\t<span>↗︎</span>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto={ENV.EPICSHOP_DEPLOYED ? `https://${host}/login` : '/login'}\n\t\t\t\t\t\t\tclassName=\"flex h-full items-center justify-center space-x-1.5 bg-white/20 px-5 text-sm font-semibold shadow-md transition hover:bg-white/30\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon name=\"User\" size=\"lg\" />\n\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Login</span>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t</div>\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\t// @ts-expect-error framer-motion + latest typescript types has issues\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=\"ml-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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=\"ml-2\">{children}</span>\n\t\t</motion.li>\n\t)\n}\n\nfunction MobileNavigation({\n\tisMenuOpened,\n\tonMenuOpenChange: setMenuOpened,\n}: {\n\tisMenuOpened: boolean\n\tonMenuOpenChange: (change: boolean) => void\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tconst user = useOptionalUser()\n\tconst nextExerciseRoute = useNextExerciseRoute()\n\tconst params = useParams()\n\tconst { users } = usePresence()\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\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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\t\t\tclassName=\"flex w-full flex-grow flex-col justify-between overflow-x-auto p-6 scrollbar-thin scrollbar-thumb-scrollbar\"\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\t// @ts-expect-error framer-motion + latest typescript types has issues\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{data.exercises.map(({ exerciseNumber, title, steps }) => {\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\tconst exerciseNum = exerciseNumber.toString().padStart(2, '0')\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<Link\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\tto={`/${exerciseNum}`}\n\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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-2xl font-bold outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background after:content-[\"\"] hover:underline focus:underline',\n\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)}\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{title}\n\t\t\t\t\t\t\t\t\t\t\t\t{showPlayground ? ' 🛝' : null}\n\t\t\t\t\t\t\t\t\t\t\t</Link>\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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"ml-4 mt-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={`/${exerciseNum}`}\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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-xl font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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(({ name, stepNumber, title }) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isActive =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNumber(params.stepNumber) === stepNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst step = stepNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.padStart(2, '0')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isPlayground =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname === data.playground.appName\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<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={`/${exerciseNum}/${step}`}\n\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\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative whitespace-nowrap px-2 py-0.5 pr-3 text-xl font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background after:content-[\"\"] hover:underline focus:underline',\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\t'bg-foreground text-background':\n\t\t\t\t\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\t\t},\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>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{isPlayground\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? `${step}. ${title} 🛝`\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: `${step}. ${title}`}\n\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</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={`/${exerciseNum}/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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-base font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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</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 whitespace-nowrap text-lg font-bold 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'bg-black text-white after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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=\"flex-grow\" />\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\t{\n\t\t\t\t\t\t\t\t'w-full border-t': isMenuOpened,\n\t\t\t\t\t\t\t\t// left border is covered by the menu\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<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'flex h-14 flex-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>\n\t\t\t\t\t\t\t\t{user.avatarUrl ? (\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.avatarUrl}\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=\"flex-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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</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=\"flex-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-14 w-14 items-center justify-center self-start p-4 sm:mb-4 sm:w-full',\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'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<ThemeSwitch />\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 Navigation({\n\tisMenuOpened,\n\tonMenuOpenChange: setMenuOpened,\n}: {\n\tisMenuOpened: boolean\n\tonMenuOpenChange: (change: boolean) => void\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tconst user = useOptionalUser()\n\tconst nextExerciseRoute = useNextExerciseRoute()\n\tconst params = useParams()\n\tconst { users } = usePresence()\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\tconst exNum = Number(params.exerciseNumber).toString().padStart(2, '0')\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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\t\t\tclassName=\"flex flex-grow flex-col justify-between overflow-y-auto p-6 scrollbar-thin scrollbar-thumb-scrollbar\"\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\t// @ts-expect-error framer-motion + latest typescript types has issues\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{data.exercises.map(({ exerciseNumber, title, steps }) => {\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\tconst exerciseNum = exerciseNumber.toString().padStart(2, '0')\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<Link\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\tto={`/${exerciseNum}`}\n\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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-2xl font-bold outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background after:content-[\"\"] hover:underline focus:underline',\n\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)}\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{title}\n\t\t\t\t\t\t\t\t\t\t\t\t{showPlayground ? ' 🛝' : null}\n\t\t\t\t\t\t\t\t\t\t\t</Link>\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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"ml-4 mt-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={`/${exerciseNum}`}\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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-xl font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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(({ name, stepNumber, title }) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isActive =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNumber(params.stepNumber) === stepNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst step = stepNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.padStart(2, '0')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isPlayground =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname === data.playground.appName\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<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={`/${exerciseNum}/${step}`}\n\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\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative whitespace-nowrap px-2 py-0.5 pr-3 text-xl font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background after:content-[\"\"] hover:underline focus:underline',\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\t'bg-foreground text-background':\n\t\t\t\t\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\t\t},\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>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{isPlayground\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? `${step}. ${title} 🛝`\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: `${step}. ${title}`}\n\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</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={`/${exerciseNum}/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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-base font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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</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 whitespace-nowrap text-lg font-bold 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'bg-black text-white after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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 flex-grow flex-col justify-center\">\n\t\t\t\t\t\t\t<div className=\"orientation-sideways w-full font-mono text-sm font-medium uppercase leading-none\">\n\t\t\t\t\t\t\t\t{exercise?.title ? (\n\t\t\t\t\t\t\t\t\t<Link to={`/${exNum}`}>{exercise.title}</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={`/${exNum}/${app.stepNumber\n\t\t\t\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t\t\t\t.padStart(2, '0')}`}\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<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=\"flex h-14 w-full flex-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>\n\t\t\t\t\t\t\t\t{user.avatarUrl ? (\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.avatarUrl}\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=\"flex-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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</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=\"flex-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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<div className=\"mb-4 w-full self-start border-t pl-3 pt-[15px]\">\n\t\t\t\t\t\t<ThemeSwitch />\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 NavToggle({\n\ttitle,\n\tisMenuOpened,\n\tsetMenuOpened,\n\tmenuControls,\n}: {\n\ttitle: string\n\tisMenuOpened: boolean\n\tsetMenuOpened: (value: boolean) => void\n\tmenuControls?: AnimationControls\n}) {\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 handleKeyUp(event: KeyboardEvent) {\n\t\t\tif (event.key === 'Escape') {\n\t\t\t\tmenuButtonRef.current?.click()\n\t\t\t}\n\t\t}\n\t\tdocument.addEventListener('keyup', handleKeyUp)\n\t\treturn () => document.removeEventListener('keyup', handleKeyUp)\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 flex-shrink-0 items-center justify-between overflow-hidden border-r sm:w-full sm:border-b sm:border-r-0',\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.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.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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\tclassName=\"absolute right-5 whitespace-nowrap font-mono text-sm 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","DIALOG_NAME","createDialogContext","createDialogScope","createContextScope","DialogProvider","useDialogContext","Dialog","props","__scopeDialog","children","openProp","defaultOpen","onOpenChange","modal","triggerRef","React.useRef","contentRef","open","setOpen","useControllableState","jsx","useId","React.useCallback","prevOpen","TRIGGER_NAME","DialogTrigger","React.forwardRef","forwardedRef","triggerProps","context","composedTriggerRef","useComposedRefs","Primitive","getState","composeEventHandlers","PORTAL_NAME","PortalProvider","usePortalContext","DialogPortal","forceMount","container","React.Children","Presence","PortalPrimitive","OVERLAY_NAME","DialogOverlay","portalContext","overlayProps","DialogOverlayImpl","RemoveScroll","Slot","CONTENT_NAME","DialogContent","contentProps","DialogContentModal","DialogContentNonModal","composedRefs","React.useEffect","content","hideOthers","DialogContentImpl","event","_a","originalEvent","ctrlLeftClick","hasInteractedOutsideRef","hasPointerDownOutsideRef","_b","target","trapFocus","onOpenAutoFocus","onCloseAutoFocus","useFocusGuards","jsxs","Fragment","FocusScope","DismissableLayer","TitleWarning","DescriptionWarning","TITLE_NAME","DialogTitle","titleProps","DESCRIPTION_NAME","DialogDescription","descriptionProps","CLOSE_NAME","DialogClose","closeProps","TITLE_WARNING_NAME","WarningProvider","useWarningContext","createContext","titleId","titleWarningContext","MESSAGE","DESCRIPTION_WARNING_NAME","descriptionId","describedById","Root","Trigger","Portal","Overlay","Content","Title","Description","Close","DialogPrimitive.Root","DialogPrimitive.Trigger","DialogPrimitive.Portal","className","ref","DialogPrimitive.Overlay","cn","DialogPrimitive.Content","DialogPrimitive.Close","Icon","DialogHeader","DialogPrimitive.Title","DialogPrimitive.Description","opacities","shadows","getScoreClassNames","score","opacityNumber","Math","round","length","shadowNumber","FacePile","isMenuOpened","loggedInUser","useOptionalUser","users","usePresence","product","displayNameShort","useWorkshopConfig","limit","numberOverLimit","shouldShowNumberOverLimit","tiffany","Link","rel","to","alt","src","overLimitLabel","TooltipProvider","slice","map","user","scoreClassNames","locationLabel","getLocationLabel","location","Tooltip","TooltipTrigger","asChild","avatarUrl","tabIndex","name","TooltipContent","origin","includes","id","line1","line2","useIsWide","App","isWide","isHydrated","useHydrated","setMenuOpened","React","NoUserBanner","MobileNavigation","onMenuOpenChange","Navigation","Outlet","exercise","exercisePortion","exerciseNumber","stepNumber","filter","Boolean","s","toString","padStart","join","type","workshopTitle","host","displayName","details","ENV","EPICSHOP_DEPLOYED","EPICSHOP_GITHUB_REPO","href","Logo","size","style","itemVariants","hidden","opacity","x","visible","NavigationExerciseListItem","progressClassName","useExerciseProgressClassName","motion","li","variants","NavigationExerciseStepListItem","progressItemSearch","useProgressItemClassName","data","useLoaderData","nextExerciseRoute","useNextExerciseRoute","params","useParams","listVariants","transition","duration","when","staggerChildren","NavToggle","title","div","initial","animate","ul","exercises","steps","isActive","Number","showPlayground","playground","exerciseNum","prefetch","clsx","step","isPlayground","appName","NavLink","SimpleTooltip","email","state","from","ThemeSwitch","OPENED_MENU_WIDTH","find","e","app","solutions","problems","p","menuControls","menuVariants","close","width","exNum","menuButtonRef","path01Variants","d","closed","path02Variants","moving","path01Controls","path02Controls","toggleMenu","start","handleKeyUp","current","click","document","addEventListener","removeEventListener","onClick","height","viewBox","path","stroke","strokeWidth","delay","y"],"mappings":"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","x_google_ignoreList":[0,1,3]}
1
+ {"version":3,"file":"_layout-DkGEbcMk.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","../../../../../node_modules/@radix-ui/react-dialog/dist/index.mjs","../../../app/components/ui/dialog.tsx","../../../app/routes/_app+/_layout.tsx"],"sourcesContent":["import { invariant } from '../../utils/errors.mjs';\nimport { setTarget } from '../../render/utils/setters.mjs';\nimport { animateVisualElement } from '../interfaces/visual-element.mjs';\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","import { animationControls } from './animation-controls.mjs';\nimport { useConstant } from '../../utils/use-constant.mjs';\nimport { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';\n\n/**\n * Creates `AnimationControls`, which can be used to manually start, stop\n * and sequence animations on one or more components.\n *\n * The returned `AnimationControls` 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","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","\"use client\";\n\n// packages/react/dialog/src/Dialog.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { createContext, createContextScope } from \"@radix-ui/react-context\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { DismissableLayer } from \"@radix-ui/react-dismissable-layer\";\nimport { FocusScope } from \"@radix-ui/react-focus-scope\";\nimport { Portal as PortalPrimitive } from \"@radix-ui/react-portal\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useFocusGuards } from \"@radix-ui/react-focus-guards\";\nimport { RemoveScroll } from \"react-remove-scroll\";\nimport { hideOthers } from \"aria-hidden\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { Fragment, jsx, jsxs } from \"react/jsx-runtime\";\nvar DIALOG_NAME = \"Dialog\";\nvar [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);\nvar [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);\nvar Dialog = (props) => {\n const {\n __scopeDialog,\n children,\n open: openProp,\n defaultOpen,\n onOpenChange,\n modal = true\n } = props;\n const triggerRef = React.useRef(null);\n const contentRef = React.useRef(null);\n const [open = false, setOpen] = useControllableState({\n prop: openProp,\n defaultProp: defaultOpen,\n onChange: onOpenChange\n });\n return /* @__PURE__ */ jsx(\n DialogProvider,\n {\n scope: __scopeDialog,\n triggerRef,\n contentRef,\n contentId: useId(),\n titleId: useId(),\n descriptionId: useId(),\n open,\n onOpenChange: setOpen,\n onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),\n modal,\n children\n }\n );\n};\nDialog.displayName = DIALOG_NAME;\nvar TRIGGER_NAME = \"DialogTrigger\";\nvar DialogTrigger = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...triggerProps } = props;\n const context = useDialogContext(TRIGGER_NAME, __scopeDialog);\n const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef);\n return /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n \"aria-haspopup\": \"dialog\",\n \"aria-expanded\": context.open,\n \"aria-controls\": context.contentId,\n \"data-state\": getState(context.open),\n ...triggerProps,\n ref: composedTriggerRef,\n onClick: composeEventHandlers(props.onClick, context.onOpenToggle)\n }\n );\n }\n);\nDialogTrigger.displayName = TRIGGER_NAME;\nvar PORTAL_NAME = \"DialogPortal\";\nvar [PortalProvider, usePortalContext] = createDialogContext(PORTAL_NAME, {\n forceMount: void 0\n});\nvar DialogPortal = (props) => {\n const { __scopeDialog, forceMount, children, container } = props;\n const context = useDialogContext(PORTAL_NAME, __scopeDialog);\n return /* @__PURE__ */ jsx(PortalProvider, { scope: __scopeDialog, forceMount, children: React.Children.map(children, (child) => /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(PortalPrimitive, { asChild: true, container, children: child }) })) });\n};\nDialogPortal.displayName = PORTAL_NAME;\nvar OVERLAY_NAME = \"DialogOverlay\";\nvar DialogOverlay = React.forwardRef(\n (props, forwardedRef) => {\n const portalContext = usePortalContext(OVERLAY_NAME, props.__scopeDialog);\n const { forceMount = portalContext.forceMount, ...overlayProps } = props;\n const context = useDialogContext(OVERLAY_NAME, props.__scopeDialog);\n return context.modal ? /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(DialogOverlayImpl, { ...overlayProps, ref: forwardedRef }) }) : null;\n }\n);\nDialogOverlay.displayName = OVERLAY_NAME;\nvar DialogOverlayImpl = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...overlayProps } = props;\n const context = useDialogContext(OVERLAY_NAME, __scopeDialog);\n return (\n // Make sure `Content` is scrollable even when it doesn't live inside `RemoveScroll`\n // ie. when `Overlay` and `Content` are siblings\n /* @__PURE__ */ jsx(RemoveScroll, { as: Slot, allowPinchZoom: true, shards: [context.contentRef], children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n \"data-state\": getState(context.open),\n ...overlayProps,\n ref: forwardedRef,\n style: { pointerEvents: \"auto\", ...overlayProps.style }\n }\n ) })\n );\n }\n);\nvar CONTENT_NAME = \"DialogContent\";\nvar DialogContent = React.forwardRef(\n (props, forwardedRef) => {\n const portalContext = usePortalContext(CONTENT_NAME, props.__scopeDialog);\n const { forceMount = portalContext.forceMount, ...contentProps } = props;\n const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: context.modal ? /* @__PURE__ */ jsx(DialogContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(DialogContentNonModal, { ...contentProps, ref: forwardedRef }) });\n }\n);\nDialogContent.displayName = CONTENT_NAME;\nvar DialogContentModal = React.forwardRef(\n (props, forwardedRef) => {\n const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n const contentRef = React.useRef(null);\n const composedRefs = useComposedRefs(forwardedRef, context.contentRef, contentRef);\n React.useEffect(() => {\n const content = contentRef.current;\n if (content) return hideOthers(content);\n }, []);\n return /* @__PURE__ */ jsx(\n DialogContentImpl,\n {\n ...props,\n ref: composedRefs,\n trapFocus: context.open,\n disableOutsidePointerEvents: true,\n onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {\n event.preventDefault();\n context.triggerRef.current?.focus();\n }),\n onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event) => {\n const originalEvent = event.detail.originalEvent;\n const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;\n const isRightClick = originalEvent.button === 2 || ctrlLeftClick;\n if (isRightClick) event.preventDefault();\n }),\n onFocusOutside: composeEventHandlers(\n props.onFocusOutside,\n (event) => event.preventDefault()\n )\n }\n );\n }\n);\nvar DialogContentNonModal = React.forwardRef(\n (props, forwardedRef) => {\n const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n const hasInteractedOutsideRef = React.useRef(false);\n const hasPointerDownOutsideRef = React.useRef(false);\n return /* @__PURE__ */ jsx(\n DialogContentImpl,\n {\n ...props,\n ref: forwardedRef,\n trapFocus: false,\n disableOutsidePointerEvents: false,\n onCloseAutoFocus: (event) => {\n props.onCloseAutoFocus?.(event);\n if (!event.defaultPrevented) {\n if (!hasInteractedOutsideRef.current) context.triggerRef.current?.focus();\n event.preventDefault();\n }\n hasInteractedOutsideRef.current = false;\n hasPointerDownOutsideRef.current = false;\n },\n onInteractOutside: (event) => {\n props.onInteractOutside?.(event);\n if (!event.defaultPrevented) {\n hasInteractedOutsideRef.current = true;\n if (event.detail.originalEvent.type === \"pointerdown\") {\n hasPointerDownOutsideRef.current = true;\n }\n }\n const target = event.target;\n const targetIsTrigger = context.triggerRef.current?.contains(target);\n if (targetIsTrigger) event.preventDefault();\n if (event.detail.originalEvent.type === \"focusin\" && hasPointerDownOutsideRef.current) {\n event.preventDefault();\n }\n }\n }\n );\n }\n);\nvar DialogContentImpl = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, trapFocus, onOpenAutoFocus, onCloseAutoFocus, ...contentProps } = props;\n const context = useDialogContext(CONTENT_NAME, __scopeDialog);\n const contentRef = React.useRef(null);\n const composedRefs = useComposedRefs(forwardedRef, contentRef);\n useFocusGuards();\n return /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(\n FocusScope,\n {\n asChild: true,\n loop: true,\n trapped: trapFocus,\n onMountAutoFocus: onOpenAutoFocus,\n onUnmountAutoFocus: onCloseAutoFocus,\n children: /* @__PURE__ */ jsx(\n DismissableLayer,\n {\n role: \"dialog\",\n id: context.contentId,\n \"aria-describedby\": context.descriptionId,\n \"aria-labelledby\": context.titleId,\n \"data-state\": getState(context.open),\n ...contentProps,\n ref: composedRefs,\n onDismiss: () => context.onOpenChange(false)\n }\n )\n }\n ),\n /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(TitleWarning, { titleId: context.titleId }),\n /* @__PURE__ */ jsx(DescriptionWarning, { contentRef, descriptionId: context.descriptionId })\n ] })\n ] });\n }\n);\nvar TITLE_NAME = \"DialogTitle\";\nvar DialogTitle = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...titleProps } = props;\n const context = useDialogContext(TITLE_NAME, __scopeDialog);\n return /* @__PURE__ */ jsx(Primitive.h2, { id: context.titleId, ...titleProps, ref: forwardedRef });\n }\n);\nDialogTitle.displayName = TITLE_NAME;\nvar DESCRIPTION_NAME = \"DialogDescription\";\nvar DialogDescription = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...descriptionProps } = props;\n const context = useDialogContext(DESCRIPTION_NAME, __scopeDialog);\n return /* @__PURE__ */ jsx(Primitive.p, { id: context.descriptionId, ...descriptionProps, ref: forwardedRef });\n }\n);\nDialogDescription.displayName = DESCRIPTION_NAME;\nvar CLOSE_NAME = \"DialogClose\";\nvar DialogClose = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeDialog, ...closeProps } = props;\n const context = useDialogContext(CLOSE_NAME, __scopeDialog);\n return /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n ...closeProps,\n ref: forwardedRef,\n onClick: composeEventHandlers(props.onClick, () => context.onOpenChange(false))\n }\n );\n }\n);\nDialogClose.displayName = CLOSE_NAME;\nfunction getState(open) {\n return open ? \"open\" : \"closed\";\n}\nvar TITLE_WARNING_NAME = \"DialogTitleWarning\";\nvar [WarningProvider, useWarningContext] = createContext(TITLE_WARNING_NAME, {\n contentName: CONTENT_NAME,\n titleName: TITLE_NAME,\n docsSlug: \"dialog\"\n});\nvar TitleWarning = ({ titleId }) => {\n const titleWarningContext = useWarningContext(TITLE_WARNING_NAME);\n const MESSAGE = `\\`${titleWarningContext.contentName}\\` requires a \\`${titleWarningContext.titleName}\\` for the component to be accessible for screen reader users.\n\nIf you want to hide the \\`${titleWarningContext.titleName}\\`, you can wrap it with our VisuallyHidden component.\n\nFor more information, see https://radix-ui.com/primitives/docs/components/${titleWarningContext.docsSlug}`;\n React.useEffect(() => {\n if (titleId) {\n const hasTitle = document.getElementById(titleId);\n if (!hasTitle) console.error(MESSAGE);\n }\n }, [MESSAGE, titleId]);\n return null;\n};\nvar DESCRIPTION_WARNING_NAME = \"DialogDescriptionWarning\";\nvar DescriptionWarning = ({ contentRef, descriptionId }) => {\n const descriptionWarningContext = useWarningContext(DESCRIPTION_WARNING_NAME);\n const MESSAGE = `Warning: Missing \\`Description\\` or \\`aria-describedby={undefined}\\` for {${descriptionWarningContext.contentName}}.`;\n React.useEffect(() => {\n const describedById = contentRef.current?.getAttribute(\"aria-describedby\");\n if (descriptionId && describedById) {\n const hasDescription = document.getElementById(descriptionId);\n if (!hasDescription) console.warn(MESSAGE);\n }\n }, [MESSAGE, contentRef, descriptionId]);\n return null;\n};\nvar Root = Dialog;\nvar Trigger = DialogTrigger;\nvar Portal = DialogPortal;\nvar Overlay = DialogOverlay;\nvar Content = DialogContent;\nvar Title = DialogTitle;\nvar Description = DialogDescription;\nvar Close = DialogClose;\nexport {\n Close,\n Content,\n Description,\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n Overlay,\n Portal,\n Root,\n Title,\n Trigger,\n WarningProvider,\n createDialogScope\n};\n//# sourceMappingURL=index.mjs.map\n","import * as DialogPrimitive from '@radix-ui/react-dialog'\nimport * as React from 'react'\nimport { cn } from '#app/utils/misc.tsx'\nimport { Icon } from '../icons'\n\nconst Dialog = DialogPrimitive.Root\n\nconst DialogTrigger = DialogPrimitive.Trigger\n\nconst DialogPortal = DialogPrimitive.Portal\n\nconst DialogClose = DialogPrimitive.Close\n\nfunction DialogOverlay({\n\tclassName,\n\tref,\n\t...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n\treturn (\n\t\t<DialogPrimitive.Overlay\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t'fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName\n\nfunction DialogContent({\n\tclassName,\n\tchildren,\n\tref,\n\t...props\n}: React.ComponentProps<typeof DialogPrimitive.Content>) {\n\treturn (\n\t\t<DialogPortal>\n\t\t\t<DialogOverlay />\n\t\t\t<DialogPrimitive.Content\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\">\n\t\t\t\t\t<Icon name=\"Close\" />\n\t\t\t\t\t<span className=\"sr-only\">Close</span>\n\t\t\t\t</DialogPrimitive.Close>\n\t\t\t</DialogPrimitive.Content>\n\t\t</DialogPortal>\n\t)\n}\nDialogContent.displayName = DialogPrimitive.Content.displayName\n\nfunction DialogHeader({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'flex flex-col space-y-1.5 text-center sm:text-left',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogHeader.displayName = 'DialogHeader'\n\nfunction DialogFooter({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogFooter.displayName = 'DialogFooter'\n\nfunction DialogTitle({\n\tclassName,\n\tref,\n\t...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n\treturn (\n\t\t<DialogPrimitive.Title\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t'text-lg font-semibold leading-none tracking-tight',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogTitle.displayName = DialogPrimitive.Title.displayName\n\nfunction DialogDescription({\n\tclassName,\n\tref,\n\t...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n\treturn (\n\t\t<DialogPrimitive.Description\n\t\t\tref={ref}\n\t\t\tclassName={cn('text-sm text-muted-foreground', className)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\nDialogDescription.displayName = DialogPrimitive.Description.displayName\n\nexport {\n\tDialog,\n\tDialogClose,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogOverlay,\n\tDialogPortal,\n\tDialogTitle,\n\tDialogTrigger,\n}\n","import {\n\textractNumbersAndTypeFromAppNameOrPath,\n\tgetExercises,\n\tgetPlaygroundAppName,\n} from '@epic-web/workshop-utils/apps.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n} from '@epic-web/workshop-utils/timing.server'\nimport {\n\tjson,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n} from '@remix-run/node'\nimport {\n\tLink,\n\tNavLink,\n\tOutlet,\n\tuseLoaderData,\n\tuseParams,\n} from '@remix-run/react'\nimport { clsx } from 'clsx'\nimport {\n\tmotion,\n\tuseAnimationControls,\n\ttype AnimationControls,\n} from 'framer-motion'\nimport * as React from 'react'\nimport { useHydrated } from 'remix-utils/use-hydrated'\nimport { Icon } from '#app/components/icons.tsx'\nimport { makeMediaQueryStore } from '#app/components/media-query.ts'\nimport { Logo } from '#app/components/product.tsx'\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogHeader,\n\tDialogTrigger,\n} from '#app/components/ui/dialog.js'\nimport {\n\tSimpleTooltip,\n\tTooltip,\n\tTooltipContent,\n\tTooltipProvider,\n\tTooltipTrigger,\n} from '#app/components/ui/tooltip.tsx'\nimport { useOptionalUser } from '#app/components/user.tsx'\nimport { useWorkshopConfig } from '#app/components/workshop-config.js'\nimport { cn } from '#app/utils/misc.tsx'\nimport { usePresence, type User } from '#app/utils/presence.tsx'\nimport {\n\tuseExerciseProgressClassName,\n\tuseNextExerciseRoute,\n\tuseProgressItemClassName,\n\ttype ProgressItemSearch,\n} from '../progress.tsx'\nimport { ThemeSwitch } from '../theme/index.tsx'\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('appLayoutLoader')\n\tconst { title: workshopTitle } = getWorkshopConfig()\n\tconst [exercises, playgroundAppName] = await Promise.all([\n\t\tgetExercises({ request, timings }),\n\t\tgetPlaygroundAppName(),\n\t])\n\n\tconst playground = {\n\t\tappName: playgroundAppName,\n\t\texerciseNumber: Number(\n\t\t\textractNumbersAndTypeFromAppNameOrPath(playgroundAppName ?? '')\n\t\t\t\t?.exerciseNumber,\n\t\t),\n\t}\n\n\tconst result = json(\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})),\n\t\t\t})),\n\t\t\tplayground,\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]\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-purple-700 hover:opacity-100 focus:opacity-100 dark:shadow-purple-200',\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 locationLabel = getLocationLabel(user.location)\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>\n\t\t\t\t\t\t\t\t\t{user.avatarUrl ? (\n\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\ttabIndex={0}\n\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\tclassName={cn(\n\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\tscoreClassNames,\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\tsrc={user.avatarUrl}\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<div\n\t\t\t\t\t\t\t\t\t\t\ttabIndex={0}\n\t\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\t\tclassName={cn(\n\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\tscoreClassNames,\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<Icon name=\"User\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\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>\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{locationLabel\n\t\t\t\t\t\t\t\t\t\t\t\t? ` is ${user.location?.origin?.includes('localhost') ? 'working' : 'learning'} ${\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{locationLabel?.line1 ? (\n\t\t\t\t\t\t\t\t\t\t\t<span>{locationLabel.line1}</span>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t\t{locationLabel?.line2 ? (\n\t\t\t\t\t\t\t\t\t\t\t<span>{locationLabel.line2}</span>\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</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>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\ttabIndex={0}\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'flex items-center justify-center rounded-full border bg-accent text-xs text-accent-foreground',\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 overflow-hidden text-ellipsis whitespace-nowrap 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\nconst useIsWide = makeMediaQueryStore('(min-width: 640px)', true)\n\nexport default function App() {\n\tconst user = useOptionalUser()\n\tconst isWide = useIsWide()\n\tconst isHydrated = useHydrated()\n\n\tconst [isMenuOpened, setMenuOpened] = React.useState(false)\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/>\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 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/>\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 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) : (\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)}\n\t\t</div>\n\t)\n\treturn (\n\t\t<div className=\"z-10 flex h-16 items-center justify-between border-b bg-gradient-to-tr from-blue-500 to-indigo-500 pl-4 text-white\">\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<div className=\"hidden h-full flex-col items-center sm:flex md:flex-row\">\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto={`https://${host}`}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\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>\n\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Join {displayName}</span>\n\t\t\t\t\t\t\t<span>↗︎</span>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto={ENV.EPICSHOP_DEPLOYED ? `https://${host}/login` : '/login'}\n\t\t\t\t\t\t\tclassName=\"flex h-full items-center justify-center space-x-1.5 bg-white/20 px-5 text-sm font-semibold shadow-md transition hover:bg-white/30\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon name=\"User\" size=\"lg\" />\n\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Login</span>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t</div>\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<div className=\"flex h-full items-center\">\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto={`https://${host}`}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\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>\n\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Join</span>\n\t\t\t\t\t\t\t<span>↗︎</span>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\tto={ENV.EPICSHOP_DEPLOYED ? `https://${host}/login` : '/login'}\n\t\t\t\t\t\t\tclassName=\"flex h-full items-center justify-center space-x-1.5 bg-white/20 px-5 text-sm font-semibold shadow-md transition hover:bg-white/30\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon name=\"User\" size=\"lg\" />\n\t\t\t\t\t\t\t<span className=\"drop-shadow-sm\">Login</span>\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t</div>\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\t// @ts-expect-error framer-motion + latest typescript types has issues\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=\"ml-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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=\"ml-2\">{children}</span>\n\t\t</motion.li>\n\t)\n}\n\nfunction MobileNavigation({\n\tisMenuOpened,\n\tonMenuOpenChange: setMenuOpened,\n}: {\n\tisMenuOpened: boolean\n\tonMenuOpenChange: (change: boolean) => void\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tconst user = useOptionalUser()\n\tconst nextExerciseRoute = useNextExerciseRoute()\n\tconst params = useParams()\n\tconst { users } = usePresence()\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\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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\t\t\tclassName=\"flex w-full flex-grow flex-col justify-between overflow-x-auto p-6 scrollbar-thin scrollbar-thumb-scrollbar\"\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\t// @ts-expect-error framer-motion + latest typescript types has issues\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{data.exercises.map(({ exerciseNumber, title, steps }) => {\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\tconst exerciseNum = exerciseNumber.toString().padStart(2, '0')\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<Link\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\tto={`/${exerciseNum}`}\n\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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-2xl font-bold outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background after:content-[\"\"] hover:underline focus:underline',\n\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)}\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{title}\n\t\t\t\t\t\t\t\t\t\t\t\t{showPlayground ? ' 🛝' : null}\n\t\t\t\t\t\t\t\t\t\t\t</Link>\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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"ml-4 mt-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={`/${exerciseNum}`}\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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-xl font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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(({ name, stepNumber, title }) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isActive =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNumber(params.stepNumber) === stepNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst step = stepNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.padStart(2, '0')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isPlayground =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname === data.playground.appName\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<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={`/${exerciseNum}/${step}`}\n\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\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative whitespace-nowrap px-2 py-0.5 pr-3 text-xl font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background after:content-[\"\"] hover:underline focus:underline',\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\t'bg-foreground text-background':\n\t\t\t\t\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\t\t},\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>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{isPlayground\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? `${step}. ${title} 🛝`\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: `${step}. ${title}`}\n\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</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={`/${exerciseNum}/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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-base font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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</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 whitespace-nowrap text-lg font-bold 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'bg-black text-white after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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=\"flex-grow\" />\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\t{\n\t\t\t\t\t\t\t\t'w-full border-t': isMenuOpened,\n\t\t\t\t\t\t\t\t// left border is covered by the menu\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<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'flex h-14 flex-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>\n\t\t\t\t\t\t\t\t{user.avatarUrl ? (\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.avatarUrl}\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=\"flex-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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</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=\"flex-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-14 w-14 items-center justify-center self-start p-4 sm:mb-4 sm:w-full',\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'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<ThemeSwitch />\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 Navigation({\n\tisMenuOpened,\n\tonMenuOpenChange: setMenuOpened,\n}: {\n\tisMenuOpened: boolean\n\tonMenuOpenChange: (change: boolean) => void\n}) {\n\tconst data = useLoaderData<typeof loader>()\n\tconst user = useOptionalUser()\n\tconst nextExerciseRoute = useNextExerciseRoute()\n\tconst params = useParams()\n\tconst { users } = usePresence()\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\tconst exNum = Number(params.exerciseNumber).toString().padStart(2, '0')\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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\t\t\tclassName=\"flex flex-grow flex-col justify-between overflow-y-auto p-6 scrollbar-thin scrollbar-thumb-scrollbar\"\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\t// @ts-expect-error framer-motion + latest typescript types has issues\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{data.exercises.map(({ exerciseNumber, title, steps }) => {\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\tconst exerciseNum = exerciseNumber.toString().padStart(2, '0')\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<Link\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\tto={`/${exerciseNum}`}\n\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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-2xl font-bold outline-none hover:underline focus:underline',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background after:content-[\"\"] hover:underline focus:underline',\n\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)}\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{title}\n\t\t\t\t\t\t\t\t\t\t\t\t{showPlayground ? ' 🛝' : null}\n\t\t\t\t\t\t\t\t\t\t\t</Link>\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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"ml-4 mt-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={`/${exerciseNum}`}\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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-xl font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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(({ name, stepNumber, title }) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isActive =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNumber(params.stepNumber) === stepNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst step = stepNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.padStart(2, '0')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst isPlayground =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname === data.playground.appName\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<Link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tto={`/${exerciseNum}/${step}`}\n\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\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative whitespace-nowrap px-2 py-0.5 pr-3 text-xl font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background after:content-[\"\"] hover:underline focus:underline',\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\t'bg-foreground text-background':\n\t\t\t\t\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\t\t},\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>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{isPlayground\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? `${step}. ${title} 🛝`\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: `${step}. ${title}`}\n\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</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={`/${exerciseNum}/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'relative whitespace-nowrap px-2 py-0.5 pr-3 text-base font-medium outline-none after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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</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 whitespace-nowrap text-lg font-bold 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'bg-black text-white after:absolute after:-bottom-2.5 after:-right-2.5 after:h-5 after:w-5 after:rotate-45 after:scale-75 after:bg-background 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 flex-grow flex-col justify-center\">\n\t\t\t\t\t\t\t<div className=\"orientation-sideways w-full font-mono text-sm font-medium uppercase leading-none\">\n\t\t\t\t\t\t\t\t{exercise?.title ? (\n\t\t\t\t\t\t\t\t\t<Link to={`/${exNum}`}>{exercise.title}</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={`/${exNum}/${app.stepNumber\n\t\t\t\t\t\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t\t\t\t\t\t.padStart(2, '0')}`}\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<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=\"flex h-14 w-full flex-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>\n\t\t\t\t\t\t\t\t{user.avatarUrl ? (\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.avatarUrl}\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=\"flex-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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</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=\"flex-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\t// @ts-expect-error framer-motion + latest typescript types has issues\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<div className=\"mb-4 w-full self-start border-t pl-3 pt-[15px]\">\n\t\t\t\t\t\t<ThemeSwitch />\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 NavToggle({\n\ttitle,\n\tisMenuOpened,\n\tsetMenuOpened,\n\tmenuControls,\n}: {\n\ttitle: string\n\tisMenuOpened: boolean\n\tsetMenuOpened: (value: boolean) => void\n\tmenuControls?: AnimationControls\n}) {\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 handleKeyUp(event: KeyboardEvent) {\n\t\t\tif (event.key === 'Escape') {\n\t\t\t\tmenuButtonRef.current?.click()\n\t\t\t}\n\t\t}\n\t\tdocument.addEventListener('keyup', handleKeyUp)\n\t\treturn () => document.removeEventListener('keyup', handleKeyUp)\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 flex-shrink-0 items-center justify-between overflow-hidden border-r sm:w-full sm:border-b sm:border-r-0',\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.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.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\t// @ts-expect-error framer-motion + latest typescript types has issues\n\t\t\t\t\tclassName=\"absolute right-5 whitespace-nowrap font-mono text-sm 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","DIALOG_NAME","createDialogContext","createDialogScope","createContextScope","DialogProvider","useDialogContext","Dialog","props","__scopeDialog","children","openProp","defaultOpen","onOpenChange","modal","triggerRef","React.useRef","contentRef","open","setOpen","useControllableState","jsx","useId","React.useCallback","prevOpen","TRIGGER_NAME","DialogTrigger","React.forwardRef","forwardedRef","triggerProps","context","composedTriggerRef","useComposedRefs","Primitive","getState","composeEventHandlers","PORTAL_NAME","PortalProvider","usePortalContext","DialogPortal","forceMount","container","React.Children","Presence","PortalPrimitive","OVERLAY_NAME","DialogOverlay","portalContext","overlayProps","DialogOverlayImpl","RemoveScroll","Slot","CONTENT_NAME","DialogContent","contentProps","DialogContentModal","DialogContentNonModal","composedRefs","React.useEffect","content","hideOthers","DialogContentImpl","event","_a","originalEvent","ctrlLeftClick","hasInteractedOutsideRef","hasPointerDownOutsideRef","_b","target","trapFocus","onOpenAutoFocus","onCloseAutoFocus","useFocusGuards","jsxs","Fragment","FocusScope","DismissableLayer","TitleWarning","DescriptionWarning","TITLE_NAME","DialogTitle","titleProps","DESCRIPTION_NAME","DialogDescription","descriptionProps","CLOSE_NAME","DialogClose","closeProps","TITLE_WARNING_NAME","WarningProvider","useWarningContext","createContext","titleId","titleWarningContext","MESSAGE","DESCRIPTION_WARNING_NAME","descriptionId","describedById","Root","Trigger","Portal","Overlay","Content","Title","Description","Close","DialogPrimitive.Root","DialogPrimitive.Trigger","DialogPrimitive.Portal","className","ref","DialogPrimitive.Overlay","cn","DialogPrimitive.Content","DialogPrimitive.Close","Icon","DialogHeader","DialogPrimitive.Title","DialogPrimitive.Description","opacities","shadows","getScoreClassNames","score","opacityNumber","Math","round","length","shadowNumber","FacePile","isMenuOpened","loggedInUser","useOptionalUser","users","usePresence","product","displayNameShort","useWorkshopConfig","limit","numberOverLimit","shouldShowNumberOverLimit","tiffany","Link","rel","to","alt","src","overLimitLabel","TooltipProvider","slice","map","user","scoreClassNames","locationLabel","getLocationLabel","location","Tooltip","TooltipTrigger","asChild","avatarUrl","tabIndex","name","TooltipContent","origin","includes","id","line1","line2","useIsWide","App","isWide","isHydrated","useHydrated","setMenuOpened","React","NoUserBanner","MobileNavigation","onMenuOpenChange","Navigation","Outlet","exercise","exercisePortion","exerciseNumber","stepNumber","filter","Boolean","s","toString","padStart","join","type","workshopTitle","host","displayName","details","ENV","EPICSHOP_DEPLOYED","EPICSHOP_GITHUB_REPO","href","Logo","size","style","itemVariants","hidden","opacity","x","visible","NavigationExerciseListItem","progressClassName","useExerciseProgressClassName","motion","li","variants","NavigationExerciseStepListItem","progressItemSearch","useProgressItemClassName","data","useLoaderData","nextExerciseRoute","useNextExerciseRoute","params","useParams","listVariants","transition","duration","when","staggerChildren","NavToggle","title","div","initial","animate","ul","exercises","steps","isActive","Number","showPlayground","playground","exerciseNum","prefetch","clsx","step","isPlayground","appName","NavLink","SimpleTooltip","email","state","from","ThemeSwitch","OPENED_MENU_WIDTH","find","e","app","solutions","problems","p","menuControls","menuVariants","close","width","exNum","menuButtonRef","path01Variants","d","closed","path02Variants","moving","path01Controls","path02Controls","toggleMenu","start","handleKeyUp","current","click","document","addEventListener","removeEventListener","onClick","height","viewBox","path","stroke","strokeWidth","delay","y"],"mappings":"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","x_google_ignoreList":[0,1,3]}
@@ -1,2 +1,2 @@
1
- import{j as e}from"./index-1cKOJFpX.js";import{B as a}from"./button-CQ6cnotS.js";import{I as i}from"./misc-Txs7O6JX.js";import{S as o}from"./tooltip-DTFU8ajx.js";import{u as m,a as u}from"./user-D6tTg1yS.js";import{u as x}from"./presence-Cr--lRCr.js";import{u as h,a as p,L as r,F as c}from"./components-CME-nGId.js";import"./request-info-CEhUGODY.js";const D={getSitemapEntries:()=>null};function O(){const l=h(),d=p(),t=m(),s=u(),n=x();return e.jsxs("main",{className:"container flex h-full w-full max-w-3xl flex-grow flex-col items-center justify-center gap-4",children:[e.jsx("img",{className:"h-36 w-36 rounded-full",alt:(s==null?void 0:s.displayName)??t.name??t.email,src:t.avatarUrl}),e.jsx("h1",{className:"mb-1 text-2xl",children:"Your Account"}),e.jsx("p",{className:"text-center text-gray-700 dark:text-gray-300",children:t.name?`Hi ${(s==null?void 0:s.displayName)??t.name}, your device is logged in with ${t.email}.`:`Your device is logged in with ${t.email}.`}),s?e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-center text-gray-700 dark:text-gray-300",children:["And you are connected to discord as ",s.displayName," (",s.id,")."]}),e.jsxs("div",{className:"flex justify-center gap-2",children:[e.jsx(d.Form,{method:"post",children:e.jsx(a,{varient:"mono",name:"intent",value:"disconnect-discord",children:"Disconnect Discord"})}),e.jsx(o,{content:"Your discord connection gives you access to the exclusive Discord channels for Epic Web",children:e.jsx(i,{name:"Question",tabIndex:0})})]})]}):e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(r,{to:l.discordAuthUrl,className:"inline-flex items-center gap-2 underline",children:[e.jsx(i,{name:"Discord",size:"lg"}),"Connect Discord"]}),e.jsx(o,{content:"This will give you access to the exclusive Discord channels for Epic Web",children:e.jsx(i,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(c,{method:"POST",children:[e.jsx("input",{name:"optOut",type:"hidden",value:n!=null&&n.optOut?"false":"true"}),e.jsxs(a,{varient:"mono",name:"intent",value:"presence-opt-out",children:[n!=null&&n.optOut?"Opt in to":"Opt out of"," presence"]})]}),e.jsx(o,{content:"This controls whether your name and avatar are displayed in the pile of faces in navigation",children:e.jsx(i,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(c,{method:"post",children:e.jsx(a,{varient:"mono",name:"intent",value:"logout",children:"Log device out"})}),e.jsx(o,{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(i,{name:"Question",tabIndex:0})})]}),e.jsxs("p",{children:["Check"," ",e.jsx(r,{to:"/onboarding",className:"underline",children:"/onboarding"})," ","if you'd like to review onboarding again."]}),e.jsxs("p",{children:["Check"," ",e.jsx(r,{to:"/support",className:"underline",children:"/support"})," ","if you need support."]})]})}export{O as default,D as handle};
2
- //# sourceMappingURL=account-DWhUP9x5.js.map
1
+ import{j as e}from"./index-1cKOJFpX.js";import{B as a}from"./button-CQ6cnotS.js";import{I as i}from"./misc-Txs7O6JX.js";import{S as o}from"./tooltip-DTFU8ajx.js";import{u as m,a as u}from"./user-DvujSs-t.js";import{u as x}from"./presence-Cr--lRCr.js";import{u as h,a as p,L as r,F as c}from"./components-CME-nGId.js";import"./request-info-CEhUGODY.js";const D={getSitemapEntries:()=>null};function O(){const l=h(),d=p(),t=m(),s=u(),n=x();return e.jsxs("main",{className:"container flex h-full w-full max-w-3xl flex-grow flex-col items-center justify-center gap-4",children:[e.jsx("img",{className:"h-36 w-36 rounded-full",alt:(s==null?void 0:s.displayName)??t.name??t.email,src:t.avatarUrl}),e.jsx("h1",{className:"mb-1 text-2xl",children:"Your Account"}),e.jsx("p",{className:"text-center text-gray-700 dark:text-gray-300",children:t.name?`Hi ${(s==null?void 0:s.displayName)??t.name}, your device is logged in with ${t.email}.`:`Your device is logged in with ${t.email}.`}),s?e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-center text-gray-700 dark:text-gray-300",children:["And you are connected to discord as ",s.displayName," (",s.id,")."]}),e.jsxs("div",{className:"flex justify-center gap-2",children:[e.jsx(d.Form,{method:"post",children:e.jsx(a,{varient:"mono",name:"intent",value:"disconnect-discord",children:"Disconnect Discord"})}),e.jsx(o,{content:"Your discord connection gives you access to the exclusive Discord channels for Epic Web",children:e.jsx(i,{name:"Question",tabIndex:0})})]})]}):e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(r,{to:l.discordAuthUrl,className:"inline-flex items-center gap-2 underline",children:[e.jsx(i,{name:"Discord",size:"lg"}),"Connect Discord"]}),e.jsx(o,{content:"This will give you access to the exclusive Discord channels for Epic Web",children:e.jsx(i,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(c,{method:"POST",children:[e.jsx("input",{name:"optOut",type:"hidden",value:n!=null&&n.optOut?"false":"true"}),e.jsxs(a,{varient:"mono",name:"intent",value:"presence-opt-out",children:[n!=null&&n.optOut?"Opt in to":"Opt out of"," presence"]})]}),e.jsx(o,{content:"This controls whether your name and avatar are displayed in the pile of faces in navigation",children:e.jsx(i,{name:"Question",tabIndex:0})})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(c,{method:"post",children:e.jsx(a,{varient:"mono",name:"intent",value:"logout",children:"Log device out"})}),e.jsx(o,{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(i,{name:"Question",tabIndex:0})})]}),e.jsxs("p",{children:["Check"," ",e.jsx(r,{to:"/onboarding",className:"underline",children:"/onboarding"})," ","if you'd like to review onboarding again."]}),e.jsxs("p",{children:["Check"," ",e.jsx(r,{to:"/support",className:"underline",children:"/support"})," ","if you need support."]})]})}export{O as default,D as handle};
2
+ //# sourceMappingURL=account-D1DCJCnR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"account-DWhUP9x5.js","sources":["../../../app/routes/_app+/account.tsx"],"sourcesContent":["import { deleteCache } from '@epic-web/workshop-utils/cache.server'\nimport {\n\tdeleteDb,\n\tdeleteDiscordInfo,\n\trequireAuthInfo,\n\tsetPresencePreferences,\n} from '@epic-web/workshop-utils/db.server'\nimport { type SEOHandle } from '@nasa-gcn/remix-seo'\nimport { json, redirect, type LoaderFunctionArgs } from '@remix-run/node'\nimport { Form, Link, useFetcher, useLoaderData } from '@remix-run/react'\nimport { Button } from '#app/components/button.tsx'\nimport { Icon } from '#app/components/icons.tsx'\nimport { SimpleTooltip } from '#app/components/ui/tooltip.js'\nimport { useOptionalDiscordMember, useUser } from '#app/components/user.tsx'\nimport { ensureUndeployed } from '#app/utils/misc.tsx'\nimport { usePresencePreferences } from '#app/utils/presence.tsx'\nimport { redirectWithToast } from '#app/utils/toast.server.ts'\nimport { getDiscordAuthURL } from '../discord.callback.ts'\n\nexport const handle: SEOHandle = {\n\tgetSitemapEntries: () => null,\n}\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tensureUndeployed()\n\tawait requireAuthInfo({ request })\n\treturn json({ discordAuthUrl: getDiscordAuthURL() })\n}\n\nexport async function action({ request }: { request: Request }) {\n\tensureUndeployed()\n\tconst formData = await request.formData()\n\tconst intent = formData.get('intent')\n\tif (intent === 'disconnect-discord') {\n\t\tawait deleteDiscordInfo()\n\t\treturn redirectWithToast('/account', {\n\t\t\ttype: 'success',\n\t\t\ttitle: 'Disconnected',\n\t\t\tdescription: 'Local discord data has been deleted.',\n\t\t})\n\t} else if (intent === 'logout') {\n\t\tawait deleteDb()\n\t\tawait deleteCache()\n\t\treturn redirectWithToast('/login', {\n\t\t\ttype: 'success',\n\t\t\ttitle: 'Logged out',\n\t\t\tdescription: 'Goodbye! Come back soon!',\n\t\t})\n\t} else if (intent === 'presence-opt-out') {\n\t\tconst optOut = formData.get('optOut') === 'true'\n\t\tawait setPresencePreferences({ optOut })\n\t\treturn redirectWithToast('/account', {\n\t\t\ttitle: optOut ? 'Opted out' : 'Opted in',\n\t\t\tdescription: `You are now ${optOut ? 'invisible' : 'visible'}.`,\n\t\t\ttype: 'success',\n\t\t})\n\t}\n\n\treturn redirect('/account')\n}\n\nexport default function Account() {\n\tconst data = useLoaderData<typeof loader>()\n\tconst disconnectFetcher = useFetcher()\n\tconst user = useUser()\n\tconst discordMember = useOptionalDiscordMember()\n\tconst presencePreferences = usePresencePreferences()\n\treturn (\n\t\t<main className=\"container flex h-full w-full max-w-3xl flex-grow flex-col items-center justify-center gap-4\">\n\t\t\t<img\n\t\t\t\tclassName=\"h-36 w-36 rounded-full\"\n\t\t\t\talt={discordMember?.displayName ?? user.name ?? user.email}\n\t\t\t\tsrc={user.avatarUrl}\n\t\t\t/>\n\t\t\t<h1 className=\"mb-1 text-2xl\">Your Account</h1>\n\t\t\t<p className=\"text-center text-gray-700 dark:text-gray-300\">\n\t\t\t\t{user.name\n\t\t\t\t\t? `Hi ${\n\t\t\t\t\t\t\tdiscordMember?.displayName ?? user.name\n\t\t\t\t\t\t}, your device is logged in with ${user.email}.`\n\t\t\t\t\t: `Your device is logged in with ${user.email}.`}\n\t\t\t</p>\n\t\t\t{discordMember ? (\n\t\t\t\t<>\n\t\t\t\t\t<p className=\"text-center text-gray-700 dark:text-gray-300\">\n\t\t\t\t\t\tAnd you are connected to discord as {discordMember.displayName} (\n\t\t\t\t\t\t{discordMember.id}).\n\t\t\t\t\t</p>\n\t\t\t\t\t<div className=\"flex justify-center gap-2\">\n\t\t\t\t\t\t<disconnectFetcher.Form method=\"post\">\n\t\t\t\t\t\t\t<Button varient=\"mono\" name=\"intent\" value=\"disconnect-discord\">\n\t\t\t\t\t\t\t\tDisconnect Discord\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</disconnectFetcher.Form>\n\t\t\t\t\t\t<SimpleTooltip content=\"Your discord connection gives you access to the exclusive Discord channels for Epic Web\">\n\t\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto={data.discordAuthUrl}\n\t\t\t\t\t\tclassName=\"inline-flex items-center gap-2 underline\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon name=\"Discord\" size=\"lg\" />\n\t\t\t\t\t\tConnect Discord\n\t\t\t\t\t</Link>\n\t\t\t\t\t<SimpleTooltip content=\"This will give you access to the exclusive Discord channels for Epic Web\">\n\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<Form method=\"POST\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tname=\"optOut\"\n\t\t\t\t\t\ttype=\"hidden\"\n\t\t\t\t\t\tvalue={presencePreferences?.optOut ? 'false' : 'true'}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button varient=\"mono\" name=\"intent\" value=\"presence-opt-out\">\n\t\t\t\t\t\t{presencePreferences?.optOut ? 'Opt in to' : 'Opt out of'} presence\n\t\t\t\t\t</Button>\n\t\t\t\t</Form>\n\t\t\t\t<SimpleTooltip content=\"This controls whether your name and avatar are displayed in the pile of faces in navigation\">\n\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t</SimpleTooltip>\n\t\t\t</div>\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<Form method=\"post\">\n\t\t\t\t\t<Button varient=\"mono\" name=\"intent\" value=\"logout\">\n\t\t\t\t\t\tLog device out\n\t\t\t\t\t</Button>\n\t\t\t\t</Form>\n\t\t\t\t<SimpleTooltip\n\t\t\t\t\tcontent={\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\tNote: it is your <i className=\"italic\">device</i> that's logged\n\t\t\t\t\t\t\tin, not your browser.\n\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\tSo all browsers on this device will be logged in with the same\n\t\t\t\t\t\t\taccount on this device.\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t</SimpleTooltip>\n\t\t\t</div>\n\t\t\t<p>\n\t\t\t\tCheck{' '}\n\t\t\t\t<Link to=\"/onboarding\" className=\"underline\">\n\t\t\t\t\t/onboarding\n\t\t\t\t</Link>{' '}\n\t\t\t\tif you'd like to review onboarding again.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tCheck{' '}\n\t\t\t\t<Link to=\"/support\" className=\"underline\">\n\t\t\t\t\t/support\n\t\t\t\t</Link>{' '}\n\t\t\t\tif you need support.\n\t\t\t</p>\n\t\t</main>\n\t)\n}\n"],"names":["handle","getSitemapEntries","Account","data","useLoaderData","disconnectFetcher","useFetcher","user","useUser","discordMember","useOptionalDiscordMember","presencePreferences","usePresencePreferences","jsxs","className","children","jsx","alt","displayName","name","email","src","avatarUrl","Fragment","id","Form","method","Button","varient","value","SimpleTooltip","content","Icon","tabIndex","Link","to","discordAuthUrl","size","type","optOut"],"mappings":"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"}
1
+ {"version":3,"file":"account-D1DCJCnR.js","sources":["../../../app/routes/_app+/account.tsx"],"sourcesContent":["import { deleteCache } from '@epic-web/workshop-utils/cache.server'\nimport {\n\tdeleteDb,\n\tdeleteDiscordInfo,\n\trequireAuthInfo,\n\tsetPresencePreferences,\n} from '@epic-web/workshop-utils/db.server'\nimport { type SEOHandle } from '@nasa-gcn/remix-seo'\nimport { json, redirect, type LoaderFunctionArgs } from '@remix-run/node'\nimport { Form, Link, useFetcher, useLoaderData } from '@remix-run/react'\nimport { Button } from '#app/components/button.tsx'\nimport { Icon } from '#app/components/icons.tsx'\nimport { SimpleTooltip } from '#app/components/ui/tooltip.js'\nimport { useOptionalDiscordMember, useUser } from '#app/components/user.tsx'\nimport { ensureUndeployed } from '#app/utils/misc.tsx'\nimport { usePresencePreferences } from '#app/utils/presence.tsx'\nimport { redirectWithToast } from '#app/utils/toast.server.ts'\nimport { getDiscordAuthURL } from '../discord.callback.ts'\n\nexport const handle: SEOHandle = {\n\tgetSitemapEntries: () => null,\n}\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n\tensureUndeployed()\n\tawait requireAuthInfo({ request })\n\treturn json({ discordAuthUrl: getDiscordAuthURL() })\n}\n\nexport async function action({ request }: { request: Request }) {\n\tensureUndeployed()\n\tconst formData = await request.formData()\n\tconst intent = formData.get('intent')\n\tif (intent === 'disconnect-discord') {\n\t\tawait deleteDiscordInfo()\n\t\treturn redirectWithToast('/account', {\n\t\t\ttype: 'success',\n\t\t\ttitle: 'Disconnected',\n\t\t\tdescription: 'Local discord data has been deleted.',\n\t\t})\n\t} else if (intent === 'logout') {\n\t\tawait deleteDb()\n\t\tawait deleteCache()\n\t\treturn redirectWithToast('/login', {\n\t\t\ttype: 'success',\n\t\t\ttitle: 'Logged out',\n\t\t\tdescription: 'Goodbye! Come back soon!',\n\t\t})\n\t} else if (intent === 'presence-opt-out') {\n\t\tconst optOut = formData.get('optOut') === 'true'\n\t\tawait setPresencePreferences({ optOut })\n\t\treturn redirectWithToast('/account', {\n\t\t\ttitle: optOut ? 'Opted out' : 'Opted in',\n\t\t\tdescription: `You are now ${optOut ? 'invisible' : 'visible'}.`,\n\t\t\ttype: 'success',\n\t\t})\n\t}\n\n\treturn redirect('/account')\n}\n\nexport default function Account() {\n\tconst data = useLoaderData<typeof loader>()\n\tconst disconnectFetcher = useFetcher()\n\tconst user = useUser()\n\tconst discordMember = useOptionalDiscordMember()\n\tconst presencePreferences = usePresencePreferences()\n\treturn (\n\t\t<main className=\"container flex h-full w-full max-w-3xl flex-grow flex-col items-center justify-center gap-4\">\n\t\t\t<img\n\t\t\t\tclassName=\"h-36 w-36 rounded-full\"\n\t\t\t\talt={discordMember?.displayName ?? user.name ?? user.email}\n\t\t\t\tsrc={user.avatarUrl}\n\t\t\t/>\n\t\t\t<h1 className=\"mb-1 text-2xl\">Your Account</h1>\n\t\t\t<p className=\"text-center text-gray-700 dark:text-gray-300\">\n\t\t\t\t{user.name\n\t\t\t\t\t? `Hi ${\n\t\t\t\t\t\t\tdiscordMember?.displayName ?? user.name\n\t\t\t\t\t\t}, your device is logged in with ${user.email}.`\n\t\t\t\t\t: `Your device is logged in with ${user.email}.`}\n\t\t\t</p>\n\t\t\t{discordMember ? (\n\t\t\t\t<>\n\t\t\t\t\t<p className=\"text-center text-gray-700 dark:text-gray-300\">\n\t\t\t\t\t\tAnd you are connected to discord as {discordMember.displayName} (\n\t\t\t\t\t\t{discordMember.id}).\n\t\t\t\t\t</p>\n\t\t\t\t\t<div className=\"flex justify-center gap-2\">\n\t\t\t\t\t\t<disconnectFetcher.Form method=\"post\">\n\t\t\t\t\t\t\t<Button varient=\"mono\" name=\"intent\" value=\"disconnect-discord\">\n\t\t\t\t\t\t\t\tDisconnect Discord\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</disconnectFetcher.Form>\n\t\t\t\t\t\t<SimpleTooltip content=\"Your discord connection gives you access to the exclusive Discord channels for Epic Web\">\n\t\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<Link\n\t\t\t\t\t\tto={data.discordAuthUrl}\n\t\t\t\t\t\tclassName=\"inline-flex items-center gap-2 underline\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon name=\"Discord\" size=\"lg\" />\n\t\t\t\t\t\tConnect Discord\n\t\t\t\t\t</Link>\n\t\t\t\t\t<SimpleTooltip content=\"This will give you access to the exclusive Discord channels for Epic Web\">\n\t\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t\t</SimpleTooltip>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<Form method=\"POST\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tname=\"optOut\"\n\t\t\t\t\t\ttype=\"hidden\"\n\t\t\t\t\t\tvalue={presencePreferences?.optOut ? 'false' : 'true'}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button varient=\"mono\" name=\"intent\" value=\"presence-opt-out\">\n\t\t\t\t\t\t{presencePreferences?.optOut ? 'Opt in to' : 'Opt out of'} presence\n\t\t\t\t\t</Button>\n\t\t\t\t</Form>\n\t\t\t\t<SimpleTooltip content=\"This controls whether your name and avatar are displayed in the pile of faces in navigation\">\n\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t</SimpleTooltip>\n\t\t\t</div>\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<Form method=\"post\">\n\t\t\t\t\t<Button varient=\"mono\" name=\"intent\" value=\"logout\">\n\t\t\t\t\t\tLog device out\n\t\t\t\t\t</Button>\n\t\t\t\t</Form>\n\t\t\t\t<SimpleTooltip\n\t\t\t\t\tcontent={\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\tNote: it is your <i className=\"italic\">device</i> that's logged\n\t\t\t\t\t\t\tin, not your browser.\n\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\tSo all browsers on this device will be logged in with the same\n\t\t\t\t\t\t\taccount on this device.\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<Icon name=\"Question\" tabIndex={0} />\n\t\t\t\t</SimpleTooltip>\n\t\t\t</div>\n\t\t\t<p>\n\t\t\t\tCheck{' '}\n\t\t\t\t<Link to=\"/onboarding\" className=\"underline\">\n\t\t\t\t\t/onboarding\n\t\t\t\t</Link>{' '}\n\t\t\t\tif you'd like to review onboarding again.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tCheck{' '}\n\t\t\t\t<Link to=\"/support\" className=\"underline\">\n\t\t\t\t\t/support\n\t\t\t\t</Link>{' '}\n\t\t\t\tif you need support.\n\t\t\t</p>\n\t\t</main>\n\t)\n}\n"],"names":["handle","getSitemapEntries","Account","data","useLoaderData","disconnectFetcher","useFetcher","user","useUser","discordMember","useOptionalDiscordMember","presencePreferences","usePresencePreferences","jsxs","className","children","jsx","alt","displayName","name","email","src","avatarUrl","Fragment","id","Form","method","Button","varient","value","SimpleTooltip","content","Icon","tabIndex","Link","to","discordAuthUrl","size","type","optOut"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{c as o,j as r}from"./index-1cKOJFpX.js";import{d as e,a as m}from"./misc-Txs7O6JX.js";import{D as p}from"./diff-B5EME8RQ.js";import{N as n}from"./nav-chevrons-Cbc1bd_j.js";import{u as f,b as c}from"./components-CME-nGId.js";import"./accordion-CKwXYK9L.js";import"./tooltip-DTFU8ajx.js";import"./index-9dWszLxO.js";import"./index-j_VpxCZh.js";import"./mdx-CGcvotZI.js";import"./epic-video-CzGRLoYH.js";import"./index-DlJAkutV.js";import"./request-info-CEhUGODY.js";import"./pe-CUZaIcdt.js";import"./loading-CF7oQHQf.js";import"./user-D6tTg1yS.js";import"./workshop-config-CL4F08kr.js";import"./progress-bar-bUuKn1Q8.js";function E(){const i=f(),[s]=c();new URLSearchParams(s).set("forceFresh","diff");const t=o(),a=e.useSpinDelay(t.state!=="idle",{delay:200,minDuration:200});return r.jsxs("div",{className:m("grid h-full grid-rows-[1fr,auto]",{"cursor-wait opacity-30":a}),children:[r.jsx("div",{className:"overflow-y-auto",children:r.jsx(p,{diff:i.diff,allApps:i.allApps})}),r.jsx("div",{className:"flex h-16 items-center justify-end border-t",children:r.jsx(n,{prev:i.prevLink,next:i.nextLink})})]})}export{E as default};
2
- //# sourceMappingURL=diff-CKxYA_sC.js.map
1
+ import{c as o,j as r}from"./index-1cKOJFpX.js";import{d as e,a as m}from"./misc-Txs7O6JX.js";import{D as p}from"./diff-hoOood-9.js";import{N as n}from"./nav-chevrons-Cbc1bd_j.js";import{u as f,b as c}from"./components-CME-nGId.js";import"./accordion-CKwXYK9L.js";import"./tooltip-DTFU8ajx.js";import"./index-9dWszLxO.js";import"./index-j_VpxCZh.js";import"./mdx-DvqHp8UI.js";import"./epic-video-BFcdejfC.js";import"./index-DlJAkutV.js";import"./request-info-CEhUGODY.js";import"./pe-CUZaIcdt.js";import"./loading-CF7oQHQf.js";import"./user-DvujSs-t.js";import"./workshop-config-CL4F08kr.js";import"./progress-bar-bUuKn1Q8.js";function E(){const i=f(),[s]=c();new URLSearchParams(s).set("forceFresh","diff");const t=o(),a=e.useSpinDelay(t.state!=="idle",{delay:200,minDuration:200});return r.jsxs("div",{className:m("grid h-full grid-rows-[1fr,auto]",{"cursor-wait opacity-30":a}),children:[r.jsx("div",{className:"overflow-y-auto",children:r.jsx(p,{diff:i.diff,allApps:i.allApps})}),r.jsx("div",{className:"flex h-16 items-center justify-end border-t",children:r.jsx(n,{prev:i.prevLink,next:i.nextLink})})]})}export{E as default};
2
+ //# sourceMappingURL=diff-CU8At1c4.js.map