@kerros/editor 0.0.0-stage → 0.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +35 -2
- package/dist/SitePlanner.js +1189 -0
- package/dist/SitePlanner.js.map +1 -0
- package/dist/adapters/basemap.js +11 -0
- package/dist/adapters/basemap.js.map +1 -0
- package/dist/adapters/persistence.js +121 -0
- package/dist/adapters/persistence.js.map +1 -0
- package/dist/adapters/status.js +11 -0
- package/dist/adapters/status.js.map +1 -0
- package/dist/adapters/useProjectPersistence.js +56 -0
- package/dist/adapters/useProjectPersistence.js.map +1 -0
- package/dist/components/AiImportPanel.js +635 -0
- package/dist/components/AiImportPanel.js.map +1 -0
- package/dist/components/AnalysisPreview.js +179 -0
- package/dist/components/AnalysisPreview.js.map +1 -0
- package/dist/components/ElevatorPanel.js +120 -0
- package/dist/components/ElevatorPanel.js.map +1 -0
- package/dist/components/Icons.js +57 -0
- package/dist/components/Icons.js.map +1 -0
- package/dist/components/ImportDialog.js +467 -0
- package/dist/components/ImportDialog.js.map +1 -0
- package/dist/components/Inspector.js +1184 -0
- package/dist/components/Inspector.js.map +1 -0
- package/dist/components/NavigatePanel.js +301 -0
- package/dist/components/NavigatePanel.js.map +1 -0
- package/dist/components/NavigationGraph.js +234 -0
- package/dist/components/NavigationGraph.js.map +1 -0
- package/dist/components/StructureExplorer.js +510 -0
- package/dist/components/StructureExplorer.js.map +1 -0
- package/dist/components/StructureView.js +286 -0
- package/dist/components/StructureView.js.map +1 -0
- package/dist/components/controls.js +209 -0
- package/dist/components/controls.js.map +1 -0
- package/dist/components/graphLayout.js +27 -0
- package/dist/components/graphLayout.js.map +1 -0
- package/dist/host.js +175 -0
- package/dist/host.js.map +1 -0
- package/dist/i18n.js +88 -0
- package/dist/i18n.js.map +1 -0
- package/dist/import/analysisPreview.js +41 -0
- package/dist/import/analysisPreview.js.map +1 -0
- package/dist/import/brief.js +29 -0
- package/dist/import/brief.js.map +1 -0
- package/dist/import/checkpoint.js +50 -0
- package/dist/import/checkpoint.js.map +1 -0
- package/dist/import/detect.js +120 -0
- package/dist/import/detect.js.map +1 -0
- package/dist/import/documentSvg.js +49 -0
- package/dist/import/documentSvg.js.map +1 -0
- package/dist/import/instructions.js +20 -0
- package/dist/import/instructions.js.map +1 -0
- package/dist/import/openings.js +61 -0
- package/dist/import/openings.js.map +1 -0
- package/dist/import/planImport.js +233 -0
- package/dist/import/planImport.js.map +1 -0
- package/dist/import/register.js +47 -0
- package/dist/import/register.js.map +1 -0
- package/dist/import/runs.js +67 -0
- package/dist/import/runs.js.map +1 -0
- package/dist/import/session.js +23 -0
- package/dist/import/session.js.map +1 -0
- package/dist/import/types.js +13 -0
- package/dist/import/types.js.map +1 -0
- package/dist/import/usage.js +29 -0
- package/dist/import/usage.js.map +1 -0
- package/dist/import/walls.js +112 -0
- package/dist/import/walls.js.map +1 -0
- package/dist/index.js +178 -0
- package/dist/index.js.map +1 -0
- package/dist/map/CabinMaterials.js +81 -0
- package/dist/map/CabinMaterials.js.map +1 -0
- package/dist/map/CabinMirror.js +43 -0
- package/dist/map/CabinMirror.js.map +1 -0
- package/dist/map/Doors.js +80 -0
- package/dist/map/Doors.js.map +1 -0
- package/dist/map/ElevatorCabin.js +93 -0
- package/dist/map/ElevatorCabin.js.map +1 -0
- package/dist/map/FixtureLights.js +117 -0
- package/dist/map/FixtureLights.js.map +1 -0
- package/dist/map/MapCanvas.js +2161 -0
- package/dist/map/MapCanvas.js.map +1 -0
- package/dist/map/Passenger.js +69 -0
- package/dist/map/Passenger.js.map +1 -0
- package/dist/map/SceneLayer.js +1534 -0
- package/dist/map/SceneLayer.js.map +1 -0
- package/dist/map/UndergroundContext.js +153 -0
- package/dist/map/UndergroundContext.js.map +1 -0
- package/dist/map/ambience.js +194 -0
- package/dist/map/ambience.js.map +1 -0
- package/dist/map/architecture.js +305 -0
- package/dist/map/architecture.js.map +1 -0
- package/dist/map/bathMusic.js +92 -0
- package/dist/map/bathMusic.js.map +1 -0
- package/dist/map/cameraAim.js +33 -0
- package/dist/map/cameraAim.js.map +1 -0
- package/dist/map/elevators.js +56 -0
- package/dist/map/elevators.js.map +1 -0
- package/dist/map/excavation.js +52 -0
- package/dist/map/excavation.js.map +1 -0
- package/dist/map/exteriors.js +25 -0
- package/dist/map/exteriors.js.map +1 -0
- package/dist/map/features.js +218 -0
- package/dist/map/features.js.map +1 -0
- package/dist/map/fences.js +29 -0
- package/dist/map/fences.js.map +1 -0
- package/dist/map/journey.js +112 -0
- package/dist/map/journey.js.map +1 -0
- package/dist/map/levels.js +6 -0
- package/dist/map/levels.js.map +1 -0
- package/dist/map/lighting.js +143 -0
- package/dist/map/lighting.js.map +1 -0
- package/dist/map/loadBasemap.js +26 -0
- package/dist/map/loadBasemap.js.map +1 -0
- package/dist/map/materials.js +183 -0
- package/dist/map/materials.js.map +1 -0
- package/dist/map/poolLighting.js +39 -0
- package/dist/map/poolLighting.js.map +1 -0
- package/dist/map/projection.js +24 -0
- package/dist/map/projection.js.map +1 -0
- package/dist/map/rampGeometry.js +38 -0
- package/dist/map/rampGeometry.js.map +1 -0
- package/dist/map/route.js +107 -0
- package/dist/map/route.js.map +1 -0
- package/dist/map/stairSurfaces.js +115 -0
- package/dist/map/stairSurfaces.js.map +1 -0
- package/dist/map/surfaces.js +136 -0
- package/dist/map/surfaces.js.map +1 -0
- package/dist/map/textures.js +95 -0
- package/dist/map/textures.js.map +1 -0
- package/dist/map/underground.js +34 -0
- package/dist/map/underground.js.map +1 -0
- package/dist/map/walk.js +433 -0
- package/dist/map/walk.js.map +1 -0
- package/dist/map/walkContext.js +46 -0
- package/dist/map/walkContext.js.map +1 -0
- package/dist/map/walkDimensions.js +7 -0
- package/dist/map/walkDimensions.js.map +1 -0
- package/dist/map/walkJourney.js +85 -0
- package/dist/map/walkJourney.js.map +1 -0
- package/dist/map/walkSurfaces.js +106 -0
- package/dist/map/walkSurfaces.js.map +1 -0
- package/dist/map/wallJoins.js +70 -0
- package/dist/map/wallJoins.js.map +1 -0
- package/dist/map/water.js +274 -0
- package/dist/map/water.js.map +1 -0
- package/dist/model/authoring.js +99 -0
- package/dist/model/authoring.js.map +1 -0
- package/dist/model/boundaries.js +548 -0
- package/dist/model/boundaries.js.map +1 -0
- package/dist/model/coverage.js +30 -0
- package/dist/model/coverage.js.map +1 -0
- package/dist/model/document.js +52 -0
- package/dist/model/document.js.map +1 -0
- package/dist/model/doors.js +47 -0
- package/dist/model/doors.js.map +1 -0
- package/dist/model/factory.js +56 -0
- package/dist/model/factory.js.map +1 -0
- package/dist/model/geometry.js +454 -0
- package/dist/model/geometry.js.map +1 -0
- package/dist/model/history.js +29 -0
- package/dist/model/history.js.map +1 -0
- package/dist/model/imports.js +45 -0
- package/dist/model/imports.js.map +1 -0
- package/dist/model/inference.js +182 -0
- package/dist/model/inference.js.map +1 -0
- package/dist/model/materials.js +11 -0
- package/dist/model/materials.js.map +1 -0
- package/dist/model/mutations.js +157 -0
- package/dist/model/mutations.js.map +1 -0
- package/dist/model/navigation.js +275 -0
- package/dist/model/navigation.js.map +1 -0
- package/dist/model/ontology.js +109 -0
- package/dist/model/ontology.js.map +1 -0
- package/dist/model/passages.js +5 -0
- package/dist/model/passages.js.map +1 -0
- package/dist/model/portals.js +42 -0
- package/dist/model/portals.js.map +1 -0
- package/dist/model/precision.js +11 -0
- package/dist/model/precision.js.map +1 -0
- package/dist/model/project.js +31 -0
- package/dist/model/project.js.map +1 -0
- package/dist/model/ramps.js +10 -0
- package/dist/model/ramps.js.map +1 -0
- package/dist/model/roomNavigation.js +87 -0
- package/dist/model/roomNavigation.js.map +1 -0
- package/dist/model/routeClearance.js +72 -0
- package/dist/model/routeClearance.js.map +1 -0
- package/dist/model/spaces.js +104 -0
- package/dist/model/spaces.js.map +1 -0
- package/dist/model/stairGeometry.js +40 -0
- package/dist/model/stairGeometry.js.map +1 -0
- package/dist/model/stairTraversal.js +48 -0
- package/dist/model/stairTraversal.js.map +1 -0
- package/dist/model/topology.js +63 -0
- package/dist/model/topology.js.map +1 -0
- package/dist/model/types.js +35 -0
- package/dist/model/types.js.map +1 -0
- package/dist/model/validate.js +240 -0
- package/dist/model/validate.js.map +1 -0
- package/dist/model/vertical.js +129 -0
- package/dist/model/vertical.js.map +1 -0
- package/dist/model/walls.js +261 -0
- package/dist/model/walls.js.map +1 -0
- package/dist/planner/DrawingDock.js +231 -0
- package/dist/planner/DrawingDock.js.map +1 -0
- package/dist/planner/FloorControls.js +93 -0
- package/dist/planner/FloorControls.js.map +1 -0
- package/dist/planner/MapSettings.js +143 -0
- package/dist/planner/MapSettings.js.map +1 -0
- package/dist/planner/PlannerHelp.js +57 -0
- package/dist/planner/PlannerHelp.js.map +1 -0
- package/dist/planner/ProjectSidebar.js +246 -0
- package/dist/planner/ProjectSidebar.js.map +1 -0
- package/dist/planner/floors.js +18 -0
- package/dist/planner/floors.js.map +1 -0
- package/dist/planner/useDrawingTools.js +341 -0
- package/dist/planner/useDrawingTools.js.map +1 -0
- package/dist/planner/useMapDisplay.js +51 -0
- package/dist/planner/useMapDisplay.js.map +1 -0
- package/dist/planner/usePlannerKeyboard.js +138 -0
- package/dist/planner/usePlannerKeyboard.js.map +1 -0
- package/dist/planner/useReferenceAlignment.js +50 -0
- package/dist/planner/useReferenceAlignment.js.map +1 -0
- package/dist/styles.css +4931 -0
- package/dist/theme/index.js +34 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/types/SitePlanner.d.ts +5 -0
- package/dist/types/adapters/basemap.d.ts +2 -0
- package/dist/types/adapters/persistence.d.ts +29 -0
- package/dist/types/adapters/status.d.ts +4 -0
- package/dist/types/adapters/useProjectPersistence.d.ts +13 -0
- package/dist/types/components/AiImportPanel.d.ts +9 -0
- package/dist/types/components/AnalysisPreview.d.ts +4 -0
- package/dist/types/components/ElevatorPanel.d.ts +18 -0
- package/dist/types/components/Icons.d.ts +8 -0
- package/dist/types/components/ImportDialog.d.ts +42 -0
- package/dist/types/components/Inspector.d.ts +38 -0
- package/dist/types/components/NavigatePanel.d.ts +27 -0
- package/dist/types/components/NavigationGraph.d.ts +10 -0
- package/dist/types/components/StructureExplorer.d.ts +8 -0
- package/dist/types/components/StructureView.d.ts +22 -0
- package/dist/types/components/controls.d.ts +52 -0
- package/dist/types/components/graphLayout.d.ts +9 -0
- package/dist/types/editor/host.d.ts +9 -0
- package/dist/types/editor/index.d.ts +2 -0
- package/dist/types/i18n.d.ts +85 -0
- package/dist/types/import/analysisPreview.d.ts +27 -0
- package/dist/types/import/brief.d.ts +22 -0
- package/dist/types/import/checkpoint.d.ts +49 -0
- package/dist/types/import/detect.d.ts +34 -0
- package/dist/types/import/documentSvg.d.ts +2 -0
- package/dist/types/import/index.d.ts +10 -0
- package/dist/types/import/instructions.d.ts +7 -0
- package/dist/types/import/openings.d.ts +22 -0
- package/dist/types/import/planImport.d.ts +22 -0
- package/dist/types/import/register.d.ts +25 -0
- package/dist/types/import/runs.d.ts +31 -0
- package/dist/types/import/session.d.ts +33 -0
- package/dist/types/import/types.d.ts +56 -0
- package/dist/types/import/usage.d.ts +10 -0
- package/dist/types/import/walls.d.ts +37 -0
- package/dist/types/map/CabinMaterials.d.ts +18 -0
- package/dist/types/map/CabinMirror.d.ts +13 -0
- package/dist/types/map/Doors.d.ts +11 -0
- package/dist/types/map/ElevatorCabin.d.ts +20 -0
- package/dist/types/map/FixtureLights.d.ts +35 -0
- package/dist/types/map/MapCanvas.d.ts +87 -0
- package/dist/types/map/Passenger.d.ts +18 -0
- package/dist/types/map/SceneLayer.d.ts +306 -0
- package/dist/types/map/UndergroundContext.d.ts +18 -0
- package/dist/types/map/ambience.d.ts +29 -0
- package/dist/types/map/architecture.d.ts +8 -0
- package/dist/types/map/bathMusic.d.ts +14 -0
- package/dist/types/map/cameraAim.d.ts +20 -0
- package/dist/types/map/elevators.d.ts +16 -0
- package/dist/types/map/excavation.d.ts +9 -0
- package/dist/types/map/exteriors.d.ts +3 -0
- package/dist/types/map/features.d.ts +33 -0
- package/dist/types/map/fences.d.ts +4 -0
- package/dist/types/map/journey.d.ts +36 -0
- package/dist/types/map/levels.d.ts +4 -0
- package/dist/types/map/lighting.d.ts +103 -0
- package/dist/types/map/loadBasemap.d.ts +4 -0
- package/dist/types/map/materials.d.ts +38 -0
- package/dist/types/map/poolLighting.d.ts +11 -0
- package/dist/types/map/projection.d.ts +9 -0
- package/dist/types/map/rampGeometry.d.ts +8 -0
- package/dist/types/map/route.d.ts +59 -0
- package/dist/types/map/stairSurfaces.d.ts +29 -0
- package/dist/types/map/surfaces.d.ts +36 -0
- package/dist/types/map/textures.d.ts +8 -0
- package/dist/types/map/underground.d.ts +30 -0
- package/dist/types/map/walk.d.ts +232 -0
- package/dist/types/map/walkContext.d.ts +11 -0
- package/dist/types/map/walkDimensions.d.ts +5 -0
- package/dist/types/map/walkJourney.d.ts +33 -0
- package/dist/types/map/walkSurfaces.d.ts +27 -0
- package/dist/types/map/wallJoins.d.ts +6 -0
- package/dist/types/map/water.d.ts +12 -0
- package/dist/types/model/authoring.d.ts +38 -0
- package/dist/types/model/boundaries.d.ts +41 -0
- package/dist/types/model/coverage.d.ts +8 -0
- package/dist/types/model/document.d.ts +9 -0
- package/dist/types/model/doors.d.ts +19 -0
- package/dist/types/model/factory.d.ts +5 -0
- package/dist/types/model/geometry.d.ts +99 -0
- package/dist/types/model/history.d.ts +10 -0
- package/dist/types/model/host.d.ts +154 -0
- package/dist/types/model/imports.d.ts +7 -0
- package/dist/types/model/inference.d.ts +46 -0
- package/dist/types/model/live.d.ts +60 -0
- package/dist/types/model/materials.d.ts +28 -0
- package/dist/types/model/mutations.d.ts +178 -0
- package/dist/types/model/navigation.d.ts +70 -0
- package/dist/types/model/ontology.d.ts +43 -0
- package/dist/types/model/passages.d.ts +2 -0
- package/dist/types/model/portals.d.ts +9 -0
- package/dist/types/model/precision.d.ts +11 -0
- package/dist/types/model/project.d.ts +8 -0
- package/dist/types/model/ramps.d.ts +7 -0
- package/dist/types/model/roomNavigation.d.ts +15 -0
- package/dist/types/model/routeClearance.d.ts +11 -0
- package/dist/types/model/spaces.d.ts +46 -0
- package/dist/types/model/stairGeometry.d.ts +27 -0
- package/dist/types/model/stairTraversal.d.ts +8 -0
- package/dist/types/model/topology.d.ts +14 -0
- package/dist/types/model/types.d.ts +369 -0
- package/dist/types/model/validate.d.ts +38 -0
- package/dist/types/model/vertical.d.ts +145 -0
- package/dist/types/model/walls.d.ts +71 -0
- package/dist/types/planner/DrawingDock.d.ts +16 -0
- package/dist/types/planner/FloorControls.d.ts +17 -0
- package/dist/types/planner/MapSettings.d.ts +16 -0
- package/dist/types/planner/PlannerHelp.d.ts +3 -0
- package/dist/types/planner/ProjectSidebar.d.ts +32 -0
- package/dist/types/planner/floors.d.ts +3 -0
- package/dist/types/planner/types.d.ts +3 -0
- package/dist/types/planner/useDrawingTools.d.ts +52 -0
- package/dist/types/planner/useMapDisplay.d.ts +29 -0
- package/dist/types/planner/usePlannerKeyboard.d.ts +18 -0
- package/dist/types/planner/useReferenceAlignment.d.ts +30 -0
- package/dist/types/schema/index.d.ts +25 -0
- package/dist/types/theme/index.d.ts +55 -0
- package/package.json +52 -4
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import { jsxs as a, jsx as e, Fragment as E } from "react/jsx-runtime";
|
|
2
|
+
import { lazy as ce, useState as p, useEffect as I, useRef as de, Suspense as pe } from "react";
|
|
3
|
+
import { Check as X, UploadCloud as he, ArrowRight as Q, X as me, FileImage as ue, FileJson as fe } from "lucide-react";
|
|
4
|
+
import { uid as H } from "../model/types.js";
|
|
5
|
+
import "polygon-clipping";
|
|
6
|
+
import { blobDataUrl as ge, importProject as be } from "../model/document.js";
|
|
7
|
+
import { importFootprints as we } from "../model/imports.js";
|
|
8
|
+
import { detectLayers as ye, LAYER_ROLES as L, layerPattern as Ne } from "../import/detect.js";
|
|
9
|
+
import { Modal as ve } from "./controls.js";
|
|
10
|
+
const ke = ce(() => import("./AiImportPanel.js").then((l) => ({ default: l.AiImportPanel }))), z = {
|
|
11
|
+
exteriorFace: "Outer wall face",
|
|
12
|
+
interiorFace: "Inner wall face",
|
|
13
|
+
partitionFaces: "Partition faces",
|
|
14
|
+
doors: "Doors",
|
|
15
|
+
windows: "Windows",
|
|
16
|
+
labels: "Room labels",
|
|
17
|
+
stairs: ""
|
|
18
|
+
}, Ce = (l, o) => {
|
|
19
|
+
const c = l.layers.find((m) => m.layer === o);
|
|
20
|
+
return c ? `${c.entities} entities · ${Object.keys(c.types).join(" ")}${c.width > 0 ? ` · ${c.width.toFixed(1)}×${c.height.toFixed(1)} m` : ""}` : o;
|
|
21
|
+
}, V = "kerros:layer-profiles", Se = () => {
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(localStorage.getItem(V) ?? "{}");
|
|
24
|
+
} catch {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
function Pe({
|
|
29
|
+
detection: l,
|
|
30
|
+
roles: o,
|
|
31
|
+
onRole: c
|
|
32
|
+
}) {
|
|
33
|
+
const [m, P] = p(l.missing.length > 0), [k, f] = p(Se), [C, b] = p(""), N = () => {
|
|
34
|
+
const n = C.trim();
|
|
35
|
+
if (!n) return;
|
|
36
|
+
const r = { ...k, [n]: o };
|
|
37
|
+
f(r);
|
|
38
|
+
try {
|
|
39
|
+
localStorage.setItem(V, JSON.stringify(r));
|
|
40
|
+
} catch {
|
|
41
|
+
}
|
|
42
|
+
b("");
|
|
43
|
+
}, S = (n) => {
|
|
44
|
+
var r;
|
|
45
|
+
for (const d of L) c(d, ((r = k[n]) == null ? void 0 : r[d]) ?? null);
|
|
46
|
+
}, w = L.filter((n) => !o[n]);
|
|
47
|
+
return /* @__PURE__ */ a("section", { className: "layer-picker", children: [
|
|
48
|
+
/* @__PURE__ */ a("button", { className: "layer-picker-head", onClick: () => P(!m), children: [
|
|
49
|
+
/* @__PURE__ */ a("span", { children: [
|
|
50
|
+
/* @__PURE__ */ a("strong", { children: [
|
|
51
|
+
l.layers.length,
|
|
52
|
+
" layers"
|
|
53
|
+
] }),
|
|
54
|
+
w.length ? /* @__PURE__ */ a("small", { className: "warn", children: [
|
|
55
|
+
w.map((n) => z[n]).join(", "),
|
|
56
|
+
" not found"
|
|
57
|
+
] }) : /* @__PURE__ */ e("small", { children: "every role matched a layer" })
|
|
58
|
+
] }),
|
|
59
|
+
/* @__PURE__ */ e(Q, { size: 15, style: { transform: m ? "rotate(90deg)" : "none" } })
|
|
60
|
+
] }),
|
|
61
|
+
m && /* @__PURE__ */ a(E, { children: [
|
|
62
|
+
/* @__PURE__ */ e("p", { className: "helper", children: "Read from the geometry, not the layer names — a door swing is an arc whatever the layer is called. Correct anything it got wrong. One layer may hold both wall faces, which is how some offices draw them; pick it for both." }),
|
|
63
|
+
/* @__PURE__ */ e("div", { className: "layer-rows", children: L.map((n) => /* @__PURE__ */ a("div", { className: `layer-row ${o[n] ? "assigned" : "unset"}`, children: [
|
|
64
|
+
/* @__PURE__ */ a("span", { className: "layer-name", children: [
|
|
65
|
+
z[n],
|
|
66
|
+
/* @__PURE__ */ e("small", { children: o[n] ? Ce(l, o[n]) : "not found" })
|
|
67
|
+
] }),
|
|
68
|
+
/* @__PURE__ */ a(
|
|
69
|
+
"select",
|
|
70
|
+
{
|
|
71
|
+
"aria-label": z[n],
|
|
72
|
+
value: o[n] ?? "",
|
|
73
|
+
onChange: (r) => c(n, r.target.value || null),
|
|
74
|
+
children: [
|
|
75
|
+
/* @__PURE__ */ e("option", { value: "", children: "—" }),
|
|
76
|
+
l.layers.map((r) => /* @__PURE__ */ e("option", { value: r.layer, children: r.layer }, r.layer))
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
] }, n)) }),
|
|
81
|
+
/* @__PURE__ */ a("div", { className: "layer-profiles", children: [
|
|
82
|
+
/* @__PURE__ */ e(
|
|
83
|
+
"input",
|
|
84
|
+
{
|
|
85
|
+
"aria-label": "Profile name",
|
|
86
|
+
placeholder: "Save as… (e.g. the office's name)",
|
|
87
|
+
value: C,
|
|
88
|
+
onChange: (n) => b(n.target.value)
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
/* @__PURE__ */ e("button", { className: "button secondary small", onClick: N, disabled: !C.trim(), children: "Save" }),
|
|
92
|
+
Object.keys(k).map((n) => /* @__PURE__ */ e("button", { className: "button secondary small", onClick: () => S(n), children: n }, n))
|
|
93
|
+
] })
|
|
94
|
+
] })
|
|
95
|
+
] });
|
|
96
|
+
}
|
|
97
|
+
function ze({
|
|
98
|
+
project: l,
|
|
99
|
+
floorId: o,
|
|
100
|
+
assets: c,
|
|
101
|
+
onClose: m,
|
|
102
|
+
onProject: P,
|
|
103
|
+
onAiProject: k,
|
|
104
|
+
onAiRunningChange: f,
|
|
105
|
+
onFootprints: C,
|
|
106
|
+
onDrawing: b,
|
|
107
|
+
onPlan: N,
|
|
108
|
+
onOrigin: S,
|
|
109
|
+
importProjections: w = [],
|
|
110
|
+
aiImport: n,
|
|
111
|
+
pdfDrawing: r,
|
|
112
|
+
mode: d = "reference"
|
|
113
|
+
}) {
|
|
114
|
+
var q;
|
|
115
|
+
const [h, Z] = p(
|
|
116
|
+
d === "plan" ? n ? "ai" : "plan" : "drawing"
|
|
117
|
+
), [i, F] = p(null), [B, ee] = p(0), [W, te] = p("building"), [G, ae] = p(o), [$, re] = p(String(l.origin[2] ?? 0)), [j, ne] = p(1), [O, R] = p(!1), [M, D] = p(""), K = de(null), [x, le] = p(!1);
|
|
118
|
+
I(() => (f == null || f(x), () => f == null ? void 0 : f(!1)), [x, f]);
|
|
119
|
+
const [v, A] = p(null), [T, U] = p({});
|
|
120
|
+
I(() => {
|
|
121
|
+
if (h !== "plan" || !i) return A(null);
|
|
122
|
+
let t = !0;
|
|
123
|
+
return (async () => {
|
|
124
|
+
try {
|
|
125
|
+
const s = JSON.parse(await i.text()), g = Array.isArray(s) ? s : s.entities ?? [];
|
|
126
|
+
if (!t || !Array.isArray(g)) return;
|
|
127
|
+
const u = ye(g);
|
|
128
|
+
A(u), U(
|
|
129
|
+
Object.fromEntries(u.layers.filter((y) => y.role).map((y) => [y.role, y.layer]))
|
|
130
|
+
);
|
|
131
|
+
} catch {
|
|
132
|
+
t && A(null);
|
|
133
|
+
}
|
|
134
|
+
})(), () => {
|
|
135
|
+
t = !1;
|
|
136
|
+
};
|
|
137
|
+
}, [i, h]);
|
|
138
|
+
async function ie() {
|
|
139
|
+
var t;
|
|
140
|
+
if (i) {
|
|
141
|
+
R(!0), D("");
|
|
142
|
+
try {
|
|
143
|
+
if (i.size > 50 * 1024 * 1024) throw new Error("Choose a file smaller than 50 MB.");
|
|
144
|
+
if (h === "project") await P(await be(await i.text(), c));
|
|
145
|
+
else if (h === "plan") {
|
|
146
|
+
const s = JSON.parse(await i.text()), g = Array.isArray(s) ? s : s.entities ?? null;
|
|
147
|
+
if (!Array.isArray(g))
|
|
148
|
+
throw new Error("Expected plan-entity JSON (see scripts/plan-import/extract.mjs).");
|
|
149
|
+
const u = Number($);
|
|
150
|
+
Number.isFinite(u) && u !== (l.origin[2] ?? 0) && (S == null || S(u));
|
|
151
|
+
const y = Object.entries(T).filter(([, J]) => J), se = y.length ? {
|
|
152
|
+
...v == null ? void 0 : v.suggested,
|
|
153
|
+
...Object.fromEntries(y.map(([J, oe]) => [J, Ne(oe)]))
|
|
154
|
+
} : v == null ? void 0 : v.suggested;
|
|
155
|
+
N == null || N(g, G, se);
|
|
156
|
+
} else if (h === "footprint")
|
|
157
|
+
C(
|
|
158
|
+
we(JSON.parse(await i.text()), l, W, (t = w[B - 1]) == null ? void 0 : t.toLngLat)
|
|
159
|
+
);
|
|
160
|
+
else {
|
|
161
|
+
let s = i;
|
|
162
|
+
if (i.type === "application/pdf" || i.name.toLowerCase().endsWith(".pdf")) {
|
|
163
|
+
if (!r)
|
|
164
|
+
throw new Error(
|
|
165
|
+
"PDF conversion requires a connected import backend. Start make up or use an image drawing."
|
|
166
|
+
);
|
|
167
|
+
s = await r.render(i, j);
|
|
168
|
+
}
|
|
169
|
+
if (!["image/png", "image/jpeg", "image/webp"].includes(s.type))
|
|
170
|
+
throw new Error("Use a PNG, JPEG, WebP, or PDF drawing.");
|
|
171
|
+
const g = await createImageBitmap(s), u = g.width, y = g.height;
|
|
172
|
+
g.close(), await b({
|
|
173
|
+
blob: s,
|
|
174
|
+
name: i.name + (i.name.endsWith(".pdf") ? ` · page ${j}` : ""),
|
|
175
|
+
width: u,
|
|
176
|
+
height: y
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
m();
|
|
180
|
+
} catch (s) {
|
|
181
|
+
D(s.message);
|
|
182
|
+
} finally {
|
|
183
|
+
R(!1);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const Y = /* @__PURE__ */ e("div", { className: "import-tabs", children: (d === "plan" ? [...n ? ["ai"] : [], "plan"] : ["drawing", "footprint", "project"]).map((t) => /* @__PURE__ */ a(
|
|
188
|
+
"button",
|
|
189
|
+
{
|
|
190
|
+
className: h === t ? "active" : "",
|
|
191
|
+
disabled: x || O,
|
|
192
|
+
onClick: () => {
|
|
193
|
+
Z(t), F(null), D("");
|
|
194
|
+
},
|
|
195
|
+
children: [
|
|
196
|
+
t === "drawing" ? /* @__PURE__ */ e(ue, { size: 19 }) : /* @__PURE__ */ e(fe, { size: 19 }),
|
|
197
|
+
t === "drawing" ? "Floor drawing" : t === "footprint" ? "GeoJSON" : t === "plan" ? "CAD plan" : t === "ai" ? "AI import" : "Project"
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
t
|
|
201
|
+
)) }), _ = /* @__PURE__ */ a(E, { children: [
|
|
202
|
+
d !== "plan" && Y,
|
|
203
|
+
h === "ai" && n ? /* @__PURE__ */ e(
|
|
204
|
+
pe,
|
|
205
|
+
{
|
|
206
|
+
fallback: /* @__PURE__ */ e("p", { className: "helper", role: "status", children: "Loading AI import…" }),
|
|
207
|
+
children: /* @__PURE__ */ e(
|
|
208
|
+
ke,
|
|
209
|
+
{
|
|
210
|
+
adapter: n,
|
|
211
|
+
assets: c,
|
|
212
|
+
onProject: k ?? P,
|
|
213
|
+
onRunningChange: le,
|
|
214
|
+
currentProject: l
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
) : /* @__PURE__ */ a(E, { children: [
|
|
219
|
+
/* @__PURE__ */ a(
|
|
220
|
+
"button",
|
|
221
|
+
{
|
|
222
|
+
className: "dropzone",
|
|
223
|
+
onClick: () => {
|
|
224
|
+
var t;
|
|
225
|
+
return (t = K.current) == null ? void 0 : t.click();
|
|
226
|
+
},
|
|
227
|
+
onDragOver: (t) => t.preventDefault(),
|
|
228
|
+
onDrop: (t) => {
|
|
229
|
+
t.preventDefault(), F(t.dataTransfer.files[0] ?? null);
|
|
230
|
+
},
|
|
231
|
+
children: [
|
|
232
|
+
i ? /* @__PURE__ */ e(X, { size: 30 }) : /* @__PURE__ */ e(he, { size: 32 }),
|
|
233
|
+
/* @__PURE__ */ e("strong", { children: (i == null ? void 0 : i.name) ?? "Drop a file here, or browse" }),
|
|
234
|
+
/* @__PURE__ */ e("span", { children: h === "drawing" ? "PNG, JPEG, WebP or PDF · up to 50 MB" : "JSON or GeoJSON · up to 50 MB" })
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
/* @__PURE__ */ e(
|
|
239
|
+
"input",
|
|
240
|
+
{
|
|
241
|
+
ref: K,
|
|
242
|
+
type: "file",
|
|
243
|
+
hidden: !0,
|
|
244
|
+
accept: h === "drawing" ? ".png,.jpg,.jpeg,.webp,.pdf" : ".json,.geojson",
|
|
245
|
+
onChange: (t) => {
|
|
246
|
+
var s;
|
|
247
|
+
return F(((s = t.target.files) == null ? void 0 : s[0]) ?? null);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
),
|
|
251
|
+
h === "drawing" && /* @__PURE__ */ a("p", { className: "helper", children: [
|
|
252
|
+
"Your drawing will be added to ",
|
|
253
|
+
((q = l.floors.find((t) => t.id === o)) == null ? void 0 : q.name) ?? "Outdoor site",
|
|
254
|
+
". Match two points to position it on the map, or calibrate a known distance."
|
|
255
|
+
] }),
|
|
256
|
+
h === "plan" && /* @__PURE__ */ a(E, { children: [
|
|
257
|
+
/* @__PURE__ */ a("label", { className: "field", children: [
|
|
258
|
+
/* @__PURE__ */ e("span", { children: "Target floor" }),
|
|
259
|
+
/* @__PURE__ */ a("select", { value: G ?? "", onChange: (t) => ae(t.target.value || null), children: [
|
|
260
|
+
l.floors.map((t) => /* @__PURE__ */ e("option", { value: t.id, children: t.name }, t.id)),
|
|
261
|
+
/* @__PURE__ */ e("option", { value: "", children: "Outdoor site" })
|
|
262
|
+
] })
|
|
263
|
+
] }),
|
|
264
|
+
/* @__PURE__ */ a("p", { className: "helper", children: [
|
|
265
|
+
"Walls, rooms, doors and windows will be built on the chosen floor — repeat per floor for a multi-storey building. Produce the JSON from a DWG with",
|
|
266
|
+
" ",
|
|
267
|
+
/* @__PURE__ */ e("code", { children: "scripts/plan-import/extract.mjs --expand --units m" }),
|
|
268
|
+
"."
|
|
269
|
+
] }),
|
|
270
|
+
v && /* @__PURE__ */ e(
|
|
271
|
+
Pe,
|
|
272
|
+
{
|
|
273
|
+
detection: v,
|
|
274
|
+
roles: T,
|
|
275
|
+
onRole: (t, s) => U((g) => {
|
|
276
|
+
const u = { ...g };
|
|
277
|
+
return s ? u[t] = s : delete u[t], u;
|
|
278
|
+
})
|
|
279
|
+
}
|
|
280
|
+
),
|
|
281
|
+
/* @__PURE__ */ a("label", { className: "field", children: [
|
|
282
|
+
/* @__PURE__ */ e("span", { children: "Site bearing" }),
|
|
283
|
+
/* @__PURE__ */ e(
|
|
284
|
+
"input",
|
|
285
|
+
{
|
|
286
|
+
type: "number",
|
|
287
|
+
"aria-label": "Site bearing",
|
|
288
|
+
step: 0.1,
|
|
289
|
+
min: -360,
|
|
290
|
+
max: 360,
|
|
291
|
+
value: $,
|
|
292
|
+
onChange: (t) => re(t.target.value)
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
] }),
|
|
296
|
+
/* @__PURE__ */ e("p", { className: "helper", children: "A drawing is square to its sheet, not to the world, so an imported plan lands on the site's current heading. Degrees clockwise from north; adjustable afterwards under Site anchor." })
|
|
297
|
+
] }),
|
|
298
|
+
h === "drawing" && (i == null ? void 0 : i.name.toLowerCase().endsWith(".pdf")) && /* @__PURE__ */ a("label", { className: "field", children: [
|
|
299
|
+
/* @__PURE__ */ e("span", { children: "PDF page" }),
|
|
300
|
+
/* @__PURE__ */ e(
|
|
301
|
+
"input",
|
|
302
|
+
{
|
|
303
|
+
type: "number",
|
|
304
|
+
"aria-label": "PDF page",
|
|
305
|
+
min: 1,
|
|
306
|
+
value: j,
|
|
307
|
+
onChange: (t) => ne(Number(t.target.value))
|
|
308
|
+
}
|
|
309
|
+
)
|
|
310
|
+
] }),
|
|
311
|
+
h === "footprint" && /* @__PURE__ */ a("div", { className: "field-grid", children: [
|
|
312
|
+
/* @__PURE__ */ a("label", { className: "field", children: [
|
|
313
|
+
/* @__PURE__ */ e("span", { children: "Source coordinates" }),
|
|
314
|
+
/* @__PURE__ */ a("select", { value: B, onChange: (t) => ee(Number(t.target.value)), children: [
|
|
315
|
+
/* @__PURE__ */ e("option", { value: 0, children: "WGS84 · longitude / latitude" }),
|
|
316
|
+
w.map((t, s) => /* @__PURE__ */ e("option", { value: s + 1, children: t.label }, t.label))
|
|
317
|
+
] })
|
|
318
|
+
] }),
|
|
319
|
+
/* @__PURE__ */ a("label", { className: "field", children: [
|
|
320
|
+
/* @__PURE__ */ e("span", { children: "Import as" }),
|
|
321
|
+
/* @__PURE__ */ a("select", { value: W, onChange: (t) => te(t.target.value), children: [
|
|
322
|
+
/* @__PURE__ */ e("option", { value: "building", children: "Building footprint" }),
|
|
323
|
+
/* @__PURE__ */ e("option", { value: "parcel", children: "Parcel boundary" })
|
|
324
|
+
] })
|
|
325
|
+
] })
|
|
326
|
+
] }),
|
|
327
|
+
h === "project" && /* @__PURE__ */ e("p", { className: "helper", children: "Open a portable Kerros JSON export as a new project, including its reference images." }),
|
|
328
|
+
M && /* @__PURE__ */ e("p", { className: "form-error", role: "alert", children: M }),
|
|
329
|
+
/* @__PURE__ */ a("footer", { children: [
|
|
330
|
+
/* @__PURE__ */ e("button", { className: "button secondary", onClick: m, children: "Cancel" }),
|
|
331
|
+
/* @__PURE__ */ a("button", { className: "button primary", disabled: !i || O, onClick: ie, children: [
|
|
332
|
+
O ? "Preparing…" : h === "drawing" ? "Align drawing" : "Import",
|
|
333
|
+
/* @__PURE__ */ e(Q, { size: 16 })
|
|
334
|
+
] })
|
|
335
|
+
] })
|
|
336
|
+
] })
|
|
337
|
+
] });
|
|
338
|
+
return d === "plan" ? /* @__PURE__ */ a("aside", { className: "inspector plan-import-panel", "aria-label": "Plan import", onKeyDown: (t) => t.stopPropagation(), children: [
|
|
339
|
+
/* @__PURE__ */ a("header", { className: "inspector-top", children: [
|
|
340
|
+
/* @__PURE__ */ e("h2", { children: "Plan import" }),
|
|
341
|
+
/* @__PURE__ */ e(
|
|
342
|
+
"button",
|
|
343
|
+
{
|
|
344
|
+
className: "icon-button",
|
|
345
|
+
"aria-label": "Close plan import",
|
|
346
|
+
title: x ? "Hide sidebar; import keeps running" : "Close plan import",
|
|
347
|
+
disabled: O,
|
|
348
|
+
onClick: m,
|
|
349
|
+
children: /* @__PURE__ */ e(me, { size: 20 })
|
|
350
|
+
}
|
|
351
|
+
)
|
|
352
|
+
] }),
|
|
353
|
+
Y,
|
|
354
|
+
/* @__PURE__ */ e("div", { className: h === "ai" ? "ai-import-shell" : "inspector-scroll", children: _ })
|
|
355
|
+
] }) : /* @__PURE__ */ e(
|
|
356
|
+
ve,
|
|
357
|
+
{
|
|
358
|
+
title: "Reference drawings and files",
|
|
359
|
+
subtitle: "Align a drawing for tracing, add site geometry, or open a saved project.",
|
|
360
|
+
onClose: m,
|
|
361
|
+
children: _
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
function Ie({
|
|
366
|
+
drawing: l,
|
|
367
|
+
mapPoints: o,
|
|
368
|
+
imagePoints: c,
|
|
369
|
+
setImagePoints: m,
|
|
370
|
+
onCancel: P,
|
|
371
|
+
onPreview: k,
|
|
372
|
+
onConfirm: f,
|
|
373
|
+
onKnownDistance: C,
|
|
374
|
+
preview: b
|
|
375
|
+
}) {
|
|
376
|
+
const [N, S] = p(""), [w, n] = p(10);
|
|
377
|
+
return I(() => {
|
|
378
|
+
let r = !0;
|
|
379
|
+
return ge(l.blob).then((d) => {
|
|
380
|
+
r && S(d);
|
|
381
|
+
}), () => {
|
|
382
|
+
r = !1;
|
|
383
|
+
};
|
|
384
|
+
}, [l.blob]), /* @__PURE__ */ a("aside", { className: "alignment-panel", children: [
|
|
385
|
+
/* @__PURE__ */ a("div", { className: "panel-heading", children: [
|
|
386
|
+
/* @__PURE__ */ e("span", { className: "eyebrow", children: "REFERENCE DRAWING" }),
|
|
387
|
+
/* @__PURE__ */ e("h2", { children: "Align your drawing" }),
|
|
388
|
+
/* @__PURE__ */ e("p", { children: c.length < 2 ? "1. Pick two recognizable points in this drawing." : o.length < 2 ? "2. Click the same points on the map, in the same order." : b ? "3. Check the overlay on the map, then confirm." : "3. Preview the alignment before saving." })
|
|
389
|
+
] }),
|
|
390
|
+
/* @__PURE__ */ a(
|
|
391
|
+
"div",
|
|
392
|
+
{
|
|
393
|
+
className: "alignment-image",
|
|
394
|
+
onClick: (r) => {
|
|
395
|
+
if (c.length >= 2 || b) return;
|
|
396
|
+
const d = r.currentTarget.getBoundingClientRect();
|
|
397
|
+
m([
|
|
398
|
+
...c,
|
|
399
|
+
[
|
|
400
|
+
(r.clientX - d.left) / d.width * l.width,
|
|
401
|
+
(r.clientY - d.top) / d.height * l.height
|
|
402
|
+
]
|
|
403
|
+
]);
|
|
404
|
+
},
|
|
405
|
+
children: [
|
|
406
|
+
N && /* @__PURE__ */ e("img", { src: N, alt: "Architectural drawing to align" }),
|
|
407
|
+
c.map((r, d) => /* @__PURE__ */ e("b", { style: { left: `${r[0] / l.width * 100}%`, top: `${r[1] / l.height * 100}%` }, children: d + 1 }, d))
|
|
408
|
+
]
|
|
409
|
+
}
|
|
410
|
+
),
|
|
411
|
+
/* @__PURE__ */ e("div", { className: "alignment-progress", children: [0, 1].map((r) => /* @__PURE__ */ a("span", { className: o[r] ? "done" : "", children: [
|
|
412
|
+
o[r] ? /* @__PURE__ */ e(X, { size: 14 }) : r + 1,
|
|
413
|
+
" Reference point ",
|
|
414
|
+
r + 1
|
|
415
|
+
] }, r)) }),
|
|
416
|
+
/* @__PURE__ */ e("button", { className: "text-button", onClick: () => m([]), children: "Reset reference points" }),
|
|
417
|
+
/* @__PURE__ */ a("div", { className: "known-distance", children: [
|
|
418
|
+
/* @__PURE__ */ e("strong", { children: "Have a dimension instead?" }),
|
|
419
|
+
/* @__PURE__ */ e("p", { children: "Select two image points and enter their real distance. Place and rotate the overlay using its properties afterward." }),
|
|
420
|
+
/* @__PURE__ */ a("label", { className: "field", children: [
|
|
421
|
+
/* @__PURE__ */ e("span", { children: "Known distance (m)" }),
|
|
422
|
+
/* @__PURE__ */ e("input", { type: "number", min: 0.01, value: w, onChange: (r) => n(Number(r.target.value)) })
|
|
423
|
+
] }),
|
|
424
|
+
/* @__PURE__ */ e(
|
|
425
|
+
"button",
|
|
426
|
+
{
|
|
427
|
+
className: "button secondary",
|
|
428
|
+
disabled: c.length !== 2 || w <= 0,
|
|
429
|
+
onClick: () => C(w),
|
|
430
|
+
children: "Calibrate distance"
|
|
431
|
+
}
|
|
432
|
+
)
|
|
433
|
+
] }),
|
|
434
|
+
/* @__PURE__ */ a("div", { className: "alignment-actions", children: [
|
|
435
|
+
/* @__PURE__ */ e("button", { className: "button secondary", onClick: P, children: "Cancel" }),
|
|
436
|
+
/* @__PURE__ */ e(
|
|
437
|
+
"button",
|
|
438
|
+
{
|
|
439
|
+
className: "button primary",
|
|
440
|
+
disabled: c.length !== 2 || o.length !== 2,
|
|
441
|
+
onClick: b ? f : k,
|
|
442
|
+
children: b ? "Confirm alignment" : "Preview"
|
|
443
|
+
}
|
|
444
|
+
)
|
|
445
|
+
] })
|
|
446
|
+
] });
|
|
447
|
+
}
|
|
448
|
+
const Be = (l, o) => ({
|
|
449
|
+
id: H(),
|
|
450
|
+
floorId: o,
|
|
451
|
+
assetId: H(),
|
|
452
|
+
name: l.name,
|
|
453
|
+
width: l.width,
|
|
454
|
+
height: l.height,
|
|
455
|
+
origin: [-29, 18],
|
|
456
|
+
scale: 58 / l.width,
|
|
457
|
+
rotation: 0,
|
|
458
|
+
opacity: 0.65,
|
|
459
|
+
visible: !0,
|
|
460
|
+
locked: !1
|
|
461
|
+
});
|
|
462
|
+
export {
|
|
463
|
+
Ie as AlignmentPanel,
|
|
464
|
+
ze as ImportDialog,
|
|
465
|
+
Be as makeDrawing
|
|
466
|
+
};
|
|
467
|
+
//# sourceMappingURL=ImportDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImportDialog.js","sources":["../../../../src/components/ImportDialog.tsx"],"sourcesContent":["import { lazy, Suspense, useEffect, useRef, useState } from 'react';\nimport { FileImage, FileJson, UploadCloud, ArrowRight, Check, X } from 'lucide-react';\nimport type { AssetRepository, Drawing, Point, ProjectDocument } from '../model/types';\nimport type { AiImportAdapter, ImportProjection, PdfDrawingAdapter } from '../model/host';\nimport { uid } from '../model/types';\nimport { blobDataUrl, importProject } from '../adapters/persistence';\nimport { importFootprints } from '../model/imports';\nimport type { PlanEntity } from '../import/planImport';\nimport type { PlanLayerMap } from '../import/types';\nimport { detectLayers, layerPattern, LAYER_ROLES, type LayerDetection, type LayerRole } from '../import/detect';\nimport { Modal } from './controls';\nconst AiImportPanel = lazy(() => import('./AiImportPanel').then(m => ({ default: m.AiImportPanel })));\n\nexport interface PreparedDrawing {\n blob: Blob;\n name: string;\n width: number;\n height: number;\n}\nconst ROLE_LABELS: Record<LayerRole, string> = {\n exteriorFace: 'Outer wall face',\n interiorFace: 'Inner wall face',\n partitionFaces: 'Partition faces',\n doors: 'Doors',\n windows: 'Windows',\n labels: 'Room labels',\n stairs: '',\n};\n/** What a layer looks like, for the line under a role's name. */\nconst described = (detection: LayerDetection, layer: string) => {\n const r = detection.layers.find(x => x.layer === layer);\n if (!r) return layer;\n return `${r.entities} entities · ${Object.keys(r.types).join(' ')}${r.width > 0 ? ` · ${r.width.toFixed(1)}×${r.height.toFixed(1)} m` : ''}`;\n};\nconst PROFILES_KEY = 'kerros:layer-profiles';\ntype Profiles = Record<string, Partial<Record<LayerRole, string>>>;\nconst readProfiles = (): Profiles => {\n try {\n return JSON.parse(localStorage.getItem(PROFILES_KEY) ?? '{}') as Profiles;\n } catch {\n return {}; // storage blocked or corrupt — an unsaved mapping still imports fine\n }\n};\n\n/** The layer census, with the role each layer was read as and a way to correct it.\n *\n * Detection is good at doors, windows, labels and partitions and can be wrong about which pair of\n * lines is the wall — and on a drawing that has no separate face layers at all it finds no pair and\n * says so. Either way the drawing is right here to be looked at, so the fix is a dropdown rather\n * than a failed import and a puzzled reread of the manual. */\nfunction LayerPicker({\n detection,\n roles,\n onRole,\n}: {\n detection: LayerDetection;\n roles: Partial<Record<LayerRole, string>>;\n onRole: (role: LayerRole, layer: string | null) => void;\n}) {\n const [open, setOpen] = useState(detection.missing.length > 0);\n const [profiles, setProfiles] = useState<Profiles>(readProfiles);\n const [profileName, setProfileName] = useState('');\n const save = () => {\n const name = profileName.trim();\n if (!name) return;\n const next = { ...profiles, [name]: roles };\n setProfiles(next);\n try {\n localStorage.setItem(PROFILES_KEY, JSON.stringify(next));\n } catch {\n /* nothing to do: the mapping still applies to this import */\n }\n setProfileName('');\n };\n const apply = (name: string) => {\n for (const role of LAYER_ROLES) onRole(role, profiles[name]?.[role] ?? null);\n };\n const missing = LAYER_ROLES.filter(r => !roles[r]);\n return (\n <section className=\"layer-picker\">\n <button className=\"layer-picker-head\" onClick={() => setOpen(!open)}>\n <span>\n <strong>{detection.layers.length} layers</strong>\n {missing.length ? (\n <small className=\"warn\">{missing.map(r => ROLE_LABELS[r]).join(', ')} not found</small>\n ) : (\n <small>every role matched a layer</small>\n )}\n </span>\n <ArrowRight size={15} style={{ transform: open ? 'rotate(90deg)' : 'none' }} />\n </button>\n {open && (\n <>\n <p className=\"helper\">\n Read from the geometry, not the layer names — a door swing is an arc whatever the layer is called. Correct\n anything it got wrong. One layer may hold both wall faces, which is how some offices draw them; pick it for\n both.\n </p>\n <div className=\"layer-rows\">\n {LAYER_ROLES.map(role => (\n <div className={`layer-row ${roles[role] ? 'assigned' : 'unset'}`} key={role}>\n <span className=\"layer-name\">\n {ROLE_LABELS[role]}\n <small>{roles[role] ? described(detection, roles[role]!) : 'not found'}</small>\n </span>\n <select\n aria-label={ROLE_LABELS[role]}\n value={roles[role] ?? ''}\n onChange={e => onRole(role, e.target.value || null)}\n >\n <option value=\"\">—</option>\n {detection.layers.map(r => (\n <option key={r.layer} value={r.layer}>\n {r.layer}\n </option>\n ))}\n </select>\n </div>\n ))}\n </div>\n <div className=\"layer-profiles\">\n <input\n aria-label=\"Profile name\"\n placeholder=\"Save as… (e.g. the office's name)\"\n value={profileName}\n onChange={e => setProfileName(e.target.value)}\n />\n <button className=\"button secondary small\" onClick={save} disabled={!profileName.trim()}>\n Save\n </button>\n {Object.keys(profiles).map(name => (\n <button className=\"button secondary small\" key={name} onClick={() => apply(name)}>\n {name}\n </button>\n ))}\n </div>\n </>\n )}\n </section>\n );\n}\n\nexport function ImportDialog({\n project,\n floorId,\n assets,\n onClose,\n onProject,\n onAiProject,\n onAiRunningChange,\n onFootprints,\n onDrawing,\n onPlan,\n onOrigin,\n importProjections = [],\n aiImport,\n pdfDrawing,\n mode = 'reference',\n}: {\n project: ProjectDocument;\n floorId: string | null;\n assets: AssetRepository;\n onClose: () => void;\n onProject: (p: ProjectDocument) => void | Promise<void>;\n onAiProject?: (p: ProjectDocument) => void | Promise<void>;\n onAiRunningChange?: (running: boolean) => void;\n onFootprints: (objects: ProjectDocument['objects']) => void;\n onDrawing: (drawing: PreparedDrawing) => void | Promise<void>;\n /** CAD plan entities (metres, extracted host-side — see scripts/plan-import). The handler builds\n * walls, rooms and openings on the chosen floor through the editor's transactional commit. */\n onPlan?: (entities: PlanEntity[], floorId: string | null, layers?: PlanLayerMap) => void;\n /** Turn the site to a new bearing (degrees clockwise from north) before the plan is applied. */\n onOrigin?: (bearing: number) => void;\n importProjections?: ImportProjection[];\n aiImport?: AiImportAdapter;\n pdfDrawing?: PdfDrawingAdapter;\n mode?: 'reference' | 'plan';\n}) {\n const [kind, setKind] = useState<'drawing' | 'footprint' | 'plan' | 'project' | 'ai'>(\n mode === 'plan' ? (aiImport ? 'ai' : 'plan') : 'drawing',\n ),\n [file, setFile] = useState<File | null>(null),\n [crsIndex, setCrsIndex] = useState(0), // 0 = WGS84 lng/lat; 1..N = importProjections[i-1]\n [type, setType] = useState<'building' | 'parcel'>('building'),\n [planFloor, setPlanFloor] = useState(floorId),\n [bearing, setBearing] = useState(String(project.origin[2] ?? 0)),\n [page, setPage] = useState(1),\n [busy, setBusy] = useState(false),\n [error, setError] = useState('');\n const input = useRef<HTMLInputElement>(null);\n const [aiBusy, setAiBusy] = useState(false);\n useEffect(() => {\n onAiRunningChange?.(aiBusy);\n return () => onAiRunningChange?.(false);\n }, [aiBusy, onAiRunningChange]);\n // The layer census, read as soon as a CAD file is chosen — the roles are what the import turns on,\n // so they have to be reviewable before it runs, not explained afterwards by a bad result.\n const [detection, setDetection] = useState<LayerDetection | null>(null);\n const [roles, setRoles] = useState<Partial<Record<LayerRole, string>>>({});\n useEffect(() => {\n if (kind !== 'plan' || !file) return setDetection(null);\n let live = true;\n void (async () => {\n try {\n const parsed: unknown = JSON.parse(await file.text());\n const list = Array.isArray(parsed) ? parsed : ((parsed as { entities?: PlanEntity[] }).entities ?? []);\n if (!live || !Array.isArray(list)) return;\n const found = detectLayers(list as PlanEntity[]);\n setDetection(found);\n setRoles(\n Object.fromEntries(found.layers.filter(r => r.role).map(r => [r.role!, r.layer])) as Partial<\n Record<LayerRole, string>\n >,\n );\n } catch {\n if (live) setDetection(null); // not plan-entity JSON; proceed() will say so properly\n }\n })();\n return () => {\n live = false;\n };\n }, [file, kind]);\n async function proceed() {\n if (!file) return;\n setBusy(true);\n setError('');\n try {\n if (file.size > 50 * 1024 * 1024) throw new Error('Choose a file smaller than 50 MB.');\n if (kind === 'project') await onProject(await importProject(await file.text(), assets));\n else if (kind === 'plan') {\n const parsed: unknown = JSON.parse(await file.text());\n const entities = Array.isArray(parsed) ? parsed : ((parsed as { entities?: PlanEntity[] }).entities ?? null);\n if (!Array.isArray(entities))\n throw new Error('Expected plan-entity JSON (see scripts/plan-import/extract.mjs).');\n // The heading is a property of the site, not of this sheet — apply it before the plan lands,\n // so the walls are built into a frame already facing the right way.\n const heading = Number(bearing);\n if (Number.isFinite(heading) && heading !== (project.origin[2] ?? 0)) onOrigin?.(heading);\n const named = Object.entries(roles).filter(([, layer]) => layer);\n const layers = named.length\n ? ({\n ...detection?.suggested,\n ...Object.fromEntries(named.map(([role, layer]) => [role, layerPattern(layer!)])),\n } as PlanLayerMap)\n : detection?.suggested;\n onPlan?.(entities as PlanEntity[], planFloor, layers);\n } else if (kind === 'footprint')\n onFootprints(\n importFootprints(JSON.parse(await file.text()), project, type, importProjections[crsIndex - 1]?.toLngLat),\n );\n else {\n let blob: Blob = file;\n if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) {\n if (!pdfDrawing)\n throw new Error(\n 'PDF conversion requires a connected import backend. Start make up or use an image drawing.',\n );\n blob = await pdfDrawing.render(file, page);\n }\n if (!['image/png', 'image/jpeg', 'image/webp'].includes(blob.type))\n throw new Error('Use a PNG, JPEG, WebP, or PDF drawing.');\n const bitmap = await createImageBitmap(blob);\n const width = bitmap.width,\n height = bitmap.height;\n bitmap.close();\n await onDrawing({\n blob,\n name: file.name + (file.name.endsWith('.pdf') ? ` · page ${page}` : ''),\n width,\n height,\n });\n }\n onClose();\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setBusy(false);\n }\n }\n const tabs = (\n <div className=\"import-tabs\">\n {(mode === 'plan'\n ? [...(aiImport ? ['ai' as const] : []), 'plan' as const]\n : ['drawing' as const, 'footprint' as const, 'project' as const]\n ).map(k => (\n <button\n key={k}\n className={kind === k ? 'active' : ''}\n disabled={aiBusy || busy}\n onClick={() => {\n setKind(k);\n setFile(null);\n setError('');\n }}\n >\n {k === 'drawing' ? <FileImage size={19} /> : <FileJson size={19} />}\n {k === 'drawing'\n ? 'Floor drawing'\n : k === 'footprint'\n ? 'GeoJSON'\n : k === 'plan'\n ? 'CAD plan'\n : k === 'ai'\n ? 'AI import'\n : 'Project'}\n </button>\n ))}\n </div>\n );\n const contents = (\n <>\n {mode !== 'plan' && tabs}\n {kind === 'ai' && aiImport ? (\n <Suspense\n fallback={\n <p className=\"helper\" role=\"status\">\n Loading AI import…\n </p>\n }\n >\n <AiImportPanel\n adapter={aiImport}\n assets={assets}\n onProject={onAiProject ?? onProject}\n onRunningChange={setAiBusy}\n currentProject={project}\n />\n </Suspense>\n ) : (\n <>\n <button\n className=\"dropzone\"\n onClick={() => input.current?.click()}\n onDragOver={e => e.preventDefault()}\n onDrop={e => {\n e.preventDefault();\n setFile(e.dataTransfer.files[0] ?? null);\n }}\n >\n {file ? <Check size={30} /> : <UploadCloud size={32} />}\n <strong>{file?.name ?? 'Drop a file here, or browse'}</strong>\n <span>{kind === 'drawing' ? 'PNG, JPEG, WebP or PDF · up to 50 MB' : 'JSON or GeoJSON · up to 50 MB'}</span>\n </button>\n <input\n ref={input}\n type=\"file\"\n hidden\n accept={kind === 'drawing' ? '.png,.jpg,.jpeg,.webp,.pdf' : '.json,.geojson'}\n onChange={e => setFile(e.target.files?.[0] ?? null)}\n />\n {kind === 'drawing' && (\n <p className=\"helper\">\n Your drawing will be added to {project.floors.find(f => f.id === floorId)?.name ?? 'Outdoor site'}. Match\n two points to position it on the map, or calibrate a known distance.\n </p>\n )}\n {kind === 'plan' && (\n <>\n <label className=\"field\">\n <span>Target floor</span>\n <select value={planFloor ?? ''} onChange={e => setPlanFloor(e.target.value || null)}>\n {project.floors.map(f => (\n <option key={f.id} value={f.id}>\n {f.name}\n </option>\n ))}\n <option value=\"\">Outdoor site</option>\n </select>\n </label>\n <p className=\"helper\">\n Walls, rooms, doors and windows will be built on the chosen floor — repeat per floor for a multi-storey\n building. Produce the JSON from a DWG with{' '}\n <code>scripts/plan-import/extract.mjs --expand --units m</code>.\n </p>\n {detection && (\n <LayerPicker\n detection={detection}\n roles={roles}\n onRole={(role, layer) =>\n setRoles(current => {\n const next = { ...current };\n if (layer) next[role] = layer;\n else delete next[role];\n return next;\n })\n }\n />\n )}\n <label className=\"field\">\n <span>Site bearing</span>\n <input\n type=\"number\"\n aria-label=\"Site bearing\"\n step={0.1}\n min={-360}\n max={360}\n value={bearing}\n onChange={e => setBearing(e.target.value)}\n />\n </label>\n <p className=\"helper\">\n A drawing is square to its sheet, not to the world, so an imported plan lands on the site's current\n heading. Degrees clockwise from north; adjustable afterwards under Site anchor.\n </p>\n </>\n )}\n {kind === 'drawing' && file?.name.toLowerCase().endsWith('.pdf') && (\n <label className=\"field\">\n <span>PDF page</span>\n <input\n type=\"number\"\n aria-label=\"PDF page\"\n min={1}\n value={page}\n onChange={e => setPage(Number(e.target.value))}\n />\n </label>\n )}\n {kind === 'footprint' && (\n <div className=\"field-grid\">\n <label className=\"field\">\n <span>Source coordinates</span>\n <select value={crsIndex} onChange={e => setCrsIndex(Number(e.target.value))}>\n <option value={0}>WGS84 · longitude / latitude</option>\n {importProjections.map((p, i) => (\n <option key={p.label} value={i + 1}>\n {p.label}\n </option>\n ))}\n </select>\n </label>\n <label className=\"field\">\n <span>Import as</span>\n <select value={type} onChange={e => setType(e.target.value as typeof type)}>\n <option value=\"building\">Building footprint</option>\n <option value=\"parcel\">Parcel boundary</option>\n </select>\n </label>\n </div>\n )}\n {kind === 'project' && (\n <p className=\"helper\">\n Open a portable Kerros JSON export as a new project, including its reference images.\n </p>\n )}\n {error && (\n <p className=\"form-error\" role=\"alert\">\n {error}\n </p>\n )}\n <footer>\n <button className=\"button secondary\" onClick={onClose}>\n Cancel\n </button>\n <button className=\"button primary\" disabled={!file || busy} onClick={proceed}>\n {busy ? 'Preparing…' : kind === 'drawing' ? 'Align drawing' : 'Import'}\n <ArrowRight size={16} />\n </button>\n </footer>\n </>\n )}\n </>\n );\n return mode === 'plan' ? (\n <aside className=\"inspector plan-import-panel\" aria-label=\"Plan import\" onKeyDown={e => e.stopPropagation()}>\n <header className=\"inspector-top\">\n <h2>Plan import</h2>\n <button\n className=\"icon-button\"\n aria-label=\"Close plan import\"\n title={aiBusy ? 'Hide sidebar; import keeps running' : 'Close plan import'}\n disabled={busy}\n onClick={onClose}\n >\n <X size={20} />\n </button>\n </header>\n {tabs}\n <div className={kind === 'ai' ? 'ai-import-shell' : 'inspector-scroll'}>{contents}</div>\n </aside>\n ) : (\n <Modal\n title=\"Reference drawings and files\"\n subtitle=\"Align a drawing for tracing, add site geometry, or open a saved project.\"\n onClose={onClose}\n >\n {contents}\n </Modal>\n );\n}\nexport function AlignmentPanel({\n drawing,\n mapPoints,\n imagePoints,\n setImagePoints,\n onCancel,\n onPreview,\n onConfirm,\n onKnownDistance,\n preview,\n}: {\n drawing: PreparedDrawing;\n mapPoints: Point[];\n imagePoints: Point[];\n setImagePoints: (points: Point[]) => void;\n onCancel: () => void;\n onPreview: () => void;\n onConfirm: () => void;\n onKnownDistance: (metres: number) => void;\n preview: boolean;\n}) {\n const [url, setUrl] = useState(''),\n [metres, setMetres] = useState(10);\n useEffect(() => {\n let active = true;\n blobDataUrl(drawing.blob).then(data => {\n if (active) setUrl(data);\n });\n return () => {\n active = false;\n };\n }, [drawing.blob]);\n return (\n <aside className=\"alignment-panel\">\n <div className=\"panel-heading\">\n <span className=\"eyebrow\">REFERENCE DRAWING</span>\n <h2>Align your drawing</h2>\n <p>\n {imagePoints.length < 2\n ? '1. Pick two recognizable points in this drawing.'\n : mapPoints.length < 2\n ? '2. Click the same points on the map, in the same order.'\n : preview\n ? '3. Check the overlay on the map, then confirm.'\n : '3. Preview the alignment before saving.'}\n </p>\n </div>\n <div\n className=\"alignment-image\"\n onClick={e => {\n if (imagePoints.length >= 2 || preview) return;\n const rect = e.currentTarget.getBoundingClientRect();\n setImagePoints([\n ...imagePoints,\n [\n ((e.clientX - rect.left) / rect.width) * drawing.width,\n ((e.clientY - rect.top) / rect.height) * drawing.height,\n ],\n ]);\n }}\n >\n {url && <img src={url} alt=\"Architectural drawing to align\" />}\n {imagePoints.map((p, i) => (\n <b key={i} style={{ left: `${(p[0] / drawing.width) * 100}%`, top: `${(p[1] / drawing.height) * 100}%` }}>\n {i + 1}\n </b>\n ))}\n </div>\n <div className=\"alignment-progress\">\n {[0, 1].map(i => (\n <span key={i} className={mapPoints[i] ? 'done' : ''}>\n {mapPoints[i] ? <Check size={14} /> : i + 1} Reference point {i + 1}\n </span>\n ))}\n </div>\n <button className=\"text-button\" onClick={() => setImagePoints([])}>\n Reset reference points\n </button>\n <div className=\"known-distance\">\n <strong>Have a dimension instead?</strong>\n <p>\n Select two image points and enter their real distance. Place and rotate the overlay using its properties\n afterward.\n </p>\n <label className=\"field\">\n <span>Known distance (m)</span>\n <input type=\"number\" min={0.01} value={metres} onChange={e => setMetres(Number(e.target.value))} />\n </label>\n <button\n className=\"button secondary\"\n disabled={imagePoints.length !== 2 || metres <= 0}\n onClick={() => onKnownDistance(metres)}\n >\n Calibrate distance\n </button>\n </div>\n <div className=\"alignment-actions\">\n <button className=\"button secondary\" onClick={onCancel}>\n Cancel\n </button>\n <button\n className=\"button primary\"\n disabled={imagePoints.length !== 2 || mapPoints.length !== 2}\n onClick={preview ? onConfirm : onPreview}\n >\n {preview ? 'Confirm alignment' : 'Preview'}\n </button>\n </div>\n </aside>\n );\n}\nexport const makeDrawing = (prepared: PreparedDrawing, floorId: string | null): Drawing => ({\n id: uid(),\n floorId,\n assetId: uid(),\n name: prepared.name,\n width: prepared.width,\n height: prepared.height,\n origin: [-29, 18],\n scale: 58 / prepared.width,\n rotation: 0,\n opacity: 0.65,\n visible: true,\n locked: false,\n});\n"],"names":["AiImportPanel","lazy","m","ROLE_LABELS","described","detection","layer","r","x","PROFILES_KEY","readProfiles","LayerPicker","roles","onRole","open","setOpen","useState","profiles","setProfiles","profileName","setProfileName","save","name","next","apply","role","LAYER_ROLES","_a","missing","jsxs","jsx","ArrowRight","Fragment","e","ImportDialog","project","floorId","assets","onClose","onProject","onAiProject","onAiRunningChange","onFootprints","onDrawing","onPlan","onOrigin","importProjections","aiImport","pdfDrawing","mode","kind","setKind","file","setFile","crsIndex","setCrsIndex","type","setType","planFloor","setPlanFloor","bearing","setBearing","page","setPage","busy","setBusy","error","setError","input","useRef","aiBusy","setAiBusy","useEffect","setDetection","setRoles","live","parsed","list","found","detectLayers","proceed","importProject","entities","heading","named","layers","layerPattern","importFootprints","blob","bitmap","width","height","tabs","k","FileImage","FileJson","contents","Suspense","Check","UploadCloud","f","current","p","i","X","Modal","AlignmentPanel","drawing","mapPoints","imagePoints","setImagePoints","onCancel","onPreview","onConfirm","onKnownDistance","preview","url","setUrl","metres","setMetres","active","blobDataUrl","data","rect","makeDrawing","prepared","uid"],"mappings":"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"}
|