@seatlayer/core 0.51.0 → 0.53.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.
- package/LICENSE +16 -17
- package/README.md +8 -18
- package/dist/chunk-54A7LIL5.js +1 -0
- package/dist/chunk-IJI4WU57.js +1 -0
- package/dist/chunk-XPPT3OGQ.js +1 -0
- package/dist/core/seatConfidence.cjs +1 -76
- package/dist/core/seatConfidence.d.cts +1 -1
- package/dist/core/seatConfidence.d.ts +1 -1
- package/dist/core/seatConfidence.js +1 -51
- package/dist/de-75NWRKC5.js +1 -0
- package/dist/es-BM7EJ7PW.js +1 -0
- package/dist/fr-HPXQHIB4.js +1 -0
- package/dist/index.cjs +1 -12130
- package/dist/index.d.cts +169 -70
- package/dist/index.d.ts +169 -70
- package/dist/index.js +1 -9718
- package/dist/picker/minimapGeometry.cjs +1 -0
- package/dist/picker/minimapGeometry.d.cts +37 -0
- package/dist/picker/minimapGeometry.d.ts +37 -0
- package/dist/picker/minimapGeometry.js +1 -0
- package/dist/{types-DR54nqKL.d.cts → types-tLOunI-B.d.cts} +131 -1
- package/dist/{types-DR54nqKL.d.ts → types-tLOunI-B.d.ts} +131 -1
- package/dist/view/panoramaDelivery.cjs +1 -126
- package/dist/view/panoramaDelivery.js +1 -17
- package/dist/view3d/crossfade/panorama.cjs +1 -459
- package/dist/view3d/crossfade/panorama.d.cts +2 -4
- package/dist/view3d/crossfade/panorama.d.ts +2 -4
- package/dist/view3d/crossfade/panorama.js +1 -30
- package/dist/view3d/index.cjs +63 -6930
- package/dist/view3d/index.d.cts +82 -33
- package/dist/view3d/index.d.ts +82 -33
- package/dist/view3d/index.js +63 -6062
- package/package.json +15 -7
- package/dist/chunk-AZODENEL.js +0 -97
- package/dist/chunk-AZODENEL.js.map +0 -1
- package/dist/chunk-BE3F7CT3.js +0 -341
- package/dist/chunk-BE3F7CT3.js.map +0 -1
- package/dist/chunk-GD267BFB.js +0 -1496
- package/dist/chunk-GD267BFB.js.map +0 -1
- package/dist/core/seatConfidence.cjs.map +0 -1
- package/dist/core/seatConfidence.js.map +0 -1
- package/dist/de-V53JPFHN.js +0 -292
- package/dist/de-V53JPFHN.js.map +0 -1
- package/dist/es-37ISLCZA.js +0 -292
- package/dist/es-37ISLCZA.js.map +0 -1
- package/dist/fr-QKK2T64Q.js +0 -292
- package/dist/fr-QKK2T64Q.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/view/panoramaDelivery.cjs.map +0 -1
- package/dist/view/panoramaDelivery.js.map +0 -1
- package/dist/view3d/crossfade/panorama.cjs.map +0 -1
- package/dist/view3d/crossfade/panorama.js.map +0 -1
- package/dist/view3d/index.cjs.map +0 -1
- package/dist/view3d/index.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/view/panoramaDelivery.ts"],"sourcesContent":["/** Progressive delivery policy shared by the WebGL and DOM panorama viewers. */\n\nexport interface PanoramaDeliverySource {\n url: string;\n previewUrl?: string;\n sourceWidth?: number;\n sourceHeight?: number;\n previewWidth?: number;\n previewHeight?: number;\n}\n\nexport interface PanoramaDeliveryConstraints {\n saveData?: boolean;\n maxTextureSize?: number;\n maxDecodedBytes?: number;\n}\n\nexport interface PanoramaDeliveryPlan {\n initialUrl: string;\n upgradeUrl?: string;\n initialWidth?: number;\n initialHeight?: number;\n reason: 'full-only' | 'progressive' | 'save-data' | 'texture-limit' | 'memory-limit';\n}\n\n/** Approximate GPU allocation including a complete mip chain (4/3 overhead). */\nexport function estimatePanoramaTextureBytes(width: number, height: number): number {\n if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return 0;\n return Math.ceil(width * height * 4 * (4 / 3));\n}\n\n/** Conservative per-panorama budget, raised only on devices reporting ample RAM. */\nexport function panoramaTextureBudgetBytes(deviceMemoryGb?: number): number {\n const mib = deviceMemoryGb !== undefined && deviceMemoryGb <= 2\n ? 32\n : deviceMemoryGb !== undefined && deviceMemoryGb >= 8\n ? 192\n : 96;\n return mib * 1024 * 1024;\n}\n\nexport function browserPanoramaConstraints(maxTextureSize?: number): PanoramaDeliveryConstraints {\n const nav = typeof navigator === 'undefined'\n ? undefined\n : navigator as Navigator & { deviceMemory?: number; connection?: { saveData?: boolean } };\n return {\n saveData: nav?.connection?.saveData === true,\n maxTextureSize,\n maxDecodedBytes: panoramaTextureBudgetBytes(nav?.deviceMemory),\n };\n}\n\n/** Select the first image and whether a later sharp-image upgrade is safe. */\nexport function planPanoramaDelivery(\n source: PanoramaDeliverySource,\n constraints: PanoramaDeliveryConstraints = {},\n): PanoramaDeliveryPlan {\n const previewUrl = source.previewUrl?.trim();\n if (!previewUrl || previewUrl === source.url) {\n return {\n initialUrl: source.url,\n initialWidth: source.sourceWidth,\n initialHeight: source.sourceHeight,\n reason: 'full-only',\n };\n }\n\n const initial = {\n initialUrl: previewUrl,\n initialWidth: source.previewWidth,\n initialHeight: source.previewHeight,\n };\n if (constraints.saveData) return { ...initial, reason: 'save-data' };\n if (constraints.maxTextureSize !== undefined && source.sourceWidth !== undefined && source.sourceHeight !== undefined\n && Math.max(source.sourceWidth, source.sourceHeight) > constraints.maxTextureSize) {\n return { ...initial, reason: 'texture-limit' };\n }\n if (constraints.maxDecodedBytes !== undefined && source.sourceWidth !== undefined && source.sourceHeight !== undefined\n && estimatePanoramaTextureBytes(source.sourceWidth, source.sourceHeight) > constraints.maxDecodedBytes) {\n return { ...initial, reason: 'memory-limit' };\n }\n return { ...initial, upgradeUrl: source.url, reason: 'progressive' };\n}\n\nfunction abortError(): DOMException {\n return new DOMException('Panorama image load aborted', 'AbortError');\n}\n\n/** Decode before resolving so callers never upload or reveal a partial image. */\nexport function loadPanoramaImage(url: string, signal?: AbortSignal): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) { reject(abortError()); return; }\n const image = new Image();\n image.crossOrigin = 'anonymous';\n let settled = false;\n const cleanup = (): void => {\n image.onload = null;\n image.onerror = null;\n signal?.removeEventListener('abort', onAbort);\n };\n const finish = (error?: unknown): void => {\n if (settled) return;\n settled = true;\n cleanup();\n if (error) reject(error);\n else resolve(image);\n };\n const onAbort = (): void => {\n image.src = '';\n finish(abortError());\n };\n image.onload = () => {\n const decoded = typeof image.decode === 'function' ? image.decode() : Promise.resolve();\n void decoded.then(() => finish(), () => finish());\n };\n image.onerror = () => finish(new Error('panorama_image_failed'));\n signal?.addEventListener('abort', onAbort, { once: true });\n image.src = url;\n });\n}\n\n/** Let the preview paint before starting a potentially large decode. */\nexport function schedulePanoramaUpgrade(work: () => void): () => void {\n const host = globalThis as typeof globalThis & {\n requestIdleCallback?: (cb: () => void, opts?: { timeout: number }) => number;\n cancelIdleCallback?: (id: number) => void;\n };\n if (host.requestIdleCallback) {\n const id = host.requestIdleCallback(work, { timeout: 1200 });\n return () => host.cancelIdleCallback?.(id);\n }\n const id = globalThis.setTimeout(work, 32);\n return () => globalThis.clearTimeout(id);\n}\n"],"mappings":"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","names":["id"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/view3d/crossfade/panorama.ts","../../../src/view/panoramaDelivery.ts"],"sourcesContent":["/**\n * Slice 3 hand-off — the DOM panorama overlay the fly-to-seat cinematic\n * dissolves into. Decoupled by design: the CALLER supplies the equirectangular\n * image (via mountVenue3D's getSeatView), so view3d never imports the app's\n * panorama generator and the chunk stays lean.\n *\n * Technique (mirrors SeatPicker.openSeatView, reimplemented small): an equirect\n * image panned with `repeat-x`; the initial horizontal offset is set so the\n * panorama's bearing matches the final camera yaw — the dissolve reads as the\n * same view sharpening, not a cut. CSS opacity fade is compositor-only.\n */\n\nimport type { SeatViewCoverage } from '../../core/types';\nimport {\n browserPanoramaConstraints,\n loadPanoramaImage,\n planPanoramaDelivery,\n schedulePanoramaUpgrade,\n} from '../../view/panoramaDelivery';\n\nexport interface SeatView {\n url: string;\n /** Lightweight equirect used for first paint before `url` replaces it. */\n previewUrl?: string;\n /**\n * Optional authenticated byte-to-object-URL resolver. The buyer picker uses\n * this for a deferred sharp-image upgrade so progressive view media never\n * needs a bearer in its URL.\n */\n resolveUrl?: (url: string) => Promise<string | null>;\n sourceWidth?: number;\n sourceHeight?: number;\n previewWidth?: number;\n previewHeight?: number;\n /**\n * True when `url` is a SYNTHESISED panorama rather than a real photograph.\n *\n * It decides which of two very different things the buyer gets, so the caller\n * must say rather than the renderer guess. A generated equirect is a picture\n * of a 3D scene the renderer already has: at 2048×1024 it covers 106° of\n * horizontal view in ~600 source pixels, which a 3072-device-pixel viewport\n * magnifies FIVE times, and no amount of art survives that. So a generated\n * view is not drawn as an image at all — the camera simply looks around the\n * real scene, which has no resolution ceiling.\n *\n * A real photo has no such substitute and goes on the sphere, where a 5760 or\n * 8192-wide capture has three to four times the detail to give.\n */\n generated?: boolean;\n /** Explicit media provenance; avoids inferring buyer truth from source copy. */\n mediaKind?: 'photo' | 'demo-render' | 'model';\n /** Bearing (deg, 0 = facing the focal/stage) the panorama should open centred\n * on, to match the camera's final yaw. Default 0 (both face the stage). */\n initialBearingDeg?: number;\n /** Initial vertical orientation. Positive looks up; clamped to the viewer's\n * safe pitch range. Uploaded captures use this to match the live seat pose. */\n initialPitchDeg?: number;\n /** How specifically this image represents the selected inventory unit. */\n coverage?: SeatViewCoverage;\n /** ISO capture date/time when known. Unknown is preferable to invented age. */\n capturedAt?: string;\n /** Optional buyer-safe provenance, for example \"Provided by the venue\". */\n sourceLabel?: string;\n}\n\n/** Honest, compact buyer disclosure for the panorama currently on screen. */\nexport function seatViewDisclosure(view: SeatView): string {\n const demo = view.mediaKind === 'demo-render';\n const coverage = view.generated || view.mediaKind === 'model'\n ? 'Live 3D · chart-derived seat-eye'\n : demo\n ? view.coverage === 'exact-seat'\n ? 'AI-generated exact-seat demo'\n : view.coverage === 'row-representative'\n ? 'AI-generated representative row demo'\n : view.coverage === 'section-representative'\n ? 'AI-generated representative section demo'\n : 'AI-generated illustrative venue demo'\n : view.coverage === 'exact-seat'\n ? 'Exact seat photo'\n : view.coverage === 'row-representative'\n ? 'Representative row view'\n : view.coverage === 'section-representative'\n ? 'Representative section view'\n : view.coverage === 'venue-representative'\n ? 'Representative venue view'\n : 'Venue photo';\n const year = view.capturedAt && /^\\d{4}/.test(view.capturedAt) ? view.capturedAt.slice(0, 4) : '';\n return [coverage, year ? `${demo ? 'created' : 'captured'} ${year}` : '', view.sourceLabel ?? ''].filter(Boolean).join(' · ');\n}\n\n/** True only when the panorama should be presented as organizer-authored media.\n * Representative AI demo assets travel through the same URL field as venue\n * photos, so provenance—not URL presence—must decide the buyer badge. */\nexport function isAuthoredSeatView(view: SeatView): boolean {\n if (view.generated || view.mediaKind === 'model' || view.mediaKind === 'demo-render') return false;\n const source = view.sourceLabel?.trim() ?? '';\n return !/^(?:AI[- ]generated|generated\\s+(?:demo|preview))/i.test(source);\n}\n\nexport interface PanoramaHandle {\n /** Fade out and return to the (frozen) 3D view; calls opts.onClose after. */\n close(): void;\n /** Immediate teardown (dispose) — no fade, no onClose. */\n dispose(): void;\n}\n\n/**\n * Vertical field of view (deg) the windowed panorama shows. The source image is\n * a full 180° equirect sphere; showing it raw wastes ~⅔ of the frame on dead sky\n * and black floor, with the horizon content band squished into the middle. We\n * instead scale the image so only this central slice fills the viewport height,\n * horizon-centred, and let the user drag pitch within ±`MAX_PITCH_DEG`.\n */\nexport const VFOV_DEG = 70;\nexport const MIN_VFOV_DEG = 35;\nexport const MAX_VFOV_DEG = 90;\n\n/** Keep wheel, keyboard and pinch zoom inside a useful, non-disorienting range. */\nexport function clampPanoramaFov(fovDeg: number): number {\n return Math.max(MIN_VFOV_DEG, Math.min(MAX_VFOV_DEG, fovDeg));\n}\n/** Users may look this far up/down from the horizon; well inside the image so\n * the clamp never reveals past its top/bottom edge. */\nexport const MAX_PITCH_DEG = 35;\n\n/**\n * Horizontal background-position (px) that centres `bearingDeg` in the viewport,\n * assuming the equirect image's yaw 0 sits at its horizontal centre. `bgW` is the\n * full scaled image width representing 360° — so this is invariant to the vertical\n * FOV windowing (which scales width and height by the same factor). `repeat-x`\n * handles the wrap, so any real value is valid.\n */\nexport function bearingToOffsetPx(bearingDeg: number, viewportW: number, bgW: number): number {\n const col = (0.5 + bearingDeg / 360) * bgW; // image column (px) for the bearing\n return viewportW / 2 - col;\n}\n\n/**\n * Full scaled image height (px) so that a `vfovDeg`-tall slice fills `viewportH`.\n * The image spans 180° vertically, so height = viewportH · 180/vfov.\n */\nexport function windowedBgHeight(viewportH: number, vfovDeg: number = VFOV_DEG): number {\n return viewportH * (180 / vfovDeg);\n}\n\n/**\n * background-position Y (px) that centres the image's horizon (its vertical\n * centre) in the viewport, offset by `pitchPx` (deviation from the horizon,\n * clamped to ±`MAX_PITCH_DEG`). Positive `pitchPx` looks up.\n */\nexport function horizonOffsetPy(viewportH: number, bgH: number, pitchPx: number): number {\n return (viewportH - bgH) / 2 + clampPitchPx(pitchPx, bgH);\n}\n\n/** Clamp a pitch drag (px) to ±MAX_PITCH_DEG of image travel, and never past the\n * image edge. `bgH` px map the full 180°, so a degree is `bgH/180` px. */\nexport function clampPitchPx(pitchPx: number, bgH: number): number {\n const limit = (MAX_PITCH_DEG / 180) * bgH;\n return Math.max(-limit, Math.min(limit, pitchPx));\n}\n\nexport interface PanoramaOptions {\n fadeMs?: number;\n seatLabel?: string;\n disclosure?: string;\n /** Prefix for the disclosure chip; generated live geometry is not a panorama. */\n disclosurePrefix?: string;\n onClose?: () => void;\n /** Cancels stale preview/full-resolution image work when a flight is retargeted. */\n signal?: AbortSignal;\n}\n\nexport function mountPanorama(container: HTMLElement, view: SeatView, opts: PanoramaOptions = {}): PanoramaHandle {\n const fadeMs = opts.fadeMs ?? 400;\n const bearing = view.initialBearingDeg ?? 0;\n\n const delivery = planPanoramaDelivery(view, browserPanoramaConstraints());\n const loadAbort = new AbortController();\n const abortFromCaller = (): void => loadAbort.abort();\n opts.signal?.addEventListener('abort', abortFromCaller, { once: true });\n const root = document.createElement('div');\n const priorFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n root.setAttribute('role', 'dialog');\n root.setAttribute('aria-modal', 'true');\n root.setAttribute('aria-label', opts.seatLabel ? `View from ${opts.seatLabel}` : 'View from seat');\n root.tabIndex = -1;\n Object.assign(root.style, {\n position: 'absolute', inset: '0', zIndex: '10', opacity: '0',\n transition: `opacity ${fadeMs}ms ease`, background: '#05070c',\n overflow: 'hidden', touchAction: 'none',\n } as CSSStyleDeclaration);\n\n const pano = document.createElement('div');\n Object.assign(pano.style, {\n position: 'absolute', inset: '0',\n backgroundImage: `url(\"${delivery.initialUrl}\")`, backgroundRepeat: 'repeat-x',\n cursor: 'grab',\n } as CSSStyleDeclaration);\n root.appendChild(pano);\n\n // Close affordance.\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.textContent = '✕';\n Object.assign(closeBtn.style, {\n position: 'absolute', top: '12px', right: '12px', zIndex: '2',\n width: '44px', height: '44px', borderRadius: '999px', cursor: 'pointer',\n border: '1px solid rgba(255,255,255,0.25)', background: 'rgba(8,12,18,0.6)',\n color: '#e6edf3', fontSize: '15px', lineHeight: '1',\n } as CSSStyleDeclaration);\n root.appendChild(closeBtn);\n\n if (opts.disclosure) {\n const disclosure = document.createElement('div');\n disclosure.textContent = `${opts.disclosurePrefix ?? '360° panorama'} · ${opts.disclosure}`;\n Object.assign(disclosure.style, {\n position: 'absolute', top: '12px', left: '12px', zIndex: '2',\n maxWidth: 'calc(100% - 88px)', padding: '8px 11px', borderRadius: '999px',\n overflow: 'hidden', color: '#dce6f8', background: 'rgba(8,12,18,0.68)',\n font: '600 11px/1.2 ui-sans-serif, system-ui, sans-serif', textOverflow: 'ellipsis',\n whiteSpace: 'nowrap', pointerEvents: 'none', backdropFilter: 'blur(6px)',\n } as CSSStyleDeclaration);\n root.appendChild(disclosure);\n }\n\n const hint = document.createElement('div');\n hint.textContent = 'Drag to look · pinch or scroll to zoom · Esc to close';\n Object.assign(hint.style, {\n position: 'absolute', bottom: '12px', left: '0', right: '0', textAlign: 'center',\n color: 'rgba(230,237,243,0.7)', font: '12px ui-sans-serif, system-ui, sans-serif',\n pointerEvents: 'none',\n } as CSSStyleDeclaration);\n root.appendChild(hint);\n\n container.appendChild(root);\n closeBtn.focus({ preventScroll: true });\n\n // Layout: window a ~70° vertical slice of the sphere (horizon-centred) so the\n // venue fills the frame instead of floating in dead sky + black floor. The\n // image is scaled so that slice is exactly the viewport height; width scales by\n // the same factor, so `bearingToOffsetPx` stays correct. `pitchPx` is the\n // vertical drag deviation from the horizon, clamped to ±35°.\n let bgW = 0;\n let bgH = 0;\n let posX = 0;\n let pitchPx = 0;\n let viewFov = VFOV_DEG;\n const layout = (): void => {\n const vh = root.clientHeight || 1;\n const vw = root.clientWidth || 1;\n const natW = img.naturalWidth || vw * 2;\n const natH = img.naturalHeight || vh;\n const centredImageRatio = bgW > 0 ? (vw / 2 - posX) / bgW : 0;\n const pitchRatio = bgH > 0 ? pitchPx / bgH : 0;\n bgH = windowedBgHeight(vh, viewFov);\n bgW = bgH * (natW / natH);\n pano.style.backgroundSize = `${bgW}px ${bgH}px`;\n if (!posInitialised) {\n posX = bearingToOffsetPx(bearing, vw, bgW);\n pitchPx = clampPitchPx(((view.initialPitchDeg ?? 0) / 180) * bgH, bgH);\n posInitialised = true;\n }\n else posX = vw / 2 - centredImageRatio * bgW;\n pitchPx = clampPitchPx(pitchRatio * bgH, bgH);\n pano.style.backgroundPosition = `${posX}px ${horizonOffsetPy(vh, bgH, pitchPx)}px`;\n };\n let posInitialised = false;\n\n const applyPos = (): void => {\n const vh = root.clientHeight || 1;\n pitchPx = clampPitchPx(pitchPx, bgH);\n pano.style.backgroundPosition = `${posX}px ${horizonOffsetPy(vh, bgH, pitchPx)}px`;\n };\n\n let img = new Image();\n img.onload = layout;\n img.src = delivery.initialUrl;\n let cancelUpgrade = (): void => {};\n if (delivery.upgradeUrl) {\n cancelUpgrade = schedulePanoramaUpgrade(() => {\n const resolved = view.resolveUrl\n ? view.resolveUrl(delivery.upgradeUrl!)\n : Promise.resolve(delivery.upgradeUrl!);\n void resolved.then((url) => {\n if (!url || loadAbort.signal.aborted) return null;\n return loadPanoramaImage(url, loadAbort.signal).then((full) => ({ full, url }));\n }).then((loaded) => {\n if (!loaded) return;\n if (disposed || loadAbort.signal.aborted) return;\n img = loaded.full;\n pano.style.backgroundImage = `url(\"${loaded.url}\")`;\n layout();\n }).catch(() => { /* the preview remains usable */ });\n });\n }\n // If it's already cached, onload may not fire — lay out on next frame too.\n requestAnimationFrame(layout);\n\n // Pan: horizontal (repeat-x wraps seamlessly) + vertical pitch (clamped ±35°).\n let dragging = false;\n let lastX = 0;\n let lastY = 0;\n let pinchDistance = 0;\n const pointers = new Map<number, { x: number; y: number }>();\n const distanceBetweenPointers = (): number => {\n const [a, b] = [...pointers.values()];\n return a && b ? Math.hypot(a.x - b.x, a.y - b.y) : 0;\n };\n const setViewFov = (nextFov: number): void => {\n const clamped = clampPanoramaFov(nextFov);\n if (clamped === viewFov) return;\n viewFov = clamped;\n layout();\n };\n const onDown = (e: PointerEvent): void => {\n pointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\n dragging = pointers.size === 1;\n lastX = e.clientX; lastY = e.clientY;\n if (pointers.size === 2) pinchDistance = distanceBetweenPointers();\n pano.style.cursor = 'grabbing';\n try { pano.setPointerCapture?.(e.pointerId); } catch { /* no active pointer */ }\n };\n const onMove = (e: PointerEvent): void => {\n if (!pointers.has(e.pointerId)) return;\n pointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\n if (pointers.size >= 2) {\n const nextDistance = distanceBetweenPointers();\n if (pinchDistance > 0 && nextDistance > 0) setViewFov(viewFov * (pinchDistance / nextDistance));\n pinchDistance = nextDistance;\n dragging = false;\n return;\n }\n if (!dragging) return;\n posX += e.clientX - lastX;\n pitchPx += e.clientY - lastY;\n lastX = e.clientX;\n lastY = e.clientY;\n applyPos();\n };\n const onUp = (e: PointerEvent): void => {\n pointers.delete(e.pointerId);\n pinchDistance = pointers.size === 2 ? distanceBetweenPointers() : 0;\n const remaining = pointers.values().next().value as { x: number; y: number } | undefined;\n dragging = pointers.size === 1;\n if (remaining) { lastX = remaining.x; lastY = remaining.y; }\n else pano.style.cursor = 'grab';\n try { pano.releasePointerCapture?.(e.pointerId); } catch { /* no active pointer */ }\n };\n const onWheel = (e: WheelEvent): void => {\n e.preventDefault();\n setViewFov(viewFov + e.deltaY * 0.04);\n };\n pano.addEventListener('pointerdown', onDown);\n pano.addEventListener('pointermove', onMove);\n pano.addEventListener('pointerup', onUp);\n pano.addEventListener('pointercancel', onUp);\n pano.addEventListener('wheel', onWheel, { passive: false });\n\n let closed = false;\n let disposed = false;\n let fadeTimer = 0;\n const removeListeners = (): void => {\n pano.removeEventListener('pointerdown', onDown);\n pano.removeEventListener('pointermove', onMove);\n pano.removeEventListener('pointerup', onUp);\n pano.removeEventListener('pointercancel', onUp);\n pano.removeEventListener('wheel', onWheel);\n window.removeEventListener('keydown', onKey);\n };\n const teardown = (): void => {\n cancelUpgrade();\n loadAbort.abort();\n opts.signal?.removeEventListener('abort', abortFromCaller);\n if (fadeTimer) { window.clearTimeout(fadeTimer); fadeTimer = 0; }\n removeListeners();\n if (root.parentNode) root.parentNode.removeChild(root);\n if (priorFocus?.isConnected) priorFocus.focus({ preventScroll: true });\n };\n const close = (): void => {\n if (closed) return;\n closed = true;\n root.style.opacity = '0';\n // Guard the fade callback: a dispose() (or a retarget that disposes us) inside\n // the fade window clears the timer AND flips `disposed`, so a stray fire can\n // never call onClose into a newer flight/panorama.\n const done = (): void => {\n fadeTimer = 0;\n if (disposed) return;\n teardown();\n opts.onClose?.();\n };\n fadeTimer = window.setTimeout(done, fadeMs);\n };\n const onKey = (e: KeyboardEvent): void => {\n if (e.key === 'Tab') { e.preventDefault(); closeBtn.focus({ preventScroll: true }); return; }\n if (e.key === 'Escape') { e.stopPropagation(); close(); return; }\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n posX += e.key === 'ArrowLeft' ? -32 : 32;\n } else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n pitchPx += (e.key === 'ArrowUp' ? 4 : -4) * (bgH / 180);\n } else if (e.key === '+' || e.key === '=') {\n setViewFov(viewFov - 5);\n e.preventDefault();\n return;\n } else if (e.key === '-') {\n setViewFov(viewFov + 5);\n e.preventDefault();\n return;\n } else {\n return;\n }\n e.preventDefault();\n applyPos();\n };\n window.addEventListener('keydown', onKey);\n closeBtn.addEventListener('click', close);\n\n // Fade in on the next frame (0 → 1).\n requestAnimationFrame(() => { root.style.opacity = '1'; });\n\n return {\n close,\n dispose(): void { closed = true; disposed = true; teardown(); },\n };\n}\n","/** Progressive delivery policy shared by the WebGL and DOM panorama viewers. */\n\nexport interface PanoramaDeliverySource {\n url: string;\n previewUrl?: string;\n sourceWidth?: number;\n sourceHeight?: number;\n previewWidth?: number;\n previewHeight?: number;\n}\n\nexport interface PanoramaDeliveryConstraints {\n saveData?: boolean;\n maxTextureSize?: number;\n maxDecodedBytes?: number;\n}\n\nexport interface PanoramaDeliveryPlan {\n initialUrl: string;\n upgradeUrl?: string;\n initialWidth?: number;\n initialHeight?: number;\n reason: 'full-only' | 'progressive' | 'save-data' | 'texture-limit' | 'memory-limit';\n}\n\n/** Approximate GPU allocation including a complete mip chain (4/3 overhead). */\nexport function estimatePanoramaTextureBytes(width: number, height: number): number {\n if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return 0;\n return Math.ceil(width * height * 4 * (4 / 3));\n}\n\n/** Conservative per-panorama budget, raised only on devices reporting ample RAM. */\nexport function panoramaTextureBudgetBytes(deviceMemoryGb?: number): number {\n const mib = deviceMemoryGb !== undefined && deviceMemoryGb <= 2\n ? 32\n : deviceMemoryGb !== undefined && deviceMemoryGb >= 8\n ? 192\n : 96;\n return mib * 1024 * 1024;\n}\n\nexport function browserPanoramaConstraints(maxTextureSize?: number): PanoramaDeliveryConstraints {\n const nav = typeof navigator === 'undefined'\n ? undefined\n : navigator as Navigator & { deviceMemory?: number; connection?: { saveData?: boolean } };\n return {\n saveData: nav?.connection?.saveData === true,\n maxTextureSize,\n maxDecodedBytes: panoramaTextureBudgetBytes(nav?.deviceMemory),\n };\n}\n\n/** Select the first image and whether a later sharp-image upgrade is safe. */\nexport function planPanoramaDelivery(\n source: PanoramaDeliverySource,\n constraints: PanoramaDeliveryConstraints = {},\n): PanoramaDeliveryPlan {\n const previewUrl = source.previewUrl?.trim();\n if (!previewUrl || previewUrl === source.url) {\n return {\n initialUrl: source.url,\n initialWidth: source.sourceWidth,\n initialHeight: source.sourceHeight,\n reason: 'full-only',\n };\n }\n\n const initial = {\n initialUrl: previewUrl,\n initialWidth: source.previewWidth,\n initialHeight: source.previewHeight,\n };\n if (constraints.saveData) return { ...initial, reason: 'save-data' };\n if (constraints.maxTextureSize !== undefined && source.sourceWidth !== undefined && source.sourceHeight !== undefined\n && Math.max(source.sourceWidth, source.sourceHeight) > constraints.maxTextureSize) {\n return { ...initial, reason: 'texture-limit' };\n }\n if (constraints.maxDecodedBytes !== undefined && source.sourceWidth !== undefined && source.sourceHeight !== undefined\n && estimatePanoramaTextureBytes(source.sourceWidth, source.sourceHeight) > constraints.maxDecodedBytes) {\n return { ...initial, reason: 'memory-limit' };\n }\n return { ...initial, upgradeUrl: source.url, reason: 'progressive' };\n}\n\nfunction abortError(): DOMException {\n return new DOMException('Panorama image load aborted', 'AbortError');\n}\n\n/** Decode before resolving so callers never upload or reveal a partial image. */\nexport function loadPanoramaImage(url: string, signal?: AbortSignal): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) { reject(abortError()); return; }\n const image = new Image();\n image.crossOrigin = 'anonymous';\n let settled = false;\n const cleanup = (): void => {\n image.onload = null;\n image.onerror = null;\n signal?.removeEventListener('abort', onAbort);\n };\n const finish = (error?: unknown): void => {\n if (settled) return;\n settled = true;\n cleanup();\n if (error) reject(error);\n else resolve(image);\n };\n const onAbort = (): void => {\n image.src = '';\n finish(abortError());\n };\n image.onload = () => {\n const decoded = typeof image.decode === 'function' ? image.decode() : Promise.resolve();\n void decoded.then(() => finish(), () => finish());\n };\n image.onerror = () => finish(new Error('panorama_image_failed'));\n signal?.addEventListener('abort', onAbort, { once: true });\n image.src = url;\n });\n}\n\n/** Let the preview paint before starting a potentially large decode. */\nexport function schedulePanoramaUpgrade(work: () => void): () => void {\n const host = globalThis as typeof globalThis & {\n requestIdleCallback?: (cb: () => void, opts?: { timeout: number }) => number;\n cancelIdleCallback?: (id: number) => void;\n };\n if (host.requestIdleCallback) {\n const id = host.requestIdleCallback(work, { timeout: 1200 });\n return () => host.cancelIdleCallback?.(id);\n }\n const id = globalThis.setTimeout(work, 32);\n return () => globalThis.clearTimeout(id);\n}\n"],"mappings":"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","names":["id"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|