@react-arch/core 0.1.2 → 0.1.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/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -10
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/model.ts","../src/commands.ts","../src/history.ts","../src/serialize.ts","../src/defaults.ts","../src/furniture.ts"],"mappings":";;;;cAGa,aAAA;AAAA,KAED,WAAA;AAAA,KACA,cAAA;AAAA,KACA,SAAA;AAAA,UAEK,IAAA;EACf,EAAA;EACA,OAAA;EACA,KAAA,EAAO,IAAA;EACP,GAAA,EAAK,IAAI;EACT,SAAA;EACA,MAAA;EACA,UAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,UAGe,OAAA;EACf,EAAA;EACA,OAAA;EACA,MAAA;EACA,IAAA,EAAM,WAAA;EAlBa;EAoBnB,MAAA;EACA,KAAA;EACA,MAAA;EACA,UAAA;EACA,KAAA,GAAQ,cAAA;EACR,KAAA,GAAQ,SAAA;EACR,UAAA;AAAA;AAAA,UAGe,IAAA;EACf,EAAA;EACA,OAAA;EACA,IAAA;EAvBA;EAyBA,OAAA,EAAS,IAAI;EACb,eAAA;EACA,eAAA;EACA,iBAAA;EACA,SAAA;EACA,MAAA;AAAA;AAAA,UAGe,cAAA;EACf,EAAA;EACA,OAAA;EACA,IAAA;EACA,QAAA,EAAU,IAAA;EACV,QAAA,EAAU,IAAA;EACV,KAAA,EAAO,IAAA;EACP,OAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,UAGI,KAAA;EACf,EAAA;EACA,UAAA;EACA,IAAA;EACA,SAAA;EACA,MAAA;EACA,OAAA;EACA,MAAA;EACA,KAAA,EAAO,IAAA;EACP,KAAA,EAAO,IAAA;EACP,QAAA,EAAU,OAAA;EACV,OAAA,EAAS,cAAA;AAAA;AAAA,UAGM,QAAA;EACf,EAAA;EACA,IAAA;EACA,MAAA,EAAQ,KAAK;AAAA;AAAA,KAGH,gBAAA;AAAA,UAUK,QAAA;EACf,EAAA;EACA,IAAA;EACA,QAAA,EAAU,gBAAgB;EAC1B,SAAA;EACA,SAAA;EACA,SAAA;EACA,OAAA;EACA,UAAA;AAAA;AAAA,UAGe,KAAA;EACf,EAAA;EACA,IAAA;EACA,GAAA;EACA,IAAA;AAAA;AAAA,UAGe,IAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA,GAAU,IAAI;AAAA;AAAA,UAGC,gBAAA;EACf,EAAA;EACA,OAAA;EACA,IAAA;EACA,KAAA,EAAO,KAAA;EACP,IAAA,GAAO,IAAA;EACP,SAAA,EAAW,QAAA;EACX,SAAA,EAAW,QAAA;EACX,MAAA,EAAQ,KAAA;EACR,QAAA,EAAU,MAAA;AAAA;;UAIK,WAAA;EACf,IAAA;EACA,MAAA;EACA,EAAA;AAAA;AAAA,UAGe,YAAA;EACf,IAAA;EACA,OAAA;EACA,QAAA;AAAA;AAAA,UAGe,aAAA;EACf,QAAA,EAAU,gBAAA;EACV,OAAA,EAAS,WAAA;EACT,QAAA,EAAU,YAAA;AAAA;AAAA,iBAOI,SAAA,CACd,GAAA,EAAK,gBAAA,EACL,OAAA;EACG,QAAA,EAAU,QAAA;EAAU,KAAA,EAAO,KAAA;AAAA;AAAA,iBAQhB,SAAA,CAAU,GAAA,EAAK,gBAAA,GAAmB,KAAK;AAAA,iBAIvC,QAAA,CAAS,GAAA,EAAK,gBAAA,EAAkB,MAAA,WAAiB,IAAI;AAAA,iBAQrD,QAAA,CAAS,GAAA,EAAK,gBAAA,EAAkB,MAAA,WAAiB,IAAI;AAAA,iBAQrD,WAAA,CACd,GAAA,EAAK,gBAAA,EACL,SAAA,WACC,OAAO;AAAA,KAQE,UAAA;AAAA,UAEK,SAAA;EACf,IAAA,EAAM,UAAU;EAChB,EAAA;AAAA;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/model.ts","../src/commands.ts","../src/history.ts","../src/serialize.ts","../src/defaults.ts","../src/furniture.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -54,14 +54,17 @@ function requireFloor(doc, floorId) {
|
|
|
54
54
|
if (!found) throw new Error(`Floor not found: ${floorId}`);
|
|
55
55
|
return found.floor;
|
|
56
56
|
}
|
|
57
|
+
function cloneVec2(v) {
|
|
58
|
+
return [v[0], v[1]];
|
|
59
|
+
}
|
|
57
60
|
function createWall(doc, input) {
|
|
58
61
|
return mutate(doc, (draft) => {
|
|
59
62
|
const floor = requireFloor(draft, input.floorId);
|
|
60
63
|
const wall = {
|
|
61
64
|
id: input.id ?? createId("wall"),
|
|
62
65
|
floorId: input.floorId,
|
|
63
|
-
start: input.start,
|
|
64
|
-
end: input.end,
|
|
66
|
+
start: cloneVec2(input.start),
|
|
67
|
+
end: cloneVec2(input.end),
|
|
65
68
|
thickness: input.thickness ?? .2,
|
|
66
69
|
height: input.height ?? floor.height,
|
|
67
70
|
materialId: input.materialId
|
|
@@ -79,7 +82,7 @@ function updateWall(doc, wallId, patch) {
|
|
|
79
82
|
for (const floor of allFloorsOf(draft)) {
|
|
80
83
|
const wall = floor.walls.find((w) => w.id === wallId);
|
|
81
84
|
if (!wall) continue;
|
|
82
|
-
Object.assign(wall, patch);
|
|
85
|
+
Object.assign(wall, deepClone(patch));
|
|
83
86
|
reattachOpenings(floor, wall, warnings);
|
|
84
87
|
return [{
|
|
85
88
|
kind: "update",
|
|
@@ -113,6 +116,15 @@ function deleteWall(doc, wallId) {
|
|
|
113
116
|
entity: "wall",
|
|
114
117
|
id: wallId
|
|
115
118
|
});
|
|
119
|
+
for (const room of floor.rooms) {
|
|
120
|
+
if (!room.boundaryWallIds?.includes(wallId)) continue;
|
|
121
|
+
room.boundaryWallIds = room.boundaryWallIds.filter((id) => id !== wallId);
|
|
122
|
+
changes.push({
|
|
123
|
+
kind: "update",
|
|
124
|
+
entity: "room",
|
|
125
|
+
id: room.id
|
|
126
|
+
});
|
|
127
|
+
}
|
|
116
128
|
floor.openings = floor.openings.filter((o) => {
|
|
117
129
|
if (o.wallId === wallId) {
|
|
118
130
|
changes.push({
|
|
@@ -145,7 +157,7 @@ function createRoom(doc, input) {
|
|
|
145
157
|
id: input.id ?? createId("room"),
|
|
146
158
|
floorId: input.floorId,
|
|
147
159
|
name: input.name,
|
|
148
|
-
polygon: input.polygon,
|
|
160
|
+
polygon: input.polygon.map(cloneVec2),
|
|
149
161
|
floorMaterialId: input.floorMaterialId,
|
|
150
162
|
ceilingMaterialId: input.ceilingMaterialId,
|
|
151
163
|
usageType: input.usageType
|
|
@@ -163,7 +175,7 @@ function updateRoom(doc, roomId, patch) {
|
|
|
163
175
|
for (const floor of allFloorsOf(draft)) {
|
|
164
176
|
const room = floor.rooms.find((r) => r.id === roomId);
|
|
165
177
|
if (!room) continue;
|
|
166
|
-
Object.assign(room, patch);
|
|
178
|
+
Object.assign(room, deepClone(patch));
|
|
167
179
|
return [{
|
|
168
180
|
kind: "update",
|
|
169
181
|
entity: "room",
|
|
@@ -321,6 +333,7 @@ function duplicateFloor(doc, floorId) {
|
|
|
321
333
|
copy.rooms.forEach((r) => {
|
|
322
334
|
r.id = createId("room");
|
|
323
335
|
r.floorId = copy.id;
|
|
336
|
+
if (r.boundaryWallIds) r.boundaryWallIds = r.boundaryWallIds.map((id) => idMap.get(id) ?? id);
|
|
324
337
|
});
|
|
325
338
|
copy.objects.forEach((ob) => {
|
|
326
339
|
ob.id = createId("object");
|
|
@@ -413,8 +426,8 @@ var History = class {
|
|
|
413
426
|
this.past.push({
|
|
414
427
|
id: createId("hist"),
|
|
415
428
|
label,
|
|
416
|
-
before,
|
|
417
|
-
after
|
|
429
|
+
before: deepClone(before),
|
|
430
|
+
after: deepClone(after)
|
|
418
431
|
});
|
|
419
432
|
if (this.past.length > this.limit) this.past.shift();
|
|
420
433
|
this.future = [];
|
|
@@ -429,13 +442,13 @@ var History = class {
|
|
|
429
442
|
const entry = this.past.pop();
|
|
430
443
|
if (!entry) return null;
|
|
431
444
|
this.future.push(entry);
|
|
432
|
-
return entry.before;
|
|
445
|
+
return deepClone(entry.before);
|
|
433
446
|
}
|
|
434
447
|
redo() {
|
|
435
448
|
const entry = this.future.pop();
|
|
436
449
|
if (!entry) return null;
|
|
437
450
|
this.past.push(entry);
|
|
438
|
-
return entry.after;
|
|
451
|
+
return deepClone(entry.after);
|
|
439
452
|
}
|
|
440
453
|
get undoLabel() {
|
|
441
454
|
return this.past.at(-1)?.label ?? null;
|
|
@@ -541,7 +554,7 @@ function createEmptyDocument(options = {}) {
|
|
|
541
554
|
name: options.buildingName ?? options.name ?? "Building",
|
|
542
555
|
floors: []
|
|
543
556
|
}],
|
|
544
|
-
materials:
|
|
557
|
+
materials: DEFAULT_MATERIALS.map((m) => ({ ...m })),
|
|
545
558
|
assets: [],
|
|
546
559
|
metadata: {}
|
|
547
560
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["wl"],"sources":["../src/model.ts","../src/commands.ts","../src/history.ts","../src/serialize.ts","../src/defaults.ts","../src/furniture.ts"],"sourcesContent":["import type { Units, Vec2, Vec3 } from \"@react-arch/shared\";\n\n/** The current on-disk model version. Bump when the schema changes. */\nexport const MODEL_VERSION = \"0.1.0\";\n\nexport type OpeningType = \"door\" | \"window\" | \"opening\";\nexport type SwingDirection = \"in\" | \"out\";\nexport type HingeSide = \"left\" | \"right\";\n\nexport interface Wall {\n id: string;\n floorId: string;\n start: Vec2;\n end: Vec2;\n thickness: number;\n height: number;\n materialId?: string;\n layerId?: string;\n locked?: boolean;\n}\n\nexport interface Opening {\n id: string;\n floorId: string;\n wallId: string;\n type: OpeningType;\n /** Distance along the wall centerline to the opening center. */\n offset: number;\n width: number;\n height: number;\n sillHeight: number;\n swing?: SwingDirection;\n hinge?: HingeSide;\n materialId?: string;\n}\n\nexport interface Room {\n id: string;\n floorId: string;\n name: string;\n /** Explicit polygon (metres). Rooms may also be derived from wall loops. */\n polygon: Vec2[];\n boundaryWallIds?: string[];\n floorMaterialId?: string;\n ceilingMaterialId?: string;\n usageType?: string;\n height?: number;\n}\n\nexport interface BuildingObject {\n id: string;\n floorId: string;\n type: string;\n position: Vec3;\n rotation: Vec3;\n scale: Vec3;\n assetId?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface Floor {\n id: string;\n buildingId: string;\n name: string;\n elevation: number;\n height: number;\n visible: boolean;\n locked: boolean;\n walls: Wall[];\n rooms: Room[];\n openings: Opening[];\n objects: BuildingObject[];\n}\n\nexport interface Building {\n id: string;\n name: string;\n floors: Floor[];\n}\n\nexport type MaterialCategory =\n | \"wall\"\n | \"floor\"\n | \"ceiling\"\n | \"glass\"\n | \"wood\"\n | \"metal\"\n | \"ceramic\"\n | \"custom\";\n\nexport interface Material {\n id: string;\n name: string;\n category: MaterialCategory;\n baseColor: string;\n roughness?: number;\n metalness?: number;\n opacity?: number;\n textureUrl?: string;\n}\n\nexport interface Asset {\n id: string;\n name: string;\n url?: string;\n kind: string;\n}\n\nexport interface Site {\n id: string;\n name: string;\n polygon?: Vec2[];\n}\n\nexport interface BuildingDocument {\n id: string;\n version: string;\n name: string;\n units: Units;\n site?: Site;\n buildings: Building[];\n materials: Material[];\n assets: Asset[];\n metadata: Record<string, unknown>;\n}\n\n/** A single semantic change emitted by a command. */\nexport interface ModelChange {\n kind: \"create\" | \"update\" | \"delete\";\n entity: \"wall\" | \"room\" | \"opening\" | \"floor\" | \"object\" | \"document\";\n id: string;\n}\n\nexport interface ModelWarning {\n code: string;\n message: string;\n entityId?: string;\n}\n\nexport interface CommandResult {\n document: BuildingDocument;\n changes: ModelChange[];\n warnings: ModelWarning[];\n}\n\n// ---------------------------------------------------------------------------\n// Read helpers\n// ---------------------------------------------------------------------------\n\nexport function findFloor(\n doc: BuildingDocument,\n floorId: string,\n): { building: Building; floor: Floor } | undefined {\n for (const building of doc.buildings) {\n const floor = building.floors.find((f) => f.id === floorId);\n if (floor) return { building, floor };\n }\n return undefined;\n}\n\nexport function allFloors(doc: BuildingDocument): Floor[] {\n return doc.buildings.flatMap((b) => b.floors);\n}\n\nexport function findWall(doc: BuildingDocument, wallId: string): Wall | undefined {\n for (const floor of allFloors(doc)) {\n const w = floor.walls.find((x) => x.id === wallId);\n if (w) return w;\n }\n return undefined;\n}\n\nexport function findRoom(doc: BuildingDocument, roomId: string): Room | undefined {\n for (const floor of allFloors(doc)) {\n const r = floor.rooms.find((x) => x.id === roomId);\n if (r) return r;\n }\n return undefined;\n}\n\nexport function findOpening(\n doc: BuildingDocument,\n openingId: string,\n): Opening | undefined {\n for (const floor of allFloors(doc)) {\n const o = floor.openings.find((x) => x.id === openingId);\n if (o) return o;\n }\n return undefined;\n}\n\nexport type EntityKind = \"wall\" | \"room\" | \"opening\" | \"floor\" | \"object\";\n\nexport interface EntityRef {\n kind: EntityKind;\n id: string;\n}\n","import { createId, deepClone, type Vec2 } from \"@react-arch/shared\";\nimport { openingFits, wallLength, type WallLike } from \"@react-arch/geometry\";\nimport {\n type BuildingDocument,\n type CommandResult,\n type Floor,\n type ModelChange,\n type ModelWarning,\n type Opening,\n type OpeningType,\n type Room,\n type Wall,\n findFloor,\n} from \"./model.js\";\n\n/**\n * Commands are pure: they take a document and return a brand-new document plus\n * a list of changes and warnings. They never mutate the input. The studio /\n * editor layers feed these into the history stack for undo/redo.\n */\n\nfunction mutate(\n doc: BuildingDocument,\n fn: (draft: BuildingDocument, warnings: ModelWarning[]) => ModelChange[],\n): CommandResult {\n const draft = deepClone(doc);\n const warnings: ModelWarning[] = [];\n const changes = fn(draft, warnings);\n return { document: draft, changes, warnings };\n}\n\nfunction requireFloor(doc: BuildingDocument, floorId: string): Floor {\n const found = findFloor(doc, floorId);\n if (!found) throw new Error(`Floor not found: ${floorId}`);\n return found.floor;\n}\n\n// --- Walls -----------------------------------------------------------------\n\nexport interface CreateWallInput {\n floorId: string;\n start: Vec2;\n end: Vec2;\n thickness?: number;\n height?: number;\n materialId?: string;\n id?: string;\n}\n\nexport function createWall(\n doc: BuildingDocument,\n input: CreateWallInput,\n): CommandResult {\n return mutate(doc, (draft) => {\n const floor = requireFloor(draft, input.floorId);\n const wall: Wall = {\n id: input.id ?? createId(\"wall\"),\n floorId: input.floorId,\n start: input.start,\n end: input.end,\n thickness: input.thickness ?? 0.2,\n height: input.height ?? floor.height,\n materialId: input.materialId,\n };\n floor.walls.push(wall);\n return [{ kind: \"create\", entity: \"wall\", id: wall.id }];\n });\n}\n\nexport function updateWall(\n doc: BuildingDocument,\n wallId: string,\n patch: Partial<Omit<Wall, \"id\" | \"floorId\">>,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n for (const floor of allFloorsOf(draft)) {\n const wall = floor.walls.find((w) => w.id === wallId);\n if (!wall) continue;\n Object.assign(wall, patch);\n reattachOpenings(floor, wall, warnings);\n return [{ kind: \"update\", entity: \"wall\", id: wallId }];\n }\n warnings.push({ code: \"wall-missing\", message: `Wall ${wallId} not found` });\n return [];\n });\n}\n\n/** Move a wall's endpoints, keeping attached openings within bounds. */\nexport function moveWall(\n doc: BuildingDocument,\n wallId: string,\n start: Vec2,\n end: Vec2,\n): CommandResult {\n return updateWall(doc, wallId, { start, end });\n}\n\nexport function deleteWall(doc: BuildingDocument, wallId: string): CommandResult {\n return mutate(doc, (draft) => {\n const changes: ModelChange[] = [];\n for (const floor of allFloorsOf(draft)) {\n const idx = floor.walls.findIndex((w) => w.id === wallId);\n if (idx === -1) continue;\n floor.walls.splice(idx, 1);\n changes.push({ kind: \"delete\", entity: \"wall\", id: wallId });\n // Cascade: drop openings attached to the wall.\n floor.openings = floor.openings.filter((o) => {\n if (o.wallId === wallId) {\n changes.push({ kind: \"delete\", entity: \"opening\", id: o.id });\n return false;\n }\n return true;\n });\n break;\n }\n return changes;\n });\n}\n\n// --- Rooms -----------------------------------------------------------------\n\nexport interface CreateRoomInput {\n floorId: string;\n name: string;\n polygon: Vec2[];\n id?: string;\n floorMaterialId?: string;\n ceilingMaterialId?: string;\n usageType?: string;\n}\n\n/** Convenience: build a rectangular room from origin + size. */\nexport function rectRoomPolygon(\n x: number,\n y: number,\n width: number,\n depth: number,\n): Vec2[] {\n return [\n [x, y],\n [x + width, y],\n [x + width, y + depth],\n [x, y + depth],\n ];\n}\n\nexport function createRoom(\n doc: BuildingDocument,\n input: CreateRoomInput,\n): CommandResult {\n return mutate(doc, (draft) => {\n const floor = requireFloor(draft, input.floorId);\n const room: Room = {\n id: input.id ?? createId(\"room\"),\n floorId: input.floorId,\n name: input.name,\n polygon: input.polygon,\n floorMaterialId: input.floorMaterialId,\n ceilingMaterialId: input.ceilingMaterialId,\n usageType: input.usageType,\n };\n floor.rooms.push(room);\n return [{ kind: \"create\", entity: \"room\", id: room.id }];\n });\n}\n\nexport function updateRoom(\n doc: BuildingDocument,\n roomId: string,\n patch: Partial<Omit<Room, \"id\" | \"floorId\">>,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n for (const floor of allFloorsOf(draft)) {\n const room = floor.rooms.find((r) => r.id === roomId);\n if (!room) continue;\n Object.assign(room, patch);\n return [{ kind: \"update\", entity: \"room\", id: roomId }];\n }\n warnings.push({ code: \"room-missing\", message: `Room ${roomId} not found` });\n return [];\n });\n}\n\nexport function deleteRoom(doc: BuildingDocument, roomId: string): CommandResult {\n return mutate(doc, (draft) => {\n for (const floor of allFloorsOf(draft)) {\n const idx = floor.rooms.findIndex((r) => r.id === roomId);\n if (idx === -1) continue;\n floor.rooms.splice(idx, 1);\n return [{ kind: \"delete\", entity: \"room\", id: roomId }];\n }\n return [];\n });\n}\n\n// --- Openings --------------------------------------------------------------\n\nexport interface CreateOpeningInput {\n wallId: string;\n type: OpeningType;\n offset: number;\n width: number;\n height: number;\n sillHeight?: number;\n id?: string;\n}\n\nexport function createOpening(\n doc: BuildingDocument,\n input: CreateOpeningInput,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n for (const floor of allFloorsOf(draft)) {\n const wall = floor.walls.find((w) => w.id === input.wallId);\n if (!wall) continue;\n const opening: Opening = {\n id: input.id ?? createId(\"opening\"),\n floorId: floor.id,\n wallId: input.wallId,\n type: input.type,\n offset: input.offset,\n width: input.width,\n height: input.height,\n sillHeight: input.sillHeight ?? (input.type === \"window\" ? 0.9 : 0),\n };\n if (!openingFits(wall, opening)) {\n warnings.push({\n code: \"opening-overflow\",\n message: `Opening ${opening.id} does not fit within wall ${wall.id}`,\n entityId: opening.id,\n });\n }\n floor.openings.push(opening);\n return [{ kind: \"create\", entity: \"opening\", id: opening.id }];\n }\n warnings.push({\n code: \"wall-missing\",\n message: `Wall ${input.wallId} not found for opening`,\n });\n return [];\n });\n}\n\nexport function updateOpening(\n doc: BuildingDocument,\n openingId: string,\n patch: Partial<Omit<Opening, \"id\" | \"floorId\" | \"wallId\">>,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n for (const floor of allFloorsOf(draft)) {\n const opening = floor.openings.find((o) => o.id === openingId);\n if (!opening) continue;\n Object.assign(opening, patch);\n const wall = floor.walls.find((w) => w.id === opening.wallId);\n if (wall && !openingFits(wall, opening)) {\n warnings.push({\n code: \"opening-overflow\",\n message: `Opening ${opening.id} no longer fits its wall`,\n entityId: opening.id,\n });\n }\n return [{ kind: \"update\", entity: \"opening\", id: openingId }];\n }\n return [];\n });\n}\n\nexport function moveOpening(\n doc: BuildingDocument,\n openingId: string,\n offset: number,\n): CommandResult {\n return updateOpening(doc, openingId, { offset });\n}\n\nexport function deleteOpening(\n doc: BuildingDocument,\n openingId: string,\n): CommandResult {\n return mutate(doc, (draft) => {\n for (const floor of allFloorsOf(draft)) {\n const idx = floor.openings.findIndex((o) => o.id === openingId);\n if (idx === -1) continue;\n floor.openings.splice(idx, 1);\n return [{ kind: \"delete\", entity: \"opening\", id: openingId }];\n }\n return [];\n });\n}\n\n// --- Floors ----------------------------------------------------------------\n\nexport interface CreateFloorInput {\n buildingId: string;\n name: string;\n elevation: number;\n height?: number;\n id?: string;\n}\n\nexport function createFloor(\n doc: BuildingDocument,\n input: CreateFloorInput,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n const building = draft.buildings.find((b) => b.id === input.buildingId);\n if (!building) {\n warnings.push({ code: \"building-missing\", message: \"Building not found\" });\n return [];\n }\n const floor: Floor = {\n id: input.id ?? createId(\"floor\"),\n buildingId: building.id,\n name: input.name,\n elevation: input.elevation,\n height: input.height ?? 2.8,\n visible: true,\n locked: false,\n walls: [],\n rooms: [],\n openings: [],\n objects: [],\n };\n building.floors.push(floor);\n building.floors.sort((a, b) => a.elevation - b.elevation);\n return [{ kind: \"create\", entity: \"floor\", id: floor.id }];\n });\n}\n\nexport function duplicateFloor(\n doc: BuildingDocument,\n floorId: string,\n): CommandResult {\n return mutate(doc, (draft) => {\n for (const building of draft.buildings) {\n const floor = building.floors.find((f) => f.id === floorId);\n if (!floor) continue;\n const idMap = new Map<string, string>();\n const copy: Floor = deepClone(floor);\n copy.id = createId(\"floor\");\n copy.name = `${floor.name} (copy)`;\n copy.elevation = floor.elevation + floor.height;\n // Re-id child entities and keep opening→wall references consistent.\n copy.walls.forEach((w) => {\n const nid = createId(\"wall\");\n idMap.set(w.id, nid);\n w.id = nid;\n w.floorId = copy.id;\n });\n copy.openings.forEach((o) => {\n o.id = createId(\"opening\");\n o.floorId = copy.id;\n o.wallId = idMap.get(o.wallId) ?? o.wallId;\n });\n copy.rooms.forEach((r) => {\n r.id = createId(\"room\");\n r.floorId = copy.id;\n });\n copy.objects.forEach((ob) => {\n ob.id = createId(\"object\");\n ob.floorId = copy.id;\n });\n building.floors.push(copy);\n building.floors.sort((a, b) => a.elevation - b.elevation);\n return [{ kind: \"create\", entity: \"floor\", id: copy.id }];\n }\n return [];\n });\n}\n\nexport function reorderFloor(\n doc: BuildingDocument,\n floorId: string,\n newElevation: number,\n): CommandResult {\n return mutate(doc, (draft) => {\n const floor = requireFloor(draft, floorId);\n floor.elevation = newElevation;\n for (const building of draft.buildings) {\n building.floors.sort((a, b) => a.elevation - b.elevation);\n }\n return [{ kind: \"update\", entity: \"floor\", id: floorId }];\n });\n}\n\nexport function updateFloor(\n doc: BuildingDocument,\n floorId: string,\n patch: Partial<Pick<Floor, \"name\" | \"elevation\" | \"height\" | \"visible\" | \"locked\">>,\n): CommandResult {\n return mutate(doc, (draft) => {\n const floor = requireFloor(draft, floorId);\n Object.assign(floor, patch);\n return [{ kind: \"update\", entity: \"floor\", id: floorId }];\n });\n}\n\nexport function deleteFloor(doc: BuildingDocument, floorId: string): CommandResult {\n return mutate(doc, (draft) => {\n for (const building of draft.buildings) {\n const idx = building.floors.findIndex((f) => f.id === floorId);\n if (idx === -1) continue;\n building.floors.splice(idx, 1);\n return [{ kind: \"delete\", entity: \"floor\", id: floorId }];\n }\n return [];\n });\n}\n\n// --- internals -------------------------------------------------------------\n\nfunction allFloorsOf(doc: BuildingDocument): Floor[] {\n return doc.buildings.flatMap((b) => b.floors);\n}\n\n/** Clamp openings so they stay attached after a wall changes length. */\nfunction reattachOpenings(floor: Floor, wall: Wall, warnings: ModelWarning[]): void {\n const wl: WallLike = wall;\n const len = wallLength(wl);\n for (const opening of floor.openings) {\n if (opening.wallId !== wall.id) continue;\n const half = opening.width / 2;\n const clamped = Math.min(Math.max(opening.offset, half), Math.max(half, len - half));\n if (clamped !== opening.offset) {\n opening.offset = clamped;\n warnings.push({\n code: \"opening-reclamped\",\n message: `Opening ${opening.id} re-positioned to stay on wall`,\n entityId: opening.id,\n });\n }\n }\n}\n","import { createId } from \"@react-arch/shared\";\nimport type { BuildingDocument } from \"./model.js\";\n\nexport interface HistoryEntry {\n id: string;\n label: string;\n before: BuildingDocument;\n after: BuildingDocument;\n}\n\n/**\n * Command-based undo/redo. Keeps full document snapshots per entry which is\n * simple and correct for the MVP; this can later move to patches / op logs\n * without changing the public surface.\n */\nexport class History {\n private past: HistoryEntry[] = [];\n private future: HistoryEntry[] = [];\n\n constructor(private limit = 200) {}\n\n push(label: string, before: BuildingDocument, after: BuildingDocument): void {\n this.past.push({ id: createId(\"hist\"), label, before, after });\n if (this.past.length > this.limit) this.past.shift();\n this.future = [];\n }\n\n canUndo(): boolean {\n return this.past.length > 0;\n }\n\n canRedo(): boolean {\n return this.future.length > 0;\n }\n\n undo(): BuildingDocument | null {\n const entry = this.past.pop();\n if (!entry) return null;\n this.future.push(entry);\n return entry.before;\n }\n\n redo(): BuildingDocument | null {\n const entry = this.future.pop();\n if (!entry) return null;\n this.past.push(entry);\n return entry.after;\n }\n\n get undoLabel(): string | null {\n return this.past.at(-1)?.label ?? null;\n }\n\n get redoLabel(): string | null {\n return this.future.at(-1)?.label ?? null;\n }\n\n clear(): void {\n this.past = [];\n this.future = [];\n }\n}\n","import { MODEL_VERSION, type BuildingDocument } from \"./model.js\";\n\n/**\n * Migration registry. Each migration upgrades a document one version forward.\n * Add new entries as the schema evolves; `migrate` chains them in order.\n */\ntype Migration = (doc: Record<string, unknown>) => Record<string, unknown>;\n\nconst migrations: Record<string, Migration> = {\n // Example placeholder for the first real migration:\n // \"0.0.1\": (doc) => ({ ...doc, version: \"0.1.0\", assets: doc.assets ?? [] }),\n};\n\nexport function migrate(input: Record<string, unknown>): Record<string, unknown> {\n let doc = { ...input };\n let guard = 0;\n while (doc.version !== MODEL_VERSION && guard < 50) {\n const m = migrations[doc.version as string];\n if (!m) break; // No path forward; validation will report the mismatch.\n doc = m(doc);\n guard += 1;\n }\n return doc;\n}\n\nexport function serialize(doc: BuildingDocument): string {\n return JSON.stringify(doc, null, 2);\n}\n\nexport function deserialize(json: string): BuildingDocument {\n const raw = JSON.parse(json) as Record<string, unknown>;\n return migrate(raw) as unknown as BuildingDocument;\n}\n\nexport function isCompatibleVersion(version: string): boolean {\n // Same major.minor is considered compatible for the MVP.\n const [a, b] = version.split(\".\");\n const [ca, cb] = MODEL_VERSION.split(\".\");\n return a === ca && b === cb;\n}\n","import { createId } from \"@react-arch/shared\";\nimport type { BuildingDocument, Material } from \"./model.js\";\nimport { MODEL_VERSION } from \"./model.js\";\n\nexport const DEFAULT_MATERIALS: Material[] = [\n { id: \"mat-plaster\", name: \"White Plaster\", category: \"wall\", baseColor: \"#e8e6e1\", roughness: 0.9 },\n { id: \"mat-concrete\", name: \"Concrete\", category: \"wall\", baseColor: \"#9b9b97\", roughness: 0.8 },\n { id: \"mat-oak\", name: \"Oak Floor\", category: \"floor\", baseColor: \"#b88a52\", roughness: 0.6 },\n { id: \"mat-dark-wood\", name: \"Dark Wood\", category: \"wood\", baseColor: \"#4a3525\", roughness: 0.5 },\n { id: \"mat-glass\", name: \"Glass\", category: \"glass\", baseColor: \"#bcd6e6\", opacity: 0.35, roughness: 0.05, metalness: 0.1 },\n { id: \"mat-metal\", name: \"Metal\", category: \"metal\", baseColor: \"#8a8d91\", metalness: 0.9, roughness: 0.3 },\n { id: \"mat-tile\", name: \"Ceramic Tile\", category: \"ceramic\", baseColor: \"#d8dcdd\", roughness: 0.4 },\n];\n\nexport interface EmptyDocumentOptions {\n name?: string;\n units?: \"metric\" | \"imperial\";\n buildingName?: string;\n}\n\nexport function createEmptyDocument(\n options: EmptyDocumentOptions = {},\n): BuildingDocument {\n const buildingId = createId(\"bld\");\n return {\n id: createId(\"doc\"),\n version: MODEL_VERSION,\n name: options.name ?? \"Untitled\",\n units: options.units ?? \"metric\",\n buildings: [\n {\n id: buildingId,\n name: options.buildingName ?? options.name ?? \"Building\",\n floors: [],\n },\n ],\n materials: [...DEFAULT_MATERIALS],\n assets: [],\n metadata: {},\n };\n}\n","import type { Vec3 } from \"@react-arch/shared\";\n\n/**\n * Placeholder furniture geometry. Each entry is the base footprint (metres) at\n * scale 1: `w` along plan X, `d` along plan Y, `h` vertical. A building object's\n * `scale` multiplies these. Intentionally simple boxes for the MVP — no\n * photorealistic assets.\n */\nexport interface FurnitureDims {\n width: number;\n depth: number;\n height: number;\n}\n\nconst CATALOG: Record<string, FurnitureDims> = {\n bed: { width: 1.0, depth: 1.0, height: 0.5 },\n sofa: { width: 2.0, depth: 0.9, height: 0.75 },\n table: { width: 1.2, depth: 0.8, height: 0.74 },\n desk: { width: 1.2, depth: 0.6, height: 0.74 },\n chair: { width: 0.5, depth: 0.5, height: 0.9 },\n sink: { width: 0.5, depth: 0.42, height: 0.85 },\n toilet: { width: 0.4, depth: 0.6, height: 0.78 },\n shower: { width: 0.9, depth: 0.9, height: 0.12 },\n \"kitchen counter\": { width: 1.0, depth: 0.6, height: 0.9 },\n wardrobe: { width: 1.2, depth: 0.6, height: 2.0 },\n};\n\nconst DEFAULT_DIMS: FurnitureDims = { width: 0.6, depth: 0.6, height: 0.6 };\n\nexport const FURNITURE_TYPES = Object.keys(CATALOG);\n\n/** Resolve the footprint of a furniture type, applying its scale. */\nexport function furnitureDims(type: string, scale: Vec3 = [1, 1, 1]): FurnitureDims {\n const base = CATALOG[type] ?? DEFAULT_DIMS;\n return {\n width: base.width * scale[0],\n depth: base.depth * scale[1],\n height: base.height * scale[2],\n };\n}\n\n/** A subtle per-category colour for the placeholder geometry. */\nexport function furnitureColor(type: string): string {\n if (type === \"shower\" || type === \"sink\" || type === \"toilet\") return \"#9fb6c2\";\n if (type.includes(\"counter\") || type === \"table\" || type === \"desk\") return \"#9c7b54\";\n if (type === \"bed\" || type === \"sofa\") return \"#7c8aa0\";\n return \"#8a8f99\";\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["wl"],"sources":["../src/model.ts","../src/commands.ts","../src/history.ts","../src/serialize.ts","../src/defaults.ts","../src/furniture.ts"],"sourcesContent":["import type { Units, Vec2, Vec3 } from \"@react-arch/shared\";\n\n/** The current on-disk model version. Bump when the schema changes. */\nexport const MODEL_VERSION = \"0.1.0\";\n\nexport type OpeningType = \"door\" | \"window\" | \"opening\";\nexport type SwingDirection = \"in\" | \"out\";\nexport type HingeSide = \"left\" | \"right\";\n\nexport interface Wall {\n id: string;\n floorId: string;\n start: Vec2;\n end: Vec2;\n thickness: number;\n height: number;\n materialId?: string;\n layerId?: string;\n locked?: boolean;\n}\n\nexport interface Opening {\n id: string;\n floorId: string;\n wallId: string;\n type: OpeningType;\n /** Distance along the wall centerline to the opening center. */\n offset: number;\n width: number;\n height: number;\n sillHeight: number;\n swing?: SwingDirection;\n hinge?: HingeSide;\n materialId?: string;\n}\n\nexport interface Room {\n id: string;\n floorId: string;\n name: string;\n /** Explicit polygon (metres). Rooms may also be derived from wall loops. */\n polygon: Vec2[];\n boundaryWallIds?: string[];\n floorMaterialId?: string;\n ceilingMaterialId?: string;\n usageType?: string;\n height?: number;\n}\n\nexport interface BuildingObject {\n id: string;\n floorId: string;\n type: string;\n position: Vec3;\n rotation: Vec3;\n scale: Vec3;\n assetId?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface Floor {\n id: string;\n buildingId: string;\n name: string;\n elevation: number;\n height: number;\n visible: boolean;\n locked: boolean;\n walls: Wall[];\n rooms: Room[];\n openings: Opening[];\n objects: BuildingObject[];\n}\n\nexport interface Building {\n id: string;\n name: string;\n floors: Floor[];\n}\n\nexport type MaterialCategory =\n | \"wall\"\n | \"floor\"\n | \"ceiling\"\n | \"glass\"\n | \"wood\"\n | \"metal\"\n | \"ceramic\"\n | \"custom\";\n\nexport interface Material {\n id: string;\n name: string;\n category: MaterialCategory;\n baseColor: string;\n roughness?: number;\n metalness?: number;\n opacity?: number;\n textureUrl?: string;\n}\n\nexport interface Asset {\n id: string;\n name: string;\n url?: string;\n kind: string;\n}\n\nexport interface Site {\n id: string;\n name: string;\n polygon?: Vec2[];\n}\n\nexport interface BuildingDocument {\n id: string;\n version: string;\n name: string;\n units: Units;\n site?: Site;\n buildings: Building[];\n materials: Material[];\n assets: Asset[];\n metadata: Record<string, unknown>;\n}\n\n/** A single semantic change emitted by a command. */\nexport interface ModelChange {\n kind: \"create\" | \"update\" | \"delete\";\n entity: \"wall\" | \"room\" | \"opening\" | \"floor\" | \"object\" | \"document\";\n id: string;\n}\n\nexport interface ModelWarning {\n code: string;\n message: string;\n entityId?: string;\n}\n\nexport interface CommandResult {\n document: BuildingDocument;\n changes: ModelChange[];\n warnings: ModelWarning[];\n}\n\n// ---------------------------------------------------------------------------\n// Read helpers\n// ---------------------------------------------------------------------------\n\nexport function findFloor(\n doc: BuildingDocument,\n floorId: string,\n): { building: Building; floor: Floor } | undefined {\n for (const building of doc.buildings) {\n const floor = building.floors.find((f) => f.id === floorId);\n if (floor) return { building, floor };\n }\n return undefined;\n}\n\nexport function allFloors(doc: BuildingDocument): Floor[] {\n return doc.buildings.flatMap((b) => b.floors);\n}\n\nexport function findWall(doc: BuildingDocument, wallId: string): Wall | undefined {\n for (const floor of allFloors(doc)) {\n const w = floor.walls.find((x) => x.id === wallId);\n if (w) return w;\n }\n return undefined;\n}\n\nexport function findRoom(doc: BuildingDocument, roomId: string): Room | undefined {\n for (const floor of allFloors(doc)) {\n const r = floor.rooms.find((x) => x.id === roomId);\n if (r) return r;\n }\n return undefined;\n}\n\nexport function findOpening(\n doc: BuildingDocument,\n openingId: string,\n): Opening | undefined {\n for (const floor of allFloors(doc)) {\n const o = floor.openings.find((x) => x.id === openingId);\n if (o) return o;\n }\n return undefined;\n}\n\nexport type EntityKind = \"wall\" | \"room\" | \"opening\" | \"floor\" | \"object\";\n\nexport interface EntityRef {\n kind: EntityKind;\n id: string;\n}\n","import { createId, deepClone, type Vec2 } from \"@react-arch/shared\";\nimport { openingFits, wallLength, type WallLike } from \"@react-arch/geometry\";\nimport {\n type BuildingDocument,\n type CommandResult,\n type Floor,\n type ModelChange,\n type ModelWarning,\n type Opening,\n type OpeningType,\n type Room,\n type Wall,\n findFloor,\n} from \"./model.js\";\n\n/**\n * Commands are pure: they take a document and return a brand-new document plus\n * a list of changes and warnings. They never mutate the input. The studio /\n * editor layers feed these into the history stack for undo/redo.\n */\n\nfunction mutate(\n doc: BuildingDocument,\n fn: (draft: BuildingDocument, warnings: ModelWarning[]) => ModelChange[],\n): CommandResult {\n const draft = deepClone(doc);\n const warnings: ModelWarning[] = [];\n const changes = fn(draft, warnings);\n return { document: draft, changes, warnings };\n}\n\nfunction requireFloor(doc: BuildingDocument, floorId: string): Floor {\n const found = findFloor(doc, floorId);\n if (!found) throw new Error(`Floor not found: ${floorId}`);\n return found.floor;\n}\n\nfunction cloneVec2(v: Vec2): Vec2 {\n return [v[0], v[1]];\n}\n\n// --- Walls -----------------------------------------------------------------\n\nexport interface CreateWallInput {\n floorId: string;\n start: Vec2;\n end: Vec2;\n thickness?: number;\n height?: number;\n materialId?: string;\n id?: string;\n}\n\nexport function createWall(\n doc: BuildingDocument,\n input: CreateWallInput,\n): CommandResult {\n return mutate(doc, (draft) => {\n const floor = requireFloor(draft, input.floorId);\n const wall: Wall = {\n id: input.id ?? createId(\"wall\"),\n floorId: input.floorId,\n start: cloneVec2(input.start),\n end: cloneVec2(input.end),\n thickness: input.thickness ?? 0.2,\n height: input.height ?? floor.height,\n materialId: input.materialId,\n };\n floor.walls.push(wall);\n return [{ kind: \"create\", entity: \"wall\", id: wall.id }];\n });\n}\n\nexport function updateWall(\n doc: BuildingDocument,\n wallId: string,\n patch: Partial<Omit<Wall, \"id\" | \"floorId\">>,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n for (const floor of allFloorsOf(draft)) {\n const wall = floor.walls.find((w) => w.id === wallId);\n if (!wall) continue;\n Object.assign(wall, deepClone(patch));\n reattachOpenings(floor, wall, warnings);\n return [{ kind: \"update\", entity: \"wall\", id: wallId }];\n }\n warnings.push({ code: \"wall-missing\", message: `Wall ${wallId} not found` });\n return [];\n });\n}\n\n/** Move a wall's endpoints, keeping attached openings within bounds. */\nexport function moveWall(\n doc: BuildingDocument,\n wallId: string,\n start: Vec2,\n end: Vec2,\n): CommandResult {\n return updateWall(doc, wallId, { start, end });\n}\n\nexport function deleteWall(doc: BuildingDocument, wallId: string): CommandResult {\n return mutate(doc, (draft) => {\n const changes: ModelChange[] = [];\n for (const floor of allFloorsOf(draft)) {\n const idx = floor.walls.findIndex((w) => w.id === wallId);\n if (idx === -1) continue;\n floor.walls.splice(idx, 1);\n changes.push({ kind: \"delete\", entity: \"wall\", id: wallId });\n for (const room of floor.rooms) {\n if (!room.boundaryWallIds?.includes(wallId)) continue;\n room.boundaryWallIds = room.boundaryWallIds.filter((id) => id !== wallId);\n changes.push({ kind: \"update\", entity: \"room\", id: room.id });\n }\n // Cascade: drop openings attached to the wall.\n floor.openings = floor.openings.filter((o) => {\n if (o.wallId === wallId) {\n changes.push({ kind: \"delete\", entity: \"opening\", id: o.id });\n return false;\n }\n return true;\n });\n break;\n }\n return changes;\n });\n}\n\n// --- Rooms -----------------------------------------------------------------\n\nexport interface CreateRoomInput {\n floorId: string;\n name: string;\n polygon: Vec2[];\n id?: string;\n floorMaterialId?: string;\n ceilingMaterialId?: string;\n usageType?: string;\n}\n\n/** Convenience: build a rectangular room from origin + size. */\nexport function rectRoomPolygon(\n x: number,\n y: number,\n width: number,\n depth: number,\n): Vec2[] {\n return [\n [x, y],\n [x + width, y],\n [x + width, y + depth],\n [x, y + depth],\n ];\n}\n\nexport function createRoom(\n doc: BuildingDocument,\n input: CreateRoomInput,\n): CommandResult {\n return mutate(doc, (draft) => {\n const floor = requireFloor(draft, input.floorId);\n const room: Room = {\n id: input.id ?? createId(\"room\"),\n floorId: input.floorId,\n name: input.name,\n polygon: input.polygon.map(cloneVec2),\n floorMaterialId: input.floorMaterialId,\n ceilingMaterialId: input.ceilingMaterialId,\n usageType: input.usageType,\n };\n floor.rooms.push(room);\n return [{ kind: \"create\", entity: \"room\", id: room.id }];\n });\n}\n\nexport function updateRoom(\n doc: BuildingDocument,\n roomId: string,\n patch: Partial<Omit<Room, \"id\" | \"floorId\">>,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n for (const floor of allFloorsOf(draft)) {\n const room = floor.rooms.find((r) => r.id === roomId);\n if (!room) continue;\n Object.assign(room, deepClone(patch));\n return [{ kind: \"update\", entity: \"room\", id: roomId }];\n }\n warnings.push({ code: \"room-missing\", message: `Room ${roomId} not found` });\n return [];\n });\n}\n\nexport function deleteRoom(doc: BuildingDocument, roomId: string): CommandResult {\n return mutate(doc, (draft) => {\n for (const floor of allFloorsOf(draft)) {\n const idx = floor.rooms.findIndex((r) => r.id === roomId);\n if (idx === -1) continue;\n floor.rooms.splice(idx, 1);\n return [{ kind: \"delete\", entity: \"room\", id: roomId }];\n }\n return [];\n });\n}\n\n// --- Openings --------------------------------------------------------------\n\nexport interface CreateOpeningInput {\n wallId: string;\n type: OpeningType;\n offset: number;\n width: number;\n height: number;\n sillHeight?: number;\n id?: string;\n}\n\nexport function createOpening(\n doc: BuildingDocument,\n input: CreateOpeningInput,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n for (const floor of allFloorsOf(draft)) {\n const wall = floor.walls.find((w) => w.id === input.wallId);\n if (!wall) continue;\n const opening: Opening = {\n id: input.id ?? createId(\"opening\"),\n floorId: floor.id,\n wallId: input.wallId,\n type: input.type,\n offset: input.offset,\n width: input.width,\n height: input.height,\n sillHeight: input.sillHeight ?? (input.type === \"window\" ? 0.9 : 0),\n };\n if (!openingFits(wall, opening)) {\n warnings.push({\n code: \"opening-overflow\",\n message: `Opening ${opening.id} does not fit within wall ${wall.id}`,\n entityId: opening.id,\n });\n }\n floor.openings.push(opening);\n return [{ kind: \"create\", entity: \"opening\", id: opening.id }];\n }\n warnings.push({\n code: \"wall-missing\",\n message: `Wall ${input.wallId} not found for opening`,\n });\n return [];\n });\n}\n\nexport function updateOpening(\n doc: BuildingDocument,\n openingId: string,\n patch: Partial<Omit<Opening, \"id\" | \"floorId\" | \"wallId\">>,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n for (const floor of allFloorsOf(draft)) {\n const opening = floor.openings.find((o) => o.id === openingId);\n if (!opening) continue;\n Object.assign(opening, patch);\n const wall = floor.walls.find((w) => w.id === opening.wallId);\n if (wall && !openingFits(wall, opening)) {\n warnings.push({\n code: \"opening-overflow\",\n message: `Opening ${opening.id} no longer fits its wall`,\n entityId: opening.id,\n });\n }\n return [{ kind: \"update\", entity: \"opening\", id: openingId }];\n }\n return [];\n });\n}\n\nexport function moveOpening(\n doc: BuildingDocument,\n openingId: string,\n offset: number,\n): CommandResult {\n return updateOpening(doc, openingId, { offset });\n}\n\nexport function deleteOpening(\n doc: BuildingDocument,\n openingId: string,\n): CommandResult {\n return mutate(doc, (draft) => {\n for (const floor of allFloorsOf(draft)) {\n const idx = floor.openings.findIndex((o) => o.id === openingId);\n if (idx === -1) continue;\n floor.openings.splice(idx, 1);\n return [{ kind: \"delete\", entity: \"opening\", id: openingId }];\n }\n return [];\n });\n}\n\n// --- Floors ----------------------------------------------------------------\n\nexport interface CreateFloorInput {\n buildingId: string;\n name: string;\n elevation: number;\n height?: number;\n id?: string;\n}\n\nexport function createFloor(\n doc: BuildingDocument,\n input: CreateFloorInput,\n): CommandResult {\n return mutate(doc, (draft, warnings) => {\n const building = draft.buildings.find((b) => b.id === input.buildingId);\n if (!building) {\n warnings.push({ code: \"building-missing\", message: \"Building not found\" });\n return [];\n }\n const floor: Floor = {\n id: input.id ?? createId(\"floor\"),\n buildingId: building.id,\n name: input.name,\n elevation: input.elevation,\n height: input.height ?? 2.8,\n visible: true,\n locked: false,\n walls: [],\n rooms: [],\n openings: [],\n objects: [],\n };\n building.floors.push(floor);\n building.floors.sort((a, b) => a.elevation - b.elevation);\n return [{ kind: \"create\", entity: \"floor\", id: floor.id }];\n });\n}\n\nexport function duplicateFloor(\n doc: BuildingDocument,\n floorId: string,\n): CommandResult {\n return mutate(doc, (draft) => {\n for (const building of draft.buildings) {\n const floor = building.floors.find((f) => f.id === floorId);\n if (!floor) continue;\n const idMap = new Map<string, string>();\n const copy: Floor = deepClone(floor);\n copy.id = createId(\"floor\");\n copy.name = `${floor.name} (copy)`;\n copy.elevation = floor.elevation + floor.height;\n // Re-id child entities and keep opening→wall references consistent.\n copy.walls.forEach((w) => {\n const nid = createId(\"wall\");\n idMap.set(w.id, nid);\n w.id = nid;\n w.floorId = copy.id;\n });\n copy.openings.forEach((o) => {\n o.id = createId(\"opening\");\n o.floorId = copy.id;\n o.wallId = idMap.get(o.wallId) ?? o.wallId;\n });\n copy.rooms.forEach((r) => {\n r.id = createId(\"room\");\n r.floorId = copy.id;\n if (r.boundaryWallIds) {\n r.boundaryWallIds = r.boundaryWallIds.map((id) => idMap.get(id) ?? id);\n }\n });\n copy.objects.forEach((ob) => {\n ob.id = createId(\"object\");\n ob.floorId = copy.id;\n });\n building.floors.push(copy);\n building.floors.sort((a, b) => a.elevation - b.elevation);\n return [{ kind: \"create\", entity: \"floor\", id: copy.id }];\n }\n return [];\n });\n}\n\nexport function reorderFloor(\n doc: BuildingDocument,\n floorId: string,\n newElevation: number,\n): CommandResult {\n return mutate(doc, (draft) => {\n const floor = requireFloor(draft, floorId);\n floor.elevation = newElevation;\n for (const building of draft.buildings) {\n building.floors.sort((a, b) => a.elevation - b.elevation);\n }\n return [{ kind: \"update\", entity: \"floor\", id: floorId }];\n });\n}\n\nexport function updateFloor(\n doc: BuildingDocument,\n floorId: string,\n patch: Partial<Pick<Floor, \"name\" | \"elevation\" | \"height\" | \"visible\" | \"locked\">>,\n): CommandResult {\n return mutate(doc, (draft) => {\n const floor = requireFloor(draft, floorId);\n Object.assign(floor, patch);\n return [{ kind: \"update\", entity: \"floor\", id: floorId }];\n });\n}\n\nexport function deleteFloor(doc: BuildingDocument, floorId: string): CommandResult {\n return mutate(doc, (draft) => {\n for (const building of draft.buildings) {\n const idx = building.floors.findIndex((f) => f.id === floorId);\n if (idx === -1) continue;\n building.floors.splice(idx, 1);\n return [{ kind: \"delete\", entity: \"floor\", id: floorId }];\n }\n return [];\n });\n}\n\n// --- internals -------------------------------------------------------------\n\nfunction allFloorsOf(doc: BuildingDocument): Floor[] {\n return doc.buildings.flatMap((b) => b.floors);\n}\n\n/** Clamp openings so they stay attached after a wall changes length. */\nfunction reattachOpenings(floor: Floor, wall: Wall, warnings: ModelWarning[]): void {\n const wl: WallLike = wall;\n const len = wallLength(wl);\n for (const opening of floor.openings) {\n if (opening.wallId !== wall.id) continue;\n const half = opening.width / 2;\n const clamped = Math.min(Math.max(opening.offset, half), Math.max(half, len - half));\n if (clamped !== opening.offset) {\n opening.offset = clamped;\n warnings.push({\n code: \"opening-reclamped\",\n message: `Opening ${opening.id} re-positioned to stay on wall`,\n entityId: opening.id,\n });\n }\n }\n}\n","import { createId, deepClone } from \"@react-arch/shared\";\nimport type { BuildingDocument } from \"./model.js\";\n\nexport interface HistoryEntry {\n id: string;\n label: string;\n before: BuildingDocument;\n after: BuildingDocument;\n}\n\n/**\n * Command-based undo/redo. Keeps full document snapshots per entry which is\n * simple and correct for the MVP; this can later move to patches / op logs\n * without changing the public surface.\n */\nexport class History {\n private past: HistoryEntry[] = [];\n private future: HistoryEntry[] = [];\n\n constructor(private limit = 200) {}\n\n push(label: string, before: BuildingDocument, after: BuildingDocument): void {\n this.past.push({ id: createId(\"hist\"), label, before: deepClone(before), after: deepClone(after) });\n if (this.past.length > this.limit) this.past.shift();\n this.future = [];\n }\n\n canUndo(): boolean {\n return this.past.length > 0;\n }\n\n canRedo(): boolean {\n return this.future.length > 0;\n }\n\n undo(): BuildingDocument | null {\n const entry = this.past.pop();\n if (!entry) return null;\n this.future.push(entry);\n return deepClone(entry.before);\n }\n\n redo(): BuildingDocument | null {\n const entry = this.future.pop();\n if (!entry) return null;\n this.past.push(entry);\n return deepClone(entry.after);\n }\n\n get undoLabel(): string | null {\n return this.past.at(-1)?.label ?? null;\n }\n\n get redoLabel(): string | null {\n return this.future.at(-1)?.label ?? null;\n }\n\n clear(): void {\n this.past = [];\n this.future = [];\n }\n}\n","import { MODEL_VERSION, type BuildingDocument } from \"./model.js\";\n\n/**\n * Migration registry. Each migration upgrades a document one version forward.\n * Add new entries as the schema evolves; `migrate` chains them in order.\n */\ntype Migration = (doc: Record<string, unknown>) => Record<string, unknown>;\n\nconst migrations: Record<string, Migration> = {\n // Example placeholder for the first real migration:\n // \"0.0.1\": (doc) => ({ ...doc, version: \"0.1.0\", assets: doc.assets ?? [] }),\n};\n\nexport function migrate(input: Record<string, unknown>): Record<string, unknown> {\n let doc = { ...input };\n let guard = 0;\n while (doc.version !== MODEL_VERSION && guard < 50) {\n const m = migrations[doc.version as string];\n if (!m) break; // No path forward; validation will report the mismatch.\n doc = m(doc);\n guard += 1;\n }\n return doc;\n}\n\nexport function serialize(doc: BuildingDocument): string {\n return JSON.stringify(doc, null, 2);\n}\n\nexport function deserialize(json: string): BuildingDocument {\n const raw = JSON.parse(json) as Record<string, unknown>;\n return migrate(raw) as unknown as BuildingDocument;\n}\n\nexport function isCompatibleVersion(version: string): boolean {\n // Same major.minor is considered compatible for the MVP.\n const [a, b] = version.split(\".\");\n const [ca, cb] = MODEL_VERSION.split(\".\");\n return a === ca && b === cb;\n}\n","import { createId } from \"@react-arch/shared\";\nimport type { BuildingDocument, Material } from \"./model.js\";\nimport { MODEL_VERSION } from \"./model.js\";\n\nexport const DEFAULT_MATERIALS: Material[] = [\n { id: \"mat-plaster\", name: \"White Plaster\", category: \"wall\", baseColor: \"#e8e6e1\", roughness: 0.9 },\n { id: \"mat-concrete\", name: \"Concrete\", category: \"wall\", baseColor: \"#9b9b97\", roughness: 0.8 },\n { id: \"mat-oak\", name: \"Oak Floor\", category: \"floor\", baseColor: \"#b88a52\", roughness: 0.6 },\n { id: \"mat-dark-wood\", name: \"Dark Wood\", category: \"wood\", baseColor: \"#4a3525\", roughness: 0.5 },\n { id: \"mat-glass\", name: \"Glass\", category: \"glass\", baseColor: \"#bcd6e6\", opacity: 0.35, roughness: 0.05, metalness: 0.1 },\n { id: \"mat-metal\", name: \"Metal\", category: \"metal\", baseColor: \"#8a8d91\", metalness: 0.9, roughness: 0.3 },\n { id: \"mat-tile\", name: \"Ceramic Tile\", category: \"ceramic\", baseColor: \"#d8dcdd\", roughness: 0.4 },\n];\n\nexport interface EmptyDocumentOptions {\n name?: string;\n units?: \"metric\" | \"imperial\";\n buildingName?: string;\n}\n\nexport function createEmptyDocument(\n options: EmptyDocumentOptions = {},\n): BuildingDocument {\n const buildingId = createId(\"bld\");\n return {\n id: createId(\"doc\"),\n version: MODEL_VERSION,\n name: options.name ?? \"Untitled\",\n units: options.units ?? \"metric\",\n buildings: [\n {\n id: buildingId,\n name: options.buildingName ?? options.name ?? \"Building\",\n floors: [],\n },\n ],\n materials: DEFAULT_MATERIALS.map((m) => ({ ...m })),\n assets: [],\n metadata: {},\n };\n}\n","import type { Vec3 } from \"@react-arch/shared\";\n\n/**\n * Placeholder furniture geometry. Each entry is the base footprint (metres) at\n * scale 1: `w` along plan X, `d` along plan Y, `h` vertical. A building object's\n * `scale` multiplies these. Intentionally simple boxes for the MVP — no\n * photorealistic assets.\n */\nexport interface FurnitureDims {\n width: number;\n depth: number;\n height: number;\n}\n\nconst CATALOG: Record<string, FurnitureDims> = {\n bed: { width: 1.0, depth: 1.0, height: 0.5 },\n sofa: { width: 2.0, depth: 0.9, height: 0.75 },\n table: { width: 1.2, depth: 0.8, height: 0.74 },\n desk: { width: 1.2, depth: 0.6, height: 0.74 },\n chair: { width: 0.5, depth: 0.5, height: 0.9 },\n sink: { width: 0.5, depth: 0.42, height: 0.85 },\n toilet: { width: 0.4, depth: 0.6, height: 0.78 },\n shower: { width: 0.9, depth: 0.9, height: 0.12 },\n \"kitchen counter\": { width: 1.0, depth: 0.6, height: 0.9 },\n wardrobe: { width: 1.2, depth: 0.6, height: 2.0 },\n};\n\nconst DEFAULT_DIMS: FurnitureDims = { width: 0.6, depth: 0.6, height: 0.6 };\n\nexport const FURNITURE_TYPES = Object.keys(CATALOG);\n\n/** Resolve the footprint of a furniture type, applying its scale. */\nexport function furnitureDims(type: string, scale: Vec3 = [1, 1, 1]): FurnitureDims {\n const base = CATALOG[type] ?? DEFAULT_DIMS;\n return {\n width: base.width * scale[0],\n depth: base.depth * scale[1],\n height: base.height * scale[2],\n };\n}\n\n/** A subtle per-category colour for the placeholder geometry. */\nexport function furnitureColor(type: string): string {\n if (type === \"shower\" || type === \"sink\" || type === \"toilet\") return \"#9fb6c2\";\n if (type.includes(\"counter\") || type === \"table\" || type === \"desk\") return \"#9c7b54\";\n if (type === \"bed\" || type === \"sofa\") return \"#7c8aa0\";\n return \"#8a8f99\";\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-arch/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@react-arch/
|
|
16
|
-
"@react-arch/
|
|
15
|
+
"@react-arch/shared": "0.1.3",
|
|
16
|
+
"@react-arch/geometry": "0.1.3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"typescript": "^5.7.2",
|