{ "version": 3, "sources": ["../../../data/react_hooks.ts", "../../../app/app_error.tsx", "../../../utils/async.ts", "../../../utils/debouncer.ts", "css-module-js:./image.scss", "../../../app/gallery/image_manager.ts", "../../../app/gallery/image.tsx", "css-module-js:./build/loaders/icon.scss", "icon-js:arrow_left", "icon-js:arrow_right", "icon-js:close", "css-module-js:./full_view.scss", "../../../app/gallery/full_view.tsx", "../../../app/gallery/tile_styles.ts", "css-module-js:./tile.scss", "../../../app/gallery/tile.tsx", "css-module-js:./gallery.scss", "../../../app/gallery/gallery.tsx", "css-module-js:./gallery_controller.scss", "../../../app/gallery/gallery_controller.tsx"], "sourcesContent": ["import { useCallback, useContext, useEffect, useState } from \"preact/hooks\";\nimport { delay } from \"../utils/async\";\nimport { Disposable } from \"../utils/disposable\";\nimport { Dispatcher } from \"../utils/events/dispatcher\";\nimport { DataProvider, DataProviderQueryResult, NON_EXISTING } from \"./data_provider\";\nimport { DataContext } from \"./react_context\";\n\nclass StateCache {\n private dispatcher = new Dispatcher();\n private ids_: string[];\n private state_!: DataResult;\n private currentAttachment: Disposable | null = null;\n\n onUpdate = this.dispatcher.signal();\n\n constructor(ids: string[], private provider: DataProvider) {\n this.ids_ = ids;\n this.fetch();\n }\n\n private fetch() {\n const result = this.provider.get(this.ids_);\n\n this.state_ = makeDataResultObject(result);\n this.dispatcher.emit(this.onUpdate);\n\n if (this.currentAttachment) {\n this.currentAttachment.dispose();\n }\n\n const disposable = new Disposable();\n this.currentAttachment = disposable;\n result.onUpdate.attach(() => {\n this.dispatcher.emit(this.onUpdate);\n }, disposable);\n }\n\n updateIds(ids: string[]) {\n this.ids_ = ids;\n this.fetch();\n }\n\n get ids() {\n return this.ids_;\n }\n\n get state() {\n return this.state_;\n }\n}\n\nconst stateCache = new WeakMap();\n\nexport function useData(ids: string[]): DataResult {\n const dataContext = useContext(DataContext);\n if (!dataContext) throw new Error(\"Data hook not used inside of a DataContext.\");\n\n const [key] = useState({});\n let cached = stateCache.get(key);\n if (!cached) {\n const result = dataContext.provider.get(ids);\n const state = makeDataResultObject(result);\n cached = new StateCache(ids, dataContext.provider);\n stateCache.set(ids, cached);\n }\n\n if (!areIdsEqual(ids, cached.ids)) {\n // update cache since IDs changed\n cached.updateIds(ids);\n }\n\n const [, setDataState] = useState({});\n\n useCallback(() => {\n const disposable = new Disposable();\n cached!.onUpdate.attach(() => {\n setDataState({});\n }, disposable);\n\n () => {\n // clean up\n disposable.dispose();\n };\n }, [cached]);\n\n if (cached.state.isLoading) {\n throw cached.onUpdate.next();\n }\n\n return cached.state as DataResult;\n}\n\nfunction areIdsEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n\n return true;\n}\n\nfunction makeDataResultObject(queryResult: DataProviderQueryResult): DataResult {\n const value = queryResult.onUpdate.lastValue as T | typeof NON_EXISTING | undefined;\n const isLoading = !queryResult.onUpdate.hasValue;\n const exists = !isLoading && value !== NON_EXISTING;\n return {\n value: exists ? value : undefined,\n isLoading,\n exists,\n };\n}\n\ninterface DataResult {\n value: TValue | undefined;\n isLoading: boolean;\n exists: boolean;\n}\n", "import { h, Fragment, Component } from \"preact\";\nimport { assert } from \"../utils/asserts\";\nimport { AppContext } from \"./app_context\";\n\nexport class AppError extends Error {\n constructor(readonly type: AppErrorType) {\n super();\n }\n}\n\nexport enum AppErrorType {\n PAGE_NOT_FOUND,\n}\n\ninterface Props {\n errorType: AppErrorType;\n}\n\nexport class AppErrorComponent extends Component {\n static contextType = AppContext;\n\n componentDidMount() {\n (this.context as AppContext).reportAppError(this.props.errorType);\n }\n\n componentWillUnmount() {}\n\n render() {\n return <>;\n }\n}\n", "export function delay(ms: number): Promise {\n return new Promise((resolve) => {\n setTimeout(() => resolve(), ms);\n });\n}\n\nexport class Resolver {\n readonly promise: Promise;\n private resolveInternal!: (res: T) => void;\n private rejectInternal!: (e: unknown) => void;\n constructor() {\n this.promise = new Promise((resolve, reject) => {\n this.resolveInternal = resolve;\n this.rejectInternal = reject;\n });\n }\n\n resolve(res: T) {\n this.resolveInternal(res);\n }\n\n reject(err: unknown = undefined) {\n this.rejectInternal(err);\n }\n}\n", "export interface DebouncerOpts {\n waitMs: number;\n}\n\nexport class Debouncer {\n private readonly waitMs;\n private isCallbackPending = false;\n private runningCallbackPromise: Promise | null = null;\n private debounceTimerId: NodeJS.Timeout | null = null;\n\n constructor(\n private readonly callback: () => void | Promise,\n { waitMs }: DebouncerOpts\n ) {\n this.waitMs = waitMs;\n }\n\n fire() {\n if (this.debounceTimerId) {\n clearTimeout(this.debounceTimerId);\n }\n\n this.debounceTimerId = setTimeout(async () => {\n this.debounceTimerId = null;\n\n if (this.runningCallbackPromise) {\n await this.runningCallbackPromise;\n }\n\n this.runningCallbackPromise = Promise.resolve(this.callback()).finally(\n () => {\n this.runningCallbackPromise = null;\n }\n );\n }, this.waitMs);\n }\n}\n", "import \"./image.scss\";\n const mappedNames = {\"container\":\"_container_1wfhl_1\",\"img\":\"_img_1wfhl_8\",\"transition-out\":\"_transition-out_1wfhl_15\",\"low-res-loading\":\"_low-res-loading_1wfhl_20\"};\n\n function mapName(name) {\n if (!(name in mappedNames)) {\n // throw new Error(\"Unknown class name '\" + name + \"'.\");\n return null;\n }\n\n return mappedNames[name];\n }\n\n export default function(...args) {\n const results = [];\n for (const arg of args) {\n if (typeof arg === \"string\") {\n const mappedName = mapName(arg);\n if (mappedName) results.push(mappedName);\n } else if (typeof arg === \"object\") {\n for (const [name, active] of Object.entries(arg)) {\n const mappedName = mappedNames[name];\n if (active && mappedName) results.push(mappedName);\n }\n }\n }\n\n return results.join(\" \");\n }\n ", "import { ImageSource } from \"../../gallery/gallery_image\";\n\nexport class ImageManager {\n private loadedUrls = new Map();\n\n setSourceLoaded(source: ImageSource) {\n const { url } = source;\n if (isDataUrl(url)) return;\n this.loadedUrls.set(url, source);\n }\n\n isLoaded(source: ImageSource): boolean {\n const { url } = source;\n if (isDataUrl(url)) return true;\n\n return this.loadedUrls.has(url);\n }\n}\n\nfunction isDataUrl(url: string) {\n return url.startsWith(\"data:\");\n}\n\nexport const imageManager = new ImageManager();\n", "import { Component, h } from \"preact\";\nimport { AssetManager } from \"../../asset_manager/asset_manager\";\nimport { GalleryImage, ImageSource } from \"../../gallery/gallery_image\";\nimport { assert } from \"../../utils/asserts\";\nimport { delay } from \"../../utils/async\";\nimport { Debouncer } from \"../../utils/debouncer\";\nimport { AppContext } from \"../app_context\";\n\nimport css from \"./image.scss\";\nimport { imageManager } from \"./image_manager\";\n\nconst LOW_RES_THRESHOLD = 50;\n\ninterface Props {\n image: GalleryImage;\n preloadWidth?: number;\n onInitialLoad?: () => void;\n debug?: boolean;\n}\n\ninterface SourceLoadingStage {\n source: ImageSource;\n lowResLoading: boolean;\n id: number;\n timestamp: number;\n}\n\ninterface State {\n currentSource: SourceLoadingStage;\n loadingSource?: SourceLoadingStage;\n transitioningOutSource?: SourceLoadingStage;\n}\n\nexport class Image extends Component {\n private containerEl: HTMLElement | null = null;\n private sortedSources: ImageSource[] | null = null;\n private resizeObserver?: ResizeObserver;\n private resizeDebouncer = new Debouncer(\n () => {\n this.maybeUpdateImageSource();\n },\n { waitMs: 500 }\n );\n private initialLoaded = false;\n private mounted = false;\n\n constructor(props: Props) {\n super(props);\n\n this.handleImageUpdate({ updateSource: false });\n const { bestLoadedSource, bestSource } = this.getBestSource();\n\n this.state = {\n currentSource: {\n source: bestLoadedSource!,\n id: 0,\n lowResLoading: bestLoadedSource!.width <= LOW_RES_THRESHOLD,\n timestamp: performance.now(),\n },\n loadingSource:\n bestSource && bestSource.url !== bestLoadedSource!.url\n ? {\n source: bestSource,\n id: 1,\n lowResLoading: false,\n timestamp: performance.now(),\n }\n : undefined,\n };\n\n if (BUILD_PLATFORM === \"browser\") {\n this.resizeObserver = new ResizeObserver(() => {\n this.resizeDebouncer.fire();\n });\n }\n }\n\n render() {\n const { currentSource, loadingSource, transitioningOutSource } = this.state;\n const { image } = this.props;\n\n let lowResLoading = currentSource?.lowResLoading;\n\n const x = (\n \n {(appContext) => {\n assert(appContext);\n const { assetManager } = appContext;\n const currentImg = this.makeImg(assetManager, image, currentSource, \"current\");\n const loadingImg = this.makeImg(assetManager, image, loadingSource, \"pending\");\n const transitioningOutImg = this.makeImg(\n assetManager,\n image,\n transitioningOutSource,\n \"transition-out\"\n );\n return [loadingImg, currentImg, transitioningOutImg].filter((item) => item);\n }}\n \n );\n\n return (\n \n {x}\n \n );\n }\n\n private makeImg(\n assetManager: AssetManager,\n image: GalleryImage,\n source: SourceLoadingStage | undefined,\n type: \"pending\" | \"current\" | \"transition-out\"\n ) {\n if (!source) return null;\n\n const url = assetManager.getUrl(source.source.url);\n return (\n \n );\n }\n\n private setContainerEl = (el: HTMLElement | null) => {\n const previousEl = this.containerEl;\n this.containerEl = el;\n\n const { resizeObserver } = this;\n if (!resizeObserver) return;\n\n if (previousEl) resizeObserver.unobserve(previousEl);\n if (el) {\n resizeObserver.observe(el);\n }\n\n if (!previousEl && el) this.maybeUpdateImageSource();\n };\n\n private maybeEmitInitialLoad() {\n if (this.initialLoaded) return;\n\n this.initialLoaded = true;\n const { onInitialLoad } = this.props;\n if (onInitialLoad) onInitialLoad();\n }\n\n private handleCurrentImageLoad = async () => {\n if (!this.mounted) return;\n\n this.maybeEmitInitialLoad();\n };\n\n private handlePendingImageLoad = async () => {\n if (!this.mounted) return;\n\n this.maybeEmitInitialLoad();\n\n const { loadingSource } = this.state;\n if (!loadingSource) return;\n\n imageManager.setSourceLoaded(loadingSource.source);\n\n this.setState((prevState) => {\n if (loadingSource !== prevState.loadingSource) return null;\n const animate =\n prevState.currentSource && performance.now() - prevState.currentSource.timestamp > 100;\n return {\n transitioningOutSource: animate ? prevState.currentSource : undefined,\n currentSource: prevState.loadingSource,\n loadingSource: undefined,\n lowResLoading: false,\n };\n });\n\n // wait for animation to finish\n await delay(500);\n if (!this.mounted) return;\n\n this.setState((prevState) => {\n return {\n transitioningOutSource: undefined,\n };\n });\n };\n\n private getBestSource(): {\n bestSource: ImageSource;\n bestLoadedSource?: ImageSource;\n isPartial: boolean;\n } {\n const { containerEl, sortedSources } = this;\n\n // Find the best source for current size\n const width = containerEl?.clientWidth ?? this.props.preloadWidth ?? 0;\n\n let bestSource: ImageSource | null = null;\n let bestLoadedSource: ImageSource | null = null;\n let bestSourceFound = false;\n for (const source of sortedSources!) {\n let isLoaded = imageManager.isLoaded(source);\n\n // Keep going if current best source is still too small\n if (!bestSource || bestSource.width < width) {\n bestSource = source;\n }\n\n if (isLoaded && (!bestLoadedSource || bestLoadedSource.width < width)) {\n bestLoadedSource = source;\n }\n\n if (source.width > width) {\n // The smallest source whose width is larger than the element\n bestSourceFound = true;\n }\n }\n\n return {\n bestSource: bestSource!,\n bestLoadedSource: bestLoadedSource!,\n isPartial: width <= 0,\n };\n }\n\n private maybeUpdateImageSource() {\n let { bestSource, bestLoadedSource, isPartial } = this.getBestSource();\n\n if (bestLoadedSource) {\n this.maybeUseSource(bestLoadedSource);\n }\n\n this.maybeLoadSource(bestSource);\n }\n\n private maybeUseSource(source: ImageSource) {\n const { currentSource } = this.state;\n if (source.url !== currentSource.source.url && source.width > currentSource.source.width) {\n this.setState((prevState) => {\n return {\n currentSource: {\n source: source!,\n id: currentSource.id,\n lowResLoading: false,\n timestamp: performance.now(),\n },\n };\n });\n }\n }\n\n private maybeLoadSource(source: ImageSource) {\n const { currentSource, loadingSource } = this.state;\n if (\n source.url !== currentSource.source.url &&\n source.width > currentSource.source.width &&\n (!loadingSource || source.url !== loadingSource.source.url)\n ) {\n this.setState((prevState) => {\n return {\n loadingSource: {\n source: source!,\n id: Math.max(currentSource.id, loadingSource?.id ?? 0) + 1,\n lowResLoading: false,\n timestamp: performance.now(),\n },\n };\n });\n }\n }\n\n private handleImageUpdate({ updateSource = true } = {}) {\n const { image } = this.props;\n const sortedSources = [...image.sources];\n sortedSources.sort((a, b) => a.width - b.width);\n this.sortedSources = sortedSources;\n\n // TODO: set lowResLoading to true again and use an initial source\n if (updateSource) {\n this.maybeUpdateImageSource();\n }\n }\n\n componentDidMount() {\n this.mounted = true;\n this.maybeUpdateImageSource();\n }\n\n componentDidUpdate(prevProps: Props) {\n const { props } = this;\n if (prevProps.image !== props.image) {\n /*\n this.handleImageUpdate();\n const { bestLoadedSource, bestSource } = this.getBestSource();\n\n this.setState({\n currentSource: {\n source: bestLoadedSource!,\n id: 0,\n lowResLoading: bestLoadedSource!.width <= LOW_RES_THRESHOLD,\n timestamp: performance.now(),\n },\n loadingSource:\n bestSource && bestSource.url !== bestLoadedSource!.url\n ? {\n source: bestSource,\n id: 1,\n lowResLoading: false,\n timestamp: performance.now(),\n }\n : undefined,\n });\n */\n }\n }\n\n componentWillUnmount() {\n const { resizeObserver } = this;\n this.mounted = false;\n if (resizeObserver) resizeObserver.disconnect();\n }\n}\n", "import \"./build/loaders/icon.scss\";\n const mappedNames = {\"icon\":\"_icon_1p1fc_1\"};\n\n function mapName(name) {\n if (!(name in mappedNames)) {\n // throw new Error(\"Unknown class name '\" + name + \"'.\");\n return null;\n }\n\n return mappedNames[name];\n }\n\n export default function(...args) {\n const results = [];\n for (const arg of args) {\n if (typeof arg === \"string\") {\n const mappedName = mapName(arg);\n if (mappedName) results.push(mappedName);\n } else if (typeof arg === \"object\") {\n for (const [name, active] of Object.entries(arg)) {\n const mappedName = mappedNames[name];\n if (active && mappedName) results.push(mappedName);\n }\n }\n }\n\n return results.join(\" \");\n }\n ", "\nimport svg from \"./assets/icons/arrow_left.svg\";\nimport css from \"./build/loaders/icon.scss\";\nimport { h } from \"preact\"\nexport default function Icon() {\n return ;\n}", "\nimport svg from \"./assets/icons/arrow_right.svg\";\nimport css from \"./build/loaders/icon.scss\";\nimport { h } from \"preact\"\nexport default function Icon() {\n return ;\n}", "\nimport svg from \"./assets/icons/close.svg\";\nimport css from \"./build/loaders/icon.scss\";\nimport { h } from \"preact\"\nexport default function Icon() {\n return ;\n}", "import \"./full_view.scss\";\n const mappedNames = {\"full-view-container\":\"_full-view-container_1bi53_1\",\"in-transition\":\"_in-transition_1bi53_13\",\"image-container\":\"_image-container_1bi53_17\",\"left-controls\":\"_left-controls_1bi53_22\",\"right-controls\":\"_right-controls_1bi53_26\",\"right-top-controls\":\"_right-top-controls_1bi53_30\",\"button\":\"_button_1bi53_40\",\"body-no-scroll\":\"_body-no-scroll_1bi53_65\"};\n\n function mapName(name) {\n if (!(name in mappedNames)) {\n // throw new Error(\"Unknown class name '\" + name + \"'.\");\n return null;\n }\n\n return mappedNames[name];\n }\n\n export default function(...args) {\n const results = [];\n for (const arg of args) {\n if (typeof arg === \"string\") {\n const mappedName = mapName(arg);\n if (mappedName) results.push(mappedName);\n } else if (typeof arg === \"object\") {\n for (const [name, active] of Object.entries(arg)) {\n const mappedName = mappedNames[name];\n if (active && mappedName) results.push(mappedName);\n }\n }\n }\n\n return results.join(\" \");\n }\n ", "import { h, FunctionComponent } from \"preact\";\nimport { useCallback, useEffect } from \"preact/hooks\";\n\nimport { Tile } from \"./tile\";\nimport { Image } from \"./image\";\nimport { TILE_COLORS } from \"./tile_styles\";\n\nimport LeftArrowIcon from \"icon:arrow_left\";\nimport RightArrowIcon from \"icon:arrow_right\";\nimport CloseIcon from \"icon:close\";\nimport css from \"./full_view.scss\";\n\ninterface Props {\n tile: Tile;\n inTransition?: boolean;\n onClose?: () => void;\n onGoToNext?: () => void;\n onGoToPrevious?: () => void;\n}\n\nexport const FULL_VIEW_MARGIN_P = 0.05;\n\nexport const FullView: FunctionComponent = (props) => {\n const { tile, inTransition, onClose, onGoToNext, onGoToPrevious } = props;\n\n const handleClose = useCallback(() => {\n if (onClose) onClose();\n }, [onClose]);\n\n const handleNext = useCallback(() => {\n if (onGoToNext) onGoToNext();\n }, [onGoToNext]);\n\n const handlePrevious = useCallback(() => {\n if (onGoToPrevious) onGoToPrevious();\n }, [onGoToPrevious]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n handleClose();\n } else if (e.key === \"ArrowLeft\") {\n handlePrevious();\n } else if (e.key === \"ArrowRight\") {\n handleNext();\n }\n },\n [handleClose, handlePrevious, handleNext]\n );\n\n useEffect(() => {\n if (BUILD_PLATFORM !== \"browser\") return;\n\n document.body.classList.add(css(\"body-no-scroll\"));\n document.addEventListener(\"keydown\", handleKeyDown);\n\n // clean up\n return () => {\n document.body.classList.remove(css(\"body-no-scroll\"));\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n });\n\n const showNext = !!onGoToNext;\n const showPrevious = !!onGoToPrevious;\n\n return (\n
\n
\n \n
\n
\n {showPrevious ? (\n \n ) : null}\n
\n
\n \n
\n
\n {showNext ? (\n \n ) : null}\n
\n
\n );\n};\n", "export const TILE_SIZES = {\n small: { width: 25 },\n medium: { width: 30 },\n large: { width: 35 },\n \"x-large\": { width: 50 },\n};\n\nexport enum TileColor {\n GRAY = \"gray\",\n RED = \"red\",\n BLUE = \"blue\",\n ORANGE = \"orange\",\n GREEN = \"green\",\n PURPLE = \"purple\",\n YELLOW = \"yellow\",\n}\n\nexport const TILE_COLORS = {\n [TileColor.GRAY]: { backgroundColor: \"#ddd\" },\n [TileColor.RED]: { backgroundColor: \"#f31\" },\n [TileColor.BLUE]: { backgroundColor: \"#9de\" },\n [TileColor.ORANGE]: { backgroundColor: \"#f80\" },\n [TileColor.GREEN]: { backgroundColor: \"#6f8\" },\n [TileColor.PURPLE]: { backgroundColor: \"#d6f\" },\n [TileColor.YELLOW]: { backgroundColor: \"#fd5\" },\n};\n", "import \"./tile.scss\";\n const mappedNames = {\"tile\":\"_tile_121jy_1\",\"image\":\"_image_121jy_6\",\"image-placeholder\":\"_image-placeholder_121jy_7\",\"tile-pos-left\":\"_tile-pos-left_121jy_26\",\"tile-pos-right\":\"_tile-pos-right_121jy_30\",\"tile-pos-far-right\":\"_tile-pos-far-right_121jy_35\"};\n\n function mapName(name) {\n if (!(name in mappedNames)) {\n // throw new Error(\"Unknown class name '\" + name + \"'.\");\n return null;\n }\n\n return mappedNames[name];\n }\n\n export default function(...args) {\n const results = [];\n for (const arg of args) {\n if (typeof arg === \"string\") {\n const mappedName = mapName(arg);\n if (mappedName) results.push(mappedName);\n } else if (typeof arg === \"object\") {\n for (const [name, active] of Object.entries(arg)) {\n const mappedName = mappedNames[name];\n if (active && mappedName) results.push(mappedName);\n }\n }\n }\n\n return results.join(\" \");\n }\n ", "import { h, FunctionComponent } from \"preact\";\nimport { GalleryImage } from \"../../gallery/gallery_image\";\nimport { TileColor, TILE_COLORS, TILE_SIZES } from \"./tile_styles\";\nimport { Image } from \"./image\";\n\nimport css from \"./tile.scss\";\nimport { useCallback } from \"preact/hooks\";\n\nexport interface Tile {\n color: TileColor;\n size: \"small\" | \"medium\" | \"large\" | \"x-large\";\n position: \"left\" | \"right\" | \"far-left\" | \"far-right\";\n lift?: boolean;\n image: GalleryImage;\n}\n\ninterface Props {\n tile: Tile;\n tileElementRef: (tile: Tile) => (el: HTMLDivElement | null) => void;\n onClick?: () => void;\n class?: string;\n}\n\nexport const TileComponent: FunctionComponent = (props) => {\n const { tile, onClick, tileElementRef } = props;\n\n const handleTileClick = useCallback(() => {\n if (onClick) onClick();\n }, [onClick]);\n\n const image = tile.image;\n\n const tileSizeInfo = TILE_SIZES[tile.size]!;\n const tileColorInfo = TILE_COLORS[tile.color];\n\n const style = {\n width: `${tileSizeInfo.width}vw`,\n height: `${tileSizeInfo.width / image.aspect}vw`,\n backgroundColor: tileColorInfo.backgroundColor,\n };\n\n return (\n \n \n {image ? (\n
\n \n
\n ) : (\n
\n )}\n \n \n );\n};\n", "import \"./gallery.scss\";\n const mappedNames = {\"tiles-container\":\"_tiles-container_1cgai_1\",\"scroll-reference\":\"_scroll-reference_1cgai_17\",\"tile-wrapper\":\"_tile-wrapper_1cgai_25\",\"tile-pos-lift\":\"_tile-pos-lift_1cgai_28\",\"transition-to-full\":\"_transition-to-full_1cgai_31\",\"phantom\":\"_phantom_1cgai_35\",\"full-view-transition-bg\":\"_full-view-transition-bg_1cgai_51\",\"full-view-reverse-transition-bg\":\"_full-view-reverse-transition-bg_1cgai_52\",\"bg-fade-in\":\"_bg-fade-in_1cgai_1\"};\n\n function mapName(name) {\n if (!(name in mappedNames)) {\n // throw new Error(\"Unknown class name '\" + name + \"'.\");\n return null;\n }\n\n return mappedNames[name];\n }\n\n export default function(...args) {\n const results = [];\n for (const arg of args) {\n if (typeof arg === \"string\") {\n const mappedName = mapName(arg);\n if (mappedName) results.push(mappedName);\n } else if (typeof arg === \"object\") {\n for (const [name, active] of Object.entries(arg)) {\n const mappedName = mappedNames[name];\n if (active && mappedName) results.push(mappedName);\n }\n }\n }\n\n return results.join(\" \");\n }\n ", "import { h, FunctionComponent } from \"preact\";\nimport { Ref, useCallback, useContext, useEffect, useMemo, useRef, useState } from \"preact/hooks\";\n\nimport { FullView, FULL_VIEW_MARGIN_P } from \"./full_view\";\nimport { Tile, TileComponent } from \"./tile\";\nimport { assert } from \"../../utils/asserts\";\nimport { RoutingContext } from \"../routing_context\";\n\nimport css from \"./gallery.scss\";\n\ninterface Props {\n tiles: Tile[];\n galleryId: string;\n selectedImageId?: string;\n}\n\ninterface State {\n selectedTile: Tile | null;\n isTransitioningToFullView: boolean;\n isTransitioningFromFullView: boolean;\n showGallery: boolean;\n}\n\nconst GALLERY_URL_STATE_SYMBOL = \"_gallery_url_state\";\n\nfunction getFullViewTransitionEndStyle(el: HTMLElement) {\n const rect = el.getBoundingClientRect();\n const scale =\n Math.min(window.innerWidth / rect.width, window.innerHeight / rect.height) *\n (1 - FULL_VIEW_MARGIN_P * 2);\n\n const translateX = window.innerWidth / 2 - rect.left - rect.width / 2;\n const translateY = window.innerHeight / 2 - rect.top - rect.height / 2;\n\n return {\n transform: `translate(${translateX}px, ${translateY}px) scale(${scale})`,\n };\n}\n\nfunction getFullViewTransitionStartStyle(el: HTMLElement) {\n return {\n transform: \"translate(0, 0) scale(1)\",\n };\n}\n\nfunction useLazyRef(initialValue: () => T): Ref {\n const ref = useRef(undefined);\n if (ref.current === undefined) ref.current = initialValue();\n\n return ref as Ref;\n}\n\nfunction useTileScrollObserver() {\n const containerEl = useRef(null);\n\n const observedTilesRef = useLazyRef(() => new Set());\n const tileElementsRef = useLazyRef(() => new TilesElementMap());\n\n const handleTileIntersection = useCallback(\n (entry: IntersectionObserverEntry) => {\n const tileWrapperEl = entry.target as HTMLElement;\n const tileEl = tileWrapperEl.children.item(0)! as HTMLElement;\n const imageEl = tileEl.children.item(0)! as HTMLElement;\n\n const ratio =\n (entry.intersectionRect.bottom - entry.boundingClientRect.top) /\n entry.boundingClientRect.height;\n\n const t = (Math.min(Math.max(ratio, 0.2), 0.8) - 0.2) / 0.6;\n\n const scale = t * 0.4 + 0.6;\n const opacity = t;\n\n imageEl.style.opacity = `${opacity}`;\n tileEl.style.transform = `scale(${scale})`;\n\n tileElementsRef.current.setVisible(tileEl, entry.isIntersecting);\n },\n [tileElementsRef]\n );\n\n const intersectionObserverRef = useRef();\n useEffect(() => {\n if (BUILD_PLATFORM !== \"browser\") return;\n\n const intersectionObserver = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n handleTileIntersection(entry);\n }\n },\n {\n root: null,\n threshold: [0, ...getSteps(0.2, 0.8, 100), 1],\n rootMargin: \"0px 0px -10% 0px\",\n }\n );\n intersectionObserverRef.current = intersectionObserver;\n\n return () => {\n intersectionObserver.disconnect();\n };\n }, [handleTileIntersection]);\n\n // DONE?\n const updateObservedTiles = useCallback(() => {\n const intersectionObserver = intersectionObserverRef.current;\n if (!intersectionObserver || !containerEl.current) return;\n\n const children = containerEl.current.querySelectorAll(`.${css(\"tile-wrapper\")}`);\n\n const observedTiles = observedTilesRef.current;\n const remainingTiles = new Set(observedTiles);\n for (let i = 0; i < children.length; i++) {\n const el = children.item(i) as HTMLDivElement;\n\n if (remainingTiles.has(el)) {\n remainingTiles.delete(el);\n continue;\n }\n\n observedTiles.add(el);\n intersectionObserver.observe(el);\n }\n\n for (const el of remainingTiles.values()) {\n observedTiles.delete(el);\n intersectionObserver.unobserve(el);\n }\n }, [observedTilesRef]);\n\n useEffect(() => {\n updateObservedTiles();\n });\n\n return { containerEl, tileElements: tileElementsRef.current };\n}\n\nfunction useSelectedTile(\n tiles: Tile[],\n selectedImageId: string | undefined,\n tileElements: TilesElementMap\n) {\n const [showGallery, setShowGallery] = useState(!selectedImageId);\n const [isTransitioningToFullView, setIsTransitioningToFullView] = useState(false);\n const [isTransitioningFromFullView, setIsTransitioningFromFullView] = useState(false);\n const [fullViewTile, setFullViewTile] = useState();\n const pendingTransitionAnimation = useRef();\n\n const selectedTile = useMemo(\n () =>\n selectedImageId ? tiles.find((tile) => tile.image.id === selectedImageId) ?? null : null,\n [selectedImageId, tiles]\n );\n\n const [nextTile, previousTile] = useMemo(() => {\n if (!selectedTile) return [undefined, undefined];\n\n const i = tiles.indexOf(selectedTile);\n const nextTile = tiles[i + 1];\n const previousTile = tiles[i - 1];\n\n return [nextTile, previousTile];\n }, [tiles, selectedTile]);\n\n // Reset animation after transition to full view is complete.\n // This allows the transition back to be able to calculate the correct \"end\" coordinates.\n useEffect(() => {\n if (isTransitioningToFullView || isTransitioningFromFullView) return;\n if (!pendingTransitionAnimation.current) return;\n\n pendingTransitionAnimation.current.cancel();\n pendingTransitionAnimation.current = undefined;\n }, [isTransitioningToFullView, isTransitioningFromFullView]);\n\n useEffect(() => {\n if (selectedTile === fullViewTile) return;\n\n // Start animation\n if (selectedTile) {\n const tileElement = first(tileElements.getVisibleTileElements(selectedTile));\n\n if (tileElement && !fullViewTile) {\n // transition to full view\n tileElement.style.transform = \"scale(1)\";\n const animation = tileElement.animate(\n [\n getFullViewTransitionStartStyle(tileElement),\n getFullViewTransitionEndStyle(tileElement),\n ],\n { duration: 200, fill: \"forwards\", easing: \"ease\" }\n );\n\n animation.addEventListener(\"finish\", () => {\n // Save this animation so that it can be deleted when the animation is done and\n // final state is rendered. If animation is deleted before that, we will flicker\n // back to the original view momentarly.\n pendingTransitionAnimation.current = animation;\n\n // Render final post-transition state.\n setIsTransitioningToFullView(false);\n });\n\n setFullViewTile(selectedTile);\n setIsTransitioningToFullView(true);\n } else {\n // skip transition\n setFullViewTile(selectedTile);\n }\n } else if (fullViewTile) {\n const tileElement = first(tileElements.getVisibleTileElements(fullViewTile));\n\n if (tileElement) {\n // transition from full view\n setIsTransitioningFromFullView(true);\n setShowGallery(true);\n\n const animation = tileElement.animate(\n [\n getFullViewTransitionEndStyle(tileElement),\n getFullViewTransitionStartStyle(tileElement),\n ],\n { duration: 200, fill: \"forwards\", easing: \"ease\" }\n );\n animation.addEventListener(\"finish\", () => {\n /*\n ????\n if (intersectionObserver) {\n intersectionObserver\n .takeRecords()\n .forEach((entry) => handleTileIntersection(entry));\n }\n */\n\n // Render post-transition state\n setFullViewTile(null);\n setIsTransitioningFromFullView(false);\n\n // Delete this animation.\n // Note that deleting this animation does not need to wait for the above\n // state to be rendered.\n animation.cancel();\n });\n } else {\n // skip transition\n setFullViewTile(null);\n setShowGallery(true);\n }\n }\n }, [tileElements, fullViewTile, selectedTile]);\n\n return {\n fullViewTile,\n nextTile,\n previousTile,\n showGallery,\n isTransitioningFromFullView,\n isTransitioningToFullView,\n };\n}\n\nexport const Gallery: FunctionComponent = (props) => {\n const { tiles, selectedImageId, galleryId } = props;\n\n // DONE\n const routing = useContext(RoutingContext);\n\n // DONE\n const handleFullViewClose = useCallback(() => {\n const urlState = window.history.state;\n if (urlState && GALLERY_URL_STATE_SYMBOL in urlState) {\n history.back();\n } else {\n const url = getUrlForSelectedTile(galleryId, undefined);\n routing.push(url);\n }\n }, [routing, galleryId]);\n\n const { containerEl, tileElements } = useTileScrollObserver();\n\n const {\n showGallery,\n fullViewTile,\n nextTile,\n previousTile,\n isTransitioningFromFullView,\n isTransitioningToFullView,\n } = useSelectedTile(tiles, selectedImageId, tileElements);\n\n let handleGoToNext;\n let handleGoToPrevious;\n\n handleGoToNext = useCallback(() => {\n if (!fullViewTile) return;\n const i = tiles.indexOf(fullViewTile);\n const tile = tiles[i + 1];\n const url = getUrlForSelectedTile(galleryId, tile);\n assert(routing);\n routing.replace(url, {\n [GALLERY_URL_STATE_SYMBOL]: true,\n });\n }, [routing, galleryId, tiles, fullViewTile]);\n\n handleGoToPrevious = useCallback(() => {\n if (!fullViewTile) return;\n const i = tiles.indexOf(fullViewTile);\n const tile = tiles[i - 1];\n const url = getUrlForSelectedTile(galleryId, tile);\n assert(routing);\n routing.replace(url, {\n [GALLERY_URL_STATE_SYMBOL]: true,\n });\n }, [routing, galleryId, tiles, fullViewTile]);\n\n // DONE\n const handleTileClick = useCallback(\n (tile: Tile) => {\n const url = getUrlForSelectedTile(galleryId, tile);\n assert(routing);\n routing.push(url, {\n [GALLERY_URL_STATE_SYMBOL]: true,\n });\n },\n [routing, galleryId]\n );\n\n const tileEls = [];\n if (showGallery) {\n for (const tile of tiles) {\n const isSelected = tile === fullViewTile;\n tileEls.push(\n handleTileClick(tile)}\n tileElementRef={(tile: Tile) => tileElements.ref(tile)}\n />\n );\n }\n }\n\n let fullViewEl = null;\n if (fullViewTile) {\n fullViewEl = (\n \n );\n }\n\n let fullViewTransitionEl = null;\n if (isTransitioningToFullView) {\n fullViewTransitionEl =
;\n } else if (isTransitioningFromFullView) {\n fullViewTransitionEl =
;\n }\n\n return (\n
\n {fullViewTransitionEl}\n {fullViewEl}\n
\n {tileEls}\n
\n );\n};\n\nfunction getUrlForSelectedTile(galleryId: string, selectedTile?: Tile) {\n if (selectedTile) {\n return `/gallery/${galleryId}/${selectedTile.image.id}`;\n }\n\n return `/gallery/${galleryId}`;\n}\n\nexport function getSteps(start: number, end: number, steps: number): number[] {\n const arr = new Array(steps).fill(0).map((_, i) => {\n return (i / (steps - 1)) * (end - start) + start;\n });\n arr.push(end);\n return arr;\n}\n\ninterface TilesElementInfo {\n setElement: (el: HTMLElement | null) => void;\n currentElement: HTMLElement | null;\n}\n\nclass TilesElementMap {\n private refs = new WeakMap>();\n private visibleElements = new WeakSet();\n\n setVisible(el: HTMLElement, visible: boolean) {\n if (visible) this.visibleElements.add(el);\n else this.visibleElements.delete(el);\n }\n\n ref(tile: Tile, index = 0): (el: HTMLElement | null) => void {\n const { refs } = this;\n let refMap = refs.get(tile);\n if (!refMap) {\n refMap = new Map();\n refs.set(tile, refMap);\n }\n\n let info = refMap.get(index);\n if (!info) {\n const info2: TilesElementInfo = {\n setElement: (el: HTMLElement | null) => {\n info2.currentElement = el;\n },\n currentElement: null,\n };\n\n refMap.set(index, info2);\n info = info2;\n }\n\n return info.setElement;\n }\n\n *getVisibleTileElements(tile: Tile): Iterable {\n const infos = this.refs.get(tile)?.values();\n if (!infos) return;\n\n for (const info of infos) {\n const el = info.currentElement;\n if (el && this.visibleElements.has(el)) {\n yield el;\n }\n }\n }\n}\n\nfunction first(it: Iterable): T | undefined {\n for (const item of it) {\n return item;\n }\n\n return undefined;\n}\n", "import \"./gallery_controller.scss\";\n const mappedNames = {\"container\":\"_container_dsphr_1\"};\n\n function mapName(name) {\n if (!(name in mappedNames)) {\n // throw new Error(\"Unknown class name '\" + name + \"'.\");\n return null;\n }\n\n return mappedNames[name];\n }\n\n export default function(...args) {\n const results = [];\n for (const arg of args) {\n if (typeof arg === \"string\") {\n const mappedName = mapName(arg);\n if (mappedName) results.push(mappedName);\n } else if (typeof arg === \"object\") {\n for (const [name, active] of Object.entries(arg)) {\n const mappedName = mappedNames[name];\n if (active && mappedName) results.push(mappedName);\n }\n }\n }\n\n return results.join(\" \");\n }\n ", "import { h, FunctionComponent } from \"preact\";\nimport { useData } from \"../../data/react_hooks\";\nimport { Gallery } from \"../../gallery/gallery\";\nimport { AppError, AppErrorType } from \"../app_error\";\nimport { Gallery as GalleryComponent } from \"./gallery\";\n\nimport css from \"./gallery_controller.scss\";\n\ninterface Props {\n galleryId?: string;\n selectedImageId?: string;\n showTitle?: boolean;\n}\n\nexport const GalleryController: FunctionComponent = (props) => {\n const galleryData = useData([\"gallery\", props.galleryId!]);\n const showTitle = props.showTitle === undefined ?? true;\n\n if (!galleryData.exists) {\n throw new AppError(AppErrorType.PAGE_NOT_FOUND);\n }\n\n const gallery = galleryData.value as Gallery;\n let title;\n if (showTitle) {\n title =

{gallery.title}

;\n }\n return (\n
\n {title}\n \n {\n //
{JSON.stringify(galleryData, null, 2)}
\n }\n
\n );\n};\n"], "mappings": "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", "names": [] }