@eyeon/map 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +27 -0
  2. package/dist/assets/MapViewer.css +1 -0
  3. package/dist/assets/index.css +1 -0
  4. package/dist/chunks/MapViewer.js +530 -0
  5. package/dist/chunks/MapViewer.js.map +1 -0
  6. package/dist/chunks/graph-tools.js +153 -0
  7. package/dist/chunks/graph-tools.js.map +1 -0
  8. package/dist/chunks/pathfinding.js +343 -0
  9. package/dist/chunks/pathfinding.js.map +1 -0
  10. package/dist/core/geometry/index.d.ts +42 -0
  11. package/dist/core/geometry/index.d.ts.map +1 -0
  12. package/dist/core/import/index.d.ts +51 -0
  13. package/dist/core/import/index.d.ts.map +1 -0
  14. package/dist/core/index.d.ts +7 -0
  15. package/dist/core/index.d.ts.map +1 -0
  16. package/dist/core/index.js +282 -0
  17. package/dist/core/index.js.map +1 -0
  18. package/dist/core/publish/index.d.ts +28 -0
  19. package/dist/core/publish/index.d.ts.map +1 -0
  20. package/dist/core/routing/graph-tools.d.ts +47 -0
  21. package/dist/core/routing/graph-tools.d.ts.map +1 -0
  22. package/dist/core/routing/pathfinding.d.ts +22 -0
  23. package/dist/core/routing/pathfinding.d.ts.map +1 -0
  24. package/dist/core/types.d.ts +406 -0
  25. package/dist/core/types.d.ts.map +1 -0
  26. package/dist/editor/MapEditor.d.ts +31 -0
  27. package/dist/editor/MapEditor.d.ts.map +1 -0
  28. package/dist/editor/canvas/EditorCanvas.d.ts +22 -0
  29. package/dist/editor/canvas/EditorCanvas.d.ts.map +1 -0
  30. package/dist/editor/index.css +248 -0
  31. package/dist/editor/index.d.ts +5 -0
  32. package/dist/editor/index.d.ts.map +1 -0
  33. package/dist/editor/index.js +734 -0
  34. package/dist/editor/index.js.map +1 -0
  35. package/dist/editor/panels/Inspector.d.ts +14 -0
  36. package/dist/editor/panels/Inspector.d.ts.map +1 -0
  37. package/dist/editor/panels/LeftRail.d.ts +36 -0
  38. package/dist/editor/panels/LeftRail.d.ts.map +1 -0
  39. package/dist/editor/panels/PreviewOverlay.d.ts +6 -0
  40. package/dist/editor/panels/PreviewOverlay.d.ts.map +1 -0
  41. package/dist/index.d.ts +3 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/viewer/MapViewer.d.ts +26 -0
  44. package/dist/viewer/MapViewer.d.ts.map +1 -0
  45. package/dist/viewer/components/LevelMeshes.d.ts +11 -0
  46. package/dist/viewer/components/LevelMeshes.d.ts.map +1 -0
  47. package/dist/viewer/components/MapScene.d.ts +12 -0
  48. package/dist/viewer/components/MapScene.d.ts.map +1 -0
  49. package/dist/viewer/components/RouteLine.d.ts +8 -0
  50. package/dist/viewer/components/RouteLine.d.ts.map +1 -0
  51. package/dist/viewer/index.css +210 -0
  52. package/dist/viewer/index.d.ts +4 -0
  53. package/dist/viewer/index.d.ts.map +1 -0
  54. package/dist/viewer/index.js +7 -0
  55. package/dist/viewer/index.js.map +1 -0
  56. package/dist/viewer/ui/RuntimeChrome.d.ts +19 -0
  57. package/dist/viewer/ui/RuntimeChrome.d.ts.map +1 -0
  58. package/package.json +81 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapViewer.js","sources":["../../src/viewer/components/LevelMeshes.tsx","../../src/viewer/components/RouteLine.tsx","../../src/viewer/components/MapScene.tsx","../../src/viewer/ui/RuntimeChrome.tsx","../../src/viewer/MapViewer.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport * as THREE from 'three';\nimport type { PublishedLevel, ThemeDefaults, ShapeKind } from '../../core';\n\nfunction kindColor(kind: ShapeKind, theme: ThemeDefaults, fill?: string): string {\n if (fill) return fill;\n switch (kind) {\n case 'unit':\n return theme.STORE_DEFAULT_COLOR;\n case 'walkable':\n return theme.WALKABLE_COLOR;\n case 'wall':\n case 'boundary':\n return theme.WALL_COLOR;\n case 'parking_zone':\n return theme.PARKING_ZONE_COLOR;\n case 'green_area':\n return theme.GREEN_AREA_COLOR;\n case 'water':\n return theme.WATER_COLOR;\n case 'floorplate':\n return theme.BASE_COLOR;\n case 'void':\n return '#00000000';\n default:\n return '#e2e8f0';\n }\n}\n\nfunction polygonShape(points: { x: number; y: number }[]): THREE.Shape | null {\n if (points.length < 3) return null;\n const shape = new THREE.Shape();\n shape.moveTo(points[0].x, points[0].y);\n for (let i = 1; i < points.length; i++) {\n shape.lineTo(points[i].x, points[i].y);\n }\n shape.closePath();\n return shape;\n}\n\nexport interface LevelMeshesProps {\n level: PublishedLevel;\n theme: ThemeDefaults;\n is3d: boolean;\n selectedRetailerId?: number | null;\n onSelectShape?: (shapeId: number) => void;\n}\n\nexport function LevelMeshes({\n level,\n theme,\n is3d,\n selectedRetailerId,\n onSelectShape,\n}: LevelMeshesProps) {\n const meshes = useMemo(() => {\n return level.shapes\n .filter((s) => s.kind !== 'void')\n .map((shape) => {\n const polys = shape.geometry.polygons;\n const threeShapes = polys\n .map(polygonShape)\n .filter((s): s is THREE.Shape => s != null);\n if (threeShapes.length === 0) return null;\n\n const selected =\n selectedRetailerId != null &&\n shape.assignment?.retailerId === selectedRetailerId;\n const color = selected\n ? theme.ACCENT_COLOR\n : kindColor(shape.kind, theme, shape.style.fill);\n const extrude =\n is3d && (shape.kind === 'unit' || shape.kind === 'wall')\n ? shape.style.extrudeHeight ??\n (shape.kind === 'unit' ? theme.STORE_HEIGHT : 2)\n : 0;\n\n return { shape, threeShapes, color, extrude, selected };\n })\n .filter(Boolean) as Array<{\n shape: (typeof level.shapes)[number];\n threeShapes: THREE.Shape[];\n color: string;\n extrude: number;\n selected: boolean;\n }>;\n }, [level, theme, is3d, selectedRetailerId]);\n\n return (\n <group>\n {meshes.map(({ shape, threeShapes, color, extrude, selected }) => (\n <group key={shape.id}>\n {threeShapes.map((geoShape, idx) => (\n <mesh\n key={`${shape.id}-${idx}`}\n position={[0, 0, shape.zIndex * 0.01]}\n onClick={(e) => {\n e.stopPropagation();\n if (\n shape.kind === 'unit' ||\n shape.kind === 'amenity' ||\n shape.kind === 'kiosk_screen' ||\n shape.kind === 'entrance'\n ) {\n onSelectShape?.(shape.id);\n }\n }}\n >\n {extrude > 0 ? (\n <extrudeGeometry\n args={[\n geoShape,\n { depth: extrude, bevelEnabled: false },\n ]}\n />\n ) : (\n <shapeGeometry args={[geoShape]} />\n )}\n <meshBasicMaterial\n color={color}\n transparent={shape.style.transparent || shape.kind === 'amenity'}\n opacity={shape.style.opacity ?? (shape.kind === 'amenity' ? 0.01 : 1)}\n side={THREE.DoubleSide}\n />\n {selected && (\n <lineSegments>\n <edgesGeometry\n args={[\n extrude > 0\n ? new THREE.ExtrudeGeometry(geoShape, {\n depth: extrude,\n bevelEnabled: false,\n })\n : new THREE.ShapeGeometry(geoShape),\n ]}\n />\n <lineBasicMaterial color={theme.ACCENT_COLOR} />\n </lineSegments>\n )}\n </mesh>\n ))}\n </group>\n ))}\n </group>\n );\n}\n","import React, { useMemo } from 'react';\nimport * as THREE from 'three';\nimport type { PathResult } from '../../core';\n\nexport function RouteLine({\n route,\n activeLevelId,\n color,\n}: {\n route: PathResult;\n activeLevelId: number | null;\n color: string;\n}) {\n const points = useMemo(() => {\n return route.points\n .filter((p) => activeLevelId == null || p.levelId === activeLevelId)\n .map((p) => new THREE.Vector3(p.x, p.y, 2));\n }, [route, activeLevelId]);\n\n if (points.length < 2) return null;\n\n const curve = new THREE.CatmullRomCurve3(points);\n return (\n <mesh>\n <tubeGeometry args={[curve, Math.max(points.length * 4, 8), 1.5, 8, false]} />\n <meshBasicMaterial color={color} />\n </mesh>\n );\n}\n","import React, { useMemo } from 'react';\nimport { Canvas } from '@react-three/fiber';\nimport { OrthographicCamera, OrbitControls } from '@react-three/drei';\nimport type { PathResult, PublishedDocument, ThemeDefaults } from '../../core';\nimport { LevelMeshes } from './LevelMeshes';\nimport { RouteLine } from './RouteLine';\n\nexport interface MapSceneProps {\n doc: PublishedDocument;\n theme: ThemeDefaults;\n activeLevelId: number | null;\n route: PathResult | null;\n selectedRetailerId?: number | null;\n onSelectShape?: (shapeId: number, levelId: number) => void;\n}\n\nexport function MapScene({\n doc,\n theme,\n activeLevelId,\n route,\n selectedRetailerId,\n onSelectShape,\n}: MapSceneProps) {\n const is3d = theme.MAP_STYLE === '3D';\n\n const bounds = useMemo(() => {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const level of doc.levels) {\n if (activeLevelId != null && level.id !== activeLevelId && level.kind !== 'outdoor') {\n continue;\n }\n for (const shape of level.shapes) {\n minX = Math.min(minX, shape.bbox.minX);\n minY = Math.min(minY, shape.bbox.minY);\n maxX = Math.max(maxX, shape.bbox.maxX);\n maxY = Math.max(maxY, shape.bbox.maxY);\n }\n }\n if (!Number.isFinite(minX)) {\n return { cx: 0, cy: 0, size: 500 };\n }\n return {\n cx: (minX + maxX) / 2,\n cy: (minY + maxY) / 2,\n size: Math.max(maxX - minX, maxY - minY, 100),\n };\n }, [doc, activeLevelId]);\n\n const zoom = 800 / bounds.size;\n\n return (\n <Canvas\n style={{ width: '100%', height: '100%', background: theme.MAP_BACKGROUND_COLOR }}\n orthographic={!is3d}\n camera={\n is3d\n ? { position: [bounds.cx, bounds.cy - bounds.size, bounds.size], fov: 50, near: 1, far: 10000 }\n : undefined\n }\n >\n {!is3d && (\n <OrthographicCamera\n makeDefault\n position={[bounds.cx, bounds.cy, 500]}\n zoom={zoom}\n near={0.1}\n far={5000}\n />\n )}\n <ambientLight intensity={0.85} />\n <directionalLight position={[200, 400, 200]} intensity={0.4} />\n\n {doc.levels.map((level) => {\n const visible =\n level.kind === 'outdoor' ||\n activeLevelId == null ||\n level.id === activeLevelId;\n if (!visible) return null;\n return (\n <LevelMeshes\n key={level.id}\n level={level}\n theme={theme}\n is3d={is3d}\n selectedRetailerId={selectedRetailerId}\n onSelectShape={(shapeId) => onSelectShape?.(shapeId, level.id)}\n />\n );\n })}\n\n {route && <RouteLine route={route} activeLevelId={activeLevelId} color={theme.ACCENT_COLOR} />}\n\n <OrbitControls\n enableRotate={is3d}\n enablePan\n target={[bounds.cx, bounds.cy, 0]}\n maxDistance={theme.CAMERA_MAX_DISTANCE}\n minDistance={theme.CAMERA_MIN_DISTANCE}\n />\n </Canvas>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport type {\n CmAmenityCatalogItem,\n PathResult,\n PublishedDocument,\n} from '../../core';\n\nexport interface RuntimeChromeProps {\n doc: PublishedDocument;\n amenities: CmAmenityCatalogItem[];\n searchOpen: boolean;\n onSearchOpenChange: (open: boolean) => void;\n activeLevelId: number | null;\n onActiveLevelChange: (id: number) => void;\n fromAnchorId: number | null;\n toAnchorId: number | null;\n onFromChange: (id: number | null) => void;\n onToChange: (id: number | null) => void;\n accessibleOnly: boolean;\n onAccessibleOnlyChange: (v: boolean) => void;\n route: PathResult | null;\n}\n\ninterface ListItem {\n id: string;\n label: string;\n group: string;\n anchorId: number | null;\n levelId: number;\n kind: 'store' | 'amenity';\n}\n\nexport function RuntimeChrome({\n doc,\n amenities,\n searchOpen,\n onSearchOpenChange,\n activeLevelId,\n onActiveLevelChange,\n fromAnchorId,\n toAnchorId,\n onFromChange,\n onToChange,\n accessibleOnly,\n onAccessibleOnlyChange,\n route,\n}: RuntimeChromeProps) {\n const [query, setQuery] = useState('');\n const [selectedItem, setSelectedItem] = useState<ListItem | null>(null);\n\n const items = useMemo(() => {\n const list: ListItem[] = [];\n for (const level of doc.levels) {\n for (const shape of level.shapes) {\n const anchor = level.anchors.find((a) => a.shapeId === shape.id) ?? null;\n if (shape.kind === 'unit' && shape.assignment?.retailerId) {\n list.push({\n id: `store-${shape.id}`,\n label:\n shape.assignment.customLabel ||\n shape.label.text ||\n shape.key,\n group: level.name,\n anchorId: anchor?.id ?? null,\n levelId: level.id,\n kind: 'store',\n });\n }\n if (shape.kind === 'amenity' && shape.assignment?.amenityId) {\n const amenity = amenities.find((a) => a.id === shape.assignment!.amenityId);\n list.push({\n id: `amenity-${shape.id}`,\n label: amenity?.name ?? shape.key,\n group: 'Amenities',\n anchorId: anchor?.id ?? null,\n levelId: level.id,\n kind: 'amenity',\n });\n }\n }\n }\n return list;\n }, [doc, amenities]);\n\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return items;\n return items.filter((i) => i.label.toLowerCase().includes(q));\n }, [items, query]);\n\n const grouped = useMemo(() => {\n const map = new Map<string, ListItem[]>();\n for (const item of filtered) {\n const arr = map.get(item.group) ?? [];\n arr.push(item);\n map.set(item.group, arr);\n }\n return Array.from(map.entries());\n }, [filtered]);\n\n const anchorOptions = items.filter((i) => i.anchorId != null);\n\n return (\n <div className=\"eyeon-map-chrome\">\n <div className=\"eyeon-map-chrome__top\">\n <button\n type=\"button\"\n className=\"eyeon-map-chrome__search-toggle\"\n onClick={() => onSearchOpenChange(!searchOpen)}\n aria-expanded={searchOpen}\n >\n {searchOpen ? 'Close' : 'Search'}\n </button>\n\n <div className=\"eyeon-map-chrome__amenities\">\n {amenities.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n className=\"eyeon-map-chrome__amenity\"\n title={a.name}\n onClick={() => {\n const match = items.find(\n (i) => i.kind === 'amenity' && i.label === a.name && i.anchorId != null,\n );\n if (match?.anchorId != null) {\n onToChange(match.anchorId);\n onActiveLevelChange(match.levelId);\n }\n }}\n >\n {a.builtinIcon ? (\n <span className=\"eyeon-map-chrome__amenity-icon\">{a.builtinIcon}</span>\n ) : (\n <span className=\"eyeon-map-chrome__amenity-label\">{a.name.slice(0, 2)}</span>\n )}\n </button>\n ))}\n </div>\n </div>\n\n {searchOpen && (\n <div className=\"eyeon-map-chrome__panel\">\n <input\n className=\"eyeon-map-chrome__search-input\"\n placeholder=\"Search stores & amenities\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n autoFocus\n />\n\n <div className=\"eyeon-map-chrome__groups\">\n {grouped.map(([group, groupItems]) => (\n <div key={group} className=\"eyeon-map-chrome__group\">\n <div className=\"eyeon-map-chrome__group-title\">{group}</div>\n {groupItems.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n className=\"eyeon-map-chrome__item\"\n onClick={() => {\n setSelectedItem(item);\n if (item.anchorId != null) {\n onToChange(item.anchorId);\n onActiveLevelChange(item.levelId);\n }\n }}\n >\n {item.label}\n </button>\n ))}\n </div>\n ))}\n </div>\n\n {selectedItem && (\n <div className=\"eyeon-map-chrome__detail\">\n <div className=\"eyeon-map-chrome__detail-title\">{selectedItem.label}</div>\n <div className=\"eyeon-map-chrome__detail-meta\">{selectedItem.group}</div>\n </div>\n )}\n\n <div className=\"eyeon-map-chrome__route\">\n <label>\n From\n <select\n value={fromAnchorId ?? ''}\n onChange={(e) =>\n onFromChange(e.target.value ? Number(e.target.value) : null)\n }\n >\n <option value=\"\">Select start</option>\n {anchorOptions.map((i) => (\n <option key={i.id} value={i.anchorId!}>\n {i.label}\n </option>\n ))}\n </select>\n </label>\n <label>\n To\n <select\n value={toAnchorId ?? ''}\n onChange={(e) =>\n onToChange(e.target.value ? Number(e.target.value) : null)\n }\n >\n <option value=\"\">Select destination</option>\n {anchorOptions.map((i) => (\n <option key={i.id} value={i.anchorId!}>\n {i.label}\n </option>\n ))}\n </select>\n </label>\n <label className=\"eyeon-map-chrome__accessible\">\n <input\n type=\"checkbox\"\n checked={accessibleOnly}\n onChange={(e) => onAccessibleOnlyChange(e.target.checked)}\n />\n Accessible route\n </label>\n {route && (\n <div className=\"eyeon-map-chrome__route-meta\">\n {route.levelChanges.length > 0\n ? `${route.levelChanges.length} level change(s)`\n : 'Same level'}\n </div>\n )}\n </div>\n </div>\n )}\n\n <div className=\"eyeon-map-chrome__floors\">\n {doc.levels\n .filter((l) => l.kind === 'floor')\n .map((l) => (\n <button\n key={l.id}\n type=\"button\"\n className={\n l.id === activeLevelId\n ? 'eyeon-map-chrome__floor is-active'\n : 'eyeon-map-chrome__floor'\n }\n onClick={() => onActiveLevelChange(l.id)}\n >\n {l.name}\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import React, { Suspense, useEffect, useMemo, useState } from 'react';\nimport type {\n CmAmenityCatalogItem,\n PathResult,\n PublishedDocument,\n ThemeDefaults,\n} from '../core';\nimport { compileGraph, findPath, DEFAULT_THEME } from '../core';\nimport { MapScene } from './components/MapScene';\nimport { RuntimeChrome } from './ui/RuntimeChrome';\nimport './viewer.css';\n\nexport interface MapViewerProps {\n /** Published (or draft) document. If omitted, fetched from webApiURI. */\n document?: PublishedDocument | null;\n webApiURI?: string;\n /** Prefer fetching /v1/map/document */\n centerId?: number;\n role?: 'WP_SITE' | 'DISPLAY_APP' | 'PORTAL_PREVIEW' | 'DEMO';\n kioskId?: number | null;\n selectedRetailerId?: number | null;\n imageProxyUrl?: string;\n themeOverrides?: Partial<ThemeDefaults>;\n onExtractedAmenities?: (codes: string[]) => void;\n onSelectShape?: (shapeId: number) => void;\n createRouteRef?: React.MutableRefObject<{\n createRouteToStore: (retailerId: number) => void;\n createRouteToAmenity: (amenityCode: string) => void;\n clearRoute: () => void;\n } | null>;\n className?: string;\n style?: React.CSSProperties;\n}\n\nasync function fetchDocument(webApiURI: string): Promise<PublishedDocument> {\n const base = webApiURI.replace(/\\/$/, '');\n const res = await fetch(`${base}/v1/map/document`, { credentials: 'include' });\n if (!res.ok) {\n throw new Error(`Failed to load map document (${res.status})`);\n }\n return res.json();\n}\n\nexport function MapViewer(props: MapViewerProps) {\n const {\n document: documentProp,\n webApiURI,\n role = 'WP_SITE',\n kioskId = null,\n selectedRetailerId = null,\n themeOverrides,\n onExtractedAmenities,\n createRouteRef,\n className,\n style,\n } = props;\n\n const [doc, setDoc] = useState<PublishedDocument | null>(documentProp ?? null);\n const [error, setError] = useState<string | null>(null);\n const [route, setRoute] = useState<PathResult | null>(null);\n const [fromAnchorId, setFromAnchorId] = useState<number | null>(null);\n const [toAnchorId, setToAnchorId] = useState<number | null>(null);\n const [accessibleOnly, setAccessibleOnly] = useState(false);\n const [activeLevelId, setActiveLevelId] = useState<number | null>(null);\n const [searchOpen, setSearchOpen] = useState(false);\n\n useEffect(() => {\n if (documentProp) {\n setDoc(documentProp);\n return;\n }\n if (!webApiURI) return;\n let cancelled = false;\n fetchDocument(webApiURI)\n .then((d) => {\n if (!cancelled) setDoc(d);\n })\n .catch((e) => {\n if (!cancelled) setError(e instanceof Error ? e.message : String(e));\n });\n return () => {\n cancelled = true;\n };\n }, [documentProp, webApiURI]);\n\n useEffect(() => {\n if (!doc) return;\n if (activeLevelId == null && doc.levels.length > 0) {\n setActiveLevelId(doc.levels[0].id);\n }\n const codes = new Set<string>();\n for (const level of doc.levels) {\n for (const shape of level.shapes) {\n if (shape.kind === 'amenity' && shape.assignment?.amenityId != null) {\n const amenity = doc.amenities.find((a) => a.id === shape.assignment!.amenityId);\n if (amenity) codes.add(amenity.code);\n }\n }\n }\n onExtractedAmenities?.(Array.from(codes));\n }, [doc, activeLevelId, onExtractedAmenities]);\n\n // Prefill \"from\" for kiosk role\n useEffect(() => {\n if (!doc || role !== 'DISPLAY_APP' || kioskId == null) return;\n for (const level of doc.levels) {\n for (const shape of level.shapes) {\n if (\n shape.kind === 'kiosk_screen' &&\n shape.assignment?.kioskId === kioskId\n ) {\n const anchor = level.anchors.find((a) => a.shapeId === shape.id);\n if (anchor) setFromAnchorId(anchor.id);\n }\n }\n }\n }, [doc, role, kioskId]);\n\n const compiled = useMemo(() => {\n if (!doc) return null;\n return compileGraph(\n doc.graph.nodes.map((n) => ({\n id: n.id,\n levelId: n.levelId,\n shapeId: n.shapeId,\n kind: n.kind,\n x: n.x,\n y: n.y,\n connectorId: n.connectorId,\n })),\n doc.graph.edges.map((e) => ({\n id: e.id,\n mapId: doc.mapId,\n fromAnchorId: e.from,\n toAnchorId: e.to,\n weight: e.weight,\n directed: e.directed,\n accessible: e.accessible,\n kind: e.kind,\n })),\n doc.connectors,\n );\n }, [doc]);\n\n const runRoute = (fromId: number | null, toId: number | null) => {\n if (!compiled || fromId == null || toId == null) {\n setRoute(null);\n return;\n }\n const result = findPath(compiled, fromId, toId, { accessibleOnly });\n setRoute(result);\n };\n\n useEffect(() => {\n runRoute(fromAnchorId, toAnchorId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fromAnchorId, toAnchorId, accessibleOnly, compiled]);\n\n useEffect(() => {\n if (!createRouteRef || !doc) return;\n createRouteRef.current = {\n createRouteToStore(retailerId: number) {\n for (const level of doc.levels) {\n for (const shape of level.shapes) {\n if (shape.assignment?.retailerId === retailerId) {\n const anchor = level.anchors.find((a) => a.shapeId === shape.id);\n if (anchor) {\n setToAnchorId(anchor.id);\n setActiveLevelId(level.id);\n }\n }\n }\n }\n },\n createRouteToAmenity(amenityCode: string) {\n const amenity = doc.amenities.find((a) => a.code === amenityCode);\n if (!amenity) return;\n for (const level of doc.levels) {\n for (const shape of level.shapes) {\n if (shape.assignment?.amenityId === amenity.id) {\n const anchor = level.anchors.find((a) => a.shapeId === shape.id);\n if (anchor) {\n setToAnchorId(anchor.id);\n setActiveLevelId(level.id);\n return;\n }\n }\n }\n }\n },\n clearRoute() {\n setToAnchorId(null);\n setRoute(null);\n },\n };\n }, [createRouteRef, doc]);\n\n const theme: ThemeDefaults = {\n ...DEFAULT_THEME,\n ...(doc?.theme ?? {}),\n ...(themeOverrides ?? {}),\n };\n\n if (error) {\n return (\n <div className={`eyeon-map-viewer eyeon-map-viewer--error ${className ?? ''}`} style={style}>\n <div className=\"eyeon-map-viewer__error\">{error}</div>\n </div>\n );\n }\n\n if (!doc) {\n return (\n <div className={`eyeon-map-viewer eyeon-map-viewer--loading ${className ?? ''}`} style={style}>\n <div className=\"eyeon-map-viewer__loading\">Loading map…</div>\n </div>\n );\n }\n\n const amenitiesOnMap: CmAmenityCatalogItem[] = doc.amenities.filter((a) =>\n doc.levels.some((l) =>\n l.shapes.some((s) => s.assignment?.amenityId === a.id),\n ),\n );\n\n return (\n <div\n className={`eyeon-map-viewer eyeon-map-viewer--${role} ${className ?? ''}`}\n style={\n {\n ...style,\n ['--map-accent' as string]: theme.ACCENT_COLOR,\n ['--map-bg' as string]: theme.MAP_BACKGROUND_COLOR,\n } as React.CSSProperties\n }\n >\n {role !== 'DISPLAY_APP' && (\n <RuntimeChrome\n doc={doc}\n amenities={amenitiesOnMap}\n searchOpen={searchOpen}\n onSearchOpenChange={setSearchOpen}\n activeLevelId={activeLevelId}\n onActiveLevelChange={setActiveLevelId}\n fromAnchorId={fromAnchorId}\n toAnchorId={toAnchorId}\n onFromChange={setFromAnchorId}\n onToChange={setToAnchorId}\n accessibleOnly={accessibleOnly}\n onAccessibleOnlyChange={setAccessibleOnly}\n route={route}\n />\n )}\n\n <div className=\"eyeon-map-viewer__canvas\">\n <Suspense fallback={null}>\n <MapScene\n doc={doc}\n theme={theme}\n activeLevelId={activeLevelId}\n route={route}\n selectedRetailerId={selectedRetailerId}\n onSelectShape={(shapeId, levelId) => {\n setActiveLevelId(levelId);\n const level = doc.levels.find((l) => l.id === levelId);\n const anchor = level?.anchors.find((a) => a.shapeId === shapeId);\n if (anchor) setToAnchorId(anchor.id);\n props.onSelectShape?.(shapeId);\n }}\n />\n </Suspense>\n </div>\n </div>\n );\n}\n\nexport default MapViewer;\n"],"names":["kindColor","kind","theme","fill","polygonShape","points","shape","THREE","i","LevelMeshes","level","is3d","selectedRetailerId","onSelectShape","meshes","useMemo","s","threeShapes","selected","_a","color","extrude","jsx","geoShape","idx","jsxs","e","RouteLine","route","activeLevelId","p","curve","MapScene","doc","bounds","minX","minY","maxX","maxY","zoom","Canvas","OrthographicCamera","shapeId","OrbitControls","RuntimeChrome","amenities","searchOpen","onSearchOpenChange","onActiveLevelChange","fromAnchorId","toAnchorId","onFromChange","onToChange","accessibleOnly","onAccessibleOnlyChange","query","setQuery","useState","selectedItem","setSelectedItem","items","list","anchor","a","_b","amenity","filtered","q","grouped","map","item","arr","anchorOptions","match","group","groupItems","l","fetchDocument","webApiURI","base","res","MapViewer","props","documentProp","role","kioskId","themeOverrides","onExtractedAmenities","createRouteRef","className","style","setDoc","error","setError","setRoute","setFromAnchorId","setToAnchorId","setAccessibleOnly","setActiveLevelId","setSearchOpen","useEffect","cancelled","d","codes","compiled","compileGraph","n","runRoute","fromId","toId","result","findPath","retailerId","amenityCode","DEFAULT_THEME","amenitiesOnMap","Suspense","levelId"],"mappings":";;;;;;AAIA,SAASA,EAAUC,GAAiBC,GAAsBC,GAAuB;AAC/E,MAAIA,EAAM,QAAOA;AACjB,UAAQF,GAAA;AAAA,IACN,KAAK;AACH,aAAOC,EAAM;AAAA,IACf,KAAK;AACH,aAAOA,EAAM;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AACH,aAAOA,EAAM;AAAA,IACf,KAAK;AACH,aAAOA,EAAM;AAAA,IACf,KAAK;AACH,aAAOA,EAAM;AAAA,IACf,KAAK;AACH,aAAOA,EAAM;AAAA,IACf,KAAK;AACH,aAAOA,EAAM;AAAA,IACf,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb;AAEA,SAASE,EAAaC,GAAwD;AAC5E,MAAIA,EAAO,SAAS,EAAG,QAAO;AAC9B,QAAMC,IAAQ,IAAIC,EAAM,MAAA;AACxB,EAAAD,EAAM,OAAOD,EAAO,CAAC,EAAE,GAAGA,EAAO,CAAC,EAAE,CAAC;AACrC,WAASG,IAAI,GAAGA,IAAIH,EAAO,QAAQG;AACjC,IAAAF,EAAM,OAAOD,EAAOG,CAAC,EAAE,GAAGH,EAAOG,CAAC,EAAE,CAAC;AAEvC,SAAAF,EAAM,UAAA,GACCA;AACT;AAUO,SAASG,EAAY;AAAA,EAC1B,OAAAC;AAAA,EACA,OAAAR;AAAA,EACA,MAAAS;AAAA,EACA,oBAAAC;AAAA,EACA,eAAAC;AACF,GAAqB;AACnB,QAAMC,IAASC,EAAQ,MACdL,EAAM,OACV,OAAO,CAACM,MAAMA,EAAE,SAAS,MAAM,EAC/B,IAAI,CAACV,MAAU;;AAEd,UAAMW,IADQX,EAAM,SAAS,SAE1B,IAAIF,CAAY,EAChB,OAAO,CAACY,MAAwBA,KAAK,IAAI;AAC5C,QAAIC,EAAY,WAAW,EAAG,QAAO;AAErC,UAAMC,IACJN,KAAsB,UACtBO,IAAAb,EAAM,eAAN,gBAAAa,EAAkB,gBAAeP,GAC7BQ,IAAQF,IACVhB,EAAM,eACNF,EAAUM,EAAM,MAAMJ,GAAOI,EAAM,MAAM,IAAI,GAC3Ce,IACJV,MAASL,EAAM,SAAS,UAAUA,EAAM,SAAS,UAC7CA,EAAM,MAAM,kBACXA,EAAM,SAAS,SAASJ,EAAM,eAAe,KAC9C;AAEN,WAAO,EAAE,OAAAI,GAAO,aAAAW,GAAa,OAAAG,GAAO,SAAAC,GAAS,UAAAH,EAAA;AAAA,EAC/C,CAAC,EACA,OAAO,OAAO,GAOhB,CAACR,GAAOR,GAAOS,GAAMC,CAAkB,CAAC;AAE3C,2BACG,SAAA,EACE,UAAAE,EAAO,IAAI,CAAC,EAAE,OAAAR,GAAO,aAAAW,GAAa,OAAAG,GAAO,SAAAC,GAAS,UAAAH,EAAA,MACjD,gBAAAI,EAAC,SAAA,EACE,YAAY,IAAI,CAACC,GAAUC,MAC1B,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC,UAAU,CAAC,GAAG,GAAGnB,EAAM,SAAS,IAAI;AAAA,MACpC,SAAS,CAACoB,MAAM;AACd,QAAAA,EAAE,gBAAA,IAEApB,EAAM,SAAS,UACfA,EAAM,SAAS,aACfA,EAAM,SAAS,kBACfA,EAAM,SAAS,gBAEfO,KAAA,QAAAA,EAAgBP,EAAM;AAAA,MAE1B;AAAA,MAEC,UAAA;AAAA,QAAAe,IAAU,IACT,gBAAAC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM;AAAA,cACJC;AAAA,cACA,EAAE,OAAOF,GAAS,cAAc,GAAA;AAAA,YAAM;AAAA,UACxC;AAAA,QAAA,IAGF,gBAAAC,EAAC,iBAAA,EAAc,MAAM,CAACC,CAAQ,EAAA,CAAG;AAAA,QAEnC,gBAAAD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAAF;AAAA,YACA,aAAad,EAAM,MAAM,eAAeA,EAAM,SAAS;AAAA,YACvD,SAASA,EAAM,MAAM,YAAYA,EAAM,SAAS,YAAY,OAAO;AAAA,YACnE,MAAMC,EAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAEbW,uBACE,gBAAA,EACC,UAAA;AAAA,UAAA,gBAAAI;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM;AAAA,gBACJD,IAAU,IACN,IAAId,EAAM,gBAAgBgB,GAAU;AAAA,kBAClC,OAAOF;AAAA,kBACP,cAAc;AAAA,gBAAA,CACf,IACD,IAAId,EAAM,cAAcgB,CAAQ;AAAA,cAAA;AAAA,YACtC;AAAA,UAAA;AAAA,UAEF,gBAAAD,EAAC,qBAAA,EAAkB,OAAOpB,EAAM,aAAA,CAAc;AAAA,QAAA,EAAA,CAChD;AAAA,MAAA;AAAA,IAAA;AAAA,IA3CG,GAAGI,EAAM,EAAE,IAAIkB,CAAG;AAAA,EAAA,CA8C1B,KAjDSlB,EAAM,EAkDlB,CACD,EAAA,CACH;AAEJ;AC7IO,SAASqB,GAAU;AAAA,EACxB,OAAAC;AAAA,EACA,eAAAC;AAAA,EACA,OAAAT;AACF,GAIG;AACD,QAAMf,IAASU,EAAQ,MACda,EAAM,OACV,OAAO,CAACE,MAAMD,KAAiB,QAAQC,EAAE,YAAYD,CAAa,EAClE,IAAI,CAACC,MAAM,IAAIvB,EAAM,QAAQuB,EAAE,GAAGA,EAAE,GAAG,CAAC,CAAC,GAC3C,CAACF,GAAOC,CAAa,CAAC;AAEzB,MAAIxB,EAAO,SAAS,EAAG,QAAO;AAE9B,QAAM0B,IAAQ,IAAIxB,EAAM,iBAAiBF,CAAM;AAC/C,2BACG,QAAA,EACC,UAAA;AAAA,IAAA,gBAAAiB,EAAC,gBAAA,EAAa,MAAM,CAACS,GAAO,KAAK,IAAI1B,EAAO,SAAS,GAAG,CAAC,GAAG,KAAK,GAAG,EAAK,GAAG;AAAA,IAC5E,gBAAAiB,EAAC,uBAAkB,OAAAF,EAAA,CAAc;AAAA,EAAA,GACnC;AAEJ;ACZO,SAASY,GAAS;AAAA,EACvB,KAAAC;AAAA,EACA,OAAA/B;AAAA,EACA,eAAA2B;AAAA,EACA,OAAAD;AAAA,EACA,oBAAAhB;AAAA,EACA,eAAAC;AACF,GAAkB;AAChB,QAAMF,IAAOT,EAAM,cAAc,MAE3BgC,IAASnB,EAAQ,MAAM;AAC3B,QAAIoB,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAW5B,KAASuB,EAAI;AACtB,UAAI,EAAAJ,KAAiB,QAAQnB,EAAM,OAAOmB,KAAiBnB,EAAM,SAAS;AAG1E,mBAAWJ,KAASI,EAAM;AACxB,UAAAyB,IAAO,KAAK,IAAIA,GAAM7B,EAAM,KAAK,IAAI,GACrC8B,IAAO,KAAK,IAAIA,GAAM9B,EAAM,KAAK,IAAI,GACrC+B,IAAO,KAAK,IAAIA,GAAM/B,EAAM,KAAK,IAAI,GACrCgC,IAAO,KAAK,IAAIA,GAAMhC,EAAM,KAAK,IAAI;AAGzC,WAAK,OAAO,SAAS6B,CAAI,IAGlB;AAAA,MACL,KAAKA,IAAOE,KAAQ;AAAA,MACpB,KAAKD,IAAOE,KAAQ;AAAA,MACpB,MAAM,KAAK,IAAID,IAAOF,GAAMG,IAAOF,GAAM,GAAG;AAAA,IAAA,IALrC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,IAAA;AAAA,EAOjC,GAAG,CAACH,GAAKJ,CAAa,CAAC,GAEjBU,IAAO,MAAML,EAAO;AAE1B,SACE,gBAAAT;AAAA,IAACe;AAAA,IAAA;AAAA,MACC,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,YAAYtC,EAAM,qBAAA;AAAA,MAC1D,cAAc,CAACS;AAAA,MACf,QACEA,IACI,EAAE,UAAU,CAACuB,EAAO,IAAIA,EAAO,KAAKA,EAAO,MAAMA,EAAO,IAAI,GAAG,KAAK,IAAI,MAAM,GAAG,KAAK,QACtF;AAAA,MAGL,UAAA;AAAA,QAAA,CAACvB,KACA,gBAAAW;AAAA,UAACmB;AAAA,UAAA;AAAA,YACC,aAAW;AAAA,YACX,UAAU,CAACP,EAAO,IAAIA,EAAO,IAAI,GAAG;AAAA,YACpC,MAAAK;AAAA,YACA,MAAM;AAAA,YACN,KAAK;AAAA,UAAA;AAAA,QAAA;AAAA,QAGT,gBAAAjB,EAAC,gBAAA,EAAa,WAAW,KAAA,CAAM;AAAA,QAC/B,gBAAAA,EAAC,sBAAiB,UAAU,CAAC,KAAK,KAAK,GAAG,GAAG,WAAW,KAAK;AAAA,QAE5DW,EAAI,OAAO,IAAI,CAACvB,MAEbA,EAAM,SAAS,aACfmB,KAAiB,QACjBnB,EAAM,OAAOmB,IAGb,gBAAAP;AAAA,UAACb;AAAA,UAAA;AAAA,YAEC,OAAAC;AAAA,YACA,OAAAR;AAAA,YACA,MAAAS;AAAA,YACA,oBAAAC;AAAA,YACA,eAAe,CAAC8B,MAAY7B,KAAA,gBAAAA,EAAgB6B,GAAShC,EAAM;AAAA,UAAE;AAAA,UALxDA,EAAM;AAAA,QAAA,IAHM,IAWtB;AAAA,QAEAkB,KAAS,gBAAAN,EAACK,IAAA,EAAU,OAAAC,GAAc,eAAAC,GAA8B,OAAO3B,EAAM,cAAc;AAAA,QAE5F,gBAAAoB;AAAA,UAACqB;AAAA,UAAA;AAAA,YACC,cAAchC;AAAA,YACd,WAAS;AAAA,YACT,QAAQ,CAACuB,EAAO,IAAIA,EAAO,IAAI,CAAC;AAAA,YAChC,aAAahC,EAAM;AAAA,YACnB,aAAaA,EAAM;AAAA,UAAA;AAAA,QAAA;AAAA,MACrB;AAAA,IAAA;AAAA,EAAA;AAGN;ACzEO,SAAS0C,GAAc;AAAA,EAC5B,KAAAX;AAAA,EACA,WAAAY;AAAA,EACA,YAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,eAAAlB;AAAA,EACA,qBAAAmB;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,OAAA1B;AACF,GAAuB;AACrB,QAAM,CAAC2B,GAAOC,CAAQ,IAAIC,EAAS,EAAE,GAC/B,CAACC,GAAcC,CAAe,IAAIF,EAA0B,IAAI,GAEhEG,IAAQ7C,EAAQ,MAAM;;AAC1B,UAAM8C,IAAmB,CAAA;AACzB,eAAWnD,KAASuB,EAAI;AACtB,iBAAW3B,KAASI,EAAM,QAAQ;AAChC,cAAMoD,IAASpD,EAAM,QAAQ,KAAK,CAACqD,MAAMA,EAAE,YAAYzD,EAAM,EAAE,KAAK;AAcpE,YAbIA,EAAM,SAAS,YAAUa,IAAAb,EAAM,eAAN,QAAAa,EAAkB,eAC7C0C,EAAK,KAAK;AAAA,UACR,IAAI,SAASvD,EAAM,EAAE;AAAA,UACrB,OACEA,EAAM,WAAW,eACjBA,EAAM,MAAM,QACZA,EAAM;AAAA,UACR,OAAOI,EAAM;AAAA,UACb,WAAUoD,KAAA,gBAAAA,EAAQ,OAAM;AAAA,UACxB,SAASpD,EAAM;AAAA,UACf,MAAM;AAAA,QAAA,CACP,GAECJ,EAAM,SAAS,eAAa0D,IAAA1D,EAAM,eAAN,QAAA0D,EAAkB,YAAW;AAC3D,gBAAMC,IAAUpB,EAAU,KAAK,CAACkB,MAAMA,EAAE,OAAOzD,EAAM,WAAY,SAAS;AAC1E,UAAAuD,EAAK,KAAK;AAAA,YACR,IAAI,WAAWvD,EAAM,EAAE;AAAA,YACvB,QAAO2D,KAAA,gBAAAA,EAAS,SAAQ3D,EAAM;AAAA,YAC9B,OAAO;AAAA,YACP,WAAUwD,KAAA,gBAAAA,EAAQ,OAAM;AAAA,YACxB,SAASpD,EAAM;AAAA,YACf,MAAM;AAAA,UAAA,CACP;AAAA,QACH;AAAA,MACF;AAEF,WAAOmD;AAAA,EACT,GAAG,CAAC5B,GAAKY,CAAS,CAAC,GAEbqB,IAAWnD,EAAQ,MAAM;AAC7B,UAAMoD,IAAIZ,EAAM,KAAA,EAAO,YAAA;AACvB,WAAKY,IACEP,EAAM,OAAO,CAACpD,MAAMA,EAAE,MAAM,YAAA,EAAc,SAAS2D,CAAC,CAAC,IAD7CP;AAAA,EAEjB,GAAG,CAACA,GAAOL,CAAK,CAAC,GAEXa,IAAUrD,EAAQ,MAAM;AAC5B,UAAMsD,wBAAU,IAAA;AAChB,eAAWC,KAAQJ,GAAU;AAC3B,YAAMK,IAAMF,EAAI,IAAIC,EAAK,KAAK,KAAK,CAAA;AACnC,MAAAC,EAAI,KAAKD,CAAI,GACbD,EAAI,IAAIC,EAAK,OAAOC,CAAG;AAAA,IACzB;AACA,WAAO,MAAM,KAAKF,EAAI,QAAA,CAAS;AAAA,EACjC,GAAG,CAACH,CAAQ,CAAC,GAEPM,IAAgBZ,EAAM,OAAO,CAACpD,MAAMA,EAAE,YAAY,IAAI;AAE5D,SACE,gBAAAiB,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,yBACb,UAAA;AAAA,MAAA,gBAAAH;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAMyB,EAAmB,CAACD,CAAU;AAAA,UAC7C,iBAAeA;AAAA,UAEd,cAAa,UAAU;AAAA,QAAA;AAAA,MAAA;AAAA,wBAGzB,OAAA,EAAI,WAAU,+BACZ,UAAAD,EAAU,IAAI,CAACkB,MACd,gBAAAzC;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAOyC,EAAE;AAAA,UACT,SAAS,MAAM;AACb,kBAAMU,IAAQb,EAAM;AAAA,cAClB,CAACpD,MAAMA,EAAE,SAAS,aAAaA,EAAE,UAAUuD,EAAE,QAAQvD,EAAE,YAAY;AAAA,YAAA;AAErE,aAAIiE,KAAA,gBAAAA,EAAO,aAAY,SACrBrB,EAAWqB,EAAM,QAAQ,GACzBzB,EAAoByB,EAAM,OAAO;AAAA,UAErC;AAAA,UAEC,YAAE,cACD,gBAAAnD,EAAC,UAAK,WAAU,kCAAkC,YAAE,YAAA,CAAY,IAEhE,gBAAAA,EAAC,QAAA,EAAK,WAAU,mCAAmC,UAAAyC,EAAE,KAAK,MAAM,GAAG,CAAC,EAAA,CAAE;AAAA,QAAA;AAAA,QAjBnEA,EAAE;AAAA,MAAA,CAoBV,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IAECjB,KACC,gBAAArB,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,MAAA,gBAAAH;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,aAAY;AAAA,UACZ,OAAOiC;AAAA,UACP,UAAU,CAAC,MAAMC,EAAS,EAAE,OAAO,KAAK;AAAA,UACxC,WAAS;AAAA,QAAA;AAAA,MAAA;AAAA,MAGX,gBAAAlC,EAAC,OAAA,EAAI,WAAU,4BACZ,YAAQ,IAAI,CAAC,CAACoD,GAAOC,CAAU,MAC9B,gBAAAlD,EAAC,OAAA,EAAgB,WAAU,2BACzB,UAAA;AAAA,QAAA,gBAAAH,EAAC,OAAA,EAAI,WAAU,iCAAiC,UAAAoD,GAAM;AAAA,QACrDC,EAAW,IAAI,CAACL,MACf,gBAAAhD;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAM;AACb,cAAAqC,EAAgBW,CAAI,GAChBA,EAAK,YAAY,SACnBlB,EAAWkB,EAAK,QAAQ,GACxBtB,EAAoBsB,EAAK,OAAO;AAAA,YAEpC;AAAA,YAEC,UAAAA,EAAK;AAAA,UAAA;AAAA,UAXDA,EAAK;AAAA,QAAA,CAab;AAAA,MAAA,KAjBOI,CAkBV,CACD,GACH;AAAA,MAEChB,KACC,gBAAAjC,EAAC,OAAA,EAAI,WAAU,4BACb,UAAA;AAAA,QAAA,gBAAAH,EAAC,OAAA,EAAI,WAAU,kCAAkC,UAAAoC,EAAa,OAAM;AAAA,QACpE,gBAAApC,EAAC,OAAA,EAAI,WAAU,iCAAiC,YAAa,MAAA,CAAM;AAAA,MAAA,GACrE;AAAA,MAGF,gBAAAG,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,SAAA,EAAM,UAAA;AAAA,UAAA;AAAA,UAEL,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAOwB,KAAgB;AAAA,cACvB,UAAU,CAAC,MACTE,EAAa,EAAE,OAAO,QAAQ,OAAO,EAAE,OAAO,KAAK,IAAI,IAAI;AAAA,cAG7D,UAAA;AAAA,gBAAA,gBAAA7B,EAAC,UAAA,EAAO,OAAM,IAAG,UAAA,gBAAY;AAAA,gBAC5BkD,EAAc,IAAI,CAAChE,MAClB,gBAAAc,EAAC,UAAA,EAAkB,OAAOd,EAAE,UACzB,UAAAA,EAAE,MAAA,GADQA,EAAE,EAEf,CACD;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH,GACF;AAAA,0BACC,SAAA,EAAM,UAAA;AAAA,UAAA;AAAA,UAEL,gBAAAiB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAOyB,KAAc;AAAA,cACrB,UAAU,CAAC,MACTE,EAAW,EAAE,OAAO,QAAQ,OAAO,EAAE,OAAO,KAAK,IAAI,IAAI;AAAA,cAG3D,UAAA;AAAA,gBAAA,gBAAA9B,EAAC,UAAA,EAAO,OAAM,IAAG,UAAA,sBAAkB;AAAA,gBAClCkD,EAAc,IAAI,CAAChE,MAClB,gBAAAc,EAAC,UAAA,EAAkB,OAAOd,EAAE,UACzB,UAAAA,EAAE,MAAA,GADQA,EAAE,EAEf,CACD;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH,GACF;AAAA,QACA,gBAAAiB,EAAC,SAAA,EAAM,WAAU,gCACf,UAAA;AAAA,UAAA,gBAAAH;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS+B;AAAA,cACT,UAAU,CAAC,MAAMC,EAAuB,EAAE,OAAO,OAAO;AAAA,YAAA;AAAA,UAAA;AAAA,UACxD;AAAA,QAAA,GAEJ;AAAA,QACC1B,KACC,gBAAAN,EAAC,OAAA,EAAI,WAAU,gCACZ,UAAAM,EAAM,aAAa,SAAS,IACzB,GAAGA,EAAM,aAAa,MAAM,qBAC5B,aAAA,CACN;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,GACF;AAAA,IAGF,gBAAAN,EAAC,OAAA,EAAI,WAAU,4BACZ,YAAI,OACF,OAAO,CAACsD,MAAMA,EAAE,SAAS,OAAO,EAChC,IAAI,CAACA,MACJ,gBAAAtD;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,WACEsD,EAAE,OAAO/C,IACL,sCACA;AAAA,QAEN,SAAS,MAAMmB,EAAoB4B,EAAE,EAAE;AAAA,QAEtC,UAAAA,EAAE;AAAA,MAAA;AAAA,MATEA,EAAE;AAAA,IAAA,CAWV,EAAA,CACL;AAAA,EAAA,GACF;AAEJ;AC5NA,eAAeC,GAAcC,GAA+C;AAC1E,QAAMC,IAAOD,EAAU,QAAQ,OAAO,EAAE,GAClCE,IAAM,MAAM,MAAM,GAAGD,CAAI,oBAAoB,EAAE,aAAa,WAAW;AAC7E,MAAI,CAACC,EAAI;AACP,UAAM,IAAI,MAAM,gCAAgCA,EAAI,MAAM,GAAG;AAE/D,SAAOA,EAAI,KAAA;AACb;AAEO,SAASC,GAAUC,GAAuB;AAC/C,QAAM;AAAA,IACJ,UAAUC;AAAA,IACV,WAAAL;AAAA,IACA,MAAAM,IAAO;AAAA,IACP,SAAAC,IAAU;AAAA,IACV,oBAAAzE,IAAqB;AAAA,IACrB,gBAAA0E;AAAA,IACA,sBAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,WAAAC;AAAA,IACA,OAAAC;AAAA,EAAA,IACER,GAEE,CAACjD,GAAK0D,CAAM,IAAIlC,EAAmC0B,KAAgB,IAAI,GACvE,CAACS,GAAOC,CAAQ,IAAIpC,EAAwB,IAAI,GAChD,CAAC7B,GAAOkE,CAAQ,IAAIrC,EAA4B,IAAI,GACpD,CAACR,GAAc8C,CAAe,IAAItC,EAAwB,IAAI,GAC9D,CAACP,GAAY8C,CAAa,IAAIvC,EAAwB,IAAI,GAC1D,CAACJ,GAAgB4C,CAAiB,IAAIxC,EAAS,EAAK,GACpD,CAAC5B,GAAeqE,CAAgB,IAAIzC,EAAwB,IAAI,GAChE,CAACX,GAAYqD,CAAa,IAAI1C,EAAS,EAAK;AAElD,EAAA2C,EAAU,MAAM;AACd,QAAIjB,GAAc;AAChB,MAAAQ,EAAOR,CAAY;AACnB;AAAA,IACF;AACA,QAAI,CAACL,EAAW;AAChB,QAAIuB,IAAY;AAChB,WAAAxB,GAAcC,CAAS,EACpB,KAAK,CAACwB,MAAM;AACX,MAAKD,KAAWV,EAAOW,CAAC;AAAA,IAC1B,CAAC,EACA,MAAM,CAAC5E,MAAM;AACZ,MAAK2E,KAAWR,EAASnE,aAAa,QAAQA,EAAE,UAAU,OAAOA,CAAC,CAAC;AAAA,IACrE,CAAC,GACI,MAAM;AACX,MAAA2E,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAClB,GAAcL,CAAS,CAAC,GAE5BsB,EAAU,MAAM;;AACd,QAAI,CAACnE,EAAK;AACV,IAAIJ,KAAiB,QAAQI,EAAI,OAAO,SAAS,KAC/CiE,EAAiBjE,EAAI,OAAO,CAAC,EAAE,EAAE;AAEnC,UAAMsE,wBAAY,IAAA;AAClB,eAAW7F,KAASuB,EAAI;AACtB,iBAAW3B,KAASI,EAAM;AACxB,YAAIJ,EAAM,SAAS,eAAaa,IAAAb,EAAM,eAAN,gBAAAa,EAAkB,cAAa,MAAM;AACnE,gBAAM8C,IAAUhC,EAAI,UAAU,KAAK,CAAC8B,MAAMA,EAAE,OAAOzD,EAAM,WAAY,SAAS;AAC9E,UAAI2D,KAASsC,EAAM,IAAItC,EAAQ,IAAI;AAAA,QACrC;AAGJ,IAAAsB,KAAA,QAAAA,EAAuB,MAAM,KAAKgB,CAAK;AAAA,EACzC,GAAG,CAACtE,GAAKJ,GAAe0D,CAAoB,CAAC,GAG7Ca,EAAU,MAAM;;AACd,QAAI,GAACnE,KAAOmD,MAAS,iBAAiBC,KAAW;AACjD,iBAAW3E,KAASuB,EAAI;AACtB,mBAAW3B,KAASI,EAAM;AACxB,cACEJ,EAAM,SAAS,oBACfa,IAAAb,EAAM,eAAN,gBAAAa,EAAkB,aAAYkE,GAC9B;AACA,kBAAMvB,IAASpD,EAAM,QAAQ,KAAK,CAACqD,MAAMA,EAAE,YAAYzD,EAAM,EAAE;AAC/D,YAAIwD,KAAQiC,EAAgBjC,EAAO,EAAE;AAAA,UACvC;AAAA;AAAA,EAGN,GAAG,CAAC7B,GAAKmD,GAAMC,CAAO,CAAC;AAEvB,QAAMmB,IAAWzF,EAAQ,MAClBkB,IACEwE;AAAA,IACLxE,EAAI,MAAM,MAAM,IAAI,CAACyE,OAAO;AAAA,MAC1B,IAAIA,EAAE;AAAA,MACN,SAASA,EAAE;AAAA,MACX,SAASA,EAAE;AAAA,MACX,MAAMA,EAAE;AAAA,MACR,GAAGA,EAAE;AAAA,MACL,GAAGA,EAAE;AAAA,MACL,aAAaA,EAAE;AAAA,IAAA,EACf;AAAA,IACFzE,EAAI,MAAM,MAAM,IAAI,CAACP,OAAO;AAAA,MAC1B,IAAIA,EAAE;AAAA,MACN,OAAOO,EAAI;AAAA,MACX,cAAcP,EAAE;AAAA,MAChB,YAAYA,EAAE;AAAA,MACd,QAAQA,EAAE;AAAA,MACV,UAAUA,EAAE;AAAA,MACZ,YAAYA,EAAE;AAAA,MACd,MAAMA,EAAE;AAAA,IAAA,EACR;AAAA,IACFO,EAAI;AAAA,EAAA,IArBW,MAuBhB,CAACA,CAAG,CAAC,GAEF0E,IAAW,CAACC,GAAuBC,MAAwB;AAC/D,QAAI,CAACL,KAAYI,KAAU,QAAQC,KAAQ,MAAM;AAC/C,MAAAf,EAAS,IAAI;AACb;AAAA,IACF;AACA,UAAMgB,IAASC,EAASP,GAAUI,GAAQC,GAAM,EAAE,gBAAAxD,GAAgB;AAClE,IAAAyC,EAASgB,CAAM;AAAA,EACjB;AAEA,EAAAV,EAAU,MAAM;AACd,IAAAO,EAAS1D,GAAcC,CAAU;AAAA,EAEnC,GAAG,CAACD,GAAcC,GAAYG,GAAgBmD,CAAQ,CAAC,GAEvDJ,EAAU,MAAM;AACd,IAAI,CAACZ,KAAkB,CAACvD,MACxBuD,EAAe,UAAU;AAAA,MACvB,mBAAmBwB,GAAoB;;AACrC,mBAAWtG,KAASuB,EAAI;AACtB,qBAAW3B,KAASI,EAAM;AACxB,kBAAIS,IAAAb,EAAM,eAAN,gBAAAa,EAAkB,gBAAe6F,GAAY;AAC/C,oBAAMlD,IAASpD,EAAM,QAAQ,KAAK,CAACqD,MAAMA,EAAE,YAAYzD,EAAM,EAAE;AAC/D,cAAIwD,MACFkC,EAAclC,EAAO,EAAE,GACvBoC,EAAiBxF,EAAM,EAAE;AAAA,YAE7B;AAAA,MAGN;AAAA,MACA,qBAAqBuG,GAAqB;;AACxC,cAAMhD,IAAUhC,EAAI,UAAU,KAAK,CAAC8B,MAAMA,EAAE,SAASkD,CAAW;AAChE,YAAKhD;AACL,qBAAWvD,KAASuB,EAAI;AACtB,uBAAW3B,KAASI,EAAM;AACxB,oBAAIS,IAAAb,EAAM,eAAN,gBAAAa,EAAkB,eAAc8C,EAAQ,IAAI;AAC9C,sBAAMH,IAASpD,EAAM,QAAQ,KAAK,CAACqD,MAAMA,EAAE,YAAYzD,EAAM,EAAE;AAC/D,oBAAIwD,GAAQ;AACV,kBAAAkC,EAAclC,EAAO,EAAE,GACvBoC,EAAiBxF,EAAM,EAAE;AACzB;AAAA,gBACF;AAAA,cACF;AAAA;AAAA,MAGN;AAAA,MACA,aAAa;AACX,QAAAsF,EAAc,IAAI,GAClBF,EAAS,IAAI;AAAA,MACf;AAAA,IAAA;AAAA,EAEJ,GAAG,CAACN,GAAgBvD,CAAG,CAAC;AAExB,QAAM/B,IAAuB;AAAA,IAC3B,GAAGgH;AAAA,IACH,IAAIjF,KAAA,gBAAAA,EAAK,UAAS,CAAA;AAAA,IAClB,GAAIqD,KAAkB,CAAA;AAAA,EAAC;AAGzB,MAAIM;AACF,WACE,gBAAAtE,EAAC,OAAA,EAAI,WAAW,4CAA4CmE,KAAa,EAAE,IAAI,OAAAC,GAC7E,UAAA,gBAAApE,EAAC,OAAA,EAAI,WAAU,2BAA2B,aAAM,GAClD;AAIJ,MAAI,CAACW;AACH,WACE,gBAAAX,EAAC,OAAA,EAAI,WAAW,8CAA8CmE,KAAa,EAAE,IAAI,OAAAC,GAC/E,UAAA,gBAAApE,EAAC,OAAA,EAAI,WAAU,6BAA4B,0BAAY,GACzD;AAIJ,QAAM6F,IAAyClF,EAAI,UAAU;AAAA,IAAO,CAAC8B,MACnE9B,EAAI,OAAO;AAAA,MAAK,CAAC2C,MACfA,EAAE,OAAO,KAAK,CAAC5D,MAAA;;AAAM,iBAAAG,IAAAH,EAAE,eAAF,gBAAAG,EAAc,eAAc4C,EAAE;AAAA,OAAE;AAAA,IAAA;AAAA,EACvD;AAGF,SACE,gBAAAtC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,sCAAsC2D,CAAI,IAAIK,KAAa,EAAE;AAAA,MACxE,OACE;AAAA,QACE,GAAGC;AAAA,QACF,gBAA2BxF,EAAM;AAAA,QACjC,YAAuBA,EAAM;AAAA,MAAA;AAAA,MAIjC,UAAA;AAAA,QAAAkF,MAAS,iBACR,gBAAA9D;AAAA,UAACsB;AAAA,UAAA;AAAA,YACC,KAAAX;AAAA,YACA,WAAWkF;AAAA,YACX,YAAArE;AAAA,YACA,oBAAoBqD;AAAA,YACpB,eAAAtE;AAAA,YACA,qBAAqBqE;AAAA,YACrB,cAAAjD;AAAA,YACA,YAAAC;AAAA,YACA,cAAc6C;AAAA,YACd,YAAYC;AAAA,YACZ,gBAAA3C;AAAA,YACA,wBAAwB4C;AAAA,YACxB,OAAArE;AAAA,UAAA;AAAA,QAAA;AAAA,0BAIH,OAAA,EAAI,WAAU,4BACb,UAAA,gBAAAN,EAAC8F,GAAA,EAAS,UAAU,MAClB,UAAA,gBAAA9F;AAAA,UAACU;AAAA,UAAA;AAAA,YACC,KAAAC;AAAA,YACA,OAAA/B;AAAA,YACA,eAAA2B;AAAA,YACA,OAAAD;AAAA,YACA,oBAAAhB;AAAA,YACA,eAAe,CAAC8B,GAAS2E,MAAY;;AACnC,cAAAnB,EAAiBmB,CAAO;AACxB,oBAAM3G,IAAQuB,EAAI,OAAO,KAAK,CAAC2C,MAAMA,EAAE,OAAOyC,CAAO,GAC/CvD,IAASpD,KAAA,gBAAAA,EAAO,QAAQ,KAAK,CAACqD,MAAMA,EAAE,YAAYrB;AACxD,cAAIoB,KAAQkC,EAAclC,EAAO,EAAE,IACnC3C,IAAA+D,EAAM,kBAAN,QAAA/D,EAAA,KAAA+D,GAAsBxC;AAAA,YACxB;AAAA,UAAA;AAAA,QAAA,GAEJ,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -0,0 +1,153 @@
