@eyeon/map 2.0.1 → 2.0.3
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 +18 -1
- package/dist/assets/MapViewer.css +1 -1
- package/dist/assets/index.css +1 -1
- package/dist/chunks/MapViewer.js +1988 -358
- package/dist/chunks/MapViewer.js.map +1 -1
- package/dist/chunks/graph-tools.js +202 -109
- package/dist/chunks/graph-tools.js.map +1 -1
- package/dist/chunks/stacking.js +1426 -0
- package/dist/chunks/stacking.js.map +1 -0
- package/dist/core/filletPolygon.d.ts +10 -0
- package/dist/core/filletPolygon.d.ts.map +1 -0
- package/dist/core/geometry/index.d.ts +41 -4
- package/dist/core/geometry/index.d.ts.map +1 -1
- package/dist/core/hostChrome.d.ts +20 -0
- package/dist/core/hostChrome.d.ts.map +1 -0
- package/dist/core/import/index.d.ts +52 -3
- package/dist/core/import/index.d.ts.map +1 -1
- package/dist/core/import/svgStyle.d.ts +21 -0
- package/dist/core/import/svgStyle.d.ts.map +1 -0
- package/dist/core/import/svgTransform.d.ts +49 -0
- package/dist/core/import/svgTransform.d.ts.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +89 -279
- package/dist/core/index.js.map +1 -1
- package/dist/core/layerStyles.d.ts +44 -0
- package/dist/core/layerStyles.d.ts.map +1 -0
- package/dist/core/mediaUrl.d.ts +3 -0
- package/dist/core/mediaUrl.d.ts.map +1 -0
- package/dist/core/outdoorDecoration.d.ts +16 -0
- package/dist/core/outdoorDecoration.d.ts.map +1 -0
- package/dist/core/publish/index.d.ts +8 -2
- package/dist/core/publish/index.d.ts.map +1 -1
- package/dist/core/routing/graph-tools.d.ts +28 -2
- package/dist/core/routing/graph-tools.d.ts.map +1 -1
- package/dist/core/routing/pathfinding.d.ts.map +1 -1
- package/dist/core/stacking.d.ts +61 -0
- package/dist/core/stacking.d.ts.map +1 -0
- package/dist/core/types.d.ts +31 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/editor/MapEditor.d.ts +28 -16
- package/dist/editor/MapEditor.d.ts.map +1 -1
- package/dist/editor/canvas/EditorCanvas.d.ts +56 -6
- package/dist/editor/canvas/EditorCanvas.d.ts.map +1 -1
- package/dist/editor/canvas/OutdoorSvgUnderlay.d.ts +7 -0
- package/dist/editor/canvas/OutdoorSvgUnderlay.d.ts.map +1 -0
- package/dist/editor/canvas/coords.d.ts +51 -0
- package/dist/editor/canvas/coords.d.ts.map +1 -0
- package/dist/editor/canvas/editorFill.d.ts +10 -0
- package/dist/editor/canvas/editorFill.d.ts.map +1 -0
- package/dist/editor/canvas/editorHover.d.ts +14 -0
- package/dist/editor/canvas/editorHover.d.ts.map +1 -0
- package/dist/editor/canvas/underlayHint.d.ts +5 -0
- package/dist/editor/canvas/underlayHint.d.ts.map +1 -0
- package/dist/editor/connectorAssignments.d.ts +64 -0
- package/dist/editor/connectorAssignments.d.ts.map +1 -0
- package/dist/editor/draftOps.d.ts +22 -0
- package/dist/editor/draftOps.d.ts.map +1 -0
- package/dist/editor/editorSectionReturn.d.ts +12 -0
- package/dist/editor/editorSectionReturn.d.ts.map +1 -0
- package/dist/editor/floorsListReturn.d.ts +5 -0
- package/dist/editor/floorsListReturn.d.ts.map +1 -0
- package/dist/editor/geometryEdit.d.ts +54 -0
- package/dist/editor/geometryEdit.d.ts.map +1 -0
- package/dist/editor/hexColor.d.ts +4 -0
- package/dist/editor/hexColor.d.ts.map +1 -0
- package/dist/editor/history.d.ts +31 -0
- package/dist/editor/history.d.ts.map +1 -0
- package/dist/editor/index.css +1497 -143
- package/dist/editor/index.d.ts +9 -3
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/editor/index.js +6377 -601
- package/dist/editor/index.js.map +1 -1
- package/dist/editor/labelText.d.ts +15 -0
- package/dist/editor/labelText.d.ts.map +1 -0
- package/dist/editor/labels.d.ts +5 -0
- package/dist/editor/labels.d.ts.map +1 -0
- package/dist/editor/panels/ConnectorAssign.d.ts +12 -0
- package/dist/editor/panels/ConnectorAssign.d.ts.map +1 -0
- package/dist/editor/panels/FloorsPanel.d.ts +64 -0
- package/dist/editor/panels/FloorsPanel.d.ts.map +1 -0
- package/dist/editor/panels/ImportReviewPanel.d.ts +22 -0
- package/dist/editor/panels/ImportReviewPanel.d.ts.map +1 -0
- package/dist/editor/panels/Inspector.d.ts +6 -3
- package/dist/editor/panels/Inspector.d.ts.map +1 -1
- package/dist/editor/panels/LeftRail.d.ts +26 -11
- package/dist/editor/panels/LeftRail.d.ts.map +1 -1
- package/dist/editor/panels/PreviewOverlay.d.ts +11 -2
- package/dist/editor/panels/PreviewOverlay.d.ts.map +1 -1
- package/dist/editor/pathRings.d.ts +79 -0
- package/dist/editor/pathRings.d.ts.map +1 -0
- package/dist/editor/portalSurface.d.ts +37 -0
- package/dist/editor/portalSurface.d.ts.map +1 -0
- package/dist/editor/previewDocument.d.ts +9 -0
- package/dist/editor/previewDocument.d.ts.map +1 -0
- package/dist/editor/railAssignments.d.ts +22 -0
- package/dist/editor/railAssignments.d.ts.map +1 -0
- package/dist/editor/routeStubs.d.ts +103 -0
- package/dist/editor/routeStubs.d.ts.map +1 -0
- package/dist/editor/snapPoint.d.ts +5 -0
- package/dist/editor/snapPoint.d.ts.map +1 -0
- package/dist/editor/splitJoin.d.ts +78 -0
- package/dist/editor/splitJoin.d.ts.map +1 -0
- package/dist/editor/tools.d.ts +49 -0
- package/dist/editor/tools.d.ts.map +1 -0
- package/dist/test-maps/shops-at-south-town/BASE - Shops At South Town.ai +26703 -28
- package/dist/test-maps/shops-at-south-town/LF - Shops At South Town.ai +4459 -0
- package/dist/test-maps/shops-at-south-town/SVG/BASE - Shops At South Town.svg +567 -0
- package/dist/test-maps/shops-at-south-town/SVG/LF - Shops At South Town.svg +238 -0
- package/dist/test-maps/shops-at-south-town/SVG/UF - Shops At South Town.svg +276 -0
- package/dist/test-maps/shops-at-south-town/UF - Shops At South Town.ai +4131 -1
- package/dist/ui/ModernSelect.d.ts +14 -0
- package/dist/ui/ModernSelect.d.ts.map +1 -0
- package/dist/ui/selectSearch.d.ts +9 -0
- package/dist/ui/selectSearch.d.ts.map +1 -0
- package/dist/viewer/MapViewer.d.ts +14 -3
- package/dist/viewer/MapViewer.d.ts.map +1 -1
- package/dist/viewer/camera.d.ts +37 -0
- package/dist/viewer/camera.d.ts.map +1 -0
- package/dist/viewer/components/CameraRig.d.ts +18 -0
- package/dist/viewer/components/CameraRig.d.ts.map +1 -0
- package/dist/viewer/components/LevelMeshes.d.ts +6 -1
- package/dist/viewer/components/LevelMeshes.d.ts.map +1 -1
- package/dist/viewer/components/MapScene.d.ts +6 -1
- package/dist/viewer/components/MapScene.d.ts.map +1 -1
- package/dist/viewer/components/SvgVectorLayer.d.ts +18 -0
- package/dist/viewer/components/SvgVectorLayer.d.ts.map +1 -0
- package/dist/viewer/index.css +236 -37
- package/dist/viewer/index.d.ts +4 -0
- package/dist/viewer/index.d.ts.map +1 -1
- package/dist/viewer/index.js +9 -4
- package/dist/viewer/index.js.map +1 -1
- package/dist/viewer/ui/MapControls.d.ts +22 -0
- package/dist/viewer/ui/MapControls.d.ts.map +1 -0
- package/dist/viewer/ui/RuntimeChrome.d.ts +3 -3
- package/dist/viewer/ui/RuntimeChrome.d.ts.map +1 -1
- package/package.json +7 -3
- package/dist/chunks/pathfinding.js +0 -343
- package/dist/chunks/pathfinding.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stacking.js","sources":["../../src/core/layerStyles.ts","../../src/core/types.ts","../../src/core/hostChrome.ts","../../src/core/mediaUrl.ts","../../src/core/geometry/index.ts","../../src/core/import/svgStyle.ts","../../src/core/import/svgTransform.ts","../../src/core/import/index.ts","../../src/core/filletPolygon.ts","../../src/core/routing/pathfinding.ts","../../src/core/publish/index.ts","../../src/core/stacking.ts"],"sourcesContent":["/**\n * Code-only static layer styling for recognized SVG layer-name prefixes.\n * Never loaded from or saved to portal / database theme settings — mirrors\n * v1 `staticMapLayerSettings` in `@eyeon/threejs-map`.\n */\n\nexport interface StaticLayerStyle {\n fill?: string;\n stroke?: string;\n strokeWidth?: number;\n renderOrder: number;\n extrudeHeight?: number;\n}\n\n/**\n * v1 walking-path has no portal setting — it keeps the SVG fill, and every\n * published mall file uses this icy walkway color. v2 locks the same hex.\n */\nexport const WALKING_PATH_COLOR = '#E9F7FC';\n\n/**\n * Prefix → house style. Matching is normalized so `parking-lane`,\n * `parking_lane`, and `parking-lanes` all resolve to the same entry.\n */\nexport const STATIC_LAYER_STYLES: Record<string, StaticLayerStyle> = {\n 'green-area': {\n fill: '#C4DDAB',\n renderOrder: 2,\n extrudeHeight: 1,\n },\n 'water-area': {\n fill: '#5cc0f9',\n renderOrder: 2,\n extrudeHeight: 1,\n },\n 'parking-lane': {\n fill: '#F6F6F6',\n renderOrder: 2,\n extrudeHeight: 1,\n },\n 'parking-line': {\n stroke: '#DDDDDD',\n strokeWidth: 0.6,\n renderOrder: 6,\n extrudeHeight: 0.5,\n },\n 'parking-icon': {\n fill: '#CCCCCC',\n renderOrder: 7,\n extrudeHeight: 1,\n },\n 'walking-path': {\n fill: WALKING_PATH_COLOR,\n renderOrder: 2,\n extrudeHeight: 1,\n },\n};\n\n/** Collapse punctuation so `parking_lane_2` and `parking-lanes` compare as words. */\nexport function normalizeLayerName(label: string): string {\n return label\n .toLowerCase()\n .replace(/[-_]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/**\n * Resolve a static house style from an SVG element / group id.\n * Returns null when the name is not a reserved decoration layer.\n *\n * Matches when the normalized name equals the key, starts with the key as a\n * word (`parking lane 2`), or is a simple plural (`parking lanes`).\n */\nexport function resolveLayerStyle(layerName: string | null | undefined): StaticLayerStyle | null {\n if (!layerName) return null;\n const normalized = normalizeLayerName(layerName);\n if (!normalized) return null;\n\n const keys = Object.keys(STATIC_LAYER_STYLES).sort((a, b) => b.length - a.length);\n for (const key of keys) {\n const keyNorm = normalizeLayerName(key);\n if (normalized === keyNorm) return STATIC_LAYER_STYLES[key];\n // `parking lane 2`, `parking lane-extra`\n if (normalized.startsWith(`${keyNorm} `)) return STATIC_LAYER_STYLES[key];\n // Plural: `parking lanes` from `parking-lanes`\n if (normalized === `${keyNorm}s`) return STATIC_LAYER_STYLES[key];\n if (normalized.startsWith(`${keyNorm}s `)) return STATIC_LAYER_STYLES[key];\n }\n return null;\n}\n\n/**\n * sourceSvgId values the live outdoor SVG should skip because `cm_shapes`\n * already owns them. Static house layers stay in the SVG so walking-path\n * (and parking / green) keep their code colors even when an older import\n * also persisted a walkable row.\n */\nexport function svgIdsOwnedByShapes(\n shapes: Iterable<{ sourceSvgId?: string | null }>,\n options?: { omitStaticLayers?: boolean },\n): Set<string> {\n const omitStatic = options?.omitStaticLayers === true;\n const ids = new Set<string>();\n for (const shape of shapes) {\n const id = shape.sourceSvgId;\n if (!id) continue;\n if (omitStatic && resolveLayerStyle(id)) continue;\n ids.add(id);\n }\n return ids;\n}\n","/**\n * @eyeon/map/core — shared document model types.\n * Pure TypeScript; no React / Three.js.\n */\n\nimport { WALKING_PATH_COLOR } from './layerStyles';\n\nexport type MapVersion = 1 | 2;\n\n/**\n * Surface the map is embedded in.\n *\n * - `PORTAL` — admin Center Map editor (`MapEditor`). Left rail is Map options\n * (Floors, Kiosks, Settings) plus Edit Map — never viewer chrome. Default\n * center is MapViewer (click-to-assign, no editor grid). Edit Map swaps\n * in the geometry canvas and grid.\n * - `PORTAL_ASSIGN` — admin editor default center (`MapViewer` for click-to-\n * assign). Floors + zoom only — no search / amenities.\n * - `WEBSITE` — public website (`MapViewer`).\n * - `DISPLAY_APP` — kiosk (`MapViewer`).\n */\nexport type MapHost =\n | 'PORTAL'\n | 'PORTAL_ASSIGN'\n | 'WEBSITE'\n | 'DISPLAY_APP';\n\n/** Staff editor host. `PORTAL` always shows Map options inside the library. */\nexport type MapEditorHost = Extract<MapHost, 'PORTAL' | 'WEBSITE'>;\n\n/** Public / assign viewer. Never includes Map options. */\nexport type MapViewerHost = Extract<\n MapHost,\n 'WEBSITE' | 'DISPLAY_APP' | 'PORTAL_ASSIGN'\n>;\n\nexport type LevelKind = 'outdoor' | 'floor';\n\nexport type ShapeKind =\n | 'unit'\n | 'amenity'\n | 'kiosk_screen'\n | 'connector'\n | 'entrance'\n | 'walkable'\n | 'void'\n | 'wall'\n | 'boundary'\n | 'floorplate'\n | 'decor'\n | 'label'\n | 'zone'\n | 'parking_zone'\n | 'green_area'\n | 'water'\n | 'parking_icon';\n\nexport type AnchorKind = 'unit' | 'junction' | 'connector' | 'entrance';\n\nexport type EdgeKind = 'walk' | 'unit_link' | 'connector' | 'entrance_link';\n\nexport type ConnectorKind =\n | 'escalator'\n | 'elevator'\n | 'stairs'\n | 'ramp'\n | 'travelator';\n\nexport type ConnectorDirection = 'up' | 'down' | 'both';\n\nexport type UnitStatus =\n | 'occupied'\n | 'vacant'\n | 'coming_soon'\n | 'under_renovation';\n\nexport type AssignmentTargetType =\n | 'retailer'\n | 'amenity'\n | 'kiosk'\n | 'none';\n\nexport type ShapeOrigin = 'import' | 'manual';\n\nexport type DeviceType = 'display_app' | 'desktop' | 'tablet' | 'mobile';\n\nexport type MapRenderMode = '2D' | '3D';\n\nexport interface Vec2 {\n x: number;\n y: number;\n}\n\nexport interface Vec3 {\n x: number;\n y: number;\n z: number;\n}\n\nexport interface BBox {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nexport interface ViewBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Absolute SVG path subpath preserving Illustrator beziers. */\nexport interface PathSubpath {\n d: string;\n closed: boolean;\n}\n\nexport interface ShapeGeometry {\n /** Absolute path data (Illustrator-compatible). */\n paths: PathSubpath[];\n /** Cached polygon approximation for hit-testing / routing. */\n polygons: Vec2[][];\n}\n\nexport interface ShapeStyle {\n fill?: string;\n stroke?: string;\n strokeWidth?: number;\n opacity?: number;\n extrudeHeight?: number;\n transparent?: boolean;\n}\n\nexport interface ShapeLabel {\n text?: string;\n imageKey?: string;\n size?: number;\n rotate?: number;\n offsetX?: number;\n offsetY?: number;\n color?: string;\n autoFit?: boolean;\n}\n\nexport interface LevelTransform {\n translateX: number;\n translateY: number;\n scale: number;\n rotate: number;\n}\n\nexport interface ThemeDefaults {\n MAP_STYLE: MapRenderMode;\n MAP_BACKGROUND_COLOR: string;\n ACCENT_COLOR: string;\n STORE_DEFAULT_COLOR: string;\n STORE_TEXT_COLOR: string;\n STORE_HEIGHT: number;\n /** Viewer-only corner radius for store (`unit`) polygons. Edit Map stays sharp. */\n STORE_RADIUS: number;\n WALL_COLOR: string;\n WALL_THICKNESS: number;\n BOUNDARY_COLOR: string;\n BOUNDARY_THICKNESS: number;\n BASE_COLOR: string;\n OVERLAY_COLOR: string;\n OVERLAY_OPACITY: number;\n PARKING_ZONE_COLOR: string;\n GREEN_AREA_COLOR: string;\n WATER_COLOR: string;\n WALKABLE_COLOR: string;\n KIOSK_SIZE: number;\n ZOOM_STEP: number;\n CAMERA_MAX_DISTANCE: number;\n CAMERA_MIN_DISTANCE: number;\n}\n\nexport const DEFAULT_THEME: ThemeDefaults = {\n MAP_STYLE: '2D',\n MAP_BACKGROUND_COLOR: '#FFFFFF',\n ACCENT_COLOR: '#2563eb',\n STORE_DEFAULT_COLOR: '#e2e8f0',\n STORE_TEXT_COLOR: '#1e293b',\n STORE_HEIGHT: 4,\n STORE_RADIUS: 0,\n WALL_COLOR: '#64748b',\n WALL_THICKNESS: 0.4,\n BOUNDARY_COLOR: '#334155',\n BOUNDARY_THICKNESS: 0.6,\n BASE_COLOR: '#ffffff',\n OVERLAY_COLOR: '#000000',\n OVERLAY_OPACITY: 0.15,\n PARKING_ZONE_COLOR: '#cbd5e1',\n GREEN_AREA_COLOR: '#86efac',\n WATER_COLOR: '#7dd3fc',\n WALKABLE_COLOR: WALKING_PATH_COLOR,\n KIOSK_SIZE: 12,\n ZOOM_STEP: 0.5,\n CAMERA_MAX_DISTANCE: 2000,\n CAMERA_MIN_DISTANCE: 50,\n};\n\n/** Early v2 default; same as canvas, so parking-lane #F6F6F6 disappeared. */\nconst LEGACY_V2_MAP_BACKGROUND = '#f5f5f5';\n\n/** Pre-house-color walkway fills — colder gray, then the beige guess. */\nconst LEGACY_WALKABLE_COLORS = new Set(['#f8fafc', '#f1efea']);\n\nconst MAX_STORE_RADIUS = 500;\n\n/** Non-negative store corner radius in SVG units. Invalid values become 0. */\nexport function clampStoreRadius(value: unknown): number {\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n) || n <= 0) return 0;\n return Math.min(n, MAX_STORE_RADIUS);\n}\n\nexport function mergeTheme(\n ...partials: Array<Partial<ThemeDefaults> | null | undefined>\n): ThemeDefaults {\n const theme = Object.assign({}, DEFAULT_THEME, ...partials.filter(Boolean));\n if (theme.MAP_BACKGROUND_COLOR.toLowerCase() === LEGACY_V2_MAP_BACKGROUND) {\n theme.MAP_BACKGROUND_COLOR = DEFAULT_THEME.MAP_BACKGROUND_COLOR;\n }\n if (LEGACY_WALKABLE_COLORS.has(theme.WALKABLE_COLOR.toLowerCase())) {\n theme.WALKABLE_COLOR = WALKING_PATH_COLOR;\n }\n theme.STORE_RADIUS = clampStoreRadius(theme.STORE_RADIUS);\n return theme;\n}\n\nexport interface CmMap {\n id: number;\n centerId: number;\n baseSvgKey: string | null;\n baseViewbox: ViewBox | null;\n unitsPerMeter: number;\n theme: Partial<ThemeDefaults>;\n /** Current production document row in cm_revisions (overwritten in place). */\n publishedRevisionId: number | null;\n draftUpdatedAt: string | null;\n createdAt: string;\n}\n\nexport interface CmBuilding {\n id: number;\n mapId: number;\n name: string;\n ordering: number;\n}\n\nexport interface CmLevel {\n id: number;\n mapId: number;\n buildingId: number | null;\n kind: LevelKind;\n name: string;\n levelIndex: number;\n ordering: number;\n sourceSvgKey: string | null;\n /** Resolved CDN URL for editor preview (not persisted). */\n sourceSvgUrl?: string | null;\n sourceViewbox: ViewBox | null;\n transform: LevelTransform;\n isActive: boolean;\n}\n\nexport interface CmShape {\n id: number;\n levelId: number;\n key: string;\n kind: ShapeKind;\n geometry: ShapeGeometry;\n bbox: BBox;\n zIndex: number;\n style: ShapeStyle;\n label: ShapeLabel;\n sourceSvgId: string | null;\n origin: ShapeOrigin;\n /** When true, outdoor re-import never overwrites geometry/bbox. */\n geometryLocked?: boolean;\n /** Set when sourceSvgId disappeared from a re-upload; filtered from public docs. */\n orphanedAt?: string | null;\n}\n\nexport interface CmShapeAssignment {\n shapeId: number;\n targetType: AssignmentTargetType;\n retailerId: number | null;\n amenityId: number | null;\n kioskId: number | null;\n unitStatus: UnitStatus;\n unitNumber: string | null;\n customLabel: string | null;\n customImageKey: string | null;\n}\n\nexport interface CmAnchor {\n id: number;\n levelId: number;\n shapeId: number | null;\n kind: AnchorKind;\n x: number;\n y: number;\n connectorId: number | null;\n}\n\nexport interface CmRouteEdge {\n id: number;\n mapId: number;\n fromAnchorId: number;\n toAnchorId: number;\n weight: number | null;\n directed: boolean;\n accessible: boolean;\n kind: EdgeKind;\n}\n\nexport interface CmConnector {\n id: number;\n mapId: number;\n kind: ConnectorKind;\n name: string;\n direction: ConnectorDirection;\n accessible: boolean;\n}\n\nexport interface CmAmenityCatalogItem {\n id: number;\n centerId: number | null;\n code: string;\n name: string;\n iconKey: string | null;\n builtinIcon: string | null;\n ordering: number;\n isActive: boolean;\n}\n\nexport interface CmResponsiveOverride {\n id: number;\n mapId: number;\n levelId: number | null;\n device: DeviceType;\n camera: Vec3;\n controls: Vec3;\n}\n\nexport interface PublishedGraphNode {\n id: number;\n levelId: number;\n x: number;\n y: number;\n kind: AnchorKind;\n shapeId: number | null;\n connectorId: number | null;\n}\n\nexport interface PublishedGraphEdge {\n id: number;\n from: number;\n to: number;\n weight: number;\n directed: boolean;\n accessible: boolean;\n kind: EdgeKind;\n}\n\nexport interface PublishedLevel {\n id: number;\n buildingId: number | null;\n kind: LevelKind;\n name: string;\n levelIndex: number;\n ordering: number;\n sourceSvgUrl: string | null;\n viewbox: ViewBox | null;\n transform: LevelTransform;\n shapes: Array<CmShape & { assignment?: CmShapeAssignment | null }>;\n anchors: CmAnchor[];\n}\n\nexport interface PublishedDocument {\n version: 2;\n revisionId: number;\n revisionNumber: number;\n centerId: number;\n mapId: number;\n theme: ThemeDefaults;\n baseSvgUrl: string | null;\n baseViewbox: ViewBox | null;\n buildings: CmBuilding[];\n levels: PublishedLevel[];\n connectors: CmConnector[];\n amenities: CmAmenityCatalogItem[];\n graph: {\n nodes: PublishedGraphNode[];\n edges: PublishedGraphEdge[];\n };\n responsiveOverrides: CmResponsiveOverride[];\n publishedAt: string;\n}\n\nexport interface ImportClassification {\n sourceSvgId: string;\n kind: ShapeKind | null;\n guessed: boolean;\n message?: string;\n}\n\nexport interface ImportReport {\n classified: ImportClassification[];\n unrecognized: string[];\n guessed: ImportClassification[];\n walkableCount: number;\n voidCount: number;\n unitCount: number;\n warnings: string[];\n}\n\nexport type DiffChangeType = 'added' | 'removed' | 'moved' | 'unchanged' | 'kind_changed';\n\nexport interface ImportDiffItem {\n sourceSvgId: string;\n change: DiffChangeType;\n existingShapeId?: number;\n newKind?: ShapeKind | null;\n existingKind?: ShapeKind | null;\n preserve?: {\n key?: string;\n assignment?: boolean;\n anchors?: boolean;\n };\n /** True when portal Edit Map owns this shape's geometry. */\n geometryLocked?: boolean;\n}\n\nexport interface ImportDiff {\n items: ImportDiffItem[];\n shapes: Array<{\n key: string;\n kind: ShapeKind;\n geometry: ShapeGeometry;\n bbox: BBox;\n sourceSvgId: string;\n style: ShapeStyle;\n }>;\n viewbox: ViewBox | null;\n}\n\nexport interface WeldResult {\n survivingAnchorId: number;\n removedAnchorIds: number[];\n rewiredEdgeIds: number[];\n}\n\nexport interface AutoConnectResult {\n unitAnchorId: number;\n junctionAnchor: { x: number; y: number; existingId?: number };\n edge: { fromAnchorId: number; toAnchorId?: number };\n}\n\nexport interface SkeletonSuggestion {\n anchors: Array<{ tempId: string; x: number; y: number; kind: AnchorKind }>;\n edges: Array<{ fromTempId: string; toTempId: string }>;\n}\n\nexport interface PathResult {\n anchorIds: number[];\n points: Array<Vec2 & { levelId: number }>;\n totalWeight: number;\n levelChanges: Array<{ fromLevelId: number; toLevelId: number; connectorId: number | null }>;\n}\n\nexport type BatchOp =\n | { op: 'upsert_shape'; shape: Partial<CmShape> & { levelId: number; key: string } }\n | { op: 'delete_shape'; shapeId: number }\n | { op: 'upsert_assignment'; assignment: CmShapeAssignment }\n | { op: 'delete_assignment'; shapeId: number }\n | { op: 'upsert_anchor'; anchor: Partial<CmAnchor> & { levelId: number; x: number; y: number; kind: AnchorKind } }\n | { op: 'delete_anchor'; anchorId: number }\n | { op: 'upsert_edge'; edge: Partial<CmRouteEdge> & { mapId: number; fromAnchorId: number; toAnchorId: number } }\n | { op: 'delete_edge'; edgeId: number }\n | { op: 'weld_anchors'; anchorIds: number[]; tolerance?: number }\n | { op: 'upsert_level'; level: Partial<CmLevel> & { mapId: number; name: string; kind: LevelKind } }\n | { op: 'delete_level'; levelId: number }\n | { op: 'upsert_building'; building: Partial<CmBuilding> & { mapId: number; name: string } }\n | { op: 'delete_building'; buildingId: number }\n | { op: 'update_theme'; theme: Partial<ThemeDefaults> }\n | { op: 'upsert_connector'; connector: Partial<CmConnector> & { mapId: number; kind: ConnectorKind; name: string } }\n | { op: 'delete_connector'; connectorId: number };\n\nexport const INTERACTIVE_SHAPE_KINDS: ShapeKind[] = [\n 'unit',\n 'amenity',\n 'kiosk_screen',\n 'connector',\n 'entrance',\n 'parking_zone',\n];\n\nexport const FLOOR_CHANGE_PENALTY = 10000;\n\nexport const DEFAULT_WELD_TOLERANCE = 2.5;\n","import type { MapHost, MapViewerHost } from './types';\n\n/** Which library surface a host should mount. `PORTAL` is the staff editor. */\nexport function mapSurface(host: MapHost): 'editor' | 'viewer' {\n return host === 'PORTAL' ? 'editor' : 'viewer';\n}\n\n/**\n * Public chrome. Mirrors v1 MapBox (`UIComponent` + `SceneComponent`):\n * floors + zoom/reset on every viewer host; amenity icons on WEBSITE\n * (v1 hides them for PORTAL and DISPLAY_APP); kiosk origin only on DISPLAY_APP.\n * Search is v2-owned (v1 MapBox has none) and follows the public directory hosts.\n */\nexport interface ViewerChrome {\n search: boolean;\n amenities: boolean;\n floors: boolean;\n zoomReset: boolean;\n kioskOrigin: boolean;\n fetchDraft: boolean;\n}\n\nconst PUBLIC_CHROME: ViewerChrome = {\n search: true,\n amenities: true,\n floors: true,\n zoomReset: true,\n kioskOrigin: false,\n fetchDraft: false,\n};\n\nconst VIEWER_CHROME: Record<MapViewerHost, ViewerChrome> = {\n WEBSITE: PUBLIC_CHROME,\n /** Assign mode: click shapes, no public directory chrome. */\n PORTAL_ASSIGN: {\n search: false,\n amenities: false,\n floors: true,\n zoomReset: true,\n kioskOrigin: false,\n fetchDraft: false,\n },\n DISPLAY_APP: {\n search: false,\n amenities: false,\n floors: true,\n zoomReset: true,\n kioskOrigin: true,\n fetchDraft: false,\n },\n};\n\nexport function viewerChrome(host: MapViewerHost): ViewerChrome {\n return VIEWER_CHROME[host];\n}\n\nexport function isMapViewerHost(host: MapHost): host is MapViewerHost {\n return host !== 'PORTAL';\n}\n","/** Same contract as v1 `getMediaProxyUrl`: proxy base + encoded URL, no query key. */\nexport function resolveFetchUrl(url: string, imageProxyUrl?: string | null): string {\n if (!imageProxyUrl) return url;\n return imageProxyUrl + encodeURIComponent(url);\n}\n","import type { BBox, PathSubpath, ShapeGeometry, Vec2, ViewBox } from '../types';\n\n/**\n * Mirror points about the middle of a viewbox height.\n *\n * Never call this on stored geometry. Stored geometry keeps SVG user space\n * (Y down) so `paths`, `polygons`, anchors and the designer SVG all agree;\n * the viewer flips once at render. This helper exists only for render-side\n * and ad-hoc conversions.\n */\nexport function flipY(points: Vec2[], viewboxHeight: number): Vec2[] {\n return points.map((p) => ({ x: p.x, y: viewboxHeight - p.y }));\n}\n\nexport function distance(a: Vec2, b: Vec2): number {\n const dx = a.x - b.x;\n const dy = a.y - b.y;\n return Math.hypot(dx, dy);\n}\n\nexport function bboxOf(points: Vec2[]): BBox {\n if (points.length === 0) {\n return { minX: 0, minY: 0, maxX: 0, maxY: 0 };\n }\n let minX = points[0].x;\n let minY = points[0].y;\n let maxX = points[0].x;\n let maxY = points[0].y;\n for (let i = 1; i < points.length; i++) {\n const p = points[i];\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n return { minX, minY, maxX, maxY };\n}\n\nexport function bboxUnion(a: BBox, b: BBox): BBox {\n return {\n minX: Math.min(a.minX, b.minX),\n minY: Math.min(a.minY, b.minY),\n maxX: Math.max(a.maxX, b.maxX),\n maxY: Math.max(a.maxY, b.maxY),\n };\n}\n\nexport function centroid(points: Vec2[]): Vec2 {\n if (points.length === 0) return { x: 0, y: 0 };\n let sx = 0;\n let sy = 0;\n for (const p of points) {\n sx += p.x;\n sy += p.y;\n }\n return { x: sx / points.length, y: sy / points.length };\n}\n\nexport function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean {\n let inside = false;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i].x;\n const yi = polygon[i].y;\n const xj = polygon[j].x;\n const yj = polygon[j].y;\n const intersect =\n yi > point.y !== yj > point.y &&\n point.x < ((xj - xi) * (point.y - yi)) / (yj - yi + Number.EPSILON) + xi;\n if (intersect) inside = !inside;\n }\n return inside;\n}\n\nexport function pointInPolygons(point: Vec2, polygons: Vec2[][]): boolean {\n return polygons.some((poly) => pointInPolygon(point, poly));\n}\n\n/** Project point onto segment; returns closest point and t in [0,1]. */\nexport function projectOntoSegment(\n point: Vec2,\n a: Vec2,\n b: Vec2,\n): { point: Vec2; t: number; distance: number } {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const lenSq = dx * dx + dy * dy;\n if (lenSq === 0) {\n return { point: { ...a }, t: 0, distance: distance(point, a) };\n }\n let t = ((point.x - a.x) * dx + (point.y - a.y) * dy) / lenSq;\n t = Math.max(0, Math.min(1, t));\n const proj = { x: a.x + t * dx, y: a.y + t * dy };\n return { point: proj, t, distance: distance(point, proj) };\n}\n\nexport function nearestPointOnPolyline(\n point: Vec2,\n polyline: Vec2[],\n): { point: Vec2; segmentIndex: number; distance: number } | null {\n if (polyline.length < 2) return null;\n let best: { point: Vec2; segmentIndex: number; distance: number } | null = null;\n for (let i = 0; i < polyline.length - 1; i++) {\n const proj = projectOntoSegment(point, polyline[i], polyline[i + 1]);\n if (!best || proj.distance < best.distance) {\n best = { point: proj.point, segmentIndex: i, distance: proj.distance };\n }\n }\n return best;\n}\n\n/**\n * Approximate a cubic bezier into line segments.\n */\nexport function approximateCubic(\n p0: Vec2,\n p1: Vec2,\n p2: Vec2,\n p3: Vec2,\n segments = 8,\n): Vec2[] {\n const out: Vec2[] = [];\n for (let i = 0; i <= segments; i++) {\n const t = i / segments;\n const u = 1 - t;\n out.push({\n x:\n u * u * u * p0.x +\n 3 * u * u * t * p1.x +\n 3 * u * t * t * p2.x +\n t * t * t * p3.x,\n y:\n u * u * u * p0.y +\n 3 * u * u * t * p1.y +\n 3 * u * t * t * p2.y +\n t * t * t * p3.y,\n });\n }\n return out;\n}\n\nexport function approximateQuadratic(\n p0: Vec2,\n p1: Vec2,\n p2: Vec2,\n segments = 6,\n): Vec2[] {\n const out: Vec2[] = [];\n for (let i = 0; i <= segments; i++) {\n const t = i / segments;\n const u = 1 - t;\n out.push({\n x: u * u * p0.x + 2 * u * t * p1.x + t * t * p2.x,\n y: u * u * p0.y + 2 * u * t * p1.y + t * t * p2.y,\n });\n }\n return out;\n}\n\n/**\n * A quarter turn is about the largest sweep a single cubic approximates well,\n * so an arc gets `approximateCubic`'s 8 segments per 90° of sweep. An arc and a\n * visually equivalent cubic therefore flatten to comparable point counts.\n */\nconst ARC_SEGMENTS_PER_QUADRANT = 8;\n\n/**\n * Flatten an SVG elliptical arc, using the endpoint-to-centre parameterisation\n * of SVG 1.1 appendix F.6.\n *\n * Returns `p0` first, like `approximateCubic`, so callers append `slice(1)`.\n */\nexport function approximateArc(\n p0: Vec2,\n rx: number,\n ry: number,\n xAxisRotationDeg: number,\n largeArc: boolean,\n sweep: boolean,\n p1: Vec2,\n): Vec2[] {\n // F.6.2: coincident endpoints drop the arc; a zero radius becomes a line.\n if (p0.x === p1.x && p0.y === p1.y) return [{ ...p0 }];\n let arx = Math.abs(rx);\n let ary = Math.abs(ry);\n if (arx === 0 || ary === 0 || !Number.isFinite(arx) || !Number.isFinite(ary)) {\n return [{ ...p0 }, { ...p1 }];\n }\n\n const phi = ((xAxisRotationDeg % 360) * Math.PI) / 180;\n const cosPhi = Math.cos(phi);\n const sinPhi = Math.sin(phi);\n\n // F.6.5.1 — half the chord, rotated into the ellipse's own frame.\n const dx2 = (p0.x - p1.x) / 2;\n const dy2 = (p0.y - p1.y) / 2;\n const x1p = cosPhi * dx2 + sinPhi * dy2;\n const y1p = -sinPhi * dx2 + cosPhi * dy2;\n\n // F.6.6.2 — radii too small to span the endpoints are scaled by sqrt(Λ).\n const lambda = (x1p * x1p) / (arx * arx) + (y1p * y1p) / (ary * ary);\n if (lambda > 1) {\n const scale = Math.sqrt(lambda);\n arx *= scale;\n ary *= scale;\n }\n\n // F.6.5.2 — centre in the ellipse frame.\n const rxSq = arx * arx;\n const rySq = ary * ary;\n const numerator = rxSq * rySq - rxSq * y1p * y1p - rySq * x1p * x1p;\n const denominator = rxSq * y1p * y1p + rySq * x1p * x1p;\n const factor =\n Math.sqrt(Math.max(0, numerator / denominator)) * (largeArc === sweep ? -1 : 1);\n const cxp = (factor * arx * y1p) / ary;\n const cyp = (-factor * ary * x1p) / arx;\n\n // F.6.5.3 — centre back in user space.\n const cx = cosPhi * cxp - sinPhi * cyp + (p0.x + p1.x) / 2;\n const cy = sinPhi * cxp + cosPhi * cyp + (p0.y + p1.y) / 2;\n\n // F.6.5.5 / F.6.5.6 — start angle and swept angle.\n const ux = (x1p - cxp) / arx;\n const uy = (y1p - cyp) / ary;\n const vx = (-x1p - cxp) / arx;\n const vy = (-y1p - cyp) / ary;\n const theta1 = Math.atan2(uy, ux);\n let deltaTheta = Math.atan2(ux * vy - uy * vx, ux * vx + uy * vy);\n if (!sweep && deltaTheta > 0) deltaTheta -= 2 * Math.PI;\n else if (sweep && deltaTheta < 0) deltaTheta += 2 * Math.PI;\n\n // Round rather than ceil the quadrant count. A chord that is almost exactly\n // the ellipse diameter is a near-degenerate half turn, so tiny coordinate\n // noise — a rewritten `d` rounded by the transform baker, say — swings the\n // sweep either side of pi. Rounding is stable at whole quadrants, which is\n // precisely where those degeneracies sit; ceil would flip a segment count\n // there and desynchronise `paths[].d` from `polygons`.\n const ideal = (Math.abs(deltaTheta) / (Math.PI / 2)) * ARC_SEGMENTS_PER_QUADRANT;\n const segments = Math.max(1, Math.round(ideal));\n\n const out: Vec2[] = [{ ...p0 }];\n for (let i = 1; i <= segments; i++) {\n const theta = theta1 + (deltaTheta * i) / segments;\n const cosT = Math.cos(theta);\n const sinT = Math.sin(theta);\n out.push({\n x: cx + arx * cosPhi * cosT - ary * sinPhi * sinT,\n y: cy + arx * sinPhi * cosT + ary * cosPhi * sinT,\n });\n }\n // Trig round-off must not leave a gap before the next command.\n out[out.length - 1] = { ...p1 };\n return out;\n}\n\nconst WHITESPACE_RE = /[\\s,]/;\n\n/**\n * Split path data into command letters and numbers.\n *\n * A plain number regex cannot do this: arc flags may be written without any\n * separator, so `a1 1 0 011 1` is legal and means flags `0` then `1` followed\n * by the coordinate `1`. Tracking the argument slot lets the two flag\n * positions of every `A`/`a` group consume exactly one character.\n */\nexport function tokenizePathData(d: string): string[] {\n const tokens: string[] = [];\n let i = 0;\n let cmd = '';\n let argIndex = 0;\n\n while (i < d.length) {\n const ch = d[i];\n if (WHITESPACE_RE.test(ch)) {\n i++;\n continue;\n }\n if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {\n cmd = ch;\n argIndex = 0;\n tokens.push(ch);\n i++;\n continue;\n }\n\n // Slots 3 and 4 of each 7-argument arc group are single-character flags.\n const arcSlot = cmd === 'A' || cmd === 'a' ? argIndex % 7 : -1;\n if ((arcSlot === 3 || arcSlot === 4) && (ch === '0' || ch === '1')) {\n tokens.push(ch);\n i++;\n argIndex++;\n continue;\n }\n\n const start = i;\n let digits = 0;\n if (ch === '+' || ch === '-') i++;\n while (i < d.length && d[i] >= '0' && d[i] <= '9') {\n i++;\n digits++;\n }\n if (d[i] === '.') {\n i++;\n while (i < d.length && d[i] >= '0' && d[i] <= '9') {\n i++;\n digits++;\n }\n }\n if (digits > 0 && (d[i] === 'e' || d[i] === 'E')) {\n const beforeExponent = i;\n i++;\n if (d[i] === '+' || d[i] === '-') i++;\n if (i < d.length && d[i] >= '0' && d[i] <= '9') {\n while (i < d.length && d[i] >= '0' && d[i] <= '9') i++;\n } else {\n i = beforeExponent;\n }\n }\n if (digits === 0) {\n // Not a number at all — step over it rather than looping forever.\n i = start + 1;\n continue;\n }\n tokens.push(d.slice(start, i));\n argIndex++;\n }\n\n return tokens;\n}\n\n/**\n * Parse SVG path `d` into absolute polygon approximations.\n * Supports M/L/H/V/C/Q/S/T/A/Z (absolute and relative).\n *\n * Output stays in the input's coordinate space — deliberately no Y flip, so\n * `paths[].d`, `polygons`, anchors and route geometry never diverge. The\n * viewer applies the single flip at render time.\n */\nexport function pathToPolygons(d: string): Vec2[][] {\n const tokens = tokenizePathData(d);\n const polygons: Vec2[][] = [];\n let current: Vec2[] = [];\n let x = 0;\n let y = 0;\n let startX = 0;\n let startY = 0;\n let lastCtrl: Vec2 | null = null;\n let i = 0;\n let cmd = '';\n\n const readNum = () => Number(tokens[i++]);\n\n while (i < tokens.length) {\n const t = tokens[i];\n if (/[a-zA-Z]/.test(t)) {\n cmd = t;\n i++;\n }\n\n switch (cmd) {\n case 'M':\n case 'm': {\n const isRel = cmd === 'm';\n const nx = readNum();\n const ny = readNum();\n x = isRel ? x + nx : nx;\n y = isRel ? y + ny : ny;\n if (current.length > 0) polygons.push(current);\n current = [{ x, y }];\n startX = x;\n startY = y;\n lastCtrl = null;\n cmd = isRel ? 'l' : 'L';\n break;\n }\n case 'L':\n case 'l': {\n const isRel = cmd === 'l';\n const nx = readNum();\n const ny = readNum();\n x = isRel ? x + nx : nx;\n y = isRel ? y + ny : ny;\n current.push({ x, y });\n lastCtrl = null;\n break;\n }\n case 'H':\n case 'h': {\n const isRel = cmd === 'h';\n const nx = readNum();\n x = isRel ? x + nx : nx;\n current.push({ x, y });\n lastCtrl = null;\n break;\n }\n case 'V':\n case 'v': {\n const isRel = cmd === 'v';\n const ny = readNum();\n y = isRel ? y + ny : ny;\n current.push({ x, y });\n lastCtrl = null;\n break;\n }\n case 'C':\n case 'c': {\n const isRel = cmd === 'c';\n const x1 = isRel ? x + readNum() : readNum();\n const y1 = isRel ? y + readNum() : readNum();\n const x2 = isRel ? x + readNum() : readNum();\n const y2 = isRel ? y + readNum() : readNum();\n const nx = isRel ? x + readNum() : readNum();\n const ny = isRel ? y + readNum() : readNum();\n const approx = approximateCubic(\n { x, y },\n { x: x1, y: y1 },\n { x: x2, y: y2 },\n { x: nx, y: ny },\n );\n current.push(...approx.slice(1));\n lastCtrl = { x: x2, y: y2 };\n x = nx;\n y = ny;\n break;\n }\n case 'Q':\n case 'q': {\n const isRel = cmd === 'q';\n const x1 = isRel ? x + readNum() : readNum();\n const y1 = isRel ? y + readNum() : readNum();\n const nx = isRel ? x + readNum() : readNum();\n const ny = isRel ? y + readNum() : readNum();\n const approx = approximateQuadratic(\n { x, y },\n { x: x1, y: y1 },\n { x: nx, y: ny },\n );\n current.push(...approx.slice(1));\n lastCtrl = { x: x1, y: y1 };\n x = nx;\n y = ny;\n break;\n }\n case 'S':\n case 's': {\n const isRel = cmd === 's';\n const cx: number = lastCtrl ? 2 * x - lastCtrl.x : x;\n const cy: number = lastCtrl ? 2 * y - lastCtrl.y : y;\n const x2 = isRel ? x + readNum() : readNum();\n const y2 = isRel ? y + readNum() : readNum();\n const nx = isRel ? x + readNum() : readNum();\n const ny = isRel ? y + readNum() : readNum();\n const approx = approximateCubic(\n { x, y },\n { x: cx, y: cy },\n { x: x2, y: y2 },\n { x: nx, y: ny },\n );\n current.push(...approx.slice(1));\n lastCtrl = { x: x2, y: y2 };\n x = nx;\n y = ny;\n break;\n }\n case 'T':\n case 't': {\n const isRel = cmd === 't';\n const cx: number = lastCtrl ? 2 * x - lastCtrl.x : x;\n const cy: number = lastCtrl ? 2 * y - lastCtrl.y : y;\n const nx = isRel ? x + readNum() : readNum();\n const ny = isRel ? y + readNum() : readNum();\n const approx = approximateQuadratic(\n { x, y },\n { x: cx, y: cy },\n { x: nx, y: ny },\n );\n current.push(...approx.slice(1));\n lastCtrl = { x: cx, y: cy };\n x = nx;\n y = ny;\n break;\n }\n case 'A':\n case 'a': {\n const isRel = cmd === 'a';\n const rx = readNum();\n const ry = readNum();\n const rot = readNum();\n const largeArc = readNum() !== 0;\n const sweep = readNum() !== 0;\n const nx = isRel ? x + readNum() : readNum();\n const ny = isRel ? y + readNum() : readNum();\n const approx = approximateArc(\n { x, y },\n rx,\n ry,\n rot,\n largeArc,\n sweep,\n { x: nx, y: ny },\n );\n current.push(...approx.slice(1));\n lastCtrl = null;\n x = nx;\n y = ny;\n break;\n }\n case 'Z':\n case 'z': {\n current.push({ x: startX, y: startY });\n polygons.push(current);\n current = [];\n x = startX;\n y = startY;\n lastCtrl = null;\n break;\n }\n default:\n // Unknown command — skip one token to avoid infinite loop\n i++;\n break;\n }\n }\n\n if (current.length > 0) polygons.push(current);\n\n return polygons;\n}\n\n/** First absolute `M` of a path, or null when the path does not start with one. */\nfunction firstMoveTo(d: string): Vec2 | null {\n const m = d.match(\n /^\\s*M\\s*(-?\\d*\\.?\\d+(?:e[-+]?\\d+)?)[\\s,]+(-?\\d*\\.?\\d+(?:e[-+]?\\d+)?)/i,\n );\n if (!m) return null;\n const x = Number(m[1]);\n const y = Number(m[2]);\n return Number.isFinite(x) && Number.isFinite(y) ? { x, y } : null;\n}\n\n/**\n * Rows written before the Y-flip removal hold `polygons` mirrored about the\n * viewbox while `paths[].d` stayed in SVG space, which renders the map upside\n * down. `paths` is authoritative, so rebuild `polygons` whenever the two\n * disagree. Comparing only the opening `M` keeps healthy geometry O(1).\n */\nexport function isGeometrySpaceStale(geometry: ShapeGeometry): boolean {\n const d = geometry.paths[0]?.d;\n if (!d) return false;\n if (geometry.polygons.length === 0) return false;\n const start = firstMoveTo(d);\n const first = geometry.polygons[0]?.[0];\n if (!start || !first) return false;\n return Math.abs(start.x - first.x) > 0.01 || Math.abs(start.y - first.y) > 0.01;\n}\n\n/** Return geometry with `polygons` rebuilt from `paths` when they disagree. */\nexport function normalizeGeometrySpace(geometry: ShapeGeometry): ShapeGeometry {\n if (!isGeometrySpaceStale(geometry)) return geometry;\n const polygons = geometry.paths.flatMap((p) => pathToPolygons(p.d));\n if (polygons.length === 0) return geometry;\n return { paths: geometry.paths, polygons };\n}\n\n/** `paths` keeps the original `d`; `polygons` must stay in the same space. */\nexport function buildGeometryFromPaths(pathDs: string[]): ShapeGeometry {\n const paths: PathSubpath[] = pathDs.map((d) => ({\n d,\n closed: /z/i.test(d),\n }));\n const polygons = pathDs.flatMap((d) => pathToPolygons(d));\n return { paths, polygons };\n}\n\nexport function geometryBBox(geometry: ShapeGeometry): BBox {\n const all = geometry.polygons.flat();\n return bboxOf(all);\n}\n\nexport function geometryCentroid(geometry: ShapeGeometry): Vec2 {\n return centroid(geometry.polygons.flat());\n}\n\n/**\n * Snap a delta angle to the nearest increment around a base angle.\n * baseDeg is the working orientation (e.g. from \"match this wall\").\n */\nexport function snapAngle(\n from: Vec2,\n to: Vec2,\n baseDeg = 0,\n increments: number[] = [15, 45, 90],\n): Vec2 {\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const len = Math.hypot(dx, dy);\n if (len === 0) return { ...to };\n\n const rawDeg = (Math.atan2(dy, dx) * 180) / Math.PI;\n const relative = rawDeg - baseDeg;\n let best = relative;\n let bestDiff = Infinity;\n for (const step of increments) {\n const snapped = Math.round(relative / step) * step;\n const diff = Math.abs(relative - snapped);\n if (diff < bestDiff) {\n bestDiff = diff;\n best = snapped;\n }\n }\n const finalDeg = ((best + baseDeg) * Math.PI) / 180;\n return {\n x: from.x + Math.cos(finalDeg) * len,\n y: from.y + Math.sin(finalDeg) * len,\n };\n}\n\n/** Derive working base angle from two wall points (degrees). */\nexport function angleFromWall(a: Vec2, b: Vec2): number {\n return (Math.atan2(b.y - a.y, b.x - a.x) * 180) / Math.PI;\n}\n\nexport function parseViewBox(raw: string | null | undefined): ViewBox | null {\n if (!raw) return null;\n const parts = raw.trim().split(/[\\s,]+/).map(Number);\n if (parts.length !== 4 || parts.some((n) => Number.isNaN(n))) return null;\n return { x: parts[0], y: parts[1], width: parts[2], height: parts[3] };\n}\n","/**\n * Inline CSS class rules from `<style>` tags as SVG presentation attributes.\n * Works in Node (no DOM) so the SVG importer can resolve fills/strokes.\n * Mirrors v1 `inlineSvgStyles` behaviour for class→attribute mapping.\n */\n\nconst CSS_TO_SVG_ATTR: Record<string, string> = {\n fill: 'fill',\n 'fill-opacity': 'fill-opacity',\n stroke: 'stroke',\n 'stroke-width': 'stroke-width',\n 'stroke-opacity': 'stroke-opacity',\n opacity: 'opacity',\n};\n\nfunction parseCssDeclarations(block: string): Record<string, string> {\n const declarations: Record<string, string> = {};\n for (const declaration of block.split(';')) {\n const sep = declaration.indexOf(':');\n if (sep === -1) continue;\n const property = declaration.slice(0, sep).trim().toLowerCase();\n const value = declaration.slice(sep + 1).trim();\n if (property && value) declarations[property] = value;\n }\n return declarations;\n}\n\nfunction parseCssClassRules(cssText: string): Map<string, Record<string, string>> {\n const classStyles = new Map<string, Record<string, string>>();\n const normalizedCss = cssText.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n for (const match of normalizedCss.matchAll(/([^{]+)\\{([^}]*)\\}/g)) {\n const selectors = match[1].split(',').map((s) => s.trim());\n const declarations = parseCssDeclarations(match[2]);\n for (const selector of selectors) {\n const classMatch = selector.match(/^\\.([a-zA-Z0-9_-]+)$/);\n if (!classMatch) continue;\n const className = classMatch[1];\n classStyles.set(className, {\n ...(classStyles.get(className) || {}),\n ...declarations,\n });\n }\n }\n return classStyles;\n}\n\nfunction mergeClassStyles(\n classAttr: string,\n classStyles: Map<string, Record<string, string>>,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const name of classAttr.split(/\\s+/).map((c) => c.trim()).filter(Boolean)) {\n Object.assign(merged, classStyles.get(name) || {});\n }\n return merged;\n}\n\n/**\n * Rewrite SVG text so class-based fills/strokes become presentation attributes.\n * Safe to call in Node — pure string rewrite, no DOMParser.\n */\nexport function inlineSvgStyles(svgText: string): string {\n const styleBlocks: string[] = [];\n const withoutComments = svgText.replace(/<!--[\\s\\S]*?-->/g, '');\n for (const m of withoutComments.matchAll(/<style\\b[^>]*>([\\s\\S]*?)<\\/style>/gi)) {\n styleBlocks.push(m[1]);\n }\n if (styleBlocks.length === 0) return svgText;\n\n const classStyles = new Map<string, Record<string, string>>();\n for (const block of styleBlocks) {\n for (const [name, decls] of parseCssClassRules(block)) {\n classStyles.set(name, { ...(classStyles.get(name) || {}), ...decls });\n }\n }\n if (classStyles.size === 0) return svgText;\n\n return svgText.replace(\n /<(path|polygon|polyline|line|rect|g|circle|ellipse)\\b([^>]*)>/gi,\n (full, tag: string, attrs: string) => {\n // `[^>]*` swallows the `/` in `/>`, so strip it before rewriting attrs.\n const selfClosing = /\\/\\s*$/.test(attrs);\n const cleanAttrs = attrs.replace(/\\/\\s*$/, '');\n const classMatch = cleanAttrs.match(/\\bclass\\s*=\\s*[\"']([^\"']*)[\"']/i);\n if (!classMatch) return full;\n const merged = mergeClassStyles(classMatch[1], classStyles);\n let nextAttrs = cleanAttrs;\n for (const [cssProp, value] of Object.entries(merged)) {\n const svgAttr = CSS_TO_SVG_ATTR[cssProp];\n if (!svgAttr) continue;\n if (new RegExp(`\\\\b${svgAttr}\\\\s*=`, 'i').test(nextAttrs)) continue;\n nextAttrs += ` ${svgAttr}=\"${value}\"`;\n }\n return `<${tag}${nextAttrs}${selfClosing ? ' /' : ''}>`;\n },\n );\n}\n\nexport interface SvgPresentationStyle {\n fill?: string;\n stroke?: string;\n strokeWidth?: number;\n opacity?: number;\n}\n\n/** Read presentation attributes from an attribute string. */\nexport function readPresentationStyle(attrs: string): SvgPresentationStyle {\n const out: SvgPresentationStyle = {};\n const fill = attrs.match(/\\bfill\\s*=\\s*[\"']([^\"']*)[\"']/i)?.[1];\n const stroke = attrs.match(/\\bstroke\\s*=\\s*[\"']([^\"']*)[\"']/i)?.[1];\n const strokeWidth = attrs.match(/\\bstroke-width\\s*=\\s*[\"']?(-?[\\d.]+)/i)?.[1];\n const opacity = attrs.match(/\\bopacity\\s*=\\s*[\"']?(-?[\\d.]+)/i)?.[1];\n const fillOpacity = attrs.match(/\\bfill-opacity\\s*=\\s*[\"']?(-?[\\d.]+)/i)?.[1];\n if (fill && fill.toLowerCase() !== 'none') out.fill = fill;\n if (stroke && stroke.toLowerCase() !== 'none') out.stroke = stroke;\n if (strokeWidth != null && !Number.isNaN(Number(strokeWidth))) {\n out.strokeWidth = Number(strokeWidth);\n }\n if (opacity != null && !Number.isNaN(Number(opacity))) {\n out.opacity = Number(opacity);\n } else if (fillOpacity != null && !Number.isNaN(Number(fillOpacity))) {\n out.opacity = Number(fillOpacity);\n }\n return out;\n}\n\n/** Merge child over parent — child wins when set. */\nexport function mergePresentationStyle(\n parent: SvgPresentationStyle,\n child: SvgPresentationStyle,\n): SvgPresentationStyle {\n return {\n fill: child.fill ?? parent.fill,\n stroke: child.stroke ?? parent.stroke,\n strokeWidth: child.strokeWidth ?? parent.strokeWidth,\n opacity: child.opacity ?? parent.opacity,\n };\n}\n","/**\n * SVG `transform` attribute support for the importer.\n *\n * Pure string/matrix math — no DOM, so it runs in Node during server-side\n * import. Geometry stays in raw SVG user space (Y down); these helpers only\n * bake `transform` attributes into coordinates, they never flip axes.\n */\n\nimport type { Vec2 } from '../types';\nimport { tokenizePathData } from '../geometry';\n\n/**\n * 2D affine matrix in SVG order:\n *\n * ```\n * | a c e |\n * | b d f |\n * | 0 0 1 |\n * ```\n */\nexport interface Matrix2D {\n a: number;\n b: number;\n c: number;\n d: number;\n e: number;\n f: number;\n}\n\nexport const IDENTITY_MATRIX: Matrix2D = { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };\n\n/**\n * Matrix product `outer × inner`: the returned matrix applies `inner` first,\n * then `outer`. SVG composes `transform=\"A B\"` the same way — the rightmost\n * transform is applied to the geometry first, and an ancestor `<g>` transform\n * is the outer one relative to its descendants.\n */\nexport function multiplyMatrix(outer: Matrix2D, inner: Matrix2D): Matrix2D {\n return {\n a: outer.a * inner.a + outer.c * inner.b,\n b: outer.b * inner.a + outer.d * inner.b,\n c: outer.a * inner.c + outer.c * inner.d,\n d: outer.b * inner.c + outer.d * inner.d,\n e: outer.a * inner.e + outer.c * inner.f + outer.e,\n f: outer.b * inner.e + outer.d * inner.f + outer.f,\n };\n}\n\nexport function applyMatrix(m: Matrix2D, p: Vec2): Vec2 {\n return {\n x: m.a * p.x + m.c * p.y + m.e,\n y: m.b * p.x + m.d * p.y + m.f,\n };\n}\n\nexport function isIdentityMatrix(m: Matrix2D, epsilon = 1e-9): boolean {\n return (\n Math.abs(m.a - 1) < epsilon &&\n Math.abs(m.b) < epsilon &&\n Math.abs(m.c) < epsilon &&\n Math.abs(m.d - 1) < epsilon &&\n Math.abs(m.e) < epsilon &&\n Math.abs(m.f) < epsilon\n );\n}\n\nfunction translateMatrix(tx: number, ty: number): Matrix2D {\n return { a: 1, b: 0, c: 0, d: 1, e: tx, f: ty };\n}\n\nfunction rotateMatrix(deg: number): Matrix2D {\n const rad = (deg * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n return { a: cos, b: sin, c: -sin, d: cos, e: 0, f: 0 };\n}\n\nfunction transformFunctionMatrix(name: string, args: number[]): Matrix2D | null {\n switch (name) {\n case 'matrix':\n if (args.length < 6) return null;\n return { a: args[0], b: args[1], c: args[2], d: args[3], e: args[4], f: args[5] };\n case 'translate':\n if (args.length < 1) return null;\n return translateMatrix(args[0], args[1] ?? 0);\n case 'scale': {\n if (args.length < 1) return null;\n const sx = args[0];\n const sy = args[1] ?? sx;\n return { a: sx, b: 0, c: 0, d: sy, e: 0, f: 0 };\n }\n case 'rotate': {\n if (args.length < 1) return null;\n const rot = rotateMatrix(args[0]);\n if (args.length < 3) return rot;\n const cx = args[1];\n const cy = args[2];\n return multiplyMatrix(\n multiplyMatrix(translateMatrix(cx, cy), rot),\n translateMatrix(-cx, -cy),\n );\n }\n case 'skewx':\n if (args.length < 1) return null;\n return { a: 1, b: 0, c: Math.tan((args[0] * Math.PI) / 180), d: 1, e: 0, f: 0 };\n case 'skewy':\n if (args.length < 1) return null;\n return { a: 1, b: Math.tan((args[0] * Math.PI) / 180), c: 0, d: 1, e: 0, f: 0 };\n default:\n return null;\n }\n}\n\nconst TRANSFORM_FN_RE = /([a-zA-Z]+)\\s*\\(([^)]*)\\)/g;\n\n/**\n * Parse an SVG `transform` attribute into a single affine matrix.\n * Unknown functions are skipped. Returns identity for empty / unparseable input.\n */\nexport function parseTransform(raw: string | null | undefined): Matrix2D {\n if (!raw) return IDENTITY_MATRIX;\n let result = IDENTITY_MATRIX;\n TRANSFORM_FN_RE.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = TRANSFORM_FN_RE.exec(raw)) !== null) {\n const name = match[1].toLowerCase();\n const args = match[2]\n .trim()\n .split(/[\\s,]+/)\n .filter(Boolean)\n .map(Number);\n if (args.some((n) => Number.isNaN(n))) continue;\n const next = transformFunctionMatrix(name, args);\n if (!next) continue;\n // Leftmost function is outermost: earlier entries apply last.\n result = multiplyMatrix(result, next);\n }\n return result;\n}\n\n/** Trim float noise so rewritten `d` strings stay readable and stable. */\nfunction fmt(n: number): string {\n if (!Number.isFinite(n)) return '0';\n const rounded = Math.round(n * 1e4) / 1e4;\n return Object.is(rounded, -0) ? '0' : String(rounded);\n}\n\n/**\n * Re-express an elliptical arc under an affine map.\n * The ellipse basis is `A · R(phi) · diag(rx, ry)`; its singular values are the\n * new radii and the left rotation is the new x-axis-rotation.\n */\nfunction transformArc(\n m: Matrix2D,\n rx: number,\n ry: number,\n phiDeg: number,\n): { rx: number; ry: number; phiDeg: number } {\n const phi = (phiDeg * Math.PI) / 180;\n const cos = Math.cos(phi);\n const sin = Math.sin(phi);\n // Ellipse basis in user space, then the matrix linear part.\n const e11 = cos * rx;\n const e21 = sin * rx;\n const e12 = -sin * ry;\n const e22 = cos * ry;\n const m11 = m.a * e11 + m.c * e21;\n const m21 = m.b * e11 + m.d * e21;\n const m12 = m.a * e12 + m.c * e22;\n const m22 = m.b * e12 + m.d * e22;\n // Closed-form 2x2 SVD.\n const E = (m11 + m22) / 2;\n const F = (m11 - m22) / 2;\n const G = (m21 + m12) / 2;\n const H = (m21 - m12) / 2;\n const q = Math.hypot(E, H);\n const r = Math.hypot(F, G);\n const outRx = Math.abs(q + r);\n const outRy = Math.abs(q - r);\n const a1 = Math.atan2(G, F);\n const a2 = Math.atan2(H, E);\n const outPhi = ((a2 + a1) / 2) * (180 / Math.PI);\n return { rx: outRx, ry: outRy, phiDeg: outPhi };\n}\n\n/**\n * Bake an affine matrix into a path `d` string, emitting absolute commands.\n *\n * Flattening a bezier commutes with an affine map (control points transform\n * independently, sampling parameters do not change), so\n * `pathToPolygons(transformPathD(d, m))` equals `pathToPolygons(d)` mapped\n * through `m`. That is what keeps `geometry.paths[].d` and `geometry.polygons`\n * in the same coordinate space.\n *\n * Arcs commute exactly under a similarity (translate / rotate / uniform scale /\n * mirror), which covers Illustrator output. A shear or non-uniform scale maps\n * the same curve but reparameterises it, so individual sample points may shift\n * along the outline even though the outline itself is right.\n */\nexport function transformPathD(d: string, m: Matrix2D): string {\n if (!d || isIdentityMatrix(m)) return d;\n const tokens = tokenizePathData(d);\n const out: string[] = [];\n const flipsOrientation = m.a * m.d - m.b * m.c < 0;\n\n let i = 0;\n let cmd = '';\n // Current point / subpath start in *source* space.\n let x = 0;\n let y = 0;\n let startX = 0;\n let startY = 0;\n\n const readNum = () => {\n const n = Number(tokens[i++]);\n return Number.isNaN(n) ? 0 : n;\n };\n const emit = (letter: string, ...coords: number[]) => {\n out.push(letter + (coords.length ? ' ' + coords.map(fmt).join(' ') : ''));\n };\n const point = (px: number, py: number): [number, number] => {\n const p = applyMatrix(m, { x: px, y: py });\n return [p.x, p.y];\n };\n\n while (i < tokens.length) {\n const t = tokens[i];\n if (/[a-zA-Z]/.test(t)) {\n cmd = t;\n i++;\n }\n\n switch (cmd) {\n case 'M':\n case 'm': {\n const rel = cmd === 'm';\n const nx = readNum();\n const ny = readNum();\n x = rel ? x + nx : nx;\n y = rel ? y + ny : ny;\n startX = x;\n startY = y;\n emit('M', ...point(x, y));\n cmd = rel ? 'l' : 'L';\n break;\n }\n case 'L':\n case 'l': {\n const rel = cmd === 'l';\n const nx = readNum();\n const ny = readNum();\n x = rel ? x + nx : nx;\n y = rel ? y + ny : ny;\n emit('L', ...point(x, y));\n break;\n }\n case 'H':\n case 'h': {\n const rel = cmd === 'h';\n const nx = readNum();\n x = rel ? x + nx : nx;\n // A rotation or skew makes a horizontal run non-horizontal.\n emit('L', ...point(x, y));\n break;\n }\n case 'V':\n case 'v': {\n const rel = cmd === 'v';\n const ny = readNum();\n y = rel ? y + ny : ny;\n emit('L', ...point(x, y));\n break;\n }\n case 'C':\n case 'c': {\n const rel = cmd === 'c';\n const x1 = rel ? x + readNum() : readNum();\n const y1 = rel ? y + readNum() : readNum();\n const x2 = rel ? x + readNum() : readNum();\n const y2 = rel ? y + readNum() : readNum();\n const nx = rel ? x + readNum() : readNum();\n const ny = rel ? y + readNum() : readNum();\n emit('C', ...point(x1, y1), ...point(x2, y2), ...point(nx, ny));\n x = nx;\n y = ny;\n break;\n }\n case 'S':\n case 's': {\n const rel = cmd === 's';\n const x2 = rel ? x + readNum() : readNum();\n const y2 = rel ? y + readNum() : readNum();\n const nx = rel ? x + readNum() : readNum();\n const ny = rel ? y + readNum() : readNum();\n // Reflection of the previous control point is affine-covariant.\n emit('S', ...point(x2, y2), ...point(nx, ny));\n x = nx;\n y = ny;\n break;\n }\n case 'Q':\n case 'q': {\n const rel = cmd === 'q';\n const x1 = rel ? x + readNum() : readNum();\n const y1 = rel ? y + readNum() : readNum();\n const nx = rel ? x + readNum() : readNum();\n const ny = rel ? y + readNum() : readNum();\n emit('Q', ...point(x1, y1), ...point(nx, ny));\n x = nx;\n y = ny;\n break;\n }\n case 'T':\n case 't': {\n const rel = cmd === 't';\n const nx = rel ? x + readNum() : readNum();\n const ny = rel ? y + readNum() : readNum();\n emit('T', ...point(nx, ny));\n x = nx;\n y = ny;\n break;\n }\n case 'A':\n case 'a': {\n const rel = cmd === 'a';\n const rx = readNum();\n const ry = readNum();\n const rot = readNum();\n const largeArc = readNum();\n const sweep = readNum();\n const nx = rel ? x + readNum() : readNum();\n const ny = rel ? y + readNum() : readNum();\n const arc = transformArc(m, rx, ry, rot);\n const [tx, ty] = point(nx, ny);\n out.push(\n `A ${fmt(arc.rx)} ${fmt(arc.ry)} ${fmt(arc.phiDeg)} ${largeArc ? 1 : 0} ` +\n `${(sweep ? 1 : 0) ^ (flipsOrientation ? 1 : 0)} ${fmt(tx)} ${fmt(ty)}`,\n );\n x = nx;\n y = ny;\n break;\n }\n case 'Z':\n case 'z': {\n out.push('Z');\n x = startX;\n y = startY;\n break;\n }\n default:\n // Unknown command — skip a token so we cannot loop forever.\n i++;\n break;\n }\n }\n\n return out.join(' ');\n}\n","import type {\n BBox,\n ImportClassification,\n ImportDiff,\n ImportDiffItem,\n ImportReport,\n ShapeGeometry,\n ShapeKind,\n ShapeStyle,\n ViewBox,\n} from '../types';\nimport { INTERACTIVE_SHAPE_KINDS } from '../types';\nimport {\n buildGeometryFromPaths,\n geometryBBox,\n geometryCentroid,\n parseViewBox,\n} from '../geometry';\nimport { resolveLayerStyle } from '../layerStyles';\nimport {\n inlineSvgStyles,\n mergePresentationStyle,\n readPresentationStyle,\n type SvgPresentationStyle,\n} from './svgStyle';\nimport {\n IDENTITY_MATRIX,\n multiplyMatrix,\n parseTransform,\n transformPathD,\n type Matrix2D,\n} from './svgTransform';\n\n/** Prefix → shape kind for floor SVGs. */\nconst FLOOR_PREFIXES: Array<{ prefix: string; kind: ShapeKind }> = [\n { prefix: 'walkable', kind: 'walkable' },\n { prefix: 'void', kind: 'void' },\n { prefix: 'unit', kind: 'unit' },\n { prefix: 'store', kind: 'unit' }, // v1 compatibility\n { prefix: 'wall', kind: 'wall' },\n { prefix: 'boundary', kind: 'boundary' },\n { prefix: 'outer-wall', kind: 'wall' },\n { prefix: 'amenity-', kind: 'amenity' },\n { prefix: 'kiosk-', kind: 'kiosk_screen' },\n { prefix: 'escalator-', kind: 'connector' },\n { prefix: 'elevator-', kind: 'connector' },\n { prefix: 'stairs-', kind: 'connector' },\n { prefix: 'entrance-', kind: 'entrance' },\n { prefix: 'zone-', kind: 'zone' },\n { prefix: 'label-', kind: 'label' },\n { prefix: 'floorplate', kind: 'floorplate' },\n { prefix: 'base', kind: 'floorplate' },\n { prefix: 'decor', kind: 'decor' },\n { prefix: 'special-shape', kind: 'decor' },\n { prefix: 'overlay', kind: 'decor' },\n { prefix: 'green-area', kind: 'green_area' },\n { prefix: 'parking-lane', kind: 'parking_zone' },\n { prefix: 'parking-line', kind: 'decor' },\n { prefix: 'parking-icon', kind: 'parking_icon' },\n { prefix: 'walking-path', kind: 'walkable' },\n { prefix: 'water', kind: 'water' },\n];\n\n/** Prefix → shape kind for outdoor / base layer. */\nconst BASE_PREFIXES: Array<{ prefix: string; kind: ShapeKind }> = [\n { prefix: 'parking-zone', kind: 'parking_zone' },\n { prefix: 'parking-lane', kind: 'parking_zone' },\n { prefix: 'parking-line', kind: 'decor' },\n { prefix: 'parking-icon', kind: 'parking_icon' },\n { prefix: 'green-area', kind: 'green_area' },\n { prefix: 'water', kind: 'water' },\n { prefix: 'walking-path', kind: 'walkable' },\n { prefix: 'decor', kind: 'decor' },\n { prefix: 'entrance-', kind: 'entrance' },\n { prefix: 'unit', kind: 'unit' },\n { prefix: 'store', kind: 'unit' },\n { prefix: 'interactive-', kind: 'unit' },\n { prefix: 'walkable', kind: 'walkable' },\n { prefix: 'void', kind: 'void' },\n { prefix: 'amenity-', kind: 'amenity' },\n { prefix: 'kiosk-', kind: 'kiosk_screen' },\n // Connectors also appear in outdoor artboards (car-park decks, ramps).\n { prefix: 'escalator-', kind: 'connector' },\n { prefix: 'elevator-', kind: 'connector' },\n { prefix: 'stairs-', kind: 'connector' },\n];\n\n/** v1 / Illustrator walking-path ids (`route-path`, `route-path-12`). */\nexport function isRoutePathLabel(label: string): boolean {\n const n = normalizeLayerLabel(label);\n return n === 'route path' || n.startsWith('route path ');\n}\n\n/** Folder that holds walking paths (`ROUTES`, `route-path`, `WAYFINDING`). */\nexport function isRouteFolderLabel(label: string): boolean {\n const n = normalizeLayerLabel(label);\n return (\n n === 'routes' ||\n n === 'route' ||\n n === 'wayfinding' ||\n n === 'wayfinding routes' ||\n isRoutePathLabel(label)\n );\n}\n\n/**\n * Outdoor / base imports only persist interactive polygons (+ walkable/void for\n * autoroute). Decoration stays in the live SVG renderer.\n */\nexport const IMPORT_PERSISTED_KINDS: readonly ShapeKind[] = [\n ...INTERACTIVE_SHAPE_KINDS,\n 'walkable',\n 'void',\n];\n\n/** Centroid shift (world units) above which a matched shape is flagged `moved`. */\nexport const IMPORT_DRIFT_THRESHOLD = 8;\n\nexport interface RawSvgElement {\n id: string;\n tag: string;\n d?: string;\n points?: string;\n x1?: number;\n y1?: number;\n x2?: number;\n y2?: number;\n /** True when data-interactive is set or the element is inside an INTERACTIVE group. */\n interactive?: boolean;\n /** Resolved fill/stroke after group inheritance + CSS class inlining. */\n style?: SvgPresentationStyle;\n}\n\ninterface GroupFrame {\n id: string | null;\n /** Named INTERACTIVE* group (not NON_INTERACTIVE*). Children are assignable units. */\n interactiveContainer: boolean;\n /** Named NON_INTERACTIVE* group. Children keep prefix classification only. */\n nonInteractiveContainer: boolean;\n /** STORES / UNITS / store-layer — Illustrator folder, never a shape. */\n storeFolder: boolean;\n /** This group or an INTERACTIVE/STORES ancestor applies (unless a closer NON_INTERACTIVE wins). */\n inInteractive: boolean;\n collectedPaths: string[];\n style: SvgPresentationStyle;\n /** Own `transform` composed with every ancestor `<g>` transform. */\n matrix: Matrix2D;\n /** A descendant carried its own `id` — this group behaves like a folder. */\n hasNamedChild: boolean;\n /** ROUTES / route-path folder — unnamed children are walking paths. */\n routeContainer: boolean;\n}\n\nexport interface ParsedSvg {\n viewbox: ViewBox | null;\n elements: RawSvgElement[];\n routePathDs: string[];\n /** Structural problems worth surfacing in the import report. */\n warnings: string[];\n}\n\nexport function classifyId(\n id: string,\n mode: 'floor' | 'base' = 'floor',\n): { kind: ShapeKind | null; guessed: boolean } {\n // Layer folders first — `store` prefix must not claim `STORES`.\n if (isLayerContainerLabel(id)) {\n return { kind: null, guessed: false };\n }\n const lower = id.toLowerCase();\n const table = mode === 'base' ? BASE_PREFIXES : FLOOR_PREFIXES;\n for (const { prefix, kind } of table) {\n if (lower === prefix || lower.startsWith(prefix)) {\n return { kind, guessed: false };\n }\n }\n // interactive-* or data-interactive attribute handled by caller\n if (lower.startsWith('interactive')) {\n return { kind: 'unit', guessed: true };\n }\n return { kind: null, guessed: false };\n}\n\n/** Collapse Illustrator id / data-name punctuation so labels compare as words. */\nexport function normalizeLayerLabel(label: string): string {\n return label\n .toLowerCase()\n .replace(/[-_]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/** Illustrator / designer NON_INTERACTIVE, NON-INTERACTIVE, \"NON INTERACTIVE ITEMS\". */\nexport function isNonInteractiveGroupLabel(label: string): boolean {\n return /non[-_ ]?interactive/i.test(label);\n}\n\n/**\n * INTERACTIVE, INTERACTIVE_ITEMS, INTERACTIVE-2, data-name=\"INTERACTIVE ITEMS\".\n * Excludes NON_INTERACTIVE* and generated ids like interactive-anon-1.\n */\nexport function isInteractiveGroupLabel(label: string): boolean {\n if (isNonInteractiveGroupLabel(label)) return false;\n return /^interactive( items)?( \\d+)?$/.test(normalizeLayerLabel(label));\n}\n\n/**\n * STORES, store-layer, UNITS — folder names only.\n * Does not match store-46 / unit-12 (those are leaf stores).\n */\nexport function isStoreFolderLabel(label: string): boolean {\n const n = normalizeLayerLabel(label);\n return n === 'stores' || n === 'store layer' || n === 'units' || n === 'unit layer';\n}\n\n/**\n * Illustrator layer / folder: never emit as a shape, never join descendants into one `d`.\n */\nexport function isLayerContainerLabel(label: string): boolean {\n return (\n isInteractiveGroupLabel(label) ||\n isNonInteractiveGroupLabel(label) ||\n isStoreFolderLabel(label) ||\n isRouteFolderLabel(label)\n );\n}\n\nfunction isContainerFrame(frame: GroupFrame): boolean {\n return frame.interactiveContainer || frame.nonInteractiveContainer || frame.storeFolder;\n}\n\nfunction attrValue(attrs: string, name: string): string | null {\n const m = attrs.match(new RegExp(`\\\\b${name}\\\\s*=\\\\s*[\"']([^\"']*)[\"']`, 'i'));\n return m ? m[1] : null;\n}\n\nfunction numAttr(attrs: string, name: string): number {\n const m = attrs.match(new RegExp(`\\\\b${name}\\\\s*=\\\\s*[\"']?(-?[\\\\d.]+)`, 'i'));\n return m ? Number(m[1]) : 0;\n}\n\nfunction hasDataInteractive(attrs: string): boolean {\n return /\\bdata-interactive\\s*=\\s*[\"']?(true|1|yes)/i.test(attrs);\n}\n\nfunction labelsFromAttrs(attrs: string): string[] {\n return [attrValue(attrs, 'id'), attrValue(attrs, 'data-name')].filter(\n (s): s is string => Boolean(s),\n );\n}\n\nfunction groupKindFromLabels(labels: string[]): {\n interactiveContainer: boolean;\n nonInteractiveContainer: boolean;\n storeFolder: boolean;\n} {\n if (labels.some(isNonInteractiveGroupLabel)) {\n return { interactiveContainer: false, nonInteractiveContainer: true, storeFolder: false };\n }\n if (labels.some(isInteractiveGroupLabel)) {\n return { interactiveContainer: true, nonInteractiveContainer: false, storeFolder: false };\n }\n if (labels.some(isStoreFolderLabel)) {\n return { interactiveContainer: false, nonInteractiveContainer: false, storeFolder: true };\n }\n return { interactiveContainer: false, nonInteractiveContainer: false, storeFolder: false };\n}\n\nfunction pointsToPath(points: string): string {\n const nums = points.trim().split(/[\\s,]+/).map(Number);\n if (nums.length < 4) return '';\n let d = `M ${nums[0]} ${nums[1]}`;\n for (let i = 2; i < nums.length; i += 2) {\n d += ` L ${nums[i]} ${nums[i + 1]}`;\n }\n d += ' Z';\n return d;\n}\n\nfunction lineToPath(x1: number, y1: number, x2: number, y2: number): string {\n return `M ${x1} ${y1} L ${x2} ${y2}`;\n}\n\nfunction geometryFromTag(tag: string, attrs: string): string | undefined {\n if (tag === 'path') {\n return attrValue(attrs, 'd') ?? undefined;\n }\n if (tag === 'polygon' || tag === 'polyline') {\n const points = attrValue(attrs, 'points');\n return points ? pointsToPath(points) : undefined;\n }\n if (tag === 'line') {\n return lineToPath(\n numAttr(attrs, 'x1'),\n numAttr(attrs, 'y1'),\n numAttr(attrs, 'x2'),\n numAttr(attrs, 'y2'),\n );\n }\n if (tag === 'rect') {\n const x = numAttr(attrs, 'x');\n const y = numAttr(attrs, 'y');\n const w = numAttr(attrs, 'width');\n const h = numAttr(attrs, 'height');\n return `M ${x} ${y} L ${x + w} ${y} L ${x + w} ${y + h} L ${x} ${y + h} Z`;\n }\n return undefined;\n}\n\n/**\n * Lightweight SVG string parser — no DOM required (works in Node).\n * Scans tags sequentially and tracks `<g>` ancestry so Illustrator folders\n * (INTERACTIVE, STORES, NON_INTERACTIVE*) are never joined into one shape.\n */\nexport function parseSvgString(svg: string): ParsedSvg {\n const stripped = inlineSvgStyles(svg).replace(/<!--[\\s\\S]*?-->/g, '');\n const viewboxMatch = stripped.match(/viewBox\\s*=\\s*[\"']([^\"']+)[\"']/i);\n const viewbox = parseViewBox(viewboxMatch?.[1]);\n\n const elements: RawSvgElement[] = [];\n const routePathDs: string[] = [];\n const warnings: string[] = [];\n const stack: GroupFrame[] = [];\n let anon = 0;\n\n const inRouteContainer = (): boolean =>\n stack.some((frame) => frame.routeContainer);\n\n const parentStyle = (): SvgPresentationStyle => {\n for (let i = stack.length - 1; i >= 0; i--) {\n const s = stack[i].style;\n if (s.fill || s.stroke || s.strokeWidth != null || s.opacity != null) {\n // Merge from root → leaf\n break;\n }\n }\n let merged: SvgPresentationStyle = {};\n for (const frame of stack) {\n merged = mergePresentationStyle(merged, frame.style);\n }\n return merged;\n };\n\n const inInteractive = (): boolean => {\n for (let i = stack.length - 1; i >= 0; i--) {\n if (stack[i].nonInteractiveContainer) return false;\n if (stack[i].interactiveContainer || stack[i].storeFolder) return true;\n }\n return false;\n };\n\n /** Accumulated `<g>` transform for the element currently being read. */\n const parentMatrix = (): Matrix2D =>\n stack.length > 0 ? stack[stack.length - 1].matrix : IDENTITY_MATRIX;\n\n const markNamedChild = () => {\n for (let i = stack.length - 1; i >= 0; i--) {\n const frame = stack[i];\n if (isContainerFrame(frame)) continue;\n if (frame.id) {\n frame.hasNamedChild = true;\n return;\n }\n }\n };\n\n const findCollector = (): GroupFrame | null => {\n for (let i = stack.length - 1; i >= 0; i--) {\n const frame = stack[i];\n if (isContainerFrame(frame)) continue;\n if (frame.id) return frame;\n }\n return null;\n };\n\n const closeGroup = (frame: GroupFrame) => {\n if (frame.routeContainer) {\n for (const collected of frame.collectedPaths) emitRoute('path', collected);\n return;\n }\n if (isContainerFrame(frame)) return;\n if (!frame.id || frame.collectedPaths.length === 0) return;\n if (frame.hasNamedChild) {\n // A folder-like group (KIOSK, ESCALATORS, …) that also holds a stray\n // unnamed path: the stray silently merges into one shape keyed after\n // the group. Classification is unchanged — the designer gets a warning.\n warnings.push(\n `Group ${frame.id} mixes named children with ${frame.collectedPaths.length} unnamed path(s); ` +\n `the unnamed paths were merged into a single shape \"${frame.id}\" — give them ids if they are separate shapes`,\n );\n }\n elements.push({\n id: frame.id,\n tag: 'g',\n d: frame.collectedPaths.join(' '),\n interactive: frame.inInteractive,\n style: mergePresentationStyle(parentStyle(), frame.style),\n });\n };\n\n const emitRoute = (tag: string, d: string | undefined) => {\n if (!d) return;\n const open =\n tag === 'polyline' || tag === 'polygon' || tag === 'path'\n ? d.replace(/\\s*Z\\s*$/i, '')\n : d;\n if (routePathDs.includes(open)) return;\n routePathDs.push(open);\n };\n\n const tokenRe = /<(\\/?)(path|polygon|polyline|line|rect|g)\\b([^>]*)(\\/?)>/gi;\n let match: RegExpExecArray | null;\n while ((match = tokenRe.exec(stripped)) !== null) {\n const closing = match[1] === '/';\n const tag = match[2].toLowerCase();\n const attrs = match[3] ?? '';\n const selfClosing = match[4] === '/' || /\\/\\s*$/.test(attrs);\n\n if (closing) {\n if (tag === 'g') {\n const frame = stack.pop();\n if (frame) closeGroup(frame);\n }\n continue;\n }\n\n if (tag === 'g') {\n const id = attrValue(attrs, 'id');\n const labels = labelsFromAttrs(attrs);\n const { interactiveContainer, nonInteractiveContainer, storeFolder } =\n groupKindFromLabels(labels);\n const parentInteractive = inInteractive();\n if (id) markNamedChild();\n const frame: GroupFrame = {\n id,\n interactiveContainer,\n nonInteractiveContainer,\n storeFolder,\n inInteractive:\n interactiveContainer ||\n storeFolder ||\n hasDataInteractive(attrs) ||\n (parentInteractive && !nonInteractiveContainer),\n collectedPaths: [],\n style: readPresentationStyle(attrs),\n matrix: multiplyMatrix(parentMatrix(), parseTransform(attrValue(attrs, 'transform'))),\n hasNamedChild: false,\n routeContainer:\n labels.some(isRouteFolderLabel) || inRouteContainer(),\n };\n if (!selfClosing) stack.push(frame);\n continue;\n }\n\n const id = attrValue(attrs, 'id');\n const raw = geometryFromTag(tag, attrs);\n // Bake own + inherited group transforms so every emitted `d` is in root\n // user space, matching the polygons derived from it later.\n const matrix = multiplyMatrix(parentMatrix(), parseTransform(attrValue(attrs, 'transform')));\n const d = raw ? transformPathD(raw, matrix) : raw;\n const interactive = hasDataInteractive(attrs) || inInteractive();\n const style = mergePresentationStyle(parentStyle(), readPresentationStyle(attrs));\n\n const dataName = attrValue(attrs, 'data-name');\n const routeNamed =\n (id != null && isRoutePathLabel(id)) ||\n (dataName != null && isRoutePathLabel(dataName));\n if (routeNamed || (!id && inRouteContainer())) {\n emitRoute(tag, d);\n continue;\n }\n\n if (id) {\n markNamedChild();\n if (d) {\n elements.push({ id, tag, d, interactive, style });\n }\n continue;\n }\n\n if (!d) continue;\n\n const collector = findCollector();\n if (collector) {\n collector.collectedPaths.push(d);\n // Prefer first child style onto the collector when empty\n if (!collector.style.fill && style.fill) collector.style = style;\n } else if (interactive) {\n anon += 1;\n elements.push({\n id: `interactive-anon-${anon}`,\n tag,\n d,\n interactive: true,\n style,\n });\n }\n }\n\n while (stack.length > 0) {\n closeGroup(stack.pop()!);\n }\n\n return { viewbox, elements, routePathDs, warnings };\n}\n\nexport interface ImportedShapeDraft {\n key: string;\n kind: ShapeKind;\n geometry: ShapeGeometry;\n bbox: BBox;\n sourceSvgId: string;\n style: ShapeStyle;\n}\n\nfunction slugKey(id: string): string {\n return id\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 80);\n}\n\nfunction styleFromElement(\n el: RawSvgElement,\n sourceSvgId: string,\n): ShapeStyle {\n const layer = resolveLayerStyle(sourceSvgId);\n const style: ShapeStyle = {};\n if (layer?.fill) style.fill = layer.fill;\n else if (el.style?.fill) style.fill = el.style.fill;\n if (layer?.stroke) style.stroke = layer.stroke;\n else if (el.style?.stroke) style.stroke = el.style.stroke;\n if (layer?.strokeWidth != null) style.strokeWidth = layer.strokeWidth;\n else if (el.style?.strokeWidth != null) style.strokeWidth = el.style.strokeWidth;\n if (el.style?.opacity != null) style.opacity = el.style.opacity;\n if (layer?.extrudeHeight != null) style.extrudeHeight = layer.extrudeHeight;\n return style;\n}\n\nfunction viewBoxesEqual(a: ViewBox | null, b: ViewBox | null): boolean {\n if (a == null && b == null) return true;\n if (a == null || b == null) return false;\n return (\n Math.abs(a.x - b.x) < 0.01 &&\n Math.abs(a.y - b.y) < 0.01 &&\n Math.abs(a.width - b.width) < 0.01 &&\n Math.abs(a.height - b.height) < 0.01\n );\n}\n\nexport interface ImportSvgOptions {\n /** Previous level viewBox — used to detect artboard changes on re-upload. */\n previousViewbox?: ViewBox | null;\n}\n\nexport function importSvg(\n svg: string,\n mode: 'floor' | 'base' = 'floor',\n options: ImportSvgOptions = {},\n): {\n report: ImportReport;\n shapes: ImportedShapeDraft[];\n viewbox: ViewBox | null;\n routePathDs: string[];\n viewBoxChanged: boolean;\n} {\n const parsed = parseSvgString(svg);\n const classified: ImportClassification[] = [];\n const unrecognized: string[] = [];\n const guessed: ImportClassification[] = [];\n const warnings: string[] = [...parsed.warnings];\n const shapes: ImportedShapeDraft[] = [];\n\n let walkableCount = 0;\n let voidCount = 0;\n let unitCount = 0;\n\n const viewBoxChanged =\n options.previousViewbox != null &&\n parsed.viewbox != null &&\n !viewBoxesEqual(options.previousViewbox, parsed.viewbox);\n\n if (viewBoxChanged) {\n warnings.push(\n 'SVG viewBox differs from the stored artboard — re-upload blocked until the designer restores the original viewBox',\n );\n }\n\n for (const el of parsed.elements) {\n if (isLayerContainerLabel(el.id)) continue;\n let { kind, guessed: isGuessed } = classifyId(el.id, mode);\n if (el.interactive && !kind) {\n kind = 'unit';\n isGuessed = true;\n }\n\n const entry: ImportClassification = {\n sourceSvgId: el.id,\n kind,\n guessed: isGuessed,\n };\n\n // Floor mode: keep unrecognized as decor so discarding the SVG loses nothing.\n // Outdoor / base mode: skip unrecognized — live SVG renderer draws them.\n if (!kind) {\n unrecognized.push(el.id);\n if (mode === 'floor') {\n kind = 'decor';\n entry.kind = 'decor';\n entry.message = 'No matching prefix; imported as decor (floor mode)';\n } else {\n entry.message = 'No matching prefix; skipped (outdoor decor stays in SVG)';\n classified.push(entry);\n continue;\n }\n }\n\n if (!el.d) {\n warnings.push(`Element ${el.id} has no drawable geometry`);\n continue;\n }\n\n // Outdoor: only persist interactive (+ walkable/void). Decoration stays in SVG.\n // Static house-style layers (green-area, parking-lane, …) are never rows.\n if (mode === 'base') {\n const isStaticDecor = resolveLayerStyle(el.id) != null;\n const shouldPersist =\n !isStaticDecor &&\n (IMPORT_PERSISTED_KINDS.includes(kind) || Boolean(el.interactive));\n if (!shouldPersist) {\n classified.push({\n ...entry,\n message: isStaticDecor\n ? 'Static decoration — rendered from outdoor SVG'\n : 'Decoration — not persisted; rendered from outdoor SVG',\n });\n continue;\n }\n }\n\n if (isGuessed) {\n guessed.push(entry);\n entry.message = entry.message ?? 'Guessed kind from interactive/fallback rule';\n }\n classified.push(entry);\n\n if (kind === 'walkable') walkableCount++;\n if (kind === 'void') voidCount++;\n if (kind === 'unit') unitCount++;\n\n const geometry = buildGeometryFromPaths([el.d]);\n const bbox = geometryBBox(geometry);\n\n shapes.push({\n key: slugKey(el.id),\n kind,\n geometry,\n bbox,\n sourceSvgId: el.id,\n style: styleFromElement(el, el.id),\n });\n }\n\n if (mode === 'floor' && walkableCount === 0) {\n warnings.push(\n 'No walkable layer found — auto-skeleton will be unavailable for this level',\n );\n }\n\n return {\n report: {\n classified,\n unrecognized,\n guessed,\n walkableCount,\n voidCount,\n unitCount,\n warnings,\n },\n shapes,\n viewbox: parsed.viewbox,\n routePathDs: parsed.routePathDs,\n viewBoxChanged,\n };\n}\n\nexport interface ExistingShapeRef {\n id: number;\n sourceSvgId: string | null;\n kind: ShapeKind;\n key: string;\n /** When set, centroid drift is measured against the new draft. */\n bbox?: BBox | null;\n geometryLocked?: boolean;\n}\n\n/**\n * Diff newly imported shapes against existing level shapes by source_svg_id.\n * Emits `moved` when a matched id's centroid drifts past IMPORT_DRIFT_THRESHOLD.\n */\nexport function diffImport(\n imported: ImportedShapeDraft[],\n existing: ExistingShapeRef[],\n viewbox: ViewBox | null,\n options: { driftThreshold?: number } = {},\n): ImportDiff {\n const driftThreshold = options.driftThreshold ?? IMPORT_DRIFT_THRESHOLD;\n const existingBySource = new Map(\n existing\n .filter((e) => e.sourceSvgId)\n .map((e) => [e.sourceSvgId as string, e]),\n );\n const seen = new Set<string>();\n const items: ImportDiffItem[] = [];\n\n for (const shape of imported) {\n const prev = existingBySource.get(shape.sourceSvgId);\n seen.add(shape.sourceSvgId);\n if (!prev) {\n items.push({\n sourceSvgId: shape.sourceSvgId,\n change: 'added',\n newKind: shape.kind,\n });\n } else if (prev.kind !== shape.kind) {\n items.push({\n sourceSvgId: shape.sourceSvgId,\n change: 'kind_changed',\n existingShapeId: prev.id,\n existingKind: prev.kind,\n newKind: shape.kind,\n preserve: { key: prev.key, assignment: true, anchors: true },\n geometryLocked: prev.geometryLocked,\n });\n } else {\n let change: ImportDiffItem['change'] = 'unchanged';\n if (prev.bbox) {\n const prevCx = (prev.bbox.minX + prev.bbox.maxX) / 2;\n const prevCy = (prev.bbox.minY + prev.bbox.maxY) / 2;\n const next = geometryCentroid(shape.geometry);\n const drift = Math.hypot(next.x - prevCx, next.y - prevCy);\n if (drift > driftThreshold) change = 'moved';\n }\n items.push({\n sourceSvgId: shape.sourceSvgId,\n change,\n existingShapeId: prev.id,\n existingKind: prev.kind,\n newKind: shape.kind,\n preserve: { key: prev.key, assignment: true, anchors: true },\n geometryLocked: prev.geometryLocked,\n });\n }\n }\n\n for (const prev of existing) {\n if (prev.sourceSvgId && !seen.has(prev.sourceSvgId)) {\n items.push({\n sourceSvgId: prev.sourceSvgId,\n change: 'removed',\n existingShapeId: prev.id,\n existingKind: prev.kind,\n geometryLocked: prev.geometryLocked,\n });\n }\n }\n\n return {\n items,\n shapes: imported,\n viewbox,\n };\n}\n\nexport {\n inlineSvgStyles,\n readPresentationStyle,\n mergePresentationStyle,\n} from './svgStyle';\n\nexport {\n IDENTITY_MATRIX,\n applyMatrix,\n isIdentityMatrix,\n multiplyMatrix,\n parseTransform,\n transformPathD,\n type Matrix2D,\n} from './svgTransform';\n","import { distance } from './geometry';\nimport { clampStoreRadius, type Vec2 } from './types';\n\nconst EPS = 1e-6;\n/** Illustrator-style: only corner anchors, not smooth wall wobble. */\nconst MIN_CORNER_TURN = (15 * Math.PI) / 180;\nconst EDGE_GAP = 1e-3;\nconst TWO_PI = Math.PI * 2;\n\nfunction almostSame(a: Vec2, b: Vec2): boolean {\n return Math.abs(a.x - b.x) < EPS && Math.abs(a.y - b.y) < EPS;\n}\n\nfunction add(a: Vec2, b: Vec2): Vec2 {\n return { x: a.x + b.x, y: a.y + b.y };\n}\n\nfunction sub(a: Vec2, b: Vec2): Vec2 {\n return { x: a.x - b.x, y: a.y - b.y };\n}\n\nfunction scale(a: Vec2, s: number): Vec2 {\n return { x: a.x * s, y: a.y * s };\n}\n\nfunction pointOnCircle(center: Vec2, radius: number, angle: number): Vec2 {\n return {\n x: center.x + Math.cos(angle) * radius,\n y: center.y + Math.sin(angle) * radius,\n };\n}\n\n/** Drop duplicate consecutive points and a repeated closing vertex. */\nexport function uniqueClosedRing(points: Vec2[]): Vec2[] {\n const ring: Vec2[] = [];\n for (const point of points) {\n const last = ring[ring.length - 1];\n if (last && almostSame(last, point)) continue;\n ring.push(point);\n }\n if (ring.length >= 2 && almostSame(ring[0], ring[ring.length - 1])) ring.pop();\n return ring;\n}\n\n/**\n * Illustrator Round Corners: replace each real corner with a circular arc\n * tangent to both walls. The arc stays at the corner (never the long way\n * through the store). Shallow wall bends are left alone.\n */\nexport function filletPolygon(points: Vec2[], radius: number): Vec2[] {\n const r = clampStoreRadius(radius);\n const ring = uniqueClosedRing(points);\n if (ring.length < 3 || r <= 0) return points;\n\n const n = ring.length;\n const inN: Vec2[] = new Array(n);\n const outN: Vec2[] = new Array(n);\n const outLen: number[] = new Array(n);\n const turn: number[] = new Array(n);\n const inD = new Array(n).fill(0);\n const outD = new Array(n).fill(0);\n const fillet = new Array(n).fill(false);\n\n for (let i = 0; i < n; i++) {\n const prev = ring[(i - 1 + n) % n];\n const curr = ring[i];\n const next = ring[(i + 1) % n];\n const incoming = distance(prev, curr);\n const outgoing = distance(curr, next);\n outLen[i] = outgoing;\n if (incoming < EPS || outgoing < EPS) {\n inN[i] = { x: 1, y: 0 };\n outN[i] = { x: 1, y: 0 };\n turn[i] = 0;\n continue;\n }\n inN[i] = scale(sub(curr, prev), 1 / incoming);\n outN[i] = scale(sub(next, curr), 1 / outgoing);\n const cross = inN[i].x * outN[i].y - inN[i].y * outN[i].x;\n const dot = inN[i].x * outN[i].x + inN[i].y * outN[i].y;\n turn[i] = Math.atan2(cross, dot);\n const absTurn = Math.abs(turn[i]);\n if (absTurn < MIN_CORNER_TURN) continue;\n // Illustrator uses the same offset for convex and concave:\n // d = r / tan((π − |turn|)/2). Splitting those cases made\n // store-40's inner notch bulge instead of a tight inner radius.\n const wedge = Math.PI - absTurn;\n const tanHalf = Math.tan(wedge / 2);\n if (tanHalf < EPS || wedge <= EPS || wedge >= Math.PI - EPS) continue;\n const desired = r / tanHalf;\n inD[i] = desired;\n outD[i] = desired;\n fillet[i] = true;\n }\n\n for (let i = 0; i < n; i++) {\n const j = (i + 1) % n;\n const need = outD[i] + inD[j];\n const available = Math.max(0, outLen[i] - EDGE_GAP);\n if (need <= available || need <= EPS) continue;\n const scaleDown = available / need;\n outD[i] *= scaleDown;\n inD[j] *= scaleDown;\n }\n\n const out: Vec2[] = [];\n for (let i = 0; i < n; i++) {\n const curr = ring[i];\n const d = Math.min(inD[i], outD[i]);\n const absTurn = Math.abs(turn[i]);\n const wedge = Math.PI - absTurn;\n const actualR = d * Math.tan(wedge / 2);\n if (!fillet[i] || actualR < EPS || d < EPS) {\n out.push({ ...curr });\n continue;\n }\n\n const start = add(curr, scale(inN[i], -d));\n const end = add(curr, scale(outN[i], d));\n const sign = turn[i] > 0 ? 1 : -1;\n const center = add(start, {\n x: -inN[i].y * sign * actualR,\n y: inN[i].x * sign * actualR,\n });\n const a0 = Math.atan2(start.y - center.y, start.x - center.x);\n const a1 = Math.atan2(end.y - center.y, end.x - center.x);\n const sweepCCW = (a1 - a0 + TWO_PI) % TWO_PI;\n const sweepCW = (a0 - a1 + TWO_PI) % TWO_PI;\n const midCCW = pointOnCircle(center, actualR, a0 + sweepCCW / 2);\n const midCW = pointOnCircle(center, actualR, a0 - sweepCW / 2);\n const useCCW = distance(midCCW, curr) <= distance(midCW, curr);\n const sweep = useCCW ? sweepCCW : sweepCW;\n const steps = Math.max(8, Math.min(28, Math.ceil((sweep * actualR) / 2)));\n\n for (let s = 0; s <= steps; s++) {\n const t = s / steps;\n const ang = useCCW ? a0 + sweep * t : a0 - sweep * t;\n out.push(pointOnCircle(center, actualR, ang));\n }\n }\n\n return out;\n}\n","import createGraph, { type Graph } from 'ngraph.graph';\nimport path from 'ngraph.path';\nimport type {\n CmAnchor,\n CmConnector,\n CmRouteEdge,\n PathResult,\n PublishedGraphEdge,\n PublishedGraphNode,\n} from '../types';\nimport { FLOOR_CHANGE_PENALTY } from '../types';\nimport { distance } from '../geometry';\n\nexport interface CompiledGraph {\n graph: Graph;\n nodes: PublishedGraphNode[];\n edges: PublishedGraphEdge[];\n anchorById: Map<number, CmAnchor>;\n}\n\nexport function compileGraph(\n anchors: CmAnchor[],\n edges: CmRouteEdge[],\n connectors: CmConnector[] = [],\n): CompiledGraph {\n const graph = createGraph();\n const anchorById = new Map(anchors.map((a) => [a.id, a]));\n const connectorById = new Map(connectors.map((c) => [c.id, c]));\n\n const nodes: PublishedGraphNode[] = anchors.map((a) => ({\n id: a.id,\n levelId: a.levelId,\n x: a.x,\n y: a.y,\n kind: a.kind,\n shapeId: a.shapeId,\n connectorId: a.connectorId,\n }));\n\n for (const n of nodes) {\n graph.addNode(n.id, n);\n }\n\n const publishedEdges: PublishedGraphEdge[] = [];\n\n for (const e of edges) {\n const from = anchorById.get(e.fromAnchorId);\n const to = anchorById.get(e.toAnchorId);\n if (!from || !to) continue;\n\n let weight = e.weight;\n if (weight == null) {\n weight = distance(from, to);\n if (from.levelId !== to.levelId) {\n weight += FLOOR_CHANGE_PENALTY;\n }\n }\n\n // Accessibility: connector edges inherit connector.accessible\n let accessible = e.accessible;\n if (e.kind === 'connector' && from.connectorId != null) {\n const conn = connectorById.get(from.connectorId);\n if (conn) accessible = conn.accessible;\n }\n\n const pub: PublishedGraphEdge = {\n id: e.id,\n from: e.fromAnchorId,\n to: e.toAnchorId,\n weight,\n directed: e.directed,\n accessible,\n kind: e.kind,\n };\n publishedEdges.push(pub);\n\n graph.addLink(e.fromAnchorId, e.toAnchorId, pub);\n if (!e.directed) {\n graph.addLink(e.toAnchorId, e.fromAnchorId, pub);\n }\n }\n\n return { graph, nodes, edges: publishedEdges, anchorById };\n}\n\nexport interface FindPathOptions {\n accessibleOnly?: boolean;\n}\n\n/**\n * NBA* pathfinding over the compiled graph.\n * Returns null if no path exists.\n */\nexport function findPath(\n compiled: CompiledGraph,\n fromAnchorId: number,\n toAnchorId: number,\n options: FindPathOptions = {},\n): PathResult | null {\n const { graph, anchorById } = compiled;\n if (!anchorById.has(fromAnchorId) || !anchorById.has(toAnchorId)) {\n return null;\n }\n\n const finder = path.nba(graph, {\n oriented: true,\n distance(fromNode, toNode, link) {\n const data = link.data as PublishedGraphEdge | undefined;\n if (options.accessibleOnly && data && !data.accessible) {\n return Number.POSITIVE_INFINITY;\n }\n return data?.weight ?? 1;\n },\n heuristic(fromNode, toNode) {\n const a = anchorById.get(fromNode.id as number);\n const b = anchorById.get(toNode.id as number);\n if (!a || !b) return 0;\n let d = distance(a, b);\n if (a.levelId !== b.levelId) d += FLOOR_CHANGE_PENALTY;\n return d;\n },\n });\n\n const raw = finder.find(fromAnchorId, toAnchorId);\n if (!raw || raw.length === 0) return null;\n\n // ngraph returns destination → start; reverse\n const nodes = raw.reverse();\n const anchorIds = nodes.map((n) => n.id as number);\n const points: PathResult['points'] = [];\n const levelChanges: PathResult['levelChanges'] = [];\n let totalWeight = 0;\n\n for (let i = 0; i < anchorIds.length; i++) {\n const a = anchorById.get(anchorIds[i])!;\n points.push({ x: a.x, y: a.y, levelId: a.levelId });\n if (i > 0) {\n const prev = anchorById.get(anchorIds[i - 1])!;\n totalWeight += distance(prev, a);\n if (prev.levelId !== a.levelId) {\n totalWeight += FLOOR_CHANGE_PENALTY;\n levelChanges.push({\n fromLevelId: prev.levelId,\n toLevelId: a.levelId,\n connectorId: a.connectorId ?? prev.connectorId,\n });\n }\n }\n }\n\n return { anchorIds, points, totalWeight, levelChanges };\n}\n\n/**\n * Find the nearest matching amenity shape anchor from a start point.\n */\nexport function findNearestAmenityPath(\n compiled: CompiledGraph,\n fromAnchorId: number,\n amenityAnchorIds: number[],\n options: FindPathOptions = {},\n): PathResult | null {\n let best: PathResult | null = null;\n for (const targetId of amenityAnchorIds) {\n const result = findPath(compiled, fromAnchorId, targetId, options);\n if (!result) continue;\n if (!best || result.totalWeight < best.totalWeight) {\n best = result;\n }\n }\n return best;\n}\n","import type {\n CmAmenityCatalogItem,\n CmAnchor,\n CmBuilding,\n CmConnector,\n CmLevel,\n CmResponsiveOverride,\n CmRouteEdge,\n CmShape,\n CmShapeAssignment,\n PublishedDocument,\n ThemeDefaults,\n ViewBox,\n} from '../types';\nimport { mergeTheme } from '../types';\nimport { compileGraph } from '../routing/pathfinding';\nimport { geometryBBox, normalizeGeometrySpace } from '../geometry';\n\nexport interface PublishInput {\n revisionId: number;\n revisionNumber: number;\n centerId: number;\n mapId: number;\n theme: Partial<ThemeDefaults>;\n baseSvgUrl: string | null;\n baseViewbox: ViewBox | null;\n buildings: CmBuilding[];\n levels: CmLevel[];\n shapes: CmShape[];\n assignments: CmShapeAssignment[];\n anchors: CmAnchor[];\n edges: CmRouteEdge[];\n connectors: CmConnector[];\n amenities: CmAmenityCatalogItem[];\n responsiveOverrides: CmResponsiveOverride[];\n /** Resolve S3 key → CDN URL for level source SVGs. */\n resolveSvgUrl?: (key: string | null) => string | null;\n publishedAt?: string;\n}\n\n/**\n * Compile live cm_* rows into the current production document.\n * Used by Save Changes (overwrite-in-place) and draft preview (?draft=1).\n */\nexport function compileDocument(input: PublishInput): PublishedDocument {\n const theme: ThemeDefaults = mergeTheme(input.theme);\n const assignmentByShape = new Map(\n input.assignments.map((a) => [a.shapeId, a]),\n );\n const resolve = input.resolveSvgUrl ?? ((k: string | null) => k);\n\n const levels = input.levels\n .filter((l) => l.isActive)\n .sort((a, b) => a.ordering - b.ordering)\n .map((level) => {\n const levelShapes = input.shapes\n .filter((s) => s.levelId === level.id)\n .map((s) => {\n // Heals rows imported before the Y-flip removal without a re-import.\n const geometry = normalizeGeometrySpace(s.geometry);\n return {\n ...s,\n geometry,\n bbox: geometry === s.geometry ? s.bbox : geometryBBox(geometry),\n assignment: assignmentByShape.get(s.id) ?? null,\n };\n });\n const levelAnchors = input.anchors.filter((a) => a.levelId === level.id);\n return {\n id: level.id,\n buildingId: level.buildingId,\n kind: level.kind,\n name: level.name,\n levelIndex: level.levelIndex,\n ordering: level.ordering,\n sourceSvgUrl: resolve(level.sourceSvgKey) ?? level.sourceSvgUrl ?? null,\n viewbox: level.sourceViewbox,\n transform: level.transform,\n shapes: levelShapes,\n anchors: levelAnchors,\n };\n });\n\n const { nodes, edges } = compileGraph(\n input.anchors,\n input.edges,\n input.connectors,\n );\n\n return {\n version: 2,\n revisionId: input.revisionId,\n revisionNumber: input.revisionNumber,\n centerId: input.centerId,\n mapId: input.mapId,\n theme,\n baseSvgUrl: input.baseSvgUrl,\n baseViewbox: input.baseViewbox,\n buildings: input.buildings,\n levels,\n connectors: input.connectors,\n amenities: input.amenities.filter((a) => a.isActive),\n graph: { nodes, edges },\n responsiveOverrides: input.responsiveOverrides,\n publishedAt: input.publishedAt ?? new Date().toISOString(),\n };\n}\n\n/**\n * Heal a document that was compiled before the Y-flip removal. Viewer hosts\n * load `cm_revisions` JSON as-is (they never re-run `compileDocument`), so\n * stale polygons would otherwise render upside down relative to the editor.\n */\nexport function normalizePublishedDocument(\n doc: PublishedDocument,\n): PublishedDocument {\n let changed = false;\n const levels = doc.levels.map((level) => {\n let levelChanged = false;\n const shapes = level.shapes.map((shape) => {\n const geometry = normalizeGeometrySpace(shape.geometry);\n if (geometry === shape.geometry) return shape;\n levelChanged = true;\n return {\n ...shape,\n geometry,\n bbox: geometryBBox(geometry),\n };\n });\n if (!levelChanged) return level;\n changed = true;\n return { ...level, shapes };\n });\n return changed ? { ...doc, levels } : doc;\n}\n","import type { LevelKind, PublishedLevel, ViewBox } from './types';\n\nexport interface StackLevel {\n id: number;\n kind: LevelKind;\n ordering: number;\n levelIndex: number;\n}\n\n/** Same comparator as admin FloorsPanel `buildingFloors`. */\nexport function compareBuildingFloors(\n a: { ordering: number; levelIndex: number },\n b: { ordering: number; levelIndex: number },\n): number {\n return a.ordering - b.ordering || a.levelIndex - b.levelIndex;\n}\n\nexport interface SceneBounds {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n cx: number;\n cy: number;\n size: number;\n}\n\nexport function isOutdoorLevel(level: { kind: string }): boolean {\n return level.kind === 'outdoor';\n}\n\n/**\n * Persistent base + optional building-floor overlay.\n * Outdoor/base is never dropped when a floor is selected.\n * Selecting Outdoor hides building floors (base stays).\n */\nexport function viewerLevelStack<T extends { id: number; kind: string }>(\n levels: T[],\n activeLevelId: number | null,\n): T[] {\n const outdoor = levels.filter(isOutdoorLevel);\n const active =\n activeLevelId == null\n ? null\n : (levels.find((level) => level.id === activeLevelId) ?? null);\n\n if (!active || isOutdoorLevel(active)) {\n return outdoor;\n }\n\n if (outdoor.some((level) => level.id === active.id)) {\n return outdoor;\n }\n return [...outdoor, active];\n}\n\n/** Building floors only, same order as the admin Floors list. */\nexport function floorSwitcherLevels<T extends StackLevel>(levels: T[]): T[] {\n return levels\n .filter((level) => level.kind === 'floor')\n .slice()\n .sort(compareBuildingFloors);\n}\n\n/**\n * Switcher buttons top-to-bottom — same order as the admin Floors list.\n * Do not reverse: staff order the list (upper level at the top) and the map\n * must match that.\n */\nexport function floorSwitcherDisplayLevels<T extends StackLevel>(levels: T[]): T[] {\n return floorSwitcherLevels(levels);\n}\n\n/** Hide the map floor list when there is only one building floor. */\nexport function shouldShowFloorSwitcher<T extends StackLevel>(levels: T[]): boolean {\n return floorSwitcherLevels(levels).length > 1;\n}\n\n/**\n * Prefer the last building floor in admin Floors order (bottom of the list).\n * The list stays upper-to-ground top-to-bottom; visitors should land on ground.\n */\nexport function defaultViewerLevelId(\n levels: Array<{ id: number; kind: string; ordering: number; levelIndex: number }>,\n): number | null {\n return floorSwitcherLevels(levels as StackLevel[]).at(-1)?.id ?? levels[0]?.id ?? null;\n}\n\nexport function viewBoxToBounds(viewbox: ViewBox): SceneBounds {\n return {\n minX: viewbox.x,\n minY: viewbox.y,\n maxX: viewbox.x + viewbox.width,\n maxY: viewbox.y + viewbox.height,\n cx: viewbox.x + viewbox.width / 2,\n cy: viewbox.y + viewbox.height / 2,\n size: Math.max(viewbox.width, viewbox.height, 100),\n };\n}\n\nexport function expandBounds(target: SceneBounds, next: SceneBounds): SceneBounds {\n const minX = Math.min(target.minX, next.minX);\n const minY = Math.min(target.minY, next.minY);\n const maxX = Math.max(target.maxX, next.maxX);\n const maxY = Math.max(target.maxY, next.maxY);\n return {\n minX,\n minY,\n maxX,\n maxY,\n cx: (minX + maxX) / 2,\n cy: (minY + maxY) / 2,\n size: Math.max(maxX - minX, maxY - minY, 100),\n };\n}\n\nexport function boundsFromStackedLevels(\n levels: PublishedLevel[],\n activeLevelId: number | null,\n baseViewbox?: ViewBox | null,\n): SceneBounds {\n let bounds: SceneBounds | null = baseViewbox ? viewBoxToBounds(baseViewbox) : null;\n\n for (const level of viewerLevelStack(levels, activeLevelId)) {\n if (level.viewbox) {\n const vb = viewBoxToBounds(level.viewbox);\n bounds = bounds ? expandBounds(bounds, vb) : vb;\n }\n for (const shape of level.shapes) {\n const shapeBounds: SceneBounds = {\n minX: shape.bbox.minX,\n minY: shape.bbox.minY,\n maxX: shape.bbox.maxX,\n maxY: shape.bbox.maxY,\n cx: (shape.bbox.minX + shape.bbox.maxX) / 2,\n cy: (shape.bbox.minY + shape.bbox.maxY) / 2,\n size: Math.max(\n shape.bbox.maxX - shape.bbox.minX,\n shape.bbox.maxY - shape.bbox.minY,\n 100,\n ),\n };\n bounds = bounds ? expandBounds(bounds, shapeBounds) : shapeBounds;\n }\n }\n\n return bounds ?? { minX: 0, minY: 0, maxX: 500, maxY: 500, cx: 250, cy: 250, size: 500 };\n}\n\nexport function unionViewBox(\n primary: ViewBox | null | undefined,\n secondary: ViewBox | null | undefined,\n): ViewBox {\n if (!primary && !secondary) return { x: 0, y: 0, width: 1000, height: 800 };\n if (!primary) return secondary!;\n if (!secondary) return primary;\n const minX = Math.min(primary.x, secondary.x);\n const minY = Math.min(primary.y, secondary.y);\n const maxX = Math.max(primary.x + primary.width, secondary.x + secondary.width);\n const maxY = Math.max(primary.y + primary.height, secondary.y + secondary.height);\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n"],"names":["WALKING_PATH_COLOR","STATIC_LAYER_STYLES","normalizeLayerName","label","resolveLayerStyle","layerName","normalized","keys","a","b","key","keyNorm","svgIdsOwnedByShapes","shapes","options","omitStatic","ids","shape","id","DEFAULT_THEME","LEGACY_V2_MAP_BACKGROUND","LEGACY_WALKABLE_COLORS","MAX_STORE_RADIUS","clampStoreRadius","value","n","mergeTheme","partials","theme","INTERACTIVE_SHAPE_KINDS","FLOOR_CHANGE_PENALTY","DEFAULT_WELD_TOLERANCE","mapSurface","host","PUBLIC_CHROME","VIEWER_CHROME","viewerChrome","isMapViewerHost","resolveFetchUrl","url","imageProxyUrl","flipY","points","viewboxHeight","p","distance","dx","dy","bboxOf","minX","minY","maxX","maxY","bboxUnion","centroid","sx","sy","pointInPolygon","point","polygon","inside","i","j","xi","yi","xj","yj","pointInPolygons","polygons","poly","projectOntoSegment","lenSq","t","proj","nearestPointOnPolyline","polyline","best","approximateCubic","p0","p1","p2","p3","segments","out","u","approximateQuadratic","ARC_SEGMENTS_PER_QUADRANT","approximateArc","rx","ry","xAxisRotationDeg","largeArc","sweep","arx","ary","phi","cosPhi","sinPhi","dx2","dy2","x1p","y1p","lambda","scale","rxSq","rySq","numerator","denominator","factor","cxp","cyp","cx","cy","ux","uy","vx","vy","theta1","deltaTheta","ideal","theta","cosT","sinT","WHITESPACE_RE","tokenizePathData","d","tokens","cmd","argIndex","ch","arcSlot","start","digits","beforeExponent","pathToPolygons","current","x","y","startX","startY","lastCtrl","readNum","isRel","nx","ny","x1","y1","x2","y2","approx","rot","firstMoveTo","m","isGeometrySpaceStale","geometry","_a","first","_b","normalizeGeometrySpace","buildGeometryFromPaths","pathDs","paths","geometryBBox","all","geometryCentroid","snapAngle","from","to","baseDeg","increments","len","relative","bestDiff","step","snapped","diff","finalDeg","angleFromWall","parseViewBox","raw","parts","CSS_TO_SVG_ATTR","parseCssDeclarations","block","declarations","declaration","sep","property","parseCssClassRules","cssText","classStyles","normalizedCss","match","selectors","s","selector","classMatch","className","mergeClassStyles","classAttr","merged","name","c","inlineSvgStyles","svgText","styleBlocks","withoutComments","decls","full","tag","attrs","selfClosing","cleanAttrs","nextAttrs","cssProp","svgAttr","readPresentationStyle","fill","stroke","strokeWidth","_c","opacity","_d","fillOpacity","_e","mergePresentationStyle","parent","child","IDENTITY_MATRIX","multiplyMatrix","outer","inner","applyMatrix","isIdentityMatrix","epsilon","translateMatrix","tx","ty","rotateMatrix","deg","rad","cos","sin","transformFunctionMatrix","args","TRANSFORM_FN_RE","parseTransform","result","next","fmt","rounded","transformArc","phiDeg","e11","e21","e12","e22","m11","m21","m12","m22","E","F","G","H","q","r","outRx","outRy","a1","outPhi","transformPathD","flipsOrientation","emit","letter","coords","px","py","rel","arc","FLOOR_PREFIXES","BASE_PREFIXES","isRoutePathLabel","normalizeLayerLabel","isRouteFolderLabel","IMPORT_PERSISTED_KINDS","IMPORT_DRIFT_THRESHOLD","classifyId","mode","isLayerContainerLabel","lower","table","prefix","kind","isNonInteractiveGroupLabel","isInteractiveGroupLabel","isStoreFolderLabel","isContainerFrame","frame","attrValue","numAttr","hasDataInteractive","labelsFromAttrs","groupKindFromLabels","labels","pointsToPath","nums","lineToPath","geometryFromTag","w","h","parseSvgString","svg","stripped","viewboxMatch","viewbox","elements","routePathDs","warnings","stack","anon","inRouteContainer","parentStyle","inInteractive","parentMatrix","markNamedChild","findCollector","closeGroup","collected","emitRoute","open","tokenRe","closing","interactiveContainer","nonInteractiveContainer","storeFolder","parentInteractive","matrix","interactive","style","dataName","collector","slugKey","styleFromElement","el","sourceSvgId","layer","viewBoxesEqual","importSvg","parsed","classified","unrecognized","guessed","walkableCount","voidCount","unitCount","viewBoxChanged","isGuessed","entry","isStaticDecor","bbox","diffImport","imported","existing","driftThreshold","existingBySource","e","seen","items","prev","change","prevCx","prevCy","EPS","MIN_CORNER_TURN","EDGE_GAP","TWO_PI","almostSame","add","sub","pointOnCircle","center","radius","angle","uniqueClosedRing","ring","last","filletPolygon","inN","outN","outLen","turn","inD","outD","fillet","curr","incoming","outgoing","cross","dot","absTurn","wedge","tanHalf","desired","need","available","scaleDown","actualR","end","sign","a0","sweepCCW","sweepCW","midCCW","midCW","useCCW","steps","ang","compileGraph","anchors","edges","connectors","graph","createGraph","anchorById","connectorById","nodes","publishedEdges","weight","accessible","conn","pub","findPath","compiled","fromAnchorId","toAnchorId","path","fromNode","toNode","link","data","anchorIds","levelChanges","totalWeight","findNearestAmenityPath","amenityAnchorIds","targetId","compileDocument","input","assignmentByShape","resolve","k","levels","l","level","levelShapes","levelAnchors","normalizePublishedDocument","doc","changed","levelChanged","compareBuildingFloors","isOutdoorLevel","viewerLevelStack","activeLevelId","outdoor","active","floorSwitcherLevels","floorSwitcherDisplayLevels","shouldShowFloorSwitcher","defaultViewerLevelId","viewBoxToBounds","expandBounds","target","boundsFromStackedLevels","baseViewbox","bounds","vb","shapeBounds","unionViewBox","primary","secondary"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Vec2 } from './types';
|
|
2
|
+
/** Drop duplicate consecutive points and a repeated closing vertex. */
|
|
3
|
+
export declare function uniqueClosedRing(points: Vec2[]): Vec2[];
|
|
4
|
+
/**
|
|
5
|
+
* Illustrator Round Corners: replace each real corner with a circular arc
|
|
6
|
+
* tangent to both walls. The arc stays at the corner (never the long way
|
|
7
|
+
* through the store). Shallow wall bends are left alone.
|
|
8
|
+
*/
|
|
9
|
+
export declare function filletPolygon(points: Vec2[], radius: number): Vec2[];
|
|
10
|
+
//# sourceMappingURL=filletPolygon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filletPolygon.d.ts","sourceRoot":"","sources":["../../src/core/filletPolygon.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AA+BtD,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CASvD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,CA6FpE"}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { BBox, ShapeGeometry, Vec2, ViewBox } from '../types';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Mirror points about the middle of a viewbox height.
|
|
4
|
+
*
|
|
5
|
+
* Never call this on stored geometry. Stored geometry keeps SVG user space
|
|
6
|
+
* (Y down) so `paths`, `polygons`, anchors and the designer SVG all agree;
|
|
7
|
+
* the viewer flips once at render. This helper exists only for render-side
|
|
8
|
+
* and ad-hoc conversions.
|
|
9
|
+
*/
|
|
3
10
|
export declare function flipY(points: Vec2[], viewboxHeight: number): Vec2[];
|
|
4
11
|
export declare function distance(a: Vec2, b: Vec2): number;
|
|
5
12
|
export declare function bboxOf(points: Vec2[]): BBox;
|
|
@@ -23,12 +30,42 @@ export declare function nearestPointOnPolyline(point: Vec2, polyline: Vec2[]): {
|
|
|
23
30
|
*/
|
|
24
31
|
export declare function approximateCubic(p0: Vec2, p1: Vec2, p2: Vec2, p3: Vec2, segments?: number): Vec2[];
|
|
25
32
|
export declare function approximateQuadratic(p0: Vec2, p1: Vec2, p2: Vec2, segments?: number): Vec2[];
|
|
33
|
+
/**
|
|
34
|
+
* Flatten an SVG elliptical arc, using the endpoint-to-centre parameterisation
|
|
35
|
+
* of SVG 1.1 appendix F.6.
|
|
36
|
+
*
|
|
37
|
+
* Returns `p0` first, like `approximateCubic`, so callers append `slice(1)`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function approximateArc(p0: Vec2, rx: number, ry: number, xAxisRotationDeg: number, largeArc: boolean, sweep: boolean, p1: Vec2): Vec2[];
|
|
40
|
+
/**
|
|
41
|
+
* Split path data into command letters and numbers.
|
|
42
|
+
*
|
|
43
|
+
* A plain number regex cannot do this: arc flags may be written without any
|
|
44
|
+
* separator, so `a1 1 0 011 1` is legal and means flags `0` then `1` followed
|
|
45
|
+
* by the coordinate `1`. Tracking the argument slot lets the two flag
|
|
46
|
+
* positions of every `A`/`a` group consume exactly one character.
|
|
47
|
+
*/
|
|
48
|
+
export declare function tokenizePathData(d: string): string[];
|
|
26
49
|
/**
|
|
27
50
|
* Parse SVG path `d` into absolute polygon approximations.
|
|
28
|
-
* Supports M/L/H/V/C/Q/S/T/Z (absolute and relative).
|
|
51
|
+
* Supports M/L/H/V/C/Q/S/T/A/Z (absolute and relative).
|
|
52
|
+
*
|
|
53
|
+
* Output stays in the input's coordinate space — deliberately no Y flip, so
|
|
54
|
+
* `paths[].d`, `polygons`, anchors and route geometry never diverge. The
|
|
55
|
+
* viewer applies the single flip at render time.
|
|
56
|
+
*/
|
|
57
|
+
export declare function pathToPolygons(d: string): Vec2[][];
|
|
58
|
+
/**
|
|
59
|
+
* Rows written before the Y-flip removal hold `polygons` mirrored about the
|
|
60
|
+
* viewbox while `paths[].d` stayed in SVG space, which renders the map upside
|
|
61
|
+
* down. `paths` is authoritative, so rebuild `polygons` whenever the two
|
|
62
|
+
* disagree. Comparing only the opening `M` keeps healthy geometry O(1).
|
|
29
63
|
*/
|
|
30
|
-
export declare function
|
|
31
|
-
|
|
64
|
+
export declare function isGeometrySpaceStale(geometry: ShapeGeometry): boolean;
|
|
65
|
+
/** Return geometry with `polygons` rebuilt from `paths` when they disagree. */
|
|
66
|
+
export declare function normalizeGeometrySpace(geometry: ShapeGeometry): ShapeGeometry;
|
|
67
|
+
/** `paths` keeps the original `d`; `polygons` must stay in the same space. */
|
|
68
|
+
export declare function buildGeometryFromPaths(pathDs: string[]): ShapeGeometry;
|
|
32
69
|
export declare function geometryBBox(geometry: ShapeGeometry): BBox;
|
|
33
70
|
export declare function geometryCentroid(geometry: ShapeGeometry): Vec2;
|
|
34
71
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/geometry/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAe,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEhF
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/geometry/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MapHost, MapViewerHost } from './types';
|
|
2
|
+
/** Which library surface a host should mount. `PORTAL` is the staff editor. */
|
|
3
|
+
export declare function mapSurface(host: MapHost): 'editor' | 'viewer';
|
|
4
|
+
/**
|
|
5
|
+
* Public chrome. Mirrors v1 MapBox (`UIComponent` + `SceneComponent`):
|
|
6
|
+
* floors + zoom/reset on every viewer host; amenity icons on WEBSITE
|
|
7
|
+
* (v1 hides them for PORTAL and DISPLAY_APP); kiosk origin only on DISPLAY_APP.
|
|
8
|
+
* Search is v2-owned (v1 MapBox has none) and follows the public directory hosts.
|
|
9
|
+
*/
|
|
10
|
+
export interface ViewerChrome {
|
|
11
|
+
search: boolean;
|
|
12
|
+
amenities: boolean;
|
|
13
|
+
floors: boolean;
|
|
14
|
+
zoomReset: boolean;
|
|
15
|
+
kioskOrigin: boolean;
|
|
16
|
+
fetchDraft: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function viewerChrome(host: MapViewerHost): ViewerChrome;
|
|
19
|
+
export declare function isMapViewerHost(host: MapHost): host is MapViewerHost;
|
|
20
|
+
//# sourceMappingURL=hostChrome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostChrome.d.ts","sourceRoot":"","sources":["../../src/core/hostChrome.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEtD,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAE7D;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB;AAgCD,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,YAAY,CAE9D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,aAAa,CAEpE"}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { BBox, ImportDiff, ImportReport, ShapeGeometry, ShapeKind, ShapeStyle, ViewBox } from '../types';
|
|
2
|
+
import { SvgPresentationStyle } from './svgStyle';
|
|
3
|
+
/** v1 / Illustrator walking-path ids (`route-path`, `route-path-12`). */
|
|
4
|
+
export declare function isRoutePathLabel(label: string): boolean;
|
|
5
|
+
/** Folder that holds walking paths (`ROUTES`, `route-path`, `WAYFINDING`). */
|
|
6
|
+
export declare function isRouteFolderLabel(label: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Outdoor / base imports only persist interactive polygons (+ walkable/void for
|
|
9
|
+
* autoroute). Decoration stays in the live SVG renderer.
|
|
10
|
+
*/
|
|
11
|
+
export declare const IMPORT_PERSISTED_KINDS: readonly ShapeKind[];
|
|
12
|
+
/** Centroid shift (world units) above which a matched shape is flagged `moved`. */
|
|
13
|
+
export declare const IMPORT_DRIFT_THRESHOLD = 8;
|
|
2
14
|
export interface RawSvgElement {
|
|
3
15
|
id: string;
|
|
4
16
|
tag: string;
|
|
@@ -8,20 +20,44 @@ export interface RawSvgElement {
|
|
|
8
20
|
y1?: number;
|
|
9
21
|
x2?: number;
|
|
10
22
|
y2?: number;
|
|
23
|
+
/** True when data-interactive is set or the element is inside an INTERACTIVE group. */
|
|
11
24
|
interactive?: boolean;
|
|
25
|
+
/** Resolved fill/stroke after group inheritance + CSS class inlining. */
|
|
26
|
+
style?: SvgPresentationStyle;
|
|
12
27
|
}
|
|
13
28
|
export interface ParsedSvg {
|
|
14
29
|
viewbox: ViewBox | null;
|
|
15
30
|
elements: RawSvgElement[];
|
|
16
31
|
routePathDs: string[];
|
|
32
|
+
/** Structural problems worth surfacing in the import report. */
|
|
33
|
+
warnings: string[];
|
|
17
34
|
}
|
|
18
35
|
export declare function classifyId(id: string, mode?: 'floor' | 'base'): {
|
|
19
36
|
kind: ShapeKind | null;
|
|
20
37
|
guessed: boolean;
|
|
21
38
|
};
|
|
39
|
+
/** Collapse Illustrator id / data-name punctuation so labels compare as words. */
|
|
40
|
+
export declare function normalizeLayerLabel(label: string): string;
|
|
41
|
+
/** Illustrator / designer NON_INTERACTIVE, NON-INTERACTIVE, "NON INTERACTIVE ITEMS". */
|
|
42
|
+
export declare function isNonInteractiveGroupLabel(label: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* INTERACTIVE, INTERACTIVE_ITEMS, INTERACTIVE-2, data-name="INTERACTIVE ITEMS".
|
|
45
|
+
* Excludes NON_INTERACTIVE* and generated ids like interactive-anon-1.
|
|
46
|
+
*/
|
|
47
|
+
export declare function isInteractiveGroupLabel(label: string): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* STORES, store-layer, UNITS — folder names only.
|
|
50
|
+
* Does not match store-46 / unit-12 (those are leaf stores).
|
|
51
|
+
*/
|
|
52
|
+
export declare function isStoreFolderLabel(label: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Illustrator layer / folder: never emit as a shape, never join descendants into one `d`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function isLayerContainerLabel(label: string): boolean;
|
|
22
57
|
/**
|
|
23
58
|
* Lightweight SVG string parser — no DOM required (works in Node).
|
|
24
|
-
*
|
|
59
|
+
* Scans tags sequentially and tracks `<g>` ancestry so Illustrator folders
|
|
60
|
+
* (INTERACTIVE, STORES, NON_INTERACTIVE*) are never joined into one shape.
|
|
25
61
|
*/
|
|
26
62
|
export declare function parseSvgString(svg: string): ParsedSvg;
|
|
27
63
|
export interface ImportedShapeDraft {
|
|
@@ -32,20 +68,33 @@ export interface ImportedShapeDraft {
|
|
|
32
68
|
sourceSvgId: string;
|
|
33
69
|
style: ShapeStyle;
|
|
34
70
|
}
|
|
35
|
-
export
|
|
71
|
+
export interface ImportSvgOptions {
|
|
72
|
+
/** Previous level viewBox — used to detect artboard changes on re-upload. */
|
|
73
|
+
previousViewbox?: ViewBox | null;
|
|
74
|
+
}
|
|
75
|
+
export declare function importSvg(svg: string, mode?: 'floor' | 'base', options?: ImportSvgOptions): {
|
|
36
76
|
report: ImportReport;
|
|
37
77
|
shapes: ImportedShapeDraft[];
|
|
38
78
|
viewbox: ViewBox | null;
|
|
39
79
|
routePathDs: string[];
|
|
80
|
+
viewBoxChanged: boolean;
|
|
40
81
|
};
|
|
41
82
|
export interface ExistingShapeRef {
|
|
42
83
|
id: number;
|
|
43
84
|
sourceSvgId: string | null;
|
|
44
85
|
kind: ShapeKind;
|
|
45
86
|
key: string;
|
|
87
|
+
/** When set, centroid drift is measured against the new draft. */
|
|
88
|
+
bbox?: BBox | null;
|
|
89
|
+
geometryLocked?: boolean;
|
|
46
90
|
}
|
|
47
91
|
/**
|
|
48
92
|
* Diff newly imported shapes against existing level shapes by source_svg_id.
|
|
93
|
+
* Emits `moved` when a matched id's centroid drifts past IMPORT_DRIFT_THRESHOLD.
|
|
49
94
|
*/
|
|
50
|
-
export declare function diffImport(imported: ImportedShapeDraft[], existing: ExistingShapeRef[], viewbox: ViewBox | null
|
|
95
|
+
export declare function diffImport(imported: ImportedShapeDraft[], existing: ExistingShapeRef[], viewbox: ViewBox | null, options?: {
|
|
96
|
+
driftThreshold?: number;
|
|
97
|
+
}): ImportDiff;
|
|
98
|
+
export { inlineSvgStyles, readPresentationStyle, mergePresentationStyle, } from './svgStyle';
|
|
99
|
+
export { IDENTITY_MATRIX, applyMatrix, isIdentityMatrix, multiplyMatrix, parseTransform, transformPathD, type Matrix2D, } from './svgTransform';
|
|
51
100
|
//# sourceMappingURL=index.d.ts.map
|