@epic-web/workshop-app 6.23.2 → 6.23.4
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.
- package/build/client/assets/{index-BQT6Cv4C.js → index-D4FRh1nQ.js} +2 -2
- package/build/client/assets/index-D4FRh1nQ.js.map +1 -0
- package/build/client/assets/{manifest-5865a9d7.js → manifest-8a795ec6.js} +1 -1
- package/build/server/index.js +6 -3
- package/build/server/index.js.map +1 -1
- package/package.json +3 -3
- package/build/client/assets/index-BQT6Cv4C.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epic-web/workshop-app",
|
|
3
|
-
"version": "6.23.
|
|
3
|
+
"version": "6.23.4",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"@epic-web/invariant": "^1.0.0",
|
|
42
42
|
"@epic-web/remember": "^1.1.0",
|
|
43
43
|
"@epic-web/restore-scroll": "^2.0.0",
|
|
44
|
-
"@epic-web/workshop-presence": "6.23.
|
|
45
|
-
"@epic-web/workshop-utils": "6.23.
|
|
44
|
+
"@epic-web/workshop-presence": "6.23.4",
|
|
45
|
+
"@epic-web/workshop-utils": "6.23.4",
|
|
46
46
|
"@mdx-js/mdx": "^3.1.0",
|
|
47
47
|
"@mux/mux-player-react": "^3.5.0",
|
|
48
48
|
"@nasa-gcn/remix-seo": "^2.0.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BQT6Cv4C.js","sources":["../../../../../node_modules/@radix-ui/react-roving-focus/dist/index.mjs","../../../../../node_modules/@radix-ui/react-tabs/dist/index.mjs","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/discord.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/playground.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index.tsx"],"sourcesContent":["\"use client\";\n\n// src/roving-focus-group.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { createCollection } from \"@radix-ui/react-collection\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { jsx } from \"react/jsx-runtime\";\nvar ENTRY_FOCUS = \"rovingFocusGroup.onEntryFocus\";\nvar EVENT_OPTIONS = { bubbles: false, cancelable: true };\nvar GROUP_NAME = \"RovingFocusGroup\";\nvar [Collection, useCollection, createCollectionScope] = createCollection(GROUP_NAME);\nvar [createRovingFocusGroupContext, createRovingFocusGroupScope] = createContextScope(\n GROUP_NAME,\n [createCollectionScope]\n);\nvar [RovingFocusProvider, useRovingFocusContext] = createRovingFocusGroupContext(GROUP_NAME);\nvar RovingFocusGroup = React.forwardRef(\n (props, forwardedRef) => {\n return /* @__PURE__ */ jsx(Collection.Provider, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx(Collection.Slot, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx(RovingFocusGroupImpl, { ...props, ref: forwardedRef }) }) });\n }\n);\nRovingFocusGroup.displayName = GROUP_NAME;\nvar RovingFocusGroupImpl = React.forwardRef((props, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n orientation,\n loop = false,\n dir,\n currentTabStopId: currentTabStopIdProp,\n defaultCurrentTabStopId,\n onCurrentTabStopIdChange,\n onEntryFocus,\n preventScrollOnEntryFocus = false,\n ...groupProps\n } = props;\n const ref = React.useRef(null);\n const composedRefs = useComposedRefs(forwardedRef, ref);\n const direction = useDirection(dir);\n const [currentTabStopId, setCurrentTabStopId] = useControllableState({\n prop: currentTabStopIdProp,\n defaultProp: defaultCurrentTabStopId ?? null,\n onChange: onCurrentTabStopIdChange,\n caller: GROUP_NAME\n });\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const handleEntryFocus = useCallbackRef(onEntryFocus);\n const getItems = useCollection(__scopeRovingFocusGroup);\n const isClickFocusRef = React.useRef(false);\n const [focusableItemsCount, setFocusableItemsCount] = React.useState(0);\n React.useEffect(() => {\n const node = ref.current;\n if (node) {\n node.addEventListener(ENTRY_FOCUS, handleEntryFocus);\n return () => node.removeEventListener(ENTRY_FOCUS, handleEntryFocus);\n }\n }, [handleEntryFocus]);\n return /* @__PURE__ */ jsx(\n RovingFocusProvider,\n {\n scope: __scopeRovingFocusGroup,\n orientation,\n dir: direction,\n loop,\n currentTabStopId,\n onItemFocus: React.useCallback(\n (tabStopId) => setCurrentTabStopId(tabStopId),\n [setCurrentTabStopId]\n ),\n onItemShiftTab: React.useCallback(() => setIsTabbingBackOut(true), []),\n onFocusableItemAdd: React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount + 1),\n []\n ),\n onFocusableItemRemove: React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount - 1),\n []\n ),\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n tabIndex: isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0,\n \"data-orientation\": orientation,\n ...groupProps,\n ref: composedRefs,\n style: { outline: \"none\", ...props.style },\n onMouseDown: composeEventHandlers(props.onMouseDown, () => {\n isClickFocusRef.current = true;\n }),\n onFocus: composeEventHandlers(props.onFocus, (event) => {\n const isKeyboardFocus = !isClickFocusRef.current;\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n if (!entryFocusEvent.defaultPrevented) {\n const items = getItems().filter((item) => item.focusable);\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === currentTabStopId);\n const candidateItems = [activeItem, currentItem, ...items].filter(\n Boolean\n );\n const candidateNodes = candidateItems.map((item) => item.ref.current);\n focusFirst(candidateNodes, preventScrollOnEntryFocus);\n }\n }\n isClickFocusRef.current = false;\n }),\n onBlur: composeEventHandlers(props.onBlur, () => setIsTabbingBackOut(false))\n }\n )\n }\n );\n});\nvar ITEM_NAME = \"RovingFocusGroupItem\";\nvar RovingFocusGroupItem = React.forwardRef(\n (props, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n focusable = true,\n active = false,\n tabStopId,\n children,\n ...itemProps\n } = props;\n const autoId = useId();\n const id = tabStopId || autoId;\n const context = useRovingFocusContext(ITEM_NAME, __scopeRovingFocusGroup);\n const isCurrentTabStop = context.currentTabStopId === id;\n const getItems = useCollection(__scopeRovingFocusGroup);\n const { onFocusableItemAdd, onFocusableItemRemove, currentTabStopId } = context;\n React.useEffect(() => {\n if (focusable) {\n onFocusableItemAdd();\n return () => onFocusableItemRemove();\n }\n }, [focusable, onFocusableItemAdd, onFocusableItemRemove]);\n return /* @__PURE__ */ jsx(\n Collection.ItemSlot,\n {\n scope: __scopeRovingFocusGroup,\n id,\n focusable,\n active,\n children: /* @__PURE__ */ jsx(\n Primitive.span,\n {\n tabIndex: isCurrentTabStop ? 0 : -1,\n \"data-orientation\": context.orientation,\n ...itemProps,\n ref: forwardedRef,\n onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {\n if (!focusable) event.preventDefault();\n else context.onItemFocus(id);\n }),\n onFocus: composeEventHandlers(props.onFocus, () => context.onItemFocus(id)),\n onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {\n if (event.key === \"Tab\" && event.shiftKey) {\n context.onItemShiftTab();\n return;\n }\n if (event.target !== event.currentTarget) return;\n const focusIntent = getFocusIntent(event, context.orientation, context.dir);\n if (focusIntent !== void 0) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n const items = getItems().filter((item) => item.focusable);\n let candidateNodes = items.map((item) => item.ref.current);\n if (focusIntent === \"last\") candidateNodes.reverse();\n else if (focusIntent === \"prev\" || focusIntent === \"next\") {\n if (focusIntent === \"prev\") candidateNodes.reverse();\n const currentIndex = candidateNodes.indexOf(event.currentTarget);\n candidateNodes = context.loop ? wrapArray(candidateNodes, currentIndex + 1) : candidateNodes.slice(currentIndex + 1);\n }\n setTimeout(() => focusFirst(candidateNodes));\n }\n }),\n children: typeof children === \"function\" ? children({ isCurrentTabStop, hasTabStop: currentTabStopId != null }) : children\n }\n )\n }\n );\n }\n);\nRovingFocusGroupItem.displayName = ITEM_NAME;\nvar MAP_KEY_TO_FOCUS_INTENT = {\n ArrowLeft: \"prev\",\n ArrowUp: \"prev\",\n ArrowRight: \"next\",\n ArrowDown: \"next\",\n PageUp: \"first\",\n Home: \"first\",\n PageDown: \"last\",\n End: \"last\"\n};\nfunction getDirectionAwareKey(key, dir) {\n if (dir !== \"rtl\") return key;\n return key === \"ArrowLeft\" ? \"ArrowRight\" : key === \"ArrowRight\" ? \"ArrowLeft\" : key;\n}\nfunction getFocusIntent(event, orientation, dir) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === \"vertical\" && [\"ArrowLeft\", \"ArrowRight\"].includes(key)) return void 0;\n if (orientation === \"horizontal\" && [\"ArrowUp\", \"ArrowDown\"].includes(key)) return void 0;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\nfunction focusFirst(candidates, preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidate of candidates) {\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\nfunction wrapArray(array, startIndex) {\n return array.map((_, index) => array[(startIndex + index) % array.length]);\n}\nvar Root = RovingFocusGroup;\nvar Item = RovingFocusGroupItem;\nexport {\n Item,\n Root,\n RovingFocusGroup,\n RovingFocusGroupItem,\n createRovingFocusGroupScope\n};\n//# sourceMappingURL=index.mjs.map\n","\"use client\";\n\n// src/tabs.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { createRovingFocusGroupScope } from \"@radix-ui/react-roving-focus\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as RovingFocusGroup from \"@radix-ui/react-roving-focus\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { jsx } from \"react/jsx-runtime\";\nvar TABS_NAME = \"Tabs\";\nvar [createTabsContext, createTabsScope] = createContextScope(TABS_NAME, [\n createRovingFocusGroupScope\n]);\nvar useRovingFocusGroupScope = createRovingFocusGroupScope();\nvar [TabsProvider, useTabsContext] = createTabsContext(TABS_NAME);\nvar Tabs = React.forwardRef(\n (props, forwardedRef) => {\n const {\n __scopeTabs,\n value: valueProp,\n onValueChange,\n defaultValue,\n orientation = \"horizontal\",\n dir,\n activationMode = \"automatic\",\n ...tabsProps\n } = props;\n const direction = useDirection(dir);\n const [value, setValue] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n defaultProp: defaultValue ?? \"\",\n caller: TABS_NAME\n });\n return /* @__PURE__ */ jsx(\n TabsProvider,\n {\n scope: __scopeTabs,\n baseId: useId(),\n value,\n onValueChange: setValue,\n orientation,\n dir: direction,\n activationMode,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n dir: direction,\n \"data-orientation\": orientation,\n ...tabsProps,\n ref: forwardedRef\n }\n )\n }\n );\n }\n);\nTabs.displayName = TABS_NAME;\nvar TAB_LIST_NAME = \"TabsList\";\nvar TabsList = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, loop = true, ...listProps } = props;\n const context = useTabsContext(TAB_LIST_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Root,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n orientation: context.orientation,\n dir: context.dir,\n loop,\n children: /* @__PURE__ */ jsx(\n Primitive.div,\n {\n role: \"tablist\",\n \"aria-orientation\": context.orientation,\n ...listProps,\n ref: forwardedRef\n }\n )\n }\n );\n }\n);\nTabsList.displayName = TAB_LIST_NAME;\nvar TRIGGER_NAME = \"TabsTrigger\";\nvar TabsTrigger = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, value, disabled = false, ...triggerProps } = props;\n const context = useTabsContext(TRIGGER_NAME, __scopeTabs);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n return /* @__PURE__ */ jsx(\n RovingFocusGroup.Item,\n {\n asChild: true,\n ...rovingFocusGroupScope,\n focusable: !disabled,\n active: isSelected,\n children: /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n role: \"tab\",\n \"aria-selected\": isSelected,\n \"aria-controls\": contentId,\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-disabled\": disabled ? \"\" : void 0,\n disabled,\n id: triggerId,\n ...triggerProps,\n ref: forwardedRef,\n onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {\n if (!disabled && event.button === 0 && event.ctrlKey === false) {\n context.onValueChange(value);\n } else {\n event.preventDefault();\n }\n }),\n onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {\n if ([\" \", \"Enter\"].includes(event.key)) context.onValueChange(value);\n }),\n onFocus: composeEventHandlers(props.onFocus, () => {\n const isAutomaticActivation = context.activationMode !== \"manual\";\n if (!isSelected && !disabled && isAutomaticActivation) {\n context.onValueChange(value);\n }\n })\n }\n )\n }\n );\n }\n);\nTabsTrigger.displayName = TRIGGER_NAME;\nvar CONTENT_NAME = \"TabsContent\";\nvar TabsContent = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopeTabs, value, forceMount, children, ...contentProps } = props;\n const context = useTabsContext(CONTENT_NAME, __scopeTabs);\n const triggerId = makeTriggerId(context.baseId, value);\n const contentId = makeContentId(context.baseId, value);\n const isSelected = value === context.value;\n const isMountAnimationPreventedRef = React.useRef(isSelected);\n React.useEffect(() => {\n const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);\n return () => cancelAnimationFrame(rAF);\n }, []);\n return /* @__PURE__ */ jsx(Presence, { present: forceMount || isSelected, children: ({ present }) => /* @__PURE__ */ jsx(\n Primitive.div,\n {\n \"data-state\": isSelected ? \"active\" : \"inactive\",\n \"data-orientation\": context.orientation,\n role: \"tabpanel\",\n \"aria-labelledby\": triggerId,\n hidden: !present,\n id: contentId,\n tabIndex: 0,\n ...contentProps,\n ref: forwardedRef,\n style: {\n ...props.style,\n animationDuration: isMountAnimationPreventedRef.current ? \"0s\" : void 0\n },\n children: present && children\n }\n ) });\n }\n);\nTabsContent.displayName = CONTENT_NAME;\nfunction makeTriggerId(baseId, value) {\n return `${baseId}-trigger-${value}`;\n}\nfunction makeContentId(baseId, value) {\n return `${baseId}-content-${value}`;\n}\nvar Root2 = Tabs;\nvar List = TabsList;\nvar Trigger = TabsTrigger;\nvar Content = TabsContent;\nexport {\n Content,\n List,\n Root2 as Root,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Trigger,\n createTabsScope\n};\n//# sourceMappingURL=index.mjs.map\n","import * as React from 'react'\nimport { Await, Link, useLoaderData } from 'react-router'\nimport { Icon } from '#app/components/icons.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { DiscordCTA, useDiscordCTALink } from '#app/routes/_app+/discord.tsx'\nimport { useAltDown } from '#app/utils/misc.tsx'\nimport { useIsOnline } from '#app/utils/online.ts'\nimport { type Route } from '../+types/index.tsx'\n\nexport function DiscordChat() {\n\treturn (\n\t\t<div className=\"flex h-full w-full flex-col gap-4 pt-4\">\n\t\t\t<div className=\"text-center\">\n\t\t\t\t<DiscordCTA />\n\t\t\t</div>\n\t\t\t<div className=\"flex-1 overflow-y-scroll bg-accent pb-4 scrollbar-thin scrollbar-thumb-scrollbar\">\n\t\t\t\t<DiscordPosts />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction DiscordPosts() {\n\tconst data = useLoaderData<Route.ComponentProps['loaderData']>()\n\tconst ctaLink = useDiscordCTALink()\n\tconst altDown = useAltDown()\n\tconst isOnline = useIsOnline()\n\tif (!isOnline) {\n\t\treturn (\n\t\t\t<div className=\"flex h-full flex-col items-center justify-between\">\n\t\t\t\t<div className=\"flex h-full w-full flex-col items-center justify-center text-foreground-destructive\">\n\t\t\t\t\t<Icon name=\"WifiNoConnection\" size=\"xl\">\n\t\t\t\t\t\tUnable to load discord messages when offline\n\t\t\t\t\t</Icon>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\treturn (\n\t\t<div className=\"flex h-full flex-col items-center justify-between\">\n\t\t\t<React.Suspense\n\t\t\t\tfallback={\n\t\t\t\t\t<div className=\"flex h-full w-full flex-col items-center justify-center\">\n\t\t\t\t\t\t<Loading>Loading Discord Posts</Loading>\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t<Await\n\t\t\t\t\tresolve={data.discordPostsPromise}\n\t\t\t\t\terrorElement={\n\t\t\t\t\t\t<div className=\"text-red-500\">\n\t\t\t\t\t\t\tThere was a problem loading the discord posts\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t{(posts) => (\n\t\t\t\t\t\t<ul className=\"flex w-full flex-col gap-4 p-3 xl:p-12\">\n\t\t\t\t\t\t\t{posts.map((post) => (\n\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\tkey={post.id}\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-xl border bg-background transition-all duration-200 focus-within:-translate-y-1 focus-within:shadow-lg hover:-translate-y-1 hover:shadow-lg\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<DiscordPost thread={post} />\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</Await>\n\t\t\t</React.Suspense>\n\t\t\t<div>\n\t\t\t\t<Link\n\t\t\t\t\tto={\n\t\t\t\t\t\taltDown && !ctaLink.includes('oauth')\n\t\t\t\t\t\t\t? ctaLink.replace(/^https/, 'discord')\n\t\t\t\t\t\t\t: ctaLink\n\t\t\t\t\t}\n\t\t\t\t\ttarget={ctaLink.includes('oauth') ? undefined : '_blank'}\n\t\t\t\t\trel=\"noreferrer noopener\"\n\t\t\t\t\tonClick={\n\t\t\t\t\t\taltDown\n\t\t\t\t\t\t\t? (e) => {\n\t\t\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\t\t\twindow.open(\n\t\t\t\t\t\t\t\t\t\te.currentTarget.href,\n\t\t\t\t\t\t\t\t\t\t'_blank',\n\t\t\t\t\t\t\t\t\t\t'noreferrer noopener',\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tclassName=\"flex items-center gap-2 p-2 text-xl hover:underline\"\n\t\t\t\t>\n\t\t\t\t\tCreate Post <Icon name=\"ExternalLink\" />\n\t\t\t\t</Link>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction DiscordPost({\n\tthread,\n}: {\n\tthread: Awaited<\n\t\tRoute.ComponentProps['loaderData']['discordPostsPromise']\n\t>[number]\n}) {\n\tconst reactionsWithCounts = thread.reactions.filter((r) => r.count)\n\n\treturn (\n\t\t<div>\n\t\t\t<div className=\"flex flex-col gap-2 p-4\">\n\t\t\t\t<div className=\"flex gap-4\">\n\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t{thread.tags.length ? (\n\t\t\t\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t\t\t\t{thread.tags.map((t) => (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tkey={t.name}\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-center gap-1 rounded-full bg-accent px-2 py-1 text-sm\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span className=\"h-3 w-3 leading-3\">\n\t\t\t\t\t\t\t\t\t\t\t<Emoji name={t.emojiName} url={t.emojiUrl} />\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t<span>{t.name}</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t<strong className=\"text-xl font-bold\">{thread.name}</strong>\n\t\t\t\t\t\t<div className=\"flex items-start gap-1\">\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t\t{thread.authorAvatarUrl ? (\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tsrc={thread.authorAvatarUrl}\n\t\t\t\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6 rounded-full\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclassName=\"font-bold\"\n\t\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\t\tthread.authorHexAccentColor\n\t\t\t\t\t\t\t\t\t\t\t\t? { color: thread.authorHexAccentColor }\n\t\t\t\t\t\t\t\t\t\t\t\t: {}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{thread.authorDisplayName}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t:{' '}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<span className=\"flex-1 overflow-ellipsis text-muted-foreground\">\n\t\t\t\t\t\t\t\t{thread.messagePreview}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{thread.previewImageUrl ? (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={thread.previewImageUrl}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tclassName=\"h-28 w-28 rounded-lg object-cover\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"flex justify-between\">\n\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t{reactionsWithCounts.length ? (\n\t\t\t\t\t\t\t\t<ul className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t{reactionsWithCounts.map((r, i) => (\n\t\t\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center gap-1 rounded-md border border-blue-600 bg-blue-500/20 px-[5px] py-[0.5px] text-sm\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"h-3 w-3 leading-3\">\n\t\t\t\t\t\t\t\t\t\t\t\t<Emoji name={r.emojiName} url={r.emojiUrl} />\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t<span>{r.count}</span>\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t<span className=\"inline-flex items-center gap-1\">\n\t\t\t\t\t\t\t\t<Icon name=\"Chat\" /> {thread.messageCount}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{` · ${thread.lastUpdatedDisplay}`}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span className=\"flex items-center gap-4\">\n\t\t\t\t\t\t<a href={thread.link.replace(/^https/, 'discord')}>\n\t\t\t\t\t\t\t<Icon name=\"Discord\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t<a href={thread.link} target=\"_blank\" rel=\"noreferrer noopener\">\n\t\t\t\t\t\t\t<Icon name=\"ExternalLink\" />\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nfunction Emoji({ name, url }: { name?: string; url?: string }) {\n\treturn url ? (\n\t\t<img src={url} alt={name} className=\"h-full w-full\" />\n\t) : name ? (\n\t\tname\n\t) : null\n}\n","import { toast as showToast } from 'sonner'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser'\nimport { SimpleTooltip } from '#app/components/ui/tooltip'\nimport { SetAppToPlayground } from '#app/routes/set-playground'\nimport { PlaygroundWindow } from './playground-window'\nimport { Preview } from './preview'\n\nexport function Playground({\n\tappInfo: playgroundAppInfo,\n\tinBrowserBrowserRef,\n\tproblemAppName,\n\tallApps,\n\tisUpToDate,\n}: {\n\tappInfo: Parameters<typeof Preview>['0']['appInfo'] | null\n\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n\tproblemAppName?: string\n\tallApps: Array<{ name: string; displayName: string }>\n\tisUpToDate: boolean\n}) {\n\treturn (\n\t\t<PlaygroundWindow\n\t\t\tplaygroundAppName={playgroundAppInfo?.appName}\n\t\t\tproblemAppName={problemAppName}\n\t\t\tallApps={allApps}\n\t\t\tisUpToDate={isUpToDate}\n\t\t>\n\t\t\t{playgroundAppInfo?.dev.type === 'none' ? (\n\t\t\t\t<div>\n\t\t\t\t\t<div className=\"text-foreground-secondary flex h-full items-center justify-center text-2xl\">\n\t\t\t\t\t\tNon-UI playground\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"text-foreground-secondary flex flex-wrap gap-1 text-center\">\n\t\t\t\t\t\t\tNavigate to{' '}\n\t\t\t\t\t\t\t<SimpleTooltip content={playgroundAppInfo.fullPath}>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tvoid navigator.clipboard.writeText(\n\t\t\t\t\t\t\t\t\t\t\tplaygroundAppInfo.fullPath,\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\tshowToast.success('Copied playground path to clipboard')\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tthe playground directory\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</SimpleTooltip>{' '}\n\t\t\t\t\t\t\tin your editor and terminal to work on this exercise!\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : playgroundAppInfo ? (\n\t\t\t\t<Preview\n\t\t\t\t\tid={playgroundAppInfo.appName}\n\t\t\t\t\tappInfo={playgroundAppInfo}\n\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex flex-col justify-center gap-2\">\n\t\t\t\t\t<p>Please set the playground first</p>\n\t\t\t\t\t{problemAppName ? (\n\t\t\t\t\t\t<SetAppToPlayground appName={problemAppName} />\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</PlaygroundWindow>\n\t)\n}\n","import {\n\tgetAppByName,\n\tgetAppDisplayName,\n\tgetApps,\n\tgetExerciseApp,\n\tisExerciseStepApp,\n\tisPlaygroundApp,\n\trequireExerciseApp,\n\ttype App,\n\ttype ExerciseStepApp,\n} from '@epic-web/workshop-utils/apps.server'\nimport { compileMarkdownString } from '@epic-web/workshop-utils/compile-mdx.server'\nimport { getDiffCode } from '@epic-web/workshop-utils/diff.server'\nimport { userHasAccessToWorkshop } from '@epic-web/workshop-utils/epic-api.server'\nimport {\n\tcombineServerTimings,\n\tgetServerTimeHeader,\n\tmakeTimings,\n} from '@epic-web/workshop-utils/timing.server'\nimport * as Tabs from '@radix-ui/react-tabs'\nimport { clsx } from 'clsx'\nimport * as React from 'react'\nimport { useRef } from 'react'\nimport {\n\tLink,\n\tuseLoaderData,\n\tuseNavigate,\n\tuseSearchParams,\n\tdata,\n\tredirect,\n\ttype HeadersFunction,\n\ttype LoaderFunctionArgs,\n} from 'react-router'\nimport { Diff } from '#app/components/diff.tsx'\nimport { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'\nimport { type InBrowserBrowserRef } from '#app/components/in-browser-browser.tsx'\nimport { useAltDown } from '#app/utils/misc.tsx'\nimport { fetchDiscordPosts } from './__shared/discord.server.ts'\nimport { DiscordChat } from './__shared/discord.tsx'\nimport { Playground } from './__shared/playground.tsx'\nimport { Preview } from './__shared/preview.tsx'\nimport { Tests } from './__shared/tests.tsx'\nimport { getAppRunningState } from './__shared/utils.tsx'\n\nexport async function loader({ request, params }: LoaderFunctionArgs) {\n\tconst timings = makeTimings('exerciseStepTypeIndexLoader')\n\tconst userHasAccess = await userHasAccessToWorkshop({\n\t\trequest,\n\t\ttimings,\n\t})\n\tconst searchParams = new URL(request.url).searchParams\n\tconst cacheOptions = { request, timings }\n\n\tconst [exerciseStepApp, allAppsFull, problemApp, solutionApp] =\n\t\tawait Promise.all([\n\t\t\trequireExerciseApp(params, cacheOptions),\n\t\t\tgetApps(cacheOptions),\n\t\t\tgetExerciseApp({ ...params, type: 'problem' }, cacheOptions),\n\t\t\tgetExerciseApp({ ...params, type: 'solution' }, cacheOptions),\n\t\t])\n\n\tconst playgroundApp = allAppsFull.find(isPlaygroundApp)\n\tconst reqUrl = new URL(request.url)\n\n\tconst pathnameParam = reqUrl.searchParams.get('pathname')\n\tif (pathnameParam === '' || pathnameParam === '/') {\n\t\treqUrl.searchParams.delete('pathname')\n\t\tthrow redirect(reqUrl.toString())\n\t}\n\n\tconst app1Name = reqUrl.searchParams.get('app1')\n\tconst app2Name = reqUrl.searchParams.get('app2')\n\tconst app1 = app1Name\n\t\t? await getAppByName(app1Name)\n\t\t: playgroundApp || problemApp\n\tconst app2 = app2Name ? await getAppByName(app2Name) : solutionApp\n\n\tfunction getStepId(a: ExerciseStepApp) {\n\t\treturn (\n\t\t\ta.exerciseNumber * 1000 +\n\t\t\ta.stepNumber * 10 +\n\t\t\t(a.type === 'problem' ? 0 : 1)\n\t\t)\n\t}\n\n\tfunction getStepNameAndId(a: App) {\n\t\tif (isExerciseStepApp(a)) {\n\t\t\tconst exerciseNumberStr = String(a.exerciseNumber).padStart(2, '0')\n\t\t\tconst stepNumberStr = String(a.stepNumber).padStart(2, '0')\n\n\t\t\treturn {\n\t\t\t\tstepName: `${exerciseNumberStr}/${stepNumberStr}.${a.type}`,\n\t\t\t\tstepId: getStepId(a),\n\t\t\t}\n\t\t}\n\t\treturn { stepName: '', stepId: -1 }\n\t}\n\n\tconst allApps = allAppsFull\n\t\t.filter((a, i, ar) => ar.findIndex((b) => a.name === b.name) === i)\n\t\t.map((a) => ({\n\t\t\tdisplayName: getAppDisplayName(a, allAppsFull),\n\t\t\tname: a.name,\n\t\t\ttitle: a.title,\n\t\t\ttype: a.type,\n\t\t\t...getStepNameAndId(a),\n\t\t}))\n\n\tallApps.sort((a, b) => {\n\t\t// order them by their stepId\n\t\tif (a.stepId > 0 && b.stepId > 0) return a.stepId - b.stepId\n\n\t\t// non-step apps should come after step apps\n\t\tif (a.stepId > 0) return -1\n\t\tif (b.stepId > 0) return 1\n\n\t\treturn 0\n\t})\n\n\tasync function getDiffProp() {\n\t\tif (!app1 || !app2) {\n\t\t\treturn {\n\t\t\t\tapp1: app1?.name,\n\t\t\t\tapp2: app2?.name,\n\t\t\t\tdiffCode: null,\n\t\t\t}\n\t\t}\n\t\tif (!userHasAccess) {\n\t\t\treturn {\n\t\t\t\tapp1: app1?.name,\n\t\t\t\tapp2: app2?.name,\n\t\t\t\tdiffCode: await compileMarkdownString(\n\t\t\t\t\t`<h1>Access Denied</h1><p>You must login or register for the workshop to view the diff</p>`,\n\t\t\t\t),\n\t\t\t}\n\t\t}\n\t\tconst diffCode = await getDiffCode(app1, app2, {\n\t\t\t...cacheOptions,\n\t\t\tforceFresh: searchParams.get('forceFresh') === 'diff',\n\t\t}).catch((e) => {\n\t\t\tconsole.error(e)\n\t\t\treturn null\n\t\t})\n\t\treturn {\n\t\t\tapp1: app1.name,\n\t\t\tapp2: app2.name,\n\t\t\tdiffCode,\n\t\t}\n\t}\n\n\treturn data(\n\t\t{\n\t\t\ttype: params.type as 'problem' | 'solution',\n\t\t\texerciseStepApp,\n\t\t\tallApps,\n\t\t\t// defer this promise so that we don't block the response from being sent\n\t\t\tdiscordPostsPromise: fetchDiscordPosts({ request }),\n\t\t\tplayground: playgroundApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'playground',\n\t\t\t\t\t\tfullPath: playgroundApp.fullPath,\n\t\t\t\t\t\tdev: playgroundApp.dev,\n\t\t\t\t\t\ttest: playgroundApp.test,\n\t\t\t\t\t\ttitle: playgroundApp.title,\n\t\t\t\t\t\tname: playgroundApp.name,\n\t\t\t\t\t\tappName: playgroundApp.appName,\n\t\t\t\t\t\tisUpToDate: playgroundApp.isUpToDate,\n\t\t\t\t\t\tstackBlitzUrl: playgroundApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(playgroundApp)),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tproblem: problemApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'problem',\n\t\t\t\t\t\tfullPath: problemApp.fullPath,\n\t\t\t\t\t\tdev: problemApp.dev,\n\t\t\t\t\t\ttest: problemApp.test,\n\t\t\t\t\t\ttitle: problemApp.title,\n\t\t\t\t\t\tname: problemApp.name,\n\t\t\t\t\t\tstackBlitzUrl: problemApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(problemApp)),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tsolution: solutionApp\n\t\t\t\t? ({\n\t\t\t\t\t\ttype: 'solution',\n\t\t\t\t\t\tfullPath: solutionApp.fullPath,\n\t\t\t\t\t\tdev: solutionApp.dev,\n\t\t\t\t\t\ttest: solutionApp.test,\n\t\t\t\t\t\ttitle: solutionApp.title,\n\t\t\t\t\t\tname: solutionApp.name,\n\t\t\t\t\t\tstackBlitzUrl: solutionApp.stackBlitzUrl,\n\t\t\t\t\t\t...(await getAppRunningState(solutionApp)),\n\t\t\t\t\t} as const)\n\t\t\t\t: null,\n\t\t\tdiff: getDiffProp(),\n\t\t} as const,\n\t\t{\n\t\t\theaders: {\n\t\t\t\t'Server-Timing': getServerTimeHeader(timings),\n\t\t\t},\n\t\t},\n\t)\n}\n\nexport const headers: HeadersFunction = ({ loaderHeaders, parentHeaders }) => {\n\tconst headers = {\n\t\t'Server-Timing': combineServerTimings(loaderHeaders, parentHeaders),\n\t}\n\treturn headers\n}\n\nconst tabs = [\n\t'playground',\n\t'problem',\n\t'solution',\n\t'tests',\n\t'diff',\n\t'chat',\n] as const\nconst isValidPreview = (s: string | null): s is (typeof tabs)[number] =>\n\tBoolean(s && tabs.includes(s as (typeof tabs)[number]))\n\nfunction withParam(\n\tsearchParams: URLSearchParams,\n\tkey: string,\n\tvalue: string | null,\n) {\n\tconst newSearchParams = new URLSearchParams(searchParams)\n\tif (value === null) {\n\t\tnewSearchParams.delete(key)\n\t} else {\n\t\tnewSearchParams.set(key, value)\n\t}\n\treturn newSearchParams\n}\n\nexport default function ExercisePartRoute() {\n\tconst data = useLoaderData<typeof loader>()\n\tconst [searchParams] = useSearchParams()\n\n\tconst preview = searchParams.get('preview')\n\tconst inBrowserBrowserRef = useRef<InBrowserBrowserRef>(null)\n\n\tconst altDown = useAltDown()\n\tconst navigate = useNavigate()\n\n\tfunction shouldHideTab(tab: (typeof tabs)[number]) {\n\t\tif (tab === 'tests') {\n\t\t\treturn (\n\t\t\t\tENV.EPICSHOP_DEPLOYED ||\n\t\t\t\t!data.playground ||\n\t\t\t\tdata.playground.test.type === 'none'\n\t\t\t)\n\t\t}\n\t\tif (tab === 'problem' || tab === 'solution') {\n\t\t\tif (data[tab]?.dev.type === 'none') return true\n\t\t\tif (ENV.EPICSHOP_DEPLOYED) {\n\t\t\t\treturn data[tab]?.dev.type !== 'browser' && !data[tab]?.stackBlitzUrl\n\t\t\t}\n\t\t}\n\t\tif (tab === 'playground' && ENV.EPICSHOP_DEPLOYED) return true\n\t\treturn false\n\t}\n\n\tconst activeTab = isValidPreview(preview)\n\t\t? preview\n\t\t: tabs.find((t) => !shouldHideTab(t))\n\n\t// when alt is held down, the diff tab should open to the full-page diff view\n\t// between the problem and solution (this is more for the instructor than the student)\n\tconst altDiffUrl = `/diff?${new URLSearchParams({\n\t\tapp1: data.problem?.name ?? '',\n\t\tapp2: data.solution?.name ?? '',\n\t})}`\n\n\tfunction handleDiffTabClick(event: React.MouseEvent<HTMLAnchorElement>) {\n\t\tif (event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey) {\n\t\t\tevent.preventDefault()\n\t\t\tvoid navigate(altDiffUrl)\n\t\t}\n\t}\n\n\treturn (\n\t\t<Tabs.Root\n\t\t\tclassName=\"relative flex min-w-0 flex-1 flex-col overflow-y-auto sm:col-span-1 sm:row-span-1\"\n\t\t\tvalue={activeTab}\n\t\t\t// intentionally no onValueChange here because the Link will trigger the\n\t\t\t// change.\n\t\t>\n\t\t\t<Tabs.List className=\"h-14 min-h-14 overflow-x-auto whitespace-nowrap border-b scrollbar-thin scrollbar-thumb-scrollbar\">\n\t\t\t\t{tabs.map((tab) => {\n\t\t\t\t\tconst hidden = shouldHideTab(tab)\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Tabs.Trigger key={tab} value={tab} hidden={hidden} asChild>\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tid={`${tab}-tab`}\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'clip-path-button relative h-full px-6 py-4 font-mono text-sm uppercase outline-none radix-state-active:z-10 radix-state-active:bg-foreground radix-state-active:text-background radix-state-active:hover:bg-foreground/80 radix-state-active:hover:text-background/80 radix-state-inactive:hover:bg-foreground/20 radix-state-inactive:hover:text-foreground/80 focus:bg-foreground/80 focus:text-background/80',\n\t\t\t\t\t\t\t\t\thidden ? 'hidden' : 'inline-block',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tpreventScrollReset\n\t\t\t\t\t\t\t\tprefetch=\"intent\"\n\t\t\t\t\t\t\t\tonClick={handleDiffTabClick}\n\t\t\t\t\t\t\t\tto={\n\t\t\t\t\t\t\t\t\ttab === 'diff' && altDown\n\t\t\t\t\t\t\t\t\t\t? altDiffUrl\n\t\t\t\t\t\t\t\t\t\t: `?${withParam(\n\t\t\t\t\t\t\t\t\t\t\t\tsearchParams,\n\t\t\t\t\t\t\t\t\t\t\t\t'preview',\n\t\t\t\t\t\t\t\t\t\t\t\ttab === 'playground' ? null : tab,\n\t\t\t\t\t\t\t\t\t\t\t)}`\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{tab}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t)\n\t\t\t\t})}\n\t\t\t</Tabs.List>\n\t\t\t<div className=\"relative z-10 flex min-h-96 flex-grow flex-col overflow-y-auto\">\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"playground\"\n\t\t\t\t\tclassName=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Playground\n\t\t\t\t\t\tappInfo={data.playground}\n\t\t\t\t\t\tproblemAppName={data.problem?.name}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t\tallApps={data.allApps}\n\t\t\t\t\t\tisUpToDate={data.playground?.isUpToDate ?? false}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"problem\"\n\t\t\t\t\tclassName=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={data.problem}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"solution\"\n\t\t\t\t\tclassName=\"flex w-full flex-grow items-center justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t\tforceMount\n\t\t\t\t>\n\t\t\t\t\t<Preview\n\t\t\t\t\t\tappInfo={data.solution}\n\t\t\t\t\t\tinBrowserBrowserRef={inBrowserBrowserRef}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"tests\"\n\t\t\t\t\tclassName=\"flex w-full flex-grow items-start justify-center self-start overflow-hidden radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Tests\n\t\t\t\t\t\tappInfo={data.playground}\n\t\t\t\t\t\tproblemAppName={data.problem?.name}\n\t\t\t\t\t\tallApps={data.allApps}\n\t\t\t\t\t\tisUpToDate={data.playground?.isUpToDate ?? false}\n\t\t\t\t\t/>\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"diff\"\n\t\t\t\t\tclassName=\"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<Diff diff={data.diff} allApps={data.allApps} />\n\t\t\t\t</Tabs.Content>\n\t\t\t\t<Tabs.Content\n\t\t\t\t\tvalue=\"chat\"\n\t\t\t\t\tclassName=\"flex h-full w-full flex-grow items-start justify-center self-start radix-state-inactive:hidden\"\n\t\t\t\t>\n\t\t\t\t\t<DiscordChat />\n\t\t\t\t</Tabs.Content>\n\t\t\t</div>\n\t\t</Tabs.Root>\n\t)\n}\n\nexport function ErrorBoundary() {\n\treturn (\n\t\t<GeneralErrorBoundary\n\t\t\tstatusHandlers={{\n\t\t\t\t404: () => <p>Sorry, we couldn't find an app here.</p>,\n\t\t\t}}\n\t\t/>\n\t)\n}\n"],"names":["ENTRY_FOCUS","EVENT_OPTIONS","GROUP_NAME","Collection","useCollection","createCollectionScope","createCollection","createRovingFocusGroupContext","createRovingFocusGroupScope","createContextScope","RovingFocusProvider","useRovingFocusContext","RovingFocusGroup","React.forwardRef","props","forwardedRef","jsx","RovingFocusGroupImpl","__scopeRovingFocusGroup","orientation","loop","dir","currentTabStopIdProp","defaultCurrentTabStopId","onCurrentTabStopIdChange","onEntryFocus","preventScrollOnEntryFocus","groupProps","ref","React.useRef","composedRefs","useComposedRefs","direction","useDirection","currentTabStopId","setCurrentTabStopId","useControllableState","isTabbingBackOut","setIsTabbingBackOut","React.useState","handleEntryFocus","useCallbackRef","getItems","isClickFocusRef","focusableItemsCount","setFocusableItemsCount","React.useEffect","node","React.useCallback","tabStopId","prevCount","Primitive","composeEventHandlers","event","isKeyboardFocus","entryFocusEvent","items","item","activeItem","currentItem","candidateNodes","focusFirst","ITEM_NAME","RovingFocusGroupItem","focusable","active","children","itemProps","autoId","useId","id","context","isCurrentTabStop","onFocusableItemAdd","onFocusableItemRemove","focusIntent","getFocusIntent","currentIndex","wrapArray","MAP_KEY_TO_FOCUS_INTENT","getDirectionAwareKey","key","candidates","preventScroll","PREVIOUSLY_FOCUSED_ELEMENT","candidate","array","startIndex","_","index","Root","Item","TABS_NAME","createTabsContext","createTabsScope","useRovingFocusGroupScope","TabsProvider","useTabsContext","Tabs","__scopeTabs","valueProp","onValueChange","defaultValue","activationMode","tabsProps","value","setValue","TAB_LIST_NAME","TabsList","listProps","rovingFocusGroupScope","RovingFocusGroup.Root","TRIGGER_NAME","TabsTrigger","disabled","triggerProps","triggerId","makeTriggerId","contentId","makeContentId","isSelected","RovingFocusGroup.Item","isAutomaticActivation","CONTENT_NAME","TabsContent","forceMount","contentProps","isMountAnimationPreventedRef","rAF","Presence","present","baseId","Root2","List","Trigger","Content","DiscordChat","jsxs","DiscordCTA","DiscordPosts","data","useLoaderData","ctaLink","useDiscordCTALink","altDown","useAltDown","useIsOnline","React.Suspense","Loading","Await","posts","post","DiscordPost","Link","e","Icon","thread","reactionsWithCounts","r","t","Emoji","i","name","url","Playground","playgroundAppInfo","inBrowserBrowserRef","problemAppName","allApps","isUpToDate","PlaygroundWindow","SimpleTooltip","showToast","Preview","SetAppToPlayground","tabs","isValidPreview","s","Boolean","includes","withParam","searchParams","newSearchParams","URLSearchParams","delete","set","_UNSAFE_withComponentProps","useSearchParams","preview","get","useRef","navigate","useNavigate","shouldHideTab","tab","ENV","EPICSHOP_DEPLOYED","playground","test","type","dev","stackBlitzUrl","activeTab","find","altDiffUrl","app1","problem","app2","solution","handleDiffTabClick","altKey","ctrlKey","shiftKey","metaKey","preventDefault","className","map","hidden","asChild","clsx","preventScrollReset","prefetch","onClick","to","appInfo","Tests","Diff","diff","ErrorBoundary","_UNSAFE_withErrorBoundaryProps","GeneralErrorBoundary","statusHandlers"],"mappings":"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","x_google_ignoreList":[0,1]}
|