1
+ import { D as x, n as v, d as A, p as k, a as M } from "./pathfinding.js";
2
+ function b(i, l, r, s = x) {
3
+ const n = i.filter((e) => r.includes(e.id));
4
+ if (n.length < 2) return null;
5
+ const d = n.reduce((e, u) => u.id < e.id ? u : e), o = [];
6
+ for (const e of n)
7
+ e.id !== d.id && A(e, d) <= s && o.push(e.id);
8
+ if (o.length === 0) return null;
9
+ const f = new Set(o), h = [];
10
+ for (const e of l) {
11
+ let u = !1;
12
+ if (f.has(e.fromAnchorId) && (e.fromAnchorId = d.id, u = !0), f.has(e.toAnchorId) && (e.toAnchorId = d.id, u = !0), e.fromAnchorId === e.toAnchorId) {
13
+ h.push(e.id);
14
+ continue;
15
+ }
16
+ u && h.push(e.id);
17
+ }
18
+ return {
19
+ survivingAnchorId: d.id,
20
+ removedAnchorIds: o,
21
+ rewiredEdgeIds: h
22
+ };
23
+ }
24
+ function E(i, l = x) {
25
+ const r = [], s = /* @__PURE__ */ new Set();
26
+ for (let n = 0; n < i.length; n++) {
27
+ if (s.has(i[n].id)) continue;
28
+ const d = [i[n].id];
29
+ for (let o = n + 1; o < i.length; o++)
30
+ s.has(i[o].id) || i[n].levelId === i[o].levelId && A(i[n], i[o]) <= l && (d.push(i[o].id), s.add(i[o].id));
31
+ d.length > 1 && (s.add(i[n].id), r.push(d));
32
+ }
33
+ return r;
34
+ }
35
+ function T(i, l, r, s = x) {
36
+ let n = null;
37
+ for (const o of l) {
38
+ const f = v(i, o);
39
+ f && (!n || f.distance < n.distance) && (n = { point: f.point, distance: f.distance });
40
+ }
41
+ if (!n) return null;
42
+ const d = r.find(
43
+ (o) => o.levelId === i.levelId && A(o, n.point) <= s
44
+ );
45
+ return {
46
+ unitAnchorId: i.id,
47
+ junctionAnchor: d ? { x: d.x, y: d.y, existingId: d.id } : { x: n.point.x, y: n.point.y },
48
+ edge: {
49
+ fromAnchorId: i.id,
50
+ toAnchorId: d == null ? void 0 : d.id
51
+ }
52
+ };
53
+ }
54
+ function C(i, l, r, s) {
55
+ if (r.length === 0) return null;
56
+ const n = r.flat();
57
+ if (n.length === 0) return null;
58
+ let d = 0, o = 0;
59
+ for (const e of n)
60
+ d += e.x, o += e.y;
61
+ const f = { x: d / n.length, y: o / n.length }, h = k(f, r) ? f : n[0];
62
+ return {
63
+ id: s,
64
+ levelId: l,
65
+ shapeId: i,
66
+ kind: "unit",
67
+ x: h.x,
68
+ y: h.y,
69
+ connectorId: null
70
+ };
71
+ }
72
+ function j(i, l, r = 20) {
73
+ if (i.length === 0)
74
+ return { anchors: [], edges: [] };
75
+ let s = 1 / 0, n = 1 / 0, d = -1 / 0, o = -1 / 0;
76
+ for (const t of i)
77
+ for (const c of t)
78
+ s = Math.min(s, c.x), n = Math.min(n, c.y), d = Math.max(d, c.x), o = Math.max(o, c.y);
79
+ const f = Math.max(1, Math.ceil((d - s) / r)), h = Math.max(1, Math.ceil((o - n) / r)), e = [];
80
+ for (let t = 0; t < h; t++)
81
+ for (let c = 0; c < f; c++) {
82
+ const g = s + (c + 0.5) * r, I = n + (t + 0.5) * r, m = { x: g, y: I };
83
+ k(m, i) && (l.length > 0 && k(m, l) || e.push({ key: `${c},${t}`, x: g, y: I, col: c, row: t }));
84
+ }
85
+ const u = new Map(e.map((t) => [t.key, t])), y = e.map((t) => ({
86
+ tempId: t.key,
87
+ x: t.x,
88
+ y: t.y,
89
+ kind: "junction"
90
+ })), p = [], a = /* @__PURE__ */ new Set();
91
+ for (const t of e) {
92
+ const c = [
93
+ [t.col + 1, t.row],
94
+ [t.col, t.row + 1]
95
+ ];
96
+ for (const [g, I] of c) {
97
+ const m = `${g},${I}`;
98
+ if (!u.has(m)) continue;
99
+ const w = t.key < m ? `${t.key}|${m}` : `${m}|${t.key}`;
100
+ a.has(w) || (a.add(w), p.push({ fromTempId: t.key, toTempId: m }));
101
+ }
102
+ }
103
+ return { anchors: y, edges: p };
104
+ }
105
+ function D(i, l, r, s, n = x, d) {
106
+ const o = [], f = [];
107
+ let h = s;
108
+ const e = (u, y) => {
109
+ const p = o.find(
110
+ (t) => A(t, { x: u, y }) <= n
111
+ );
112
+ if (p) return p.id;
113
+ const a = h++;
114
+ return o.push({
115
+ id: a,
116
+ levelId: l,
117
+ shapeId: null,
118
+ kind: "junction",
119
+ x: u,
120
+ y,
121
+ connectorId: null
122
+ }), a;
123
+ };
124
+ for (const u of i) {
125
+ const y = M(u, d);
126
+ for (const p of y)
127
+ for (let a = 0; a < p.length - 1; a++) {
128
+ const t = e(p[a].x, p[a].y), c = e(p[a + 1].x, p[a + 1].y);
129
+ t === c || f.some(
130
+ (I) => I.fromAnchorId === t && I.toAnchorId === c || I.fromAnchorId === c && I.toAnchorId === t
131
+ ) || f.push({
132
+ id: h++,
133
+ mapId: r,
134
+ fromAnchorId: t,
135
+ toAnchorId: c,
136
+ weight: null,
137
+ directed: !1,
138
+ accessible: !0,
139
+ kind: "walk"
140
+ });
141
+ }
142
+ }
143
+ return { anchors: o, edges: f, nextId: h };
144
+ }
145
+ export {
146
+ T as a,
147
+ j as b,
148
+ E as f,
149
+ D as i,
150
+ C as u,
151
+ b as w
152
+ };
153
+ //# sourceMappingURL=graph-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-tools.js","sources":["../../src/core/routing/graph-tools.ts"],"sourcesContent":["import type {\n AutoConnectResult,\n CmAnchor,\n CmRouteEdge,\n SkeletonSuggestion,\n Vec2,\n WeldResult,\n} from '../types';\nimport { DEFAULT_WELD_TOLERANCE } from '../types';\nimport {\n distance,\n nearestPointOnPolyline,\n pathToPolygons,\n pointInPolygons,\n} from '../geometry';\n\nexport interface AnchorLike {\n id: number;\n x: number;\n y: number;\n levelId: number;\n shapeId?: number | null;\n kind?: string;\n}\n\nexport interface EdgeLike {\n id: number;\n fromAnchorId: number;\n toAnchorId: number;\n}\n\n/**\n * Weld anchors within tolerance into the surviving (lowest id) anchor.\n * Rewires edges that referenced removed anchors.\n */\nexport function weldAnchors(\n anchors: AnchorLike[],\n edges: EdgeLike[],\n candidateIds: number[],\n tolerance = DEFAULT_WELD_TOLERANCE,\n): WeldResult | null {\n const candidates = anchors.filter((a) => candidateIds.includes(a.id));\n if (candidates.length < 2) return null;\n\n // Cluster by proximity from the first candidate's position centroid of group\n const surviving = candidates.reduce((min, a) => (a.id < min.id ? a : min));\n const removed: number[] = [];\n\n for (const a of candidates) {\n if (a.id === surviving.id) continue;\n if (distance(a, surviving) <= tolerance) {\n removed.push(a.id);\n }\n }\n\n if (removed.length === 0) return null;\n\n const removedSet = new Set(removed);\n const rewired: number[] = [];\n\n for (const edge of edges) {\n let changed = false;\n if (removedSet.has(edge.fromAnchorId)) {\n edge.fromAnchorId = surviving.id;\n changed = true;\n }\n if (removedSet.has(edge.toAnchorId)) {\n edge.toAnchorId = surviving.id;\n changed = true;\n }\n // Drop self-loops\n if (edge.fromAnchorId === edge.toAnchorId) {\n rewired.push(edge.id);\n continue;\n }\n if (changed) rewired.push(edge.id);\n }\n\n return {\n survivingAnchorId: surviving.id,\n removedAnchorIds: removed,\n rewiredEdgeIds: rewired,\n };\n}\n\n/**\n * Find all pairs of anchors within tolerance that should be welded.\n */\nexport function findWeldCandidates(\n anchors: AnchorLike[],\n tolerance = DEFAULT_WELD_TOLERANCE,\n): number[][] {\n const groups: number[][] = [];\n const used = new Set<number>();\n\n for (let i = 0; i < anchors.length; i++) {\n if (used.has(anchors[i].id)) continue;\n const group = [anchors[i].id];\n for (let j = i + 1; j < anchors.length; j++) {\n if (used.has(anchors[j].id)) continue;\n if (\n anchors[i].levelId === anchors[j].levelId &&\n distance(anchors[i], anchors[j]) <= tolerance\n ) {\n group.push(anchors[j].id);\n used.add(anchors[j].id);\n }\n }\n if (group.length > 1) {\n used.add(anchors[i].id);\n groups.push(group);\n }\n }\n return groups;\n}\n\n/**\n * Auto-connect a unit anchor to the nearest walkable segment via perpendicular projection.\n */\nexport function autoConnectUnitAnchor(\n unitAnchor: AnchorLike,\n walkablePolylines: Vec2[][],\n existingJunctions: AnchorLike[],\n weldTolerance = DEFAULT_WELD_TOLERANCE,\n): AutoConnectResult | null {\n let best: { point: Vec2; distance: number } | null = null;\n\n for (const line of walkablePolylines) {\n const hit = nearestPointOnPolyline(unitAnchor, line);\n if (hit && (!best || hit.distance < best.distance)) {\n best = { point: hit.point, distance: hit.distance };\n }\n }\n\n if (!best) return null;\n\n // Reuse existing junction if within weld tolerance\n const existing = existingJunctions.find(\n (j) =>\n j.levelId === unitAnchor.levelId &&\n distance(j, best!.point) <= weldTolerance,\n );\n\n return {\n unitAnchorId: unitAnchor.id,\n junctionAnchor: existing\n ? { x: existing.x, y: existing.y, existingId: existing.id }\n : { x: best.point.x, y: best.point.y },\n edge: {\n fromAnchorId: unitAnchor.id,\n toAnchorId: existing?.id,\n },\n };\n}\n\n/**\n * Place a unit anchor at the centroid of a shape's polygons, if the point lies inside.\n */\nexport function unitAnchorFromShape(\n shapeId: number,\n levelId: number,\n polygons: Vec2[][],\n tempId: number,\n): CmAnchor | null {\n if (polygons.length === 0) return null;\n const flat = polygons.flat();\n if (flat.length === 0) return null;\n\n let sx = 0;\n let sy = 0;\n for (const p of flat) {\n sx += p.x;\n sy += p.y;\n }\n const c = { x: sx / flat.length, y: sy / flat.length };\n\n // Prefer centroid if inside; otherwise use first polygon's average of extremes\n const point = pointInPolygons(c, polygons) ? c : flat[0];\n\n return {\n id: tempId,\n levelId,\n shapeId,\n kind: 'unit',\n x: point.x,\n y: point.y,\n connectorId: null,\n };\n}\n\n/**\n * Build a simple medial-axis-ish skeleton from walkable polygons minus voids.\n * This is a pragmatic approximation: sample a grid inside walkable, reject void cells,\n * connect adjacent free cells into a sparse graph, then prune to a polyline network.\n */\nexport function buildAutoSkeleton(\n walkablePolygons: Vec2[][],\n voidPolygons: Vec2[][],\n cellSize = 20,\n): SkeletonSuggestion {\n if (walkablePolygons.length === 0) {\n return { anchors: [], edges: [] };\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const poly of walkablePolygons) {\n for (const p of poly) {\n minX = Math.min(minX, p.x);\n minY = Math.min(minY, p.y);\n maxX = Math.max(maxX, p.x);\n maxY = Math.max(maxY, p.y);\n }\n }\n\n const cols = Math.max(1, Math.ceil((maxX - minX) / cellSize));\n const rows = Math.max(1, Math.ceil((maxY - minY) / cellSize));\n const free: Array<{ key: string; x: number; y: number; col: number; row: number }> = [];\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const x = minX + (col + 0.5) * cellSize;\n const y = minY + (row + 0.5) * cellSize;\n const pt = { x, y };\n if (!pointInPolygons(pt, walkablePolygons)) continue;\n if (voidPolygons.length > 0 && pointInPolygons(pt, voidPolygons)) continue;\n free.push({ key: `${col},${row}`, x, y, col, row });\n }\n }\n\n const byKey = new Map(free.map((c) => [c.key, c]));\n const anchors = free.map((c) => ({\n tempId: c.key,\n x: c.x,\n y: c.y,\n kind: 'junction' as const,\n }));\n\n const edges: Array<{ fromTempId: string; toTempId: string }> = [];\n const seen = new Set<string>();\n\n for (const cell of free) {\n const neighbors = [\n [cell.col + 1, cell.row],\n [cell.col, cell.row + 1],\n ];\n for (const [nc, nr] of neighbors) {\n const nk = `${nc},${nr}`;\n if (!byKey.has(nk)) continue;\n const edgeKey = cell.key < nk ? `${cell.key}|${nk}` : `${nk}|${cell.key}`;\n if (seen.has(edgeKey)) continue;\n seen.add(edgeKey);\n edges.push({ fromTempId: cell.key, toTempId: nk });\n }\n }\n\n return { anchors, edges };\n}\n\n/**\n * Convert route-path SVG line endpoints into welded anchors + edges.\n * This is the key converter step that repairs coincident-but-disconnected joins.\n */\nexport function importRoutePaths(\n pathDs: string[],\n levelId: number,\n mapId: number,\n startId: number,\n weldTolerance = DEFAULT_WELD_TOLERANCE,\n viewboxHeight?: number,\n): { anchors: CmAnchor[]; edges: CmRouteEdge[]; nextId: number } {\n const anchors: CmAnchor[] = [];\n const edges: CmRouteEdge[] = [];\n let nextId = startId;\n\n const findOrCreate = (x: number, y: number): number => {\n const existing = anchors.find(\n (a) => distance(a, { x, y }) <= weldTolerance,\n );\n if (existing) return existing.id;\n const id = nextId++;\n anchors.push({\n id,\n levelId,\n shapeId: null,\n kind: 'junction',\n x,\n y,\n connectorId: null,\n });\n return id;\n };\n\n for (const d of pathDs) {\n const polys = pathToPolygons(d, viewboxHeight);\n for (const poly of polys) {\n for (let i = 0; i < poly.length - 1; i++) {\n const a = findOrCreate(poly[i].x, poly[i].y);\n const b = findOrCreate(poly[i + 1].x, poly[i + 1].y);\n if (a === b) continue;\n // Avoid duplicate edges\n const dup = edges.some(\n (e) =>\n (e.fromAnchorId === a && e.toAnchorId === b) ||\n (e.fromAnchorId === b && e.toAnchorId === a),\n );\n if (dup) continue;\n edges.push({\n id: nextId++,\n mapId,\n fromAnchorId: a,\n toAnchorId: b,\n weight: null,\n directed: false,\n accessible: true,\n kind: 'walk',\n });\n }\n }\n }\n\n return { anchors, edges, nextId };\n}\n"],"names":["weldAnchors","anchors","edges","candidateIds","tolerance","DEFAULT_WELD_TOLERANCE","candidates","a","surviving","min","removed","distance","removedSet","rewired","edge","changed","findWeldCandidates","groups","used","i","group","j","autoConnectUnitAnchor","unitAnchor","walkablePolylines","existingJunctions","weldTolerance","best","line","hit","nearestPointOnPolyline","existing","unitAnchorFromShape","shapeId","levelId","polygons","tempId","flat","sx","sy","p","c","point","pointInPolygons","buildAutoSkeleton","walkablePolygons","voidPolygons","cellSize","minX","minY","maxX","maxY","poly","cols","rows","free","row","col","x","y","pt","byKey","seen","cell","neighbors","nc","nr","nk","edgeKey","importRoutePaths","pathDs","mapId","startId","viewboxHeight","nextId","findOrCreate","id","d","polys","pathToPolygons","b","e"],"mappings":"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"}
@@ -0,0 +1,343 @@
1
+ import N from "ngraph.graph";
2
+ import C from "ngraph.path";
3
+ const X = {
4
+ MAP_STYLE: "2D",
5
+ MAP_BACKGROUND_COLOR: "#f5f5f5",
6
+ ACCENT_COLOR: "#2563eb",
7
+ STORE_DEFAULT_COLOR: "#e2e8f0",
8
+ STORE_TEXT_COLOR: "#1e293b",
9
+ STORE_HEIGHT: 4,
10
+ WALL_COLOR: "#64748b",
11
+ WALL_THICKNESS: 0.4,
12
+ BOUNDARY_COLOR: "#334155",
13
+ BOUNDARY_THICKNESS: 0.6,
14
+ BASE_COLOR: "#ffffff",
15
+ OVERLAY_COLOR: "#000000",
16
+ OVERLAY_OPACITY: 0.15,
17
+ PARKING_ZONE_COLOR: "#cbd5e1",
18
+ GREEN_AREA_COLOR: "#86efac",
19
+ WATER_COLOR: "#7dd3fc",
20
+ WALKABLE_COLOR: "#f8fafc",
21
+ KIOSK_SIZE: 12,
22
+ ZOOM_STEP: 0.5,
23
+ CAMERA_MAX_DISTANCE: 2e3,
24
+ CAMERA_MIN_DISTANCE: 50
25
+ }, B = [
26
+ "unit",
27
+ "amenity",
28
+ "kiosk_screen",
29
+ "connector",
30
+ "entrance",
31
+ "parking_zone"
32
+ ], _ = 1e4, W = 2.5;
33
+ function b(e, n) {
34
+ return e.map((i) => ({ x: i.x, y: n - i.y }));
35
+ }
36
+ function A(e, n) {
37
+ const i = e.x - n.x, r = e.y - n.y;
38
+ return Math.hypot(i, r);
39
+ }
40
+ function M(e) {
41
+ if (e.length === 0)
42
+ return { minX: 0, minY: 0, maxX: 0, maxY: 0 };
43
+ let n = e[0].x, i = e[0].y, r = e[0].x, o = e[0].y;
44
+ for (let s = 1; s < e.length; s++) {
45
+ const t = e[s];
46
+ t.x < n && (n = t.x), t.y < i && (i = t.y), t.x > r && (r = t.x), t.y > o && (o = t.y);
47
+ }
48
+ return { minX: n, minY: i, maxX: r, maxY: o };
49
+ }
50
+ function F(e, n) {
51
+ return {
52
+ minX: Math.min(e.minX, n.minX),
53
+ minY: Math.min(e.minY, n.minY),
54
+ maxX: Math.max(e.maxX, n.maxX),
55
+ maxY: Math.max(e.maxY, n.maxY)
56
+ };
57
+ }
58
+ function T(e) {
59
+ if (e.length === 0) return { x: 0, y: 0 };
60
+ let n = 0, i = 0;
61
+ for (const r of e)
62
+ n += r.x, i += r.y;
63
+ return { x: n / e.length, y: i / e.length };
64
+ }
65
+ function k(e, n) {
66
+ let i = !1;
67
+ for (let r = 0, o = n.length - 1; r < n.length; o = r++) {
68
+ const s = n[r].x, t = n[r].y, u = n[o].x, c = n[o].y;
69
+ t > e.y != c > e.y && e.x < (u - s) * (e.y - t) / (c - t + Number.EPSILON) + s && (i = !i);
70
+ }
71
+ return i;
72
+ }
73
+ function G(e, n) {
74
+ return n.some((i) => k(e, i));
75
+ }
76
+ function S(e, n, i) {
77
+ const r = i.x - n.x, o = i.y - n.y, s = r * r + o * o;
78
+ if (s === 0)
79
+ return { point: { ...n }, t: 0, distance: A(e, n) };
80
+ let t = ((e.x - n.x) * r + (e.y - n.y) * o) / s;
81
+ t = Math.max(0, Math.min(1, t));
82
+ const u = { x: n.x + t * r, y: n.y + t * o };
83
+ return { point: u, t, distance: A(e, u) };
84
+ }
85
+ function K(e, n) {
86
+ if (n.length < 2) return null;
87
+ let i = null;
88
+ for (let r = 0; r < n.length - 1; r++) {
89
+ const o = S(e, n[r], n[r + 1]);
90
+ (!i || o.distance < i.distance) && (i = { point: o.point, segmentIndex: r, distance: o.distance });
91
+ }
92
+ return i;
93
+ }
94
+ function R(e, n, i, r, o = 8) {
95
+ const s = [];
96
+ for (let t = 0; t <= o; t++) {
97
+ const u = t / o, c = 1 - u;
98
+ s.push({
99
+ x: c * c * c * e.x + 3 * c * c * u * n.x + 3 * c * u * u * i.x + u * u * u * r.x,
100
+ y: c * c * c * e.y + 3 * c * c * u * n.y + 3 * c * u * u * i.y + u * u * u * r.y
101
+ });
102
+ }
103
+ return s;
104
+ }
105
+ function L(e, n, i, r = 6) {
106
+ const o = [];
107
+ for (let s = 0; s <= r; s++) {
108
+ const t = s / r, u = 1 - t;
109
+ o.push({
110
+ x: u * u * e.x + 2 * u * t * n.x + t * t * i.x,
111
+ y: u * u * e.y + 2 * u * t * n.y + t * t * i.y
112
+ });
113
+ }
114
+ return o;
115
+ }
116
+ function P(e, n) {
117
+ const i = e.match(/[a-zA-Z]|-?\d*\.?\d+(?:e[-+]?\d+)?/g) ?? [], r = [];
118
+ let o = [], s = 0, t = 0, u = 0, c = 0, d = null, m = 0, y = "";
119
+ const a = () => Number(i[m++]);
120
+ for (; m < i.length; ) {
121
+ const h = i[m];
122
+ switch (/[a-zA-Z]/.test(h) && (y = h, m++), y) {
123
+ case "M":
124
+ case "m": {
125
+ const l = y === "m", f = a(), x = a();
126
+ s = l ? s + f : f, t = l ? t + x : x, o.length > 0 && r.push(o), o = [{ x: s, y: t }], u = s, c = t, d = null, y = l ? "l" : "L";
127
+ break;
128
+ }
129
+ case "L":
130
+ case "l": {
131
+ const l = y === "l", f = a(), x = a();
132
+ s = l ? s + f : f, t = l ? t + x : x, o.push({ x: s, y: t }), d = null;
133
+ break;
134
+ }
135
+ case "H":
136
+ case "h": {
137
+ const l = y === "h", f = a();
138
+ s = l ? s + f : f, o.push({ x: s, y: t }), d = null;
139
+ break;
140
+ }
141
+ case "V":
142
+ case "v": {
143
+ const l = y === "v", f = a();
144
+ t = l ? t + f : f, o.push({ x: s, y: t }), d = null;
145
+ break;
146
+ }
147
+ case "C":
148
+ case "c": {
149
+ const l = y === "c", f = l ? s + a() : a(), x = l ? t + a() : a(), I = l ? s + a() : a(), p = l ? t + a() : a(), g = l ? s + a() : a(), O = l ? t + a() : a(), E = R(
150
+ { x: s, y: t },
151
+ { x: f, y: x },
152
+ { x: I, y: p },
153
+ { x: g, y: O }
154
+ );
155
+ o.push(...E.slice(1)), d = { x: I, y: p }, s = g, t = O;
156
+ break;
157
+ }
158
+ case "Q":
159
+ case "q": {
160
+ const l = y === "q", f = l ? s + a() : a(), x = l ? t + a() : a(), I = l ? s + a() : a(), p = l ? t + a() : a(), g = L(
161
+ { x: s, y: t },
162
+ { x: f, y: x },
163
+ { x: I, y: p }
164
+ );
165
+ o.push(...g.slice(1)), d = { x: f, y: x }, s = I, t = p;
166
+ break;
167
+ }
168
+ case "S":
169
+ case "s": {
170
+ const l = y === "s", f = d ? 2 * s - d.x : s, x = d ? 2 * t - d.y : t, I = l ? s + a() : a(), p = l ? t + a() : a(), g = l ? s + a() : a(), O = l ? t + a() : a(), E = R(
171
+ { x: s, y: t },
172
+ { x: f, y: x },
173
+ { x: I, y: p },
174
+ { x: g, y: O }
175
+ );
176
+ o.push(...E.slice(1)), d = { x: I, y: p }, s = g, t = O;
177
+ break;
178
+ }
179
+ case "T":
180
+ case "t": {
181
+ const l = y === "t", f = d ? 2 * s - d.x : s, x = d ? 2 * t - d.y : t, I = l ? s + a() : a(), p = l ? t + a() : a(), g = L(
182
+ { x: s, y: t },
183
+ { x: f, y: x },
184
+ { x: I, y: p }
185
+ );
186
+ o.push(...g.slice(1)), d = { x: f, y: x }, s = I, t = p;
187
+ break;
188
+ }
189
+ case "Z":
190
+ case "z": {
191
+ o.push({ x: u, y: c }), r.push(o), o = [], s = u, t = c, d = null;
192
+ break;
193
+ }
194
+ default:
195
+ m++;
196
+ break;
197
+ }
198
+ }
199
+ return o.length > 0 && r.push(o), n != null ? r.map((h) => b(h, n)) : r;
200
+ }
201
+ function j(e, n, i = !0) {
202
+ const r = (n == null ? void 0 : n.height) ?? 0, o = e.map((t) => ({
203
+ d: t,
204
+ closed: /z/i.test(t)
205
+ })), s = e.flatMap(
206
+ (t) => P(t, i && r > 0 ? r : void 0)
207
+ );
208
+ return { paths: o, polygons: s };
209
+ }
210
+ function w(e) {
211
+ const n = e.polygons.flat();
212
+ return M(n);
213
+ }
214
+ function H(e) {
215
+ return T(e.polygons.flat());
216
+ }
217
+ function U(e, n, i = 0, r = [15, 45, 90]) {
218
+ const o = n.x - e.x, s = n.y - e.y, t = Math.hypot(o, s);
219
+ if (t === 0) return { ...n };
220
+ const c = Math.atan2(s, o) * 180 / Math.PI - i;
221
+ let d = c, m = 1 / 0;
222
+ for (const a of r) {
223
+ const h = Math.round(c / a) * a, l = Math.abs(c - h);
224
+ l < m && (m = l, d = h);
225
+ }
226
+ const y = (d + i) * Math.PI / 180;
227
+ return {
228
+ x: e.x + Math.cos(y) * t,
229
+ y: e.y + Math.sin(y) * t
230
+ };
231
+ }
232
+ function V(e, n) {
233
+ return Math.atan2(n.y - e.y, n.x - e.x) * 180 / Math.PI;
234
+ }
235
+ function Z(e) {
236
+ if (!e) return null;
237
+ const n = e.trim().split(/[\s,]+/).map(Number);
238
+ return n.length !== 4 || n.some((i) => Number.isNaN(i)) ? null : { x: n[0], y: n[1], width: n[2], height: n[3] };
239
+ }
240
+ function z(e, n, i = []) {
241
+ const r = N(), o = new Map(e.map((c) => [c.id, c])), s = new Map(i.map((c) => [c.id, c])), t = e.map((c) => ({
242
+ id: c.id,
243
+ levelId: c.levelId,
244
+ x: c.x,
245
+ y: c.y,
246
+ kind: c.kind,
247
+ shapeId: c.shapeId,
248
+ connectorId: c.connectorId
249
+ }));
250
+ for (const c of t)
251
+ r.addNode(c.id, c);
252
+ const u = [];
253
+ for (const c of n) {
254
+ const d = o.get(c.fromAnchorId), m = o.get(c.toAnchorId);
255
+ if (!d || !m) continue;
256
+ let y = c.weight;
257
+ y == null && (y = A(d, m), d.levelId !== m.levelId && (y += _));
258
+ let a = c.accessible;
259
+ if (c.kind === "connector" && d.connectorId != null) {
260
+ const l = s.get(d.connectorId);
261
+ l && (a = l.accessible);
262
+ }
263
+ const h = {
264
+ id: c.id,
265
+ from: c.fromAnchorId,
266
+ to: c.toAnchorId,
267
+ weight: y,
268
+ directed: c.directed,
269
+ accessible: a,
270
+ kind: c.kind
271
+ };
272
+ u.push(h), r.addLink(c.fromAnchorId, c.toAnchorId, h), c.directed || r.addLink(c.toAnchorId, c.fromAnchorId, h);
273
+ }
274
+ return { graph: r, nodes: t, edges: u, anchorById: o };
275
+ }
276
+ function Y(e, n, i, r = {}) {
277
+ const { graph: o, anchorById: s } = e;
278
+ if (!s.has(n) || !s.has(i))
279
+ return null;
280
+ const u = C.nba(o, {
281
+ distance(h, l, f) {
282
+ const x = f.data;
283
+ return r.accessibleOnly && x && !x.accessible ? Number.POSITIVE_INFINITY : (x == null ? void 0 : x.weight) ?? 1;
284
+ },
285
+ heuristic(h, l) {
286
+ const f = s.get(h.id), x = s.get(l.id);
287
+ if (!f || !x) return 0;
288
+ let I = A(f, x);
289
+ return f.levelId !== x.levelId && (I += _), I;
290
+ }
291
+ }).find(n, i);
292
+ if (!u || u.length === 0) return null;
293
+ const d = u.reverse().map((h) => h.id), m = [], y = [];
294
+ let a = 0;
295
+ for (let h = 0; h < d.length; h++) {
296
+ const l = s.get(d[h]);
297
+ if (m.push({ x: l.x, y: l.y, levelId: l.levelId }), h > 0) {
298
+ const f = s.get(d[h - 1]);
299
+ a += A(f, l), f.levelId !== l.levelId && (a += _, y.push({
300
+ fromLevelId: f.levelId,
301
+ toLevelId: l.levelId,
302
+ connectorId: l.connectorId ?? f.connectorId
303
+ }));
304
+ }
305
+ }
306
+ return { anchorIds: d, points: m, totalWeight: a, levelChanges: y };
307
+ }
308
+ function q(e, n, i, r = {}) {
309
+ let o = null;
310
+ for (const s of i) {
311
+ const t = Y(e, n, s, r);
312
+ t && (!o || t.totalWeight < o.totalWeight) && (o = t);
313
+ }
314
+ return o;
315
+ }
316
+ export {
317
+ W as D,
318
+ _ as F,
319
+ B as I,
320
+ P as a,
321
+ j as b,
322
+ Z as c,
323
+ A as d,
324
+ X as e,
325
+ z as f,
326
+ w as g,
327
+ V as h,
328
+ R as i,
329
+ L as j,
330
+ M as k,
331
+ F as l,
332
+ T as m,
333
+ K as n,
334
+ q as o,
335
+ G as p,
336
+ Y as q,
337
+ b as r,
338
+ H as s,
339
+ k as t,
340
+ S as u,
341
+ U as v
342
+ };
343
+ //# sourceMappingURL=pathfinding.js.map