{
  "version": 3,
  "sources": ["../../src/web/pages/projects/components/ProjectListItem.styles.ts", "../../src/web/pages/projects/components/ThumbnailImage.tsx"],
  "sourcesContent": ["import \"ProjectListItem.styles_eyufcb.wyw.css\"; export const activeUsers = \"activeUsers_a19ibpm6\";\nexport const customProjectBarButton = \"customProjectBarButton_c19nqpla\";\nexport const moreMenuButton = \"moreMenuButton_mp4d2ah\";\nexport const destructiveProjectBarButton = \"destructiveProjectBarButton_dkx2k6e\";\nexport const useTemplateButton = \"useTemplateButton_u2q0um6\";\nexport const projectThumbnailIntersectionRoot = \"projectThumbnailIntersectionRoot_p1nbokle\";\nexport const newProjectThumbnailImage = \"newProjectThumbnailImage_nrh0nr5\";\nexport const placeholder = \"placeholder_pyivple\";\nexport const placeholderDark = \"placeholderDark_p5q9nra\";\nexport const thumbnailImage = \"thumbnailImage_t1nswwii\";\nexport const thumbnailImageContainer = \"thumbnailImageContainer_tlva7tp\";\nexport const thumbnailContainer = \"thumbnailContainer_t1wdjjbg\";\nexport const thumbnailFocused = \"thumbnailFocused_trqae9v\";\nexport const thumbnailContainerBorder = \"thumbnailContainerBorder_t1v6uy59\";\nexport const projectThumbnailAvatars = \"projectThumbnailAvatars_poo9syu\";\nexport const projectHighlighted = \"projectHighlighted_p114bvzz\";\nexport const projectWrapper = \"projectWrapper_pruynu2\";\nexport const projectRow = \"projectRow_poogziy\";\nexport const projectInfo = \"projectInfo_pvav5zo\";\nexport const projectInfoRight = \"projectInfoRight_pqfszli\";\nexport const projectTitle = \"projectTitle_p1vm46yz\";\nexport const projectDescription = \"projectDescription_p1xon8az\";\nexport const projectDescriptionChunk = \"projectDescriptionChunk_pyhjgz6\";\nexport const hideOnMobile = \"hideOnMobile_h1i40kry\";\nexport const workspaceName = \"workspaceName_w1lq71hs\";\nexport const workspaceTag = \"workspaceTag_w1bpvtml\";", "import { getServiceMap } from \"@framerjs/framer-environment/domains.ts\"\nimport { IconDashboardPlaceholderLogo, useViewportWidth } from \"@framerjs/fresco\"\nimport { breakpoints, colors } from \"@framerjs/fresco/tokens\"\nimport { getLogger } from \"@framerjs/shared\"\nimport { cx } from \"@linaria/core\"\nimport { useEffect, useRef, useState } from \"react\"\nimport { accessTokenRefresher } from \"web/lib/accessTokenRefresherWeb.ts\"\nimport { useDarkMode } from \"web/lib/useDarkMode.ts\"\nimport * as classes from \"./ProjectListItem.styles.ts\"\n\nconst log = getLogger(\"web:thumbnail\")\ninterface Props {\n\tprojectId: string\n\t/** When provided, the thumbnail will be lazy-loaded when the component is about to be visible inside the container\n\t * with the provided class. Useful when showing a scrollable list of projects, but not when showing a single project. */\n\tlazyLoadingRootSelectorClass?: string\n\timageClass?: string\n\tcontainerClass?: string\n\tplaceholderDimensions?: { width: number; height: number }\n\t/** Callback invoked when the thumbnail image has done loading, needed to set some conditional styles (e.g. border). */\n\tonImageDoneLoading?: () => void\n}\n\nexport function ThumbnailImage({\n\tprojectId,\n\tlazyLoadingRootSelectorClass,\n\timageClass,\n\tcontainerClass,\n\tplaceholderDimensions,\n\tonImageDoneLoading,\n}: Props) {\n\tconst ref = useRef<HTMLDivElement>(null)\n\tconst [objectURL, setObjectURL] = useState<string>()\n\tconst { isDarkMode } = useDarkMode()\n\tconst [isFetching, setIsFetching] = useState(true)\n\n\tuseEffect(() => {\n\t\tlet isCanceled = false\n\t\tlet createdObjectURL: string | undefined = undefined\n\t\tlet observer: IntersectionObserver | undefined = undefined\n\n\t\tconst el = ref.current\n\t\tif (!el) return\n\n\t\tif (!lazyLoadingRootSelectorClass) {\n\t\t\tvoid hydrateThumbnail()\n\t\t} else {\n\t\t\tobserver = new IntersectionObserver(\n\t\t\t\tentries => {\n\t\t\t\t\tif (!entries[0]?.isIntersecting) return\n\t\t\t\t\tvoid hydrateThumbnail()\n\t\t\t\t\tobserver?.unobserve(el)\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// We can't use the viewport itself as our intersection root, because the sidebar + content grid on\n\t\t\t\t\t// the dashboard has height: 100% and overflow: auto, which results in a clipping rect equal to the\n\t\t\t\t\t// viewport's height. This would prevent us from loading thumbnails below the fold, because extending\n\t\t\t\t\t// the viewport's intersection rect via rootMargin would have no effect due to that clipping rect.\n\t\t\t\t\t// It's all neatly explained by point 2 in here:\n\t\t\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Clipping_and_the_intersection_rectangle\n\t\t\t\t\t// So instead, we need to make the content div our intersection root, and extend _its_ intersection\n\t\t\t\t\t// rect via rootMargin.\n\t\t\t\t\troot: document.querySelector(`.${lazyLoadingRootSelectorClass}`),\n\t\t\t\t\t// Load extra 8 screens worth of thumbnails.\n\t\t\t\t\trootMargin: \"0px 0px 800% 0px\",\n\t\t\t\t},\n\t\t\t)\n\n\t\t\tobserver.observe(el)\n\t\t}\n\n\t\tasync function hydrateThumbnail() {\n\t\t\ttry {\n\t\t\t\tsetIsFetching(true)\n\t\t\t\tconst thumbnail = await fetchThumbnail(projectId)\n\t\t\t\tif (isCanceled) return\n\t\t\t\tcreatedObjectURL = URL.createObjectURL(thumbnail)\n\t\t\t\tsetObjectURL(createdObjectURL)\n\t\t\t} catch (err) {\n\t\t\t\tlog.warn(\"Fetching thumbnail for\", projectId, \"failed\", err)\n\t\t\t} finally {\n\t\t\t\tif (!isCanceled) {\n\t\t\t\t\tsetIsFetching(false)\n\t\t\t\t\tonImageDoneLoading?.()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn () => {\n\t\t\tisCanceled = true\n\n\t\t\t// Clear the object URL to avoid memory leaks.\n\t\t\tif (createdObjectURL) {\n\t\t\t\tURL.revokeObjectURL(createdObjectURL)\n\t\t\t}\n\t\t\t// eslint-disable-next-line react-you-might-not-need-an-effect/no-adjust-state-on-prop-change\n\t\t\tsetObjectURL(undefined)\n\n\t\t\tobserver?.unobserve(el)\n\t\t}\n\t}, [projectId, lazyLoadingRootSelectorClass, onImageDoneLoading])\n\n\tconst isMobile = useViewportWidth() <= breakpoints.mobile\n\n\tif (isFetching || !objectURL) {\n\t\treturn (\n\t\t\t<div ref={ref}>\n\t\t\t\t{isFetching ? (\n\t\t\t\t\t<ThumbnailSkeleton {...(isMobile ? { width: 170, height: 208 } : undefined)} />\n\t\t\t\t) : (\n\t\t\t\t\t!objectURL && (\n\t\t\t\t\t\t<div className={cx(isDarkMode ? classes.placeholderDark : classes.placeholder, containerClass)}>\n\t\t\t\t\t\t\t<IconDashboardPlaceholderLogo\n\t\t\t\t\t\t\t\tfill={colors.dashboardProjectThumbnailPlaceholderLogo}\n\t\t\t\t\t\t\t\twidth={placeholderDimensions?.width || 16}\n\t\t\t\t\t\t\t\theight={placeholderDimensions?.height || 24}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t)}\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div ref={ref} className={containerClass}>\n\t\t\t<img className={cx(classes.newProjectThumbnailImage, imageClass)} src={objectURL} alt=\"\" decoding=\"async\" />\n\t\t</div>\n\t)\n}\n\nconst fetchThumbnail = async (projectId: string): Promise<Blob> => {\n\tconst url = `${getServiceMap().api}/web/projects/${projectId}/assets/screenshots/site-thumbnail.png`\n\n\tconst initWithAuthHeaders = await accessTokenRefresher.withAuthorizationHeader({})\n\tconst res = await fetch(url, initWithAuthHeaders)\n\tif (!res.ok) {\n\t\tthrow new Error(`Response is not OK: ${res.status}`)\n\t}\n\treturn res.blob()\n}\n\nfunction ThumbnailSkeleton({\n\twidth = 260,\n\theight = 320,\n\tprimaryColor = colors.loaderPrimary,\n}: {\n\twidth?: number\n\theight?: number\n\tprimaryColor?: string\n}) {\n\treturn (\n\t\t<svg role=\"img\" preserveAspectRatio=\"none\" height={height} width={width}>\n\t\t\t<title>Thumbnail skeleton</title>\n\t\t\t<rect x=\"0\" y=\"0\" width={width} height={height} style={{ fill: primaryColor }} />\n\t\t</svg>\n\t)\n}\n"],
  "mappings": "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",
  "names": []
}
