open-plant 1.1.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 (38) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/LICENSE +21 -0
  3. package/README.md +157 -0
  4. package/dist/index.cjs +94 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.js +2070 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/types/core/gl-utils.d.ts +4 -0
  9. package/dist/types/core/gl-utils.d.ts.map +1 -0
  10. package/dist/types/core/m1-tile-renderer.d.ts +42 -0
  11. package/dist/types/core/m1-tile-renderer.d.ts.map +1 -0
  12. package/dist/types/core/ortho-camera.d.ts +19 -0
  13. package/dist/types/core/ortho-camera.d.ts.map +1 -0
  14. package/dist/types/core/types.d.ts +7 -0
  15. package/dist/types/core/types.d.ts.map +1 -0
  16. package/dist/types/index.d.ts +18 -0
  17. package/dist/types/index.d.ts.map +1 -0
  18. package/dist/types/react/draw-layer.d.ts +79 -0
  19. package/dist/types/react/draw-layer.d.ts.map +1 -0
  20. package/dist/types/react/overview-map.d.ts +34 -0
  21. package/dist/types/react/overview-map.d.ts.map +1 -0
  22. package/dist/types/react/tile-viewer-canvas.d.ts +13 -0
  23. package/dist/types/react/tile-viewer-canvas.d.ts.map +1 -0
  24. package/dist/types/react/wsi-viewer-canvas.d.ts +46 -0
  25. package/dist/types/react/wsi-viewer-canvas.d.ts.map +1 -0
  26. package/dist/types/wsi/constants.d.ts +2 -0
  27. package/dist/types/wsi/constants.d.ts.map +1 -0
  28. package/dist/types/wsi/image-info.d.ts +4 -0
  29. package/dist/types/wsi/image-info.d.ts.map +1 -0
  30. package/dist/types/wsi/point-clip.d.ts +5 -0
  31. package/dist/types/wsi/point-clip.d.ts.map +1 -0
  32. package/dist/types/wsi/types.d.ts +47 -0
  33. package/dist/types/wsi/types.d.ts.map +1 -0
  34. package/dist/types/wsi/utils.d.ts +13 -0
  35. package/dist/types/wsi/utils.d.ts.map +1 -0
  36. package/dist/types/wsi/wsi-tile-renderer.d.ts +42 -0
  37. package/dist/types/wsi/wsi-tile-renderer.d.ts.map +1 -0
  38. package/package.json +67 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/core/gl-utils.ts","../src/core/ortho-camera.ts","../src/core/m1-tile-renderer.ts","../src/wsi/constants.ts","../src/wsi/utils.ts","../src/react/draw-layer.tsx","../src/wsi/image-info.ts","../src/react/overview-map.tsx","../src/react/tile-viewer-canvas.tsx","../src/wsi/point-clip.ts","../src/wsi/wsi-tile-renderer.ts","../src/react/wsi-viewer-canvas.tsx"],"sourcesContent":["function compileShader(gl: WebGL2RenderingContext, type: number, source: string): WebGLShader {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new Error(\"Failed to create shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS);\n if (!ok) {\n const log = gl.getShaderInfoLog(shader) ?? \"unknown shader error\";\n gl.deleteShader(shader);\n throw new Error(log);\n }\n\n return shader;\n}\n\nexport function createProgram(gl: WebGL2RenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram {\n const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n\n const program = gl.createProgram();\n if (!program) {\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n throw new Error(\"Failed to create program.\");\n }\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n const ok = gl.getProgramParameter(program, gl.LINK_STATUS);\n if (!ok) {\n const log = gl.getProgramInfoLog(program) ?? \"unknown link error\";\n gl.deleteProgram(program);\n throw new Error(log);\n }\n\n return program;\n}\n\nexport function requireUniformLocation(\n gl: WebGL2RenderingContext,\n program: WebGLProgram,\n uniformName: string,\n): WebGLUniformLocation {\n const location = gl.getUniformLocation(program, uniformName);\n if (!location) {\n throw new Error(`Failed to get uniform location: ${uniformName}`);\n }\n return location;\n}\n\nexport function requireWebGL2(canvas: HTMLCanvasElement): WebGL2RenderingContext {\n const context = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!context) {\n throw new Error(\"WebGL2 is not available.\");\n }\n\n return context;\n}\n","export interface ViewState {\n offsetX: number;\n offsetY: number;\n zoom: number;\n}\n\nexport class OrthoCamera {\n private viewportWidth = 1;\n private viewportHeight = 1;\n\n private viewState: ViewState = {\n offsetX: 0,\n offsetY: 0,\n zoom: 1,\n };\n\n setViewport(width: number, height: number): void {\n this.viewportWidth = Math.max(1, width);\n this.viewportHeight = Math.max(1, height);\n }\n\n getViewportSize(): { width: number; height: number } {\n return {\n width: this.viewportWidth,\n height: this.viewportHeight,\n };\n }\n\n setViewState(next: Partial<ViewState>): void {\n if (next.offsetX !== undefined) {\n this.viewState.offsetX = next.offsetX;\n }\n\n if (next.offsetY !== undefined) {\n this.viewState.offsetY = next.offsetY;\n }\n\n if (next.zoom !== undefined) {\n this.viewState.zoom = Math.max(0.0001, next.zoom);\n }\n }\n\n getViewState(): ViewState {\n return { ...this.viewState };\n }\n\n getMatrix(): Float32Array {\n const viewWidth = this.viewportWidth / this.viewState.zoom;\n const viewHeight = this.viewportHeight / this.viewState.zoom;\n\n const sx = 2 / viewWidth;\n const sy = -2 / viewHeight;\n const tx = -1 - this.viewState.offsetX * sx;\n const ty = 1 - this.viewState.offsetY * sy;\n\n return new Float32Array([\n sx,\n 0,\n 0,\n 0,\n sy,\n 0,\n tx,\n ty,\n 1,\n ]);\n }\n}\n","import {\n\tcreateProgram,\n\trequireUniformLocation,\n\trequireWebGL2,\n} from \"./gl-utils\";\nimport { OrthoCamera, type ViewState } from \"./ortho-camera\";\nimport type { Bounds, TileDefinition } from \"./types\";\n\ninterface LoadedTile {\n\tid: string;\n\tbounds: Bounds;\n\ttexture: WebGLTexture;\n}\n\nexport interface M1TileRendererOptions {\n\tcanvas: HTMLCanvasElement;\n\timageWidth: number;\n\timageHeight: number;\n\tclearColor?: [number, number, number, number];\n\tinitialViewState?: Partial<ViewState>;\n}\n\nconst VERTEX_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 aUnit;\nin vec2 aUv;\n\nuniform mat3 uCamera;\nuniform vec4 uBounds;\n\nout vec2 vUv;\n\nvoid main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n}\n`;\n\nconst FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 vUv;\nuniform sampler2D uTexture;\n\nout vec4 outColor;\n\nvoid main() {\n outColor = texture(uTexture, vUv);\n}\n`;\n\nexport class M1TileRenderer {\n\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly imageWidth: number;\n\tprivate readonly imageHeight: number;\n\tprivate readonly clearColor: [number, number, number, number];\n\tprivate readonly program: WebGLProgram;\n\tprivate readonly vao: WebGLVertexArrayObject;\n\tprivate readonly quadBuffer: WebGLBuffer;\n\tprivate readonly uCameraLocation: WebGLUniformLocation;\n\tprivate readonly uBoundsLocation: WebGLUniformLocation;\n\tprivate readonly uTextureLocation: WebGLUniformLocation;\n\tprivate readonly resizeObserver: ResizeObserver;\n\n\tprivate tiles: LoadedTile[] = [];\n\tprivate frameId: number | null = null;\n\tprivate loadVersion = 0;\n\tprivate destroyed = false;\n\tprivate fitted = false;\n\tprivate controlledViewState = false;\n\n\tconstructor(options: M1TileRendererOptions) {\n\t\tthis.canvas = options.canvas;\n\t\tthis.imageWidth = Math.max(1, options.imageWidth);\n\t\tthis.imageHeight = Math.max(1, options.imageHeight);\n\t\tthis.clearColor = options.clearColor ?? [0.03, 0.05, 0.08, 1];\n\n\t\tthis.gl = requireWebGL2(this.canvas);\n\t\tthis.program = createProgram(this.gl, VERTEX_SHADER, FRAGMENT_SHADER);\n\n\t\tconst vao = this.gl.createVertexArray();\n\t\tconst quadBuffer = this.gl.createBuffer();\n\t\tif (!vao || !quadBuffer) {\n\t\t\tthrow new Error(\"Failed to create WebGL buffers.\");\n\t\t}\n\n\t\tthis.vao = vao;\n\t\tthis.quadBuffer = quadBuffer;\n\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.quadBuffer);\n\n\t\tconst quadVertices = new Float32Array([\n\t\t\t0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1,\n\t\t]);\n\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\n\t\tconst unitLocation = this.gl.getAttribLocation(this.program, \"aUnit\");\n\t\tconst uvLocation = this.gl.getAttribLocation(this.program, \"aUv\");\n\t\tif (unitLocation < 0 || uvLocation < 0) {\n\t\t\tthrow new Error(\"Failed to get attribute locations.\");\n\t\t}\n\n\t\tconst stride = 4 * Float32Array.BYTES_PER_ELEMENT;\n\t\tthis.gl.enableVertexAttribArray(unitLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tunitLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t0,\n\t\t);\n\t\tthis.gl.enableVertexAttribArray(uvLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tuvLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t2 * Float32Array.BYTES_PER_ELEMENT,\n\t\t);\n\n\t\tthis.gl.bindVertexArray(null);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n\n\t\tthis.uCameraLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uCamera\",\n\t\t);\n\t\tthis.uBoundsLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uBounds\",\n\t\t);\n\t\tthis.uTextureLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uTexture\",\n\t\t);\n\n\t\tif (options.initialViewState) {\n\t\t\tthis.controlledViewState = true;\n\t\t\tthis.camera.setViewState(options.initialViewState);\n\t\t}\n\n\t\tthis.resizeObserver = new ResizeObserver(() => {\n\t\t\tthis.resize();\n\t\t});\n\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.resize();\n\t}\n\n\tasync setTiles(tiles: TileDefinition[]): Promise<void> {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst version = ++this.loadVersion;\n\n\t\tconst loaded = await Promise.all(\n\t\t\ttiles.map(async (tile) => {\n\t\t\t\tconst loadedTile = await this.loadTile(tile, version);\n\t\t\t\treturn loadedTile;\n\t\t\t}),\n\t\t);\n\n\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\tfor (const tile of loaded) {\n\t\t\t\tif (tile) {\n\t\t\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = loaded.filter((tile): tile is LoadedTile => tile !== null);\n\t\tthis.requestRender();\n\t}\n\n\tsetViewState(viewState: Partial<ViewState>): void {\n\t\tthis.controlledViewState = true;\n\t\tthis.camera.setViewState(viewState);\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): ViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.destroyed = true;\n\t\tthis.loadVersion += 1;\n\n\t\tif (this.frameId !== null) {\n\t\t\tcancelAnimationFrame(this.frameId);\n\t\t\tthis.frameId = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = [];\n\n\t\tthis.gl.deleteBuffer(this.quadBuffer);\n\t\tthis.gl.deleteVertexArray(this.vao);\n\t\tthis.gl.deleteProgram(this.program);\n\t}\n\n\tprivate async loadTile(\n\t\ttile: TileDefinition,\n\t\tversion: number,\n\t): Promise<LoadedTile | null> {\n\t\ttry {\n\t\t\tconst response = await fetch(tile.url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Tile fetch failed: ${response.status} ${response.statusText}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst blob = await response.blob();\n\t\t\tconst bitmap = await createImageBitmap(blob);\n\n\t\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\t\tbitmap.close();\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst texture = this.gl.createTexture();\n\t\t\tif (!texture) {\n\t\t\t\tbitmap.close();\n\t\t\t\tthrow new Error(\"Failed to create tile texture.\");\n\t\t\t}\n\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_S,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_T,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MIN_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MAG_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texImage2D(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t0,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\tbitmap,\n\t\t\t);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\t\tbitmap.close();\n\n\t\t\treturn {\n\t\t\t\tid: tile.id,\n\t\t\t\tbounds: tile.bounds,\n\t\t\t\ttexture,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`[M1TileRenderer] tile load failed: ${tile.id}`, error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate resize(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssWidth = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssHeight = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst targetWidth = Math.max(1, Math.round(cssWidth * dpr));\n\t\tconst targetHeight = Math.max(1, Math.round(cssHeight * dpr));\n\n\t\tif (\n\t\t\tthis.canvas.width !== targetWidth ||\n\t\t\tthis.canvas.height !== targetHeight\n\t\t) {\n\t\t\tthis.canvas.width = targetWidth;\n\t\t\tthis.canvas.height = targetHeight;\n\t\t}\n\n\t\tthis.camera.setViewport(cssWidth, cssHeight);\n\t\tthis.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\n\t\tif (!this.fitted && !this.controlledViewState) {\n\t\t\tthis.fitToImage();\n\t\t\tthis.fitted = true;\n\t\t}\n\n\t\tthis.requestRender();\n\t}\n\n\tprivate fitToImage(): void {\n\t\tconst viewport = this.camera.getViewportSize();\n\n\t\tconst zoom = Math.min(\n\t\t\tviewport.width / this.imageWidth,\n\t\t\tviewport.height / this.imageHeight,\n\t\t);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tconst visibleWorldWidth = viewport.width / safeZoom;\n\t\tconst visibleWorldHeight = viewport.height / safeZoom;\n\n\t\tconst offsetX = (this.imageWidth - visibleWorldWidth) * 0.5;\n\t\tconst offsetY = (this.imageHeight - visibleWorldHeight) * 0.5;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: safeZoom,\n\t\t\toffsetX,\n\t\t\toffsetY,\n\t\t});\n\t}\n\n\tprivate requestRender(): void {\n\t\tif (this.frameId !== null || this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.frameId = requestAnimationFrame(() => {\n\t\t\tthis.frameId = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tprivate render(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.gl.clearColor(\n\t\t\tthis.clearColor[0],\n\t\t\tthis.clearColor[1],\n\t\t\tthis.clearColor[2],\n\t\t\tthis.clearColor[3],\n\t\t);\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tthis.gl.useProgram(this.program);\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.uniformMatrix3fv(\n\t\t\tthis.uCameraLocation,\n\t\t\tfalse,\n\t\t\tthis.camera.getMatrix(),\n\t\t);\n\t\tthis.gl.uniform1i(this.uTextureLocation, 0);\n\n\t\tfor (const tile of this.tiles) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, tile.texture);\n\t\t\tthis.gl.uniform4f(\n\t\t\t\tthis.uBoundsLocation,\n\t\t\t\ttile.bounds[0],\n\t\t\t\ttile.bounds[1],\n\t\t\t\ttile.bounds[2],\n\t\t\t\ttile.bounds[3],\n\t\t\t);\n\t\t\tthis.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\tthis.gl.bindVertexArray(null);\n\t}\n\n\tprivate disposeTiles(tiles: LoadedTile[]): void {\n\t\tfor (const tile of tiles) {\n\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t}\n\t}\n}\n","export const DEFAULT_POINT_COLOR: [number, number, number, number] = [\n\t160, 160, 160, 255,\n];\n","import { DEFAULT_POINT_COLOR } from \"./constants\";\nimport type { TermPalette, WsiViewState } from \"./types\";\n\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nexport function calcScaleResolution(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): number {\n\tconst mpp = Number(imageMpp);\n\tconst z0 = Number(imageZoom);\n\tconst z1 = Number(currentZoom);\n\tif (!Number.isFinite(mpp) || mpp <= 0) return 1;\n\tif (!Number.isFinite(z0) || !Number.isFinite(z1)) return mpp;\n\treturn Math.pow(2, z0 - z1) * mpp;\n}\n\nexport function calcScaleLength(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): string {\n\tconst resolution = calcScaleResolution(imageMpp, imageZoom, currentZoom);\n\tlet length = 100 * resolution;\n\tif (Number(imageMpp)) {\n\t\tlet unit = \"μm\";\n\t\tif (length > 1000) {\n\t\t\tlength /= 1000;\n\t\t\tunit = \"mm\";\n\t\t}\n\t\treturn `${length.toPrecision(3)} ${unit}`;\n\t}\n\treturn `${Math.round(length * 1000) / 1000} pixels`;\n}\n\nexport function isSameViewState(\n\ta: Partial<WsiViewState> | null | undefined,\n\tb: Partial<WsiViewState> | null | undefined,\n): boolean {\n\tif (!a && !b) return true;\n\tif (!a || !b) return false;\n\treturn (\n\t\tMath.abs((a.zoom ?? 0) - (b.zoom ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetX ?? 0) - (b.offsetX ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetY ?? 0) - (b.offsetY ?? 0)) < 1e-6\n\t);\n}\n\nexport function toBearerToken(value: string | null | undefined): string {\n\tconst trimmed = String(value ?? \"\").trim();\n\tif (!trimmed) return \"\";\n\tif (/^bearer\\s+/i.test(trimmed)) {\n\t\tconst token = trimmed.replace(/^bearer\\s+/i, \"\").trim();\n\t\treturn token ? `Bearer ${token}` : \"\";\n\t}\n\treturn `Bearer ${trimmed}`;\n}\n\nexport function hexToRgba(\n\thex: string | null | undefined,\n): [number, number, number, number] {\n\tconst value = String(hex ?? \"\").trim();\n\tconst match = value.match(/^#?([0-9a-fA-F]{6})$/);\n\tif (!match) return [...DEFAULT_POINT_COLOR];\n\n\tconst n = Number.parseInt(match[1], 16);\n\treturn [(n >> 16) & 255, (n >> 8) & 255, n & 255, 255];\n}\n\nexport function buildTermPalette(\n\tterms:\n\t\t| Array<{ termId?: string | null; termColor?: string | null }>\n\t\t| null\n\t\t| undefined,\n): TermPalette {\n\tconst palette: Array<[number, number, number, number]> = [\n\t\t[...DEFAULT_POINT_COLOR],\n\t];\n\tconst termToPaletteIndex = new Map<string, number>();\n\n\tfor (const term of terms ?? []) {\n\t\tconst termId = String(term?.termId ?? \"\");\n\t\tif (!termId || termToPaletteIndex.has(termId)) continue;\n\n\t\ttermToPaletteIndex.set(termId, palette.length);\n\t\tpalette.push(hexToRgba(term?.termColor));\n\t}\n\n\tconst colors = new Uint8Array(palette.length * 4);\n\tfor (let i = 0; i < palette.length; i += 1) {\n\t\tcolors[i * 4] = palette[i][0];\n\t\tcolors[i * 4 + 1] = palette[i][1];\n\t\tcolors[i * 4 + 2] = palette[i][2];\n\t\tcolors[i * 4 + 3] = palette[i][3];\n\t}\n\n\treturn { colors, termToPaletteIndex };\n}\n\nexport function createProgram(\n\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n): WebGLProgram {\n\tconst vs = gl.createShader(gl.VERTEX_SHADER);\n\tconst fs = gl.createShader(gl.FRAGMENT_SHADER);\n\tif (!vs || !fs) {\n\t\tthrow new Error(\"Shader allocation failed\");\n\t}\n\n\tgl.shaderSource(vs, vertexSource);\n\tgl.compileShader(vs);\n\tif (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(vs) || \"vertex compile failed\");\n\t}\n\n\tgl.shaderSource(fs, fragmentSource);\n\tgl.compileShader(fs);\n\tif (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(fs) || \"fragment compile failed\");\n\t}\n\n\tconst program = gl.createProgram();\n\tif (!program) {\n\t\tthrow new Error(\"Program allocation failed\");\n\t}\n\n\tgl.attachShader(program, vs);\n\tgl.attachShader(program, fs);\n\tgl.linkProgram(program);\n\n\tgl.deleteShader(vs);\n\tgl.deleteShader(fs);\n\n\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\tthrow new Error(gl.getProgramInfoLog(program) || \"program link failed\");\n\t}\n\n\treturn program;\n}\n","import {\n\ttype CSSProperties,\n\ttype MutableRefObject,\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n} from \"react\";\nimport { calcScaleResolution } from \"../wsi/utils\";\n\nexport type StampDrawTool =\n\t| \"stamp-rectangle\"\n\t| \"stamp-circle\"\n\t| \"stamp-rectangle-2mm2\"\n\t| \"stamp-circle-2mm2\"\n\t| \"stamp-circle-hpf-0.2mm2\";\n\nexport type DrawTool =\n\t| \"cursor\"\n\t| \"freehand\"\n\t| \"rectangle\"\n\t| \"circular\"\n\t| StampDrawTool;\n\nexport type DrawCoordinate = [number, number];\n\nexport type DrawBounds = [number, number, number, number];\n\nexport interface DrawResult {\n\ttool: Exclude<DrawTool, \"cursor\">;\n\tcoordinates: DrawCoordinate[];\n\tbbox: DrawBounds;\n\tareaPx: number;\n}\n\nexport interface DrawRegion {\n\tid?: string | number;\n\tcoordinates: DrawCoordinate[];\n\tlabel?: string;\n}\n\nexport interface RegionStrokeStyle {\n\tcolor: string;\n\twidth: number;\n\tlineDash: number[];\n\tlineJoin: CanvasLineJoin;\n\tlineCap: CanvasLineCap;\n\tshadowColor: string;\n\tshadowBlur: number;\n\tshadowOffsetX: number;\n\tshadowOffsetY: number;\n}\n\nexport interface RegionLabelStyle {\n\tfontFamily: string;\n\tfontSize: number;\n\tfontWeight: string | number;\n\ttextColor: string;\n\tbackgroundColor: string;\n\tborderColor: string;\n\tborderWidth: number;\n\tpaddingX: number;\n\tpaddingY: number;\n\toffsetY: number;\n\tborderRadius: number;\n}\n\nexport interface DrawProjector {\n\tscreenToWorld(clientX: number, clientY: number): DrawCoordinate | number[];\n\tworldToScreen(worldX: number, worldY: number): DrawCoordinate | number[];\n\tgetViewState?: () => { zoom: number };\n}\n\nexport interface StampOptions {\n\trectangleAreaMm2?: number;\n\tcircleAreaMm2?: number;\n}\n\nexport interface DrawLayerProps {\n\ttool: DrawTool;\n\timageWidth: number;\n\timageHeight: number;\n\timageMpp?: number;\n\timageZoom?: number;\n\tstampOptions?: StampOptions;\n\tprojectorRef: RefObject<DrawProjector | null>;\n\tonDrawComplete?: (result: DrawResult) => void;\n\tenabled?: boolean;\n\tviewStateSignal?: unknown;\n\tpersistedRegions?: DrawRegion[];\n\tpersistedPolygons?: DrawCoordinate[][];\n\tregionStrokeStyle?: Partial<RegionStrokeStyle>;\n\tregionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n\tregionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n\thoveredRegionId?: string | number | null;\n\tactiveRegionId?: string | number | null;\n\tregionLabelStyle?: Partial<RegionLabelStyle>;\n\tinvalidateRef?: MutableRefObject<(() => void) | null>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\ninterface DrawSession {\n\tisDrawing: boolean;\n\tpointerId: number | null;\n\tstart: DrawCoordinate | null;\n\tcurrent: DrawCoordinate | null;\n\tpoints: DrawCoordinate[];\n\tstampCenter: DrawCoordinate | null;\n}\n\nconst DRAW_FILL = \"rgba(255, 77, 79, 0.16)\";\nconst FREEHAND_MIN_POINTS = 3;\nconst FREEHAND_SCREEN_STEP = 2;\nconst CIRCLE_SIDES = 96;\nconst MIN_AREA_PX = 1;\nconst EMPTY_REGIONS: DrawRegion[] = [];\nconst EMPTY_DASH: number[] = [];\nconst MICRONS_PER_MM = 1000;\nconst DEFAULT_STAMP_RECTANGLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_CIRCLE_AREA_MM2 = 2;\nconst LEGACY_HPF_CIRCLE_AREA_MM2 = 0.2;\n\nconst DEFAULT_REGION_STROKE_STYLE: RegionStrokeStyle = {\n\tcolor: \"#ff4d4f\",\n\twidth: 2,\n\tlineDash: EMPTY_DASH,\n\tlineJoin: \"round\",\n\tlineCap: \"round\",\n\tshadowColor: \"rgba(0, 0, 0, 0)\",\n\tshadowBlur: 0,\n\tshadowOffsetX: 0,\n\tshadowOffsetY: 0,\n};\n\nconst DEFAULT_REGION_LABEL_STYLE: RegionLabelStyle = {\n\tfontFamily:\n\t\t\"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n\tfontSize: 12,\n\tfontWeight: 500,\n\ttextColor: \"#ffffff\",\n\tbackgroundColor: \"rgba(8, 14, 22, 0.88)\",\n\tborderColor: \"rgba(255, 77, 79, 0.85)\",\n\tborderWidth: 1,\n\tpaddingX: 6,\n\tpaddingY: 4,\n\toffsetY: 10,\n\tborderRadius: 3,\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nfunction isStampTool(tool: DrawTool): tool is StampDrawTool {\n\treturn (\n\t\ttool === \"stamp-rectangle\" ||\n\t\ttool === \"stamp-circle\" ||\n\t\ttool === \"stamp-rectangle-2mm2\" ||\n\t\ttool === \"stamp-circle-2mm2\" ||\n\t\ttool === \"stamp-circle-hpf-0.2mm2\"\n\t);\n}\n\nfunction clampPositiveOrFallback(\n\tvalue: number | undefined,\n\tfallback: number,\n): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n\t\treturn fallback;\n\t}\n\treturn value;\n}\n\nfunction resolveStampOptions(options: StampOptions | undefined): Required<StampOptions> {\n\treturn {\n\t\trectangleAreaMm2: clampPositiveOrFallback(\n\t\t\toptions?.rectangleAreaMm2,\n\t\t\tDEFAULT_STAMP_RECTANGLE_AREA_MM2,\n\t\t),\n\t\tcircleAreaMm2: clampPositiveOrFallback(\n\t\t\toptions?.circleAreaMm2,\n\t\t\tDEFAULT_STAMP_CIRCLE_AREA_MM2,\n\t\t),\n\t};\n}\n\nfunction mm2ToUm2(areaMm2: number): number {\n\treturn areaMm2 * MICRONS_PER_MM * MICRONS_PER_MM;\n}\n\nfunction createSquareFromCenter(\n\tcenter: DrawCoordinate | null,\n\thalfLength: number,\n): DrawCoordinate[] {\n\tif (!center || !Number.isFinite(halfLength) || halfLength <= 0) return [];\n\treturn closeRing([\n\t\t[center[0] - halfLength, center[1] - halfLength],\n\t\t[center[0] + halfLength, center[1] - halfLength],\n\t\t[center[0] + halfLength, center[1] + halfLength],\n\t\t[center[0] - halfLength, center[1] + halfLength],\n\t]);\n}\n\nfunction createCircleFromCenter(\n\tcenter: DrawCoordinate | null,\n\tradius: number,\n\tsides = CIRCLE_SIDES,\n): DrawCoordinate[] {\n\tif (!center || !Number.isFinite(radius) || radius <= 0) return [];\n\n\tconst coords: DrawCoordinate[] = [];\n\tfor (let i = 0; i <= sides; i += 1) {\n\t\tconst t = (i / sides) * Math.PI * 2;\n\t\tcoords.push([\n\t\t\tcenter[0] + Math.cos(t) * radius,\n\t\t\tcenter[1] + Math.sin(t) * radius,\n\t\t]);\n\t}\n\n\treturn closeRing(coords);\n}\n\nexport function closeRing(coords: DrawCoordinate[]): DrawCoordinate[] {\n\tif (!Array.isArray(coords) || coords.length < 3) return [];\n\n\tconst out = coords.map(([x, y]) => [x, y] as DrawCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\n\treturn out;\n}\n\nexport function createRectangle(\n\tstart: DrawCoordinate | null,\n\tend: DrawCoordinate | null,\n): DrawCoordinate[] {\n\tif (!start || !end) return [];\n\n\treturn closeRing([\n\t\t[start[0], start[1]],\n\t\t[end[0], start[1]],\n\t\t[end[0], end[1]],\n\t\t[start[0], end[1]],\n\t]);\n}\n\nexport function createCircle(\n\tstart: DrawCoordinate | null,\n\tend: DrawCoordinate | null,\n\tsides = CIRCLE_SIDES,\n): DrawCoordinate[] {\n\tif (!start || !end) return [];\n\n\tconst centerX = (start[0] + end[0]) * 0.5;\n\tconst centerY = (start[1] + end[1]) * 0.5;\n\tconst radius = Math.hypot(end[0] - start[0], end[1] - start[1]) * 0.5;\n\tif (radius < 1) return [];\n\n\tconst coords: DrawCoordinate[] = [];\n\tfor (let i = 0; i <= sides; i += 1) {\n\t\tconst t = (i / sides) * Math.PI * 2;\n\t\tcoords.push([\n\t\t\tcenterX + Math.cos(t) * radius,\n\t\t\tcenterY + Math.sin(t) * radius,\n\t\t]);\n\t}\n\n\treturn closeRing(coords);\n}\n\nfunction polygonArea(coords: DrawCoordinate[]): number {\n\tif (!Array.isArray(coords) || coords.length < 4) return 0;\n\n\tlet sum = 0;\n\tfor (let i = 0; i < coords.length - 1; i += 1) {\n\t\tconst a = coords[i];\n\t\tconst b = coords[i + 1];\n\t\tsum += a[0] * b[1] - b[0] * a[1];\n\t}\n\n\treturn Math.abs(sum * 0.5);\n}\n\nfunction computeBounds(coords: DrawCoordinate[]): DrawBounds {\n\tif (!Array.isArray(coords) || coords.length === 0) return [0, 0, 0, 0];\n\n\tlet minX = Infinity;\n\tlet minY = Infinity;\n\tlet maxX = -Infinity;\n\tlet maxY = -Infinity;\n\n\tfor (const [x, y] of coords) {\n\t\tif (x < minX) minX = x;\n\t\tif (x > maxX) maxX = x;\n\t\tif (y < minY) minY = y;\n\t\tif (y > maxY) maxY = y;\n\t}\n\n\treturn [minX, minY, maxX, maxY];\n}\n\nfunction isValidPolygon(coords: DrawCoordinate[]): boolean {\n\treturn (\n\t\tArray.isArray(coords) &&\n\t\tcoords.length >= 4 &&\n\t\tpolygonArea(coords) > MIN_AREA_PX\n\t);\n}\n\nfunction drawPath(\n\tctx: CanvasRenderingContext2D,\n\tpoints: DrawCoordinate[],\n\tstrokeStyle: RegionStrokeStyle,\n\tclose = false,\n\tfill = false,\n): void {\n\tif (points.length === 0) return;\n\n\tctx.beginPath();\n\tctx.moveTo(points[0][0], points[0][1]);\n\tfor (let i = 1; i < points.length; i += 1) {\n\t\tctx.lineTo(points[i][0], points[i][1]);\n\t}\n\n\tif (close) {\n\t\tctx.closePath();\n\t}\n\tif (fill && close) {\n\t\tctx.fillStyle = DRAW_FILL;\n\t\tctx.fill();\n\t}\n\n\tctx.strokeStyle = strokeStyle.color;\n\tctx.lineWidth = strokeStyle.width;\n\tctx.lineJoin = strokeStyle.lineJoin;\n\tctx.lineCap = strokeStyle.lineCap;\n\tctx.shadowColor = strokeStyle.shadowColor;\n\tctx.shadowBlur = strokeStyle.shadowBlur;\n\tctx.shadowOffsetX = strokeStyle.shadowOffsetX;\n\tctx.shadowOffsetY = strokeStyle.shadowOffsetY;\n\tctx.setLineDash(strokeStyle.lineDash);\n\tctx.stroke();\n\tctx.setLineDash(EMPTY_DASH);\n\tctx.shadowColor = \"rgba(0, 0, 0, 0)\";\n\tctx.shadowBlur = 0;\n\tctx.shadowOffsetX = 0;\n\tctx.shadowOffsetY = 0;\n}\n\nfunction resolveStrokeStyle(\n\tstyle: Partial<RegionStrokeStyle> | undefined,\n): RegionStrokeStyle {\n\tconst dash = Array.isArray(style?.lineDash)\n\t\t? style.lineDash.filter((value) => Number.isFinite(value) && value >= 0)\n\t\t: EMPTY_DASH;\n\tconst width =\n\t\ttypeof style?.width === \"number\" && Number.isFinite(style.width)\n\t\t\t? Math.max(0, style.width)\n\t\t\t: DEFAULT_REGION_STROKE_STYLE.width;\n\tconst shadowBlur =\n\t\ttypeof style?.shadowBlur === \"number\" && Number.isFinite(style.shadowBlur)\n\t\t\t? Math.max(0, style.shadowBlur)\n\t\t\t: DEFAULT_REGION_STROKE_STYLE.shadowBlur;\n\tconst shadowOffsetX =\n\t\ttypeof style?.shadowOffsetX === \"number\" &&\n\t\tNumber.isFinite(style.shadowOffsetX)\n\t\t\t? style.shadowOffsetX\n\t\t\t: DEFAULT_REGION_STROKE_STYLE.shadowOffsetX;\n\tconst shadowOffsetY =\n\t\ttypeof style?.shadowOffsetY === \"number\" &&\n\t\tNumber.isFinite(style.shadowOffsetY)\n\t\t\t? style.shadowOffsetY\n\t\t\t: DEFAULT_REGION_STROKE_STYLE.shadowOffsetY;\n\treturn {\n\t\tcolor: style?.color || DEFAULT_REGION_STROKE_STYLE.color,\n\t\twidth,\n\t\tlineDash: dash.length ? dash : EMPTY_DASH,\n\t\tlineJoin: style?.lineJoin || DEFAULT_REGION_STROKE_STYLE.lineJoin,\n\t\tlineCap: style?.lineCap || DEFAULT_REGION_STROKE_STYLE.lineCap,\n\t\tshadowColor: style?.shadowColor || DEFAULT_REGION_STROKE_STYLE.shadowColor,\n\t\tshadowBlur,\n\t\tshadowOffsetX,\n\t\tshadowOffsetY,\n\t};\n}\n\nfunction mergeStrokeStyle(\n\tbase: RegionStrokeStyle,\n\toverride: Partial<RegionStrokeStyle> | undefined,\n): RegionStrokeStyle {\n\tif (!override) return base;\n\treturn resolveStrokeStyle({\n\t\tcolor: override.color ?? base.color,\n\t\twidth: override.width ?? base.width,\n\t\tlineDash: override.lineDash ?? base.lineDash,\n\t\tlineJoin: override.lineJoin ?? base.lineJoin,\n\t\tlineCap: override.lineCap ?? base.lineCap,\n\t\tshadowColor: override.shadowColor ?? base.shadowColor,\n\t\tshadowBlur: override.shadowBlur ?? base.shadowBlur,\n\t\tshadowOffsetX: override.shadowOffsetX ?? base.shadowOffsetX,\n\t\tshadowOffsetY: override.shadowOffsetY ?? base.shadowOffsetY,\n\t});\n}\n\nfunction isSameRegionId(\n\ta: string | number | null | undefined,\n\tb: string | number | null | undefined,\n): boolean {\n\tif (a === null || a === undefined || b === null || b === undefined) {\n\t\treturn false;\n\t}\n\treturn String(a) === String(b);\n}\n\nfunction resolveLabelStyle(\n\tstyle: Partial<RegionLabelStyle> | undefined,\n): RegionLabelStyle {\n\tconst px =\n\t\ttypeof style?.paddingX === \"number\" && Number.isFinite(style.paddingX)\n\t\t\t? Math.max(0, style.paddingX)\n\t\t\t: DEFAULT_REGION_LABEL_STYLE.paddingX;\n\tconst py =\n\t\ttypeof style?.paddingY === \"number\" && Number.isFinite(style.paddingY)\n\t\t\t? Math.max(0, style.paddingY)\n\t\t\t: DEFAULT_REGION_LABEL_STYLE.paddingY;\n\tconst fs =\n\t\ttypeof style?.fontSize === \"number\" && Number.isFinite(style.fontSize)\n\t\t\t? Math.max(8, style.fontSize)\n\t\t\t: DEFAULT_REGION_LABEL_STYLE.fontSize;\n\tconst bw =\n\t\ttypeof style?.borderWidth === \"number\" && Number.isFinite(style.borderWidth)\n\t\t\t? Math.max(0, style.borderWidth)\n\t\t\t: DEFAULT_REGION_LABEL_STYLE.borderWidth;\n\tconst oy =\n\t\ttypeof style?.offsetY === \"number\" && Number.isFinite(style.offsetY)\n\t\t\t? style.offsetY\n\t\t\t: DEFAULT_REGION_LABEL_STYLE.offsetY;\n\tconst br =\n\t\ttypeof style?.borderRadius === \"number\" &&\n\t\tNumber.isFinite(style.borderRadius)\n\t\t\t? Math.max(0, style.borderRadius)\n\t\t\t: DEFAULT_REGION_LABEL_STYLE.borderRadius;\n\treturn {\n\t\tfontFamily: style?.fontFamily || DEFAULT_REGION_LABEL_STYLE.fontFamily,\n\t\tfontSize: fs,\n\t\tfontWeight: style?.fontWeight || DEFAULT_REGION_LABEL_STYLE.fontWeight,\n\t\ttextColor: style?.textColor || DEFAULT_REGION_LABEL_STYLE.textColor,\n\t\tbackgroundColor:\n\t\t\tstyle?.backgroundColor || DEFAULT_REGION_LABEL_STYLE.backgroundColor,\n\t\tborderColor: style?.borderColor || DEFAULT_REGION_LABEL_STYLE.borderColor,\n\t\tborderWidth: bw,\n\t\tpaddingX: px,\n\t\tpaddingY: py,\n\t\toffsetY: oy,\n\t\tborderRadius: br,\n\t};\n}\n\nfunction drawRoundedRect(\n\tctx: CanvasRenderingContext2D,\n\tx: number,\n\ty: number,\n\twidth: number,\n\theight: number,\n\tradius: number,\n): void {\n\tconst r = Math.max(0, Math.min(radius, width * 0.5, height * 0.5));\n\tctx.beginPath();\n\tctx.moveTo(x + r, y);\n\tctx.lineTo(x + width - r, y);\n\tctx.quadraticCurveTo(x + width, y, x + width, y + r);\n\tctx.lineTo(x + width, y + height - r);\n\tctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height);\n\tctx.lineTo(x + r, y + height);\n\tctx.quadraticCurveTo(x, y + height, x, y + height - r);\n\tctx.lineTo(x, y + r);\n\tctx.quadraticCurveTo(x, y, x + r, y);\n\tctx.closePath();\n}\n\nfunction getTopAnchor(coords: DrawCoordinate[]): DrawCoordinate | null {\n\tif (!coords.length) return null;\n\n\tlet minY = Infinity;\n\tfor (const point of coords) {\n\t\tif (point[1] < minY) minY = point[1];\n\t}\n\tif (!Number.isFinite(minY)) return null;\n\n\tlet minX = Infinity;\n\tlet maxX = -Infinity;\n\tfor (const point of coords) {\n\t\tif (Math.abs(point[1] - minY) > 0.5) continue;\n\t\tif (point[0] < minX) minX = point[0];\n\t\tif (point[0] > maxX) maxX = point[0];\n\t}\n\n\tif (!Number.isFinite(minX) || !Number.isFinite(maxX)) return null;\n\treturn [(minX + maxX) * 0.5, minY];\n}\n\nfunction drawRegionLabel(\n\tctx: CanvasRenderingContext2D,\n\ttext: string,\n\tanchor: DrawCoordinate,\n\tcanvasWidth: number,\n\tcanvasHeight: number,\n\tlabelStyle: RegionLabelStyle,\n): void {\n\tconst label = text.trim();\n\tif (!label) return;\n\n\tctx.save();\n\tctx.font = `${labelStyle.fontWeight} ${labelStyle.fontSize}px ${labelStyle.fontFamily}`;\n\tctx.textAlign = \"center\";\n\tctx.textBaseline = \"middle\";\n\n\tconst textWidth = ctx.measureText(label).width;\n\tconst boxWidth = textWidth + labelStyle.paddingX * 2;\n\tconst boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n\tconst x = clamp(\n\t\tanchor[0],\n\t\tboxWidth * 0.5 + 1,\n\t\tcanvasWidth - boxWidth * 0.5 - 1,\n\t);\n\tconst y = clamp(\n\t\tanchor[1] - labelStyle.offsetY,\n\t\tboxHeight * 0.5 + 1,\n\t\tcanvasHeight - boxHeight * 0.5 - 1,\n\t);\n\tconst left = x - boxWidth * 0.5;\n\tconst top = y - boxHeight * 0.5;\n\n\tctx.fillStyle = labelStyle.backgroundColor;\n\tctx.strokeStyle = labelStyle.borderColor;\n\tctx.lineWidth = labelStyle.borderWidth;\n\tdrawRoundedRect(\n\t\tctx,\n\t\tleft,\n\t\ttop,\n\t\tboxWidth,\n\t\tboxHeight,\n\t\tlabelStyle.borderRadius,\n\t);\n\tctx.fill();\n\tif (labelStyle.borderWidth > 0) {\n\t\tctx.stroke();\n\t}\n\n\tctx.fillStyle = labelStyle.textColor;\n\tctx.fillText(label, x, y + 0.5);\n\tctx.restore();\n}\n\nfunction clampWorld(\n\tcoord: DrawCoordinate,\n\timageWidth: number,\n\timageHeight: number,\n): DrawCoordinate {\n\treturn [clamp(coord[0], 0, imageWidth), clamp(coord[1], 0, imageHeight)];\n}\n\nfunction toCoord(value: DrawCoordinate | number[]): DrawCoordinate | null {\n\tif (!Array.isArray(value) || value.length < 2) return null;\n\tconst x = Number(value[0]);\n\tconst y = Number(value[1]);\n\tif (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n\treturn [x, y];\n}\n\nexport function DrawLayer({\n\ttool,\n\timageWidth,\n\timageHeight,\n\timageMpp,\n\timageZoom,\n\tstampOptions,\n\tprojectorRef,\n\tonDrawComplete,\n\tenabled,\n\tviewStateSignal,\n\tpersistedRegions,\n\tpersistedPolygons,\n\tregionStrokeStyle,\n\tregionStrokeHoverStyle,\n\tregionStrokeActiveStyle,\n\thoveredRegionId = null,\n\tactiveRegionId = null,\n\tregionLabelStyle,\n\tinvalidateRef,\n\tclassName,\n\tstyle,\n}: DrawLayerProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst drawPendingRef = useRef(false);\n\tconst lastToolRef = useRef<DrawTool>(tool);\n\tconst sessionRef = useRef<DrawSession>({\n\t\tisDrawing: false,\n\t\tpointerId: null,\n\t\tstart: null,\n\t\tcurrent: null,\n\t\tpoints: [],\n\t\tstampCenter: null,\n\t});\n\n\tconst active = enabled ?? tool !== \"cursor\";\n\tconst mergedPersistedRegions = useMemo<DrawRegion[]>(() => {\n\t\tif (persistedRegions && persistedRegions.length > 0) {\n\t\t\treturn persistedRegions;\n\t\t}\n\t\tif (!persistedPolygons || persistedPolygons.length === 0) {\n\t\t\treturn EMPTY_REGIONS;\n\t\t}\n\t\treturn persistedPolygons.map((coordinates, index) => ({\n\t\t\tid: index,\n\t\t\tcoordinates,\n\t\t}));\n\t}, [persistedRegions, persistedPolygons]);\n\n\tconst resolvedStrokeStyle = useMemo(\n\t\t() => resolveStrokeStyle(regionStrokeStyle),\n\t\t[regionStrokeStyle],\n\t);\n\tconst resolvedHoverStrokeStyle = useMemo(\n\t\t() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeHoverStyle),\n\t\t[resolvedStrokeStyle, regionStrokeHoverStyle],\n\t);\n\tconst resolvedActiveStrokeStyle = useMemo(\n\t\t() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeActiveStyle),\n\t\t[resolvedStrokeStyle, regionStrokeActiveStyle],\n\t);\n\n\tconst resolvedLabelStyle = useMemo(\n\t\t() => resolveLabelStyle(regionLabelStyle),\n\t\t[regionLabelStyle],\n\t);\n\tconst resolvedStampOptions = useMemo(\n\t\t() => resolveStampOptions(stampOptions),\n\t\t[stampOptions],\n\t);\n\n\tconst mergedStyle = useMemo<CSSProperties>(\n\t\t() => ({\n\t\t\tposition: \"absolute\",\n\t\t\tinset: 0,\n\t\t\tzIndex: 2,\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tdisplay: \"block\",\n\t\t\ttouchAction: \"none\",\n\t\t\tpointerEvents: active ? \"auto\" : \"none\",\n\t\t\tcursor: active ? \"crosshair\" : \"default\",\n\t\t\t...style,\n\t\t}),\n\t\t[active, style],\n\t);\n\n\tconst resizeCanvas = useCallback(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return;\n\n\t\tconst rect = canvas.getBoundingClientRect();\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\t\tconst w = Math.max(1, Math.round(rect.width * dpr));\n\t\tconst h = Math.max(1, Math.round(rect.height * dpr));\n\n\t\tif (canvas.width !== w || canvas.height !== h) {\n\t\t\tcanvas.width = w;\n\t\t\tcanvas.height = h;\n\t\t}\n\t}, []);\n\n\tconst worldToScreenPoints = useCallback(\n\t\t(points: DrawCoordinate[]): DrawCoordinate[] => {\n\t\t\tconst projector = projectorRef.current;\n\t\t\tif (!projector || points.length === 0) return [];\n\n\t\t\tconst out = new Array<DrawCoordinate>(points.length);\n\t\t\tfor (let i = 0; i < points.length; i += 1) {\n\t\t\t\tconst coord = toCoord(\n\t\t\t\t\tprojector.worldToScreen(points[i][0], points[i][1]),\n\t\t\t\t);\n\t\t\t\tif (!coord) return [];\n\t\t\t\tout[i] = coord;\n\t\t\t}\n\t\t\treturn out;\n\t\t},\n\t\t[projectorRef],\n\t);\n\n\tconst micronsToWorldPixels = useCallback(\n\t\t(lengthUm: number): number => {\n\t\t\tif (!Number.isFinite(lengthUm) || lengthUm <= 0) return 0;\n\n\t\t\t// If mpp is missing, fall back to 1um/px assumption.\n\t\t\tconst mppValue =\n\t\t\t\ttypeof imageMpp === \"number\" && Number.isFinite(imageMpp) && imageMpp > 0\n\t\t\t\t\t? imageMpp\n\t\t\t\t\t: 1;\n\t\t\tconst imageZoomValue =\n\t\t\t\ttypeof imageZoom === \"number\" && Number.isFinite(imageZoom)\n\t\t\t\t\t? imageZoom\n\t\t\t\t\t: 0;\n\t\t\tconst viewZoomRaw = projectorRef.current?.getViewState?.().zoom;\n\t\t\tconst viewZoom =\n\t\t\t\ttypeof viewZoomRaw === \"number\" &&\n\t\t\t\tNumber.isFinite(viewZoomRaw) &&\n\t\t\t\tviewZoomRaw > 0\n\t\t\t\t\t? viewZoomRaw\n\t\t\t\t\t: 1;\n\t\t\tconst continuousZoom = imageZoomValue + Math.log2(viewZoom);\n\t\t\tconst umPerScreenPixel = Math.max(\n\t\t\t\t1e-9,\n\t\t\t\tcalcScaleResolution(mppValue, imageZoomValue, continuousZoom),\n\t\t\t);\n\t\t\tconst screenPixels = lengthUm / umPerScreenPixel;\n\t\t\treturn screenPixels / viewZoom;\n\t\t},\n\t\t[imageMpp, imageZoom, projectorRef],\n\t);\n\n\tconst buildStampCoords = useCallback(\n\t\t(stampTool: StampDrawTool, center: DrawCoordinate | null): DrawCoordinate[] => {\n\t\t\tif (!center) return [];\n\n\t\t\tlet areaMm2 = 0;\n\t\t\tif (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n\t\t\t\tareaMm2 =\n\t\t\t\t\tstampTool === \"stamp-rectangle-2mm2\"\n\t\t\t\t\t\t? DEFAULT_STAMP_RECTANGLE_AREA_MM2\n\t\t\t\t\t\t: resolvedStampOptions.rectangleAreaMm2;\n\t\t\t} else if (\n\t\t\t\tstampTool === \"stamp-circle\" ||\n\t\t\t\tstampTool === \"stamp-circle-2mm2\" ||\n\t\t\t\tstampTool === \"stamp-circle-hpf-0.2mm2\"\n\t\t\t) {\n\t\t\t\tareaMm2 =\n\t\t\t\t\tstampTool === \"stamp-circle-hpf-0.2mm2\"\n\t\t\t\t\t\t? LEGACY_HPF_CIRCLE_AREA_MM2\n\t\t\t\t\t\t: stampTool === \"stamp-circle-2mm2\"\n\t\t\t\t\t\t\t? DEFAULT_STAMP_CIRCLE_AREA_MM2\n\t\t\t\t\t\t\t: resolvedStampOptions.circleAreaMm2;\n\t\t\t}\n\t\t\tif (!Number.isFinite(areaMm2) || areaMm2 <= 0) return [];\n\n\t\t\tconst areaUm2 = mm2ToUm2(areaMm2);\n\t\t\tlet coords: DrawCoordinate[] = [];\n\t\t\tif (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n\t\t\t\tconst halfLength = micronsToWorldPixels(Math.sqrt(areaUm2) * 0.5);\n\t\t\t\tcoords = createSquareFromCenter(center, halfLength);\n\t\t\t} else if (\n\t\t\t\tstampTool === \"stamp-circle\" ||\n\t\t\t\tstampTool === \"stamp-circle-2mm2\" ||\n\t\t\t\tstampTool === \"stamp-circle-hpf-0.2mm2\"\n\t\t\t) {\n\t\t\t\tconst radius = micronsToWorldPixels(Math.sqrt(areaUm2 / Math.PI));\n\t\t\t\tcoords = createCircleFromCenter(center, radius);\n\t\t\t}\n\n\t\t\tif (!coords.length) return [];\n\t\t\treturn coords.map((point) => clampWorld(point, imageWidth, imageHeight));\n\t\t},\n\t\t[micronsToWorldPixels, imageWidth, imageHeight, resolvedStampOptions],\n\t);\n\n\tconst buildPreviewCoords = useCallback((): DrawCoordinate[] => {\n\t\tconst session = sessionRef.current;\n\t\tif (isStampTool(tool)) {\n\t\t\treturn buildStampCoords(tool, session.stampCenter);\n\t\t}\n\t\tif (!session.isDrawing) return [];\n\n\t\tif (tool === \"freehand\") {\n\t\t\treturn session.points;\n\t\t}\n\t\tif (tool === \"rectangle\") {\n\t\t\treturn createRectangle(session.start, session.current);\n\t\t}\n\t\tif (tool === \"circular\") {\n\t\t\treturn createCircle(session.start, session.current);\n\t\t}\n\n\t\treturn [];\n\t}, [tool, buildStampCoords]);\n\n\tconst drawOverlay = useCallback(() => {\n\t\tresizeCanvas();\n\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return;\n\n\t\tconst ctx = canvas.getContext(\"2d\");\n\t\tif (!ctx) return;\n\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\t\tconst canvasWidth = canvas.width / dpr;\n\t\tconst canvasHeight = canvas.height / dpr;\n\t\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\n\t\tctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n\t\t// Persisted ROI outlines always remain visible.\n\t\tif (mergedPersistedRegions.length > 0) {\n\t\t\tfor (let i = 0; i < mergedPersistedRegions.length; i += 1) {\n\t\t\t\tconst region = mergedPersistedRegions[i];\n\t\t\t\tconst ring = region?.coordinates;\n\t\t\t\tif (!ring || ring.length < 3) continue;\n\t\t\t\tconst closed = closeRing(ring);\n\t\t\t\tconst screen = worldToScreenPoints(closed);\n\t\t\t\tif (screen.length >= 4) {\n\t\t\t\t\tconst regionKey = region.id ?? i;\n\t\t\t\t\tconst strokeStyle = isSameRegionId(activeRegionId, regionKey)\n\t\t\t\t\t\t? resolvedActiveStrokeStyle\n\t\t\t\t\t\t: isSameRegionId(hoveredRegionId, regionKey)\n\t\t\t\t\t\t\t? resolvedHoverStrokeStyle\n\t\t\t\t\t\t\t: resolvedStrokeStyle;\n\t\t\t\t\tdrawPath(ctx, screen, strokeStyle, true, false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (active) {\n\t\t\tconst preview = buildPreviewCoords();\n\t\t\tif (preview.length > 0) {\n\t\t\t\tif (tool === \"freehand\") {\n\t\t\t\t\tconst line = worldToScreenPoints(preview);\n\t\t\t\t\tif (line.length >= 2) {\n\t\t\t\t\t\tdrawPath(ctx, line, resolvedStrokeStyle, false, false);\n\t\t\t\t\t}\n\t\t\t\t\tif (line.length >= 3) {\n\t\t\t\t\t\tdrawPath(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tworldToScreenPoints(closeRing(preview)),\n\t\t\t\t\t\t\tresolvedStrokeStyle,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst polygon = worldToScreenPoints(preview);\n\t\t\t\t\tif (polygon.length >= 4) {\n\t\t\t\t\t\tdrawPath(ctx, polygon, resolvedStrokeStyle, true, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Draw labels last so they stay visually on top.\n\t\tif (mergedPersistedRegions.length > 0) {\n\t\t\tfor (const region of mergedPersistedRegions) {\n\t\t\t\tif (!region.label) continue;\n\t\t\t\tconst ring = region?.coordinates;\n\t\t\t\tif (!ring || ring.length < 3) continue;\n\t\t\t\tconst closed = closeRing(ring);\n\t\t\t\tconst anchorWorld = getTopAnchor(closed);\n\t\t\t\tif (!anchorWorld) continue;\n\t\t\t\tconst anchorScreen = toCoord(\n\t\t\t\t\tprojectorRef.current?.worldToScreen(anchorWorld[0], anchorWorld[1]) ??\n\t\t\t\t\t\t[],\n\t\t\t\t);\n\t\t\t\tif (!anchorScreen) continue;\n\t\t\t\tdrawRegionLabel(\n\t\t\t\t\tctx,\n\t\t\t\t\tregion.label,\n\t\t\t\t\tanchorScreen,\n\t\t\t\t\tcanvasWidth,\n\t\t\t\t\tcanvasHeight,\n\t\t\t\t\tresolvedLabelStyle,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}, [\n\t\tactive,\n\t\ttool,\n\t\tbuildPreviewCoords,\n\t\tresizeCanvas,\n\t\tworldToScreenPoints,\n\t\tprojectorRef,\n\t\tmergedPersistedRegions,\n\t\thoveredRegionId,\n\t\tactiveRegionId,\n\t\tresolvedStrokeStyle,\n\t\tresolvedHoverStrokeStyle,\n\t\tresolvedActiveStrokeStyle,\n\t\tresolvedLabelStyle,\n\t]);\n\n\tconst requestDraw = useCallback(() => {\n\t\tif (drawPendingRef.current) return;\n\t\tdrawPendingRef.current = true;\n\t\trequestAnimationFrame(() => {\n\t\t\tdrawPendingRef.current = false;\n\t\t\tdrawOverlay();\n\t\t});\n\t}, [drawOverlay]);\n\n\tconst resetSession = useCallback(() => {\n\t\tconst session = sessionRef.current;\n\t\tconst canvas = canvasRef.current;\n\n\t\tif (\n\t\t\tcanvas &&\n\t\t\tsession.pointerId !== null &&\n\t\t\tcanvas.hasPointerCapture(session.pointerId)\n\t\t) {\n\t\t\ttry {\n\t\t\t\tcanvas.releasePointerCapture(session.pointerId);\n\t\t\t} catch {\n\t\t\t\t// noop\n\t\t\t}\n\t\t}\n\n\t\tsession.isDrawing = false;\n\t\tsession.pointerId = null;\n\t\tsession.start = null;\n\t\tsession.current = null;\n\t\tsession.points = [];\n\t\tsession.stampCenter = null;\n\t}, []);\n\n\tconst toWorld = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>): DrawCoordinate | null => {\n\t\t\tconst projector = projectorRef.current;\n\t\t\tif (!projector || imageWidth <= 0 || imageHeight <= 0) return null;\n\n\t\t\tconst raw = toCoord(\n\t\t\t\tprojector.screenToWorld(event.clientX, event.clientY),\n\t\t\t);\n\t\t\tif (!raw) return null;\n\t\t\treturn clampWorld(raw, imageWidth, imageHeight);\n\t\t},\n\t\t[projectorRef, imageWidth, imageHeight],\n\t);\n\n\tconst finishSession = useCallback(() => {\n\t\tconst session = sessionRef.current;\n\t\tif (!session.isDrawing) {\n\t\t\tresetSession();\n\t\t\trequestDraw();\n\t\t\treturn;\n\t\t}\n\n\t\tlet coordinates: DrawCoordinate[] = [];\n\t\tif (tool === \"freehand\") {\n\t\t\tif (session.points.length >= FREEHAND_MIN_POINTS) {\n\t\t\t\tcoordinates = closeRing(session.points);\n\t\t\t}\n\t\t} else if (tool === \"rectangle\") {\n\t\t\tcoordinates = createRectangle(session.start, session.current);\n\t\t} else if (tool === \"circular\") {\n\t\t\tcoordinates = createCircle(session.start, session.current);\n\t\t}\n\n\t\tif (\n\t\t\t(tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\") &&\n\t\t\tisValidPolygon(coordinates) &&\n\t\t\tonDrawComplete\n\t\t) {\n\t\t\tonDrawComplete({\n\t\t\t\ttool,\n\t\t\t\tcoordinates,\n\t\t\t\tbbox: computeBounds(coordinates),\n\t\t\t\tareaPx: polygonArea(coordinates),\n\t\t\t});\n\t\t}\n\n\t\tresetSession();\n\t\trequestDraw();\n\t}, [tool, onDrawComplete, resetSession, requestDraw]);\n\n\tconst handleStampAt = useCallback(\n\t\t(stampTool: StampDrawTool, center: DrawCoordinate): void => {\n\t\t\tconst coordinates = buildStampCoords(stampTool, center);\n\t\t\tif (!isValidPolygon(coordinates) || !onDrawComplete) return;\n\t\t\tonDrawComplete({\n\t\t\t\ttool: stampTool,\n\t\t\t\tcoordinates,\n\t\t\t\tbbox: computeBounds(coordinates),\n\t\t\t\tareaPx: polygonArea(coordinates),\n\t\t\t});\n\t\t},\n\t\t[buildStampCoords, onDrawComplete],\n\t);\n\n\tconst handlePointerDown = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tif (!active) return;\n\t\t\tif (tool === \"cursor\") return;\n\t\t\tif (event.button !== 0) return;\n\n\t\t\tconst world = toWorld(event);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tif (isStampTool(tool)) {\n\t\t\t\tconst session = sessionRef.current;\n\t\t\t\tsession.stampCenter = world;\n\t\t\t\thandleStampAt(tool, world);\n\t\t\t\trequestDraw();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (canvas) {\n\t\t\t\tcanvas.setPointerCapture(event.pointerId);\n\t\t\t}\n\n\t\t\tconst session = sessionRef.current;\n\t\t\tsession.isDrawing = true;\n\t\t\tsession.pointerId = event.pointerId;\n\t\t\tsession.start = world;\n\t\t\tsession.current = world;\n\t\t\tsession.points = tool === \"freehand\" ? [world] : [];\n\t\t\trequestDraw();\n\t\t},\n\t\t[active, tool, toWorld, handleStampAt, requestDraw],\n\t);\n\n\tconst handlePointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tif (!active) return;\n\t\t\tif (tool === \"cursor\") return;\n\n\t\t\tconst world = toWorld(event);\n\t\t\tif (!world) return;\n\n\t\t\tif (isStampTool(tool)) {\n\t\t\t\tconst session = sessionRef.current;\n\t\t\t\tsession.stampCenter = world;\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\trequestDraw();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst session = sessionRef.current;\n\t\t\tif (!session.isDrawing || session.pointerId !== event.pointerId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tif (tool === \"freehand\") {\n\t\t\t\tconst projector = projectorRef.current;\n\t\t\t\tconst zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n\t\t\t\tconst minWorldStep = FREEHAND_SCREEN_STEP / zoom;\n\t\t\t\tconst minWorldStep2 = minWorldStep * minWorldStep;\n\t\t\t\tconst prev = session.points[session.points.length - 1];\n\n\t\t\t\tif (!prev) {\n\t\t\t\t\tsession.points.push(world);\n\t\t\t\t} else {\n\t\t\t\t\tconst dx = world[0] - prev[0];\n\t\t\t\t\tconst dy = world[1] - prev[1];\n\t\t\t\t\tif (dx * dx + dy * dy >= minWorldStep2) {\n\t\t\t\t\t\tsession.points.push(world);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsession.current = world;\n\t\t\t}\n\n\t\t\trequestDraw();\n\t\t},\n\t\t[active, tool, toWorld, requestDraw, projectorRef],\n\t);\n\n\tconst handlePointerUp = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst session = sessionRef.current;\n\t\t\tif (!session.isDrawing || session.pointerId !== event.pointerId) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (canvas && canvas.hasPointerCapture(event.pointerId)) {\n\t\t\t\ttry {\n\t\t\t\t\tcanvas.releasePointerCapture(event.pointerId);\n\t\t\t\t} catch {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfinishSession();\n\t\t},\n\t\t[finishSession],\n\t);\n\n\tconst handlePointerLeave = useCallback(() => {\n\t\tif (!isStampTool(tool)) return;\n\t\tconst session = sessionRef.current;\n\t\tif (!session.stampCenter) return;\n\t\tsession.stampCenter = null;\n\t\trequestDraw();\n\t}, [tool, requestDraw]);\n\n\tuseEffect(() => {\n\t\tresizeCanvas();\n\t\trequestDraw();\n\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return undefined;\n\n\t\tconst observer = new ResizeObserver(() => {\n\t\t\tresizeCanvas();\n\t\t\trequestDraw();\n\t\t});\n\t\tobserver.observe(canvas);\n\n\t\treturn () => {\n\t\t\tobserver.disconnect();\n\t\t};\n\t}, [resizeCanvas, requestDraw]);\n\n\tuseEffect(() => {\n\t\tif (!active) {\n\t\t\tresetSession();\n\t\t}\n\t\trequestDraw();\n\t}, [active, requestDraw, resetSession]);\n\n\tuseEffect(() => {\n\t\tif (lastToolRef.current === tool) {\n\t\t\treturn;\n\t\t}\n\t\tlastToolRef.current = tool;\n\t\tresetSession();\n\t\trequestDraw();\n\t}, [tool, resetSession, requestDraw]);\n\n\tuseEffect(() => {\n\t\trequestDraw();\n\t}, [viewStateSignal, mergedPersistedRegions, requestDraw]);\n\n\tuseEffect(() => {\n\t\tif (!invalidateRef) return undefined;\n\t\tinvalidateRef.current = requestDraw;\n\t\treturn () => {\n\t\t\tif (invalidateRef.current === requestDraw) {\n\t\t\t\tinvalidateRef.current = null;\n\t\t\t}\n\t\t};\n\t}, [invalidateRef, requestDraw]);\n\n\tuseEffect(() => {\n\t\tif (!active) return undefined;\n\n\t\tconst onKeyDown = (event: KeyboardEvent): void => {\n\t\t\tif (event.key !== \"Escape\") return;\n\t\t\tresetSession();\n\t\t\trequestDraw();\n\t\t};\n\n\t\twindow.addEventListener(\"keydown\", onKeyDown);\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"keydown\", onKeyDown);\n\t\t};\n\t}, [active, resetSession, requestDraw]);\n\n\treturn (\n\t\t<canvas\n\t\t\tref={canvasRef}\n\t\t\tclassName={className}\n\t\t\tstyle={mergedStyle}\n\t\t\tonPointerDown={handlePointerDown}\n\t\t\tonPointerMove={handlePointerMove}\n\t\t\tonPointerUp={handlePointerUp}\n\t\t\tonPointerCancel={handlePointerUp}\n\t\t\tonPointerLeave={handlePointerLeave}\n\t\t\tonContextMenu={(event) => {\n\t\t\t\tif (active) event.preventDefault();\n\t\t\t}}\n\t\t\tonWheel={(event) => {\n\t\t\t\tif (active) event.preventDefault();\n\t\t\t}}\n\t\t/>\n\t);\n}\n","import type { WsiImageSource, WsiTerm } from \"./types\";\n\nexport function normalizeImageInfo(\n\traw: any,\n\ttileBaseUrl: string,\n): WsiImageSource {\n\tconst ims = raw?.imsInfo || {};\n\n\tconst width = Number(ims.width ?? raw?.width ?? 0);\n\tconst height = Number(ims.height ?? raw?.height ?? 0);\n\tconst tileSize = Number(ims.tileSize ?? raw?.tileSize ?? 0);\n\tconst maxTierZoom = Number(ims.zoom ?? raw?.zoom ?? 0);\n\tconst tilePath = String(ims.path ?? raw?.path ?? \"\");\n\tconst mpp = Number(ims.mpp ?? raw?.mpp ?? 0);\n\n\tif (!width || !height || !tileSize || !tilePath) {\n\t\tthrow new Error(\n\t\t\t\"이미지 메타데이터가 불완전합니다. width/height/tileSize/path 확인 필요\",\n\t\t);\n\t}\n\n\tconst terms: WsiTerm[] = Array.isArray(raw?.terms)\n\t\t? raw.terms.map((term: any) => ({\n\t\t\t\ttermId: String(term?.termId ?? \"\"),\n\t\t\t\ttermName: String(term?.termName ?? \"\"),\n\t\t\t\ttermColor: String(term?.termColor ?? \"\"),\n\t\t\t}))\n\t\t: [];\n\n\treturn {\n\t\tid: raw?._id || \"unknown\",\n\t\tname: raw?.name || \"unknown\",\n\t\twidth,\n\t\theight,\n\t\tmpp: Number.isFinite(mpp) && mpp > 0 ? mpp : undefined,\n\t\ttileSize,\n\t\tmaxTierZoom: Number.isFinite(maxTierZoom)\n\t\t\t? Math.max(0, Math.floor(maxTierZoom))\n\t\t\t: 0,\n\t\ttilePath,\n\t\ttileBaseUrl,\n\t\tterms,\n\t};\n}\n\nexport function toTileUrl(\n\tsource: Pick<WsiImageSource, \"tilePath\" | \"tileBaseUrl\">,\n\ttier: number,\n\tx: number,\n\ty: number,\n): string {\n\tconst normalizedPath = source.tilePath.startsWith(\"/\")\n\t\t? source.tilePath\n\t\t: `/${source.tilePath}`;\n\treturn `${source.tileBaseUrl}${normalizedPath}/${tier}/${y}_${x}.webp`;\n}\n","import {\n\ttype CSSProperties,\n\ttype MutableRefObject,\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n} from \"react\";\nimport { toTileUrl } from \"../wsi/image-info\";\nimport type { WsiImageSource, WsiViewState } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\n\ntype Bounds = [number, number, number, number];\n\nexport interface OverviewMapProjector {\n\tgetViewState: () => WsiViewState;\n\tsetViewState: (next: Partial<WsiViewState>) => void;\n\tgetViewBounds?: () => number[];\n}\n\nexport type OverviewMapPosition =\n\t| \"bottom-right\"\n\t| \"bottom-left\"\n\t| \"top-right\"\n\t| \"top-left\";\n\nexport interface OverviewMapOptions {\n\twidth: number;\n\theight: number;\n\tmargin: number;\n\tposition: OverviewMapPosition;\n\tborderRadius: number;\n\tborderWidth: number;\n\tbackgroundColor: string;\n\tborderColor: string;\n\tviewportStrokeColor: string;\n\tviewportFillColor: string;\n\tinteractive: boolean;\n\tshowThumbnail: boolean;\n\tmaxThumbnailTiles: number;\n}\n\nexport interface OverviewMapProps {\n\tsource: WsiImageSource;\n\tprojectorRef: RefObject<OverviewMapProjector | null>;\n\tauthToken?: string;\n\toptions?: Partial<OverviewMapOptions>;\n\tinvalidateRef?: MutableRefObject<(() => void) | null>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nconst DEFAULT_OVERVIEW_MAP_OPTIONS: OverviewMapOptions = {\n\twidth: 220,\n\theight: 140,\n\tmargin: 16,\n\tposition: \"bottom-right\",\n\tborderRadius: 10,\n\tborderWidth: 1.5,\n\tbackgroundColor: \"rgba(4, 10, 18, 0.88)\",\n\tborderColor: \"rgba(230, 244, 255, 0.35)\",\n\tviewportStrokeColor: \"rgba(255, 106, 61, 0.95)\",\n\tviewportFillColor: \"rgba(255, 106, 61, 0.2)\",\n\tinteractive: true,\n\tshowThumbnail: true,\n\tmaxThumbnailTiles: 16,\n};\n\nfunction toPositiveNumber(\n\tvalue: number | undefined,\n\tfallback: number,\n\tmin = 1,\n): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n\treturn Math.max(min, value);\n}\n\nfunction isFiniteBounds(bounds: number[] | null | undefined): bounds is Bounds {\n\treturn (\n\t\tArray.isArray(bounds) &&\n\t\tbounds.length === 4 &&\n\t\tNumber.isFinite(bounds[0]) &&\n\t\tNumber.isFinite(bounds[1]) &&\n\t\tNumber.isFinite(bounds[2]) &&\n\t\tNumber.isFinite(bounds[3])\n\t);\n}\n\nexport function OverviewMap({\n\tsource,\n\tprojectorRef,\n\tauthToken = \"\",\n\toptions,\n\tinvalidateRef,\n\tclassName,\n\tstyle,\n}: OverviewMapProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst thumbnailRef = useRef<HTMLCanvasElement | null>(null);\n\tconst lastBoundsRef = useRef<Bounds | null>(null);\n\tconst draggingRef = useRef<{ active: boolean; pointerId: number | null }>({\n\t\tactive: false,\n\t\tpointerId: null,\n\t});\n\tconst rafRef = useRef<number | null>(null);\n\tconst drawPendingRef = useRef(false);\n\n\tconst width = toPositiveNumber(\n\t\toptions?.width,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.width,\n\t\t64,\n\t);\n\tconst height = toPositiveNumber(\n\t\toptions?.height,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.height,\n\t\t48,\n\t);\n\tconst margin = toPositiveNumber(\n\t\toptions?.margin,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.margin,\n\t\t0,\n\t);\n\tconst borderRadius = toPositiveNumber(\n\t\toptions?.borderRadius,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderRadius,\n\t\t0,\n\t);\n\tconst borderWidth = toPositiveNumber(\n\t\toptions?.borderWidth,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderWidth,\n\t\t0,\n\t);\n\tconst maxThumbnailTiles = Math.max(\n\t\t1,\n\t\tMath.round(\n\t\t\ttoPositiveNumber(\n\t\t\t\toptions?.maxThumbnailTiles,\n\t\t\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.maxThumbnailTiles,\n\t\t\t\t1,\n\t\t\t),\n\t\t),\n\t);\n\n\tconst backgroundColor =\n\t\toptions?.backgroundColor || DEFAULT_OVERVIEW_MAP_OPTIONS.backgroundColor;\n\tconst borderColor =\n\t\toptions?.borderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.borderColor;\n\tconst viewportStrokeColor =\n\t\toptions?.viewportStrokeColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportStrokeColor;\n\tconst viewportFillColor =\n\t\toptions?.viewportFillColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportFillColor;\n\tconst interactive =\n\t\toptions?.interactive ?? DEFAULT_OVERVIEW_MAP_OPTIONS.interactive;\n\tconst showThumbnail =\n\t\toptions?.showThumbnail ?? DEFAULT_OVERVIEW_MAP_OPTIONS.showThumbnail;\n\tconst position =\n\t\toptions?.position || DEFAULT_OVERVIEW_MAP_OPTIONS.position;\n\n\tconst mergedStyle = useMemo<CSSProperties>(() => {\n\t\tconst pos: CSSProperties = {};\n\t\tif (position === \"top-left\" || position === \"bottom-left\") pos.left = margin;\n\t\telse pos.right = margin;\n\t\tif (position === \"top-left\" || position === \"top-right\") pos.top = margin;\n\t\telse pos.bottom = margin;\n\n\t\treturn {\n\t\t\tposition: \"absolute\",\n\t\t\t...pos,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tborderRadius,\n\t\t\toverflow: \"hidden\",\n\t\t\tzIndex: 4,\n\t\t\tpointerEvents: interactive ? \"auto\" : \"none\",\n\t\t\ttouchAction: \"none\",\n\t\t\tboxShadow: \"0 10px 22px rgba(0, 0, 0, 0.3)\",\n\t\t\t...style,\n\t\t};\n\t}, [margin, position, width, height, borderRadius, interactive, style]);\n\n\tconst draw = useCallback(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return;\n\n\t\tconst ctx = canvas.getContext(\"2d\");\n\t\tif (!ctx) return;\n\n\t\tconst cssW = width;\n\t\tconst cssH = height;\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\t\tif (canvas.width !== pixelW || canvas.height !== pixelH) {\n\t\t\tcanvas.width = pixelW;\n\t\t\tcanvas.height = pixelH;\n\t\t}\n\n\t\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\n\t\tctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, cssW, cssH);\n\n\t\tconst preview = thumbnailRef.current;\n\t\tif (preview) {\n\t\t\tctx.drawImage(preview, 0, 0, cssW, cssH);\n\t\t}\n\n\t\tctx.strokeStyle = borderColor;\n\t\tctx.lineWidth = borderWidth;\n\t\tctx.strokeRect(\n\t\t\tborderWidth * 0.5,\n\t\t\tborderWidth * 0.5,\n\t\t\tcssW - borderWidth,\n\t\t\tcssH - borderWidth,\n\t\t);\n\n\t\tconst projector = projectorRef.current;\n\t\tconst bounds = projector?.getViewBounds?.();\n\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t? bounds\n\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t? lastBoundsRef.current\n\t\t\t\t: null;\n\t\tif (!safeBounds) return;\n\t\tlastBoundsRef.current = safeBounds;\n\n\t\tconst sx = cssW / Math.max(1, source.width);\n\t\tconst sy = cssH / Math.max(1, source.height);\n\n\t\tconst left = clamp(safeBounds[0] * sx, 0, cssW);\n\t\tconst top = clamp(safeBounds[1] * sy, 0, cssH);\n\t\tconst right = clamp(safeBounds[2] * sx, 0, cssW);\n\t\tconst bottom = clamp(safeBounds[3] * sy, 0, cssH);\n\t\tconst rectW = Math.max(1, right - left);\n\t\tconst rectH = Math.max(1, bottom - top);\n\n\t\tctx.fillStyle = viewportFillColor;\n\t\tctx.fillRect(left, top, rectW, rectH);\n\n\t\tctx.strokeStyle = viewportStrokeColor;\n\t\tctx.lineWidth = 1.5;\n\t\tctx.strokeRect(\n\t\t\tleft + 0.5,\n\t\t\ttop + 0.5,\n\t\t\tMath.max(1, rectW - 1),\n\t\t\tMath.max(1, rectH - 1),\n\t\t);\n\t}, [\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tborderColor,\n\t\tborderWidth,\n\t\tprojectorRef,\n\t\tsource.width,\n\t\tsource.height,\n\t\tviewportFillColor,\n\t\tviewportStrokeColor,\n\t]);\n\n\tconst requestDraw = useCallback(() => {\n\t\tif (drawPendingRef.current) return;\n\t\tdrawPendingRef.current = true;\n\t\trafRef.current = requestAnimationFrame(() => {\n\t\t\tdrawPendingRef.current = false;\n\t\t\trafRef.current = null;\n\t\t\tdraw();\n\t\t});\n\t}, [draw]);\n\n\tconst toWorldFromClient = useCallback(\n\t\t(clientX: number, clientY: number): [number, number] | null => {\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return null;\n\n\t\t\tconst rect = canvas.getBoundingClientRect();\n\t\t\tif (!rect.width || !rect.height) return null;\n\n\t\t\tconst nx = clamp((clientX - rect.left) / rect.width, 0, 1);\n\t\t\tconst ny = clamp((clientY - rect.top) / rect.height, 0, 1);\n\t\t\treturn [nx * source.width, ny * source.height];\n\t\t},\n\t\t[source.width, source.height],\n\t);\n\n\tconst recenterTo = useCallback(\n\t\t(worldX: number, worldY: number) => {\n\t\t\tconst projector = projectorRef.current;\n\t\t\tif (!projector) return;\n\n\t\t\tconst bounds = projector.getViewBounds?.();\n\t\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t\t? bounds\n\t\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t\t? lastBoundsRef.current\n\t\t\t\t\t: null;\n\t\t\tif (!safeBounds) return;\n\n\t\t\tconst visibleW = Math.max(1e-6, safeBounds[2] - safeBounds[0]);\n\t\t\tconst visibleH = Math.max(1e-6, safeBounds[3] - safeBounds[1]);\n\n\t\t\tprojector.setViewState({\n\t\t\t\toffsetX: worldX - visibleW * 0.5,\n\t\t\t\toffsetY: worldY - visibleH * 0.5,\n\t\t\t});\n\t\t\trequestDraw();\n\t\t},\n\t\t[projectorRef, requestDraw],\n\t);\n\n\tconst handlePointerDown = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tif (!interactive) return;\n\t\t\tif (event.button !== 0) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tcanvas.setPointerCapture(event.pointerId);\n\t\t\tdraggingRef.current = { active: true, pointerId: event.pointerId };\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[interactive, toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerUp = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (canvas && canvas.hasPointerCapture(event.pointerId)) {\n\t\t\t\ttry {\n\t\t\t\t\tcanvas.releasePointerCapture(event.pointerId);\n\t\t\t\t} catch {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\trequestDraw();\n\t\t},\n\t\t[requestDraw],\n\t);\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tthumbnailRef.current = null;\n\t\trequestDraw();\n\n\t\tconst tier = 0;\n\t\tconst levelScale = 2 ** (source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(source.height / levelScale);\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n\t\tconst tileCount = tilesX * tilesY;\n\n\t\tif (!showThumbnail || tileCount > maxThumbnailTiles) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst preview = document.createElement(\"canvas\");\n\t\tpreview.width = Math.max(1, Math.round(width));\n\t\tpreview.height = Math.max(1, Math.round(height));\n\t\tconst ctx = preview.getContext(\"2d\");\n\t\tif (!ctx) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, preview.width, preview.height);\n\n\t\tconst requests: Array<{\n\t\t\turl: string;\n\t\t\tbounds: Bounds;\n\t\t}> = [];\n\n\t\tfor (let y = 0; y < tilesY; y += 1) {\n\t\t\tfor (let x = 0; x < tilesX; x += 1) {\n\t\t\t\tconst left = x * source.tileSize * levelScale;\n\t\t\t\tconst top = y * source.tileSize * levelScale;\n\t\t\t\tconst right =\n\t\t\t\t\tMath.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom =\n\t\t\t\t\tMath.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n\t\t\t\trequests.push({\n\t\t\t\t\turl: toTileUrl(source, tier, x, y),\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvoid Promise.allSettled(\n\t\t\trequests.map(async (tile) => {\n\t\t\t\tconst useAuthHeader = !!authToken;\n\t\t\t\tconst response = await fetch(tile.url, {\n\t\t\t\t\theaders: useAuthHeader ? { Authorization: authToken } : undefined,\n\t\t\t\t});\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`HTTP ${response.status}`);\n\t\t\t\t}\n\t\t\t\tconst bitmap = await createImageBitmap(await response.blob());\n\t\t\t\treturn { tile, bitmap };\n\t\t\t}),\n\t\t).then((results) => {\n\t\t\tif (cancelled) {\n\t\t\t\tfor (const result of results) {\n\t\t\t\t\tif (result.status === \"fulfilled\") {\n\t\t\t\t\t\tresult.value.bitmap.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst sx = preview.width / Math.max(1, source.width);\n\t\t\tconst sy = preview.height / Math.max(1, source.height);\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.status !== \"fulfilled\") continue;\n\t\t\t\tconst {\n\t\t\t\t\ttile: { bounds },\n\t\t\t\t\tbitmap,\n\t\t\t\t} = result.value;\n\t\t\t\tconst dx = bounds[0] * sx;\n\t\t\t\tconst dy = bounds[1] * sy;\n\t\t\t\tconst dw = Math.max(1, (bounds[2] - bounds[0]) * sx);\n\t\t\t\tconst dh = Math.max(1, (bounds[3] - bounds[1]) * sy);\n\t\t\t\tctx.drawImage(bitmap, dx, dy, dw, dh);\n\t\t\t\tbitmap.close();\n\t\t\t}\n\n\t\t\tthumbnailRef.current = preview;\n\t\t\trequestDraw();\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [\n\t\tsource,\n\t\tauthToken,\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tshowThumbnail,\n\t\tmaxThumbnailTiles,\n\t\trequestDraw,\n\t]);\n\n\tuseEffect(() => {\n\t\trequestDraw();\n\t}, [requestDraw]);\n\n\tuseEffect(() => {\n\t\tif (!invalidateRef) return undefined;\n\t\tinvalidateRef.current = requestDraw;\n\t\treturn () => {\n\t\t\tif (invalidateRef.current === requestDraw) {\n\t\t\t\tinvalidateRef.current = null;\n\t\t\t}\n\t\t};\n\t}, [invalidateRef, requestDraw]);\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\tif (rafRef.current !== null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tdrawPendingRef.current = false;\n\t\t},\n\t\t[],\n\t);\n\n\treturn (\n\t\t<canvas\n\t\t\tref={canvasRef}\n\t\t\tclassName={className}\n\t\t\tstyle={mergedStyle}\n\t\t\tonPointerDown={handlePointerDown}\n\t\t\tonPointerMove={handlePointerMove}\n\t\t\tonPointerUp={handlePointerUp}\n\t\t\tonPointerCancel={handlePointerUp}\n\t\t\tonContextMenu={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t}}\n\t\t\tonWheel={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}}\n\t\t/>\n\t);\n}\n","import { type CSSProperties, useEffect, useMemo, useRef } from \"react\";\nimport { M1TileRenderer } from \"../core/m1-tile-renderer\";\nimport type { ViewState } from \"../core/ortho-camera\";\nimport type { TileDefinition } from \"../core/types\";\n\nexport interface TileViewerCanvasProps {\n\timageWidth: number;\n\timageHeight: number;\n\ttiles: TileDefinition[];\n\tviewState?: Partial<ViewState>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nexport function TileViewerCanvas({\n\timageWidth,\n\timageHeight,\n\ttiles,\n\tviewState,\n\tclassName,\n\tstyle,\n}: TileViewerCanvasProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst rendererRef = useRef<M1TileRenderer | null>(null);\n\tconst mergedStyle = useMemo(\n\t\t() => ({ width: \"100%\", height: \"100%\", display: \"block\", ...style }),\n\t\t[style],\n\t);\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst renderer = new M1TileRenderer({\n\t\t\tcanvas,\n\t\t\timageWidth,\n\t\t\timageHeight,\n\t\t\tinitialViewState: viewState,\n\t\t});\n\n\t\trendererRef.current = renderer;\n\t\tvoid renderer.setTiles(tiles);\n\n\t\treturn () => {\n\t\t\trenderer.destroy();\n\t\t\trendererRef.current = null;\n\t\t};\n\t}, [imageWidth, imageHeight]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer) {\n\t\t\treturn;\n\t\t}\n\n\t\tvoid renderer.setTiles(tiles);\n\t}, [tiles]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer || !viewState) {\n\t\t\treturn;\n\t\t}\n\n\t\trenderer.setViewState(viewState);\n\t}, [viewState]);\n\n\treturn <canvas ref={canvasRef} className={className} style={mergedStyle} />;\n}\n","import type { WsiPointData } from \"./types\";\n\nexport type RoiCoordinate = [number, number];\nexport type RoiPolygon = RoiCoordinate[];\n\ninterface PreparedPolygon {\n\tring: RoiPolygon;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n}\n\nfunction closeRing(coords: RoiPolygon): RoiPolygon {\n\tif (!Array.isArray(coords) || coords.length < 3) return [];\n\tconst out = coords.map(([x, y]) => [x, y] as RoiCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction preparePolygons(polygons: RoiPolygon[]): PreparedPolygon[] {\n\tconst prepared: PreparedPolygon[] = [];\n\tfor (const poly of polygons ?? []) {\n\t\tconst ring = closeRing(poly);\n\t\tif (ring.length < 4) continue;\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of ring) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\tif (!Number.isFinite(minX) || !Number.isFinite(minY)) continue;\n\t\tprepared.push({ ring, minX, minY, maxX, maxY });\n\t}\n\treturn prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: RoiPolygon): boolean {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\t\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nfunction isInsideAnyPolygon(\n\tx: number,\n\ty: number,\n\tpolygons: PreparedPolygon[],\n): boolean {\n\tfor (const poly of polygons) {\n\t\tif (x < poly.minX || x > poly.maxX || y < poly.minY || y > poly.maxY) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (isInsideRing(x, y, poly.ring)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nexport function filterPointDataByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): WsiPointData | null {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn null;\n\t}\n\n\tconst prepared = preparePolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tpositions: new Float32Array(0),\n\t\t\tpaletteIndices: new Uint16Array(0),\n\t\t};\n\t}\n\n\tconst count = pointData.count;\n\tconst positions = pointData.positions;\n\tconst terms = pointData.paletteIndices;\n\n\tconst nextPositions = new Float32Array(count * 2);\n\tconst nextTerms = new Uint16Array(count);\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!isInsideAnyPolygon(x, y, prepared)) continue;\n\t\tnextPositions[cursor * 2] = x;\n\t\tnextPositions[cursor * 2 + 1] = y;\n\t\tnextTerms[cursor] = terms[i];\n\t\tcursor += 1;\n\t}\n\n\treturn {\n\t\tcount: cursor,\n\t\tpositions: nextPositions.subarray(0, cursor * 2),\n\t\tpaletteIndices: nextTerms.subarray(0, cursor),\n\t};\n}\n","// @ts-nocheck\nimport { toTileUrl } from \"./image-info\";\nimport { clamp, createProgram } from \"./utils\";\n\nclass OrthoCamera {\n constructor() {\n this.viewportWidth = 1;\n this.viewportHeight = 1;\n this.viewState = { zoom: 1, offsetX: 0, offsetY: 0 };\n }\n\n setViewport(width, height) {\n this.viewportWidth = Math.max(1, width);\n this.viewportHeight = Math.max(1, height);\n }\n\n getViewport() {\n return { width: this.viewportWidth, height: this.viewportHeight };\n }\n\n setViewState(next) {\n if (typeof next.zoom === \"number\") {\n this.viewState.zoom = Math.max(0.0001, next.zoom);\n }\n if (typeof next.offsetX === \"number\") {\n this.viewState.offsetX = next.offsetX;\n }\n if (typeof next.offsetY === \"number\") {\n this.viewState.offsetY = next.offsetY;\n }\n }\n\n getViewState() {\n return { ...this.viewState };\n }\n\n getMatrix() {\n const worldWidth = this.viewportWidth / this.viewState.zoom;\n const worldHeight = this.viewportHeight / this.viewState.zoom;\n const sx = 2 / worldWidth;\n const sy = -2 / worldHeight;\n const tx = -1 - this.viewState.offsetX * sx;\n const ty = 1 - this.viewState.offsetY * sy;\n return new Float32Array([sx, 0, 0, 0, sy, 0, tx, ty, 1]);\n }\n}\n\nexport class WsiTileRenderer {\n constructor(canvas, source, options = {}) {\n this.canvas = canvas;\n this.source = source;\n this.onViewStateChange = options.onViewStateChange;\n this.onStats = options.onStats;\n this.authToken = options.authToken || \"\";\n\n this.destroyed = false;\n this.frame = null;\n this.frameSerial = 0;\n this.dragging = false;\n this.pointerId = null;\n this.lastPointerX = 0;\n this.lastPointerY = 0;\n this.interactionLocked = false;\n\n this.cache = new Map();\n this.inflight = new Map();\n this.maxCacheTiles = 320;\n this.fitZoom = 1;\n this.minZoom = 1e-6;\n this.maxZoom = 1;\n this.currentTier = 0;\n this.pointCount = 0;\n this.pointPaletteSize = 1;\n\n const gl = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n powerPreference: \"high-performance\",\n });\n if (!gl) {\n throw new Error(\"WebGL2 not supported\");\n }\n this.gl = gl;\n this.camera = new OrthoCamera();\n\n this.initTileProgram();\n this.initPointProgram();\n\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(canvas);\n\n this.boundPointerDown = event => this.onPointerDown(event);\n this.boundPointerMove = event => this.onPointerMove(event);\n this.boundPointerUp = event => this.onPointerUp(event);\n this.boundWheel = event => this.onWheel(event);\n this.boundDoubleClick = event => this.onDoubleClick(event);\n\n canvas.addEventListener(\"pointerdown\", this.boundPointerDown);\n canvas.addEventListener(\"pointermove\", this.boundPointerMove);\n canvas.addEventListener(\"pointerup\", this.boundPointerUp);\n canvas.addEventListener(\"pointercancel\", this.boundPointerUp);\n canvas.addEventListener(\"wheel\", this.boundWheel, { passive: false });\n canvas.addEventListener(\"dblclick\", this.boundDoubleClick);\n\n this.fitToImage();\n this.resize();\n }\n\n initTileProgram() {\n const gl = this.gl;\n\n const vertex = `#version 300 es\n precision highp float;\n in vec2 aUnit;\n in vec2 aUv;\n uniform mat3 uCamera;\n uniform vec4 uBounds;\n out vec2 vUv;\n void main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n }`;\n\n const fragment = `#version 300 es\n precision highp float;\n in vec2 vUv;\n uniform sampler2D uTexture;\n out vec4 outColor;\n void main() {\n outColor = texture(uTexture, vUv);\n }`;\n\n this.program = createProgram(gl, vertex, fragment);\n this.uCamera = gl.getUniformLocation(this.program, \"uCamera\");\n this.uBounds = gl.getUniformLocation(this.program, \"uBounds\");\n this.uTexture = gl.getUniformLocation(this.program, \"uTexture\");\n if (!this.uCamera || !this.uBounds || !this.uTexture) {\n throw new Error(\"uniform location lookup failed\");\n }\n\n this.vao = gl.createVertexArray();\n this.vbo = gl.createBuffer();\n if (!this.vao || !this.vbo) {\n throw new Error(\"buffer allocation failed\");\n }\n\n gl.bindVertexArray(this.vao);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([\n 0, 0, 0, 0,\n 1, 0, 1, 0,\n 0, 1, 0, 1,\n 1, 1, 1, 1,\n ]),\n gl.STATIC_DRAW,\n );\n\n const aUnit = gl.getAttribLocation(this.program, \"aUnit\");\n const aUv = gl.getAttribLocation(this.program, \"aUv\");\n gl.enableVertexAttribArray(aUnit);\n gl.enableVertexAttribArray(aUv);\n gl.vertexAttribPointer(aUnit, 2, gl.FLOAT, false, 16, 0);\n gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n\n gl.bindVertexArray(null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n }\n\n initPointProgram() {\n const gl = this.gl;\n\n const pointVertex = `#version 300 es\n precision highp float;\n in vec2 aPosition;\n in uint aTerm;\n uniform mat3 uCamera;\n uniform float uPointSize;\n flat out uint vTerm;\n void main() {\n vec3 clip = uCamera * vec3(aPosition, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n vTerm = aTerm;\n }`;\n\n const pointFragment = `#version 300 es\n precision highp float;\n flat in uint vTerm;\n uniform sampler2D uPalette;\n uniform float uPaletteSize;\n uniform float uPointSize;\n out vec4 outColor;\n void main() {\n vec2 pc = gl_PointCoord * 2.0 - 1.0;\n float r = length(pc);\n if (r > 1.0) discard;\n\n float idx = clamp(float(vTerm), 0.0, max(0.0, uPaletteSize - 1.0));\n vec2 uv = vec2((idx + 0.5) / uPaletteSize, 0.5);\n vec4 color = texture(uPalette, uv);\n if (color.a <= 0.0) discard;\n\n float ringWidth = clamp(3.0 / max(1.0, uPointSize), 0.12, 0.62);\n float innerRadius = 1.0 - ringWidth;\n float aa = 1.5 / max(1.0, uPointSize);\n\n float outerMask = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r);\n float innerMask = smoothstep(innerRadius - aa, innerRadius + aa, r);\n float alpha = outerMask * innerMask * color.a;\n if (alpha <= 0.001) discard;\n\n outColor = vec4(color.rgb * alpha, alpha);\n }`;\n\n this.pointProgram = createProgram(gl, pointVertex, pointFragment);\n this.uPointCamera = gl.getUniformLocation(this.pointProgram, \"uCamera\");\n this.uPointSize = gl.getUniformLocation(this.pointProgram, \"uPointSize\");\n this.uPointPalette = gl.getUniformLocation(this.pointProgram, \"uPalette\");\n this.uPointPaletteSize = gl.getUniformLocation(this.pointProgram, \"uPaletteSize\");\n if (!this.uPointCamera || !this.uPointSize || !this.uPointPalette || !this.uPointPaletteSize) {\n throw new Error(\"point uniform location lookup failed\");\n }\n\n this.pointVao = gl.createVertexArray();\n this.pointPosBuffer = gl.createBuffer();\n this.pointTermBuffer = gl.createBuffer();\n this.pointPaletteTexture = gl.createTexture();\n if (!this.pointVao || !this.pointPosBuffer || !this.pointTermBuffer || !this.pointPaletteTexture) {\n throw new Error(\"point buffer allocation failed\");\n }\n\n gl.bindVertexArray(this.pointVao);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.pointPosBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n const pointPosLoc = gl.getAttribLocation(this.pointProgram, \"aPosition\");\n if (pointPosLoc < 0) {\n throw new Error(\"point position attribute not found\");\n }\n gl.enableVertexAttribArray(pointPosLoc);\n gl.vertexAttribPointer(pointPosLoc, 2, gl.FLOAT, false, 0, 0);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.pointTermBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n const pointTermLoc = gl.getAttribLocation(this.pointProgram, \"aTerm\");\n if (pointTermLoc < 0) {\n throw new Error(\"point term attribute not found\");\n }\n gl.enableVertexAttribArray(pointTermLoc);\n gl.vertexAttribIPointer(pointTermLoc, 1, gl.UNSIGNED_SHORT, 0, 0);\n\n gl.bindVertexArray(null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n gl.bindTexture(gl.TEXTURE_2D, this.pointPaletteTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n 1,\n 1,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n new Uint8Array([160, 160, 160, 255]),\n );\n gl.bindTexture(gl.TEXTURE_2D, null);\n }\n\n setViewState(next) {\n const normalized = { ...next };\n if (typeof normalized.zoom === \"number\") {\n normalized.zoom = clamp(normalized.zoom, this.minZoom, this.maxZoom);\n }\n this.camera.setViewState(normalized);\n this.clampViewState();\n this.emitViewState();\n this.requestRender();\n }\n\n getViewState() {\n return this.camera.getViewState();\n }\n\n setPointPalette(colors) {\n if (!colors || !colors.length) return;\n const gl = this.gl;\n const paletteSize = Math.max(1, Math.floor(colors.length / 4));\n this.pointPaletteSize = paletteSize;\n gl.bindTexture(gl.TEXTURE_2D, this.pointPaletteTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, paletteSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, colors);\n gl.bindTexture(gl.TEXTURE_2D, null);\n this.requestRender();\n }\n\n setPointData(points) {\n const gl = this.gl;\n if (!points || !points.count || !points.positions || !points.paletteIndices) {\n this.pointCount = 0;\n this.requestRender();\n return;\n }\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.pointPosBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, points.positions, gl.STATIC_DRAW);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.pointTermBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, points.paletteIndices, gl.STATIC_DRAW);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n this.pointCount = points.count;\n this.requestRender();\n }\n\n setInteractionLock(locked) {\n const next = Boolean(locked);\n if (this.interactionLocked === next) return;\n this.interactionLocked = next;\n if (next) {\n this.cancelDrag();\n }\n }\n\n cancelDrag() {\n if (this.pointerId !== null && this.canvas.hasPointerCapture(this.pointerId)) {\n try {\n this.canvas.releasePointerCapture(this.pointerId);\n } catch {\n // noop\n }\n }\n this.dragging = false;\n this.pointerId = null;\n this.canvas.classList.remove(\"dragging\");\n }\n\n screenToWorld(clientX, clientY) {\n const rect = this.canvas.getBoundingClientRect();\n const sx = clientX - rect.left;\n const sy = clientY - rect.top;\n const state = this.camera.getViewState();\n return [state.offsetX + sx / state.zoom, state.offsetY + sy / state.zoom];\n }\n\n worldToScreen(worldX, worldY) {\n const state = this.camera.getViewState();\n return [(worldX - state.offsetX) * state.zoom, (worldY - state.offsetY) * state.zoom];\n }\n\n getPointSizeByZoom() {\n const zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n const continuousZoom = this.source.maxTierZoom + Math.log2(zoom);\n const stops = [\n [1, 2.6],\n [2, 3.1],\n [3, 3.8],\n [4, 4.8],\n [5, 6.1],\n [6, 7.4],\n [7, 8.4],\n [8, 9.0],\n [9, 11.5],\n [10, 14.5],\n [11, 18.0],\n [12, 22.0],\n ];\n let size = stops[0][1];\n for (let i = 1; i < stops.length; i += 1) {\n const [z0, s0] = stops[i - 1];\n const [z1, s1] = stops[i];\n if (continuousZoom <= z0) break;\n const t = clamp((continuousZoom - z0) / Math.max(1e-6, z1 - z0), 0, 1);\n size = s0 + (s1 - s0) * t;\n }\n\n const lastStop = stops[stops.length - 1];\n if (continuousZoom > lastStop[0]) {\n size += (continuousZoom - lastStop[0]) * 4.0;\n }\n\n return clamp(size, 2.2, 36.0);\n }\n\n fitToImage() {\n const rect = this.canvas.getBoundingClientRect();\n const vw = Math.max(1, rect.width || 1);\n const vh = Math.max(1, rect.height || 1);\n\n const zoom = Math.min(vw / this.source.width, vh / this.source.height);\n const safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n this.fitZoom = safeZoom;\n this.minZoom = Math.max(this.fitZoom * 0.5, 1e-6);\n this.maxZoom = Math.max(1, this.fitZoom * 8);\n if (this.minZoom > this.maxZoom) {\n this.minZoom = this.maxZoom;\n }\n\n const visibleWorldW = vw / safeZoom;\n const visibleWorldH = vh / safeZoom;\n\n this.camera.setViewState({\n zoom: clamp(safeZoom, this.minZoom, this.maxZoom),\n offsetX: (this.source.width - visibleWorldW) * 0.5,\n offsetY: (this.source.height - visibleWorldH) * 0.5,\n });\n\n this.clampViewState();\n this.emitViewState();\n this.requestRender();\n }\n\n zoomBy(factor, screenX, screenY) {\n const state = this.camera.getViewState();\n const nextZoom = clamp(state.zoom * factor, this.minZoom, this.maxZoom);\n if (nextZoom === state.zoom) {\n return;\n }\n\n const worldX = state.offsetX + screenX / state.zoom;\n const worldY = state.offsetY + screenY / state.zoom;\n\n this.camera.setViewState({\n zoom: nextZoom,\n offsetX: worldX - screenX / nextZoom,\n offsetY: worldY - screenY / nextZoom,\n });\n\n this.clampViewState();\n this.emitViewState();\n this.requestRender();\n }\n\n clampViewState() {\n const state = this.camera.getViewState();\n const vp = this.camera.getViewport();\n\n const visibleW = vp.width / state.zoom;\n const visibleH = vp.height / state.zoom;\n\n const marginX = visibleW * 0.2;\n const marginY = visibleH * 0.2;\n\n const minX = -marginX;\n const maxX = this.source.width - visibleW + marginX;\n const minY = -marginY;\n const maxY = this.source.height - visibleH + marginY;\n\n this.camera.setViewState({\n offsetX: clamp(state.offsetX, minX, maxX),\n offsetY: clamp(state.offsetY, minY, maxY),\n });\n }\n\n emitViewState() {\n if (typeof this.onViewStateChange === \"function\") {\n this.onViewStateChange(this.camera.getViewState());\n }\n }\n\n selectTier() {\n const zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n const rawTier = this.source.maxTierZoom + Math.log2(zoom);\n return clamp(Math.floor(rawTier), 0, this.source.maxTierZoom);\n }\n\n getViewBounds() {\n const state = this.camera.getViewState();\n const vp = this.camera.getViewport();\n return [\n state.offsetX,\n state.offsetY,\n state.offsetX + vp.width / state.zoom,\n state.offsetY + vp.height / state.zoom,\n ];\n }\n\n intersectsBounds(a, b) {\n return !(a[2] <= b[0] || a[0] >= b[2] || a[3] <= b[1] || a[1] >= b[3]);\n }\n\n getVisibleTiles() {\n const tier = this.selectTier();\n this.currentTier = tier;\n\n const state = this.camera.getViewState();\n const vp = this.camera.getViewport();\n\n const levelScale = Math.pow(2, this.source.maxTierZoom - tier);\n const levelWidth = Math.ceil(this.source.width / levelScale);\n const levelHeight = Math.ceil(this.source.height / levelScale);\n\n const tilesX = Math.max(1, Math.ceil(levelWidth / this.source.tileSize));\n const tilesY = Math.max(1, Math.ceil(levelHeight / this.source.tileSize));\n\n const viewMinX = state.offsetX;\n const viewMinY = state.offsetY;\n const viewMaxX = state.offsetX + vp.width / state.zoom;\n const viewMaxY = state.offsetY + vp.height / state.zoom;\n\n const minTileX = clamp(Math.floor((viewMinX / levelScale) / this.source.tileSize), 0, tilesX - 1);\n const maxTileX = clamp(Math.floor(((viewMaxX - 1) / levelScale) / this.source.tileSize), 0, tilesX - 1);\n const minTileY = clamp(Math.floor((viewMinY / levelScale) / this.source.tileSize), 0, tilesY - 1);\n const maxTileY = clamp(Math.floor(((viewMaxY - 1) / levelScale) / this.source.tileSize), 0, tilesY - 1);\n\n if (minTileX > maxTileX || minTileY > maxTileY) {\n return [];\n }\n\n const centerTileX = ((viewMinX + viewMaxX) * 0.5 / levelScale) / this.source.tileSize;\n const centerTileY = ((viewMinY + viewMaxY) * 0.5 / levelScale) / this.source.tileSize;\n\n const visible = [];\n\n for (let y = minTileY; y <= maxTileY; y += 1) {\n for (let x = minTileX; x <= maxTileX; x += 1) {\n const left = x * this.source.tileSize * levelScale;\n const top = y * this.source.tileSize * levelScale;\n const right = Math.min((x + 1) * this.source.tileSize, levelWidth) * levelScale;\n const bottom = Math.min((y + 1) * this.source.tileSize, levelHeight) * levelScale;\n\n const dx = x - centerTileX;\n const dy = y - centerTileY;\n\n visible.push({\n key: `${tier}/${x}/${y}`,\n tier,\n x,\n y,\n bounds: [left, top, right, bottom],\n distance2: dx * dx + dy * dy,\n url: toTileUrl(this.source, tier, x, y),\n });\n }\n }\n\n visible.sort((a, b) => a.distance2 - b.distance2);\n return visible;\n }\n\n requestTile(tile) {\n if (this.cache.has(tile.key) || this.inflight.has(tile.key) || this.destroyed) {\n return;\n }\n\n const controller = new AbortController();\n this.inflight.set(tile.key, controller);\n\n const useAuthHeader = !!this.authToken;\n fetch(tile.url, {\n signal: controller.signal,\n headers: useAuthHeader ? { Authorization: this.authToken } : undefined,\n })\n .then(response => {\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n return response.blob();\n })\n .then(blob => createImageBitmap(blob))\n .then(bitmap => {\n this.inflight.delete(tile.key);\n if (this.destroyed || controller.signal.aborted) {\n bitmap.close();\n return;\n }\n\n const texture = this.gl.createTexture();\n if (!texture) {\n bitmap.close();\n return;\n }\n\n this.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, bitmap);\n this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n bitmap.close();\n\n this.cache.set(tile.key, {\n texture,\n bounds: tile.bounds,\n tier: tile.tier,\n lastUsed: this.frameSerial,\n });\n\n this.trimCache();\n this.requestRender();\n })\n .catch(error => {\n this.inflight.delete(tile.key);\n if (controller.signal.aborted) {\n return;\n }\n console.warn(\"tile load failed\", tile.url, error);\n });\n }\n\n trimCache() {\n if (this.cache.size <= this.maxCacheTiles) {\n return;\n }\n\n const entries = Array.from(this.cache.entries());\n entries.sort((a, b) => a[1].lastUsed - b[1].lastUsed);\n\n const removeCount = this.cache.size - this.maxCacheTiles;\n for (let i = 0; i < removeCount; i += 1) {\n const [key, value] = entries[i];\n this.gl.deleteTexture(value.texture);\n this.cache.delete(key);\n }\n }\n\n render() {\n if (this.destroyed) {\n return;\n }\n\n this.frameSerial += 1;\n\n const gl = this.gl;\n gl.clearColor(0.03, 0.06, 0.1, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n const visible = this.getVisibleTiles();\n gl.useProgram(this.program);\n gl.bindVertexArray(this.vao);\n gl.uniformMatrix3fv(this.uCamera, false, this.camera.getMatrix());\n gl.uniform1i(this.uTexture, 0);\n\n const viewBounds = this.getViewBounds();\n const fallbackTiles = [];\n for (const [, cached] of this.cache) {\n if (!this.intersectsBounds(cached.bounds, viewBounds)) {\n continue;\n }\n fallbackTiles.push(cached);\n }\n\n fallbackTiles.sort((a, b) => a.tier - b.tier);\n for (const cached of fallbackTiles) {\n cached.lastUsed = this.frameSerial;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, cached.texture);\n gl.uniform4f(this.uBounds, cached.bounds[0], cached.bounds[1], cached.bounds[2], cached.bounds[3]);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n let renderedTiles = 0;\n\n for (const tile of visible) {\n const cached = this.cache.get(tile.key);\n if (!cached) {\n this.requestTile(tile);\n continue;\n }\n\n cached.lastUsed = this.frameSerial;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, cached.texture);\n gl.uniform4f(this.uBounds, cached.bounds[0], cached.bounds[1], cached.bounds[2], cached.bounds[3]);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n renderedTiles += 1;\n }\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.bindVertexArray(null);\n\n let renderedPoints = 0;\n if (this.pointCount > 0) {\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n gl.useProgram(this.pointProgram);\n gl.bindVertexArray(this.pointVao);\n gl.uniformMatrix3fv(this.uPointCamera, false, this.camera.getMatrix());\n gl.uniform1f(this.uPointSize, this.getPointSizeByZoom());\n gl.uniform1f(this.uPointPaletteSize, this.pointPaletteSize);\n gl.uniform1i(this.uPointPalette, 1);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, this.pointPaletteTexture);\n gl.drawArrays(gl.POINTS, 0, this.pointCount);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.bindVertexArray(null);\n renderedPoints = this.pointCount;\n }\n\n if (typeof this.onStats === \"function\") {\n this.onStats({\n tier: this.currentTier,\n visible: visible.length,\n rendered: renderedTiles,\n points: renderedPoints,\n fallback: fallbackTiles.length,\n cache: this.cache.size,\n inflight: this.inflight.size,\n });\n }\n }\n\n requestRender() {\n if (this.frame !== null || this.destroyed) {\n return;\n }\n\n this.frame = requestAnimationFrame(() => {\n this.frame = null;\n this.render();\n });\n }\n\n resize() {\n const rect = this.canvas.getBoundingClientRect();\n const cssW = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n const cssH = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n\n const pixelW = Math.max(1, Math.round(cssW * dpr));\n const pixelH = Math.max(1, Math.round(cssH * dpr));\n\n if (this.canvas.width !== pixelW || this.canvas.height !== pixelH) {\n this.canvas.width = pixelW;\n this.canvas.height = pixelH;\n }\n\n this.camera.setViewport(cssW, cssH);\n this.gl.viewport(0, 0, pixelW, pixelH);\n this.requestRender();\n }\n\n onPointerDown(event) {\n if (this.interactionLocked) {\n return;\n }\n this.dragging = true;\n this.pointerId = event.pointerId;\n this.lastPointerX = event.clientX;\n this.lastPointerY = event.clientY;\n this.canvas.classList.add(\"dragging\");\n this.canvas.setPointerCapture(event.pointerId);\n }\n\n onPointerMove(event) {\n if (this.interactionLocked) {\n return;\n }\n if (!this.dragging || event.pointerId !== this.pointerId) {\n return;\n }\n\n const dx = event.clientX - this.lastPointerX;\n const dy = event.clientY - this.lastPointerY;\n this.lastPointerX = event.clientX;\n this.lastPointerY = event.clientY;\n\n const state = this.camera.getViewState();\n this.camera.setViewState({\n offsetX: state.offsetX - dx / state.zoom,\n offsetY: state.offsetY - dy / state.zoom,\n });\n\n this.clampViewState();\n this.emitViewState();\n this.requestRender();\n }\n\n onPointerUp(event) {\n if (this.interactionLocked) {\n return;\n }\n if (event.pointerId !== this.pointerId) {\n return;\n }\n this.dragging = false;\n this.pointerId = null;\n this.canvas.classList.remove(\"dragging\");\n }\n\n onWheel(event) {\n if (this.interactionLocked) {\n event.preventDefault();\n return;\n }\n event.preventDefault();\n const rect = this.canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n const factor = event.deltaY < 0 ? 1.12 : 0.89;\n this.zoomBy(factor, x, y);\n }\n\n onDoubleClick(event) {\n if (this.interactionLocked) {\n return;\n }\n const rect = this.canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n this.zoomBy(event.shiftKey ? 0.8 : 1.25, x, y);\n }\n\n destroy() {\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n\n if (this.frame !== null) {\n cancelAnimationFrame(this.frame);\n this.frame = null;\n }\n\n this.resizeObserver.disconnect();\n\n this.canvas.removeEventListener(\"pointerdown\", this.boundPointerDown);\n this.canvas.removeEventListener(\"pointermove\", this.boundPointerMove);\n this.canvas.removeEventListener(\"pointerup\", this.boundPointerUp);\n this.canvas.removeEventListener(\"pointercancel\", this.boundPointerUp);\n this.canvas.removeEventListener(\"wheel\", this.boundWheel);\n this.canvas.removeEventListener(\"dblclick\", this.boundDoubleClick);\n\n this.cancelDrag();\n\n for (const [, controller] of this.inflight) {\n controller.abort();\n }\n this.inflight.clear();\n\n for (const [, value] of this.cache) {\n this.gl.deleteTexture(value.texture);\n }\n this.cache.clear();\n\n this.gl.deleteBuffer(this.vbo);\n this.gl.deleteVertexArray(this.vao);\n this.gl.deleteProgram(this.program);\n\n this.gl.deleteBuffer(this.pointPosBuffer);\n this.gl.deleteBuffer(this.pointTermBuffer);\n this.gl.deleteTexture(this.pointPaletteTexture);\n this.gl.deleteVertexArray(this.pointVao);\n this.gl.deleteProgram(this.pointProgram);\n }\n}\n","import {\n\ttype CSSProperties,\n\ttype MouseEvent as ReactMouseEvent,\n\ttype PointerEvent as ReactPointerEvent,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { filterPointDataByPolygons } from \"../wsi/point-clip\";\nimport type {\n\tWsiImageSource,\n\tWsiPointData,\n\tWsiRegion,\n\tWsiRenderStats,\n\tWsiViewState,\n} from \"../wsi/types\";\nimport { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type {\n\tDrawCoordinate,\n\tDrawResult,\n\tDrawTool,\n\tStampOptions,\n\tRegionLabelStyle,\n\tRegionStrokeStyle,\n} from \"./draw-layer\";\nimport { DrawLayer } from \"./draw-layer\";\nimport { OverviewMap, type OverviewMapOptions } from \"./overview-map\";\n\nconst EMPTY_ROI_REGIONS: WsiRegion[] = [];\nconst EMPTY_ROI_POLYGONS: DrawCoordinate[][] = [];\n\nexport interface RegionHoverEvent {\n\tregion: WsiRegion | null;\n\tregionId: string | number | null;\n\tregionIndex: number;\n\tcoordinate: DrawCoordinate | null;\n}\n\nexport interface RegionClickEvent {\n\tregion: WsiRegion;\n\tregionId: string | number;\n\tregionIndex: number;\n\tcoordinate: DrawCoordinate;\n}\n\nfunction resolveRegionId(region: WsiRegion, index: number): string | number {\n\treturn region.id ?? index;\n}\n\nfunction isPointInPolygon(\n\tpoint: DrawCoordinate,\n\tpolygon: DrawCoordinate[],\n): boolean {\n\tif (!Array.isArray(polygon) || polygon.length < 3) return false;\n\n\tconst [x, y] = point;\n\tlet inside = false;\n\n\tfor (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n\t\tconst [xi, yi] = polygon[i];\n\t\tconst [xj, yj] = polygon[j];\n\t\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / Math.max(1e-12, yj - yi) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\n\treturn inside;\n}\n\nfunction pickRegionAt(\n\tcoord: DrawCoordinate,\n\tregions: WsiRegion[],\n): {\n\tregion: WsiRegion;\n\tregionIndex: number;\n\tregionId: string | number;\n} | null {\n\tfor (let i = regions.length - 1; i >= 0; i -= 1) {\n\t\tconst region = regions[i];\n\t\tif (!region?.coordinates?.length) continue;\n\t\tif (!isPointInPolygon(coord, region.coordinates)) continue;\n\t\treturn {\n\t\t\tregion,\n\t\t\tregionIndex: i,\n\t\t\tregionId: resolveRegionId(region, i),\n\t\t};\n\t}\n\treturn null;\n}\n\nexport interface WsiViewerCanvasProps {\n\tsource: WsiImageSource | null;\n\tviewState?: Partial<WsiViewState> | null;\n\tonViewStateChange?: (next: WsiViewState) => void;\n\tonStats?: (stats: WsiRenderStats) => void;\n\tfitNonce?: number;\n\tauthToken?: string;\n\tpointData?: WsiPointData | null;\n\tpointPalette?: Uint8Array | null;\n\troiRegions?: WsiRegion[];\n\troiPolygons?: DrawCoordinate[][];\n\tclipPointsToRois?: boolean;\n\tinteractionLock?: boolean;\n\tdrawTool?: DrawTool;\n\tstampOptions?: StampOptions;\n\tregionStrokeStyle?: Partial<RegionStrokeStyle>;\n\tregionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n\tregionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n\tregionLabelStyle?: Partial<RegionLabelStyle>;\n\tonRegionHover?: (event: RegionHoverEvent) => void;\n\tonRegionClick?: (event: RegionClickEvent) => void;\n\tonActiveRegionChange?: (regionId: string | number | null) => void;\n\tonDrawComplete?: (result: DrawResult) => void;\n\tshowOverviewMap?: boolean;\n\toverviewMapOptions?: Partial<OverviewMapOptions>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nexport function WsiViewerCanvas({\n\tsource,\n\tviewState,\n\tonViewStateChange,\n\tonStats,\n\tfitNonce = 0,\n\tauthToken = \"\",\n\tpointData = null,\n\tpointPalette = null,\n\troiRegions,\n\troiPolygons,\n\tclipPointsToRois = false,\n\tinteractionLock = false,\n\tdrawTool = \"cursor\",\n\tstampOptions,\n\tregionStrokeStyle,\n\tregionStrokeHoverStyle,\n\tregionStrokeActiveStyle,\n\tregionLabelStyle,\n\tonRegionHover,\n\tonRegionClick,\n\tonActiveRegionChange,\n\tonDrawComplete,\n\tshowOverviewMap = false,\n\toverviewMapOptions,\n\tclassName,\n\tstyle,\n}: WsiViewerCanvasProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst rendererRef = useRef<WsiTileRenderer | null>(null);\n\tconst drawInvalidateRef = useRef<(() => void) | null>(null);\n\tconst overviewInvalidateRef = useRef<(() => void) | null>(null);\n\tconst onViewStateChangeRef =\n\t\tuseRef<typeof onViewStateChange>(onViewStateChange);\n\tconst [isOverviewOpen, setIsOverviewOpen] = useState(true);\n\tconst [hoveredRegionId, setHoveredRegionId] = useState<\n\t\tstring | number | null\n\t>(null);\n\tconst [activeRegionId, setActiveRegionId] = useState<string | number | null>(\n\t\tnull,\n\t);\n\tconst hoveredRegionIdRef = useRef<string | number | null>(null);\n\tconst safeRoiRegions = roiRegions ?? EMPTY_ROI_REGIONS;\n\tconst safeRoiPolygons = roiPolygons ?? EMPTY_ROI_POLYGONS;\n\n\tconst mergedStyle = useMemo<CSSProperties>(\n\t\t() => ({ position: \"relative\", width: \"100%\", height: \"100%\", ...style }),\n\t\t[style],\n\t);\n\n\tconst effectiveRoiRegions = useMemo<WsiRegion[]>(() => {\n\t\tif (safeRoiRegions.length > 0) {\n\t\t\treturn safeRoiRegions;\n\t\t}\n\t\tif (safeRoiPolygons.length === 0) {\n\t\t\treturn EMPTY_ROI_REGIONS;\n\t\t}\n\t\treturn safeRoiPolygons.map((coordinates, index) => ({\n\t\t\tid: index,\n\t\t\tcoordinates,\n\t\t}));\n\t}, [safeRoiRegions, safeRoiPolygons]);\n\n\tconst clipPolygons = useMemo(\n\t\t() => effectiveRoiRegions.map((region) => region.coordinates),\n\t\t[effectiveRoiRegions],\n\t);\n\n\tconst renderPointData = useMemo(() => {\n\t\tif (!clipPointsToRois) {\n\t\t\treturn pointData;\n\t\t}\n\t\treturn filterPointDataByPolygons(pointData, clipPolygons);\n\t}, [clipPointsToRois, pointData, clipPolygons]);\n\n\tconst overviewWidth = useMemo(() => {\n\t\tconst value = Number(overviewMapOptions?.width ?? 220);\n\t\treturn Number.isFinite(value) ? Math.max(64, value) : 220;\n\t}, [overviewMapOptions?.width]);\n\tconst overviewHeight = useMemo(() => {\n\t\tconst value = Number(overviewMapOptions?.height ?? 140);\n\t\treturn Number.isFinite(value) ? Math.max(48, value) : 140;\n\t}, [overviewMapOptions?.height]);\n\tconst overviewMargin = useMemo(() => {\n\t\tconst value = Number(overviewMapOptions?.margin ?? 16);\n\t\treturn Number.isFinite(value) ? Math.max(0, value) : 16;\n\t}, [overviewMapOptions?.margin]);\n\tconst overviewPosition = overviewMapOptions?.position || \"bottom-right\";\n\n\tconst commitActiveRegion = useCallback(\n\t\t(next: string | number | null) => {\n\t\t\tsetActiveRegionId((prev) => {\n\t\t\t\tif (String(prev) === String(next)) {\n\t\t\t\t\treturn prev;\n\t\t\t\t}\n\t\t\t\tonActiveRegionChange?.(next);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\t[onActiveRegionChange],\n\t);\n\n\tuseEffect(() => {\n\t\tonViewStateChangeRef.current = onViewStateChange;\n\t}, [onViewStateChange]);\n\n\tuseEffect(() => {\n\t\tconst hasActive =\n\t\t\tactiveRegionId === null\n\t\t\t\t? true\n\t\t\t\t: effectiveRoiRegions.some(\n\t\t\t\t\t\t(region, index) =>\n\t\t\t\t\t\t\tString(resolveRegionId(region, index)) === String(activeRegionId),\n\t\t\t\t\t);\n\t\tif (!hasActive && activeRegionId !== null) {\n\t\t\tcommitActiveRegion(null);\n\t\t}\n\n\t\tconst currentHover = hoveredRegionIdRef.current;\n\t\tconst hasHover =\n\t\t\tcurrentHover === null\n\t\t\t\t? true\n\t\t\t\t: effectiveRoiRegions.some(\n\t\t\t\t\t\t(region, index) =>\n\t\t\t\t\t\t\tString(resolveRegionId(region, index)) === String(currentHover),\n\t\t\t\t\t);\n\n\t\tif (!hasHover && currentHover !== null) {\n\t\t\thoveredRegionIdRef.current = null;\n\t\t\tsetHoveredRegionId(null);\n\t\t\tonRegionHover?.({\n\t\t\t\tregion: null,\n\t\t\t\tregionId: null,\n\t\t\t\tregionIndex: -1,\n\t\t\t\tcoordinate: null,\n\t\t\t});\n\t\t}\n\t}, [effectiveRoiRegions, activeRegionId, onRegionHover, commitActiveRegion]);\n\n\tconst emitViewStateChange = useCallback((next: WsiViewState): void => {\n\t\tconst callback = onViewStateChangeRef.current;\n\t\tif (callback) {\n\t\t\tcallback(next);\n\t\t}\n\t\tdrawInvalidateRef.current?.();\n\t\toverviewInvalidateRef.current?.();\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (!showOverviewMap) {\n\t\t\tsetIsOverviewOpen(false);\n\t\t\treturn;\n\t\t}\n\t\tsetIsOverviewOpen(true);\n\t}, [showOverviewMap, source?.id]);\n\n\tuseEffect(() => {\n\t\tif (drawTool === \"cursor\") return;\n\t\tif (hoveredRegionIdRef.current === null) return;\n\t\thoveredRegionIdRef.current = null;\n\t\tsetHoveredRegionId(null);\n\t\tonRegionHover?.({\n\t\t\tregion: null,\n\t\t\tregionId: null,\n\t\t\tregionIndex: -1,\n\t\t\tcoordinate: null,\n\t\t});\n\t}, [drawTool, onRegionHover]);\n\n\tconst resolveWorldCoord = useCallback(\n\t\t(clientX: number, clientY: number): DrawCoordinate | null => {\n\t\t\tconst renderer = rendererRef.current;\n\t\t\tif (!renderer) return null;\n\t\t\tconst raw = renderer.screenToWorld(clientX, clientY);\n\t\t\tif (!Array.isArray(raw) || raw.length < 2) return null;\n\t\t\tconst x = Number(raw[0]);\n\t\t\tconst y = Number(raw[1]);\n\t\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n\t\t\treturn [x, y];\n\t\t},\n\t\t[],\n\t);\n\n\tconst handleRegionPointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLDivElement>) => {\n\t\t\tif (drawTool !== \"cursor\") return;\n\t\t\tif (event.target !== canvasRef.current) {\n\t\t\t\tif (hoveredRegionIdRef.current !== null) {\n\t\t\t\t\thoveredRegionIdRef.current = null;\n\t\t\t\t\tsetHoveredRegionId(null);\n\t\t\t\t\tonRegionHover?.({\n\t\t\t\t\t\tregion: null,\n\t\t\t\t\t\tregionId: null,\n\t\t\t\t\t\tregionIndex: -1,\n\t\t\t\t\t\tcoordinate: null,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!effectiveRoiRegions.length) return;\n\n\t\t\tconst coord = resolveWorldCoord(event.clientX, event.clientY);\n\t\t\tif (!coord) return;\n\n\t\t\tconst hit = pickRegionAt(coord, effectiveRoiRegions);\n\t\t\tconst nextHoverId = hit?.regionId ?? null;\n\t\t\tconst prevHoverId = hoveredRegionIdRef.current;\n\t\t\tif (String(prevHoverId) === String(nextHoverId)) return;\n\n\t\t\thoveredRegionIdRef.current = nextHoverId;\n\t\t\tsetHoveredRegionId(nextHoverId);\n\t\t\tonRegionHover?.({\n\t\t\t\tregion: hit?.region ?? null,\n\t\t\t\tregionId: nextHoverId,\n\t\t\t\tregionIndex: hit?.regionIndex ?? -1,\n\t\t\t\tcoordinate: coord,\n\t\t\t});\n\t\t},\n\t\t[drawTool, effectiveRoiRegions, resolveWorldCoord, onRegionHover],\n\t);\n\n\tconst handleRegionPointerLeave = useCallback(() => {\n\t\tif (hoveredRegionIdRef.current === null) return;\n\t\thoveredRegionIdRef.current = null;\n\t\tsetHoveredRegionId(null);\n\t\tonRegionHover?.({\n\t\t\tregion: null,\n\t\t\tregionId: null,\n\t\t\tregionIndex: -1,\n\t\t\tcoordinate: null,\n\t\t});\n\t}, [onRegionHover]);\n\n\tconst handleRegionClick = useCallback(\n\t\t(event: ReactMouseEvent<HTMLDivElement>) => {\n\t\t\tif (drawTool !== \"cursor\") return;\n\t\t\tif (event.target !== canvasRef.current) return;\n\t\t\tif (!effectiveRoiRegions.length) {\n\t\t\t\tcommitActiveRegion(null);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst coord = resolveWorldCoord(event.clientX, event.clientY);\n\t\t\tif (!coord) return;\n\n\t\t\tconst hit = pickRegionAt(coord, effectiveRoiRegions);\n\t\t\tif (!hit) {\n\t\t\t\tcommitActiveRegion(null);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet nextActive: string | number | null = hit.regionId;\n\t\t\tif (activeRegionId !== null) {\n\t\t\t\tnextActive =\n\t\t\t\t\tString(activeRegionId) === String(hit.regionId) ? activeRegionId : null;\n\t\t\t}\n\t\t\tcommitActiveRegion(nextActive);\n\t\t\tonRegionClick?.({\n\t\t\t\tregion: hit.region,\n\t\t\t\tregionId: hit.regionId,\n\t\t\t\tregionIndex: hit.regionIndex,\n\t\t\t\tcoordinate: coord,\n\t\t\t});\n\t\t},\n\t\t[\n\t\t\tdrawTool,\n\t\t\teffectiveRoiRegions,\n\t\t\tresolveWorldCoord,\n\t\t\tonRegionClick,\n\t\t\tactiveRegionId,\n\t\t\tcommitActiveRegion,\n\t\t],\n\t);\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas || !source) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst renderer = new WsiTileRenderer(canvas, source, {\n\t\t\tonViewStateChange: emitViewStateChange,\n\t\t\tonStats,\n\t\t\tauthToken,\n\t\t});\n\n\t\trendererRef.current = renderer;\n\t\tif (viewState) {\n\t\t\trenderer.setViewState(viewState);\n\t\t}\n\t\trenderer.setInteractionLock(interactionLock);\n\n\t\treturn () => {\n\t\t\trenderer.destroy();\n\t\t\trendererRef.current = null;\n\t\t};\n\t}, [source, onStats, authToken, emitViewStateChange]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer || !viewState) {\n\t\t\treturn;\n\t\t}\n\t\trenderer.setViewState(viewState);\n\t}, [viewState]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer) {\n\t\t\treturn;\n\t\t}\n\t\trenderer.fitToImage();\n\t}, [fitNonce]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer || !pointPalette) {\n\t\t\treturn;\n\t\t}\n\t\trenderer.setPointPalette(pointPalette);\n\t}, [pointPalette]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer) {\n\t\t\treturn;\n\t\t}\n\t\trenderer.setPointData(renderPointData);\n\t}, [renderPointData]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer) {\n\t\t\treturn;\n\t\t}\n\t\trenderer.setInteractionLock(interactionLock);\n\t}, [interactionLock]);\n\n\treturn (\n\t\t<div\n\t\t\tclassName={className}\n\t\t\tstyle={mergedStyle}\n\t\t\tonPointerMove={handleRegionPointerMove}\n\t\t\tonPointerLeave={handleRegionPointerLeave}\n\t\t\tonClick={handleRegionClick}\n\t\t>\n\t\t\t<canvas\n\t\t\t\tref={canvasRef}\n\t\t\t\tclassName=\"wsi-render-canvas\"\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\tinset: 0,\n\t\t\t\t\tzIndex: 1,\n\t\t\t\t\twidth: \"100%\",\n\t\t\t\t\theight: \"100%\",\n\t\t\t\t\tdisplay: \"block\",\n\t\t\t\t\ttouchAction: \"none\",\n\t\t\t\t\tcursor:\n\t\t\t\t\t\tdrawTool === \"cursor\" && hoveredRegionId !== null\n\t\t\t\t\t\t\t? \"pointer\"\n\t\t\t\t\t\t\t: interactionLock\n\t\t\t\t\t\t\t\t? \"crosshair\"\n\t\t\t\t\t\t\t\t: \"grab\",\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t{source ? (\n\t\t\t\t<DrawLayer\n\t\t\t\t\ttool={drawTool}\n\t\t\t\t\tenabled={drawTool !== \"cursor\"}\n\t\t\t\t\timageWidth={source.width}\n\t\t\t\t\timageHeight={source.height}\n\t\t\t\t\timageMpp={source.mpp}\n\t\t\t\t\timageZoom={source.maxTierZoom}\n\t\t\t\t\tstampOptions={stampOptions}\n\t\t\t\t\tprojectorRef={rendererRef}\n\t\t\t\t\tviewStateSignal={viewState}\n\t\t\t\t\tpersistedRegions={effectiveRoiRegions}\n\t\t\t\t\tregionStrokeStyle={regionStrokeStyle}\n\t\t\t\t\tregionStrokeHoverStyle={regionStrokeHoverStyle}\n\t\t\t\t\tregionStrokeActiveStyle={regionStrokeActiveStyle}\n\t\t\t\t\thoveredRegionId={hoveredRegionId}\n\t\t\t\t\tactiveRegionId={activeRegionId}\n\t\t\t\t\tregionLabelStyle={regionLabelStyle}\n\t\t\t\t\tinvalidateRef={drawInvalidateRef}\n\t\t\t\t\tonDrawComplete={onDrawComplete}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{source && showOverviewMap ? (\n\t\t\t\tisOverviewOpen ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<OverviewMap\n\t\t\t\t\t\t\tsource={source}\n\t\t\t\t\t\t\tprojectorRef={rendererRef}\n\t\t\t\t\t\t\tauthToken={authToken}\n\t\t\t\t\t\t\toptions={overviewMapOptions}\n\t\t\t\t\t\t\tinvalidateRef={overviewInvalidateRef}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-label=\"Hide overview map\"\n\t\t\t\t\t\t\tonClick={() => setIsOverviewOpen(false)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\t\t\t\tzIndex: 6,\n\t\t\t\t\t\t\t\t...(overviewPosition.includes(\"left\")\n\t\t\t\t\t\t\t\t\t? { left: overviewMargin }\n\t\t\t\t\t\t\t\t\t: { right: overviewMargin }),\n\t\t\t\t\t\t\t\t...(overviewPosition.includes(\"top\")\n\t\t\t\t\t\t\t\t\t? { top: overviewMargin + overviewHeight + 8 }\n\t\t\t\t\t\t\t\t\t: { bottom: overviewMargin + overviewHeight + 8 }),\n\t\t\t\t\t\t\t\twidth: 20,\n\t\t\t\t\t\t\t\theight: 20,\n\t\t\t\t\t\t\t\tborderRadius: 999,\n\t\t\t\t\t\t\t\tborder: \"1px solid rgba(255,255,255,0.4)\",\n\t\t\t\t\t\t\t\tbackground: \"rgba(8, 14, 22, 0.9)\",\n\t\t\t\t\t\t\t\tcolor: \"#fff\",\n\t\t\t\t\t\t\t\tfontSize: 13,\n\t\t\t\t\t\t\t\tlineHeight: 1,\n\t\t\t\t\t\t\t\tcursor: \"pointer\",\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t×\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-label=\"Show overview map\"\n\t\t\t\t\t\tonClick={() => setIsOverviewOpen(true)}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\t\t\tzIndex: 6,\n\t\t\t\t\t\t\t...(overviewPosition.includes(\"left\")\n\t\t\t\t\t\t\t\t? { left: overviewMargin }\n\t\t\t\t\t\t\t\t: { right: overviewMargin }),\n\t\t\t\t\t\t\t...(overviewPosition.includes(\"top\")\n\t\t\t\t\t\t\t\t? { top: overviewMargin }\n\t\t\t\t\t\t\t\t: { bottom: overviewMargin }),\n\t\t\t\t\t\t\theight: 24,\n\t\t\t\t\t\t\tminWidth: 40,\n\t\t\t\t\t\t\tborderRadius: 999,\n\t\t\t\t\t\t\tborder: \"1px solid rgba(255,255,255,0.45)\",\n\t\t\t\t\t\t\tbackground: \"rgba(8, 14, 22, 0.9)\",\n\t\t\t\t\t\t\tcolor: \"#dff8ff\",\n\t\t\t\t\t\t\tfontSize: 11,\n\t\t\t\t\t\t\tfontWeight: 700,\n\t\t\t\t\t\t\tcursor: \"pointer\",\n\t\t\t\t\t\t\tpadding: \"0 8px\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tMap\n\t\t\t\t\t</button>\n\t\t\t\t)\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"names":["compileShader","gl","type","source","shader","log","createProgram","vertexSource","fragmentSource","vertexShader","fragmentShader","program","requireUniformLocation","uniformName","location","requireWebGL2","canvas","context","OrthoCamera$1","__publicField","width","height","next","viewWidth","viewHeight","sx","sy","tx","ty","VERTEX_SHADER","FRAGMENT_SHADER","M1TileRenderer","options","OrthoCamera","vao","quadBuffer","quadVertices","unitLocation","uvLocation","stride","tiles","version","loaded","tile","viewState","response","blob","bitmap","texture","error","rect","cssWidth","cssHeight","dpr","targetWidth","targetHeight","viewport","zoom","safeZoom","visibleWorldWidth","visibleWorldHeight","offsetX","offsetY","DEFAULT_POINT_COLOR","clamp","value","min","max","calcScaleResolution","imageMpp","imageZoom","currentZoom","mpp","z0","z1","calcScaleLength","length","unit","isSameViewState","a","b","toBearerToken","trimmed","token","hexToRgba","hex","match","n","buildTermPalette","terms","palette","termToPaletteIndex","term","termId","colors","i","vs","fs","DRAW_FILL","FREEHAND_MIN_POINTS","FREEHAND_SCREEN_STEP","CIRCLE_SIDES","MIN_AREA_PX","EMPTY_REGIONS","EMPTY_DASH","MICRONS_PER_MM","DEFAULT_STAMP_RECTANGLE_AREA_MM2","DEFAULT_STAMP_CIRCLE_AREA_MM2","LEGACY_HPF_CIRCLE_AREA_MM2","DEFAULT_REGION_STROKE_STYLE","DEFAULT_REGION_LABEL_STYLE","isStampTool","tool","clampPositiveOrFallback","fallback","resolveStampOptions","mm2ToUm2","areaMm2","createSquareFromCenter","center","halfLength","closeRing","createCircleFromCenter","radius","sides","coords","t","out","x","y","first","last","createRectangle","start","end","createCircle","centerX","centerY","polygonArea","sum","computeBounds","minX","minY","maxX","maxY","isValidPolygon","drawPath","ctx","points","strokeStyle","close","fill","resolveStrokeStyle","style","dash","shadowBlur","shadowOffsetX","shadowOffsetY","mergeStrokeStyle","base","override","isSameRegionId","resolveLabelStyle","px","py","bw","oy","br","drawRoundedRect","r","getTopAnchor","point","drawRegionLabel","text","anchor","canvasWidth","canvasHeight","labelStyle","label","boxWidth","boxHeight","left","top","clampWorld","coord","imageWidth","imageHeight","toCoord","DrawLayer","stampOptions","projectorRef","onDrawComplete","enabled","viewStateSignal","persistedRegions","persistedPolygons","regionStrokeStyle","regionStrokeHoverStyle","regionStrokeActiveStyle","hoveredRegionId","activeRegionId","regionLabelStyle","invalidateRef","className","canvasRef","useRef","drawPendingRef","lastToolRef","sessionRef","active","mergedPersistedRegions","useMemo","coordinates","index","resolvedStrokeStyle","resolvedHoverStrokeStyle","resolvedActiveStrokeStyle","resolvedLabelStyle","resolvedStampOptions","mergedStyle","resizeCanvas","useCallback","w","h","worldToScreenPoints","projector","micronsToWorldPixels","lengthUm","mppValue","imageZoomValue","viewZoomRaw","viewZoom","continuousZoom","umPerScreenPixel","buildStampCoords","stampTool","areaUm2","buildPreviewCoords","session","drawOverlay","region","ring","closed","screen","regionKey","preview","line","polygon","anchorWorld","anchorScreen","requestDraw","resetSession","toWorld","event","raw","finishSession","handleStampAt","handlePointerDown","world","handlePointerMove","minWorldStep","minWorldStep2","prev","dx","dy","handlePointerUp","handlePointerLeave","useEffect","observer","onKeyDown","jsx","normalizeImageInfo","tileBaseUrl","ims","tileSize","maxTierZoom","tilePath","toTileUrl","tier","normalizedPath","DEFAULT_OVERVIEW_MAP_OPTIONS","toPositiveNumber","isFiniteBounds","bounds","OverviewMap","authToken","thumbnailRef","lastBoundsRef","draggingRef","rafRef","margin","borderRadius","borderWidth","maxThumbnailTiles","backgroundColor","borderColor","viewportStrokeColor","viewportFillColor","interactive","showThumbnail","position","pos","draw","cssW","cssH","pixelW","pixelH","safeBounds","right","bottom","rectW","rectH","toWorldFromClient","clientX","clientY","nx","ny","recenterTo","worldX","worldY","visibleW","visibleH","drag","cancelled","levelScale","levelWidth","levelHeight","tilesX","tilesY","tileCount","requests","useAuthHeader","results","result","dw","dh","TileViewerCanvas","rendererRef","renderer","preparePolygons","polygons","prepared","poly","isInsideRing","inside","j","xi","yi","xj","yj","isInsideAnyPolygon","filterPointDataByPolygons","pointData","count","positions","nextPositions","nextTerms","cursor","worldWidth","worldHeight","WsiTileRenderer","vertex","fragment","aUnit","aUv","pointVertex","pointFragment","pointPosLoc","pointTermLoc","normalized","paletteSize","locked","state","stops","size","s0","s1","lastStop","vw","vh","visibleWorldW","visibleWorldH","factor","screenX","screenY","nextZoom","vp","marginX","marginY","rawTier","viewMinX","viewMinY","viewMaxX","viewMaxY","minTileX","maxTileX","minTileY","maxTileY","centerTileX","centerTileY","visible","controller","entries","removeCount","key","viewBounds","fallbackTiles","cached","renderedTiles","renderedPoints","EMPTY_ROI_REGIONS","EMPTY_ROI_POLYGONS","resolveRegionId","isPointInPolygon","pickRegionAt","regions","WsiViewerCanvas","onViewStateChange","onStats","fitNonce","pointPalette","roiRegions","roiPolygons","clipPointsToRois","interactionLock","drawTool","onRegionHover","onRegionClick","onActiveRegionChange","showOverviewMap","overviewMapOptions","drawInvalidateRef","overviewInvalidateRef","onViewStateChangeRef","isOverviewOpen","setIsOverviewOpen","useState","setHoveredRegionId","setActiveRegionId","hoveredRegionIdRef","safeRoiRegions","safeRoiPolygons","effectiveRoiRegions","clipPolygons","renderPointData","overviewHeight","overviewMargin","overviewPosition","commitActiveRegion","currentHover","emitViewStateChange","callback","resolveWorldCoord","handleRegionPointerMove","hit","nextHoverId","prevHoverId","handleRegionPointerLeave","handleRegionClick","nextActive","jsxs","Fragment"],"mappings":";;;;;AAAA,SAASA,GAAcC,GAA4BC,GAAcC,GAA6B;AAC5F,QAAMC,IAASH,EAAG,aAAaC,CAAI;AACnC,MAAI,CAACE;AACH,UAAM,IAAI,MAAM,0BAA0B;AAO5C,MAJAH,EAAG,aAAaG,GAAQD,CAAM,GAC9BF,EAAG,cAAcG,CAAM,GAGnB,CADOH,EAAG,mBAAmBG,GAAQH,EAAG,cAAc,GACjD;AACP,UAAMI,IAAMJ,EAAG,iBAAiBG,CAAM,KAAK;AAC3C,UAAAH,EAAG,aAAaG,CAAM,GAChB,IAAI,MAAMC,CAAG;AAAA,EACrB;AAEA,SAAOD;AACT;AAEO,SAASE,GAAcL,GAA4BM,GAAsBC,GAAsC;AACpH,QAAMC,IAAeT,GAAcC,GAAIA,EAAG,eAAeM,CAAY,GAC/DG,IAAiBV,GAAcC,GAAIA,EAAG,iBAAiBO,CAAc,GAErEG,IAAUV,EAAG,cAAA;AACnB,MAAI,CAACU;AACH,UAAAV,EAAG,aAAaQ,CAAY,GAC5BR,EAAG,aAAaS,CAAc,GACxB,IAAI,MAAM,2BAA2B;AAW7C,MARAT,EAAG,aAAaU,GAASF,CAAY,GACrCR,EAAG,aAAaU,GAASD,CAAc,GACvCT,EAAG,YAAYU,CAAO,GAEtBV,EAAG,aAAaQ,CAAY,GAC5BR,EAAG,aAAaS,CAAc,GAG1B,CADOT,EAAG,oBAAoBU,GAASV,EAAG,WAAW,GAChD;AACP,UAAMI,IAAMJ,EAAG,kBAAkBU,CAAO,KAAK;AAC7C,UAAAV,EAAG,cAAcU,CAAO,GAClB,IAAI,MAAMN,CAAG;AAAA,EACrB;AAEA,SAAOM;AACT;AAEO,SAASC,GACdX,GACAU,GACAE,GACsB;AACtB,QAAMC,IAAWb,EAAG,mBAAmBU,GAASE,CAAW;AAC3D,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,mCAAmCD,CAAW,EAAE;AAElE,SAAOC;AACT;AAEO,SAASC,GAAcC,GAAmD;AAC/E,QAAMC,IAAUD,EAAO,WAAW,UAAU;AAAA,IAC1C,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,uBAAuB;AAAA,IACvB,iBAAiB;AAAA,EAAA,CAClB;AAED,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,0BAA0B;AAG5C,SAAOA;AACT;ACpEO,IAAAC,KAAA,MAAkB;AAAA,EAAlB;AACG,IAAAC,EAAA,uBAAgB;AAChB,IAAAA,EAAA,wBAAiB;AAEjB,IAAAA,EAAA,mBAAuB;AAAA,MAC7B,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IAAA;AAAA;AAAA,EAGR,YAAYC,GAAeC,GAAsB;AAC/C,SAAK,gBAAgB,KAAK,IAAI,GAAGD,CAAK,GACtC,KAAK,iBAAiB,KAAK,IAAI,GAAGC,CAAM;AAAA,EAC1C;AAAA,EAEA,kBAAqD;AACnD,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IAAA;AAAA,EAEjB;AAAA,EAEA,aAAaC,GAAgC;AAC3C,IAAIA,EAAK,YAAY,WACnB,KAAK,UAAU,UAAUA,EAAK,UAG5BA,EAAK,YAAY,WACnB,KAAK,UAAU,UAAUA,EAAK,UAG5BA,EAAK,SAAS,WAChB,KAAK,UAAU,OAAO,KAAK,IAAI,MAAQA,EAAK,IAAI;AAAA,EAEpD;AAAA,EAEA,eAA0B;AACxB,WAAO,EAAE,GAAG,KAAK,UAAA;AAAA,EACnB;AAAA,EAEA,YAA0B;AACxB,UAAMC,IAAY,KAAK,gBAAgB,KAAK,UAAU,MAChDC,IAAa,KAAK,iBAAiB,KAAK,UAAU,MAElDC,IAAK,IAAIF,GACTG,IAAK,KAAKF,GACVG,IAAK,KAAK,KAAK,UAAU,UAAUF,GACnCG,IAAK,IAAI,KAAK,UAAU,UAAUF;AAExC,WAAO,IAAI,aAAa;AAAA,MACtBD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAC;AAAA,MACA;AAAA,MACAC;AAAA,MACAC;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EACH;AACF;AC7CA,MAAMC,KAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAsBhBC,KAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAajB,MAAMC,GAAe;AAAA,EAsB3B,YAAYC,GAAgC;AArB3B,IAAAb,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,gBAAS,IAAIc,GAAA;AACb,IAAAd,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAET,IAAAA,EAAA,eAAsB,CAAA;AACtB,IAAAA,EAAA,iBAAyB;AACzB,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,gBAAS;AACT,IAAAA,EAAA,6BAAsB;AAG7B,SAAK,SAASa,EAAQ,QACtB,KAAK,aAAa,KAAK,IAAI,GAAGA,EAAQ,UAAU,GAChD,KAAK,cAAc,KAAK,IAAI,GAAGA,EAAQ,WAAW,GAClD,KAAK,aAAaA,EAAQ,cAAc,CAAC,MAAM,MAAM,MAAM,CAAC,GAE5D,KAAK,KAAKjB,GAAc,KAAK,MAAM,GACnC,KAAK,UAAUT,GAAc,KAAK,IAAIuB,IAAeC,EAAe;AAEpE,UAAMI,IAAM,KAAK,GAAG,kBAAA,GACdC,IAAa,KAAK,GAAG,aAAA;AAC3B,QAAI,CAACD,KAAO,CAACC;AACZ,YAAM,IAAI,MAAM,iCAAiC;AAGlD,SAAK,MAAMD,GACX,KAAK,aAAaC,GAElB,KAAK,GAAG,gBAAgB,KAAK,GAAG,GAChC,KAAK,GAAG,WAAW,KAAK,GAAG,cAAc,KAAK,UAAU;AAExD,UAAMC,IAAe,IAAI,aAAa;AAAA,MACrC;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,IAAA,CAC7C;AAED,SAAK,GAAG,WAAW,KAAK,GAAG,cAAcA,GAAc,KAAK,GAAG,WAAW;AAE1E,UAAMC,IAAe,KAAK,GAAG,kBAAkB,KAAK,SAAS,OAAO,GAC9DC,IAAa,KAAK,GAAG,kBAAkB,KAAK,SAAS,KAAK;AAChE,QAAID,IAAe,KAAKC,IAAa;AACpC,YAAM,IAAI,MAAM,oCAAoC;AAGrD,UAAMC,IAAS,IAAI,aAAa;AAChC,SAAK,GAAG,wBAAwBF,CAAY,GAC5C,KAAK,GAAG;AAAA,MACPA;AAAA,MACA;AAAA,MACA,KAAK,GAAG;AAAA,MACR;AAAA,MACAE;AAAA,MACA;AAAA,IAAA,GAED,KAAK,GAAG,wBAAwBD,CAAU,GAC1C,KAAK,GAAG;AAAA,MACPA;AAAA,MACA;AAAA,MACA,KAAK,GAAG;AAAA,MACR;AAAA,MACAC;AAAA,MACA,IAAI,aAAa;AAAA,IAAA,GAGlB,KAAK,GAAG,gBAAgB,IAAI,GAC5B,KAAK,GAAG,WAAW,KAAK,GAAG,cAAc,IAAI,GAE7C,KAAK,kBAAkB3B;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAED,KAAK,kBAAkBA;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAED,KAAK,mBAAmBA;AAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAGGoB,EAAQ,qBACX,KAAK,sBAAsB,IAC3B,KAAK,OAAO,aAAaA,EAAQ,gBAAgB,IAGlD,KAAK,iBAAiB,IAAI,eAAe,MAAM;AAC9C,WAAK,OAAA;AAAA,IACN,CAAC,GAED,KAAK,eAAe,QAAQ,KAAK,MAAM,GACvC,KAAK,OAAA;AAAA,EACN;AAAA,EAEA,MAAM,SAASQ,GAAwC;AACtD,QAAI,KAAK;AACR;AAGD,UAAMC,IAAU,EAAE,KAAK,aAEjBC,IAAS,MAAM,QAAQ;AAAA,MAC5BF,EAAM,IAAI,OAAOG,MACG,MAAM,KAAK,SAASA,GAAMF,CAAO,CAEpD;AAAA,IAAA;AAGF,QAAI,KAAK,aAAaA,MAAY,KAAK,aAAa;AACnD,iBAAWE,KAAQD;AAClB,QAAIC,KACH,KAAK,GAAG,cAAcA,EAAK,OAAO;AAGpC;AAAA,IACD;AAEA,SAAK,aAAa,KAAK,KAAK,GAC5B,KAAK,QAAQD,EAAO,OAAO,CAACC,MAA6BA,MAAS,IAAI,GACtE,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,aAAaC,GAAqC;AACjD,SAAK,sBAAsB,IAC3B,KAAK,OAAO,aAAaA,CAAS,GAClC,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,eAA0B;AACzB,WAAO,KAAK,OAAO,aAAA;AAAA,EACpB;AAAA,EAEA,UAAgB;AACf,IAAI,KAAK,cAIT,KAAK,YAAY,IACjB,KAAK,eAAe,GAEhB,KAAK,YAAY,SACpB,qBAAqB,KAAK,OAAO,GACjC,KAAK,UAAU,OAGhB,KAAK,eAAe,WAAA,GACpB,KAAK,aAAa,KAAK,KAAK,GAC5B,KAAK,QAAQ,CAAA,GAEb,KAAK,GAAG,aAAa,KAAK,UAAU,GACpC,KAAK,GAAG,kBAAkB,KAAK,GAAG,GAClC,KAAK,GAAG,cAAc,KAAK,OAAO;AAAA,EACnC;AAAA,EAEA,MAAc,SACbD,GACAF,GAC6B;AAC7B,QAAI;AACH,YAAMI,IAAW,MAAM,MAAMF,EAAK,GAAG;AACrC,UAAI,CAACE,EAAS;AACb,cAAM,IAAI;AAAA,UACT,sBAAsBA,EAAS,MAAM,IAAIA,EAAS,UAAU;AAAA,QAAA;AAI9D,YAAMC,IAAO,MAAMD,EAAS,KAAA,GACtBE,IAAS,MAAM,kBAAkBD,CAAI;AAE3C,UAAI,KAAK,aAAaL,MAAY,KAAK;AACtC,eAAAM,EAAO,MAAA,GACA;AAGR,YAAMC,IAAU,KAAK,GAAG,cAAA;AACxB,UAAI,CAACA;AACJ,cAAAD,EAAO,MAAA,GACD,IAAI,MAAM,gCAAgC;AAGjD,kBAAK,GAAG,YAAY,KAAK,GAAG,YAAYC,CAAO,GAC/C,KAAK,GAAG,YAAY,KAAK,GAAG,qBAAqB,CAAC,GAClD,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR;AAAA,QACA,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACRD;AAAA,MAAA,GAED,KAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5CA,EAAO,MAAA,GAEA;AAAA,QACN,IAAIJ,EAAK;AAAA,QACT,QAAQA,EAAK;AAAA,QACb,SAAAK;AAAA,MAAA;AAAA,IAEF,SAASC,GAAO;AACf,qBAAQ,MAAM,sCAAsCN,EAAK,EAAE,IAAIM,CAAK,GAC7D;AAAA,IACR;AAAA,EACD;AAAA,EAEQ,SAAe;AACtB,QAAI,KAAK;AACR;AAGD,UAAMC,IAAO,KAAK,OAAO,sBAAA,GACnBC,IAAW,KAAK,IAAI,GAAGD,EAAK,SAAS,KAAK,OAAO,eAAe,CAAC,GACjEE,IAAY,KAAK,IAAI,GAAGF,EAAK,UAAU,KAAK,OAAO,gBAAgB,CAAC,GACpEG,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9CC,IAAc,KAAK,IAAI,GAAG,KAAK,MAAMH,IAAWE,CAAG,CAAC,GACpDE,IAAe,KAAK,IAAI,GAAG,KAAK,MAAMH,IAAYC,CAAG,CAAC;AAE5D,KACC,KAAK,OAAO,UAAUC,KACtB,KAAK,OAAO,WAAWC,OAEvB,KAAK,OAAO,QAAQD,GACpB,KAAK,OAAO,SAASC,IAGtB,KAAK,OAAO,YAAYJ,GAAUC,CAAS,GAC3C,KAAK,GAAG,SAAS,GAAG,GAAG,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,GAExD,CAAC,KAAK,UAAU,CAAC,KAAK,wBACzB,KAAK,WAAA,GACL,KAAK,SAAS,KAGf,KAAK,cAAA;AAAA,EACN;AAAA,EAEQ,aAAmB;AAC1B,UAAMI,IAAW,KAAK,OAAO,gBAAA,GAEvBC,IAAO,KAAK;AAAA,MACjBD,EAAS,QAAQ,KAAK;AAAA,MACtBA,EAAS,SAAS,KAAK;AAAA,IAAA,GAElBE,IAAW,OAAO,SAASD,CAAI,KAAKA,IAAO,IAAIA,IAAO,GAEtDE,IAAoBH,EAAS,QAAQE,GACrCE,IAAqBJ,EAAS,SAASE,GAEvCG,KAAW,KAAK,aAAaF,KAAqB,KAClDG,KAAW,KAAK,cAAcF,KAAsB;AAE1D,SAAK,OAAO,aAAa;AAAA,MACxB,MAAMF;AAAA,MACN,SAAAG;AAAA,MACA,SAAAC;AAAA,IAAA,CACA;AAAA,EACF;AAAA,EAEQ,gBAAsB;AAC7B,IAAI,KAAK,YAAY,QAAQ,KAAK,cAIlC,KAAK,UAAU,sBAAsB,MAAM;AAC1C,WAAK,UAAU,MACf,KAAK,OAAA;AAAA,IACN,CAAC;AAAA,EACF;AAAA,EAEQ,SAAe;AACtB,QAAI,MAAK,WAIT;AAAA,WAAK,GAAG;AAAA,QACP,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,MAAA,GAElB,KAAK,GAAG,MAAM,KAAK,GAAG,gBAAgB,GAEtC,KAAK,GAAG,WAAW,KAAK,OAAO,GAC/B,KAAK,GAAG,gBAAgB,KAAK,GAAG,GAChC,KAAK,GAAG;AAAA,QACP,KAAK;AAAA,QACL;AAAA,QACA,KAAK,OAAO,UAAA;AAAA,MAAU,GAEvB,KAAK,GAAG,UAAU,KAAK,kBAAkB,CAAC;AAE1C,iBAAWnB,KAAQ,KAAK;AACvB,aAAK,GAAG,cAAc,KAAK,GAAG,QAAQ,GACtC,KAAK,GAAG,YAAY,KAAK,GAAG,YAAYA,EAAK,OAAO,GACpD,KAAK,GAAG;AAAA,UACP,KAAK;AAAA,UACLA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,QAAA,GAEd,KAAK,GAAG,WAAW,KAAK,GAAG,gBAAgB,GAAG,CAAC;AAGhD,WAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5C,KAAK,GAAG,gBAAgB,IAAI;AAAA;AAAA,EAC7B;AAAA,EAEQ,aAAaH,GAA2B;AAC/C,eAAWG,KAAQH;AAClB,WAAK,GAAG,cAAcG,EAAK,OAAO;AAAA,EAEpC;AACD;ACnZO,MAAMoB,KAAwD;AAAA,EACpE;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAChB;ACCO,SAASC,EAAMC,GAAeC,GAAaC,GAAqB;AACtE,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKF,CAAK,CAAC;AAC1C;AAEO,SAASG,GACfC,GACAC,GACAC,GACS;AACT,QAAMC,IAAM,OAAOH,CAAQ,GACrBI,IAAK,OAAOH,CAAS,GACrBI,IAAK,OAAOH,CAAW;AAC7B,SAAI,CAAC,OAAO,SAASC,CAAG,KAAKA,KAAO,IAAU,IAC1C,CAAC,OAAO,SAASC,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,IAAUF,IAClD,KAAK,IAAI,GAAGC,IAAKC,CAAE,IAAIF;AAC/B;AAEO,SAASG,GACfN,GACAC,GACAC,GACS;AAET,MAAIK,IAAS,MADMR,GAAoBC,GAAUC,GAAWC,CAAW;AAEvE,MAAI,OAAOF,CAAQ,GAAG;AACrB,QAAIQ,IAAO;AACX,WAAID,IAAS,QACZA,KAAU,KACVC,IAAO,OAED,GAAGD,EAAO,YAAY,CAAC,CAAC,IAAIC,CAAI;AAAA,EACxC;AACA,SAAO,GAAG,KAAK,MAAMD,IAAS,GAAI,IAAI,GAAI;AAC3C;AAEO,SAASE,GACfC,GACAC,GACU;AACV,SAAI,CAACD,KAAK,CAACC,IAAU,KACjB,CAACD,KAAK,CAACC,IAAU,KAEpB,KAAK,KAAKD,EAAE,QAAQ,MAAMC,EAAE,QAAQ,EAAE,IAAI,QAC1C,KAAK,KAAKD,EAAE,WAAW,MAAMC,EAAE,WAAW,EAAE,IAAI,QAChD,KAAK,KAAKD,EAAE,WAAW,MAAMC,EAAE,WAAW,EAAE,IAAI;AAElD;AAEO,SAASC,GAAchB,GAA0C;AACvE,QAAMiB,IAAU,OAAOjB,KAAS,EAAE,EAAE,KAAA;AACpC,MAAI,CAACiB,EAAS,QAAO;AACrB,MAAI,cAAc,KAAKA,CAAO,GAAG;AAChC,UAAMC,IAAQD,EAAQ,QAAQ,eAAe,EAAE,EAAE,KAAA;AACjD,WAAOC,IAAQ,UAAUA,CAAK,KAAK;AAAA,EACpC;AACA,SAAO,UAAUD,CAAO;AACzB;AAEO,SAASE,GACfC,GACmC;AAEnC,QAAMC,IADQ,OAAOD,KAAO,EAAE,EAAE,KAAA,EACZ,MAAM,sBAAsB;AAChD,MAAI,CAACC,EAAO,QAAO,CAAC,GAAGvB,EAAmB;AAE1C,QAAMwB,IAAI,OAAO,SAASD,EAAM,CAAC,GAAG,EAAE;AACtC,SAAO,CAAEC,KAAK,KAAM,KAAMA,KAAK,IAAK,KAAKA,IAAI,KAAK,GAAG;AACtD;AAEO,SAASC,GACfC,GAIc;AACd,QAAMC,IAAmD;AAAA,IACxD,CAAC,GAAG3B,EAAmB;AAAA,EAAA,GAElB4B,wBAAyB,IAAA;AAE/B,aAAWC,KAAQH,KAAS,IAAI;AAC/B,UAAMI,IAAS,OAAOD,GAAM,UAAU,EAAE;AACxC,IAAI,CAACC,KAAUF,EAAmB,IAAIE,CAAM,MAE5CF,EAAmB,IAAIE,GAAQH,EAAQ,MAAM,GAC7CA,EAAQ,KAAKN,GAAUQ,GAAM,SAAS,CAAC;AAAA,EACxC;AAEA,QAAME,IAAS,IAAI,WAAWJ,EAAQ,SAAS,CAAC;AAChD,WAASK,IAAI,GAAGA,IAAIL,EAAQ,QAAQK,KAAK;AACxC,IAAAD,EAAOC,IAAI,CAAC,IAAIL,EAAQK,CAAC,EAAE,CAAC,GAC5BD,EAAOC,IAAI,IAAI,CAAC,IAAIL,EAAQK,CAAC,EAAE,CAAC,GAChCD,EAAOC,IAAI,IAAI,CAAC,IAAIL,EAAQK,CAAC,EAAE,CAAC,GAChCD,EAAOC,IAAI,IAAI,CAAC,IAAIL,EAAQK,CAAC,EAAE,CAAC;AAGjC,SAAO,EAAE,QAAAD,GAAQ,oBAAAH,EAAA;AAClB;AAEO,SAASrF,GACfL,GACAM,GACAC,GACe;AACf,QAAMwF,IAAK/F,EAAG,aAAaA,EAAG,aAAa,GACrCgG,IAAKhG,EAAG,aAAaA,EAAG,eAAe;AAC7C,MAAI,CAAC+F,KAAM,CAACC;AACX,UAAM,IAAI,MAAM,0BAA0B;AAK3C,MAFAhG,EAAG,aAAa+F,GAAIzF,CAAY,GAChCN,EAAG,cAAc+F,CAAE,GACf,CAAC/F,EAAG,mBAAmB+F,GAAI/F,EAAG,cAAc;AAC/C,UAAM,IAAI,MAAMA,EAAG,iBAAiB+F,CAAE,KAAK,uBAAuB;AAKnE,MAFA/F,EAAG,aAAagG,GAAIzF,CAAc,GAClCP,EAAG,cAAcgG,CAAE,GACf,CAAChG,EAAG,mBAAmBgG,GAAIhG,EAAG,cAAc;AAC/C,UAAM,IAAI,MAAMA,EAAG,iBAAiBgG,CAAE,KAAK,yBAAyB;AAGrE,QAAMtF,IAAUV,EAAG,cAAA;AACnB,MAAI,CAACU;AACJ,UAAM,IAAI,MAAM,2BAA2B;AAU5C,MAPAV,EAAG,aAAaU,GAASqF,CAAE,GAC3B/F,EAAG,aAAaU,GAASsF,CAAE,GAC3BhG,EAAG,YAAYU,CAAO,GAEtBV,EAAG,aAAa+F,CAAE,GAClB/F,EAAG,aAAagG,CAAE,GAEd,CAAChG,EAAG,oBAAoBU,GAASV,EAAG,WAAW;AAClD,UAAM,IAAI,MAAMA,EAAG,kBAAkBU,CAAO,KAAK,qBAAqB;AAGvE,SAAOA;AACR;AC7BA,MAAMuF,KAAY,2BACZC,KAAsB,GACtBC,KAAuB,GACvBC,KAAe,IACfC,KAAc,GACdC,KAA8B,CAAA,GAC9BC,KAAuB,CAAA,GACvBC,KAAiB,KACjBC,KAAmC,GACnCC,KAAgC,GAChCC,KAA6B,KAE7BC,KAAiD;AAAA,EACtD,OAAO;AAAA,EACP,OAAO;AAAA,EAEP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AAChB,GAEMC,KAA+C;AAAA,EACpD,YACC;AAAA,EACD,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc;AACf;AAEA,SAAS9C,GAAMC,GAAeC,GAAaC,GAAqB;AAC/D,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKF,CAAK,CAAC;AAC1C;AAEA,SAAS8C,GAAYC,GAAuC;AAC3D,SACCA,MAAS,qBACTA,MAAS,kBACTA,MAAS,0BACTA,MAAS,uBACTA,MAAS;AAEX;AAEA,SAASC,GACRhD,GACAiD,GACS;AACT,SAAI,OAAOjD,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,KAAKA,KAAS,IAC7DiD,IAEDjD;AACR;AAEA,SAASkD,GAAoBnF,GAA2D;AACvF,SAAO;AAAA,IACN,kBAAkBiF;AAAA,MACjBjF,GAAS;AAAA,MACT0E;AAAA,IAAA;AAAA,IAED,eAAeO;AAAA,MACdjF,GAAS;AAAA,MACT2E;AAAA,IAAA;AAAA,EACD;AAEF;AAEA,SAASS,GAASC,GAAyB;AAC1C,SAAOA,IAAUZ,KAAiBA;AACnC;AAEA,SAASa,GACRC,GACAC,GACmB;AACnB,SAAI,CAACD,KAAU,CAAC,OAAO,SAASC,CAAU,KAAKA,KAAc,IAAU,CAAA,IAChEC,GAAU;AAAA,IAChB,CAACF,EAAO,CAAC,IAAIC,GAAYD,EAAO,CAAC,IAAIC,CAAU;AAAA,IAC/C,CAACD,EAAO,CAAC,IAAIC,GAAYD,EAAO,CAAC,IAAIC,CAAU;AAAA,IAC/C,CAACD,EAAO,CAAC,IAAIC,GAAYD,EAAO,CAAC,IAAIC,CAAU;AAAA,IAC/C,CAACD,EAAO,CAAC,IAAIC,GAAYD,EAAO,CAAC,IAAIC,CAAU;AAAA,EAAA,CAC/C;AACF;AAEA,SAASE,GACRH,GACAI,GACAC,IAAQvB,IACW;AACnB,MAAI,CAACkB,KAAU,CAAC,OAAO,SAASI,CAAM,KAAKA,KAAU,EAAG,QAAO,CAAA;AAE/D,QAAME,IAA2B,CAAA;AACjC,WAAS9B,IAAI,GAAGA,KAAK6B,GAAO7B,KAAK,GAAG;AACnC,UAAM+B,IAAK/B,IAAI6B,IAAS,KAAK,KAAK;AAClC,IAAAC,EAAO,KAAK;AAAA,MACXN,EAAO,CAAC,IAAI,KAAK,IAAIO,CAAC,IAAIH;AAAA,MAC1BJ,EAAO,CAAC,IAAI,KAAK,IAAIO,CAAC,IAAIH;AAAA,IAAA,CAC1B;AAAA,EACF;AAEA,SAAOF,GAAUI,CAAM;AACxB;AAEO,SAASJ,GAAUI,GAA4C;AACrE,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO,CAAA;AAExD,QAAME,IAAMF,EAAO,IAAI,CAAC,CAACG,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAmB,GACrDC,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MAExBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAGvBH;AACR;AAEO,SAASK,GACfC,GACAC,GACmB;AACnB,SAAI,CAACD,KAAS,CAACC,IAAY,CAAA,IAEpBb,GAAU;AAAA,IAChB,CAACY,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IACnB,CAACC,EAAI,CAAC,GAAGD,EAAM,CAAC,CAAC;AAAA,IACjB,CAACC,EAAI,CAAC,GAAGA,EAAI,CAAC,CAAC;AAAA,IACf,CAACD,EAAM,CAAC,GAAGC,EAAI,CAAC,CAAC;AAAA,EAAA,CACjB;AACF;AAEO,SAASC,GACfF,GACAC,GACAV,IAAQvB,IACW;AACnB,MAAI,CAACgC,KAAS,CAACC,UAAY,CAAA;AAE3B,QAAME,KAAWH,EAAM,CAAC,IAAIC,EAAI,CAAC,KAAK,KAChCG,KAAWJ,EAAM,CAAC,IAAIC,EAAI,CAAC,KAAK,KAChCX,IAAS,KAAK,MAAMW,EAAI,CAAC,IAAID,EAAM,CAAC,GAAGC,EAAI,CAAC,IAAID,EAAM,CAAC,CAAC,IAAI;AAClE,MAAIV,IAAS,EAAG,QAAO,CAAA;AAEvB,QAAME,IAA2B,CAAA;AACjC,WAAS9B,IAAI,GAAGA,KAAK6B,GAAO7B,KAAK,GAAG;AACnC,UAAM+B,IAAK/B,IAAI6B,IAAS,KAAK,KAAK;AAClC,IAAAC,EAAO,KAAK;AAAA,MACXW,IAAU,KAAK,IAAIV,CAAC,IAAIH;AAAA,MACxBc,IAAU,KAAK,IAAIX,CAAC,IAAIH;AAAA,IAAA,CACxB;AAAA,EACF;AAEA,SAAOF,GAAUI,CAAM;AACxB;AAEA,SAASa,GAAYb,GAAkC;AACtD,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO;AAExD,MAAIc,IAAM;AACV,WAAS,IAAI,GAAG,IAAId,EAAO,SAAS,GAAG,KAAK,GAAG;AAC9C,UAAM9C,IAAI8C,EAAO,CAAC,GACZ7C,IAAI6C,EAAO,IAAI,CAAC;AACtB,IAAAc,KAAO5D,EAAE,CAAC,IAAIC,EAAE,CAAC,IAAIA,EAAE,CAAC,IAAID,EAAE,CAAC;AAAA,EAChC;AAEA,SAAO,KAAK,IAAI4D,IAAM,GAAG;AAC1B;AAEA,SAASC,GAAcf,GAAsC;AAC5D,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,EAAG,QAAO,CAAC,GAAG,GAAG,GAAG,CAAC;AAErE,MAAIgB,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AAEX,aAAW,CAAChB,GAAGC,CAAC,KAAKJ;AACpB,IAAIG,IAAIa,MAAMA,IAAOb,IACjBA,IAAIe,MAAMA,IAAOf,IACjBC,IAAIa,MAAMA,IAAOb,IACjBA,IAAIe,MAAMA,IAAOf;AAGtB,SAAO,CAACY,GAAMC,GAAMC,GAAMC,CAAI;AAC/B;AAEA,SAASC,GAAepB,GAAmC;AAC1D,SACC,MAAM,QAAQA,CAAM,KACpBA,EAAO,UAAU,KACjBa,GAAYb,CAAM,IAAIvB;AAExB;AAEA,SAAS4C,GACRC,GACAC,GACAC,GACAC,IAAQ,IACRC,IAAO,IACA;AACP,MAAIH,EAAO,WAAW,GAEtB;AAAA,IAAAD,EAAI,UAAA,GACJA,EAAI,OAAOC,EAAO,CAAC,EAAE,CAAC,GAAGA,EAAO,CAAC,EAAE,CAAC,CAAC;AACrC,aAASrD,IAAI,GAAGA,IAAIqD,EAAO,QAAQrD,KAAK;AACvC,MAAAoD,EAAI,OAAOC,EAAOrD,CAAC,EAAE,CAAC,GAAGqD,EAAOrD,CAAC,EAAE,CAAC,CAAC;AAGtC,IAAIuD,KACHH,EAAI,UAAA,GAEDI,KAAQD,MACXH,EAAI,YAAYjD,IAChBiD,EAAI,KAAA,IAGLA,EAAI,cAAcE,EAAY,OAC9BF,EAAI,YAAYE,EAAY,OAC5BF,EAAI,WAAWE,EAAY,UAC3BF,EAAI,UAAUE,EAAY,SAC1BF,EAAI,cAAcE,EAAY,aAC9BF,EAAI,aAAaE,EAAY,YAC7BF,EAAI,gBAAgBE,EAAY,eAChCF,EAAI,gBAAgBE,EAAY,eAChCF,EAAI,YAAYE,EAAY,QAAQ,GACpCF,EAAI,OAAA,GACJA,EAAI,YAAY3C,EAAU,GAC1B2C,EAAI,cAAc,oBAClBA,EAAI,aAAa,GACjBA,EAAI,gBAAgB,GACpBA,EAAI,gBAAgB;AAAA;AACrB;AAEA,SAASK,GACRC,GACoB;AACpB,QAAMC,IAAO,MAAM,QAAQD,GAAO,QAAQ,IACvCA,EAAM,SAAS,OAAO,CAACxF,MAAU,OAAO,SAASA,CAAK,KAAKA,KAAS,CAAC,IACrEuC,IACGpF,IACL,OAAOqI,GAAO,SAAU,YAAY,OAAO,SAASA,EAAM,KAAK,IAC5D,KAAK,IAAI,GAAGA,EAAM,KAAK,IACvB5C,GAA4B,OAC1B8C,IACL,OAAOF,GAAO,cAAe,YAAY,OAAO,SAASA,EAAM,UAAU,IACtE,KAAK,IAAI,GAAGA,EAAM,UAAU,IAC5B5C,GAA4B,YAC1B+C,IACL,OAAOH,GAAO,iBAAkB,YAChC,OAAO,SAASA,EAAM,aAAa,IAChCA,EAAM,gBACN5C,GAA4B,eAC1BgD,IACL,OAAOJ,GAAO,iBAAkB,YAChC,OAAO,SAASA,EAAM,aAAa,IAChCA,EAAM,gBACN5C,GAA4B;AAChC,SAAO;AAAA,IACN,OAAO4C,GAAO,SAAS5C,GAA4B;AAAA,IACnD,OAAAzF;AAAA,IACA,UAAUsI,EAAK,SAASA,IAAOlD;AAAA,IAC/B,UAAUiD,GAAO,YAAY5C,GAA4B;AAAA,IACzD,SAAS4C,GAAO,WAAW5C,GAA4B;AAAA,IACvD,aAAa4C,GAAO,eAAe5C,GAA4B;AAAA,IAC/D,YAAA8C;AAAA,IACA,eAAAC;AAAA,IACA,eAAAC;AAAA,EAAA;AAEF;AAEA,SAASC,GACRC,GACAC,GACoB;AACpB,SAAKA,IACER,GAAmB;AAAA,IACzB,OAAOQ,EAAS,SAASD,EAAK;AAAA,IAC9B,OAAOC,EAAS,SAASD,EAAK;AAAA,IAC9B,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,SAASC,EAAS,WAAWD,EAAK;AAAA,IAClC,aAAaC,EAAS,eAAeD,EAAK;AAAA,IAC1C,YAAYC,EAAS,cAAcD,EAAK;AAAA,IACxC,eAAeC,EAAS,iBAAiBD,EAAK;AAAA,IAC9C,eAAeC,EAAS,iBAAiBD,EAAK;AAAA,EAAA,CAC9C,IAXqBA;AAYvB;AAEA,SAASE,GACRlF,GACAC,GACU;AACV,SAAID,KAAM,QAA2BC,MAAM,QAAQA,MAAM,SACjD,KAED,OAAOD,CAAC,MAAM,OAAOC,CAAC;AAC9B;AAEA,SAASkF,GACRT,GACmB;AACnB,QAAMU,IACL,OAAOV,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAClE,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAC1B3C,GAA2B,UACzBsD,IACL,OAAOX,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAClE,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAC1B3C,GAA2B,UACzBb,IACL,OAAOwD,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAClE,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAC1B3C,GAA2B,UACzBuD,IACL,OAAOZ,GAAO,eAAgB,YAAY,OAAO,SAASA,EAAM,WAAW,IACxE,KAAK,IAAI,GAAGA,EAAM,WAAW,IAC7B3C,GAA2B,aACzBwD,IACL,OAAOb,GAAO,WAAY,YAAY,OAAO,SAASA,EAAM,OAAO,IAChEA,EAAM,UACN3C,GAA2B,SACzByD,IACL,OAAOd,GAAO,gBAAiB,YAC/B,OAAO,SAASA,EAAM,YAAY,IAC/B,KAAK,IAAI,GAAGA,EAAM,YAAY,IAC9B3C,GAA2B;AAC/B,SAAO;AAAA,IACN,YAAY2C,GAAO,cAAc3C,GAA2B;AAAA,IAC5D,UAAUb;AAAA,IACV,YAAYwD,GAAO,cAAc3C,GAA2B;AAAA,IAC5D,WAAW2C,GAAO,aAAa3C,GAA2B;AAAA,IAC1D,iBACC2C,GAAO,mBAAmB3C,GAA2B;AAAA,IACtD,aAAa2C,GAAO,eAAe3C,GAA2B;AAAA,IAC9D,aAAauD;AAAA,IACb,UAAUF;AAAA,IACV,UAAUC;AAAA,IACV,SAASE;AAAA,IACT,cAAcC;AAAA,EAAA;AAEhB;AAEA,SAASC,GACRrB,GACAnB,GACAC,GACA7G,GACAC,GACAsG,GACO;AACP,QAAM8C,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI9C,GAAQvG,IAAQ,KAAKC,IAAS,GAAG,CAAC;AACjE,EAAA8H,EAAI,UAAA,GACJA,EAAI,OAAOnB,IAAIyC,GAAGxC,CAAC,GACnBkB,EAAI,OAAOnB,IAAI5G,IAAQqJ,GAAGxC,CAAC,GAC3BkB,EAAI,iBAAiBnB,IAAI5G,GAAO6G,GAAGD,IAAI5G,GAAO6G,IAAIwC,CAAC,GACnDtB,EAAI,OAAOnB,IAAI5G,GAAO6G,IAAI5G,IAASoJ,CAAC,GACpCtB,EAAI,iBAAiBnB,IAAI5G,GAAO6G,IAAI5G,GAAQ2G,IAAI5G,IAAQqJ,GAAGxC,IAAI5G,CAAM,GACrE8H,EAAI,OAAOnB,IAAIyC,GAAGxC,IAAI5G,CAAM,GAC5B8H,EAAI,iBAAiBnB,GAAGC,IAAI5G,GAAQ2G,GAAGC,IAAI5G,IAASoJ,CAAC,GACrDtB,EAAI,OAAOnB,GAAGC,IAAIwC,CAAC,GACnBtB,EAAI,iBAAiBnB,GAAGC,GAAGD,IAAIyC,GAAGxC,CAAC,GACnCkB,EAAI,UAAA;AACL;AAEA,SAASuB,GAAa7C,GAAiD;AACtE,MAAI,CAACA,EAAO,OAAQ,QAAO;AAE3B,MAAIiB,IAAO;AACX,aAAW6B,KAAS9C;AACnB,IAAI8C,EAAM,CAAC,IAAI7B,MAAMA,IAAO6B,EAAM,CAAC;AAEpC,MAAI,CAAC,OAAO,SAAS7B,CAAI,EAAG,QAAO;AAEnC,MAAID,IAAO,OACPE,IAAO;AACX,aAAW4B,KAAS9C;AACnB,IAAI,KAAK,IAAI8C,EAAM,CAAC,IAAI7B,CAAI,IAAI,QAC5B6B,EAAM,CAAC,IAAI9B,MAAMA,IAAO8B,EAAM,CAAC,IAC/BA,EAAM,CAAC,IAAI5B,MAAMA,IAAO4B,EAAM,CAAC;AAGpC,SAAI,CAAC,OAAO,SAAS9B,CAAI,KAAK,CAAC,OAAO,SAASE,CAAI,IAAU,OACtD,EAAEF,IAAOE,KAAQ,KAAKD,CAAI;AAClC;AAEA,SAAS8B,GACRzB,GACA0B,GACAC,GACAC,GACAC,GACAC,GACO;AACP,QAAMC,IAAQL,EAAK,KAAA;AACnB,MAAI,CAACK,EAAO;AAEZ,EAAA/B,EAAI,KAAA,GACJA,EAAI,OAAO,GAAG8B,EAAW,UAAU,IAAIA,EAAW,QAAQ,MAAMA,EAAW,UAAU,IACrF9B,EAAI,YAAY,UAChBA,EAAI,eAAe;AAGnB,QAAMgC,IADYhC,EAAI,YAAY+B,CAAK,EAAE,QACZD,EAAW,WAAW,GAC7CG,IAAYH,EAAW,WAAWA,EAAW,WAAW,GAExDjD,IAAIhE;AAAA,IACT8G,EAAO,CAAC;AAAA,IACRK,IAAW,MAAM;AAAA,IACjBJ,IAAcI,IAAW,MAAM;AAAA,EAAA,GAE1BlD,IAAIjE;AAAA,IACT8G,EAAO,CAAC,IAAIG,EAAW;AAAA,IACvBG,IAAY,MAAM;AAAA,IAClBJ,IAAeI,IAAY,MAAM;AAAA,EAAA,GAE5BC,IAAOrD,IAAImD,IAAW,KACtBG,IAAMrD,IAAImD,IAAY;AAE5B,EAAAjC,EAAI,YAAY8B,EAAW,iBAC3B9B,EAAI,cAAc8B,EAAW,aAC7B9B,EAAI,YAAY8B,EAAW,aAC3BT;AAAA,IACCrB;AAAA,IACAkC;AAAA,IACAC;AAAA,IACAH;AAAA,IACAC;AAAA,IACAH,EAAW;AAAA,EAAA,GAEZ9B,EAAI,KAAA,GACA8B,EAAW,cAAc,KAC5B9B,EAAI,OAAA,GAGLA,EAAI,YAAY8B,EAAW,WAC3B9B,EAAI,SAAS+B,GAAOlD,GAAGC,IAAI,GAAG,GAC9BkB,EAAI,QAAA;AACL;AAEA,SAASoC,GACRC,GACAC,GACAC,GACiB;AACjB,SAAO,CAAC1H,GAAMwH,EAAM,CAAC,GAAG,GAAGC,CAAU,GAAGzH,GAAMwH,EAAM,CAAC,GAAG,GAAGE,CAAW,CAAC;AACxE;AAEA,SAASC,GAAQ1H,GAAyD;AACzE,MAAI,CAAC,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,EAAG,QAAO;AACtD,QAAM+D,IAAI,OAAO/D,EAAM,CAAC,CAAC,GACnBgE,IAAI,OAAOhE,EAAM,CAAC,CAAC;AACzB,SAAI,CAAC,OAAO,SAAS+D,CAAC,KAAK,CAAC,OAAO,SAASC,CAAC,IAAU,OAChD,CAACD,GAAGC,CAAC;AACb;AAEO,SAAS2D,GAAU;AAAA,EACzB,MAAA5E;AAAA,EACA,YAAAyE;AAAA,EACA,aAAAC;AAAA,EACA,UAAArH;AAAA,EACA,WAAAC;AAAA,EACA,cAAAuH;AAAA,EACA,cAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,SAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,gBAAAC,KAAiB;AAAA,EACjB,kBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,WAAAC;AAAA,EACA,OAAAlD;AACD,GAAuC;AACtC,QAAMmD,IAAYC,EAAiC,IAAI,GACjDC,KAAiBD,EAAO,EAAK,GAC7BE,IAAcF,EAAiB7F,CAAI,GACnCgG,IAAaH,EAAoB;AAAA,IACtC,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ,CAAA;AAAA,IACR,aAAa;AAAA,EAAA,CACb,GAEKI,IAASjB,KAAWhF,MAAS,UAC7BkG,IAAyBC,EAAsB,MAChDjB,KAAoBA,EAAiB,SAAS,IAC1CA,IAEJ,CAACC,KAAqBA,EAAkB,WAAW,IAC/C5F,KAED4F,EAAkB,IAAI,CAACiB,GAAaC,OAAW;AAAA,IACrD,IAAIA;AAAA,IACJ,aAAAD;AAAA,EAAA,EACC,GACA,CAAClB,GAAkBC,CAAiB,CAAC,GAElCmB,IAAsBH;AAAA,IAC3B,MAAM3D,GAAmB4C,CAAiB;AAAA,IAC1C,CAACA,CAAiB;AAAA,EAAA,GAEbmB,IAA2BJ;AAAA,IAChC,MAAMrD,GAAiBwD,GAAqBjB,CAAsB;AAAA,IAClE,CAACiB,GAAqBjB,CAAsB;AAAA,EAAA,GAEvCmB,KAA4BL;AAAA,IACjC,MAAMrD,GAAiBwD,GAAqBhB,CAAuB;AAAA,IACnE,CAACgB,GAAqBhB,CAAuB;AAAA,EAAA,GAGxCmB,KAAqBN;AAAA,IAC1B,MAAMjD,GAAkBuC,EAAgB;AAAA,IACxC,CAACA,EAAgB;AAAA,EAAA,GAEZiB,KAAuBP;AAAA,IAC5B,MAAMhG,GAAoB0E,CAAY;AAAA,IACtC,CAACA,CAAY;AAAA,EAAA,GAGR8B,KAAcR;AAAA,IACnB,OAAO;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,aAAa;AAAA,MACb,eAAeF,IAAS,SAAS;AAAA,MACjC,QAAQA,IAAS,cAAc;AAAA,MAC/B,GAAGxD;AAAA,IAAA;AAAA,IAEJ,CAACwD,GAAQxD,CAAK;AAAA,EAAA,GAGTmE,KAAeC,EAAY,MAAM;AACtC,UAAM7M,IAAS4L,EAAU;AACzB,QAAI,CAAC5L,EAAQ;AAEb,UAAMkC,IAAOlC,EAAO,sBAAA,GACdqC,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9CyK,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM5K,EAAK,QAAQG,CAAG,CAAC,GAC5C0K,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM7K,EAAK,SAASG,CAAG,CAAC;AAEnD,KAAIrC,EAAO,UAAU8M,KAAK9M,EAAO,WAAW+M,OAC3C/M,EAAO,QAAQ8M,GACf9M,EAAO,SAAS+M;AAAA,EAElB,GAAG,CAAA,CAAE,GAECC,IAAsBH;AAAA,IAC3B,CAACzE,MAA+C;AAC/C,YAAM6E,IAAYnC,EAAa;AAC/B,UAAI,CAACmC,KAAa7E,EAAO,WAAW,UAAU,CAAA;AAE9C,YAAMrB,IAAM,IAAI,MAAsBqB,EAAO,MAAM;AACnD,eAASrD,IAAI,GAAGA,IAAIqD,EAAO,QAAQrD,KAAK,GAAG;AAC1C,cAAMyF,IAAQG;AAAA,UACbsC,EAAU,cAAc7E,EAAOrD,CAAC,EAAE,CAAC,GAAGqD,EAAOrD,CAAC,EAAE,CAAC,CAAC;AAAA,QAAA;AAEnD,YAAI,CAACyF,EAAO,QAAO,CAAA;AACnB,QAAAzD,EAAIhC,CAAC,IAAIyF;AAAA,MACV;AACA,aAAOzD;AAAA,IACR;AAAA,IACA,CAAC+D,CAAY;AAAA,EAAA,GAGRoC,IAAuBL;AAAA,IAC5B,CAACM,MAA6B;AAC7B,UAAI,CAAC,OAAO,SAASA,CAAQ,KAAKA,KAAY,EAAG,QAAO;AAGxD,YAAMC,IACL,OAAO/J,KAAa,YAAY,OAAO,SAASA,CAAQ,KAAKA,IAAW,IACrEA,IACA,GACEgK,IACL,OAAO/J,KAAc,YAAY,OAAO,SAASA,CAAS,IACvDA,IACA,GACEgK,IAAcxC,EAAa,SAAS,eAAA,EAAiB,MACrDyC,IACL,OAAOD,KAAgB,YACvB,OAAO,SAASA,CAAW,KAC3BA,IAAc,IACXA,IACA,GACEE,IAAiBH,IAAiB,KAAK,KAAKE,CAAQ,GACpDE,IAAmB,KAAK;AAAA,QAC7B;AAAA,QACArK,GAAoBgK,GAAUC,GAAgBG,CAAc;AAAA,MAAA;AAG7D,aADqBL,IAAWM,IACVF;AAAA,IACvB;AAAA,IACA,CAAClK,GAAUC,GAAWwH,CAAY;AAAA,EAAA,GAG7B4C,IAAmBb;AAAA,IACxB,CAACc,GAA0BpH,MAAoD;AAC9E,UAAI,CAACA,EAAQ,QAAO,CAAA;AAEpB,UAAIF,IAAU;AAkBd,UAjBIsH,MAAc,qBAAqBA,MAAc,yBACpDtH,IACCsH,MAAc,yBACXjI,KACAgH,GAAqB,oBAEzBiB,MAAc,kBACdA,MAAc,uBACdA,MAAc,+BAEdtH,IACCsH,MAAc,4BACX/H,KACA+H,MAAc,sBACbhI,KACA+G,GAAqB,gBAEvB,CAAC,OAAO,SAASrG,CAAO,KAAKA,KAAW,UAAU,CAAA;AAEtD,YAAMuH,IAAUxH,GAASC,CAAO;AAChC,UAAIQ,IAA2B,CAAA;AAC/B,UAAI8G,MAAc,qBAAqBA,MAAc,wBAAwB;AAC5E,cAAMnH,IAAa0G,EAAqB,KAAK,KAAKU,CAAO,IAAI,GAAG;AAChE,QAAA/G,IAASP,GAAuBC,GAAQC,CAAU;AAAA,MACnD,WACCmH,MAAc,kBACdA,MAAc,uBACdA,MAAc,2BACb;AACD,cAAMhH,IAASuG,EAAqB,KAAK,KAAKU,IAAU,KAAK,EAAE,CAAC;AAChE,QAAA/G,IAASH,GAAuBH,GAAQI,CAAM;AAAA,MAC/C;AAEA,aAAKE,EAAO,SACLA,EAAO,IAAI,CAAC8C,MAAUY,GAAWZ,GAAOc,GAAYC,CAAW,CAAC,IAD5C,CAAA;AAAA,IAE5B;AAAA,IACA,CAACwC,GAAsBzC,GAAYC,GAAagC,EAAoB;AAAA,EAAA,GAG/DmB,IAAqBhB,EAAY,MAAwB;AAC9D,UAAMiB,IAAU9B,EAAW;AAC3B,WAAIjG,GAAYC,CAAI,IACZ0H,EAAiB1H,GAAM8H,EAAQ,WAAW,IAE7CA,EAAQ,YAET9H,MAAS,aACL8H,EAAQ,SAEZ9H,MAAS,cACLoB,GAAgB0G,EAAQ,OAAOA,EAAQ,OAAO,IAElD9H,MAAS,aACLuB,GAAauG,EAAQ,OAAOA,EAAQ,OAAO,IAG5C,CAAA,IAZwB,CAAA;AAAA,EAahC,GAAG,CAAC9H,GAAM0H,CAAgB,CAAC,GAErBK,IAAclB,EAAY,MAAM;AACrC,IAAAD,GAAA;AAEA,UAAM5M,IAAS4L,EAAU;AACzB,QAAI,CAAC5L,EAAQ;AAEb,UAAMmI,IAAMnI,EAAO,WAAW,IAAI;AAClC,QAAI,CAACmI,EAAK;AAEV,UAAM9F,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9C0H,IAAc/J,EAAO,QAAQqC,GAC7B2H,IAAehK,EAAO,SAASqC;AAMrC,QALA8F,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAGnI,EAAO,OAAOA,EAAO,MAAM,GAC/CmI,EAAI,aAAa9F,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC,GAGjC6J,EAAuB,SAAS;AACnC,eAASnH,IAAI,GAAGA,IAAImH,EAAuB,QAAQnH,KAAK,GAAG;AAC1D,cAAMiJ,IAAS9B,EAAuBnH,CAAC,GACjCkJ,IAAOD,GAAQ;AACrB,YAAI,CAACC,KAAQA,EAAK,SAAS,EAAG;AAC9B,cAAMC,IAASzH,GAAUwH,CAAI,GACvBE,IAASnB,EAAoBkB,CAAM;AACzC,YAAIC,EAAO,UAAU,GAAG;AACvB,gBAAMC,KAAYJ,EAAO,MAAMjJ,GACzBsD,KAAcY,GAAeuC,IAAgB4C,EAAS,IACzD5B,KACAvD,GAAesC,GAAiB6C,EAAS,IACxC7B,IACAD;AACJ,UAAApE,GAASC,GAAKgG,GAAQ9F,IAAa,IAAM,EAAK;AAAA,QAC/C;AAAA,MACD;AAGD,QAAI4D,GAAQ;AACX,YAAMoC,IAAUR,EAAA;AAChB,UAAIQ,EAAQ,SAAS;AACpB,YAAIrI,MAAS,YAAY;AACxB,gBAAMsI,IAAOtB,EAAoBqB,CAAO;AACxC,UAAIC,EAAK,UAAU,KAClBpG,GAASC,GAAKmG,GAAMhC,GAAqB,IAAO,EAAK,GAElDgC,EAAK,UAAU,KAClBpG;AAAA,YACCC;AAAA,YACA6E,EAAoBvG,GAAU4H,CAAO,CAAC;AAAA,YACtC/B;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,QAGH,OAAO;AACN,gBAAMiC,IAAUvB,EAAoBqB,CAAO;AAC3C,UAAIE,EAAQ,UAAU,KACrBrG,GAASC,GAAKoG,GAASjC,GAAqB,IAAM,EAAI;AAAA,QAExD;AAAA,IAEF;AAGA,QAAIJ,EAAuB,SAAS;AACnC,iBAAW8B,KAAU9B,GAAwB;AAC5C,YAAI,CAAC8B,EAAO,MAAO;AACnB,cAAMC,IAAOD,GAAQ;AACrB,YAAI,CAACC,KAAQA,EAAK,SAAS,EAAG;AAC9B,cAAMC,IAASzH,GAAUwH,CAAI,GACvBO,IAAc9E,GAAawE,CAAM;AACvC,YAAI,CAACM,EAAa;AAClB,cAAMC,IAAe9D;AAAA,UACpBG,EAAa,SAAS,cAAc0D,EAAY,CAAC,GAAGA,EAAY,CAAC,CAAC,KACjE,CAAA;AAAA,QAAC;AAEH,QAAKC,KACL7E;AAAA,UACCzB;AAAA,UACA6F,EAAO;AAAA,UACPS;AAAA,UACA1E;AAAA,UACAC;AAAA,UACAyC;AAAA,QAAA;AAAA,MAEF;AAAA,EAEF,GAAG;AAAA,IACFR;AAAA,IACAjG;AAAA,IACA6H;AAAA,IACAjB;AAAA,IACAI;AAAA,IACAlC;AAAA,IACAoB;AAAA,IACAX;AAAA,IACAC;AAAA,IACAc;AAAA,IACAC;AAAA,IACAC;AAAA,IACAC;AAAA,EAAA,CACA,GAEKiC,IAAc7B,EAAY,MAAM;AACrC,IAAIf,GAAe,YACnBA,GAAe,UAAU,IACzB,sBAAsB,MAAM;AAC3B,MAAAA,GAAe,UAAU,IACzBiC,EAAA;AAAA,IACD,CAAC;AAAA,EACF,GAAG,CAACA,CAAW,CAAC,GAEVY,IAAe9B,EAAY,MAAM;AACtC,UAAMiB,IAAU9B,EAAW,SACrBhM,IAAS4L,EAAU;AAEzB,QACC5L,KACA8N,EAAQ,cAAc,QACtB9N,EAAO,kBAAkB8N,EAAQ,SAAS;AAE1C,UAAI;AACH,QAAA9N,EAAO,sBAAsB8N,EAAQ,SAAS;AAAA,MAC/C,QAAQ;AAAA,MAER;AAGD,IAAAA,EAAQ,YAAY,IACpBA,EAAQ,YAAY,MACpBA,EAAQ,QAAQ,MAChBA,EAAQ,UAAU,MAClBA,EAAQ,SAAS,CAAA,GACjBA,EAAQ,cAAc;AAAA,EACvB,GAAG,CAAA,CAAE,GAECc,IAAU/B;AAAA,IACf,CAACgC,MAAuE;AACvE,YAAM5B,IAAYnC,EAAa;AAC/B,UAAI,CAACmC,KAAaxC,KAAc,KAAKC,KAAe,EAAG,QAAO;AAE9D,YAAMoE,IAAMnE;AAAA,QACXsC,EAAU,cAAc4B,EAAM,SAASA,EAAM,OAAO;AAAA,MAAA;AAErD,aAAKC,IACEvE,GAAWuE,GAAKrE,GAAYC,CAAW,IAD7B;AAAA,IAElB;AAAA,IACA,CAACI,GAAcL,GAAYC,CAAW;AAAA,EAAA,GAGjCqE,IAAgBlC,EAAY,MAAM;AACvC,UAAMiB,IAAU9B,EAAW;AAC3B,QAAI,CAAC8B,EAAQ,WAAW;AACvB,MAAAa,EAAA,GACAD,EAAA;AACA;AAAA,IACD;AAEA,QAAItC,IAAgC,CAAA;AACpC,IAAIpG,MAAS,aACR8H,EAAQ,OAAO,UAAU3I,OAC5BiH,IAAc3F,GAAUqH,EAAQ,MAAM,KAE7B9H,MAAS,cACnBoG,IAAchF,GAAgB0G,EAAQ,OAAOA,EAAQ,OAAO,IAClD9H,MAAS,eACnBoG,IAAc7E,GAAauG,EAAQ,OAAOA,EAAQ,OAAO,KAIxD9H,MAAS,cAAcA,MAAS,eAAeA,MAAS,eACzDiC,GAAemE,CAAW,KAC1BrB,KAEAA,EAAe;AAAA,MACd,MAAA/E;AAAA,MACA,aAAAoG;AAAA,MACA,MAAMxE,GAAcwE,CAAW;AAAA,MAC/B,QAAQ1E,GAAY0E,CAAW;AAAA,IAAA,CAC/B,GAGFuC,EAAA,GACAD,EAAA;AAAA,EACD,GAAG,CAAC1I,GAAM+E,GAAgB4D,GAAcD,CAAW,CAAC,GAE9CM,KAAgBnC;AAAA,IACrB,CAACc,GAA0BpH,MAAiC;AAC3D,YAAM6F,IAAcsB,EAAiBC,GAAWpH,CAAM;AACtD,MAAI,CAAC0B,GAAemE,CAAW,KAAK,CAACrB,KACrCA,EAAe;AAAA,QACd,MAAM4C;AAAA,QACN,aAAAvB;AAAA,QACA,MAAMxE,GAAcwE,CAAW;AAAA,QAC/B,QAAQ1E,GAAY0E,CAAW;AAAA,MAAA,CAC/B;AAAA,IACF;AAAA,IACA,CAACsB,GAAkB3C,CAAc;AAAA,EAAA,GAG5BkE,IAAoBpC;AAAA,IACzB,CAACgC,MAAgD;AAGhD,UAFI,CAAC5C,KACDjG,MAAS,YACT6I,EAAM,WAAW,EAAG;AAExB,YAAMK,IAAQN,EAAQC,CAAK;AAC3B,UAAI,CAACK,EAAO;AAKZ,UAHAL,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEF9I,GAAYC,CAAI,GAAG;AACtB,cAAM8H,IAAU9B,EAAW;AAC3B8B,QAAAA,EAAQ,cAAcoB,GACtBF,GAAchJ,GAAMkJ,CAAK,GACzBR,EAAA;AACA;AAAA,MACD;AAEA,YAAM1O,IAAS4L,EAAU;AACzB,MAAI5L,KACHA,EAAO,kBAAkB6O,EAAM,SAAS;AAGzC,YAAMf,IAAU9B,EAAW;AAC3B,MAAA8B,EAAQ,YAAY,IACpBA,EAAQ,YAAYe,EAAM,WAC1Bf,EAAQ,QAAQoB,GAChBpB,EAAQ,UAAUoB,GAClBpB,EAAQ,SAAS9H,MAAS,aAAa,CAACkJ,CAAK,IAAI,CAAA,GACjDR,EAAA;AAAA,IACD;AAAA,IACA,CAACzC,GAAQjG,GAAM4I,GAASI,IAAeN,CAAW;AAAA,EAAA,GAG7CS,IAAoBtC;AAAA,IACzB,CAACgC,MAAgD;AAEhD,UADI,CAAC5C,KACDjG,MAAS,SAAU;AAEvB,YAAMkJ,IAAQN,EAAQC,CAAK;AAC3B,UAAI,CAACK,EAAO;AAEZ,UAAInJ,GAAYC,CAAI,GAAG;AACtB,cAAM8H,IAAU9B,EAAW;AAC3B8B,QAAAA,EAAQ,cAAcoB,GACtBL,EAAM,eAAA,GACNA,EAAM,gBAAA,GACNH,EAAA;AACA;AAAA,MACD;AAEA,YAAMZ,IAAU9B,EAAW;AAC3B,UAAI,GAAC8B,EAAQ,aAAaA,EAAQ,cAAce,EAAM,YAMtD;AAAA,YAHAA,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEF7I,MAAS,YAAY;AACxB,gBAAMiH,IAAYnC,EAAa,SACzBrI,IAAO,KAAK,IAAI,MAAMwK,GAAW,eAAA,EAAiB,QAAQ,CAAC,GAC3DmC,IAAehK,KAAuB3C,GACtC4M,IAAgBD,IAAeA,GAC/BE,IAAOxB,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC;AAErD,cAAI,CAACwB;AACJ,YAAAxB,EAAQ,OAAO,KAAKoB,CAAK;AAAA,eACnB;AACN,kBAAMK,IAAKL,EAAM,CAAC,IAAII,EAAK,CAAC,GACtBE,IAAKN,EAAM,CAAC,IAAII,EAAK,CAAC;AAC5B,YAAIC,IAAKA,IAAKC,IAAKA,KAAMH,KACxBvB,EAAQ,OAAO,KAAKoB,CAAK;AAAA,UAE3B;AAAA,QACD;AACC,UAAApB,EAAQ,UAAUoB;AAGnB,QAAAR,EAAA;AAAA;AAAA,IACD;AAAA,IACA,CAACzC,GAAQjG,GAAM4I,GAASF,GAAa5D,CAAY;AAAA,EAAA,GAG5C2E,IAAkB5C;AAAA,IACvB,CAACgC,MAAgD;AAChD,YAAMf,IAAU9B,EAAW;AAC3B,UAAI,CAAC8B,EAAQ,aAAaA,EAAQ,cAAce,EAAM,UAAW;AAEjE,MAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AACN,YAAM7O,IAAS4L,EAAU;AACzB,UAAI5L,KAAUA,EAAO,kBAAkB6O,EAAM,SAAS;AACrD,YAAI;AACH,UAAA7O,EAAO,sBAAsB6O,EAAM,SAAS;AAAA,QAC7C,QAAQ;AAAA,QAER;AAGD,MAAAE,EAAA;AAAA,IACD;AAAA,IACA,CAACA,CAAa;AAAA,EAAA,GAGTW,IAAqB7C,EAAY,MAAM;AAC5C,QAAI,CAAC9G,GAAYC,CAAI,EAAG;AACxB,UAAM8H,IAAU9B,EAAW;AAC3B,IAAK8B,EAAQ,gBACbA,EAAQ,cAAc,MACtBY,EAAA;AAAA,EACD,GAAG,CAAC1I,GAAM0I,CAAW,CAAC;AAEtB,SAAAiB,EAAU,MAAM;AACf,IAAA/C,GAAA,GACA8B,EAAA;AAEA,UAAM1O,IAAS4L,EAAU;AACzB,QAAI,CAAC5L,EAAQ;AAEb,UAAM4P,IAAW,IAAI,eAAe,MAAM;AACzC,MAAAhD,GAAA,GACA8B,EAAA;AAAA,IACD,CAAC;AACD,WAAAkB,EAAS,QAAQ5P,CAAM,GAEhB,MAAM;AACZ,MAAA4P,EAAS,WAAA;AAAA,IACV;AAAA,EACD,GAAG,CAAChD,IAAc8B,CAAW,CAAC,GAE9BiB,EAAU,MAAM;AACf,IAAK1D,KACJ0C,EAAA,GAEDD,EAAA;AAAA,EACD,GAAG,CAACzC,GAAQyC,GAAaC,CAAY,CAAC,GAEtCgB,EAAU,MAAM;AACf,IAAI5D,EAAY,YAAY/F,MAG5B+F,EAAY,UAAU/F,GACtB2I,EAAA,GACAD,EAAA;AAAA,EACD,GAAG,CAAC1I,GAAM2I,GAAcD,CAAW,CAAC,GAEpCiB,EAAU,MAAM;AACf,IAAAjB,EAAA;AAAA,EACD,GAAG,CAACzD,GAAiBiB,GAAwBwC,CAAW,CAAC,GAEzDiB,EAAU,MAAM;AACf,QAAKjE;AACL,aAAAA,EAAc,UAAUgD,GACjB,MAAM;AACZ,QAAIhD,EAAc,YAAYgD,MAC7BhD,EAAc,UAAU;AAAA,MAE1B;AAAA,EACD,GAAG,CAACA,GAAegD,CAAW,CAAC,GAE/BiB,EAAU,MAAM;AACf,QAAI,CAAC1D,EAAQ;AAEb,UAAM4D,IAAY,CAAChB,MAA+B;AACjD,MAAIA,EAAM,QAAQ,aAClBF,EAAA,GACAD,EAAA;AAAA,IACD;AAEA,kBAAO,iBAAiB,WAAWmB,CAAS,GACrC,MAAM;AACZ,aAAO,oBAAoB,WAAWA,CAAS;AAAA,IAChD;AAAA,EACD,GAAG,CAAC5D,GAAQ0C,GAAcD,CAAW,CAAC,GAGrC,gBAAAoB;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,KAAKlE;AAAA,MACL,WAAAD;AAAA,MACA,OAAOgB;AAAA,MACP,eAAesC;AAAA,MACf,eAAeE;AAAA,MACf,aAAaM;AAAA,MACb,iBAAiBA;AAAA,MACjB,gBAAgBC;AAAA,MAChB,eAAe,CAACb,MAAU;AACzB,QAAI5C,OAAc,eAAA;AAAA,MACnB;AAAA,MACA,SAAS,CAAC4C,MAAU;AACnB,QAAI5C,OAAc,eAAA;AAAA,MACnB;AAAA,IAAA;AAAA,EAAA;AAGH;AClqCO,SAAS8D,GACfjB,GACAkB,GACiB;AACjB,QAAMC,IAAMnB,GAAK,WAAW,CAAA,GAEtB1O,IAAQ,OAAO6P,EAAI,SAASnB,GAAK,SAAS,CAAC,GAC3CzO,IAAS,OAAO4P,EAAI,UAAUnB,GAAK,UAAU,CAAC,GAC9CoB,IAAW,OAAOD,EAAI,YAAYnB,GAAK,YAAY,CAAC,GACpDqB,IAAc,OAAOF,EAAI,QAAQnB,GAAK,QAAQ,CAAC,GAC/CsB,IAAW,OAAOH,EAAI,QAAQnB,GAAK,QAAQ,EAAE,GAC7CtL,IAAM,OAAOyM,EAAI,OAAOnB,GAAK,OAAO,CAAC;AAE3C,MAAI,CAAC1O,KAAS,CAACC,KAAU,CAAC6P,KAAY,CAACE;AACtC,UAAM,IAAI;AAAA,MACT;AAAA,IAAA;AAIF,QAAM3L,IAAmB,MAAM,QAAQqK,GAAK,KAAK,IAC9CA,EAAI,MAAM,IAAI,CAAClK,OAAe;AAAA,IAC9B,QAAQ,OAAOA,GAAM,UAAU,EAAE;AAAA,IACjC,UAAU,OAAOA,GAAM,YAAY,EAAE;AAAA,IACrC,WAAW,OAAOA,GAAM,aAAa,EAAE;AAAA,EAAA,EACtC,IACD,CAAA;AAEH,SAAO;AAAA,IACN,IAAIkK,GAAK,OAAO;AAAA,IAChB,MAAMA,GAAK,QAAQ;AAAA,IACnB,OAAA1O;AAAA,IACA,QAAAC;AAAA,IACA,KAAK,OAAO,SAASmD,CAAG,KAAKA,IAAM,IAAIA,IAAM;AAAA,IAC7C,UAAA0M;AAAA,IACA,aAAa,OAAO,SAASC,CAAW,IACrC,KAAK,IAAI,GAAG,KAAK,MAAMA,CAAW,CAAC,IACnC;AAAA,IACH,UAAAC;AAAA,IACA,aAAAJ;AAAA,IACA,OAAAvL;AAAA,EAAA;AAEF;AAEO,SAAS4L,GACflR,GACAmR,GACAtJ,GACAC,GACS;AACT,QAAMsJ,IAAiBpR,EAAO,SAAS,WAAW,GAAG,IAClDA,EAAO,WACP,IAAIA,EAAO,QAAQ;AACtB,SAAO,GAAGA,EAAO,WAAW,GAAGoR,CAAc,IAAID,CAAI,IAAIrJ,CAAC,IAAID,CAAC;AAChE;ACDA,MAAMwJ,KAAmD;AAAA,EACxD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,mBAAmB;AACpB;AAEA,SAASC,GACRxN,GACAiD,GACAhD,IAAM,GACG;AACT,SAAI,OAAOD,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAUiD,IAC1D,KAAK,IAAIhD,GAAKD,CAAK;AAC3B;AAEA,SAASyN,GAAeC,GAAuD;AAC9E,SACC,MAAM,QAAQA,CAAM,KACpBA,EAAO,WAAW,KAClB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC;AAE3B;AAEO,SAASC,GAAY;AAAA,EAC3B,QAAAzR;AAAA,EACA,cAAA2L;AAAA,EACA,WAAA+F,IAAY;AAAA,EACZ,SAAA7P;AAAA,EACA,eAAA0K;AAAA,EACA,WAAAC;AAAA,EACA,OAAAlD;AACD,GAAyC;AACxC,QAAMmD,IAAYC,EAAiC,IAAI,GACjDiF,IAAejF,EAAiC,IAAI,GACpDkF,IAAgBlF,EAAsB,IAAI,GAC1CmF,IAAcnF,EAAsD;AAAA,IACzE,QAAQ;AAAA,IACR,WAAW;AAAA,EAAA,CACX,GACKoF,IAASpF,EAAsB,IAAI,GACnCC,IAAiBD,EAAO,EAAK,GAE7BzL,IAAQqQ;AAAA,IACbzP,GAAS;AAAA,IACTwP,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKnQ,IAASoQ;AAAA,IACdzP,GAAS;AAAA,IACTwP,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKU,IAAST;AAAA,IACdzP,GAAS;AAAA,IACTwP,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKW,KAAeV;AAAA,IACpBzP,GAAS;AAAA,IACTwP,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKY,KAAcX;AAAA,IACnBzP,GAAS;AAAA,IACTwP,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKa,IAAoB,KAAK;AAAA,IAC9B;AAAA,IACA,KAAK;AAAA,MACJZ;AAAA,QACCzP,GAAS;AAAA,QACTwP,GAA6B;AAAA,QAC7B;AAAA,MAAA;AAAA,IACD;AAAA,EACD,GAGKc,KACLtQ,GAAS,mBAAmBwP,GAA6B,iBACpDe,IACLvQ,GAAS,eAAewP,GAA6B,aAChDgB,IACLxQ,GAAS,uBACTwP,GAA6B,qBACxBiB,KACLzQ,GAAS,qBACTwP,GAA6B,mBACxBkB,IACL1Q,GAAS,eAAewP,GAA6B,aAChDmB,IACL3Q,GAAS,iBAAiBwP,GAA6B,eAClDoB,IACL5Q,GAAS,YAAYwP,GAA6B,UAE7C7D,IAAcR,EAAuB,MAAM;AAChD,UAAM0F,IAAqB,CAAA;AAC3B,WAAID,MAAa,cAAcA,MAAa,kBAAmB,OAAOV,MAC7D,QAAQA,GACbU,MAAa,cAAcA,MAAa,gBAAiB,MAAMV,MAC1D,SAASA,GAEX;AAAA,MACN,UAAU;AAAA,MACV,GAAGW;AAAA,MACH,OAAAzR;AAAA,MACA,QAAAC;AAAA,MACA,cAAA8Q;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAeO,IAAc,SAAS;AAAA,MACtC,aAAa;AAAA,MACb,WAAW;AAAA,MACX,GAAGjJ;AAAA,IAAA;AAAA,EAEL,GAAG,CAACyI,GAAQU,GAAUxR,GAAOC,GAAQ8Q,IAAcO,GAAajJ,CAAK,CAAC,GAEhEqJ,IAAOjF,EAAY,MAAM;AAC9B,UAAM7M,IAAS4L,EAAU;AACzB,QAAI,CAAC5L,EAAQ;AAEb,UAAMmI,IAAMnI,EAAO,WAAW,IAAI;AAClC,QAAI,CAACmI,EAAK;AAEV,UAAM4J,IAAO3R,GACP4R,IAAO3R,GACPgC,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9C4P,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO1P,CAAG,CAAC,GAC3C6P,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO3P,CAAG,CAAC;AACjD,KAAIrC,EAAO,UAAUiS,KAAUjS,EAAO,WAAWkS,OAChDlS,EAAO,QAAQiS,GACfjS,EAAO,SAASkS,IAGjB/J,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAGnI,EAAO,OAAOA,EAAO,MAAM,GAC/CmI,EAAI,aAAa9F,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC,GAErC8F,EAAI,YAAYmJ,IAChBnJ,EAAI,SAAS,GAAG,GAAG4J,GAAMC,CAAI;AAE7B,UAAM3D,IAAUyC,EAAa;AAC7B,IAAIzC,KACHlG,EAAI,UAAUkG,GAAS,GAAG,GAAG0D,GAAMC,CAAI,GAGxC7J,EAAI,cAAcoJ,GAClBpJ,EAAI,YAAYiJ,IAChBjJ,EAAI;AAAA,MACHiJ,KAAc;AAAA,MACdA,KAAc;AAAA,MACdW,IAAOX;AAAA,MACPY,IAAOZ;AAAA,IAAA;AAIR,UAAMT,KADY7F,EAAa,SACL,gBAAA,GACpBqH,IAAazB,GAAeC,EAAM,IACrCA,KACAD,GAAeK,EAAc,OAAO,IACnCA,EAAc,UACd;AACJ,QAAI,CAACoB,EAAY;AACjB,IAAApB,EAAc,UAAUoB;AAExB,UAAM1R,IAAKsR,IAAO,KAAK,IAAI,GAAG5S,EAAO,KAAK,GACpCuB,IAAKsR,IAAO,KAAK,IAAI,GAAG7S,EAAO,MAAM,GAErCkL,IAAOrH,EAAMmP,EAAW,CAAC,IAAI1R,GAAI,GAAGsR,CAAI,GACxCzH,IAAMtH,EAAMmP,EAAW,CAAC,IAAIzR,GAAI,GAAGsR,CAAI,GACvCI,IAAQpP,EAAMmP,EAAW,CAAC,IAAI1R,GAAI,GAAGsR,CAAI,GACzCM,IAASrP,EAAMmP,EAAW,CAAC,IAAIzR,GAAI,GAAGsR,CAAI,GAC1CM,IAAQ,KAAK,IAAI,GAAGF,IAAQ/H,CAAI,GAChCkI,IAAQ,KAAK,IAAI,GAAGF,IAAS/H,CAAG;AAEtC,IAAAnC,EAAI,YAAYsJ,IAChBtJ,EAAI,SAASkC,GAAMC,GAAKgI,GAAOC,CAAK,GAEpCpK,EAAI,cAAcqJ,GAClBrJ,EAAI,YAAY,KAChBA,EAAI;AAAA,MACHkC,IAAO;AAAA,MACPC,IAAM;AAAA,MACN,KAAK,IAAI,GAAGgI,IAAQ,CAAC;AAAA,MACrB,KAAK,IAAI,GAAGC,IAAQ,CAAC;AAAA,IAAA;AAAA,EAEvB,GAAG;AAAA,IACFnS;AAAA,IACAC;AAAA,IACAiR;AAAA,IACAC;AAAA,IACAH;AAAA,IACAtG;AAAA,IACA3L,EAAO;AAAA,IACPA,EAAO;AAAA,IACPsS;AAAA,IACAD;AAAA,EAAA,CACA,GAEK9C,IAAc7B,EAAY,MAAM;AACrC,IAAIf,EAAe,YACnBA,EAAe,UAAU,IACzBmF,EAAO,UAAU,sBAAsB,MAAM;AAC5C,MAAAnF,EAAe,UAAU,IACzBmF,EAAO,UAAU,MACjBa,EAAA;AAAA,IACD,CAAC;AAAA,EACF,GAAG,CAACA,CAAI,CAAC,GAEHU,KAAoB3F;AAAA,IACzB,CAAC4F,GAAiBC,MAA6C;AAC9D,YAAM1S,IAAS4L,EAAU;AACzB,UAAI,CAAC5L,EAAQ,QAAO;AAEpB,YAAMkC,IAAOlC,EAAO,sBAAA;AACpB,UAAI,CAACkC,EAAK,SAAS,CAACA,EAAK,OAAQ,QAAO;AAExC,YAAMyQ,IAAK3P,GAAOyP,IAAUvQ,EAAK,QAAQA,EAAK,OAAO,GAAG,CAAC,GACnD0Q,IAAK5P,GAAO0P,IAAUxQ,EAAK,OAAOA,EAAK,QAAQ,GAAG,CAAC;AACzD,aAAO,CAACyQ,IAAKxT,EAAO,OAAOyT,IAAKzT,EAAO,MAAM;AAAA,IAC9C;AAAA,IACA,CAACA,EAAO,OAAOA,EAAO,MAAM;AAAA,EAAA,GAGvB0T,KAAahG;AAAA,IAClB,CAACiG,GAAgBC,MAAmB;AACnC,YAAM9F,IAAYnC,EAAa;AAC/B,UAAI,CAACmC,EAAW;AAEhB,YAAM0D,IAAS1D,EAAU,gBAAA,GACnBkF,IAAazB,GAAeC,CAAM,IACrCA,IACAD,GAAeK,EAAc,OAAO,IACnCA,EAAc,UACd;AACJ,UAAI,CAACoB,EAAY;AAEjB,YAAMa,IAAW,KAAK,IAAI,MAAMb,EAAW,CAAC,IAAIA,EAAW,CAAC,CAAC,GACvDc,IAAW,KAAK,IAAI,MAAMd,EAAW,CAAC,IAAIA,EAAW,CAAC,CAAC;AAE7D,MAAAlF,EAAU,aAAa;AAAA,QACtB,SAAS6F,IAASE,IAAW;AAAA,QAC7B,SAASD,IAASE,IAAW;AAAA,MAAA,CAC7B,GACDvE,EAAA;AAAA,IACD;AAAA,IACA,CAAC5D,GAAc4D,CAAW;AAAA,EAAA,GAGrBO,KAAoBpC;AAAA,IACzB,CAACgC,MAAgD;AAEhD,UADI,CAAC6C,KACD7C,EAAM,WAAW,EAAG;AAExB,YAAM7O,IAAS4L,EAAU;AACzB,UAAI,CAAC5L,EAAQ;AAEb,YAAMkP,IAAQsD,GAAkB3D,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKK,MAELL,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEN7O,EAAO,kBAAkB6O,EAAM,SAAS,GACxCmC,EAAY,UAAU,EAAE,QAAQ,IAAM,WAAWnC,EAAM,UAAA,GACvDgE,GAAW3D,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IAC9B;AAAA,IACA,CAACwC,GAAac,IAAmBK,EAAU;AAAA,EAAA,GAGtC1D,KAAoBtC;AAAA,IACzB,CAACgC,MAAgD;AAChD,YAAMqE,IAAOlC,EAAY;AACzB,UAAI,CAACkC,EAAK,UAAUA,EAAK,cAAcrE,EAAM,UAAW;AAExD,YAAMK,IAAQsD,GAAkB3D,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKK,MAELL,EAAM,eAAA,GACNA,EAAM,gBAAA,GACNgE,GAAW3D,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IAC9B;AAAA,IACA,CAACsD,IAAmBK,EAAU;AAAA,EAAA,GAGzBpD,KAAkB5C;AAAA,IACvB,CAACgC,MAAgD;AAChD,YAAMqE,IAAOlC,EAAY;AACzB,UAAI,CAACkC,EAAK,UAAUA,EAAK,cAAcrE,EAAM,UAAW;AAExD,YAAM7O,IAAS4L,EAAU;AACzB,UAAI5L,KAAUA,EAAO,kBAAkB6O,EAAM,SAAS;AACrD,YAAI;AACH,UAAA7O,EAAO,sBAAsB6O,EAAM,SAAS;AAAA,QAC7C,QAAQ;AAAA,QAER;AAGD,MAAAmC,EAAY,UAAU,EAAE,QAAQ,IAAO,WAAW,KAAA,GAClDtC,EAAA;AAAA,IACD;AAAA,IACA,CAACA,CAAW;AAAA,EAAA;AAGb,SAAAiB,EAAU,MAAM;AACf,QAAIwD,IAAY;AAChB,IAAArC,EAAa,UAAU,MACvBpC,EAAA;AAEA,UAAM4B,IAAO,GACP8C,IAAa,MAAMjU,EAAO,cAAcmR,IACxC+C,IAAa,KAAK,KAAKlU,EAAO,QAAQiU,CAAU,GAChDE,IAAc,KAAK,KAAKnU,EAAO,SAASiU,CAAU,GAClDG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAalU,EAAO,QAAQ,CAAC,GAC5DqU,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAcnU,EAAO,QAAQ,CAAC,GAC7DsU,IAAYF,IAASC;AAE3B,QAAI,CAAC7B,KAAiB8B,IAAYpC;AACjC;AAGD,UAAMhD,IAAU,SAAS,cAAc,QAAQ;AAC/C,IAAAA,EAAQ,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAMjO,CAAK,CAAC,GAC7CiO,EAAQ,SAAS,KAAK,IAAI,GAAG,KAAK,MAAMhO,CAAM,CAAC;AAC/C,UAAM8H,KAAMkG,EAAQ,WAAW,IAAI;AACnC,QAAI,CAAClG;AACJ;AAGD,IAAAA,GAAI,YAAYmJ,IAChBnJ,GAAI,SAAS,GAAG,GAAGkG,EAAQ,OAAOA,EAAQ,MAAM;AAEhD,UAAMqF,IAGD,CAAA;AAEL,aAASzM,IAAI,GAAGA,IAAIuM,GAAQvM,KAAK;AAChC,eAASD,IAAI,GAAGA,IAAIuM,GAAQvM,KAAK,GAAG;AACnC,cAAMqD,IAAOrD,IAAI7H,EAAO,WAAWiU,GAC7B9I,IAAMrD,IAAI9H,EAAO,WAAWiU,GAC5BhB,IACL,KAAK,KAAKpL,IAAI,KAAK7H,EAAO,UAAUkU,CAAU,IAAID,GAC7Cf,IACL,KAAK,KAAKpL,IAAI,KAAK9H,EAAO,UAAUmU,CAAW,IAAIF;AACpD,QAAAM,EAAS,KAAK;AAAA,UACb,KAAKrD,GAAUlR,GAAQmR,GAAMtJ,GAAGC,CAAC;AAAA,UACjC,QAAQ,CAACoD,GAAMC,GAAK8H,GAAOC,CAAM;AAAA,QAAA,CACjC;AAAA,MACF;AAGD,WAAK,QAAQ;AAAA,MACZqB,EAAS,IAAI,OAAO/R,MAAS;AAC5B,cAAMgS,IAAgB,CAAC,CAAC9C,GAClBhP,IAAW,MAAM,MAAMF,EAAK,KAAK;AAAA,UACtC,SAASgS,IAAgB,EAAE,eAAe9C,MAAc;AAAA,QAAA,CACxD;AACD,YAAI,CAAChP,EAAS;AACb,gBAAM,IAAI,MAAM,QAAQA,EAAS,MAAM,EAAE;AAE1C,cAAME,IAAS,MAAM,kBAAkB,MAAMF,EAAS,MAAM;AAC5D,eAAO,EAAE,MAAAF,GAAM,QAAAI,EAAA;AAAA,MAChB,CAAC;AAAA,IAAA,EACA,KAAK,CAAC6R,MAAY;AACnB,UAAIT,GAAW;AACd,mBAAWU,KAAUD;AACpB,UAAIC,EAAO,WAAW,eACrBA,EAAO,MAAM,OAAO,MAAA;AAGtB;AAAA,MACD;AAEA,YAAMpT,IAAK4N,EAAQ,QAAQ,KAAK,IAAI,GAAGlP,EAAO,KAAK,GAC7CuB,IAAK2N,EAAQ,SAAS,KAAK,IAAI,GAAGlP,EAAO,MAAM;AACrD,iBAAW0U,KAAUD,GAAS;AAC7B,YAAIC,EAAO,WAAW,YAAa;AACnC,cAAM;AAAA,UACL,MAAM,EAAE,QAAAlD,EAAA;AAAA,UACR,QAAA5O;AAAA,QAAA,IACG8R,EAAO,OACLtE,IAAKoB,EAAO,CAAC,IAAIlQ,GACjB+O,IAAKmB,EAAO,CAAC,IAAIjQ,GACjBoT,IAAK,KAAK,IAAI,IAAInD,EAAO,CAAC,IAAIA,EAAO,CAAC,KAAKlQ,CAAE,GAC7CsT,IAAK,KAAK,IAAI,IAAIpD,EAAO,CAAC,IAAIA,EAAO,CAAC,KAAKjQ,CAAE;AACnD,QAAAyH,GAAI,UAAUpG,GAAQwN,GAAIC,GAAIsE,GAAIC,CAAE,GACpChS,EAAO,MAAA;AAAA,MACR;AAEA,MAAA+O,EAAa,UAAUzC,GACvBK,EAAA;AAAA,IACD,CAAC,GAEM,MAAM;AACZ,MAAAyE,IAAY;AAAA,IACb;AAAA,EACD,GAAG;AAAA,IACFhU;AAAA,IACA0R;AAAA,IACAzQ;AAAA,IACAC;AAAA,IACAiR;AAAA,IACAK;AAAA,IACAN;AAAA,IACA3C;AAAA,EAAA,CACA,GAEDiB,EAAU,MAAM;AACf,IAAAjB,EAAA;AAAA,EACD,GAAG,CAACA,CAAW,CAAC,GAEhBiB,EAAU,MAAM;AACf,QAAKjE;AACL,aAAAA,EAAc,UAAUgD,GACjB,MAAM;AACZ,QAAIhD,EAAc,YAAYgD,MAC7BhD,EAAc,UAAU;AAAA,MAE1B;AAAA,EACD,GAAG,CAACA,GAAegD,CAAW,CAAC,GAE/BiB;AAAA,IACC,MAAM,MAAM;AACX,MAAAqB,EAAY,UAAU,EAAE,QAAQ,IAAO,WAAW,KAAA,GAC9CC,EAAO,YAAY,SACtB,qBAAqBA,EAAO,OAAO,GACnCA,EAAO,UAAU,OAElBnF,EAAe,UAAU;AAAA,IAC1B;AAAA,IACA,CAAA;AAAA,EAAC,GAID,gBAAAgE;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,KAAKlE;AAAA,MACL,WAAAD;AAAA,MACA,OAAOgB;AAAA,MACP,eAAesC;AAAA,MACf,eAAeE;AAAA,MACf,aAAaM;AAAA,MACb,iBAAiBA;AAAA,MACjB,eAAe,CAACZ,MAAU;AACzB,QAAAA,EAAM,eAAA;AAAA,MACP;AAAA,MACA,SAAS,CAACA,MAAU;AACnB,QAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AAAA,MACP;AAAA,IAAA;AAAA,EAAA;AAGH;AC3fO,SAASmF,GAAiB;AAAA,EAChC,YAAAvJ;AAAA,EACA,aAAAC;AAAA,EACA,OAAAlJ;AAAA,EACA,WAAAI;AAAA,EACA,WAAA+J;AAAA,EACA,OAAAlD;AACD,GAA8C;AAC7C,QAAMmD,IAAYC,EAAiC,IAAI,GACjDoI,IAAcpI,EAA8B,IAAI,GAChDc,IAAcR;AAAA,IACnB,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,SAAS,SAAS,GAAG1D;IAC7D,CAACA,CAAK;AAAA,EAAA;AAGP,SAAAkH,EAAU,MAAM;AACf,UAAM3P,IAAS4L,EAAU;AACzB,QAAI,CAAC5L;AACJ;AAGD,UAAMkU,IAAW,IAAInT,GAAe;AAAA,MACnC,QAAAf;AAAA,MACA,YAAAyK;AAAA,MACA,aAAAC;AAAA,MACA,kBAAkB9I;AAAA,IAAA,CAClB;AAED,WAAAqS,EAAY,UAAUC,GACjBA,EAAS,SAAS1S,CAAK,GAErB,MAAM;AACZ,MAAA0S,EAAS,QAAA,GACTD,EAAY,UAAU;AAAA,IACvB;AAAA,EACD,GAAG,CAACxJ,GAAYC,CAAW,CAAC,GAE5BiF,EAAU,MAAM;AACf,UAAMuE,IAAWD,EAAY;AAC7B,IAAKC,KAIAA,EAAS,SAAS1S,CAAK;AAAA,EAC7B,GAAG,CAACA,CAAK,CAAC,GAEVmO,EAAU,MAAM;AACf,UAAMuE,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAACtS,KAIlBsS,EAAS,aAAatS,CAAS;AAAA,EAChC,GAAG,CAACA,CAAS,CAAC,sBAEN,UAAA,EAAO,KAAKgK,GAAW,WAAAD,GAAsB,OAAOgB,GAAa;AAC1E;ACzDA,SAASlG,GAAUI,GAAgC;AAClD,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO,CAAA;AACxD,QAAME,IAAMF,EAAO,IAAI,CAAC,CAACG,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAkB,GACpDC,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MACxBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAEvBH;AACR;AAEA,SAASoN,GAAgBC,GAA2C;AACnE,QAAMC,IAA8B,CAAA;AACpC,aAAWC,KAAQF,KAAY,IAAI;AAClC,UAAMnG,IAAOxH,GAAU6N,CAAI;AAC3B,QAAIrG,EAAK,SAAS,EAAG;AACrB,QAAIpG,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAW,CAAChB,GAAGC,CAAC,KAAKgH;AACpB,MAAIjH,IAAIa,MAAMA,IAAOb,IACjBA,IAAIe,MAAMA,IAAOf,IACjBC,IAAIa,MAAMA,IAAOb,IACjBA,IAAIe,MAAMA,IAAOf;AAEtB,IAAI,CAAC,OAAO,SAASY,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KACnDuM,EAAS,KAAK,EAAE,MAAApG,GAAM,MAAApG,GAAM,MAAAC,GAAM,MAAAC,GAAM,MAAAC,GAAM;AAAA,EAC/C;AACA,SAAOqM;AACR;AAEA,SAASE,GAAavN,GAAWC,GAAWgH,GAA2B;AACtE,MAAIuG,IAAS;AACb,WAASzP,IAAI,GAAG0P,IAAIxG,EAAK,SAAS,GAAGlJ,IAAIkJ,EAAK,QAAQwG,IAAI1P,GAAGA,KAAK,GAAG;AACpE,UAAM2P,IAAKzG,EAAKlJ,CAAC,EAAE,CAAC,GACd4P,IAAK1G,EAAKlJ,CAAC,EAAE,CAAC,GACd6P,IAAK3G,EAAKwG,CAAC,EAAE,CAAC,GACdI,IAAK5G,EAAKwG,CAAC,EAAE,CAAC;AAIpB,IAFCE,IAAK1N,KAAM4N,IAAK5N,KAChBD,KAAM4N,IAAKF,MAAOzN,IAAI0N,MAASE,IAAKF,KAAO,OAAO,WAAWD,UACtC,CAACF;AAAA,EAC1B;AACA,SAAOA;AACR;AAEA,SAASM,GACR9N,GACAC,GACAmN,GACU;AACV,aAAWE,KAAQF;AAClB,QAAI,EAAApN,IAAIsN,EAAK,QAAQtN,IAAIsN,EAAK,QAAQrN,IAAIqN,EAAK,QAAQrN,IAAIqN,EAAK,SAG5DC,GAAavN,GAAGC,GAAGqN,EAAK,IAAI;AAC/B,aAAO;AAGT,SAAO;AACR;AAEO,SAASS,GACfC,GACAZ,GACsB;AACtB,MAAI,CAACY,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACxE,WAAO;AAGR,QAAMX,IAAWF,GAAgBC,KAAY,EAAE;AAC/C,MAAIC,EAAS,WAAW;AACvB,WAAO;AAAA,MACN,OAAO;AAAA,MACP,WAAW,IAAI,aAAa,CAAC;AAAA,MAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,IAAA;AAInC,QAAMY,IAAQD,EAAU,OAClBE,IAAYF,EAAU,WACtBvQ,IAAQuQ,EAAU,gBAElBG,IAAgB,IAAI,aAAaF,IAAQ,CAAC,GAC1CG,IAAY,IAAI,YAAYH,CAAK;AACvC,MAAII,IAAS;AAEb,WAAStQ,IAAI,GAAGA,IAAIkQ,GAAOlQ,KAAK,GAAG;AAClC,UAAMiC,IAAIkO,EAAUnQ,IAAI,CAAC,GACnBkC,IAAIiO,EAAUnQ,IAAI,IAAI,CAAC;AAC7B,IAAK+P,GAAmB9N,GAAGC,GAAGoN,CAAQ,MACtCc,EAAcE,IAAS,CAAC,IAAIrO,GAC5BmO,EAAcE,IAAS,IAAI,CAAC,IAAIpO,GAChCmO,EAAUC,CAAM,IAAI5Q,EAAMM,CAAC,GAC3BsQ,KAAU;AAAA,EACX;AAEA,SAAO;AAAA,IACN,OAAOA;AAAA,IACP,WAAWF,EAAc,SAAS,GAAGE,IAAS,CAAC;AAAA,IAC/C,gBAAgBD,EAAU,SAAS,GAAGC,CAAM;AAAA,EAAA;AAE9C;ACjHA,MAAMpU,GAAY;AAAA,EAChB,cAAc;AACZ,SAAK,gBAAgB,GACrB,KAAK,iBAAiB,GACtB,KAAK,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,EAAA;AAAA,EACnD;AAAA,EAEA,YAAYb,GAAOC,GAAQ;AACzB,SAAK,gBAAgB,KAAK,IAAI,GAAGD,CAAK,GACtC,KAAK,iBAAiB,KAAK,IAAI,GAAGC,CAAM;AAAA,EAC1C;AAAA,EAEA,cAAc;AACZ,WAAO,EAAE,OAAO,KAAK,eAAe,QAAQ,KAAK,eAAA;AAAA,EACnD;AAAA,EAEA,aAAaC,GAAM;AACjB,IAAI,OAAOA,EAAK,QAAS,aACvB,KAAK,UAAU,OAAO,KAAK,IAAI,MAAQA,EAAK,IAAI,IAE9C,OAAOA,EAAK,WAAY,aAC1B,KAAK,UAAU,UAAUA,EAAK,UAE5B,OAAOA,EAAK,WAAY,aAC1B,KAAK,UAAU,UAAUA,EAAK;AAAA,EAElC;AAAA,EAEA,eAAe;AACb,WAAO,EAAE,GAAG,KAAK,UAAA;AAAA,EACnB;AAAA,EAEA,YAAY;AACV,UAAMgV,IAAa,KAAK,gBAAgB,KAAK,UAAU,MACjDC,IAAc,KAAK,iBAAiB,KAAK,UAAU,MACnD9U,IAAK,IAAI6U,GACT5U,IAAK,KAAK6U,GACV5U,IAAK,KAAK,KAAK,UAAU,UAAUF,GACnCG,IAAK,IAAI,KAAK,UAAU,UAAUF;AACxC,WAAO,IAAI,aAAa,CAACD,GAAI,GAAG,GAAG,GAAGC,GAAI,GAAGC,GAAIC,GAAI,CAAC,CAAC;AAAA,EACzD;AACF;AAEO,MAAM4U,GAAgB;AAAA,EAC3B,YAAYxV,GAAQb,GAAQ6B,IAAU,CAAA,GAAI;AACxC,SAAK,SAAShB,GACd,KAAK,SAASb,GACd,KAAK,oBAAoB6B,EAAQ,mBACjC,KAAK,UAAUA,EAAQ,SACvB,KAAK,YAAYA,EAAQ,aAAa,IAEtC,KAAK,YAAY,IACjB,KAAK,QAAQ,MACb,KAAK,cAAc,GACnB,KAAK,WAAW,IAChB,KAAK,YAAY,MACjB,KAAK,eAAe,GACpB,KAAK,eAAe,GACpB,KAAK,oBAAoB,IAEzB,KAAK,4BAAY,IAAA,GACjB,KAAK,+BAAe,IAAA,GACpB,KAAK,gBAAgB,KACrB,KAAK,UAAU,GACf,KAAK,UAAU,MACf,KAAK,UAAU,GACf,KAAK,cAAc,GACnB,KAAK,aAAa,GAClB,KAAK,mBAAmB;AAExB,UAAM/B,IAAKe,EAAO,WAAW,UAAU;AAAA,MACrC,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,MACP,SAAS;AAAA,MACT,iBAAiB;AAAA,IAAA,CAClB;AACD,QAAI,CAACf;AACH,YAAM,IAAI,MAAM,sBAAsB;AAExC,SAAK,KAAKA,GACV,KAAK,SAAS,IAAIgC,GAAA,GAElB,KAAK,gBAAA,GACL,KAAK,iBAAA,GAEL,KAAK,iBAAiB,IAAI,eAAe,MAAM,KAAK,QAAQ,GAC5D,KAAK,eAAe,QAAQjB,CAAM,GAElC,KAAK,mBAAmB,CAAA6O,MAAS,KAAK,cAAcA,CAAK,GACzD,KAAK,mBAAmB,CAAAA,MAAS,KAAK,cAAcA,CAAK,GACzD,KAAK,iBAAiB,CAAAA,MAAS,KAAK,YAAYA,CAAK,GACrD,KAAK,aAAa,CAAAA,MAAS,KAAK,QAAQA,CAAK,GAC7C,KAAK,mBAAmB,CAAAA,MAAS,KAAK,cAAcA,CAAK,GAEzD7O,EAAO,iBAAiB,eAAe,KAAK,gBAAgB,GAC5DA,EAAO,iBAAiB,eAAe,KAAK,gBAAgB,GAC5DA,EAAO,iBAAiB,aAAa,KAAK,cAAc,GACxDA,EAAO,iBAAiB,iBAAiB,KAAK,cAAc,GAC5DA,EAAO,iBAAiB,SAAS,KAAK,YAAY,EAAE,SAAS,IAAO,GACpEA,EAAO,iBAAiB,YAAY,KAAK,gBAAgB,GAEzD,KAAK,WAAA,GACL,KAAK,OAAA;AAAA,EACP;AAAA,EAEA,kBAAkB;AAChB,UAAMf,IAAK,KAAK,IAEVwW,IAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBTC,IAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAajB,QAJA,KAAK,UAAUpW,GAAcL,GAAIwW,GAAQC,CAAQ,GACjD,KAAK,UAAUzW,EAAG,mBAAmB,KAAK,SAAS,SAAS,GAC5D,KAAK,UAAUA,EAAG,mBAAmB,KAAK,SAAS,SAAS,GAC5D,KAAK,WAAWA,EAAG,mBAAmB,KAAK,SAAS,UAAU,GAC1D,CAAC,KAAK,WAAW,CAAC,KAAK,WAAW,CAAC,KAAK;AAC1C,YAAM,IAAI,MAAM,gCAAgC;AAKlD,QAFA,KAAK,MAAMA,EAAG,kBAAA,GACd,KAAK,MAAMA,EAAG,aAAA,GACV,CAAC,KAAK,OAAO,CAAC,KAAK;AACrB,YAAM,IAAI,MAAM,0BAA0B;AAG5C,IAAAA,EAAG,gBAAgB,KAAK,GAAG,GAC3BA,EAAG,WAAWA,EAAG,cAAc,KAAK,GAAG,GACvCA,EAAG;AAAA,MACDA,EAAG;AAAA,MACH,IAAI,aAAa;AAAA,QACf;AAAA,QAAG;AAAA,QAAG;AAAA,QAAG;AAAA,QACT;AAAA,QAAG;AAAA,QAAG;AAAA,QAAG;AAAA,QACT;AAAA,QAAG;AAAA,QAAG;AAAA,QAAG;AAAA,QACT;AAAA,QAAG;AAAA,QAAG;AAAA,QAAG;AAAA,MAAA,CACV;AAAA,MACDA,EAAG;AAAA,IAAA;AAGL,UAAM0W,IAAQ1W,EAAG,kBAAkB,KAAK,SAAS,OAAO,GAClD2W,IAAM3W,EAAG,kBAAkB,KAAK,SAAS,KAAK;AACpD,IAAAA,EAAG,wBAAwB0W,CAAK,GAChC1W,EAAG,wBAAwB2W,CAAG,GAC9B3W,EAAG,oBAAoB0W,GAAO,GAAG1W,EAAG,OAAO,IAAO,IAAI,CAAC,GACvDA,EAAG,oBAAoB2W,GAAK,GAAG3W,EAAG,OAAO,IAAO,IAAI,CAAC,GAErDA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,WAAWA,EAAG,cAAc,IAAI;AAAA,EACrC;AAAA,EAEA,mBAAmB;AACjB,UAAMA,IAAK,KAAK,IAEV4W,IAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcdC,IAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCtB,QALA,KAAK,eAAexW,GAAcL,GAAI4W,GAAaC,CAAa,GAChE,KAAK,eAAe7W,EAAG,mBAAmB,KAAK,cAAc,SAAS,GACtE,KAAK,aAAaA,EAAG,mBAAmB,KAAK,cAAc,YAAY,GACvE,KAAK,gBAAgBA,EAAG,mBAAmB,KAAK,cAAc,UAAU,GACxE,KAAK,oBAAoBA,EAAG,mBAAmB,KAAK,cAAc,cAAc,GAC5E,CAAC,KAAK,gBAAgB,CAAC,KAAK,cAAc,CAAC,KAAK,iBAAiB,CAAC,KAAK;AACzE,YAAM,IAAI,MAAM,sCAAsC;AAOxD,QAJA,KAAK,WAAWA,EAAG,kBAAA,GACnB,KAAK,iBAAiBA,EAAG,aAAA,GACzB,KAAK,kBAAkBA,EAAG,aAAA,GAC1B,KAAK,sBAAsBA,EAAG,cAAA,GAC1B,CAAC,KAAK,YAAY,CAAC,KAAK,kBAAkB,CAAC,KAAK,mBAAmB,CAAC,KAAK;AAC3E,YAAM,IAAI,MAAM,gCAAgC;AAGlD,IAAAA,EAAG,gBAAgB,KAAK,QAAQ,GAEhCA,EAAG,WAAWA,EAAG,cAAc,KAAK,cAAc,GAClDA,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,UAAM8W,IAAc9W,EAAG,kBAAkB,KAAK,cAAc,WAAW;AACvE,QAAI8W,IAAc;AAChB,YAAM,IAAI,MAAM,oCAAoC;AAEtD,IAAA9W,EAAG,wBAAwB8W,CAAW,GACtC9W,EAAG,oBAAoB8W,GAAa,GAAG9W,EAAG,OAAO,IAAO,GAAG,CAAC,GAE5DA,EAAG,WAAWA,EAAG,cAAc,KAAK,eAAe,GACnDA,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,UAAM+W,IAAe/W,EAAG,kBAAkB,KAAK,cAAc,OAAO;AACpE,QAAI+W,IAAe;AACjB,YAAM,IAAI,MAAM,gCAAgC;AAElD,IAAA/W,EAAG,wBAAwB+W,CAAY,GACvC/W,EAAG,qBAAqB+W,GAAc,GAAG/W,EAAG,gBAAgB,GAAG,CAAC,GAEhEA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,WAAWA,EAAG,cAAc,IAAI,GAEnCA,EAAG,YAAYA,EAAG,YAAY,KAAK,mBAAmB,GACtDA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,OAAO,GACjEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,OAAO,GACjEA,EAAG;AAAA,MACDA,EAAG;AAAA,MACH;AAAA,MACAA,EAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACAA,EAAG;AAAA,MACHA,EAAG;AAAA,MACH,IAAI,WAAW,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC;AAAA,IAAA,GAErCA,EAAG,YAAYA,EAAG,YAAY,IAAI;AAAA,EACpC;AAAA,EAEA,aAAaqB,GAAM;AACjB,UAAM2V,IAAa,EAAE,GAAG3V,EAAA;AACxB,IAAI,OAAO2V,EAAW,QAAS,aAC7BA,EAAW,OAAOjT,EAAMiT,EAAW,MAAM,KAAK,SAAS,KAAK,OAAO,IAErE,KAAK,OAAO,aAAaA,CAAU,GACnC,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,eAAe;AACb,WAAO,KAAK,OAAO,aAAA;AAAA,EACrB;AAAA,EAEA,gBAAgBnR,GAAQ;AACtB,QAAI,CAACA,KAAU,CAACA,EAAO,OAAQ;AAC/B,UAAM7F,IAAK,KAAK,IACViX,IAAc,KAAK,IAAI,GAAG,KAAK,MAAMpR,EAAO,SAAS,CAAC,CAAC;AAC7D,SAAK,mBAAmBoR,GACxBjX,EAAG,YAAYA,EAAG,YAAY,KAAK,mBAAmB,GACtDA,EAAG,WAAWA,EAAG,YAAY,GAAGA,EAAG,MAAMiX,GAAa,GAAG,GAAGjX,EAAG,MAAMA,EAAG,eAAe6F,CAAM,GAC7F7F,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,aAAamJ,GAAQ;AACnB,UAAMnJ,IAAK,KAAK;AAChB,QAAI,CAACmJ,KAAU,CAACA,EAAO,SAAS,CAACA,EAAO,aAAa,CAACA,EAAO,gBAAgB;AAC3E,WAAK,aAAa,GAClB,KAAK,cAAA;AACL;AAAA,IACF;AAEA,IAAAnJ,EAAG,WAAWA,EAAG,cAAc,KAAK,cAAc,GAClDA,EAAG,WAAWA,EAAG,cAAcmJ,EAAO,WAAWnJ,EAAG,WAAW,GAE/DA,EAAG,WAAWA,EAAG,cAAc,KAAK,eAAe,GACnDA,EAAG,WAAWA,EAAG,cAAcmJ,EAAO,gBAAgBnJ,EAAG,WAAW,GACpEA,EAAG,WAAWA,EAAG,cAAc,IAAI,GAEnC,KAAK,aAAamJ,EAAO,OACzB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,mBAAmB+N,GAAQ;AACzB,UAAM7V,IAAO,EAAQ6V;AACrB,IAAI,KAAK,sBAAsB7V,MAC/B,KAAK,oBAAoBA,GACrBA,KACF,KAAK,WAAA;AAAA,EAET;AAAA,EAEA,aAAa;AACX,QAAI,KAAK,cAAc,QAAQ,KAAK,OAAO,kBAAkB,KAAK,SAAS;AACzE,UAAI;AACF,aAAK,OAAO,sBAAsB,KAAK,SAAS;AAAA,MAClD,QAAQ;AAAA,MAER;AAEF,SAAK,WAAW,IAChB,KAAK,YAAY,MACjB,KAAK,OAAO,UAAU,OAAO,UAAU;AAAA,EACzC;AAAA,EAEA,cAAcmS,GAASC,GAAS;AAC9B,UAAMxQ,IAAO,KAAK,OAAO,sBAAA,GACnBzB,IAAKgS,IAAUvQ,EAAK,MACpBxB,IAAKgS,IAAUxQ,EAAK,KACpBkU,IAAQ,KAAK,OAAO,aAAA;AAC1B,WAAO,CAACA,EAAM,UAAU3V,IAAK2V,EAAM,MAAMA,EAAM,UAAU1V,IAAK0V,EAAM,IAAI;AAAA,EAC1E;AAAA,EAEA,cAActD,GAAQC,GAAQ;AAC5B,UAAMqD,IAAQ,KAAK,OAAO,aAAA;AAC1B,WAAO,EAAEtD,IAASsD,EAAM,WAAWA,EAAM,OAAOrD,IAASqD,EAAM,WAAWA,EAAM,IAAI;AAAA,EACtF;AAAA,EAEA,qBAAqB;AACnB,UAAM3T,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrD+K,IAAiB,KAAK,OAAO,cAAc,KAAK,KAAK/K,CAAI,GACzD4T,IAAQ;AAAA,MACZ,CAAC,GAAG,GAAG;AAAA,MACP,CAAC,GAAG,GAAG;AAAA,MACP,CAAC,GAAG,GAAG;AAAA,MACP,CAAC,GAAG,GAAG;AAAA,MACP,CAAC,GAAG,GAAG;AAAA,MACP,CAAC,GAAG,GAAG;AAAA,MACP,CAAC,GAAG,GAAG;AAAA,MACP,CAAC,GAAG,CAAG;AAAA,MACP,CAAC,GAAG,IAAI;AAAA,MACR,CAAC,IAAI,IAAI;AAAA,MACT,CAAC,IAAI,EAAI;AAAA,MACT,CAAC,IAAI,EAAI;AAAA,IAAA;AAEX,QAAIC,IAAOD,EAAM,CAAC,EAAE,CAAC;AACrB,aAAStR,IAAI,GAAGA,IAAIsR,EAAM,QAAQtR,KAAK,GAAG;AACxC,YAAM,CAACtB,GAAI8S,CAAE,IAAIF,EAAMtR,IAAI,CAAC,GACtB,CAACrB,GAAI8S,CAAE,IAAIH,EAAMtR,CAAC;AACxB,UAAIyI,KAAkB/J,EAAI;AAC1B,YAAMqD,IAAI9D,GAAOwK,IAAiB/J,KAAM,KAAK,IAAI,MAAMC,IAAKD,CAAE,GAAG,GAAG,CAAC;AACrE,MAAA6S,IAAOC,KAAMC,IAAKD,KAAMzP;AAAA,IAC1B;AAEA,UAAM2P,IAAWJ,EAAMA,EAAM,SAAS,CAAC;AACvC,WAAI7I,IAAiBiJ,EAAS,CAAC,MAC7BH,MAAS9I,IAAiBiJ,EAAS,CAAC,KAAK,IAGpCzT,EAAMsT,GAAM,KAAK,EAAI;AAAA,EAC9B;AAAA,EAEA,aAAa;AACX,UAAMpU,IAAO,KAAK,OAAO,sBAAA,GACnBwU,IAAK,KAAK,IAAI,GAAGxU,EAAK,SAAS,CAAC,GAChCyU,IAAK,KAAK,IAAI,GAAGzU,EAAK,UAAU,CAAC,GAEjCO,IAAO,KAAK,IAAIiU,IAAK,KAAK,OAAO,OAAOC,IAAK,KAAK,OAAO,MAAM,GAC/DjU,IAAW,OAAO,SAASD,CAAI,KAAKA,IAAO,IAAIA,IAAO;AAE5D,SAAK,UAAUC,GACf,KAAK,UAAU,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAChD,KAAK,UAAU,KAAK,IAAI,GAAG,KAAK,UAAU,CAAC,GACvC,KAAK,UAAU,KAAK,YACtB,KAAK,UAAU,KAAK;AAGtB,UAAMkU,IAAgBF,IAAKhU,GACrBmU,IAAgBF,IAAKjU;AAE3B,SAAK,OAAO,aAAa;AAAA,MACvB,MAAMM,EAAMN,GAAU,KAAK,SAAS,KAAK,OAAO;AAAA,MAChD,UAAU,KAAK,OAAO,QAAQkU,KAAiB;AAAA,MAC/C,UAAU,KAAK,OAAO,SAASC,KAAiB;AAAA,IAAA,CACjD,GAED,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,OAAOC,GAAQC,GAASC,GAAS;AAC/B,UAAMZ,IAAQ,KAAK,OAAO,aAAA,GACpBa,IAAWjU,EAAMoT,EAAM,OAAOU,GAAQ,KAAK,SAAS,KAAK,OAAO;AACtE,QAAIG,MAAab,EAAM;AACrB;AAGF,UAAMtD,IAASsD,EAAM,UAAUW,IAAUX,EAAM,MACzCrD,IAASqD,EAAM,UAAUY,IAAUZ,EAAM;AAE/C,SAAK,OAAO,aAAa;AAAA,MACvB,MAAMa;AAAA,MACN,SAASnE,IAASiE,IAAUE;AAAA,MAC5B,SAASlE,IAASiE,IAAUC;AAAA,IAAA,CAC7B,GAED,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,iBAAiB;AACf,UAAMb,IAAQ,KAAK,OAAO,aAAA,GACpBc,IAAK,KAAK,OAAO,YAAA,GAEjBlE,IAAWkE,EAAG,QAAQd,EAAM,MAC5BnD,IAAWiE,EAAG,SAASd,EAAM,MAE7Be,IAAUnE,IAAW,KACrBoE,IAAUnE,IAAW,KAErBpL,IAAO,CAACsP,GACRpP,IAAO,KAAK,OAAO,QAAQiL,IAAWmE,GACtCrP,IAAO,CAACsP,GACRpP,IAAO,KAAK,OAAO,SAASiL,IAAWmE;AAE7C,SAAK,OAAO,aAAa;AAAA,MACvB,SAASpU,EAAMoT,EAAM,SAASvO,GAAME,CAAI;AAAA,MACxC,SAAS/E,EAAMoT,EAAM,SAAStO,GAAME,CAAI;AAAA,IAAA,CACzC;AAAA,EACH;AAAA,EAEA,gBAAgB;AACd,IAAI,OAAO,KAAK,qBAAsB,cACpC,KAAK,kBAAkB,KAAK,OAAO,aAAA,CAAc;AAAA,EAErD;AAAA,EAEA,aAAa;AACX,UAAMvF,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrD4U,IAAU,KAAK,OAAO,cAAc,KAAK,KAAK5U,CAAI;AACxD,WAAOO,EAAM,KAAK,MAAMqU,CAAO,GAAG,GAAG,KAAK,OAAO,WAAW;AAAA,EAC9D;AAAA,EAEA,gBAAgB;AACd,UAAMjB,IAAQ,KAAK,OAAO,aAAA,GACpBc,IAAK,KAAK,OAAO,YAAA;AACvB,WAAO;AAAA,MACLd,EAAM;AAAA,MACNA,EAAM;AAAA,MACNA,EAAM,UAAUc,EAAG,QAAQd,EAAM;AAAA,MACjCA,EAAM,UAAUc,EAAG,SAASd,EAAM;AAAA,IAAA;AAAA,EAEtC;AAAA,EAEA,iBAAiBrS,GAAGC,GAAG;AACrB,WAAO,EAAED,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC;AAAA,EACtE;AAAA,EAEA,kBAAkB;AAChB,UAAMsM,IAAO,KAAK,WAAA;AAClB,SAAK,cAAcA;AAEnB,UAAM8F,IAAQ,KAAK,OAAO,aAAA,GACpBc,IAAK,KAAK,OAAO,YAAA,GAEjB9D,IAAa,KAAK,IAAI,GAAG,KAAK,OAAO,cAAc9C,CAAI,GACvD+C,IAAa,KAAK,KAAK,KAAK,OAAO,QAAQD,CAAU,GACrDE,IAAc,KAAK,KAAK,KAAK,OAAO,SAASF,CAAU,GAEvDG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAa,KAAK,OAAO,QAAQ,CAAC,GACjEG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAc,KAAK,OAAO,QAAQ,CAAC,GAElEgE,IAAWlB,EAAM,SACjBmB,IAAWnB,EAAM,SACjBoB,IAAWpB,EAAM,UAAUc,EAAG,QAAQd,EAAM,MAC5CqB,IAAWrB,EAAM,UAAUc,EAAG,SAASd,EAAM,MAE7CsB,IAAW1U,EAAM,KAAK,MAAOsU,IAAWlE,IAAc,KAAK,OAAO,QAAQ,GAAG,GAAGG,IAAS,CAAC,GAC1FoE,IAAW3U,EAAM,KAAK,OAAQwU,IAAW,KAAKpE,IAAc,KAAK,OAAO,QAAQ,GAAG,GAAGG,IAAS,CAAC,GAChGqE,IAAW5U,EAAM,KAAK,MAAOuU,IAAWnE,IAAc,KAAK,OAAO,QAAQ,GAAG,GAAGI,IAAS,CAAC,GAC1FqE,KAAW7U,EAAM,KAAK,OAAQyU,IAAW,KAAKrE,IAAc,KAAK,OAAO,QAAQ,GAAG,GAAGI,IAAS,CAAC;AAEtG,QAAIkE,IAAWC,KAAYC,IAAWC;AACpC,aAAO,CAAA;AAGT,UAAMC,MAAgBR,IAAWE,KAAY,MAAMpE,IAAc,KAAK,OAAO,UACvE2E,KAAgBR,IAAWE,KAAY,MAAMrE,IAAc,KAAK,OAAO,UAEvE4E,KAAU,CAAA;AAEhB,aAAS/Q,IAAI2Q,GAAU3Q,KAAK4Q,IAAU5Q,KAAK;AACzC,eAASD,IAAI0Q,GAAU1Q,KAAK2Q,GAAU3Q,KAAK,GAAG;AAC5C,cAAMqD,KAAOrD,IAAI,KAAK,OAAO,WAAWoM,GAClC9I,IAAMrD,IAAI,KAAK,OAAO,WAAWmM,GACjChB,IAAQ,KAAK,KAAKpL,IAAI,KAAK,KAAK,OAAO,UAAUqM,CAAU,IAAID,GAC/Df,IAAS,KAAK,KAAKpL,IAAI,KAAK,KAAK,OAAO,UAAUqM,CAAW,IAAIF,GAEjE7D,IAAKvI,IAAI8Q,IACTtI,IAAKvI,IAAI8Q;AAEf,QAAAC,GAAQ,KAAK;AAAA,UACX,KAAK,GAAG1H,CAAI,IAAItJ,CAAC,IAAIC,CAAC;AAAA,UACtB,MAAAqJ;AAAA,UACA,GAAAtJ;AAAA,UACA,GAAAC;AAAA,UACA,QAAQ,CAACoD,IAAMC,GAAK8H,GAAOC,CAAM;AAAA,UACjC,WAAW9C,IAAKA,IAAKC,IAAKA;AAAA,UAC1B,KAAKa,GAAU,KAAK,QAAQC,GAAMtJ,GAAGC,CAAC;AAAA,QAAA,CACvC;AAAA,MACH;AAGF,WAAA+Q,GAAQ,KAAK,CAACjU,GAAGC,MAAMD,EAAE,YAAYC,EAAE,SAAS,GACzCgU;AAAA,EACT;AAAA,EAEA,YAAYrW,GAAM;AAChB,QAAI,KAAK,MAAM,IAAIA,EAAK,GAAG,KAAK,KAAK,SAAS,IAAIA,EAAK,GAAG,KAAK,KAAK;AAClE;AAGF,UAAMsW,IAAa,IAAI,gBAAA;AACvB,SAAK,SAAS,IAAItW,EAAK,KAAKsW,CAAU;AAEtC,UAAMtE,IAAgB,CAAC,CAAC,KAAK;AAC7B,UAAMhS,EAAK,KAAK;AAAA,MACd,QAAQsW,EAAW;AAAA,MACnB,SAAStE,IAAgB,EAAE,eAAe,KAAK,cAAc;AAAA,IAAA,CAC9D,EACE,KAAK,CAAA9R,MAAY;AAChB,UAAI,CAACA,EAAS;AACZ,cAAM,IAAI,MAAM,QAAQA,EAAS,MAAM,EAAE;AAE3C,aAAOA,EAAS,KAAA;AAAA,IAClB,CAAC,EACA,KAAK,CAAAC,MAAQ,kBAAkBA,CAAI,CAAC,EACpC,KAAK,CAAAC,MAAU;AAEd,UADA,KAAK,SAAS,OAAOJ,EAAK,GAAG,GACzB,KAAK,aAAasW,EAAW,OAAO,SAAS;AAC/C,QAAAlW,EAAO,MAAA;AACP;AAAA,MACF;AAEA,YAAMC,IAAU,KAAK,GAAG,cAAA;AACxB,UAAI,CAACA,GAAS;AACZ,QAAAD,EAAO,MAAA;AACP;AAAA,MACF;AAEA,WAAK,GAAG,YAAY,KAAK,GAAG,YAAYC,CAAO,GAC/C,KAAK,GAAG,YAAY,KAAK,GAAG,qBAAqB,CAAC,GAClD,KAAK,GAAG,cAAc,KAAK,GAAG,YAAY,KAAK,GAAG,gBAAgB,KAAK,GAAG,aAAa,GACvF,KAAK,GAAG,cAAc,KAAK,GAAG,YAAY,KAAK,GAAG,gBAAgB,KAAK,GAAG,aAAa,GACvF,KAAK,GAAG,cAAc,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAoB,KAAK,GAAG,MAAM,GACpF,KAAK,GAAG,cAAc,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAoB,KAAK,GAAG,MAAM,GACpF,KAAK,GAAG,WAAW,KAAK,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,KAAK,GAAG,MAAM,KAAK,GAAG,eAAeD,CAAM,GACnG,KAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5CA,EAAO,MAAA,GAEP,KAAK,MAAM,IAAIJ,EAAK,KAAK;AAAA,QACvB,SAAAK;AAAA,QACA,QAAQL,EAAK;AAAA,QACb,MAAMA,EAAK;AAAA,QACX,UAAU,KAAK;AAAA,MAAA,CAChB,GAED,KAAK,UAAA,GACL,KAAK,cAAA;AAAA,IACP,CAAC,EACA,MAAM,CAAAM,MAAS;AAEd,MADA,KAAK,SAAS,OAAON,EAAK,GAAG,GACzB,CAAAsW,EAAW,OAAO,WAGtB,QAAQ,KAAK,oBAAoBtW,EAAK,KAAKM,CAAK;AAAA,IAClD,CAAC;AAAA,EACL;AAAA,EAEA,YAAY;AACV,QAAI,KAAK,MAAM,QAAQ,KAAK;AAC1B;AAGF,UAAMiW,IAAU,MAAM,KAAK,KAAK,MAAM,SAAS;AAC/C,IAAAA,EAAQ,KAAK,CAACnU,GAAGC,MAAMD,EAAE,CAAC,EAAE,WAAWC,EAAE,CAAC,EAAE,QAAQ;AAEpD,UAAMmU,IAAc,KAAK,MAAM,OAAO,KAAK;AAC3C,aAASpT,IAAI,GAAGA,IAAIoT,GAAapT,KAAK,GAAG;AACvC,YAAM,CAACqT,GAAKnV,CAAK,IAAIiV,EAAQnT,CAAC;AAC9B,WAAK,GAAG,cAAc9B,EAAM,OAAO,GACnC,KAAK,MAAM,OAAOmV,CAAG;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,SAAS;AACP,QAAI,KAAK;AACP;AAGF,SAAK,eAAe;AAEpB,UAAMnZ,IAAK,KAAK;AAChB,IAAAA,EAAG,WAAW,MAAM,MAAM,KAAK,CAAC,GAChCA,EAAG,MAAMA,EAAG,gBAAgB;AAE5B,UAAM+Y,IAAU,KAAK,gBAAA;AACrB,IAAA/Y,EAAG,WAAW,KAAK,OAAO,GAC1BA,EAAG,gBAAgB,KAAK,GAAG,GAC3BA,EAAG,iBAAiB,KAAK,SAAS,IAAO,KAAK,OAAO,WAAW,GAChEA,EAAG,UAAU,KAAK,UAAU,CAAC;AAE7B,UAAMoZ,IAAa,KAAK,cAAA,GAClBC,IAAgB,CAAA;AACtB,eAAW,CAAA,EAAGC,CAAM,KAAK,KAAK;AAC5B,MAAK,KAAK,iBAAiBA,EAAO,QAAQF,CAAU,KAGpDC,EAAc,KAAKC,CAAM;AAG3B,IAAAD,EAAc,KAAK,CAACvU,GAAGC,MAAMD,EAAE,OAAOC,EAAE,IAAI;AAC5C,eAAWuU,KAAUD;AACnB,MAAAC,EAAO,WAAW,KAAK,aACvBtZ,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYsZ,EAAO,OAAO,GAC5CtZ,EAAG,UAAU,KAAK,SAASsZ,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,CAAC,GACjGtZ,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC;AAGvC,QAAIuZ,IAAgB;AAEpB,eAAW7W,KAAQqW,GAAS;AAC1B,YAAMO,IAAS,KAAK,MAAM,IAAI5W,EAAK,GAAG;AACtC,UAAI,CAAC4W,GAAQ;AACX,aAAK,YAAY5W,CAAI;AACrB;AAAA,MACF;AAEA,MAAA4W,EAAO,WAAW,KAAK,aACvBtZ,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYsZ,EAAO,OAAO,GAC5CtZ,EAAG,UAAU,KAAK,SAASsZ,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,CAAC,GACjGtZ,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC,GACrCuZ,KAAiB;AAAA,IACnB;AAEA,IAAAvZ,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,gBAAgB,IAAI;AAEvB,QAAIwZ,IAAiB;AACrB,IAAI,KAAK,aAAa,MACpBxZ,EAAG,OAAOA,EAAG,KAAK,GAClBA,EAAG,UAAUA,EAAG,KAAKA,EAAG,mBAAmB,GAC3CA,EAAG,WAAW,KAAK,YAAY,GAC/BA,EAAG,gBAAgB,KAAK,QAAQ,GAChCA,EAAG,iBAAiB,KAAK,cAAc,IAAO,KAAK,OAAO,WAAW,GACrEA,EAAG,UAAU,KAAK,YAAY,KAAK,oBAAoB,GACvDA,EAAG,UAAU,KAAK,mBAAmB,KAAK,gBAAgB,GAC1DA,EAAG,UAAU,KAAK,eAAe,CAAC,GAClCA,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY,KAAK,mBAAmB,GACtDA,EAAG,WAAWA,EAAG,QAAQ,GAAG,KAAK,UAAU,GAC3CA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,gBAAgB,IAAI,GACvBwZ,IAAiB,KAAK,aAGpB,OAAO,KAAK,WAAY,cAC1B,KAAK,QAAQ;AAAA,MACX,MAAM,KAAK;AAAA,MACX,SAAST,EAAQ;AAAA,MACjB,UAAUQ;AAAA,MACV,QAAQC;AAAA,MACR,UAAUH,EAAc;AAAA,MACxB,OAAO,KAAK,MAAM;AAAA,MAClB,UAAU,KAAK,SAAS;AAAA,IAAA,CACzB;AAAA,EAEL;AAAA,EAEA,gBAAgB;AACd,IAAI,KAAK,UAAU,QAAQ,KAAK,cAIhC,KAAK,QAAQ,sBAAsB,MAAM;AACvC,WAAK,QAAQ,MACb,KAAK,OAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAEA,SAAS;AACP,UAAMpW,IAAO,KAAK,OAAO,sBAAA,GACnB6P,IAAO,KAAK,IAAI,GAAG7P,EAAK,SAAS,KAAK,OAAO,eAAe,CAAC,GAC7D8P,IAAO,KAAK,IAAI,GAAG9P,EAAK,UAAU,KAAK,OAAO,gBAAgB,CAAC,GAC/DG,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9C4P,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO1P,CAAG,CAAC,GAC3C6P,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO3P,CAAG,CAAC;AAEjD,KAAI,KAAK,OAAO,UAAU4P,KAAU,KAAK,OAAO,WAAWC,OACzD,KAAK,OAAO,QAAQD,GACpB,KAAK,OAAO,SAASC,IAGvB,KAAK,OAAO,YAAYH,GAAMC,CAAI,GAClC,KAAK,GAAG,SAAS,GAAG,GAAGC,GAAQC,CAAM,GACrC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,cAAcrD,GAAO;AACnB,IAAI,KAAK,sBAGT,KAAK,WAAW,IAChB,KAAK,YAAYA,EAAM,WACvB,KAAK,eAAeA,EAAM,SAC1B,KAAK,eAAeA,EAAM,SAC1B,KAAK,OAAO,UAAU,IAAI,UAAU,GACpC,KAAK,OAAO,kBAAkBA,EAAM,SAAS;AAAA,EAC/C;AAAA,EAEA,cAAcA,GAAO;AAInB,QAHI,KAAK,qBAGL,CAAC,KAAK,YAAYA,EAAM,cAAc,KAAK;AAC7C;AAGF,UAAMU,IAAKV,EAAM,UAAU,KAAK,cAC1BW,IAAKX,EAAM,UAAU,KAAK;AAChC,SAAK,eAAeA,EAAM,SAC1B,KAAK,eAAeA,EAAM;AAE1B,UAAMuH,IAAQ,KAAK,OAAO,aAAA;AAC1B,SAAK,OAAO,aAAa;AAAA,MACvB,SAASA,EAAM,UAAU7G,IAAK6G,EAAM;AAAA,MACpC,SAASA,EAAM,UAAU5G,IAAK4G,EAAM;AAAA,IAAA,CACrC,GAED,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,YAAYvH,GAAO;AACjB,IAAI,KAAK,qBAGLA,EAAM,cAAc,KAAK,cAG7B,KAAK,WAAW,IAChB,KAAK,YAAY,MACjB,KAAK,OAAO,UAAU,OAAO,UAAU;AAAA,EACzC;AAAA,EAEA,QAAQA,GAAO;AACb,QAAI,KAAK,mBAAmB;AAC1B,MAAAA,EAAM,eAAA;AACN;AAAA,IACF;AACA,IAAAA,EAAM,eAAA;AACN,UAAM3M,IAAO,KAAK,OAAO,sBAAA,GACnB8E,IAAI6H,EAAM,UAAU3M,EAAK,MACzB+E,IAAI4H,EAAM,UAAU3M,EAAK,KACzB4U,IAASjI,EAAM,SAAS,IAAI,OAAO;AACzC,SAAK,OAAOiI,GAAQ9P,GAAGC,CAAC;AAAA,EAC1B;AAAA,EAEA,cAAc4H,GAAO;AACnB,QAAI,KAAK;AACP;AAEF,UAAM3M,IAAO,KAAK,OAAO,sBAAA,GACnB8E,IAAI6H,EAAM,UAAU3M,EAAK,MACzB+E,IAAI4H,EAAM,UAAU3M,EAAK;AAC/B,SAAK,OAAO2M,EAAM,WAAW,MAAM,MAAM7H,GAAGC,CAAC;AAAA,EAC/C;AAAA,EAEA,UAAU;AACR,QAAI,MAAK,WAIT;AAAA,WAAK,YAAY,IAEb,KAAK,UAAU,SACjB,qBAAqB,KAAK,KAAK,GAC/B,KAAK,QAAQ,OAGf,KAAK,eAAe,WAAA,GAEpB,KAAK,OAAO,oBAAoB,eAAe,KAAK,gBAAgB,GACpE,KAAK,OAAO,oBAAoB,eAAe,KAAK,gBAAgB,GACpE,KAAK,OAAO,oBAAoB,aAAa,KAAK,cAAc,GAChE,KAAK,OAAO,oBAAoB,iBAAiB,KAAK,cAAc,GACpE,KAAK,OAAO,oBAAoB,SAAS,KAAK,UAAU,GACxD,KAAK,OAAO,oBAAoB,YAAY,KAAK,gBAAgB,GAEjE,KAAK,WAAA;AAEL,iBAAW,CAAA,EAAGgR,CAAU,KAAK,KAAK;AAChC,QAAAA,EAAW,MAAA;AAEb,WAAK,SAAS,MAAA;AAEd,iBAAW,CAAA,EAAGhV,CAAK,KAAK,KAAK;AAC3B,aAAK,GAAG,cAAcA,EAAM,OAAO;AAErC,WAAK,MAAM,MAAA,GAEX,KAAK,GAAG,aAAa,KAAK,GAAG,GAC7B,KAAK,GAAG,kBAAkB,KAAK,GAAG,GAClC,KAAK,GAAG,cAAc,KAAK,OAAO,GAElC,KAAK,GAAG,aAAa,KAAK,cAAc,GACxC,KAAK,GAAG,aAAa,KAAK,eAAe,GACzC,KAAK,GAAG,cAAc,KAAK,mBAAmB,GAC9C,KAAK,GAAG,kBAAkB,KAAK,QAAQ,GACvC,KAAK,GAAG,cAAc,KAAK,YAAY;AAAA;AAAA,EACzC;AACF;AC/zBA,MAAMyV,KAAiC,CAAA,GACjCC,KAAyC,CAAA;AAgB/C,SAASC,GAAgB5K,GAAmB3B,GAAgC;AAC3E,SAAO2B,EAAO,MAAM3B;AACrB;AAEA,SAASwM,GACRlP,GACA4E,GACU;AACV,MAAI,CAAC,MAAM,QAAQA,CAAO,KAAKA,EAAQ,SAAS,EAAG,QAAO;AAE1D,QAAM,CAACvH,GAAGC,CAAC,IAAI0C;AACf,MAAI6K,IAAS;AAEb,WAASzP,IAAI,GAAG0P,IAAIlG,EAAQ,SAAS,GAAGxJ,IAAIwJ,EAAQ,QAAQkG,IAAI1P,KAAK;AACpE,UAAM,CAAC2P,GAAIC,CAAE,IAAIpG,EAAQxJ,CAAC,GACpB,CAAC6P,GAAIC,CAAE,IAAItG,EAAQkG,CAAC;AAI1B,IAFCE,IAAK1N,KAAM4N,IAAK5N,KAChBD,KAAM4N,IAAKF,MAAOzN,IAAI0N,KAAO,KAAK,IAAI,OAAOE,IAAKF,CAAE,IAAID,UACjC,CAACF;AAAA,EAC1B;AAEA,SAAOA;AACR;AAEA,SAASsE,GACRtO,GACAuO,GAKQ;AACR,WAAS,IAAIA,EAAQ,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AAChD,UAAM/K,IAAS+K,EAAQ,CAAC;AACxB,QAAK/K,GAAQ,aAAa,UACrB6K,GAAiBrO,GAAOwD,EAAO,WAAW;AAC/C,aAAO;AAAA,QACN,QAAAA;AAAA,QACA,aAAa;AAAA,QACb,UAAU4K,GAAgB5K,GAAQ,CAAC;AAAA,MAAA;AAAA,EAErC;AACA,SAAO;AACR;AA+BO,SAASgL,GAAgB;AAAA,EAC/B,QAAA7Z;AAAA,EACA,WAAAyC;AAAA,EACA,mBAAAqX;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,WAAAtI,IAAY;AAAA,EACZ,WAAAmE,IAAY;AAAA,EACZ,cAAAoE,IAAe;AAAA,EACf,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,iBAAAC,IAAkB;AAAA,EAClB,UAAAC,IAAW;AAAA,EACX,cAAA5O;AAAA,EACA,mBAAAO;AAAA,EACA,wBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,kBAAAG;AAAA,EACA,eAAAiO;AAAA,EACA,eAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,gBAAA7O;AAAA,EACA,iBAAA8O,KAAkB;AAAA,EAClB,oBAAAC;AAAA,EACA,WAAAnO;AAAA,EACA,OAAAlD;AACD,GAA6C;AAC5C,QAAMmD,IAAYC,EAAiC,IAAI,GACjDoI,IAAcpI,EAA+B,IAAI,GACjDkO,IAAoBlO,EAA4B,IAAI,GACpDmO,KAAwBnO,EAA4B,IAAI,GACxDoO,KACLpO,EAAiCoN,CAAiB,GAC7C,CAACiB,IAAgBC,EAAiB,IAAIC,GAAS,EAAI,GACnD,CAAC7O,IAAiB8O,CAAkB,IAAID,GAE5C,IAAI,GACA,CAAC5O,GAAgB8O,CAAiB,IAAIF;AAAA,IAC3C;AAAA,EAAA,GAEKG,IAAqB1O,EAA+B,IAAI,GACxD2O,IAAiBnB,KAAcX,IAC/B+B,IAAkBnB,KAAeX,IAEjChM,IAAcR;AAAA,IACnB,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,QAAQ,GAAG1D;IACjE,CAACA,CAAK;AAAA,EAAA,GAGDiS,IAAsBvO,EAAqB,MAC5CqO,EAAe,SAAS,IACpBA,IAEJC,EAAgB,WAAW,IACvB/B,KAED+B,EAAgB,IAAI,CAACrO,GAAaC,OAAW;AAAA,IACnD,IAAIA;AAAA,IACJ,aAAAD;AAAA,EAAA,EACC,GACA,CAACoO,GAAgBC,CAAe,CAAC,GAE9BE,IAAexO;AAAA,IACpB,MAAMuO,EAAoB,IAAI,CAAC1M,MAAWA,EAAO,WAAW;AAAA,IAC5D,CAAC0M,CAAmB;AAAA,EAAA,GAGfE,KAAkBzO,EAAQ,MAC1BoN,IAGExE,GAA0BC,GAAW2F,CAAY,IAFhD3F,GAGN,CAACuE,GAAkBvE,GAAW2F,CAAY,CAAC;AAExB,EAAAxO,EAAQ,MAAM;AACnC,UAAMlJ,IAAQ,OAAO6W,GAAoB,SAAS,GAAG;AACrD,WAAO,OAAO,SAAS7W,CAAK,IAAI,KAAK,IAAI,IAAIA,CAAK,IAAI;AAAA,EACvD,GAAG,CAAC6W,GAAoB,KAAK,CAAC;AAC9B,QAAMe,IAAiB1O,EAAQ,MAAM;AACpC,UAAMlJ,IAAQ,OAAO6W,GAAoB,UAAU,GAAG;AACtD,WAAO,OAAO,SAAS7W,CAAK,IAAI,KAAK,IAAI,IAAIA,CAAK,IAAI;AAAA,EACvD,GAAG,CAAC6W,GAAoB,MAAM,CAAC,GACzBgB,IAAiB3O,EAAQ,MAAM;AACpC,UAAMlJ,IAAQ,OAAO6W,GAAoB,UAAU,EAAE;AACrD,WAAO,OAAO,SAAS7W,CAAK,IAAI,KAAK,IAAI,GAAGA,CAAK,IAAI;AAAA,EACtD,GAAG,CAAC6W,GAAoB,MAAM,CAAC,GACzBiB,IAAmBjB,GAAoB,YAAY,gBAEnDkB,IAAqBnO;AAAA,IAC1B,CAACvM,MAAiC;AACjC,MAAAga,EAAkB,CAAChL,MACd,OAAOA,CAAI,MAAM,OAAOhP,CAAI,IACxBgP,KAERsK,IAAuBtZ,CAAI,GACpBA,EACP;AAAA,IACF;AAAA,IACA,CAACsZ,CAAoB;AAAA,EAAA;AAGtB,EAAAjK,EAAU,MAAM;AACf,IAAAsK,GAAqB,UAAUhB;AAAA,EAChC,GAAG,CAACA,CAAiB,CAAC,GAEtBtJ,EAAU,MAAM;AAQf,IAAI,EANHnE,MAAmB,OAChB,KACAkP,EAAoB;AAAA,MACpB,CAAC1M,GAAQ3B,MACR,OAAOuM,GAAgB5K,GAAQ3B,CAAK,CAAC,MAAM,OAAOb,CAAc;AAAA,IAAA,MAEnDA,MAAmB,QACpCwP,EAAmB,IAAI;AAGxB,UAAMC,IAAeV,EAAmB;AASxC,IAAI,EAPHU,MAAiB,OACd,KACAP,EAAoB;AAAA,MACpB,CAAC1M,GAAQ3B,MACR,OAAOuM,GAAgB5K,GAAQ3B,CAAK,CAAC,MAAM,OAAO4O,CAAY;AAAA,IAAA,MAGlDA,MAAiB,SACjCV,EAAmB,UAAU,MAC7BF,EAAmB,IAAI,GACvBX,IAAgB;AAAA,MACf,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACZ;AAAA,EAEH,GAAG,CAACgB,GAAqBlP,GAAgBkO,GAAesB,CAAkB,CAAC;AAE3E,QAAME,IAAsBrO,EAAY,CAACvM,MAA6B;AACrE,UAAM6a,IAAWlB,GAAqB;AACtC,IAAIkB,KACHA,EAAS7a,CAAI,GAEdyZ,EAAkB,UAAA,GAClBC,GAAsB,UAAA;AAAA,EACvB,GAAG,CAAA,CAAE;AAEL,EAAArK,EAAU,MAAM;AACf,QAAI,CAACkK,IAAiB;AACrB,MAAAM,GAAkB,EAAK;AACvB;AAAA,IACD;AACA,IAAAA,GAAkB,EAAI;AAAA,EACvB,GAAG,CAACN,IAAiB1a,GAAQ,EAAE,CAAC,GAEhCwQ,EAAU,MAAM;AACf,IAAI8J,MAAa,YACbc,EAAmB,YAAY,SACnCA,EAAmB,UAAU,MAC7BF,EAAmB,IAAI,GACvBX,IAAgB;AAAA,MACf,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACZ;AAAA,EACF,GAAG,CAACD,GAAUC,CAAa,CAAC;AAE5B,QAAM0B,IAAoBvO;AAAA,IACzB,CAAC4F,GAAiBC,MAA2C;AAC5D,YAAMwB,IAAWD,EAAY;AAC7B,UAAI,CAACC,EAAU,QAAO;AACtB,YAAMpF,IAAMoF,EAAS,cAAczB,GAASC,CAAO;AACnD,UAAI,CAAC,MAAM,QAAQ5D,CAAG,KAAKA,EAAI,SAAS,EAAG,QAAO;AAClD,YAAM9H,IAAI,OAAO8H,EAAI,CAAC,CAAC,GACjB7H,KAAI,OAAO6H,EAAI,CAAC,CAAC;AACvB,aAAI,CAAC,OAAO,SAAS9H,CAAC,KAAK,CAAC,OAAO,SAASC,EAAC,IAAU,OAChD,CAACD,GAAGC,EAAC;AAAA,IACb;AAAA,IACA,CAAA;AAAA,EAAC,GAGIoU,IAA0BxO;AAAA,IAC/B,CAACgC,MAA6C;AAC7C,UAAI4K,MAAa,SAAU;AAC3B,UAAI5K,EAAM,WAAWjD,EAAU,SAAS;AACvC,QAAI2O,EAAmB,YAAY,SAClCA,EAAmB,UAAU,MAC7BF,EAAmB,IAAI,GACvBX,IAAgB;AAAA,UACf,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,aAAa;AAAA,UACb,YAAY;AAAA,QAAA,CACZ;AAEF;AAAA,MACD;AACA,UAAI,CAACgB,EAAoB,OAAQ;AAEjC,YAAMlQ,IAAQ4Q,EAAkBvM,EAAM,SAASA,EAAM,OAAO;AAC5D,UAAI,CAACrE,EAAO;AAEZ,YAAM8Q,IAAMxC,GAAatO,GAAOkQ,CAAmB,GAC7Ca,IAAcD,GAAK,YAAY,MAC/BE,IAAcjB,EAAmB;AACvC,MAAI,OAAOiB,CAAW,MAAM,OAAOD,CAAW,MAE9ChB,EAAmB,UAAUgB,GAC7BlB,EAAmBkB,CAAW,GAC9B7B,IAAgB;AAAA,QACf,QAAQ4B,GAAK,UAAU;AAAA,QACvB,UAAUC;AAAA,QACV,aAAaD,GAAK,eAAe;AAAA,QACjC,YAAY9Q;AAAA,MAAA,CACZ;AAAA,IACF;AAAA,IACA,CAACiP,GAAUiB,GAAqBU,GAAmB1B,CAAa;AAAA,EAAA,GAG3D+B,IAA2B5O,EAAY,MAAM;AAClD,IAAI0N,EAAmB,YAAY,SACnCA,EAAmB,UAAU,MAC7BF,EAAmB,IAAI,GACvBX,IAAgB;AAAA,MACf,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACZ;AAAA,EACF,GAAG,CAACA,CAAa,CAAC,GAEZgC,IAAoB7O;AAAA,IACzB,CAACgC,MAA2C;AAE3C,UADI4K,MAAa,YACb5K,EAAM,WAAWjD,EAAU,QAAS;AACxC,UAAI,CAAC8O,EAAoB,QAAQ;AAChC,QAAAM,EAAmB,IAAI;AACvB;AAAA,MACD;AAEA,YAAMxQ,IAAQ4Q,EAAkBvM,EAAM,SAASA,EAAM,OAAO;AAC5D,UAAI,CAACrE,EAAO;AAEZ,YAAM8Q,IAAMxC,GAAatO,GAAOkQ,CAAmB;AACnD,UAAI,CAACY,GAAK;AACT,QAAAN,EAAmB,IAAI;AACvB;AAAA,MACD;AAEA,UAAIW,IAAqCL,EAAI;AAC7C,MAAI9P,MAAmB,SACtBmQ,IACC,OAAOnQ,CAAc,MAAM,OAAO8P,EAAI,QAAQ,IAAI9P,IAAiB,OAErEwP,EAAmBW,CAAU,GAC7BhC,KAAgB;AAAA,QACf,QAAQ2B,EAAI;AAAA,QACZ,UAAUA,EAAI;AAAA,QACd,aAAaA,EAAI;AAAA,QACjB,YAAY9Q;AAAA,MAAA,CACZ;AAAA,IACF;AAAA,IACA;AAAA,MACCiP;AAAA,MACAiB;AAAA,MACAU;AAAA,MACAzB;AAAA,MACAnO;AAAA,MACAwP;AAAA,IAAA;AAAA,EACD;AAGD,SAAArL,EAAU,MAAM;AACf,UAAM3P,IAAS4L,EAAU;AACzB,QAAI,CAAC5L,KAAU,CAACb;AACf;AAGD,UAAM+U,IAAW,IAAIsB,GAAgBxV,GAAQb,GAAQ;AAAA,MACpD,mBAAmB+b;AAAA,MACnB,SAAAhC;AAAA,MACA,WAAArI;AAAA,IAAA,CACA;AAED,WAAAoD,EAAY,UAAUC,GAClBtS,KACHsS,EAAS,aAAatS,CAAS,GAEhCsS,EAAS,mBAAmBsF,CAAe,GAEpC,MAAM;AACZ,MAAAtF,EAAS,QAAA,GACTD,EAAY,UAAU;AAAA,IACvB;AAAA,EACD,GAAG,CAAC9U,GAAQ+Z,GAASrI,GAAWqK,CAAmB,CAAC,GAEpDvL,EAAU,MAAM;AACf,UAAMuE,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAACtS,KAGlBsS,EAAS,aAAatS,CAAS;AAAA,EAChC,GAAG,CAACA,CAAS,CAAC,GAEd+N,EAAU,MAAM;AACf,UAAMuE,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,WAAA;AAAA,EACV,GAAG,CAACiF,CAAQ,CAAC,GAEbxJ,EAAU,MAAM;AACf,UAAMuE,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAACkF,KAGlBlF,EAAS,gBAAgBkF,CAAY;AAAA,EACtC,GAAG,CAACA,CAAY,CAAC,GAEjBzJ,EAAU,MAAM;AACf,UAAMuE,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,aAAa0G,EAAe;AAAA,EACtC,GAAG,CAACA,EAAe,CAAC,GAEpBjL,EAAU,MAAM;AACf,UAAMuE,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,mBAAmBsF,CAAe;AAAA,EAC5C,GAAG,CAACA,CAAe,CAAC,GAGnB,gBAAAoC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAAjQ;AAAA,MACA,OAAOgB;AAAA,MACP,eAAe0O;AAAA,MACf,gBAAgBI;AAAA,MAChB,SAASC;AAAA,MAET,UAAA;AAAA,QAAA,gBAAA5L;AAAA,UAAC;AAAA,UAAA;AAAA,YACA,KAAKlE;AAAA,YACL,WAAU;AAAA,YACV,OAAO;AAAA,cACN,UAAU;AAAA,cACV,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,aAAa;AAAA,cACb,QACC6N,MAAa,YAAYlO,OAAoB,OAC1C,YACAiO,IACC,cACA;AAAA,YAAA;AAAA,UACN;AAAA,QAAA;AAAA,QAEAra,IACA,gBAAA2Q;AAAA,UAAClF;AAAA,UAAA;AAAA,YACA,MAAM6O;AAAA,YACN,SAASA,MAAa;AAAA,YACtB,YAAYta,EAAO;AAAA,YACnB,aAAaA,EAAO;AAAA,YACpB,UAAUA,EAAO;AAAA,YACjB,WAAWA,EAAO;AAAA,YAClB,cAAA0L;AAAA,YACA,cAAcoJ;AAAA,YACd,iBAAiBrS;AAAA,YACjB,kBAAkB8Y;AAAA,YAClB,mBAAAtP;AAAA,YACA,wBAAAC;AAAA,YACA,yBAAAC;AAAA,YACA,iBAAAC;AAAA,YACA,gBAAAC;AAAA,YACA,kBAAAC;AAAA,YACA,eAAesO;AAAA,YACf,gBAAAhP;AAAA,UAAA;AAAA,QAAA,IAEE;AAAA,QACH5L,KAAU0a,KACVK,KACC,gBAAA0B,GAAAC,IAAA,EACC,UAAA;AAAA,UAAA,gBAAA/L;AAAA,YAACc;AAAA,YAAA;AAAA,cACA,QAAAzR;AAAA,cACA,cAAc8U;AAAA,cACd,WAAApD;AAAA,cACA,SAASiJ;AAAA,cACT,eAAeE;AAAA,YAAA;AAAA,UAAA;AAAA,UAEhB,gBAAAlK;AAAA,YAAC;AAAA,YAAA;AAAA,cACA,MAAK;AAAA,cACL,cAAW;AAAA,cACX,SAAS,MAAMqK,GAAkB,EAAK;AAAA,cACtC,OAAO;AAAA,gBACN,UAAU;AAAA,gBACV,QAAQ;AAAA,gBACR,GAAIY,EAAiB,SAAS,MAAM,IACjC,EAAE,MAAMD,EAAA,IACR,EAAE,OAAOA,EAAA;AAAA,gBACZ,GAAIC,EAAiB,SAAS,KAAK,IAChC,EAAE,KAAKD,IAAiBD,IAAiB,MACzC,EAAE,QAAQC,IAAiBD,IAAiB,EAAA;AAAA,gBAC/C,OAAO;AAAA,gBACP,QAAQ;AAAA,gBACR,cAAc;AAAA,gBACd,QAAQ;AAAA,gBACR,YAAY;AAAA,gBACZ,OAAO;AAAA,gBACP,UAAU;AAAA,gBACV,YAAY;AAAA,gBACZ,QAAQ;AAAA,gBACR,SAAS;AAAA,cAAA;AAAA,cAEV,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,EAAA,CACD,IAEA,gBAAA/K;AAAA,UAAC;AAAA,UAAA;AAAA,YACA,MAAK;AAAA,YACL,cAAW;AAAA,YACX,SAAS,MAAMqK,GAAkB,EAAI;AAAA,YACrC,OAAO;AAAA,cACN,UAAU;AAAA,cACV,QAAQ;AAAA,cACR,GAAIY,EAAiB,SAAS,MAAM,IACjC,EAAE,MAAMD,EAAA,IACR,EAAE,OAAOA,EAAA;AAAA,cACZ,GAAIC,EAAiB,SAAS,KAAK,IAChC,EAAE,KAAKD,EAAA,IACP,EAAE,QAAQA,EAAA;AAAA,cACb,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,cAAc;AAAA,cACd,QAAQ;AAAA,cACR,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,QAAQ;AAAA,cACR,SAAS;AAAA,YAAA;AAAA,YAEV,UAAA;AAAA,UAAA;AAAA,QAAA,IAIC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP;"}
@@ -0,0 +1,4 @@
1
+ export declare function createProgram(gl: WebGL2RenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram;
2
+ export declare function requireUniformLocation(gl: WebGL2RenderingContext, program: WebGLProgram, uniformName: string): WebGLUniformLocation;
3
+ export declare function requireWebGL2(canvas: HTMLCanvasElement): WebGL2RenderingContext;
4
+ //# sourceMappingURL=gl-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gl-utils.d.ts","sourceRoot":"","sources":["../../../src/core/gl-utils.ts"],"names":[],"mappings":"AAmBA,wBAAgB,aAAa,CAAC,EAAE,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,YAAY,CA0BpH;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,sBAAsB,EAC1B,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,MAAM,GAClB,oBAAoB,CAMtB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,sBAAsB,CAe/E"}
@@ -0,0 +1,42 @@
1
+ import { type ViewState } from "./ortho-camera";
2
+ import type { TileDefinition } from "./types";
3
+ export interface M1TileRendererOptions {
4
+ canvas: HTMLCanvasElement;
5
+ imageWidth: number;
6
+ imageHeight: number;
7
+ clearColor?: [number, number, number, number];
8
+ initialViewState?: Partial<ViewState>;
9
+ }
10
+ export declare class M1TileRenderer {
11
+ private readonly canvas;
12
+ private readonly gl;
13
+ private readonly camera;
14
+ private readonly imageWidth;
15
+ private readonly imageHeight;
16
+ private readonly clearColor;
17
+ private readonly program;
18
+ private readonly vao;
19
+ private readonly quadBuffer;
20
+ private readonly uCameraLocation;
21
+ private readonly uBoundsLocation;
22
+ private readonly uTextureLocation;
23
+ private readonly resizeObserver;
24
+ private tiles;
25
+ private frameId;
26
+ private loadVersion;
27
+ private destroyed;
28
+ private fitted;
29
+ private controlledViewState;
30
+ constructor(options: M1TileRendererOptions);
31
+ setTiles(tiles: TileDefinition[]): Promise<void>;
32
+ setViewState(viewState: Partial<ViewState>): void;
33
+ getViewState(): ViewState;
34
+ destroy(): void;
35
+ private loadTile;
36
+ private resize;
37
+ private fitToImage;
38
+ private requestRender;
39
+ private render;
40
+ private disposeTiles;
41
+ }
42
+ //# sourceMappingURL=m1-tile-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"m1-tile-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/m1-tile-renderer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAU,cAAc,EAAE,MAAM,SAAS,CAAC;AAQtD,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;CACtC;AAqCD,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuB;IACvD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuB;IACvD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAuB;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAEhD,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,mBAAmB,CAAS;gBAExB,OAAO,EAAE,qBAAqB;IAqFpC,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BtD,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;IAMjD,YAAY,IAAI,SAAS;IAIzB,OAAO,IAAI,IAAI;YAsBD,QAAQ;IAsEtB,OAAO,CAAC,MAAM;IAgCd,OAAO,CAAC,UAAU;IAsBlB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,MAAM;IAuCd,OAAO,CAAC,YAAY;CAKpB"}
@@ -0,0 +1,19 @@
1
+ export interface ViewState {
2
+ offsetX: number;
3
+ offsetY: number;
4
+ zoom: number;
5
+ }
6
+ export declare class OrthoCamera {
7
+ private viewportWidth;
8
+ private viewportHeight;
9
+ private viewState;
10
+ setViewport(width: number, height: number): void;
11
+ getViewportSize(): {
12
+ width: number;
13
+ height: number;
14
+ };
15
+ setViewState(next: Partial<ViewState>): void;
16
+ getViewState(): ViewState;
17
+ getMatrix(): Float32Array;
18
+ }
19
+ //# sourceMappingURL=ortho-camera.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ortho-camera.d.ts","sourceRoot":"","sources":["../../../src/core/ortho-camera.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,cAAc,CAAK;IAE3B,OAAO,CAAC,SAAS,CAIf;IAEF,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAKhD,eAAe,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAOpD,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;IAc5C,YAAY,IAAI,SAAS;IAIzB,SAAS,IAAI,YAAY;CAqB1B"}
@@ -0,0 +1,7 @@
1
+ export type Bounds = [number, number, number, number];
2
+ export interface TileDefinition {
3
+ id: string;
4
+ url: string;
5
+ bounds: Bounds;
6
+ }
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,18 @@
1
+ export { M1TileRenderer } from "./core/m1-tile-renderer";
2
+ export type { ViewState } from "./core/ortho-camera";
3
+ export type { Bounds, TileDefinition } from "./core/types";
4
+ export type { DrawBounds, DrawCoordinate, DrawProjector, DrawRegion, DrawResult, DrawTool, RegionLabelStyle, RegionStrokeStyle, StampDrawTool, StampOptions, } from "./react/draw-layer";
5
+ export { closeRing, createCircle, createRectangle, DrawLayer, } from "./react/draw-layer";
6
+ export type { OverviewMapOptions, OverviewMapPosition } from "./react/overview-map";
7
+ export { OverviewMap } from "./react/overview-map";
8
+ export { TileViewerCanvas } from "./react/tile-viewer-canvas";
9
+ export type { RegionClickEvent, RegionHoverEvent, WsiViewerCanvasProps, } from "./react/wsi-viewer-canvas";
10
+ export { WsiViewerCanvas } from "./react/wsi-viewer-canvas";
11
+ export { DEFAULT_POINT_COLOR } from "./wsi/constants";
12
+ export { normalizeImageInfo, toTileUrl } from "./wsi/image-info";
13
+ export type { RoiCoordinate, RoiPolygon } from "./wsi/point-clip";
14
+ export { filterPointDataByPolygons } from "./wsi/point-clip";
15
+ export type { TermPalette, WsiCoordinate, WsiImageSource, WsiPointData, WsiRegion, WsiRenderStats, WsiTerm, WsiViewState, } from "./wsi/types";
16
+ export { buildTermPalette, calcScaleLength, calcScaleResolution, clamp, hexToRgba, isSameViewState, toBearerToken, } from "./wsi/utils";
17
+ export { WsiTileRenderer } from "./wsi/wsi-tile-renderer";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC3D,YAAY,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACb,UAAU,EACV,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,eAAe,EACf,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACZ,SAAS,EACT,cAAc,EACd,OAAO,EACP,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,KAAK,EACL,SAAS,EACT,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC"}