@ericchen1990/pano-view 3.10.0 → 4.0.1
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/README.md +109 -41
- package/README.zh-CN.md +94 -33
- package/dist/data.cjs +64 -17
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.mts +24 -12
- package/dist/data.d.ts +24 -12
- package/dist/data.mjs +64 -17
- package/dist/data.mjs.map +1 -1
- package/dist/index.cjs +455 -196
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +88 -45
- package/dist/index.d.ts +88 -45
- package/dist/index.mjs +450 -196
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +79 -74
- package/docs/dialogs.md +1 -1
- package/docs/dialogs.zh-CN.md +1 -1
- package/package.json +1 -1
package/dist/data.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/data.ts","../src/data/errors.ts","../../../shared/viewer-config.ts","../src/tile/multires.ts","../src/data/viewer.ts","../src/view-limits.ts","../src/data/popups.ts","../../../shared/cursor-assets.ts","../src/data/hotspots.ts","../src/data/map.ts","../src/data/project.ts"],"sourcesContent":["export { PanoDataError } from \"./data/errors\";\nexport type { PanoDataErrorCode } from \"./data/errors\";\nexport { sceneFromViewerConfig, loadSceneFromJson } from \"./data/viewer\";\nexport type {\n AssetUrlContext,\n AssetUrlResolver,\n JsonRequestOptions,\n SceneFromViewerConfigOptions,\n LoadSceneFromJsonOptions,\n} from \"./data/viewer\";\nexport { parsePanoProject, loadPanoProject } from \"./data/project\";\nexport type {\n PanoProjectDefinition,\n PanoProjectSceneDefinition,\n LoadedPanoProject,\n LoadedProjectScene,\n LoadPanoProjectOptions,\n} from \"./data/project\";\nexport type { ProjectHotspotDefinition, ProjectHotspotAction, ProjectHotspotTrigger, ProjectCustomHotspotAction, JsonObject, JsonValue } from \"./data/hotspots\";\nexport { resolveHotspotAssets as resolveProjectHotspotAssets } from \"./data/hotspots\";\nexport type {\n ViewerConfig,\n ViewerDocument,\n CubemapViewerConfig,\n SphereViewerConfig,\n} from \"../../../shared/viewer-config\";\n\nexport { resolveProjectPopupAssets } from \"./data/popups\";\nexport type { ProjectPopupDefinition, ProjectPopupBlock, PopupAssetUrlContext, PopupAssetUrlResolver } from \"./data/popups\";\n\nexport { parsePanoMap, resolvePanoMapAssets } from \"./data/map\";\nexport type {\n PanoMapDefinition,\n PanoMapSpotDefinition,\n PanoMapSectorDefinition,\n PanoMapSectorGradient,\n PanoMapGradientStop,\n PanoMapControlsDefinition,\n PanoMapPresentation,\n PanoMapDockedPresentation,\n PanoMapDialogPresentation,\n PanoMapCorner,\n PanoDragMotion,\n} from \"./data/map\";\n\nexport type { PanoViewLimits } from \"./view-limits\";\n\nexport { hotspotAction, setHotspotAction, projectHotspotTriggers } from \"./data/hotspots\";\n","export type PanoDataErrorCode =\n | \"INVALID_OPTIONS\"\n | \"FETCH_FAILED\"\n | \"HTTP_ERROR\"\n | \"INVALID_JSON\"\n | \"INVALID_CONFIG\"\n | \"UNSUPPORTED_SCHEMA_VERSION\"\n | \"UNSUPPORTED_PROJECTION\"\n | \"INVALID_PROJECT\"\n | \"INVALID_REFERENCE\"\n | \"ABORTED\";\n\nexport class PanoDataError extends Error {\n readonly code: PanoDataErrorCode;\n readonly status?: number;\n readonly sceneId?: string;\n readonly field?: string;\n readonly cause?: unknown;\n constructor(\n code: PanoDataErrorCode,\n message: string,\n details: {\n status?: number;\n sceneId?: string;\n field?: string;\n cause?: unknown;\n } = {}\n ) {\n super(message);\n this.name = \"PanoDataError\";\n this.code = code;\n Object.assign(this, details);\n }\n}\n\nexport function aborted(signal?: AbortSignal | null): void {\n if (signal?.aborted)\n throw new PanoDataError(\"ABORTED\", \"Loading was cancelled\");\n}\n","/** The portable rendering contract shared by the converter and browser viewer. */\nexport type ViewerCubeFace = \"f\" | \"r\" | \"b\" | \"l\" | \"u\" | \"d\";\nexport type CubemapViewerConfig = {\n type: \"tile\";\n multires: { tileSize: number; levels: number[] };\n urlTemplate: string;\n previewUrl: string;\n previewFaceOrder: ViewerCubeFace[];\n};\nexport type SphereViewerConfig = {\n type: \"sphereTile\";\n multires: { tileSize: number; levels: { width: number; height: number }[] };\n urlTemplate: string;\n previewUrl: string;\n indexBase: 0 | 1;\n};\nexport type ViewerConfig = CubemapViewerConfig | SphereViewerConfig;\nexport type ViewerDocument = ViewerConfig & { schemaVersion: 1 };\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function requiredString(value: unknown, field: string): string {\n if (typeof value !== \"string\" || !value.trim())\n throw new Error(`${field}: expected a nonempty string`);\n return value;\n}\n\nfunction positive(value: unknown, field: string): number {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value <= 0)\n throw new Error(`${field}: expected a positive safe integer`);\n return value;\n}\n\nexport function validateViewerConfig(value: unknown): ViewerConfig {\n if (!isRecord(value)) throw new Error(\"viewerConfig: expected an object\");\n if (value.type !== \"tile\" && value.type !== \"sphereTile\")\n throw new Error(\"type: expected tile or sphereTile\");\n if (!isRecord(value.multires))\n throw new Error(\"multires: expected an object\");\n const tileSize = positive(value.multires.tileSize, \"multires.tileSize\");\n if (tileSize > 8192) throw new Error(\"multires.tileSize: maximum is 8192\");\n const input = value.multires.levels;\n if (!Array.isArray(input) || input.length === 0 || input.length > 64)\n throw new Error(\"multires.levels: expected 1 to 64 levels\");\n const urlTemplate = requiredString(value.urlTemplate, \"urlTemplate\");\n const previewUrl = requiredString(value.previewUrl, \"previewUrl\");\n if (/%/.test(urlTemplate.replace(/%s|%l|%0*[hxucvywr]/g, \"\")))\n throw new Error(\"urlTemplate: unsupported placeholder\");\n if (value.type === \"tile\") {\n const levels = input.map((level, i) =>\n positive(level, `multires.levels[${i}]`)\n );\n if (levels.some((level, i) => i > 0 && level <= levels[i - 1]!))\n throw new Error(\"multires.levels: face sizes must increase\");\n const order = value.previewFaceOrder;\n if (\n !Array.isArray(order) ||\n order.length !== 6 ||\n ![\"f\", \"r\", \"b\", \"l\", \"u\", \"d\"].every((face) => order.includes(face))\n )\n throw new Error(\"previewFaceOrder: expected six unique cube faces\");\n return {\n type: \"tile\",\n multires: { tileSize, levels },\n urlTemplate,\n previewUrl,\n previewFaceOrder: [...order] as ViewerCubeFace[],\n };\n }\n if (urlTemplate.includes(\"%s\"))\n throw new Error(\"urlTemplate: sphere has no cube face\");\n if (value.indexBase !== 0 && value.indexBase !== 1)\n throw new Error(\"indexBase: expected 0 or 1\");\n const levels = input.map((level: unknown, i) => {\n if (!isRecord(level))\n throw new Error(`multires.levels[${i}]: expected dimensions`);\n const width = positive(level.width, `multires.levels[${i}].width`);\n const height = positive(level.height, `multires.levels[${i}].height`);\n if (Math.abs(width - 2 * height) > 2)\n throw new Error(`multires.levels[${i}]: expected a full 2:1 panorama`);\n return { width, height };\n });\n if (\n levels.some(\n (level, i) =>\n i > 0 &&\n (level.width <= levels[i - 1]!.width ||\n level.height <= levels[i - 1]!.height)\n )\n )\n throw new Error(\"multires.levels: dimensions must increase\");\n return {\n type: \"sphereTile\",\n multires: { tileSize, levels },\n urlTemplate,\n previewUrl,\n indexBase: value.indexBase,\n };\n}\n","import { resolveAssetUrl } from \"../asset-url\";\nimport type {\n TileAddress,\n TileMultiresConfig,\n} from \"./types\";\n\nfunction positiveInteger(value: number, name: string): number {\n if (!Number.isFinite(value) || value <= 0 || !Number.isInteger(value)) {\n throw new Error(`${name} must be a positive integer, received ${String(value)}`);\n }\n return value;\n}\n\nfunction ascendingLevels(levels: number[]): number[] {\n for (let index = 1; index < levels.length; index += 1) {\n if (levels[index]! <= levels[index - 1]!) {\n throw new Error(\"multires face sizes must be strictly ascending\");\n }\n }\n return levels;\n}\n\nexport function parseMultires(\n multires: string | TileMultiresConfig,\n): TileMultiresConfig {\n if (typeof multires !== \"string\") {\n const tileSize = positiveInteger(multires.tileSize, \"multires.tileSize\");\n if (multires.levels.length === 0) {\n throw new Error(\"multires.levels must contain at least one face size\");\n }\n const levels = ascendingLevels(\n multires.levels.map((level, index) =>\n positiveInteger(level, `multires.levels[${index}]`),\n ),\n );\n return { tileSize, levels };\n }\n\n const values = multires.split(\",\").map((part) => Number(part.trim()));\n\n if (values.length < 2 || values.some((value) => !Number.isFinite(value))) {\n throw new Error(\n \"multires must contain a tile size followed by at least one face size\",\n );\n }\n\n const tileSize = positiveInteger(values[0]!, \"multires tile size\");\n const levels = ascendingLevels(\n values.slice(1).map((level, index) =>\n positiveInteger(level, `multires level ${index + 1}`),\n ),\n );\n return { tileSize, levels };\n}\n\nexport const DEFAULT_TILE_URL_TEMPLATE = \"tiles/%s/l%l/%v/l%l_%s_%h_%v.webp\";\n\nexport function buildDefaultTileUrlTemplate(): string {\n return DEFAULT_TILE_URL_TEMPLATE;\n}\n\nexport function resolveRelativeTileUrl(\n baseUrl: string,\n relativePath: string,\n): string {\n return resolveAssetUrl(baseUrl, relativePath);\n}\n\nexport function resolveTemplateUrl(\n template: string,\n address: Pick<TileAddress, \"face\" | \"level\" | \"row\" | \"col\">,\n): string {\n return template\n .replace(/%s/g, address.face)\n .replace(/%l/g, String(address.level))\n .replace(/%(0*)([hxucvywr])/g, (_match, zeroes: string, placeholder: string) => {\n const value = \"hxuc\".includes(placeholder)\n ? address.col\n : address.row;\n return String(value).padStart(zeroes.length + 1, \"0\");\n });\n}\n","import {\n isRecord,\n validateViewerConfig,\n type ViewerConfig,\n} from \"../../../../shared/viewer-config\";\nimport type { TileScene, SphereTileScene } from \"../scenes\";\nimport type { TileAddress } from \"../tile/types\";\nimport type { SphereTileAddress } from \"../sphere-tile/types\";\nimport { resolveTemplateUrl } from \"../tile/multires\";\nimport { PanoDataError, aborted } from \"./errors\";\n\nexport type AssetUrlContext = {\n defaultUrl: string;\n kind: \"tile\" | \"preview\" | \"hotspot\" | \"map\";\n sceneId: string;\n hotspotId?: string;\n};\nexport type AssetUrlResolver = (\n path: string,\n context: AssetUrlContext\n) => string;\nexport type JsonRequestOptions = {\n requestInit?: Pick<RequestInit, \"headers\" | \"credentials\" | \"signal\">;\n};\nexport type SceneFromViewerConfigOptions = {\n id: string;\n baseUrl: string;\n resolveAssetUrl?: AssetUrlResolver;\n};\nexport type LoadSceneFromJsonOptions = Omit<\n SceneFromViewerConfigOptions,\n \"baseUrl\"\n> &\n JsonRequestOptions & { baseUrl?: string };\n\n/** URL resolution is intentionally independent of React and browser globals on the server. */\nexport function documentUrl(input: string): string {\n try {\n const url = new URL(\n input,\n typeof document === \"undefined\" ? undefined : document.baseURI\n );\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\")\n throw new Error(\"Use HTTP(S)\");\n return url.href;\n } catch (cause) {\n throw new PanoDataError(\n \"INVALID_OPTIONS\",\n \"Expected an HTTP(S) URL; Node.js requires an absolute URL\",\n { cause }\n );\n }\n}\n\nexport function directoryUrl(input: string): string {\n const url = new URL(input);\n url.search = \"\";\n url.hash = \"\";\n if (!url.pathname.endsWith(\"/\")) url.pathname += \"/\";\n return url.href;\n}\n\nexport function resolveResource(baseUrl: string, path: string): string {\n try {\n const url = new URL(path, directoryUrl(baseUrl));\n if (![\"http:\", \"https:\", \"blob:\", \"data:\"].includes(url.protocol))\n throw new Error(\"Unsupported resource URL protocol\");\n return url.href;\n } catch (cause) {\n throw new PanoDataError(\n \"INVALID_CONFIG\",\n `Invalid resource path: ${path}`,\n { cause }\n );\n }\n}\n\nexport function mapResource(\n path: string,\n context: AssetUrlContext,\n resolver?: AssetUrlResolver\n): string {\n let result: string;\n try {\n result = resolver ? resolver(path, context) : context.defaultUrl;\n } catch (cause) {\n throw new PanoDataError(\"INVALID_CONFIG\", \"resolveAssetUrl failed\", {\n sceneId: context.sceneId,\n cause,\n });\n }\n if (typeof result !== \"string\" || !result.trim())\n throw new PanoDataError(\n \"INVALID_CONFIG\",\n \"resolveAssetUrl must return a nonempty final URL\",\n { sceneId: context.sceneId }\n );\n // A root path is already final; relative callback results are ambiguous and rejected.\n if (!result.startsWith(\"/\") && !/^(https?:|blob:|data:)/i.test(result))\n throw new PanoDataError(\n \"INVALID_CONFIG\",\n \"resolveAssetUrl must return an absolute URL or a site-root path\",\n { sceneId: context.sceneId }\n );\n return result;\n}\n\nexport function parseConfig(value: unknown): ViewerConfig {\n if (isRecord(value) && value.type !== \"tile\" && value.type !== \"sphereTile\")\n throw new PanoDataError(\n \"UNSUPPORTED_PROJECTION\",\n \"Expected a tile or sphereTile configuration\",\n { field: \"type\" }\n );\n try {\n return validateViewerConfig(value);\n } catch (cause) {\n const message =\n cause instanceof Error ? cause.message : \"Invalid viewer configuration\";\n throw new PanoDataError(\"INVALID_CONFIG\", message, {\n cause,\n field: message.split(\":\")[0],\n });\n }\n}\n\nexport function sceneFromViewerConfig(\n value: unknown,\n options: SceneFromViewerConfigOptions\n): TileScene | SphereTileScene {\n if (\n !options ||\n typeof options.id !== \"string\" ||\n !options.id.trim() ||\n typeof options.baseUrl !== \"string\" ||\n !options.baseUrl.trim()\n )\n throw new PanoDataError(\"INVALID_OPTIONS\", \"id and baseUrl are required\");\n const config = parseConfig(value);\n const baseUrl = directoryUrl(documentUrl(options.baseUrl));\n const resolve = (path: string, kind: \"tile\" | \"preview\") =>\n mapResource(\n path,\n {\n kind,\n sceneId: options.id,\n defaultUrl: resolveResource(baseUrl, path),\n },\n options.resolveAssetUrl\n );\n const previewUrl = resolve(config.previewUrl, \"preview\");\n if (config.type === \"tile\") {\n return {\n ...config,\n id: options.id,\n baseUrl,\n previewUrl,\n ...(options.resolveAssetUrl\n ? {\n resolveTileUrl: (address: TileAddress) =>\n resolve(resolveTemplateUrl(config.urlTemplate, address), \"tile\"),\n }\n : {}),\n };\n }\n return {\n ...config,\n id: options.id,\n baseUrl,\n previewUrl,\n ...(options.resolveAssetUrl\n ? {\n resolveTileUrl: (address: SphereTileAddress) => {\n // Sphere callbacks use logical zero-based addresses; the document controls storage indices.\n const path = resolveTemplateUrl(config.urlTemplate, {\n face: \"f\",\n level: address.level + config.indexBase,\n row: address.row + config.indexBase,\n col: address.col + config.indexBase,\n });\n return resolve(path, \"tile\");\n },\n }\n : {}),\n };\n}\n\nexport async function readJson(\n url: string,\n options: JsonRequestOptions\n): Promise<{ value: unknown; url: string }> {\n const signal = options.requestInit?.signal;\n aborted(signal);\n let response: Response;\n try {\n response = await fetch(url, { ...options.requestInit, method: \"GET\" });\n } catch (cause) {\n aborted(signal);\n throw new PanoDataError(\n \"FETCH_FAILED\",\n \"Could not fetch JSON; check the network and server CORS settings\",\n { cause }\n );\n }\n aborted(signal);\n if (!response.ok)\n throw new PanoDataError(\n \"HTTP_ERROR\",\n `JSON request returned HTTP ${response.status}`,\n { status: response.status }\n );\n try {\n const value: unknown = await response.json();\n aborted(signal);\n return { value, url: response.url || url };\n } catch (cause) {\n aborted(signal);\n throw new PanoDataError(\n \"INVALID_JSON\",\n \"Expected JSON; check for an HTML fallback or login page\",\n { cause }\n );\n }\n}\n\nexport async function loadSceneFromJson(\n url: string,\n options: LoadSceneFromJsonOptions\n): Promise<TileScene | SphereTileScene> {\n if (!options || typeof options.id !== \"string\" || !options.id.trim())\n throw new PanoDataError(\"INVALID_OPTIONS\", \"id is required\");\n const response = await readJson(documentUrl(url), options);\n if (!isRecord(response.value))\n throw new PanoDataError(\n \"INVALID_CONFIG\",\n \"viewer.json must contain an object\"\n );\n if (response.value.schemaVersion !== 1)\n throw new PanoDataError(\n \"UNSUPPORTED_SCHEMA_VERSION\",\n \"Unsupported viewer.json schemaVersion\",\n { field: \"schemaVersion\" }\n );\n return sceneFromViewerConfig(response.value, {\n ...options,\n baseUrl: options.baseUrl ?? new URL(\".\", response.url).href,\n });\n}\n","/** Camera-center limits in degrees. A yaw min greater than max crosses ±180°. */\nexport type PanoViewLimits = {\n yaw?: { min: number; max: number };\n pitch?: { min: number; max: number };\n fov?: { min: number; max: number };\n};\n\ntype Range = { min: number; max: number };\nexport type ResolvedViewLimits = {\n yaw?: Range;\n pitch: Range;\n fov: Range;\n hardPitch: boolean;\n hardFov: boolean;\n};\n\nexport function parseViewLimits(value: unknown): PanoViewLimits | undefined {\n if (value === undefined) return undefined;\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n throw new Error(\"viewLimits: expected an object\");\n const result: PanoViewLimits = {};\n for (const axis of [\"yaw\", \"pitch\", \"fov\"] as const) {\n const input = (value as Record<string, unknown>)[axis];\n if (input === undefined) continue;\n if (!input || typeof input !== \"object\" || Array.isArray(input))\n throw new Error(`viewLimits.${axis}: expected min and max`);\n const { min, max } = input as Record<string, unknown>;\n const lower = axis === \"yaw\" ? -180 : axis === \"pitch\" ? -90 : 1;\n const upper = axis === \"yaw\" ? 180 : axis === \"pitch\" ? 90 : 179;\n if (typeof min !== \"number\" || typeof max !== \"number\" ||\n !Number.isFinite(min) || !Number.isFinite(max) ||\n min < lower || min > upper || max < lower || max > upper)\n throw new Error(`viewLimits.${axis}: expected finite min and max from ${lower} to ${upper}`);\n if (axis !== \"yaw\" && min > max)\n throw new Error(`viewLimits.${axis}: min must not exceed max`);\n result[axis] = { min, max };\n }\n return result;\n}\n\nexport function resolveViewLimits(\n base: PanoViewLimits | undefined,\n scene: PanoViewLimits | undefined,\n minFov = 30,\n maxFov = 100,\n): ResolvedViewLimits {\n const pitch = scene?.pitch ?? base?.pitch;\n const fov = scene?.fov ?? base?.fov;\n return {\n yaw: scene?.yaw ?? base?.yaw,\n pitch: pitch ?? { min: -90, max: 90 },\n fov: fov ?? { min: minFov, max: maxFov },\n hardPitch: pitch !== undefined,\n hardFov: fov !== undefined,\n };\n}\n\nexport function clampViewAxis(value: number, range: Range): number {\n return Math.max(range.min, Math.min(range.max, value));\n}\n\nexport function normalizeViewYaw(yaw: number): number {\n return ((yaw + 180) % 360 + 360) % 360 - 180;\n}\n\nfunction yawWidth(range: Range | undefined): number {\n if (!range || (range.min === -180 && range.max === 180)) return 360;\n return ((range.max - range.min) % 360 + 360) % 360;\n}\n\n/** Offset in the allowed arc; outside points use the nearest boundary (ties use min). */\nfunction yawOffset(yaw: number, range: Range): number {\n const width = yawWidth(range);\n const offset = ((yaw - range.min) % 360 + 360) % 360;\n if (offset <= width) return offset;\n return offset - width < 360 - offset ? width : 0;\n}\n\nexport function constrainViewYaw(yaw: number, range?: Range): number {\n if (yawWidth(range) === 360) return normalizeViewYaw(yaw);\n return normalizeViewYaw(range!.min + yawOffset(yaw, range!));\n}\n\n/** Clamp relative input before wrapping so a large drag cannot jump across a forbidden arc. */\nexport function applyLimitedYawDelta(yaw: number, delta: number, range?: Range): number {\n const width = yawWidth(range);\n if (width === 360) return normalizeViewYaw(yaw + delta);\n const offset = clampViewAxis(yawOffset(yaw, range!) + delta, { min: 0, max: width });\n return normalizeViewYaw(range!.min + offset);\n}\n\n/** Interpolate inside the allowed arc even when the shorter path leaves it. */\nexport function limitedYawDelta(from: number, to: number, range?: Range, shortestPath = true): number {\n if (yawWidth(range) === 360)\n return shortestPath ? normalizeViewYaw(to - from) : to - from;\n return yawOffset(to, range!) - yawOffset(from, range!);\n}\n","import { isRecord, requiredString } from \"../../../../shared/viewer-config\";\nimport { PanoDataError } from \"./errors\";\nimport { resolveResource } from \"./viewer\";\n\nexport type ProjectPopupBlock = { id: string } & (\n | { type: \"text\"; text: string }\n | { type: \"image\"; src: string; alt?: string }\n | { type: \"video\"; src: string; poster?: string }\n | { type: \"audio\"; src: string }\n);\nexport type ProjectPopupDefinition = {\n id: string;\n title: string;\n blocks: ProjectPopupBlock[];\n};\nexport type PopupAssetUrlContext = {\n defaultUrl: string;\n popupId: string;\n blockId: string;\n field: \"src\" | \"poster\";\n};\nexport type PopupAssetUrlResolver = (path: string, context: PopupAssetUrlContext) => string;\n\nexport function parsePopups(value: unknown, draft = false): ProjectPopupDefinition[] | undefined {\n if (value === undefined) return undefined;\n try {\n if (!Array.isArray(value)) throw new Error(\"popups: expected an array\");\n const ids = new Set<string>();\n const string = (input: unknown, field: string, allowEmpty = false) => {\n if (typeof input !== \"string\" || (!allowEmpty && !input.trim()))\n throw new Error(`${field}: expected a ${allowEmpty ? \"string\" : \"nonempty string\"}`);\n return input;\n };\n return value.map((entry, index) => {\n const field = `popups[${index}]`;\n if (!isRecord(entry)) throw new Error(`${field}: expected an object`);\n const id = requiredString(entry.id, `${field}.id`);\n if (ids.has(id)) throw new Error(`${field}.id: duplicate popup ID`);\n ids.add(id);\n const title = string(entry.title, `${field}.title`, draft);\n if (!Array.isArray(entry.blocks)) throw new Error(`${field}.blocks: expected an array`);\n const blockIds = new Set<string>();\n const blocks = entry.blocks.map((block, i): ProjectPopupBlock => {\n const path = `${field}.blocks[${i}]`;\n if (!isRecord(block)) throw new Error(`${path}: expected an object`);\n const id = requiredString(block.id, `${path}.id`);\n if (blockIds.has(id)) throw new Error(`${path}.id: duplicate block ID`);\n blockIds.add(id);\n if (block.type === \"text\") return { id, type: \"text\", text: string(block.text, `${path}.text`, true) };\n const src = string(block.src, `${path}.src`, draft);\n if (src) resolveResource(\"https://popup.invalid/\", src);\n if (block.type === \"image\") return {\n id, type: \"image\", src,\n ...(block.alt === undefined ? {} : { alt: string(block.alt, `${path}.alt`, true) }),\n };\n if (block.type === \"audio\") return { id, type: \"audio\", src };\n if (block.type === \"video\") {\n const poster = block.poster === undefined ? undefined : string(block.poster, `${path}.poster`, true);\n if (poster) resolveResource(\"https://popup.invalid/\", poster);\n return { id, type: \"video\", src, ...(poster ? { poster } : {}) };\n }\n throw new Error(`${path}.type: unsupported content block`);\n });\n return { id, title, blocks };\n });\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : \"Invalid popup content\";\n throw new PanoDataError(\"INVALID_PROJECT\", message, { field: message.split(\":\")[0], cause });\n }\n}\n\nexport function resolveProjectPopupAssets(\n popup: ProjectPopupDefinition,\n baseUrl: string,\n resolver?: PopupAssetUrlResolver,\n): ProjectPopupDefinition {\n return { ...popup, blocks: popup.blocks.map((block) => {\n if (block.type === \"text\") return { ...block };\n const resolve = (path: string, field: \"src\" | \"poster\") => {\n if (!path) throw new PanoDataError(\"INVALID_PROJECT\", `${popup.id}/${block.id}.${field}: choose a resource`);\n const context = { defaultUrl: resolveResource(baseUrl, path), popupId: popup.id, blockId: block.id, field };\n const result = resolver ? resolver(path, context) : context.defaultUrl;\n if (typeof result !== \"string\" || (!result.startsWith(\"/\") && !/^(https?:|blob:|data:)/i.test(result)))\n throw new PanoDataError(\"INVALID_CONFIG\", \"resolvePopupAssetUrl must return an absolute URL or a site-root path\");\n return result;\n };\n return { ...block, src: resolve(block.src, \"src\"), ...(block.type === \"video\" && block.poster ? { poster: resolve(block.poster, \"poster\") } : {}) };\n }) };\n}\n","/** Resolve image URLs inside CSS cursor values without changing keywords or hotspot coordinates. */\nexport function mapCursorAssets(\n cursor: string,\n resolve: (path: string) => string,\n): string {\n return cursor.replace(\n /url\\(\\s*(?:\"((?:\\\\.|[^\"\\\\])*)\"|'((?:\\\\.|[^'\\\\])*)'|((?:\\\\.|[^)\\\\])*?))\\s*\\)/gi,\n (\n _match,\n double: string | undefined,\n single: string | undefined,\n bare: string | undefined,\n ) => {\n const path = (double ?? single ?? bare ?? \"\").replace(\n /\\\\([\\da-f]{1,6}\\s?|.)/gi,\n (_escape, value: string) =>\n /^[\\da-f]/i.test(value)\n ? String.fromCodePoint(\n Math.min(parseInt(value.trim(), 16), 0x10ffff),\n )\n : value,\n );\n return `url(${JSON.stringify(resolve(path))})`;\n },\n );\n}\n\nexport function cursorImage(cursor: string | undefined): string | undefined {\n let image: string | undefined;\n if (cursor)\n mapCursorAssets(cursor, (path) => {\n image ??= path;\n return path;\n });\n return image;\n}\n\nexport function imageCursor(path: string): string {\n return `url(${JSON.stringify(path)}) 0 0, pointer`;\n}\n","import { mapCursorAssets } from \"../../../../shared/cursor-assets\";\nimport { isRecord, requiredString } from \"../../../../shared/viewer-config\";\nimport type { HotspotDefinition } from \"../hotspot/definitions\";\nimport type { PanoViewerState } from \"../types\";\nimport type { HotspotPosition } from \"../hotspot/types\";\nimport { PanoDataError } from \"./errors\";\nimport { mapResource, resolveResource, type AssetUrlResolver } from \"./viewer\";\n\nexport type JsonValue = null | boolean | number | string | JsonValue[] | JsonObject;\nexport type JsonObject = { [key: string]: JsonValue };\nexport const projectHotspotTriggers = [\"click\", \"pointerenter\", \"pointerleave\"] as const;\nexport type ProjectHotspotTrigger = typeof projectHotspotTriggers[number];\nexport type ProjectCustomHotspotAction = { type: \"custom\"; actionId: string; params?: JsonObject };\nexport function hotspotAction(hotspot: ProjectHotspotDefinition, trigger: ProjectHotspotTrigger) {\n return hotspot.events?.[trigger] ?? (trigger === \"click\" ? hotspot.action : undefined);\n}\nexport function setHotspotAction(hotspot: ProjectHotspotDefinition, trigger: ProjectHotspotTrigger, action?: ProjectHotspotAction): ProjectHotspotDefinition {\n const events = { ...hotspot.events };\n const next: ProjectHotspotDefinition = { ...hotspot, events };\n if (trigger === \"click\") delete next.action;\n if (action) events[trigger] = action;\n else delete events[trigger];\n if (!Object.keys(events).length) delete next.events;\n return next;\n}\nfunction jsonValue(value: unknown, seen = new Set<object>()): JsonValue {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"object\" || !value || seen.has(value)) throw new Error(\"params: expected JSON data\");\n if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new Error(\"params: expected JSON data\");\n seen.add(value);\n const result: JsonValue = Array.isArray(value) ? value.map(item => jsonValue(item, seen)) : Object.fromEntries(Object.entries(value).map(([key, item]) => [key, jsonValue(item, seen)]));\n seen.delete(value);\n return result;\n}\nfunction parseAction(action: unknown): ProjectHotspotAction {\n if (!isRecord(action)) throw new Error(\"action: expected an object\");\n if (action.type === \"scene\") return { type: \"scene\", sceneId: requiredString(action.sceneId, \"action.sceneId\") };\n if (action.type === \"popup\") return { type: \"popup\", popupId: requiredString(action.popupId, \"action.popupId\") };\n if (action.type === \"custom\") {\n if (action.params !== undefined && (!isRecord(action.params) || Array.isArray(action.params))) throw new Error(\"action.params: expected an object\");\n return { type: \"custom\", actionId: requiredString(action.actionId, \"action.actionId\"), ...(action.params === undefined ? {} : { params: jsonValue(action.params) as JsonObject }) };\n }\n if (action.type === \"view\") {\n const position = parsePosition(action.view, \"action.view\");\n const fov = finite((action.view as Record<string, unknown>).fov, \"action.view.fov\");\n if (fov <= 0 || fov >= 180) throw new Error(\"action.view.fov: expected 0 < fov < 180\");\n const duration = action.duration === undefined ? undefined : finite(action.duration, \"action.duration\");\n if (duration !== undefined && duration < 0) throw new Error(\"action.duration: expected a nonnegative number\");\n return { type: \"view\", view: { ...position, fov }, ...(duration === undefined ? {} : { duration }) };\n }\n throw new Error(\"action.type: unsupported action\");\n}\n\nexport type ProjectHotspotAction =\n | ProjectCustomHotspotAction\n | { type: \"scene\"; sceneId: string }\n | { type: \"view\"; view: PanoViewerState; duration?: number }\n | { type: \"popup\"; popupId: string };\n\nexport type ProjectHotspotDefinition = HotspotDefinition & {\n /** Legacy click fallback. events.click takes precedence. */\n action?: ProjectHotspotAction;\n events?: Partial<Record<ProjectHotspotTrigger, ProjectHotspotAction>>;\n};\n\nconst common = [\n \"label\",\n \"visible\",\n \"interactive\",\n \"pointerEvents\",\n \"cursor\",\n \"renderOrder\",\n \"tooltip\",\n \"tooltipTrigger\",\n \"tooltipPlacement\",\n \"tooltipOffset\",\n \"tooltipAppearance\",\n];\nconst point = [\n \"position\",\n \"width\",\n \"height\",\n \"scale\",\n \"mode\",\n \"distance\",\n \"scaleMode\",\n \"referenceFov\",\n \"rotation\",\n \"opacity\",\n];\nconst fields = {\n image: [\"src\"],\n graphic: [\"graphic\"],\n sequence: [\"src\", \"frameCount\", \"frameDirection\", \"playing\", \"fps\", \"loop\"],\n video: [\n \"src\",\n \"poster\",\n \"playing\",\n \"loop\",\n \"muted\",\n \"volume\",\n \"playsInline\",\n \"preload\",\n \"crossOrigin\",\n ],\n audio: [\n \"src\",\n \"format\",\n \"playing\",\n \"loop\",\n \"muted\",\n \"volume\",\n \"pauseWhenHidden\",\n \"range\",\n \"icon\",\n \"playingIcon\",\n \"marker\",\n \"crossOrigin\",\n ],\n text: [\n \"text\",\n \"fontFamily\",\n \"fontSize\",\n \"fontWeight\",\n \"fontStyle\",\n \"color\",\n \"background\",\n \"backgroundOpacity\",\n \"padding\",\n \"align\",\n \"verticalAlign\",\n \"whiteSpace\",\n \"lineHeight\",\n \"borderRadius\",\n \"stroke\",\n \"strokeWidth\",\n ],\n iframe: [\n \"src\",\n \"title\",\n \"sandbox\",\n \"allow\",\n \"referrerPolicy\",\n \"loading\",\n \"pointerPolicy\",\n \"background\",\n ],\n polygon: [\n \"vertices\",\n \"fill\",\n \"fillOpacity\",\n \"stroke\",\n \"strokeWidth\",\n \"strokeOpacity\",\n \"strokeDashSize\",\n \"strokeGapSize\",\n ],\n polyline: [\n \"vertices\",\n \"stroke\",\n \"strokeWidth\",\n \"strokeOpacity\",\n \"strokeDashSize\",\n \"strokeGapSize\",\n ],\n} satisfies Record<HotspotDefinition[\"type\"], string[]>;\nconst booleanFields = new Set([\n \"visible\",\n \"interactive\",\n \"playing\",\n \"loop\",\n \"muted\",\n \"playsInline\",\n \"pauseWhenHidden\",\n \"marker\",\n]);\nconst numberFields = new Set([\n \"renderOrder\",\n \"tooltipOffset\",\n \"width\",\n \"height\",\n \"scale\",\n \"distance\",\n \"referenceFov\",\n \"rotation\",\n \"opacity\",\n \"frameCount\",\n \"fps\",\n \"volume\",\n \"range\",\n \"fontSize\",\n \"backgroundOpacity\",\n \"padding\",\n \"lineHeight\",\n \"borderRadius\",\n \"strokeWidth\",\n \"fillOpacity\",\n \"strokeOpacity\",\n \"strokeDashSize\",\n \"strokeGapSize\",\n]);\nconst positiveFields = new Set([\n \"width\",\n \"height\",\n \"scale\",\n \"distance\",\n \"referenceFov\",\n \"frameCount\",\n \"fps\",\n \"fontSize\",\n \"lineHeight\",\n]);\nconst enums: Record<string, readonly string[]> = {\n pointerEvents: [\"auto\", \"none\"],\n tooltipTrigger: [\"always\", \"hover\", \"click\"],\n tooltipPlacement: [\"top\", \"bottom\", \"left\", \"right\"],\n mode: [\"surface\", \"billboard\"],\n scaleMode: [\"fov\", \"fixed\"],\n frameDirection: [\"horizontal\", \"vertical\"],\n preload: [\"none\", \"metadata\", \"auto\"],\n crossOrigin: [\"\", \"anonymous\", \"use-credentials\"],\n fontStyle: [\"normal\", \"italic\"],\n align: [\"left\", \"center\", \"right\"],\n verticalAlign: [\"top\", \"middle\", \"bottom\"],\n whiteSpace: [\"normal\", \"nowrap\"],\n loading: [\"eager\", \"lazy\"],\n pointerPolicy: [\"hotspot\", \"content\"],\n referrerPolicy: [\n \"\",\n \"no-referrer\",\n \"no-referrer-when-downgrade\",\n \"origin\",\n \"origin-when-cross-origin\",\n \"same-origin\",\n \"strict-origin\",\n \"strict-origin-when-cross-origin\",\n \"unsafe-url\",\n ],\n};\n\nfunction finite(value: unknown, field: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value))\n throw new Error(`${field}: expected a finite number`);\n return value;\n}\n\nexport function parsePosition(value: unknown, field: string): HotspotPosition {\n if (!isRecord(value)) throw new Error(`${field}: expected yaw and pitch`);\n const yaw = finite(value.yaw, `${field}.yaw`);\n const pitch = finite(value.pitch, `${field}.pitch`);\n if (Math.abs(pitch) > 90)\n throw new Error(`${field}.pitch: expected -90 to 90`);\n return { yaw, pitch };\n}\n\nfunction parseGraphic(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) throw new Error(\"graphic: expected an object\");\n const kind = requiredString(value.kind, \"graphic.kind\");\n if (\n ![\n \"circle\",\n \"triangle\",\n \"diamond\",\n \"star\",\n \"arrow\",\n \"rectangle\",\n \"ring\",\n \"svg\",\n \"path\",\n ].includes(kind)\n )\n throw new Error(\"graphic.kind: unsupported graphic\");\n const result: Record<string, unknown> = { kind };\n for (const key of [\"fill\", \"stroke\"]) {\n if (value[key] !== undefined)\n result[key] = requiredString(value[key], `graphic.${key}`);\n }\n for (const key of [\"strokeWidth\", \"cornerRadius\", \"innerRadius\"]) {\n if (value[key] !== undefined)\n result[key] = finite(value[key], `graphic.${key}`);\n }\n if (kind === \"svg\") result.src = requiredString(value.src, \"graphic.src\");\n if (kind === \"path\") {\n result.path = requiredString(value.path, \"graphic.path\");\n if (!Array.isArray(value.viewBox) || value.viewBox.length !== 4)\n throw new Error(\"graphic.viewBox: expected four numbers\");\n const viewBox = value.viewBox.map((n, i) =>\n finite(n, `graphic.viewBox[${i}]`)\n );\n if (viewBox[2]! <= 0 || viewBox[3]! <= 0)\n throw new Error(\"graphic.viewBox: width and height must be positive\");\n result.viewBox = viewBox;\n }\n return result;\n}\n\nfunction parseTooltip(value: unknown): unknown {\n if (typeof value === \"string\") return value;\n if (!isRecord(value)) throw new Error(\"tooltip: expected text or an object\");\n const result: Record<string, string> = {};\n for (const key of [\"text\", \"image\", \"imageAlt\"]) {\n if (value[key] !== undefined) {\n if (typeof value[key] !== \"string\")\n throw new Error(`tooltip.${key}: expected a string`);\n result[key] = value[key];\n }\n }\n return result;\n}\n\nfunction parseAppearance(value: unknown): Record<string, string | number> {\n if (!isRecord(value))\n throw new Error(\"tooltipAppearance: expected an object\");\n const result: Record<string, string | number> = {};\n for (const key of [\n \"background\",\n \"color\",\n \"border\",\n \"borderRadius\",\n \"shadow\",\n \"padding\",\n \"fontSize\",\n \"fontFamily\",\n \"lineHeight\",\n \"letterSpacing\",\n ]) {\n const item = value[key];\n if (item === undefined) continue;\n if (\n [\"background\", \"color\", \"border\", \"shadow\", \"fontFamily\"].includes(key) &&\n typeof item !== \"string\"\n )\n throw new Error(`tooltipAppearance.${key}: expected a string`);\n if (\n typeof item !== \"string\" &&\n (typeof item !== \"number\" || !Number.isFinite(item))\n )\n throw new Error(\n `tooltipAppearance.${key}: expected a string or finite number`\n );\n result[key] = item;\n }\n return result;\n}\n\nexport function parseHotspot(\n value: unknown,\n sceneId: string,\n field: string\n): ProjectHotspotDefinition {\n try {\n if (!isRecord(value)) throw new Error(\"expected a hotspot object\");\n const type = requiredString(value.type, \"type\");\n if (!Object.prototype.hasOwnProperty.call(fields, type))\n throw new Error(\"type: unsupported hotspot type\");\n const kind = type as HotspotDefinition[\"type\"];\n const result: Record<string, unknown> = {\n type,\n id: requiredString(value.id, \"id\"),\n };\n const isPath = kind === \"polygon\" || kind === \"polyline\";\n const allowed = [...common, ...(isPath ? [] : point), ...fields[kind]];\n for (const key of allowed) {\n const item = value[key];\n if (item === undefined) continue;\n if (key === \"position\") result[key] = parsePosition(item, key);\n else if (key === \"vertices\") {\n if (!Array.isArray(item) || item.length < (kind === \"polygon\" ? 3 : 2))\n throw new Error(\"vertices: not enough points\");\n result[key] = item.map((p, i) => parsePosition(p, `vertices[${i}]`));\n } else if (key === \"graphic\") result[key] = parseGraphic(item);\n else if (key === \"tooltip\") result[key] = parseTooltip(item);\n else if (key === \"tooltipAppearance\") result[key] = parseAppearance(item);\n else if (booleanFields.has(key)) {\n if (typeof item !== \"boolean\")\n throw new Error(`${key}: expected a boolean`);\n result[key] = item;\n } else if (numberFields.has(key)) {\n const n = finite(item, key);\n if (positiveFields.has(key) && n <= 0)\n throw new Error(`${key}: expected a positive number`);\n if (key === \"frameCount\" && !Number.isSafeInteger(n))\n throw new Error(\"frameCount: expected an integer\");\n if (\n [\n \"opacity\",\n \"fillOpacity\",\n \"strokeOpacity\",\n \"volume\",\n \"backgroundOpacity\",\n ].includes(key) &&\n (n < 0 || n > 1)\n )\n throw new Error(`${key}: expected 0 to 1`);\n result[key] = n;\n } else if (key === \"fontWeight\" && typeof item === \"number\")\n result[key] = finite(item, key);\n else if (\n (key === \"src\" || key === \"format\") &&\n kind === \"audio\" &&\n Array.isArray(item)\n ) {\n if (!item.length)\n throw new Error(`${key}: expected audio ${key === \"src\" ? \"sources\" : \"formats\"}`);\n result[key] = item.map((entry, i) => requiredString(entry, `${key}[${i}]`));\n } else {\n if (typeof item !== \"string\")\n throw new Error(`${key}: expected a string`);\n if (enums[key] && !enums[key].includes(item))\n throw new Error(`${key}: unsupported value`);\n result[key] = item;\n }\n }\n if (!isPath && !result.position) throw new Error(\"position: required\");\n if (isPath && !result.vertices) throw new Error(\"vertices: required\");\n if (\n [\"image\", \"sequence\", \"video\", \"audio\", \"iframe\"].includes(kind) &&\n !(typeof result.src === \"string\"\n ? result.src.trim()\n : Array.isArray(result.src))\n )\n throw new Error(\"src: required\");\n if (kind === \"graphic\" && !result.graphic)\n throw new Error(\"graphic: required\");\n if (kind === \"text\" && typeof result.text !== \"string\")\n throw new Error(\"text: required\");\n if (kind === \"sequence\" && !result.frameCount)\n throw new Error(\"frameCount: required\");\n if (value.action !== undefined) result.action = parseAction(value.action);\n if (value.events !== undefined) {\n if (!isRecord(value.events)) throw new Error(\"events: expected an object\");\n const events: Partial<Record<ProjectHotspotTrigger, ProjectHotspotAction>> = {};\n for (const key of Object.keys(value.events)) {\n if (!projectHotspotTriggers.includes(key as ProjectHotspotTrigger)) throw new Error(`events.${key}: unsupported trigger`);\n try { events[key as ProjectHotspotTrigger] = parseAction(value.events[key]); }\n catch (error) { throw new Error(`events.${key}.${error instanceof Error ? error.message : \"invalid action\"}`); }\n }\n result.events = events;\n }\n return result as ProjectHotspotDefinition;\n } catch (cause) {\n const detail = cause instanceof Error ? cause.message : \"Invalid hotspot\";\n throw new PanoDataError(\"INVALID_PROJECT\", `${field}.${detail}`, {\n sceneId,\n field: `${field}.${detail.split(\":\")[0]}`,\n cause,\n });\n }\n}\n\nexport function resolveHotspotAssets(\n hotspot: ProjectHotspotDefinition,\n baseUrl: string,\n sceneId: string,\n resolver?: AssetUrlResolver\n): ProjectHotspotDefinition {\n const resolve = (path: string) =>\n path\n ? mapResource(\n path,\n {\n kind: \"hotspot\",\n sceneId,\n hotspotId: hotspot.id,\n defaultUrl: resolveResource(baseUrl, path),\n },\n resolver\n )\n : path;\n const result = { ...hotspot };\n if (result.cursor) result.cursor = mapCursorAssets(result.cursor, resolve);\n if (result.tooltipAppearance?.background) result.tooltipAppearance = {\n ...result.tooltipAppearance,\n background: mapCursorAssets(result.tooltipAppearance.background, resolve),\n };\n if (\"src\" in result)\n result.src = Array.isArray(result.src)\n ? result.src.map(resolve)\n : resolve(result.src);\n if (\"poster\" in result && result.poster)\n result.poster = resolve(result.poster);\n if (result.type === \"audio\") {\n if (result.icon) result.icon = resolve(result.icon);\n if (result.playingIcon) result.playingIcon = resolve(result.playingIcon);\n }\n if (result.type === \"graphic\" && result.graphic.kind === \"svg\")\n result.graphic = { ...result.graphic, src: resolve(result.graphic.src) };\n if (typeof result.tooltip === \"object\")\n result.tooltip = {\n ...result.tooltip,\n ...(result.tooltip.image ? { image: resolve(result.tooltip.image) } : {}),\n };\n return result;\n}\n","import { isRecord, requiredString } from \"../../../../shared/viewer-config\";\nimport type { PanoDragMotion } from \"../drag-motion\";\nimport { PanoDataError } from \"./errors\";\nimport {\n mapResource,\n resolveResource,\n type AssetUrlResolver,\n} from \"./viewer\";\n\nexport type { PanoDragMotion };\n\nexport type PanoMapCorner = \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\n\nexport type PanoMapGradientStop = {\n offset: number;\n color: string;\n opacity?: number;\n};\n\nexport type PanoMapSectorGradient = {\n type: \"radial\" | \"linear\";\n stops: PanoMapGradientStop[];\n};\n\nexport type PanoMapSectorDefinition = {\n /** Sector opening angle in degrees. */\n angle: number;\n /** Sector radius in CSS pixels; does not scale with the floor image. */\n radius: number;\n /** When true, sector angle follows the current horizontal FOV. */\n followFov?: boolean;\n /** Solid fill color when `gradient` is omitted. */\n color?: string;\n /**\n * Overall fill opacity in [0, 1].\n * Applies in both solid and gradient modes; gradient stop opacities only\n * describe the relative fade shape and are normalized against this value.\n */\n opacity?: number;\n /** Optional sector outline color. */\n strokeColor?: string;\n /** Outline width in CSS pixels. */\n strokeWidth?: number;\n /** Outline opacity in [0, 1]. Defaults to 1 when stroke is set. */\n strokeOpacity?: number;\n /**\n * Optional fill gradient. When omitted, the sector uses a solid `color`.\n * Stop colors are independent of `color` unless the author keeps them in sync.\n */\n gradient?: PanoMapSectorGradient;\n};\n\nexport type PanoMapSpotDefinition = {\n id: string;\n sceneId: string;\n /** Normalized image X in [0, 1], origin at the top-left. */\n x: number;\n /** Normalized image Y in [0, 1], origin at the top-left. */\n y: number;\n /**\n * Clockwise degrees from image up when viewer yaw is 0.\n * Runtime sector rotation is `heading + yaw`.\n */\n heading: number;\n icon?: string;\n};\n\nexport type PanoMapControlsDefinition = {\n /** Show expand/collapse on a docked panel. */\n collapse?: boolean;\n /** Show zoom-in and zoom-out buttons. */\n zoom?: boolean;\n};\n\nexport type PanoMapDockedPresentation = {\n mode: \"docked\";\n corner?: PanoMapCorner;\n width?: number;\n height?: number;\n offsetX?: number;\n offsetY?: number;\n};\n\nexport type PanoMapDialogPresentation = {\n mode: \"dialog\";\n corner?: PanoMapCorner;\n offsetX?: number;\n offsetY?: number;\n width?: number;\n height?: number;\n};\n\nexport type PanoMapPresentation =\n | PanoMapDockedPresentation\n | PanoMapDialogPresentation;\n\nexport type PanoMapDefinition = {\n image: string;\n /**\n * Pointer interaction with the floor image.\n * - `fixed`: fit-only; no wheel/pan zoom (zoom buttons are also suppressed).\n * - `zoom`: wheel/pan zoom and optional zoom buttons.\n */\n interaction?: \"fixed\" | \"zoom\";\n presentation?: PanoMapPresentation;\n controls?: PanoMapControlsDefinition;\n /** Spot icon edge length in CSS pixels. */\n iconSize?: number;\n /**\n * Maximum zoom multiplier relative to the contain-fit scale.\n * Only applies when `interaction` is `\"zoom\"`. Defaults to 8.\n */\n maxScale?: number;\n /**\n * Pan inertia and edge bounce when `interaction` is `\"zoom\"`.\n * Omit for both on; set `false` or flag fields to disable.\n */\n dragMotion?: PanoDragMotion | false;\n spots: PanoMapSpotDefinition[];\n sector?: PanoMapSectorDefinition;\n};\n\nconst CORNERS = new Set<PanoMapCorner>([\n \"top-left\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-right\",\n]);\n\nfunction optionalNumber(\n record: Record<string, unknown>,\n key: string,\n options: { min?: number; max?: number; exclusiveMin?: number; exclusiveMax?: number } = {},\n): number | undefined {\n const value = record[key];\n if (value === undefined) return undefined;\n if (typeof value !== \"number\" || !Number.isFinite(value))\n throw new Error(`${key}: expected a finite number`);\n if (options.min !== undefined && value < options.min)\n throw new Error(`${key}: expected a number >= ${options.min}`);\n if (options.max !== undefined && value > options.max)\n throw new Error(`${key}: expected a number <= ${options.max}`);\n if (options.exclusiveMin !== undefined && value <= options.exclusiveMin)\n throw new Error(`${key}: expected a number > ${options.exclusiveMin}`);\n if (options.exclusiveMax !== undefined && value >= options.exclusiveMax)\n throw new Error(`${key}: expected a number < ${options.exclusiveMax}`);\n return value;\n}\n\nfunction requiredNumber(\n record: Record<string, unknown>,\n key: string,\n options: { min?: number; max?: number; exclusiveMin?: number; exclusiveMax?: number } = {},\n): number {\n const value = optionalNumber(record, key, options);\n if (value === undefined) throw new Error(`${key}: expected a finite number`);\n return value;\n}\n\nfunction optionalString(\n record: Record<string, unknown>,\n key: string,\n): string | undefined {\n return record[key] === undefined\n ? undefined\n : requiredString(record[key], key);\n}\n\nfunction parseGradientStop(\n value: unknown,\n field: string,\n): PanoMapGradientStop {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const offset = requiredNumber(value, \"offset\", { min: 0, max: 1 });\n const color = requiredString(value.color, `${field}.color`);\n const opacity = optionalNumber(value, \"opacity\", { min: 0, max: 1 });\n return {\n offset,\n color,\n ...(opacity === undefined ? {} : { opacity }),\n };\n}\n\nfunction parseSector(value: unknown, field: string): PanoMapSectorDefinition {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const angle = requiredNumber(value, \"angle\", { exclusiveMin: 0, exclusiveMax: 360 });\n const radius = requiredNumber(value, \"radius\", { exclusiveMin: 0 });\n const followFov =\n value.followFov === undefined\n ? undefined\n : value.followFov === true\n ? true\n : value.followFov === false\n ? false\n : (() => {\n throw new Error(`${field}.followFov: expected a boolean`);\n })();\n const color = optionalString(value, \"color\");\n const opacity = optionalNumber(value, \"opacity\", { min: 0, max: 1 });\n const strokeColor = optionalString(value, \"strokeColor\");\n const strokeWidth = optionalNumber(value, \"strokeWidth\", { min: 0 });\n const strokeOpacity = optionalNumber(value, \"strokeOpacity\", { min: 0, max: 1 });\n let gradient: PanoMapSectorGradient | undefined;\n if (value.gradient !== undefined) {\n if (!isRecord(value.gradient))\n throw new Error(`${field}.gradient: expected an object`);\n const type = value.gradient.type;\n if (type !== \"radial\" && type !== \"linear\")\n throw new Error(`${field}.gradient.type: expected \"radial\" or \"linear\"`);\n if (!Array.isArray(value.gradient.stops) || value.gradient.stops.length < 2)\n throw new Error(`${field}.gradient.stops: expected at least two stops`);\n gradient = {\n type,\n stops: value.gradient.stops.map((stop, index) =>\n parseGradientStop(stop, `${field}.gradient.stops[${index}]`),\n ),\n };\n }\n return {\n angle,\n radius,\n ...(followFov === undefined ? {} : { followFov }),\n ...(color === undefined ? {} : { color }),\n ...(opacity === undefined ? {} : { opacity }),\n ...(strokeColor === undefined ? {} : { strokeColor }),\n ...(strokeWidth === undefined ? {} : { strokeWidth }),\n ...(strokeOpacity === undefined ? {} : { strokeOpacity }),\n ...(gradient === undefined ? {} : { gradient }),\n };\n}\n\nfunction parsePresentation(\n value: unknown,\n field: string,\n): PanoMapPresentation {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const mode = value.mode;\n if (mode !== \"docked\" && mode !== \"dialog\")\n throw new Error(`${field}.mode: expected \"docked\" or \"dialog\"`);\n const cornerValue = value.corner;\n const corner =\n cornerValue === undefined\n ? undefined\n : typeof cornerValue === \"string\" && CORNERS.has(cornerValue as PanoMapCorner)\n ? (cornerValue as PanoMapCorner)\n : (() => {\n throw new Error(\n `${field}.corner: expected top-left, top-right, bottom-left, or bottom-right`,\n );\n })();\n const width = optionalNumber(value, \"width\", { exclusiveMin: 0 });\n const height = optionalNumber(value, \"height\", { exclusiveMin: 0 });\n const offsetX = optionalNumber(value, \"offsetX\", { min: 0 });\n const offsetY = optionalNumber(value, \"offsetY\", { min: 0 });\n return {\n mode,\n ...(corner === undefined ? {} : { corner }),\n ...(width === undefined ? {} : { width }),\n ...(height === undefined ? {} : { height }),\n ...(offsetX === undefined ? {} : { offsetX }),\n ...(offsetY === undefined ? {} : { offsetY }),\n };\n}\n\nfunction parseOptionalBoolean(\n value: unknown,\n field: string,\n): boolean | undefined {\n if (value === undefined) return undefined;\n if (value === true) return true;\n if (value === false) return false;\n throw new Error(`${field}: expected a boolean`);\n}\n\nfunction parseDragMotion(\n value: unknown,\n field: string,\n): PanoDragMotion | false {\n if (value === false) return false;\n if (!isRecord(value)) throw new Error(`${field}: expected an object or false`);\n const inertia = parseOptionalBoolean(value.inertia, `${field}.inertia`);\n const bounce = parseOptionalBoolean(value.bounce, `${field}.bounce`);\n const motion: PanoDragMotion = {\n ...(inertia === undefined ? {} : { inertia }),\n ...(bounce === undefined ? {} : { bounce }),\n };\n return motion;\n}\n\nfunction parseControls(\n value: unknown,\n field: string,\n): PanoMapControlsDefinition {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const collapse =\n value.collapse === undefined\n ? undefined\n : value.collapse === true\n ? true\n : value.collapse === false\n ? false\n : (() => {\n throw new Error(`${field}.collapse: expected a boolean`);\n })();\n const zoom =\n value.zoom === undefined\n ? undefined\n : value.zoom === true\n ? true\n : value.zoom === false\n ? false\n : (() => {\n throw new Error(`${field}.zoom: expected a boolean`);\n })();\n return {\n ...(collapse === undefined ? {} : { collapse }),\n ...(zoom === undefined ? {} : { zoom }),\n };\n}\n\nfunction parseSpot(\n value: unknown,\n field: string,\n sceneIds: Set<string>,\n): PanoMapSpotDefinition {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const id = requiredString(value.id, `${field}.id`);\n const sceneId = requiredString(value.sceneId, `${field}.sceneId`);\n if (!sceneIds.has(sceneId))\n throw new Error(`${field}.sceneId: scene does not exist`);\n const x = requiredNumber(value, \"x\", { min: 0, max: 1 });\n const y = requiredNumber(value, \"y\", { min: 0, max: 1 });\n const heading = requiredNumber(value, \"heading\");\n const icon = optionalString(value, \"icon\");\n if (icon) resolveResource(\"https://map.invalid/\", icon);\n return {\n id,\n sceneId,\n x,\n y,\n heading,\n ...(icon === undefined ? {} : { icon }),\n };\n}\n\n/** Parse an optional project floor plan. Scene IDs must already be collected. */\nexport function parsePanoMap(\n value: unknown,\n sceneIds: Set<string>,\n options: { draft?: boolean } = {},\n): PanoMapDefinition | undefined {\n if (value === undefined) return undefined;\n try {\n if (!isRecord(value)) throw new Error(\"map: expected an object\");\n if (typeof value.image !== \"string\" || (!options.draft && !value.image.trim()))\n throw new Error(\"map.image: expected a nonempty string\");\n const image = value.image;\n if (image.trim()) resolveResource(\"https://map.invalid/\", image);\n const interaction =\n value.interaction === undefined\n ? undefined\n : value.interaction === \"fixed\" || value.interaction === \"zoom\"\n ? value.interaction\n : (() => {\n throw new Error('map.interaction: expected \"fixed\" or \"zoom\"');\n })();\n const presentation =\n value.presentation === undefined\n ? undefined\n : parsePresentation(value.presentation, \"map.presentation\");\n const controls =\n value.controls === undefined\n ? undefined\n : parseControls(value.controls, \"map.controls\");\n const iconSize = optionalNumber(value, \"iconSize\", { exclusiveMin: 0 });\n const maxScale = optionalNumber(value, \"maxScale\", { min: 1 });\n const dragMotion =\n value.dragMotion === undefined\n ? undefined\n : parseDragMotion(value.dragMotion, \"map.dragMotion\");\n if (!Array.isArray(value.spots)) throw new Error(\"map.spots: expected an array\");\n const spotIds = new Set<string>();\n const spots = value.spots.map((spot, index) => {\n const parsed = parseSpot(spot, `map.spots[${index}]`, sceneIds);\n if (spotIds.has(parsed.id))\n throw new Error(`map.spots[${index}].id: duplicate spot ID`);\n spotIds.add(parsed.id);\n return parsed;\n });\n const sector =\n value.sector === undefined\n ? undefined\n : parseSector(value.sector, \"map.sector\");\n return {\n image,\n ...(interaction === undefined ? {} : { interaction }),\n ...(presentation === undefined ? {} : { presentation }),\n ...(controls === undefined ? {} : { controls }),\n ...(iconSize === undefined ? {} : { iconSize }),\n ...(maxScale === undefined ? {} : { maxScale }),\n ...(dragMotion === undefined ? {} : { dragMotion }),\n spots,\n ...(sector === undefined ? {} : { sector }),\n };\n } catch (cause) {\n if (cause instanceof PanoDataError) throw cause;\n const message = cause instanceof Error ? cause.message : \"Invalid map\";\n throw new PanoDataError(\"INVALID_PROJECT\", message, {\n field: message.split(\":\")[0],\n cause,\n });\n }\n}\n\nexport function resolvePanoMapAssets(\n map: PanoMapDefinition,\n baseUrl: string,\n resolveAssetUrl?: AssetUrlResolver,\n): PanoMapDefinition {\n const resolve = (path: string, spotId?: string) =>\n mapResource(\n path,\n {\n defaultUrl: resolveResource(baseUrl, path),\n kind: \"map\",\n sceneId: spotId ?? \"\",\n hotspotId: spotId,\n },\n resolveAssetUrl,\n );\n return {\n ...map,\n image: resolve(map.image),\n spots: map.spots.map((spot) =>\n spot.icon\n ? { ...spot, icon: resolve(spot.icon, spot.id) }\n : { ...spot },\n ),\n };\n}\n","import { parseViewLimits, type PanoViewLimits } from \"../view-limits\";\nimport { parsePopups, resolveProjectPopupAssets, type ProjectPopupDefinition, type PopupAssetUrlResolver } from \"./popups\";\nimport {\n isRecord,\n requiredString,\n type ViewerConfig,\n} from \"../../../../shared/viewer-config\";\nimport type { TileScene, SphereTileScene } from \"../scenes\";\nimport type { PanoViewerState } from \"../types\";\nimport { PanoDataError, aborted } from \"./errors\";\nimport {\n parseHotspot,\n projectHotspotTriggers,\n hotspotAction,\n parsePosition,\n resolveHotspotAssets,\n type ProjectHotspotDefinition,\n} from \"./hotspots\";\nimport {\n documentUrl,\n directoryUrl,\n readJson,\n parseConfig,\n resolveResource,\n sceneFromViewerConfig,\n loadSceneFromJson,\n type AssetUrlResolver,\n type JsonRequestOptions,\n} from \"./viewer\";\nimport {\n parsePanoMap,\n resolvePanoMapAssets,\n type PanoMapDefinition,\n} from \"./map\";\n\nexport type PanoProjectSceneDefinition = {\n id: string;\n title?: string;\n source: (\n | { viewerUrl: string; viewerConfig?: never }\n | { viewerConfig: ViewerConfig; viewerUrl?: never }\n ) & { baseUrl?: string };\n initialView?: Partial<PanoViewerState>;\n viewLimits?: PanoViewLimits;\n hotspots?: ProjectHotspotDefinition[];\n};\nexport type PanoProjectDefinition = {\n schemaVersion: 1;\n title?: string;\n initialSceneId?: string;\n scenes: PanoProjectSceneDefinition[];\n popups?: ProjectPopupDefinition[];\n map?: PanoMapDefinition;\n};\nexport type LoadedProjectScene = {\n scene: TileScene | SphereTileScene;\n title?: string;\n initialView?: PanoViewerState;\n hotspots: ProjectHotspotDefinition[];\n};\nexport type LoadedPanoProject = {\n title?: string;\n initialSceneId: string;\n scenes: LoadedProjectScene[];\n popups?: ProjectPopupDefinition[];\n map?: PanoMapDefinition;\n};\nexport type LoadPanoProjectOptions = JsonRequestOptions & {\n /** Directory used for project-relative references. Required for object input. */\n baseUrl?: string;\n resolveAssetUrl?: AssetUrlResolver;\n resolvePopupAssetUrl?: PopupAssetUrlResolver;\n};\n\nfunction optionalString(\n record: Record<string, unknown>,\n key: string\n): string | undefined {\n return record[key] === undefined\n ? undefined\n : requiredString(record[key], key);\n}\n\n/** Drafts permit empty scenes and unfinished popup titles/media; loading and export always validate strictly. */\nexport function parsePanoProject(value: unknown, options: { draft?: boolean } = {}): PanoProjectDefinition {\n if (!isRecord(value))\n throw new PanoDataError(\"INVALID_PROJECT\", \"Expected a project object\");\n if (value.schemaVersion !== 1)\n throw new PanoDataError(\n \"UNSUPPORTED_SCHEMA_VERSION\",\n \"Unsupported project schemaVersion\",\n { field: \"schemaVersion\" }\n );\n try {\n const popups = parsePopups(value.popups, options.draft);\n if (!Array.isArray(value.scenes) || (!options.draft && !value.scenes.length))\n throw new Error(\"scenes: expected a nonempty array\");\n const ids = new Set<string>();\n const scenes = value.scenes.map(\n (entry: unknown, index): PanoProjectSceneDefinition => {\n let id: string | undefined;\n const field = `scenes[${index}]`;\n try {\n if (!isRecord(entry)) throw new Error(\"expected a scene object\");\n id = requiredString(entry.id, \"id\");\n if (ids.has(id)) throw new Error(\"id: duplicate scene ID\");\n ids.add(id);\n if (!isRecord(entry.source))\n throw new Error(\"source: expected an object\");\n const src = entry.source;\n if (\n (src.viewerUrl !== undefined) ===\n (src.viewerConfig !== undefined)\n )\n throw new Error(\n \"source: provide exactly one of viewerUrl or viewerConfig\"\n );\n const baseUrl = optionalString(src, \"baseUrl\");\n const source: PanoProjectSceneDefinition[\"source\"] =\n src.viewerUrl !== undefined\n ? {\n viewerUrl: requiredString(src.viewerUrl, \"source.viewerUrl\"),\n baseUrl,\n }\n : { viewerConfig: parseConfig(src.viewerConfig), baseUrl };\n const viewLimits = parseViewLimits(entry.viewLimits);\n let initialView: Partial<PanoViewerState> | undefined;\n if (entry.initialView !== undefined) {\n if (!isRecord(entry.initialView))\n throw new Error(\"initialView: expected an object\");\n const input = entry.initialView;\n const position = parsePosition(\n { yaw: input.yaw ?? 0, pitch: input.pitch ?? 0 },\n \"initialView\"\n );\n const fov = input.fov ?? 75;\n if (\n typeof fov !== \"number\" ||\n !Number.isFinite(fov) ||\n fov <= 0 ||\n fov >= 180\n )\n throw new Error(\n \"initialView.fov: expected a number between 0 and 180\"\n );\n initialView = { ...position, fov };\n }\n if (entry.hotspots !== undefined && !Array.isArray(entry.hotspots))\n throw new Error(\"hotspots: expected an array\");\n const hotspotIds = new Set<string>();\n const hotspots = ((entry.hotspots ?? []) as unknown[]).map(\n (hotspot, i) => {\n const result = parseHotspot(\n hotspot,\n id!,\n `${field}.hotspots[${i}]`\n );\n if (hotspotIds.has(result.id))\n throw new Error(`hotspots[${i}].id: duplicate hotspot ID`);\n hotspotIds.add(result.id);\n return result;\n }\n );\n return {\n id,\n title: optionalString(entry, \"title\"),\n source,\n initialView,\n ...(viewLimits === undefined ? {} : { viewLimits }),\n hotspots,\n };\n } catch (cause) {\n if (cause instanceof PanoDataError && cause.sceneId) throw cause;\n const detail =\n cause instanceof Error ? cause.message : \"Invalid scene\";\n throw new PanoDataError(\n cause instanceof PanoDataError ? cause.code : \"INVALID_PROJECT\",\n `${field}.${detail}`,\n {\n sceneId: id,\n field: `${field}.${\n cause instanceof PanoDataError\n ? `source.viewerConfig.${cause.field ?? \"\"}`\n : detail.split(\":\")[0]\n }`,\n cause,\n }\n );\n }\n }\n );\n const initialSceneId =\n optionalString(value, \"initialSceneId\") ?? scenes[0]?.id;\n if (initialSceneId !== undefined && !ids.has(initialSceneId))\n throw new PanoDataError(\n \"INVALID_REFERENCE\",\n \"initialSceneId: scene does not exist\",\n { field: \"initialSceneId\" }\n );\n for (const [index, scene] of scenes.entries()) {\n for (const [i, hotspot] of (scene.hotspots ?? []).entries()) {\n for (const trigger of projectHotspotTriggers) {\n const action = hotspotAction(hotspot, trigger);\n if (action?.type === \"popup\" && !popups?.some((popup) => popup.id === action.popupId))\n throw new PanoDataError(\"INVALID_REFERENCE\", \"Hotspot target popup does not exist\", {\n sceneId: scene.id, field: `scenes[${index}].hotspots[${i}].${hotspot.events?.[trigger] ? `events.${trigger}` : \"action\"}.popupId`,\n });\n if (action?.type === \"scene\" && !ids.has(action.sceneId))\n throw new PanoDataError(\n \"INVALID_REFERENCE\",\n \"Hotspot target scene does not exist\",\n {\n sceneId: scene.id,\n field: `scenes[${index}].hotspots[${i}].${hotspot.events?.[trigger] ? `events.${trigger}` : \"action\"}.sceneId`,\n }\n );\n }\n }\n }\n const map = parsePanoMap(value.map, ids, options);\n return {\n schemaVersion: 1,\n title: optionalString(value, \"title\"),\n initialSceneId,\n scenes,\n ...(popups === undefined ? {} : { popups }),\n ...(map === undefined ? {} : { map }),\n };\n } catch (cause) {\n if (cause instanceof PanoDataError) throw cause;\n const message = cause instanceof Error ? cause.message : \"Invalid project\";\n throw new PanoDataError(\"INVALID_PROJECT\", message, {\n cause,\n field: message.split(\":\")[0],\n });\n }\n}\n\nexport async function loadPanoProject(\n source: string | PanoProjectDefinition,\n options: LoadPanoProjectOptions = {}\n): Promise<LoadedPanoProject> {\n aborted(options.requestInit?.signal);\n let definition: PanoProjectDefinition;\n let baseUrl: string;\n if (typeof source === \"string\") {\n const response = await readJson(documentUrl(source), options);\n definition = parsePanoProject(response.value);\n baseUrl = options.baseUrl ?? new URL(\".\", response.url).href;\n } else {\n if (!options.baseUrl)\n throw new PanoDataError(\n \"INVALID_OPTIONS\",\n \"baseUrl is required for project object input\"\n );\n definition = parsePanoProject(source);\n baseUrl = options.baseUrl;\n }\n const root = directoryUrl(documentUrl(baseUrl));\n const controller = new AbortController();\n const signal = options.requestInit?.signal;\n const cancel = () => controller.abort();\n signal?.addEventListener(\"abort\", cancel, { once: true });\n const scenes: LoadedProjectScene[] = new Array(definition.scenes.length);\n let next = 0;\n let failure: PanoDataError | undefined;\n async function worker() {\n while (next < definition.scenes.length && !controller.signal.aborted) {\n const index = next++;\n const item = definition.scenes[index]!;\n try {\n const sourceBase =\n item.source.baseUrl === undefined\n ? undefined\n : resolveResource(root, item.source.baseUrl);\n const sceneOptions = {\n id: item.id,\n resolveAssetUrl: options.resolveAssetUrl,\n };\n const scene =\n item.source.viewerUrl !== undefined\n ? await loadSceneFromJson(\n resolveResource(root, item.source.viewerUrl),\n {\n ...sceneOptions,\n baseUrl: sourceBase,\n requestInit: {\n ...options.requestInit,\n signal: controller.signal,\n },\n }\n )\n : sceneFromViewerConfig(item.source.viewerConfig, {\n ...sceneOptions,\n baseUrl: sourceBase ?? root,\n });\n aborted(controller.signal);\n if (item.viewLimits !== undefined) scene.viewLimits = item.viewLimits;\n scenes[index] = {\n scene,\n title: item.title,\n initialView: item.initialView\n ? { yaw: 0, pitch: 0, fov: 75, ...item.initialView }\n : undefined,\n hotspots: item.hotspots!.map((h) =>\n resolveHotspotAssets(h, root, item.id, options.resolveAssetUrl)\n ),\n };\n } catch (cause) {\n if (!failure) {\n const error =\n cause instanceof PanoDataError\n ? cause\n : new PanoDataError(\n \"INVALID_CONFIG\",\n cause instanceof Error\n ? cause.message\n : \"Could not load scene\",\n { cause }\n );\n const field = `scenes[${index}].${\n error.field ??\n (item.source.viewerUrl !== undefined\n ? \"source.viewerUrl\"\n : \"source.viewerConfig\")\n }`;\n failure = new PanoDataError(\n error.code,\n `Scene ${item.id}: ${error.message}`,\n { status: error.status, sceneId: item.id, field, cause: error }\n );\n }\n controller.abort();\n }\n }\n }\n try {\n aborted(signal);\n await Promise.all(\n Array.from({ length: Math.min(4, scenes.length) }, worker)\n );\n aborted(signal);\n if (failure) throw failure;\n return {\n title: definition.title,\n initialSceneId: definition.initialSceneId!,\n scenes,\n ...(definition.popups === undefined ? {} : { popups: definition.popups.map((popup) => resolveProjectPopupAssets(popup, root, options.resolvePopupAssetUrl)) }),\n ...(definition.map === undefined\n ? {}\n : {\n map: resolvePanoMapAssets(\n definition.map,\n root,\n options.resolveAssetUrl,\n ),\n }),\n };\n } finally {\n signal?.removeEventListener(\"abort\", cancel);\n }\n}\n"],"mappings":"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","names":["levels","id","optionalString"]}
|
|
1
|
+
{"version":3,"sources":["../src/data.ts","../src/data/errors.ts","../../../shared/viewer-config.ts","../src/tile/multires.ts","../src/data/viewer.ts","../src/view-limits.ts","../src/data/popups.ts","../../../shared/cursor-assets.ts","../src/data/hotspots.ts","../src/overlay/align.ts","../src/data/map.ts","../src/data/project.ts"],"sourcesContent":["export { PanoDataError } from \"./data/errors\";\nexport type { PanoDataErrorCode } from \"./data/errors\";\nexport { sceneFromViewerConfig, loadSceneFromJson } from \"./data/viewer\";\nexport type {\n AssetUrlContext,\n AssetUrlResolver,\n JsonRequestOptions,\n SceneFromViewerConfigOptions,\n LoadSceneFromJsonOptions,\n} from \"./data/viewer\";\nexport { parsePanoProject, loadPanoProject } from \"./data/project\";\nexport type {\n PanoProjectDefinition,\n PanoProjectSceneDefinition,\n LoadedPanoProject,\n LoadedProjectScene,\n LoadPanoProjectOptions,\n} from \"./data/project\";\nexport type { ProjectHotspotDefinition, ProjectHotspotAction, ProjectHotspotTrigger, ProjectCustomHotspotAction, JsonObject, JsonValue } from \"./data/hotspots\";\nexport { resolveHotspotAssets as resolveProjectHotspotAssets } from \"./data/hotspots\";\nexport type {\n ViewerConfig,\n ViewerDocument,\n CubemapViewerConfig,\n SphereViewerConfig,\n} from \"../../../shared/viewer-config\";\n\nexport { resolveProjectPopupAssets } from \"./data/popups\";\nexport type { ProjectPopupDefinition, ProjectPopupBlock, PopupAssetUrlContext, PopupAssetUrlResolver } from \"./data/popups\";\n\nexport { parsePanoMap, resolvePanoMapAssets } from \"./data/map\";\nexport type {\n PanoMapDefinition,\n PanoMapSpotDefinition,\n PanoMapSectorDefinition,\n PanoMapSectorGradient,\n PanoMapGradientStop,\n PanoMapControlsDefinition,\n PanoMapPresentation,\n PanoMapPanelPresentation,\n PanoMapDialogPresentation,\n PanoDragMotion,\n} from \"./data/map\";\n\nexport type { PanoViewLimits } from \"./view-limits\";\n\nexport { hotspotAction, setHotspotAction, projectHotspotTriggers } from \"./data/hotspots\";\n","export type PanoDataErrorCode =\n | \"INVALID_OPTIONS\"\n | \"FETCH_FAILED\"\n | \"HTTP_ERROR\"\n | \"INVALID_JSON\"\n | \"INVALID_CONFIG\"\n | \"UNSUPPORTED_SCHEMA_VERSION\"\n | \"UNSUPPORTED_PROJECTION\"\n | \"INVALID_PROJECT\"\n | \"INVALID_REFERENCE\"\n | \"ABORTED\";\n\nexport class PanoDataError extends Error {\n readonly code: PanoDataErrorCode;\n readonly status?: number;\n readonly sceneId?: string;\n readonly field?: string;\n readonly cause?: unknown;\n constructor(\n code: PanoDataErrorCode,\n message: string,\n details: {\n status?: number;\n sceneId?: string;\n field?: string;\n cause?: unknown;\n } = {}\n ) {\n super(message);\n this.name = \"PanoDataError\";\n this.code = code;\n Object.assign(this, details);\n }\n}\n\nexport function aborted(signal?: AbortSignal | null): void {\n if (signal?.aborted)\n throw new PanoDataError(\"ABORTED\", \"Loading was cancelled\");\n}\n","/** The portable rendering contract shared by the converter and browser viewer. */\nexport type ViewerCubeFace = \"f\" | \"r\" | \"b\" | \"l\" | \"u\" | \"d\";\nexport type CubemapViewerConfig = {\n type: \"tile\";\n multires: { tileSize: number; levels: number[] };\n urlTemplate: string;\n previewUrl: string;\n previewFaceOrder: ViewerCubeFace[];\n};\nexport type SphereViewerConfig = {\n type: \"sphereTile\";\n multires: { tileSize: number; levels: { width: number; height: number }[] };\n urlTemplate: string;\n previewUrl: string;\n indexBase: 0 | 1;\n};\nexport type ViewerConfig = CubemapViewerConfig | SphereViewerConfig;\nexport type ViewerDocument = ViewerConfig & { schemaVersion: 1 };\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function requiredString(value: unknown, field: string): string {\n if (typeof value !== \"string\" || !value.trim())\n throw new Error(`${field}: expected a nonempty string`);\n return value;\n}\n\nfunction positive(value: unknown, field: string): number {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value <= 0)\n throw new Error(`${field}: expected a positive safe integer`);\n return value;\n}\n\nexport function validateViewerConfig(value: unknown): ViewerConfig {\n if (!isRecord(value)) throw new Error(\"viewerConfig: expected an object\");\n if (value.type !== \"tile\" && value.type !== \"sphereTile\")\n throw new Error(\"type: expected tile or sphereTile\");\n if (!isRecord(value.multires))\n throw new Error(\"multires: expected an object\");\n const tileSize = positive(value.multires.tileSize, \"multires.tileSize\");\n if (tileSize > 8192) throw new Error(\"multires.tileSize: maximum is 8192\");\n const input = value.multires.levels;\n if (!Array.isArray(input) || input.length === 0 || input.length > 64)\n throw new Error(\"multires.levels: expected 1 to 64 levels\");\n const urlTemplate = requiredString(value.urlTemplate, \"urlTemplate\");\n const previewUrl = requiredString(value.previewUrl, \"previewUrl\");\n if (/%/.test(urlTemplate.replace(/%s|%l|%0*[hxucvywr]/g, \"\")))\n throw new Error(\"urlTemplate: unsupported placeholder\");\n if (value.type === \"tile\") {\n const levels = input.map((level, i) =>\n positive(level, `multires.levels[${i}]`)\n );\n if (levels.some((level, i) => i > 0 && level <= levels[i - 1]!))\n throw new Error(\"multires.levels: face sizes must increase\");\n const order = value.previewFaceOrder;\n if (\n !Array.isArray(order) ||\n order.length !== 6 ||\n ![\"f\", \"r\", \"b\", \"l\", \"u\", \"d\"].every((face) => order.includes(face))\n )\n throw new Error(\"previewFaceOrder: expected six unique cube faces\");\n return {\n type: \"tile\",\n multires: { tileSize, levels },\n urlTemplate,\n previewUrl,\n previewFaceOrder: [...order] as ViewerCubeFace[],\n };\n }\n if (urlTemplate.includes(\"%s\"))\n throw new Error(\"urlTemplate: sphere has no cube face\");\n if (value.indexBase !== 0 && value.indexBase !== 1)\n throw new Error(\"indexBase: expected 0 or 1\");\n const levels = input.map((level: unknown, i) => {\n if (!isRecord(level))\n throw new Error(`multires.levels[${i}]: expected dimensions`);\n const width = positive(level.width, `multires.levels[${i}].width`);\n const height = positive(level.height, `multires.levels[${i}].height`);\n if (Math.abs(width - 2 * height) > 2)\n throw new Error(`multires.levels[${i}]: expected a full 2:1 panorama`);\n return { width, height };\n });\n if (\n levels.some(\n (level, i) =>\n i > 0 &&\n (level.width <= levels[i - 1]!.width ||\n level.height <= levels[i - 1]!.height)\n )\n )\n throw new Error(\"multires.levels: dimensions must increase\");\n return {\n type: \"sphereTile\",\n multires: { tileSize, levels },\n urlTemplate,\n previewUrl,\n indexBase: value.indexBase,\n };\n}\n","import { resolveAssetUrl } from \"../asset-url\";\nimport type {\n TileAddress,\n TileMultiresConfig,\n} from \"./types\";\n\nfunction positiveInteger(value: number, name: string): number {\n if (!Number.isFinite(value) || value <= 0 || !Number.isInteger(value)) {\n throw new Error(`${name} must be a positive integer, received ${String(value)}`);\n }\n return value;\n}\n\nfunction ascendingLevels(levels: number[]): number[] {\n for (let index = 1; index < levels.length; index += 1) {\n if (levels[index]! <= levels[index - 1]!) {\n throw new Error(\"multires face sizes must be strictly ascending\");\n }\n }\n return levels;\n}\n\nexport function parseMultires(\n multires: string | TileMultiresConfig,\n): TileMultiresConfig {\n if (typeof multires !== \"string\") {\n const tileSize = positiveInteger(multires.tileSize, \"multires.tileSize\");\n if (multires.levels.length === 0) {\n throw new Error(\"multires.levels must contain at least one face size\");\n }\n const levels = ascendingLevels(\n multires.levels.map((level, index) =>\n positiveInteger(level, `multires.levels[${index}]`),\n ),\n );\n return { tileSize, levels };\n }\n\n const values = multires.split(\",\").map((part) => Number(part.trim()));\n\n if (values.length < 2 || values.some((value) => !Number.isFinite(value))) {\n throw new Error(\n \"multires must contain a tile size followed by at least one face size\",\n );\n }\n\n const tileSize = positiveInteger(values[0]!, \"multires tile size\");\n const levels = ascendingLevels(\n values.slice(1).map((level, index) =>\n positiveInteger(level, `multires level ${index + 1}`),\n ),\n );\n return { tileSize, levels };\n}\n\nexport const DEFAULT_TILE_URL_TEMPLATE = \"tiles/%s/l%l/%v/l%l_%s_%h_%v.webp\";\n\nexport function buildDefaultTileUrlTemplate(): string {\n return DEFAULT_TILE_URL_TEMPLATE;\n}\n\nexport function resolveRelativeTileUrl(\n baseUrl: string,\n relativePath: string,\n): string {\n return resolveAssetUrl(baseUrl, relativePath);\n}\n\nexport function resolveTemplateUrl(\n template: string,\n address: Pick<TileAddress, \"face\" | \"level\" | \"row\" | \"col\">,\n): string {\n return template\n .replace(/%s/g, address.face)\n .replace(/%l/g, String(address.level))\n .replace(/%(0*)([hxucvywr])/g, (_match, zeroes: string, placeholder: string) => {\n const value = \"hxuc\".includes(placeholder)\n ? address.col\n : address.row;\n return String(value).padStart(zeroes.length + 1, \"0\");\n });\n}\n","import {\n isRecord,\n validateViewerConfig,\n type ViewerConfig,\n} from \"../../../../shared/viewer-config\";\nimport type { TileScene, SphereTileScene } from \"../scenes\";\nimport type { TileAddress } from \"../tile/types\";\nimport type { SphereTileAddress } from \"../sphere-tile/types\";\nimport { resolveTemplateUrl } from \"../tile/multires\";\nimport { PanoDataError, aborted } from \"./errors\";\n\nexport type AssetUrlContext = {\n defaultUrl: string;\n kind: \"tile\" | \"preview\" | \"hotspot\" | \"map\";\n sceneId: string;\n hotspotId?: string;\n};\nexport type AssetUrlResolver = (\n path: string,\n context: AssetUrlContext\n) => string;\nexport type JsonRequestOptions = {\n requestInit?: Pick<RequestInit, \"headers\" | \"credentials\" | \"signal\">;\n};\nexport type SceneFromViewerConfigOptions = {\n id: string;\n baseUrl: string;\n resolveAssetUrl?: AssetUrlResolver;\n};\nexport type LoadSceneFromJsonOptions = Omit<\n SceneFromViewerConfigOptions,\n \"baseUrl\"\n> &\n JsonRequestOptions & { baseUrl?: string };\n\n/** URL resolution is intentionally independent of React and browser globals on the server. */\nexport function documentUrl(input: string): string {\n try {\n const url = new URL(\n input,\n typeof document === \"undefined\" ? undefined : document.baseURI\n );\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\")\n throw new Error(\"Use HTTP(S)\");\n return url.href;\n } catch (cause) {\n throw new PanoDataError(\n \"INVALID_OPTIONS\",\n \"Expected an HTTP(S) URL; Node.js requires an absolute URL\",\n { cause }\n );\n }\n}\n\nexport function directoryUrl(input: string): string {\n const url = new URL(input);\n url.search = \"\";\n url.hash = \"\";\n if (!url.pathname.endsWith(\"/\")) url.pathname += \"/\";\n return url.href;\n}\n\nexport function resolveResource(baseUrl: string, path: string): string {\n try {\n const url = new URL(path, directoryUrl(baseUrl));\n if (![\"http:\", \"https:\", \"blob:\", \"data:\"].includes(url.protocol))\n throw new Error(\"Unsupported resource URL protocol\");\n return url.href;\n } catch (cause) {\n throw new PanoDataError(\n \"INVALID_CONFIG\",\n `Invalid resource path: ${path}`,\n { cause }\n );\n }\n}\n\nexport function mapResource(\n path: string,\n context: AssetUrlContext,\n resolver?: AssetUrlResolver\n): string {\n let result: string;\n try {\n result = resolver ? resolver(path, context) : context.defaultUrl;\n } catch (cause) {\n throw new PanoDataError(\"INVALID_CONFIG\", \"resolveAssetUrl failed\", {\n sceneId: context.sceneId,\n cause,\n });\n }\n if (typeof result !== \"string\" || !result.trim())\n throw new PanoDataError(\n \"INVALID_CONFIG\",\n \"resolveAssetUrl must return a nonempty final URL\",\n { sceneId: context.sceneId }\n );\n // A root path is already final; relative callback results are ambiguous and rejected.\n if (!result.startsWith(\"/\") && !/^(https?:|blob:|data:)/i.test(result))\n throw new PanoDataError(\n \"INVALID_CONFIG\",\n \"resolveAssetUrl must return an absolute URL or a site-root path\",\n { sceneId: context.sceneId }\n );\n return result;\n}\n\nexport function parseConfig(value: unknown): ViewerConfig {\n if (isRecord(value) && value.type !== \"tile\" && value.type !== \"sphereTile\")\n throw new PanoDataError(\n \"UNSUPPORTED_PROJECTION\",\n \"Expected a tile or sphereTile configuration\",\n { field: \"type\" }\n );\n try {\n return validateViewerConfig(value);\n } catch (cause) {\n const message =\n cause instanceof Error ? cause.message : \"Invalid viewer configuration\";\n throw new PanoDataError(\"INVALID_CONFIG\", message, {\n cause,\n field: message.split(\":\")[0],\n });\n }\n}\n\nexport function sceneFromViewerConfig(\n value: unknown,\n options: SceneFromViewerConfigOptions\n): TileScene | SphereTileScene {\n if (\n !options ||\n typeof options.id !== \"string\" ||\n !options.id.trim() ||\n typeof options.baseUrl !== \"string\" ||\n !options.baseUrl.trim()\n )\n throw new PanoDataError(\"INVALID_OPTIONS\", \"id and baseUrl are required\");\n const config = parseConfig(value);\n const baseUrl = directoryUrl(documentUrl(options.baseUrl));\n const resolve = (path: string, kind: \"tile\" | \"preview\") =>\n mapResource(\n path,\n {\n kind,\n sceneId: options.id,\n defaultUrl: resolveResource(baseUrl, path),\n },\n options.resolveAssetUrl\n );\n const previewUrl = resolve(config.previewUrl, \"preview\");\n if (config.type === \"tile\") {\n return {\n ...config,\n id: options.id,\n baseUrl,\n previewUrl,\n ...(options.resolveAssetUrl\n ? {\n resolveTileUrl: (address: TileAddress) =>\n resolve(resolveTemplateUrl(config.urlTemplate, address), \"tile\"),\n }\n : {}),\n };\n }\n return {\n ...config,\n id: options.id,\n baseUrl,\n previewUrl,\n ...(options.resolveAssetUrl\n ? {\n resolveTileUrl: (address: SphereTileAddress) => {\n // Sphere callbacks use logical zero-based addresses; the document controls storage indices.\n const path = resolveTemplateUrl(config.urlTemplate, {\n face: \"f\",\n level: address.level + config.indexBase,\n row: address.row + config.indexBase,\n col: address.col + config.indexBase,\n });\n return resolve(path, \"tile\");\n },\n }\n : {}),\n };\n}\n\nexport async function readJson(\n url: string,\n options: JsonRequestOptions\n): Promise<{ value: unknown; url: string }> {\n const signal = options.requestInit?.signal;\n aborted(signal);\n let response: Response;\n try {\n response = await fetch(url, { ...options.requestInit, method: \"GET\" });\n } catch (cause) {\n aborted(signal);\n throw new PanoDataError(\n \"FETCH_FAILED\",\n \"Could not fetch JSON; check the network and server CORS settings\",\n { cause }\n );\n }\n aborted(signal);\n if (!response.ok)\n throw new PanoDataError(\n \"HTTP_ERROR\",\n `JSON request returned HTTP ${response.status}`,\n { status: response.status }\n );\n try {\n const value: unknown = await response.json();\n aborted(signal);\n return { value, url: response.url || url };\n } catch (cause) {\n aborted(signal);\n throw new PanoDataError(\n \"INVALID_JSON\",\n \"Expected JSON; check for an HTML fallback or login page\",\n { cause }\n );\n }\n}\n\nexport async function loadSceneFromJson(\n url: string,\n options: LoadSceneFromJsonOptions\n): Promise<TileScene | SphereTileScene> {\n if (!options || typeof options.id !== \"string\" || !options.id.trim())\n throw new PanoDataError(\"INVALID_OPTIONS\", \"id is required\");\n const response = await readJson(documentUrl(url), options);\n if (!isRecord(response.value))\n throw new PanoDataError(\n \"INVALID_CONFIG\",\n \"viewer.json must contain an object\"\n );\n if (response.value.schemaVersion !== 1)\n throw new PanoDataError(\n \"UNSUPPORTED_SCHEMA_VERSION\",\n \"Unsupported viewer.json schemaVersion\",\n { field: \"schemaVersion\" }\n );\n return sceneFromViewerConfig(response.value, {\n ...options,\n baseUrl: options.baseUrl ?? new URL(\".\", response.url).href,\n });\n}\n","/** Camera-center limits in degrees. A yaw min greater than max crosses ±180°. */\nexport type PanoViewLimits = {\n yaw?: { min: number; max: number };\n pitch?: { min: number; max: number };\n fov?: { min: number; max: number };\n};\n\ntype Range = { min: number; max: number };\nexport type ResolvedViewLimits = {\n yaw?: Range;\n pitch: Range;\n fov: Range;\n hardPitch: boolean;\n hardFov: boolean;\n};\n\nexport function parseViewLimits(value: unknown): PanoViewLimits | undefined {\n if (value === undefined) return undefined;\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n throw new Error(\"viewLimits: expected an object\");\n const result: PanoViewLimits = {};\n for (const axis of [\"yaw\", \"pitch\", \"fov\"] as const) {\n const input = (value as Record<string, unknown>)[axis];\n if (input === undefined) continue;\n if (!input || typeof input !== \"object\" || Array.isArray(input))\n throw new Error(`viewLimits.${axis}: expected min and max`);\n const { min, max } = input as Record<string, unknown>;\n const lower = axis === \"yaw\" ? -180 : axis === \"pitch\" ? -90 : 1;\n const upper = axis === \"yaw\" ? 180 : axis === \"pitch\" ? 90 : 179;\n if (typeof min !== \"number\" || typeof max !== \"number\" ||\n !Number.isFinite(min) || !Number.isFinite(max) ||\n min < lower || min > upper || max < lower || max > upper)\n throw new Error(`viewLimits.${axis}: expected finite min and max from ${lower} to ${upper}`);\n if (axis !== \"yaw\" && min > max)\n throw new Error(`viewLimits.${axis}: min must not exceed max`);\n result[axis] = { min, max };\n }\n return result;\n}\n\nexport function resolveViewLimits(\n base: PanoViewLimits | undefined,\n scene: PanoViewLimits | undefined,\n minFov = 30,\n maxFov = 100,\n): ResolvedViewLimits {\n const pitch = scene?.pitch ?? base?.pitch;\n const fov = scene?.fov ?? base?.fov;\n return {\n yaw: scene?.yaw ?? base?.yaw,\n pitch: pitch ?? { min: -90, max: 90 },\n fov: fov ?? { min: minFov, max: maxFov },\n hardPitch: pitch !== undefined,\n hardFov: fov !== undefined,\n };\n}\n\nexport function clampViewAxis(value: number, range: Range): number {\n return Math.max(range.min, Math.min(range.max, value));\n}\n\nexport function normalizeViewYaw(yaw: number): number {\n return ((yaw + 180) % 360 + 360) % 360 - 180;\n}\n\nfunction yawWidth(range: Range | undefined): number {\n if (!range || (range.min === -180 && range.max === 180)) return 360;\n return ((range.max - range.min) % 360 + 360) % 360;\n}\n\n/** Offset in the allowed arc; outside points use the nearest boundary (ties use min). */\nfunction yawOffset(yaw: number, range: Range): number {\n const width = yawWidth(range);\n const offset = ((yaw - range.min) % 360 + 360) % 360;\n if (offset <= width) return offset;\n return offset - width < 360 - offset ? width : 0;\n}\n\nexport function constrainViewYaw(yaw: number, range?: Range): number {\n if (yawWidth(range) === 360) return normalizeViewYaw(yaw);\n return normalizeViewYaw(range!.min + yawOffset(yaw, range!));\n}\n\n/** Clamp relative input before wrapping so a large drag cannot jump across a forbidden arc. */\nexport function applyLimitedYawDelta(yaw: number, delta: number, range?: Range): number {\n const width = yawWidth(range);\n if (width === 360) return normalizeViewYaw(yaw + delta);\n const offset = clampViewAxis(yawOffset(yaw, range!) + delta, { min: 0, max: width });\n return normalizeViewYaw(range!.min + offset);\n}\n\n/** Interpolate inside the allowed arc even when the shorter path leaves it. */\nexport function limitedYawDelta(from: number, to: number, range?: Range, shortestPath = true): number {\n if (yawWidth(range) === 360)\n return shortestPath ? normalizeViewYaw(to - from) : to - from;\n return yawOffset(to, range!) - yawOffset(from, range!);\n}\n","import { isRecord, requiredString } from \"../../../../shared/viewer-config\";\nimport { PanoDataError } from \"./errors\";\nimport { resolveResource } from \"./viewer\";\n\nexport type ProjectPopupBlock = { id: string } & (\n | { type: \"text\"; text: string }\n | { type: \"image\"; src: string; alt?: string }\n | { type: \"video\"; src: string; poster?: string }\n | { type: \"audio\"; src: string }\n);\nexport type ProjectPopupDefinition = {\n id: string;\n title: string;\n blocks: ProjectPopupBlock[];\n};\nexport type PopupAssetUrlContext = {\n defaultUrl: string;\n popupId: string;\n blockId: string;\n field: \"src\" | \"poster\";\n};\nexport type PopupAssetUrlResolver = (path: string, context: PopupAssetUrlContext) => string;\n\nexport function parsePopups(value: unknown, draft = false): ProjectPopupDefinition[] | undefined {\n if (value === undefined) return undefined;\n try {\n if (!Array.isArray(value)) throw new Error(\"popups: expected an array\");\n const ids = new Set<string>();\n const string = (input: unknown, field: string, allowEmpty = false) => {\n if (typeof input !== \"string\" || (!allowEmpty && !input.trim()))\n throw new Error(`${field}: expected a ${allowEmpty ? \"string\" : \"nonempty string\"}`);\n return input;\n };\n return value.map((entry, index) => {\n const field = `popups[${index}]`;\n if (!isRecord(entry)) throw new Error(`${field}: expected an object`);\n const id = requiredString(entry.id, `${field}.id`);\n if (ids.has(id)) throw new Error(`${field}.id: duplicate popup ID`);\n ids.add(id);\n const title = string(entry.title, `${field}.title`, draft);\n if (!Array.isArray(entry.blocks)) throw new Error(`${field}.blocks: expected an array`);\n const blockIds = new Set<string>();\n const blocks = entry.blocks.map((block, i): ProjectPopupBlock => {\n const path = `${field}.blocks[${i}]`;\n if (!isRecord(block)) throw new Error(`${path}: expected an object`);\n const id = requiredString(block.id, `${path}.id`);\n if (blockIds.has(id)) throw new Error(`${path}.id: duplicate block ID`);\n blockIds.add(id);\n if (block.type === \"text\") return { id, type: \"text\", text: string(block.text, `${path}.text`, true) };\n const src = string(block.src, `${path}.src`, draft);\n if (src) resolveResource(\"https://popup.invalid/\", src);\n if (block.type === \"image\") return {\n id, type: \"image\", src,\n ...(block.alt === undefined ? {} : { alt: string(block.alt, `${path}.alt`, true) }),\n };\n if (block.type === \"audio\") return { id, type: \"audio\", src };\n if (block.type === \"video\") {\n const poster = block.poster === undefined ? undefined : string(block.poster, `${path}.poster`, true);\n if (poster) resolveResource(\"https://popup.invalid/\", poster);\n return { id, type: \"video\", src, ...(poster ? { poster } : {}) };\n }\n throw new Error(`${path}.type: unsupported content block`);\n });\n return { id, title, blocks };\n });\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : \"Invalid popup content\";\n throw new PanoDataError(\"INVALID_PROJECT\", message, { field: message.split(\":\")[0], cause });\n }\n}\n\nexport function resolveProjectPopupAssets(\n popup: ProjectPopupDefinition,\n baseUrl: string,\n resolver?: PopupAssetUrlResolver,\n): ProjectPopupDefinition {\n return { ...popup, blocks: popup.blocks.map((block) => {\n if (block.type === \"text\") return { ...block };\n const resolve = (path: string, field: \"src\" | \"poster\") => {\n if (!path) throw new PanoDataError(\"INVALID_PROJECT\", `${popup.id}/${block.id}.${field}: choose a resource`);\n const context = { defaultUrl: resolveResource(baseUrl, path), popupId: popup.id, blockId: block.id, field };\n const result = resolver ? resolver(path, context) : context.defaultUrl;\n if (typeof result !== \"string\" || (!result.startsWith(\"/\") && !/^(https?:|blob:|data:)/i.test(result)))\n throw new PanoDataError(\"INVALID_CONFIG\", \"resolvePopupAssetUrl must return an absolute URL or a site-root path\");\n return result;\n };\n return { ...block, src: resolve(block.src, \"src\"), ...(block.type === \"video\" && block.poster ? { poster: resolve(block.poster, \"poster\") } : {}) };\n }) };\n}\n","/** Resolve image URLs inside CSS cursor values without changing keywords or hotspot coordinates. */\nexport function mapCursorAssets(\n cursor: string,\n resolve: (path: string) => string,\n): string {\n return cursor.replace(\n /url\\(\\s*(?:\"((?:\\\\.|[^\"\\\\])*)\"|'((?:\\\\.|[^'\\\\])*)'|((?:\\\\.|[^)\\\\])*?))\\s*\\)/gi,\n (\n _match,\n double: string | undefined,\n single: string | undefined,\n bare: string | undefined,\n ) => {\n const path = (double ?? single ?? bare ?? \"\").replace(\n /\\\\([\\da-f]{1,6}\\s?|.)/gi,\n (_escape, value: string) =>\n /^[\\da-f]/i.test(value)\n ? String.fromCodePoint(\n Math.min(parseInt(value.trim(), 16), 0x10ffff),\n )\n : value,\n );\n return `url(${JSON.stringify(resolve(path))})`;\n },\n );\n}\n\nexport function cursorImage(cursor: string | undefined): string | undefined {\n let image: string | undefined;\n if (cursor)\n mapCursorAssets(cursor, (path) => {\n image ??= path;\n return path;\n });\n return image;\n}\n\nexport function imageCursor(path: string): string {\n return `url(${JSON.stringify(path)}) 0 0, pointer`;\n}\n","import { mapCursorAssets } from \"../../../../shared/cursor-assets\";\nimport { isRecord, requiredString } from \"../../../../shared/viewer-config\";\nimport type { HotspotDefinition } from \"../hotspot/definitions\";\nimport type { PanoViewerState } from \"../types\";\nimport type { HotspotPosition } from \"../hotspot/types\";\nimport { PanoDataError } from \"./errors\";\nimport { mapResource, resolveResource, type AssetUrlResolver } from \"./viewer\";\n\nexport type JsonValue = null | boolean | number | string | JsonValue[] | JsonObject;\nexport type JsonObject = { [key: string]: JsonValue };\nexport const projectHotspotTriggers = [\"click\", \"pointerenter\", \"pointerleave\"] as const;\nexport type ProjectHotspotTrigger = typeof projectHotspotTriggers[number];\nexport type ProjectCustomHotspotAction = { type: \"custom\"; actionId: string; params?: JsonObject };\nexport function hotspotAction(hotspot: ProjectHotspotDefinition, trigger: ProjectHotspotTrigger) {\n return hotspot.events?.[trigger] ?? (trigger === \"click\" ? hotspot.action : undefined);\n}\nexport function setHotspotAction(hotspot: ProjectHotspotDefinition, trigger: ProjectHotspotTrigger, action?: ProjectHotspotAction): ProjectHotspotDefinition {\n const events = { ...hotspot.events };\n const next: ProjectHotspotDefinition = { ...hotspot, events };\n if (trigger === \"click\") delete next.action;\n if (action) events[trigger] = action;\n else delete events[trigger];\n if (!Object.keys(events).length) delete next.events;\n return next;\n}\nfunction jsonValue(value: unknown, seen = new Set<object>()): JsonValue {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"object\" || !value || seen.has(value)) throw new Error(\"params: expected JSON data\");\n if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new Error(\"params: expected JSON data\");\n seen.add(value);\n const result: JsonValue = Array.isArray(value) ? value.map(item => jsonValue(item, seen)) : Object.fromEntries(Object.entries(value).map(([key, item]) => [key, jsonValue(item, seen)]));\n seen.delete(value);\n return result;\n}\nfunction parseAction(action: unknown): ProjectHotspotAction {\n if (!isRecord(action)) throw new Error(\"action: expected an object\");\n if (action.type === \"scene\") return { type: \"scene\", sceneId: requiredString(action.sceneId, \"action.sceneId\") };\n if (action.type === \"popup\") return { type: \"popup\", popupId: requiredString(action.popupId, \"action.popupId\") };\n if (action.type === \"custom\") {\n if (action.params !== undefined && (!isRecord(action.params) || Array.isArray(action.params))) throw new Error(\"action.params: expected an object\");\n return { type: \"custom\", actionId: requiredString(action.actionId, \"action.actionId\"), ...(action.params === undefined ? {} : { params: jsonValue(action.params) as JsonObject }) };\n }\n if (action.type === \"view\") {\n const position = parsePosition(action.view, \"action.view\");\n const fov = finite((action.view as Record<string, unknown>).fov, \"action.view.fov\");\n if (fov <= 0 || fov >= 180) throw new Error(\"action.view.fov: expected 0 < fov < 180\");\n const duration = action.duration === undefined ? undefined : finite(action.duration, \"action.duration\");\n if (duration !== undefined && duration < 0) throw new Error(\"action.duration: expected a nonnegative number\");\n return { type: \"view\", view: { ...position, fov }, ...(duration === undefined ? {} : { duration }) };\n }\n throw new Error(\"action.type: unsupported action\");\n}\n\nexport type ProjectHotspotAction =\n | ProjectCustomHotspotAction\n | { type: \"scene\"; sceneId: string }\n | { type: \"view\"; view: PanoViewerState; duration?: number }\n | { type: \"popup\"; popupId: string };\n\nexport type ProjectHotspotDefinition = HotspotDefinition & {\n /** Legacy click fallback. events.click takes precedence. */\n action?: ProjectHotspotAction;\n events?: Partial<Record<ProjectHotspotTrigger, ProjectHotspotAction>>;\n};\n\nconst common = [\n \"label\",\n \"visible\",\n \"interactive\",\n \"pointerEvents\",\n \"cursor\",\n \"renderOrder\",\n \"tooltip\",\n \"tooltipTrigger\",\n \"tooltipPlacement\",\n \"tooltipOffset\",\n \"tooltipAppearance\",\n];\nconst point = [\n \"position\",\n \"width\",\n \"height\",\n \"scale\",\n \"mode\",\n \"distance\",\n \"scaleMode\",\n \"referenceFov\",\n \"rotation\",\n \"opacity\",\n];\nconst fields = {\n image: [\"src\"],\n graphic: [\"graphic\"],\n sequence: [\"src\", \"frameCount\", \"frameDirection\", \"playing\", \"fps\", \"loop\"],\n video: [\n \"src\",\n \"poster\",\n \"playing\",\n \"loop\",\n \"muted\",\n \"volume\",\n \"playsInline\",\n \"preload\",\n \"crossOrigin\",\n ],\n audio: [\n \"src\",\n \"format\",\n \"playing\",\n \"loop\",\n \"muted\",\n \"volume\",\n \"pauseWhenHidden\",\n \"range\",\n \"icon\",\n \"playingIcon\",\n \"marker\",\n \"crossOrigin\",\n ],\n text: [\n \"text\",\n \"fontFamily\",\n \"fontSize\",\n \"fontWeight\",\n \"fontStyle\",\n \"color\",\n \"background\",\n \"backgroundOpacity\",\n \"padding\",\n \"align\",\n \"verticalAlign\",\n \"whiteSpace\",\n \"lineHeight\",\n \"borderRadius\",\n \"stroke\",\n \"strokeWidth\",\n ],\n iframe: [\n \"src\",\n \"title\",\n \"sandbox\",\n \"allow\",\n \"referrerPolicy\",\n \"loading\",\n \"pointerPolicy\",\n \"background\",\n ],\n polygon: [\n \"vertices\",\n \"fill\",\n \"fillOpacity\",\n \"stroke\",\n \"strokeWidth\",\n \"strokeOpacity\",\n \"strokeDashSize\",\n \"strokeGapSize\",\n ],\n polyline: [\n \"vertices\",\n \"stroke\",\n \"strokeWidth\",\n \"strokeOpacity\",\n \"strokeDashSize\",\n \"strokeGapSize\",\n ],\n} satisfies Record<HotspotDefinition[\"type\"], string[]>;\nconst booleanFields = new Set([\n \"visible\",\n \"interactive\",\n \"playing\",\n \"loop\",\n \"muted\",\n \"playsInline\",\n \"pauseWhenHidden\",\n \"marker\",\n]);\nconst numberFields = new Set([\n \"renderOrder\",\n \"tooltipOffset\",\n \"width\",\n \"height\",\n \"scale\",\n \"distance\",\n \"referenceFov\",\n \"rotation\",\n \"opacity\",\n \"frameCount\",\n \"fps\",\n \"volume\",\n \"range\",\n \"fontSize\",\n \"backgroundOpacity\",\n \"padding\",\n \"lineHeight\",\n \"borderRadius\",\n \"strokeWidth\",\n \"fillOpacity\",\n \"strokeOpacity\",\n \"strokeDashSize\",\n \"strokeGapSize\",\n]);\nconst positiveFields = new Set([\n \"width\",\n \"height\",\n \"scale\",\n \"distance\",\n \"referenceFov\",\n \"frameCount\",\n \"fps\",\n \"fontSize\",\n \"lineHeight\",\n]);\nconst enums: Record<string, readonly string[]> = {\n pointerEvents: [\"auto\", \"none\"],\n tooltipTrigger: [\"always\", \"hover\", \"click\"],\n tooltipPlacement: [\"top\", \"bottom\", \"left\", \"right\"],\n mode: [\"surface\", \"billboard\"],\n scaleMode: [\"fov\", \"fixed\"],\n frameDirection: [\"horizontal\", \"vertical\"],\n preload: [\"none\", \"metadata\", \"auto\"],\n crossOrigin: [\"\", \"anonymous\", \"use-credentials\"],\n fontStyle: [\"normal\", \"italic\"],\n align: [\"left\", \"center\", \"right\"],\n verticalAlign: [\"top\", \"middle\", \"bottom\"],\n whiteSpace: [\"normal\", \"nowrap\"],\n loading: [\"eager\", \"lazy\"],\n pointerPolicy: [\"hotspot\", \"content\"],\n referrerPolicy: [\n \"\",\n \"no-referrer\",\n \"no-referrer-when-downgrade\",\n \"origin\",\n \"origin-when-cross-origin\",\n \"same-origin\",\n \"strict-origin\",\n \"strict-origin-when-cross-origin\",\n \"unsafe-url\",\n ],\n};\n\nfunction finite(value: unknown, field: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value))\n throw new Error(`${field}: expected a finite number`);\n return value;\n}\n\nexport function parsePosition(value: unknown, field: string): HotspotPosition {\n if (!isRecord(value)) throw new Error(`${field}: expected yaw and pitch`);\n const yaw = finite(value.yaw, `${field}.yaw`);\n const pitch = finite(value.pitch, `${field}.pitch`);\n if (Math.abs(pitch) > 90)\n throw new Error(`${field}.pitch: expected -90 to 90`);\n return { yaw, pitch };\n}\n\nfunction parseGraphic(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) throw new Error(\"graphic: expected an object\");\n const kind = requiredString(value.kind, \"graphic.kind\");\n if (\n ![\n \"circle\",\n \"triangle\",\n \"diamond\",\n \"star\",\n \"arrow\",\n \"rectangle\",\n \"ring\",\n \"svg\",\n \"path\",\n ].includes(kind)\n )\n throw new Error(\"graphic.kind: unsupported graphic\");\n const result: Record<string, unknown> = { kind };\n for (const key of [\"fill\", \"stroke\"]) {\n if (value[key] !== undefined)\n result[key] = requiredString(value[key], `graphic.${key}`);\n }\n for (const key of [\"strokeWidth\", \"cornerRadius\", \"innerRadius\"]) {\n if (value[key] !== undefined)\n result[key] = finite(value[key], `graphic.${key}`);\n }\n if (kind === \"svg\") result.src = requiredString(value.src, \"graphic.src\");\n if (kind === \"path\") {\n result.path = requiredString(value.path, \"graphic.path\");\n if (!Array.isArray(value.viewBox) || value.viewBox.length !== 4)\n throw new Error(\"graphic.viewBox: expected four numbers\");\n const viewBox = value.viewBox.map((n, i) =>\n finite(n, `graphic.viewBox[${i}]`)\n );\n if (viewBox[2]! <= 0 || viewBox[3]! <= 0)\n throw new Error(\"graphic.viewBox: width and height must be positive\");\n result.viewBox = viewBox;\n }\n return result;\n}\n\nfunction parseTooltip(value: unknown): unknown {\n if (typeof value === \"string\") return value;\n if (!isRecord(value)) throw new Error(\"tooltip: expected text or an object\");\n const result: Record<string, string> = {};\n for (const key of [\"text\", \"image\", \"imageAlt\"]) {\n if (value[key] !== undefined) {\n if (typeof value[key] !== \"string\")\n throw new Error(`tooltip.${key}: expected a string`);\n result[key] = value[key];\n }\n }\n return result;\n}\n\nfunction parseAppearance(value: unknown): Record<string, string | number> {\n if (!isRecord(value))\n throw new Error(\"tooltipAppearance: expected an object\");\n const result: Record<string, string | number> = {};\n for (const key of [\n \"background\",\n \"color\",\n \"border\",\n \"borderRadius\",\n \"shadow\",\n \"padding\",\n \"fontSize\",\n \"fontFamily\",\n \"lineHeight\",\n \"letterSpacing\",\n ]) {\n const item = value[key];\n if (item === undefined) continue;\n if (\n [\"background\", \"color\", \"border\", \"shadow\", \"fontFamily\"].includes(key) &&\n typeof item !== \"string\"\n )\n throw new Error(`tooltipAppearance.${key}: expected a string`);\n if (\n typeof item !== \"string\" &&\n (typeof item !== \"number\" || !Number.isFinite(item))\n )\n throw new Error(\n `tooltipAppearance.${key}: expected a string or finite number`\n );\n result[key] = item;\n }\n return result;\n}\n\nexport function parseHotspot(\n value: unknown,\n sceneId: string,\n field: string\n): ProjectHotspotDefinition {\n try {\n if (!isRecord(value)) throw new Error(\"expected a hotspot object\");\n const type = requiredString(value.type, \"type\");\n if (!Object.prototype.hasOwnProperty.call(fields, type))\n throw new Error(\"type: unsupported hotspot type\");\n const kind = type as HotspotDefinition[\"type\"];\n const result: Record<string, unknown> = {\n type,\n id: requiredString(value.id, \"id\"),\n };\n const isPath = kind === \"polygon\" || kind === \"polyline\";\n const allowed = [...common, ...(isPath ? [] : point), ...fields[kind]];\n for (const key of allowed) {\n const item = value[key];\n if (item === undefined) continue;\n if (key === \"position\") result[key] = parsePosition(item, key);\n else if (key === \"vertices\") {\n if (!Array.isArray(item) || item.length < (kind === \"polygon\" ? 3 : 2))\n throw new Error(\"vertices: not enough points\");\n result[key] = item.map((p, i) => parsePosition(p, `vertices[${i}]`));\n } else if (key === \"graphic\") result[key] = parseGraphic(item);\n else if (key === \"tooltip\") result[key] = parseTooltip(item);\n else if (key === \"tooltipAppearance\") result[key] = parseAppearance(item);\n else if (booleanFields.has(key)) {\n if (typeof item !== \"boolean\")\n throw new Error(`${key}: expected a boolean`);\n result[key] = item;\n } else if (numberFields.has(key)) {\n const n = finite(item, key);\n if (positiveFields.has(key) && n <= 0)\n throw new Error(`${key}: expected a positive number`);\n if (key === \"frameCount\" && !Number.isSafeInteger(n))\n throw new Error(\"frameCount: expected an integer\");\n if (\n [\n \"opacity\",\n \"fillOpacity\",\n \"strokeOpacity\",\n \"volume\",\n \"backgroundOpacity\",\n ].includes(key) &&\n (n < 0 || n > 1)\n )\n throw new Error(`${key}: expected 0 to 1`);\n result[key] = n;\n } else if (key === \"fontWeight\" && typeof item === \"number\")\n result[key] = finite(item, key);\n else if (\n (key === \"src\" || key === \"format\") &&\n kind === \"audio\" &&\n Array.isArray(item)\n ) {\n if (!item.length)\n throw new Error(`${key}: expected audio ${key === \"src\" ? \"sources\" : \"formats\"}`);\n result[key] = item.map((entry, i) => requiredString(entry, `${key}[${i}]`));\n } else {\n if (typeof item !== \"string\")\n throw new Error(`${key}: expected a string`);\n if (enums[key] && !enums[key].includes(item))\n throw new Error(`${key}: unsupported value`);\n result[key] = item;\n }\n }\n if (!isPath && !result.position) throw new Error(\"position: required\");\n if (isPath && !result.vertices) throw new Error(\"vertices: required\");\n if (\n [\"image\", \"sequence\", \"video\", \"audio\", \"iframe\"].includes(kind) &&\n !(typeof result.src === \"string\"\n ? result.src.trim()\n : Array.isArray(result.src))\n )\n throw new Error(\"src: required\");\n if (kind === \"graphic\" && !result.graphic)\n throw new Error(\"graphic: required\");\n if (kind === \"text\" && typeof result.text !== \"string\")\n throw new Error(\"text: required\");\n if (kind === \"sequence\" && !result.frameCount)\n throw new Error(\"frameCount: required\");\n if (value.action !== undefined) result.action = parseAction(value.action);\n if (value.events !== undefined) {\n if (!isRecord(value.events)) throw new Error(\"events: expected an object\");\n const events: Partial<Record<ProjectHotspotTrigger, ProjectHotspotAction>> = {};\n for (const key of Object.keys(value.events)) {\n if (!projectHotspotTriggers.includes(key as ProjectHotspotTrigger)) throw new Error(`events.${key}: unsupported trigger`);\n try { events[key as ProjectHotspotTrigger] = parseAction(value.events[key]); }\n catch (error) { throw new Error(`events.${key}.${error instanceof Error ? error.message : \"invalid action\"}`); }\n }\n result.events = events;\n }\n return result as ProjectHotspotDefinition;\n } catch (cause) {\n const detail = cause instanceof Error ? cause.message : \"Invalid hotspot\";\n throw new PanoDataError(\"INVALID_PROJECT\", `${field}.${detail}`, {\n sceneId,\n field: `${field}.${detail.split(\":\")[0]}`,\n cause,\n });\n }\n}\n\nexport function resolveHotspotAssets(\n hotspot: ProjectHotspotDefinition,\n baseUrl: string,\n sceneId: string,\n resolver?: AssetUrlResolver\n): ProjectHotspotDefinition {\n const resolve = (path: string) =>\n path\n ? mapResource(\n path,\n {\n kind: \"hotspot\",\n sceneId,\n hotspotId: hotspot.id,\n defaultUrl: resolveResource(baseUrl, path),\n },\n resolver\n )\n : path;\n const result = { ...hotspot };\n if (result.cursor) result.cursor = mapCursorAssets(result.cursor, resolve);\n if (result.tooltipAppearance?.background) result.tooltipAppearance = {\n ...result.tooltipAppearance,\n background: mapCursorAssets(result.tooltipAppearance.background, resolve),\n };\n if (\"src\" in result)\n result.src = Array.isArray(result.src)\n ? result.src.map(resolve)\n : resolve(result.src);\n if (\"poster\" in result && result.poster)\n result.poster = resolve(result.poster);\n if (result.type === \"audio\") {\n if (result.icon) result.icon = resolve(result.icon);\n if (result.playingIcon) result.playingIcon = resolve(result.playingIcon);\n }\n if (result.type === \"graphic\" && result.graphic.kind === \"svg\")\n result.graphic = { ...result.graphic, src: resolve(result.graphic.src) };\n if (typeof result.tooltip === \"object\")\n result.tooltip = {\n ...result.tooltip,\n ...(result.tooltip.image ? { image: resolve(result.tooltip.image) } : {}),\n };\n return result;\n}\n","import type { CSSProperties } from \"react\";\n\nexport const PANO_OVERLAY_ALIGNS = [\n \"top\",\n \"bottom\",\n \"left\",\n \"right\",\n \"top-left\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-right\",\n] as const;\n\nexport type PanoOverlayAlign = (typeof PANO_OVERLAY_ALIGNS)[number];\n\nexport type PanoOverlayAxis = \"horizontal\" | \"vertical\";\n\nexport type PanoOverlayInset =\n | number\n | string\n | {\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n };\n\n/** Shared screen-edge anchor for planar overlay chrome. */\nexport type PanoOverlayAnchor = {\n align?: PanoOverlayAlign;\n /** Used for corner anchors. Edges infer the axis and ignore this value. */\n axis?: PanoOverlayAxis;\n inset?: PanoOverlayInset;\n};\n\nexport type PanoOverlayCollapseEdge = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport type PanoOverlayContentAlign = \"start\" | \"center\" | \"end\";\n\nexport type ResolvedOverlayInset = {\n top: string;\n right: string;\n bottom: string;\n left: string;\n};\n\nexport type ResolvedOverlayAnchor = {\n align: PanoOverlayAlign;\n axis: PanoOverlayAxis;\n inset: ResolvedOverlayInset;\n collapseEdge: PanoOverlayCollapseEdge;\n contentAlign: PanoOverlayContentAlign;\n dockInset: string;\n};\n\nconst ALIGN_LIST = PANO_OVERLAY_ALIGNS.join(\", \");\n\nconst SAFE = {\n top: \"var(--pano-safe-top)\",\n right: \"var(--pano-safe-right)\",\n bottom: \"var(--pano-safe-bottom)\",\n left: \"var(--pano-safe-left)\",\n} as const;\n\nexport function cssLength(value: number | string): string {\n return typeof value === \"number\" ? `${value}px` : value;\n}\n\nexport function isOverlayCorner(align: PanoOverlayAlign): boolean {\n switch (align) {\n case \"top-left\":\n case \"top-right\":\n case \"bottom-left\":\n case \"bottom-right\":\n return true;\n case \"top\":\n case \"bottom\":\n case \"left\":\n case \"right\":\n return false;\n default: {\n const exhaustive: never = align;\n return exhaustive;\n }\n }\n}\n\nexport function resolveOverlayAxis(\n align: PanoOverlayAlign,\n axis: PanoOverlayAxis | undefined,\n): PanoOverlayAxis {\n switch (align) {\n case \"top\":\n case \"bottom\":\n return \"horizontal\";\n case \"left\":\n case \"right\":\n return \"vertical\";\n case \"top-left\":\n case \"top-right\":\n case \"bottom-left\":\n case \"bottom-right\":\n return axis ?? \"horizontal\";\n default: {\n const exhaustive: never = align;\n return exhaustive;\n }\n }\n}\n\nexport function overlayCollapseEdge(\n align: PanoOverlayAlign,\n axis: PanoOverlayAxis | undefined,\n): PanoOverlayCollapseEdge {\n switch (align) {\n case \"top\":\n return \"top\";\n case \"bottom\":\n return \"bottom\";\n case \"left\":\n return \"left\";\n case \"right\":\n return \"right\";\n case \"top-left\":\n return resolveOverlayAxis(align, axis) === \"horizontal\" ? \"top\" : \"left\";\n case \"top-right\":\n return resolveOverlayAxis(align, axis) === \"horizontal\" ? \"top\" : \"right\";\n case \"bottom-left\":\n return resolveOverlayAxis(align, axis) === \"horizontal\" ? \"bottom\" : \"left\";\n case \"bottom-right\":\n return resolveOverlayAxis(align, axis) === \"horizontal\" ? \"bottom\" : \"right\";\n default: {\n const exhaustive: never = align;\n return exhaustive;\n }\n }\n}\n\nexport type PanoOverlayChevron = \"up\" | \"down\" | \"left\" | \"right\";\n\n/** Chevron toward the outer edge when expanded, and back inward when collapsed. */\nexport function overlayChevron(\n edge: PanoOverlayCollapseEdge,\n collapsed: boolean,\n): PanoOverlayChevron {\n switch (edge) {\n case \"top\":\n return collapsed ? \"down\" : \"up\";\n case \"bottom\":\n return collapsed ? \"up\" : \"down\";\n case \"left\":\n return collapsed ? \"right\" : \"left\";\n case \"right\":\n return collapsed ? \"left\" : \"right\";\n default: {\n const exhaustive: never = edge;\n return exhaustive;\n }\n }\n}\n\nexport function overlayContentAlign(\n align: PanoOverlayAlign,\n axis: PanoOverlayAxis | undefined,\n): PanoOverlayContentAlign {\n const resolved = resolveOverlayAxis(align, axis);\n if (resolved === \"horizontal\") {\n switch (align) {\n case \"top-left\":\n case \"bottom-left\":\n return \"start\";\n case \"top-right\":\n case \"bottom-right\":\n return \"end\";\n case \"top\":\n case \"bottom\":\n case \"left\":\n case \"right\":\n return \"center\";\n default: {\n const exhaustive: never = align;\n return exhaustive;\n }\n }\n }\n switch (align) {\n case \"top-left\":\n case \"top-right\":\n return \"start\";\n case \"bottom-left\":\n case \"bottom-right\":\n return \"end\";\n case \"top\":\n case \"bottom\":\n case \"left\":\n case \"right\":\n return \"center\";\n default: {\n const exhaustive: never = align;\n return exhaustive;\n }\n }\n}\n\nexport function resolveOverlayInset(\n inset: PanoOverlayInset | undefined,\n fallback: number | string,\n): ResolvedOverlayInset {\n const fallbackLength = cssLength(fallback);\n if (inset === undefined) {\n return {\n top: fallbackLength,\n right: fallbackLength,\n bottom: fallbackLength,\n left: fallbackLength,\n };\n }\n if (typeof inset === \"number\" || typeof inset === \"string\") {\n const value = cssLength(inset);\n return { top: value, right: value, bottom: value, left: value };\n }\n return {\n top: cssLength(inset.top ?? fallback),\n right: cssLength(inset.right ?? fallback),\n bottom: cssLength(inset.bottom ?? fallback),\n left: cssLength(inset.left ?? fallback),\n };\n}\n\nexport function overlayDockInset(\n edge: PanoOverlayCollapseEdge,\n inset: ResolvedOverlayInset,\n): string {\n switch (edge) {\n case \"top\":\n return inset.top;\n case \"bottom\":\n return inset.bottom;\n case \"left\":\n return inset.left;\n case \"right\":\n return inset.right;\n default: {\n const exhaustive: never = edge;\n return exhaustive;\n }\n }\n}\n\nexport function resolveOverlayAnchor(\n anchor: PanoOverlayAnchor | undefined,\n defaults: { align: PanoOverlayAlign; inset: number | string },\n): ResolvedOverlayAnchor {\n const align = anchor?.align ?? defaults.align;\n const axis = resolveOverlayAxis(align, anchor?.axis);\n const inset = resolveOverlayInset(anchor?.inset, defaults.inset);\n const collapseEdge = overlayCollapseEdge(align, anchor?.axis);\n return {\n align,\n axis,\n inset,\n collapseEdge,\n contentAlign: overlayContentAlign(align, anchor?.axis),\n dockInset: overlayDockInset(collapseEdge, inset),\n };\n}\n\nfunction withSafe(inset: string, safeVariable: string): string {\n return `calc(${inset} + ${safeVariable})`;\n}\n\nfunction maxBox(inset: ResolvedOverlayInset): Pick<CSSProperties, \"maxWidth\" | \"maxHeight\"> {\n return {\n maxWidth: `calc(100% - ${inset.left} - ${inset.right} - ${SAFE.left} - ${SAFE.right})`,\n maxHeight: `calc(100% - ${inset.top} - ${inset.bottom} - ${SAFE.top} - ${SAFE.bottom})`,\n };\n}\n\nfunction horizontalSpan(\n inset: ResolvedOverlayInset,\n width: string | undefined,\n): Pick<CSSProperties, \"left\" | \"right\" | \"width\" | \"marginInline\"> {\n const left = withSafe(inset.left, SAFE.left);\n const right = withSafe(inset.right, SAFE.right);\n if (width === undefined) {\n return { left, right, width: undefined, marginInline: undefined };\n }\n return { left, right, width, marginInline: \"auto\" };\n}\n\nfunction verticalSpan(\n inset: ResolvedOverlayInset,\n height: string | undefined,\n): Pick<CSSProperties, \"top\" | \"bottom\" | \"height\" | \"marginBlock\"> {\n const top = withSafe(inset.top, SAFE.top);\n const bottom = withSafe(inset.bottom, SAFE.bottom);\n if (height === undefined) {\n return { top, bottom, height: undefined, marginBlock: undefined };\n }\n return { top, bottom, height, marginBlock: \"auto\" };\n}\n\n/**\n * Position a planar overlay on one of eight anchors.\n * Edge anchors center along that edge when the main-axis size is set, and\n * stretch between the cross-axis insets when it is omitted. Corners pin to\n * both adjacent edges and shrink to content when a size is omitted.\n */\nexport function overlayBoxStyle(\n align: PanoOverlayAlign,\n inset: ResolvedOverlayInset,\n width: number | string | undefined,\n height: number | string | undefined,\n): CSSProperties {\n const widthValue = width === undefined ? undefined : cssLength(width);\n const heightValue = height === undefined ? undefined : cssLength(height);\n const limits = maxBox(inset);\n switch (align) {\n case \"top\":\n return {\n ...horizontalSpan(inset, widthValue),\n top: withSafe(inset.top, SAFE.top),\n bottom: \"auto\",\n height: heightValue,\n ...limits,\n };\n case \"bottom\":\n return {\n ...horizontalSpan(inset, widthValue),\n top: \"auto\",\n bottom: withSafe(inset.bottom, SAFE.bottom),\n height: heightValue,\n ...limits,\n };\n case \"left\":\n return {\n ...verticalSpan(inset, heightValue),\n left: withSafe(inset.left, SAFE.left),\n right: \"auto\",\n width: widthValue,\n ...limits,\n };\n case \"right\":\n return {\n ...verticalSpan(inset, heightValue),\n left: \"auto\",\n right: withSafe(inset.right, SAFE.right),\n width: widthValue,\n ...limits,\n };\n case \"top-left\":\n return {\n top: withSafe(inset.top, SAFE.top),\n left: withSafe(inset.left, SAFE.left),\n right: \"auto\",\n bottom: \"auto\",\n width: widthValue,\n height: heightValue,\n ...limits,\n };\n case \"top-right\":\n return {\n top: withSafe(inset.top, SAFE.top),\n right: withSafe(inset.right, SAFE.right),\n left: \"auto\",\n bottom: \"auto\",\n width: widthValue,\n height: heightValue,\n ...limits,\n };\n case \"bottom-left\":\n return {\n bottom: withSafe(inset.bottom, SAFE.bottom),\n left: withSafe(inset.left, SAFE.left),\n top: \"auto\",\n right: \"auto\",\n width: widthValue,\n height: heightValue,\n ...limits,\n };\n case \"bottom-right\":\n return {\n bottom: withSafe(inset.bottom, SAFE.bottom),\n right: withSafe(inset.right, SAFE.right),\n top: \"auto\",\n left: \"auto\",\n width: widthValue,\n height: heightValue,\n ...limits,\n };\n default: {\n const exhaustive: never = align;\n return exhaustive;\n }\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseInsetLength(value: unknown, field: string): number | string {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\" && value.trim()) return value;\n throw new Error(`${field}: expected a finite number or a nonempty string`);\n}\n\nfunction parseInset(value: unknown, field: string): PanoOverlayInset {\n if (typeof value === \"number\" || typeof value === \"string\") {\n return parseInsetLength(value, field);\n }\n if (!isRecord(value)) throw new Error(`${field}: expected a number, string, or object`);\n const sides = [\"top\", \"right\", \"bottom\", \"left\"] as const;\n const inset: {\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n } = {};\n for (const side of sides) {\n if (value[side] === undefined) continue;\n inset[side] = parseInsetLength(value[side], `${field}.${side}`);\n }\n return inset;\n}\n\n/** Validate an anchor object from a project document. */\nexport function parseOverlayAnchor(value: unknown, field: string): PanoOverlayAnchor {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const align =\n value.align === undefined\n ? undefined\n : typeof value.align === \"string\" &&\n (PANO_OVERLAY_ALIGNS as readonly string[]).includes(value.align)\n ? (value.align as PanoOverlayAlign)\n : (() => {\n throw new Error(`${field}.align: expected ${ALIGN_LIST}`);\n })();\n const axis =\n value.axis === undefined\n ? undefined\n : value.axis === \"horizontal\" || value.axis === \"vertical\"\n ? value.axis\n : (() => {\n throw new Error(`${field}.axis: expected \"horizontal\" or \"vertical\"`);\n })();\n const inset = value.inset === undefined ? undefined : parseInset(value.inset, `${field}.inset`);\n return {\n ...(align === undefined ? {} : { align }),\n ...(axis === undefined ? {} : { axis }),\n ...(inset === undefined ? {} : { inset }),\n };\n}\n","import { isRecord, requiredString } from \"../../../../shared/viewer-config\";\nimport type { PanoDragMotion } from \"../drag-motion\";\nimport { parseOverlayAnchor, type PanoOverlayAnchor } from \"../overlay/align\";\nimport { PanoDataError } from \"./errors\";\nimport {\n mapResource,\n resolveResource,\n type AssetUrlResolver,\n} from \"./viewer\";\n\nexport type { PanoDragMotion };\n\nexport type PanoMapGradientStop = {\n offset: number;\n color: string;\n opacity?: number;\n};\n\nexport type PanoMapSectorGradient = {\n type: \"radial\" | \"linear\";\n stops: PanoMapGradientStop[];\n};\n\nexport type PanoMapSectorDefinition = {\n /** Sector opening angle in degrees. */\n angle: number;\n /** Sector radius in CSS pixels; does not scale with the floor image. */\n radius: number;\n /** When true, sector angle follows the current horizontal FOV. */\n followFov?: boolean;\n /** Solid fill color when `gradient` is omitted. */\n color?: string;\n /**\n * Overall fill opacity in [0, 1].\n * Applies in both solid and gradient modes; gradient stop opacities only\n * describe the relative fade shape and are normalized against this value.\n */\n opacity?: number;\n /** Optional sector outline color. */\n strokeColor?: string;\n /** Outline width in CSS pixels. */\n strokeWidth?: number;\n /** Outline opacity in [0, 1]. Defaults to 1 when stroke is set. */\n strokeOpacity?: number;\n /**\n * Optional fill gradient. When omitted, the sector uses a solid `color`.\n * Stop colors are independent of `color` unless the author keeps them in sync.\n */\n gradient?: PanoMapSectorGradient;\n};\n\nexport type PanoMapSpotDefinition = {\n id: string;\n sceneId: string;\n /** Normalized image X in [0, 1], origin at the top-left. */\n x: number;\n /** Normalized image Y in [0, 1], origin at the top-left. */\n y: number;\n /**\n * Clockwise degrees from image up when viewer yaw is 0.\n * Runtime sector rotation is `heading + yaw`.\n */\n heading: number;\n icon?: string;\n};\n\nexport type PanoMapControlsDefinition = {\n /** Show the edge tab that slides a panel off-screen. */\n collapse?: boolean;\n /** Show zoom-in and zoom-out buttons. */\n zoom?: boolean;\n};\n\nexport type PanoMapPanelPresentation = {\n mode: \"panel\";\n anchor?: PanoOverlayAnchor;\n width?: number;\n height?: number;\n};\n\nexport type PanoMapDialogPresentation = {\n mode: \"dialog\";\n anchor?: PanoOverlayAnchor;\n width?: number;\n height?: number;\n};\n\nexport type PanoMapPresentation =\n | PanoMapPanelPresentation\n | PanoMapDialogPresentation;\n\nexport type PanoMapDefinition = {\n image: string;\n /**\n * Pointer interaction with the floor image.\n * - `fixed`: fit-only; no wheel/pan zoom (zoom buttons are also suppressed).\n * - `zoom`: wheel/pan zoom and optional zoom buttons.\n */\n interaction?: \"fixed\" | \"zoom\";\n presentation?: PanoMapPresentation;\n controls?: PanoMapControlsDefinition;\n /** Spot icon edge length in CSS pixels. */\n iconSize?: number;\n /**\n * Maximum zoom multiplier relative to the contain-fit scale.\n * Only applies when `interaction` is `\"zoom\"`. Defaults to 8.\n */\n maxScale?: number;\n /**\n * Pan inertia and edge bounce when `interaction` is `\"zoom\"`.\n * Omit for both on; set `false` or flag fields to disable.\n */\n dragMotion?: PanoDragMotion | false;\n spots: PanoMapSpotDefinition[];\n sector?: PanoMapSectorDefinition;\n};\n\nfunction optionalNumber(\n record: Record<string, unknown>,\n key: string,\n options: { min?: number; max?: number; exclusiveMin?: number; exclusiveMax?: number } = {},\n): number | undefined {\n const value = record[key];\n if (value === undefined) return undefined;\n if (typeof value !== \"number\" || !Number.isFinite(value))\n throw new Error(`${key}: expected a finite number`);\n if (options.min !== undefined && value < options.min)\n throw new Error(`${key}: expected a number >= ${options.min}`);\n if (options.max !== undefined && value > options.max)\n throw new Error(`${key}: expected a number <= ${options.max}`);\n if (options.exclusiveMin !== undefined && value <= options.exclusiveMin)\n throw new Error(`${key}: expected a number > ${options.exclusiveMin}`);\n if (options.exclusiveMax !== undefined && value >= options.exclusiveMax)\n throw new Error(`${key}: expected a number < ${options.exclusiveMax}`);\n return value;\n}\n\nfunction requiredNumber(\n record: Record<string, unknown>,\n key: string,\n options: { min?: number; max?: number; exclusiveMin?: number; exclusiveMax?: number } = {},\n): number {\n const value = optionalNumber(record, key, options);\n if (value === undefined) throw new Error(`${key}: expected a finite number`);\n return value;\n}\n\nfunction optionalString(\n record: Record<string, unknown>,\n key: string,\n): string | undefined {\n return record[key] === undefined\n ? undefined\n : requiredString(record[key], key);\n}\n\nfunction parseGradientStop(\n value: unknown,\n field: string,\n): PanoMapGradientStop {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const offset = requiredNumber(value, \"offset\", { min: 0, max: 1 });\n const color = requiredString(value.color, `${field}.color`);\n const opacity = optionalNumber(value, \"opacity\", { min: 0, max: 1 });\n return {\n offset,\n color,\n ...(opacity === undefined ? {} : { opacity }),\n };\n}\n\nfunction parseSector(value: unknown, field: string): PanoMapSectorDefinition {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const angle = requiredNumber(value, \"angle\", { exclusiveMin: 0, exclusiveMax: 360 });\n const radius = requiredNumber(value, \"radius\", { exclusiveMin: 0 });\n const followFov =\n value.followFov === undefined\n ? undefined\n : value.followFov === true\n ? true\n : value.followFov === false\n ? false\n : (() => {\n throw new Error(`${field}.followFov: expected a boolean`);\n })();\n const color = optionalString(value, \"color\");\n const opacity = optionalNumber(value, \"opacity\", { min: 0, max: 1 });\n const strokeColor = optionalString(value, \"strokeColor\");\n const strokeWidth = optionalNumber(value, \"strokeWidth\", { min: 0 });\n const strokeOpacity = optionalNumber(value, \"strokeOpacity\", { min: 0, max: 1 });\n let gradient: PanoMapSectorGradient | undefined;\n if (value.gradient !== undefined) {\n if (!isRecord(value.gradient))\n throw new Error(`${field}.gradient: expected an object`);\n const type = value.gradient.type;\n if (type !== \"radial\" && type !== \"linear\")\n throw new Error(`${field}.gradient.type: expected \"radial\" or \"linear\"`);\n if (!Array.isArray(value.gradient.stops) || value.gradient.stops.length < 2)\n throw new Error(`${field}.gradient.stops: expected at least two stops`);\n gradient = {\n type,\n stops: value.gradient.stops.map((stop, index) =>\n parseGradientStop(stop, `${field}.gradient.stops[${index}]`),\n ),\n };\n }\n return {\n angle,\n radius,\n ...(followFov === undefined ? {} : { followFov }),\n ...(color === undefined ? {} : { color }),\n ...(opacity === undefined ? {} : { opacity }),\n ...(strokeColor === undefined ? {} : { strokeColor }),\n ...(strokeWidth === undefined ? {} : { strokeWidth }),\n ...(strokeOpacity === undefined ? {} : { strokeOpacity }),\n ...(gradient === undefined ? {} : { gradient }),\n };\n}\n\nfunction parsePresentation(\n value: unknown,\n field: string,\n): PanoMapPresentation {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const mode = value.mode;\n if (mode === \"docked\") {\n throw new Error(`${field}.mode: \"docked\" was removed; expected \"panel\" or \"dialog\"`);\n }\n if (mode !== \"panel\" && mode !== \"dialog\") {\n throw new Error(`${field}.mode: expected \"panel\" or \"dialog\"`);\n }\n if (\"corner\" in value) {\n throw new Error(`${field}.corner: use anchor.align`);\n }\n if (\"offsetX\" in value) {\n throw new Error(`${field}.offsetX: use anchor.inset`);\n }\n if (\"offsetY\" in value) {\n throw new Error(`${field}.offsetY: use anchor.inset`);\n }\n const anchor =\n value.anchor === undefined\n ? undefined\n : parseOverlayAnchor(value.anchor, `${field}.anchor`);\n const width = optionalNumber(value, \"width\", { exclusiveMin: 0 });\n const height = optionalNumber(value, \"height\", { exclusiveMin: 0 });\n return {\n mode,\n ...(anchor === undefined ? {} : { anchor }),\n ...(width === undefined ? {} : { width }),\n ...(height === undefined ? {} : { height }),\n };\n}\n\nfunction parseOptionalBoolean(\n value: unknown,\n field: string,\n): boolean | undefined {\n if (value === undefined) return undefined;\n if (value === true) return true;\n if (value === false) return false;\n throw new Error(`${field}: expected a boolean`);\n}\n\nfunction parseDragMotion(\n value: unknown,\n field: string,\n): PanoDragMotion | false {\n if (value === false) return false;\n if (!isRecord(value)) throw new Error(`${field}: expected an object or false`);\n const inertia = parseOptionalBoolean(value.inertia, `${field}.inertia`);\n const bounce = parseOptionalBoolean(value.bounce, `${field}.bounce`);\n const motion: PanoDragMotion = {\n ...(inertia === undefined ? {} : { inertia }),\n ...(bounce === undefined ? {} : { bounce }),\n };\n return motion;\n}\n\nfunction parseControls(\n value: unknown,\n field: string,\n): PanoMapControlsDefinition {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const collapse =\n value.collapse === undefined\n ? undefined\n : value.collapse === true\n ? true\n : value.collapse === false\n ? false\n : (() => {\n throw new Error(`${field}.collapse: expected a boolean`);\n })();\n const zoom =\n value.zoom === undefined\n ? undefined\n : value.zoom === true\n ? true\n : value.zoom === false\n ? false\n : (() => {\n throw new Error(`${field}.zoom: expected a boolean`);\n })();\n return {\n ...(collapse === undefined ? {} : { collapse }),\n ...(zoom === undefined ? {} : { zoom }),\n };\n}\n\nfunction parseSpot(\n value: unknown,\n field: string,\n sceneIds: Set<string>,\n): PanoMapSpotDefinition {\n if (!isRecord(value)) throw new Error(`${field}: expected an object`);\n const id = requiredString(value.id, `${field}.id`);\n const sceneId = requiredString(value.sceneId, `${field}.sceneId`);\n if (!sceneIds.has(sceneId))\n throw new Error(`${field}.sceneId: scene does not exist`);\n const x = requiredNumber(value, \"x\", { min: 0, max: 1 });\n const y = requiredNumber(value, \"y\", { min: 0, max: 1 });\n const heading = requiredNumber(value, \"heading\");\n const icon = optionalString(value, \"icon\");\n if (icon) resolveResource(\"https://map.invalid/\", icon);\n return {\n id,\n sceneId,\n x,\n y,\n heading,\n ...(icon === undefined ? {} : { icon }),\n };\n}\n\n/** Parse an optional project floor plan. Scene IDs must already be collected. */\nexport function parsePanoMap(\n value: unknown,\n sceneIds: Set<string>,\n options: { draft?: boolean } = {},\n): PanoMapDefinition | undefined {\n if (value === undefined) return undefined;\n try {\n if (!isRecord(value)) throw new Error(\"map: expected an object\");\n if (typeof value.image !== \"string\" || (!options.draft && !value.image.trim()))\n throw new Error(\"map.image: expected a nonempty string\");\n const image = value.image;\n if (image.trim()) resolveResource(\"https://map.invalid/\", image);\n const interaction =\n value.interaction === undefined\n ? undefined\n : value.interaction === \"fixed\" || value.interaction === \"zoom\"\n ? value.interaction\n : (() => {\n throw new Error('map.interaction: expected \"fixed\" or \"zoom\"');\n })();\n const presentation =\n value.presentation === undefined\n ? undefined\n : parsePresentation(value.presentation, \"map.presentation\");\n const controls =\n value.controls === undefined\n ? undefined\n : parseControls(value.controls, \"map.controls\");\n const iconSize = optionalNumber(value, \"iconSize\", { exclusiveMin: 0 });\n const maxScale = optionalNumber(value, \"maxScale\", { min: 1 });\n const dragMotion =\n value.dragMotion === undefined\n ? undefined\n : parseDragMotion(value.dragMotion, \"map.dragMotion\");\n if (!Array.isArray(value.spots)) throw new Error(\"map.spots: expected an array\");\n const spotIds = new Set<string>();\n const spots = value.spots.map((spot, index) => {\n const parsed = parseSpot(spot, `map.spots[${index}]`, sceneIds);\n if (spotIds.has(parsed.id))\n throw new Error(`map.spots[${index}].id: duplicate spot ID`);\n spotIds.add(parsed.id);\n return parsed;\n });\n const sector =\n value.sector === undefined\n ? undefined\n : parseSector(value.sector, \"map.sector\");\n return {\n image,\n ...(interaction === undefined ? {} : { interaction }),\n ...(presentation === undefined ? {} : { presentation }),\n ...(controls === undefined ? {} : { controls }),\n ...(iconSize === undefined ? {} : { iconSize }),\n ...(maxScale === undefined ? {} : { maxScale }),\n ...(dragMotion === undefined ? {} : { dragMotion }),\n spots,\n ...(sector === undefined ? {} : { sector }),\n };\n } catch (cause) {\n if (cause instanceof PanoDataError) throw cause;\n const message = cause instanceof Error ? cause.message : \"Invalid map\";\n throw new PanoDataError(\"INVALID_PROJECT\", message, {\n field: message.split(\":\")[0],\n cause,\n });\n }\n}\n\nexport function resolvePanoMapAssets(\n map: PanoMapDefinition,\n baseUrl: string,\n resolveAssetUrl?: AssetUrlResolver,\n): PanoMapDefinition {\n const resolve = (path: string, spotId?: string) =>\n mapResource(\n path,\n {\n defaultUrl: resolveResource(baseUrl, path),\n kind: \"map\",\n sceneId: spotId ?? \"\",\n hotspotId: spotId,\n },\n resolveAssetUrl,\n );\n return {\n ...map,\n image: resolve(map.image),\n spots: map.spots.map((spot) =>\n spot.icon\n ? { ...spot, icon: resolve(spot.icon, spot.id) }\n : { ...spot },\n ),\n };\n}\n","import { parseViewLimits, type PanoViewLimits } from \"../view-limits\";\nimport { parsePopups, resolveProjectPopupAssets, type ProjectPopupDefinition, type PopupAssetUrlResolver } from \"./popups\";\nimport {\n isRecord,\n requiredString,\n type ViewerConfig,\n} from \"../../../../shared/viewer-config\";\nimport type { TileScene, SphereTileScene } from \"../scenes\";\nimport type { PanoViewerState } from \"../types\";\nimport { PanoDataError, aborted } from \"./errors\";\nimport {\n parseHotspot,\n projectHotspotTriggers,\n hotspotAction,\n parsePosition,\n resolveHotspotAssets,\n type ProjectHotspotDefinition,\n} from \"./hotspots\";\nimport {\n documentUrl,\n directoryUrl,\n readJson,\n parseConfig,\n resolveResource,\n sceneFromViewerConfig,\n loadSceneFromJson,\n type AssetUrlResolver,\n type JsonRequestOptions,\n} from \"./viewer\";\nimport {\n parsePanoMap,\n resolvePanoMapAssets,\n type PanoMapDefinition,\n} from \"./map\";\n\nexport type PanoProjectSceneDefinition = {\n id: string;\n title?: string;\n source: (\n | { viewerUrl: string; viewerConfig?: never }\n | { viewerConfig: ViewerConfig; viewerUrl?: never }\n ) & { baseUrl?: string };\n initialView?: Partial<PanoViewerState>;\n viewLimits?: PanoViewLimits;\n hotspots?: ProjectHotspotDefinition[];\n};\nexport type PanoProjectDefinition = {\n schemaVersion: 1;\n title?: string;\n initialSceneId?: string;\n scenes: PanoProjectSceneDefinition[];\n popups?: ProjectPopupDefinition[];\n map?: PanoMapDefinition;\n};\nexport type LoadedProjectScene = {\n scene: TileScene | SphereTileScene;\n title?: string;\n initialView?: PanoViewerState;\n hotspots: ProjectHotspotDefinition[];\n};\nexport type LoadedPanoProject = {\n title?: string;\n initialSceneId: string;\n scenes: LoadedProjectScene[];\n popups?: ProjectPopupDefinition[];\n map?: PanoMapDefinition;\n};\nexport type LoadPanoProjectOptions = JsonRequestOptions & {\n /** Directory used for project-relative references. Required for object input. */\n baseUrl?: string;\n resolveAssetUrl?: AssetUrlResolver;\n resolvePopupAssetUrl?: PopupAssetUrlResolver;\n};\n\nfunction optionalString(\n record: Record<string, unknown>,\n key: string\n): string | undefined {\n return record[key] === undefined\n ? undefined\n : requiredString(record[key], key);\n}\n\n/** Drafts permit empty scenes and unfinished popup titles/media; loading and export always validate strictly. */\nexport function parsePanoProject(value: unknown, options: { draft?: boolean } = {}): PanoProjectDefinition {\n if (!isRecord(value))\n throw new PanoDataError(\"INVALID_PROJECT\", \"Expected a project object\");\n if (value.schemaVersion !== 1)\n throw new PanoDataError(\n \"UNSUPPORTED_SCHEMA_VERSION\",\n \"Unsupported project schemaVersion\",\n { field: \"schemaVersion\" }\n );\n try {\n const popups = parsePopups(value.popups, options.draft);\n if (!Array.isArray(value.scenes) || (!options.draft && !value.scenes.length))\n throw new Error(\"scenes: expected a nonempty array\");\n const ids = new Set<string>();\n const scenes = value.scenes.map(\n (entry: unknown, index): PanoProjectSceneDefinition => {\n let id: string | undefined;\n const field = `scenes[${index}]`;\n try {\n if (!isRecord(entry)) throw new Error(\"expected a scene object\");\n id = requiredString(entry.id, \"id\");\n if (ids.has(id)) throw new Error(\"id: duplicate scene ID\");\n ids.add(id);\n if (!isRecord(entry.source))\n throw new Error(\"source: expected an object\");\n const src = entry.source;\n if (\n (src.viewerUrl !== undefined) ===\n (src.viewerConfig !== undefined)\n )\n throw new Error(\n \"source: provide exactly one of viewerUrl or viewerConfig\"\n );\n const baseUrl = optionalString(src, \"baseUrl\");\n const source: PanoProjectSceneDefinition[\"source\"] =\n src.viewerUrl !== undefined\n ? {\n viewerUrl: requiredString(src.viewerUrl, \"source.viewerUrl\"),\n baseUrl,\n }\n : { viewerConfig: parseConfig(src.viewerConfig), baseUrl };\n const viewLimits = parseViewLimits(entry.viewLimits);\n let initialView: Partial<PanoViewerState> | undefined;\n if (entry.initialView !== undefined) {\n if (!isRecord(entry.initialView))\n throw new Error(\"initialView: expected an object\");\n const input = entry.initialView;\n const position = parsePosition(\n { yaw: input.yaw ?? 0, pitch: input.pitch ?? 0 },\n \"initialView\"\n );\n const fov = input.fov ?? 75;\n if (\n typeof fov !== \"number\" ||\n !Number.isFinite(fov) ||\n fov <= 0 ||\n fov >= 180\n )\n throw new Error(\n \"initialView.fov: expected a number between 0 and 180\"\n );\n initialView = { ...position, fov };\n }\n if (entry.hotspots !== undefined && !Array.isArray(entry.hotspots))\n throw new Error(\"hotspots: expected an array\");\n const hotspotIds = new Set<string>();\n const hotspots = ((entry.hotspots ?? []) as unknown[]).map(\n (hotspot, i) => {\n const result = parseHotspot(\n hotspot,\n id!,\n `${field}.hotspots[${i}]`\n );\n if (hotspotIds.has(result.id))\n throw new Error(`hotspots[${i}].id: duplicate hotspot ID`);\n hotspotIds.add(result.id);\n return result;\n }\n );\n return {\n id,\n title: optionalString(entry, \"title\"),\n source,\n initialView,\n ...(viewLimits === undefined ? {} : { viewLimits }),\n hotspots,\n };\n } catch (cause) {\n if (cause instanceof PanoDataError && cause.sceneId) throw cause;\n const detail =\n cause instanceof Error ? cause.message : \"Invalid scene\";\n throw new PanoDataError(\n cause instanceof PanoDataError ? cause.code : \"INVALID_PROJECT\",\n `${field}.${detail}`,\n {\n sceneId: id,\n field: `${field}.${\n cause instanceof PanoDataError\n ? `source.viewerConfig.${cause.field ?? \"\"}`\n : detail.split(\":\")[0]\n }`,\n cause,\n }\n );\n }\n }\n );\n const initialSceneId =\n optionalString(value, \"initialSceneId\") ?? scenes[0]?.id;\n if (initialSceneId !== undefined && !ids.has(initialSceneId))\n throw new PanoDataError(\n \"INVALID_REFERENCE\",\n \"initialSceneId: scene does not exist\",\n { field: \"initialSceneId\" }\n );\n for (const [index, scene] of scenes.entries()) {\n for (const [i, hotspot] of (scene.hotspots ?? []).entries()) {\n for (const trigger of projectHotspotTriggers) {\n const action = hotspotAction(hotspot, trigger);\n if (action?.type === \"popup\" && !popups?.some((popup) => popup.id === action.popupId))\n throw new PanoDataError(\"INVALID_REFERENCE\", \"Hotspot target popup does not exist\", {\n sceneId: scene.id, field: `scenes[${index}].hotspots[${i}].${hotspot.events?.[trigger] ? `events.${trigger}` : \"action\"}.popupId`,\n });\n if (action?.type === \"scene\" && !ids.has(action.sceneId))\n throw new PanoDataError(\n \"INVALID_REFERENCE\",\n \"Hotspot target scene does not exist\",\n {\n sceneId: scene.id,\n field: `scenes[${index}].hotspots[${i}].${hotspot.events?.[trigger] ? `events.${trigger}` : \"action\"}.sceneId`,\n }\n );\n }\n }\n }\n const map = parsePanoMap(value.map, ids, options);\n return {\n schemaVersion: 1,\n title: optionalString(value, \"title\"),\n initialSceneId,\n scenes,\n ...(popups === undefined ? {} : { popups }),\n ...(map === undefined ? {} : { map }),\n };\n } catch (cause) {\n if (cause instanceof PanoDataError) throw cause;\n const message = cause instanceof Error ? cause.message : \"Invalid project\";\n throw new PanoDataError(\"INVALID_PROJECT\", message, {\n cause,\n field: message.split(\":\")[0],\n });\n }\n}\n\nexport async function loadPanoProject(\n source: string | PanoProjectDefinition,\n options: LoadPanoProjectOptions = {}\n): Promise<LoadedPanoProject> {\n aborted(options.requestInit?.signal);\n let definition: PanoProjectDefinition;\n let baseUrl: string;\n if (typeof source === \"string\") {\n const response = await readJson(documentUrl(source), options);\n definition = parsePanoProject(response.value);\n baseUrl = options.baseUrl ?? new URL(\".\", response.url).href;\n } else {\n if (!options.baseUrl)\n throw new PanoDataError(\n \"INVALID_OPTIONS\",\n \"baseUrl is required for project object input\"\n );\n definition = parsePanoProject(source);\n baseUrl = options.baseUrl;\n }\n const root = directoryUrl(documentUrl(baseUrl));\n const controller = new AbortController();\n const signal = options.requestInit?.signal;\n const cancel = () => controller.abort();\n signal?.addEventListener(\"abort\", cancel, { once: true });\n const scenes: LoadedProjectScene[] = new Array(definition.scenes.length);\n let next = 0;\n let failure: PanoDataError | undefined;\n async function worker() {\n while (next < definition.scenes.length && !controller.signal.aborted) {\n const index = next++;\n const item = definition.scenes[index]!;\n try {\n const sourceBase =\n item.source.baseUrl === undefined\n ? undefined\n : resolveResource(root, item.source.baseUrl);\n const sceneOptions = {\n id: item.id,\n resolveAssetUrl: options.resolveAssetUrl,\n };\n const scene =\n item.source.viewerUrl !== undefined\n ? await loadSceneFromJson(\n resolveResource(root, item.source.viewerUrl),\n {\n ...sceneOptions,\n baseUrl: sourceBase,\n requestInit: {\n ...options.requestInit,\n signal: controller.signal,\n },\n }\n )\n : sceneFromViewerConfig(item.source.viewerConfig, {\n ...sceneOptions,\n baseUrl: sourceBase ?? root,\n });\n aborted(controller.signal);\n if (item.viewLimits !== undefined) scene.viewLimits = item.viewLimits;\n scenes[index] = {\n scene,\n title: item.title,\n initialView: item.initialView\n ? { yaw: 0, pitch: 0, fov: 75, ...item.initialView }\n : undefined,\n hotspots: item.hotspots!.map((h) =>\n resolveHotspotAssets(h, root, item.id, options.resolveAssetUrl)\n ),\n };\n } catch (cause) {\n if (!failure) {\n const error =\n cause instanceof PanoDataError\n ? cause\n : new PanoDataError(\n \"INVALID_CONFIG\",\n cause instanceof Error\n ? cause.message\n : \"Could not load scene\",\n { cause }\n );\n const field = `scenes[${index}].${\n error.field ??\n (item.source.viewerUrl !== undefined\n ? \"source.viewerUrl\"\n : \"source.viewerConfig\")\n }`;\n failure = new PanoDataError(\n error.code,\n `Scene ${item.id}: ${error.message}`,\n { status: error.status, sceneId: item.id, field, cause: error }\n );\n }\n controller.abort();\n }\n }\n }\n try {\n aborted(signal);\n await Promise.all(\n Array.from({ length: Math.min(4, scenes.length) }, worker)\n );\n aborted(signal);\n if (failure) throw failure;\n return {\n title: definition.title,\n initialSceneId: definition.initialSceneId!,\n scenes,\n ...(definition.popups === undefined ? {} : { popups: definition.popups.map((popup) => resolveProjectPopupAssets(popup, root, options.resolvePopupAssetUrl)) }),\n ...(definition.map === undefined\n ? {}\n : {\n map: resolvePanoMapAssets(\n definition.map,\n root,\n options.resolveAssetUrl,\n ),\n }),\n };\n } finally {\n signal?.removeEventListener(\"abort\", cancel);\n }\n}\n"],"mappings":"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","names":["levels","id","isRecord","optionalString"]}
|