@react-arch/react 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 +149 -50
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/tags.ts","../src/components.tsx","../src/registry.ts","../src/renderer.ts","../src/convert.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/tags.ts","../src/components.tsx","../src/registry.ts","../src/renderer.ts","../src/convert.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createElement, useEffect } from "react";
|
|
2
2
|
import Reconciler from "react-reconciler";
|
|
3
|
-
import {
|
|
4
|
-
import { normalize, sub } from "@react-arch/geometry";
|
|
3
|
+
import { round } from "@react-arch/shared";
|
|
4
|
+
import { dot, normal, normalize, scale, sub } from "@react-arch/geometry";
|
|
5
5
|
import { DEFAULT_MATERIALS, MODEL_VERSION } from "@react-arch/core";
|
|
6
6
|
//#region src/tags.ts
|
|
7
7
|
/**
|
|
@@ -174,6 +174,27 @@ function str(props, key) {
|
|
|
174
174
|
function vec2(v) {
|
|
175
175
|
if (Array.isArray(v) && v.length === 2 && typeof v[0] === "number" && typeof v[1] === "number") return [v[0], v[1]];
|
|
176
176
|
}
|
|
177
|
+
function idPart(value, fallback = "item") {
|
|
178
|
+
return (typeof value === "string" && value.trim() ? value : fallback).toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || fallback;
|
|
179
|
+
}
|
|
180
|
+
function uniqueId(base, used) {
|
|
181
|
+
let id = idPart(base);
|
|
182
|
+
let suffix = 2;
|
|
183
|
+
while (used.has(id)) {
|
|
184
|
+
id = `${idPart(base)}-${suffix}`;
|
|
185
|
+
suffix += 1;
|
|
186
|
+
}
|
|
187
|
+
used.add(id);
|
|
188
|
+
return id;
|
|
189
|
+
}
|
|
190
|
+
function idFromProps(props, base, used) {
|
|
191
|
+
const explicit = str(props, "id");
|
|
192
|
+
if (explicit) {
|
|
193
|
+
used.add(explicit);
|
|
194
|
+
return explicit;
|
|
195
|
+
}
|
|
196
|
+
return uniqueId(base, used);
|
|
197
|
+
}
|
|
177
198
|
/** Expand transparent <Group> nodes and drop text nodes. */
|
|
178
199
|
function flatten(nodes) {
|
|
179
200
|
const out = [];
|
|
@@ -184,10 +205,10 @@ function flatten(nodes) {
|
|
|
184
205
|
}
|
|
185
206
|
return out;
|
|
186
207
|
}
|
|
187
|
-
function toMaterial(node) {
|
|
208
|
+
function toMaterial(node, fallbackId, usedIds) {
|
|
188
209
|
const p = node.props;
|
|
189
210
|
return {
|
|
190
|
-
id:
|
|
211
|
+
id: idFromProps(p, fallbackId, usedIds),
|
|
191
212
|
name: str(p, "name") ?? "Material",
|
|
192
213
|
category: str(p, "category") ?? "custom",
|
|
193
214
|
baseColor: str(p, "baseColor") ?? "#cccccc",
|
|
@@ -214,10 +235,10 @@ const OPENING_DEFAULTS = {
|
|
|
214
235
|
sill: 0
|
|
215
236
|
}
|
|
216
237
|
};
|
|
217
|
-
function toObject(node, floorId) {
|
|
238
|
+
function toObject(node, floorId, fallbackId, usedIds) {
|
|
218
239
|
const p = node.props;
|
|
219
240
|
return {
|
|
220
|
-
id:
|
|
241
|
+
id: idFromProps(p, fallbackId, usedIds),
|
|
221
242
|
floorId,
|
|
222
243
|
type: str(p, "type") ?? "object",
|
|
223
244
|
position: [
|
|
@@ -238,10 +259,10 @@ function toObject(node, floorId) {
|
|
|
238
259
|
assetId: str(p, "assetId")
|
|
239
260
|
};
|
|
240
261
|
}
|
|
241
|
-
function convertFloor(node, buildingId, materials) {
|
|
262
|
+
function convertFloor(node, buildingId, materials, floorIndex, usedIds) {
|
|
242
263
|
const p = node.props;
|
|
243
264
|
const floor = {
|
|
244
|
-
id:
|
|
265
|
+
id: idFromProps(p, `${buildingId}-floor-${floorIndex + 1}`, usedIds),
|
|
245
266
|
buildingId,
|
|
246
267
|
name: str(p, "name") ?? "Floor",
|
|
247
268
|
elevation: num(p, "elevation", 0),
|
|
@@ -253,9 +274,12 @@ function convertFloor(node, buildingId, materials) {
|
|
|
253
274
|
openings: [],
|
|
254
275
|
objects: []
|
|
255
276
|
};
|
|
256
|
-
|
|
277
|
+
let wallIndex = 0;
|
|
278
|
+
let materialIndex = 0;
|
|
279
|
+
let objectIndex = 0;
|
|
280
|
+
const makeWall = (start, end, thickness, materialId, idBase, explicitId) => {
|
|
257
281
|
const w = {
|
|
258
|
-
id:
|
|
282
|
+
id: explicitId ? (usedIds.add(explicitId), explicitId) : uniqueId(idBase, usedIds),
|
|
259
283
|
floorId: floor.id,
|
|
260
284
|
start,
|
|
261
285
|
end,
|
|
@@ -268,20 +292,25 @@ function convertFloor(node, buildingId, materials) {
|
|
|
268
292
|
};
|
|
269
293
|
for (const child of flatten(node.children)) switch (child.tag) {
|
|
270
294
|
case TAG.material:
|
|
271
|
-
|
|
295
|
+
materialIndex += 1;
|
|
296
|
+
materials.push(toMaterial(child, `${floor.id}-material-${materialIndex}`, usedIds));
|
|
272
297
|
break;
|
|
273
298
|
case TAG.wall: {
|
|
274
|
-
const
|
|
275
|
-
|
|
299
|
+
const from = vec2(child.props.from) ?? [0, 0];
|
|
300
|
+
const to = vec2(child.props.to) ?? [0, 0];
|
|
301
|
+
wallIndex += 1;
|
|
302
|
+
const w = makeWall(from, to, num(child.props, "thickness", .2), str(child.props, "materialId"), `${floor.id}-wall-${wallIndex}`, str(child.props, "id"));
|
|
276
303
|
if (typeof child.props.height === "number") w.height = child.props.height;
|
|
277
304
|
break;
|
|
278
305
|
}
|
|
279
306
|
case TAG.room: {
|
|
307
|
+
const roomIndex = floor.rooms.length + 1;
|
|
280
308
|
const x = num(child.props, "x", 0);
|
|
281
309
|
const y = num(child.props, "y", 0);
|
|
282
310
|
const w = num(child.props, "width", 4);
|
|
283
311
|
const d = num(child.props, "depth", 4);
|
|
284
312
|
const thickness = num(child.props, "wallThickness", .2);
|
|
313
|
+
const roomId = idFromProps(child.props, `${floor.id}-room-${roomIndex}`, usedIds);
|
|
285
314
|
const polygon = [
|
|
286
315
|
[x, y],
|
|
287
316
|
[x + w, y],
|
|
@@ -289,7 +318,7 @@ function convertFloor(node, buildingId, materials) {
|
|
|
289
318
|
[x, y + d]
|
|
290
319
|
];
|
|
291
320
|
const room = {
|
|
292
|
-
id:
|
|
321
|
+
id: roomId,
|
|
293
322
|
floorId: floor.id,
|
|
294
323
|
name: str(child.props, "name") ?? "Room",
|
|
295
324
|
polygon,
|
|
@@ -300,15 +329,19 @@ function convertFloor(node, buildingId, materials) {
|
|
|
300
329
|
};
|
|
301
330
|
floor.rooms.push(room);
|
|
302
331
|
const sides = {
|
|
303
|
-
north: makeWall([x, y], [x + w, y], thickness),
|
|
304
|
-
south: makeWall([x, y + d], [x + w, y + d], thickness),
|
|
305
|
-
west: makeWall([x, y], [x, y + d], thickness),
|
|
306
|
-
east: makeWall([x + w, y], [x + w, y + d], thickness)
|
|
332
|
+
north: makeWall([x, y], [x + w, y], thickness, void 0, `${room.id}-wall-north`),
|
|
333
|
+
south: makeWall([x, y + d], [x + w, y + d], thickness, void 0, `${room.id}-wall-south`),
|
|
334
|
+
west: makeWall([x, y], [x, y + d], thickness, void 0, `${room.id}-wall-west`),
|
|
335
|
+
east: makeWall([x + w, y], [x + w, y + d], thickness, void 0, `${room.id}-wall-east`)
|
|
307
336
|
};
|
|
308
337
|
room.boundaryWallIds = Object.values(sides).map((s) => s.id);
|
|
338
|
+
let roomOpeningIndex = 0;
|
|
339
|
+
let roomObjectIndex = 0;
|
|
309
340
|
for (const o of flatten(child.children)) {
|
|
310
341
|
if (o.tag === TAG.furniture) {
|
|
311
|
-
|
|
342
|
+
objectIndex += 1;
|
|
343
|
+
roomObjectIndex += 1;
|
|
344
|
+
floor.objects.push(toObject(o, floor.id, `${room.id}-object-${roomObjectIndex}`, usedIds));
|
|
312
345
|
continue;
|
|
313
346
|
}
|
|
314
347
|
if (o.tag !== TAG.door && o.tag !== TAG.window && o.tag !== TAG.opening) continue;
|
|
@@ -317,8 +350,9 @@ function convertFloor(node, buildingId, materials) {
|
|
|
317
350
|
const side = str(o.props, "wall") ?? "south";
|
|
318
351
|
const wall = sides[side] ?? sides.south;
|
|
319
352
|
const wallLen = side === "north" || side === "south" ? w : d;
|
|
353
|
+
roomOpeningIndex += 1;
|
|
320
354
|
const opening = {
|
|
321
|
-
id:
|
|
355
|
+
id: idFromProps(o.props, `${room.id}-${type}-${side}-${roomOpeningIndex}`, usedIds),
|
|
322
356
|
floorId: floor.id,
|
|
323
357
|
wallId: wall.id,
|
|
324
358
|
type,
|
|
@@ -332,7 +366,8 @@ function convertFloor(node, buildingId, materials) {
|
|
|
332
366
|
break;
|
|
333
367
|
}
|
|
334
368
|
case TAG.furniture:
|
|
335
|
-
|
|
369
|
+
objectIndex += 1;
|
|
370
|
+
floor.objects.push(toObject(child, floor.id, `${floor.id}-object-${objectIndex}`, usedIds));
|
|
336
371
|
break;
|
|
337
372
|
default: break;
|
|
338
373
|
}
|
|
@@ -350,38 +385,98 @@ function convertFloor(node, buildingId, materials) {
|
|
|
350
385
|
* so an interior door becomes a real passage between the rooms.
|
|
351
386
|
*/
|
|
352
387
|
function mergeCoincidentWalls(floor) {
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const
|
|
357
|
-
|
|
388
|
+
const intervalOf = (w) => {
|
|
389
|
+
let d = normalize(sub(w.end, w.start));
|
|
390
|
+
if (d[0] < 0 || d[0] === 0 && d[1] < 0) d = scale(d, -1);
|
|
391
|
+
const n = normal(d);
|
|
392
|
+
const lineOffset = dot(w.start, n);
|
|
393
|
+
const t0 = dot(w.start, d);
|
|
394
|
+
const t1 = dot(w.end, d);
|
|
395
|
+
return {
|
|
396
|
+
wall: w,
|
|
397
|
+
d,
|
|
398
|
+
n,
|
|
399
|
+
lineOffset,
|
|
400
|
+
a: Math.min(t0, t1),
|
|
401
|
+
b: Math.max(t0, t1)
|
|
402
|
+
};
|
|
403
|
+
};
|
|
404
|
+
const key = (i) => {
|
|
405
|
+
if (i.d[0] === 0 && i.d[1] === 0) return `point:${round(i.wall.start[0])},${round(i.wall.start[1])}|${round(i.wall.thickness)}`;
|
|
406
|
+
return `${round(i.d[0])},${round(i.d[1])}|${round(i.lineOffset)}|${round(i.wall.thickness)}`;
|
|
358
407
|
};
|
|
408
|
+
const pointAt = (i, t) => [i.d[0] * t + i.n[0] * i.lineOffset, i.d[1] * t + i.n[1] * i.lineOffset];
|
|
409
|
+
const oldWallById = new Map(floor.walls.map((w) => [w.id, {
|
|
410
|
+
start: [...w.start],
|
|
411
|
+
end: [...w.end]
|
|
412
|
+
}]));
|
|
413
|
+
const openingCenters = /* @__PURE__ */ new Map();
|
|
414
|
+
for (const o of floor.openings) {
|
|
415
|
+
const w = oldWallById.get(o.wallId);
|
|
416
|
+
if (!w) continue;
|
|
417
|
+
const d = normalize(sub(w.end, w.start));
|
|
418
|
+
openingCenters.set(o.id, [w.start[0] + d[0] * o.offset, w.start[1] + d[1] * o.offset]);
|
|
419
|
+
}
|
|
359
420
|
const groups = /* @__PURE__ */ new Map();
|
|
360
421
|
for (const w of floor.walls) {
|
|
361
|
-
const
|
|
422
|
+
const interval = intervalOf(w);
|
|
423
|
+
const k = key(interval);
|
|
362
424
|
const g = groups.get(k);
|
|
363
|
-
if (g) g.push(
|
|
364
|
-
else groups.set(k, [
|
|
425
|
+
if (g) g.push(interval);
|
|
426
|
+
else groups.set(k, [interval]);
|
|
365
427
|
}
|
|
366
428
|
const survivors = [];
|
|
367
429
|
const survivorOf = /* @__PURE__ */ new Map();
|
|
368
|
-
|
|
369
|
-
|
|
430
|
+
let mergedAny = false;
|
|
431
|
+
const flush = (active, a, b) => {
|
|
432
|
+
const survivor = active[0].wall;
|
|
433
|
+
if (active.length > 1) {
|
|
434
|
+
survivor.start = pointAt(active[0], a);
|
|
435
|
+
survivor.end = pointAt(active[0], b);
|
|
436
|
+
mergedAny = true;
|
|
437
|
+
}
|
|
370
438
|
survivors.push(survivor);
|
|
371
|
-
for (const
|
|
439
|
+
for (const i of active) survivorOf.set(i.wall.id, survivor);
|
|
440
|
+
};
|
|
441
|
+
for (const group of groups.values()) {
|
|
442
|
+
if (group.length === 1) {
|
|
443
|
+
const only = group[0];
|
|
444
|
+
survivors.push(only.wall);
|
|
445
|
+
survivorOf.set(only.wall.id, only.wall);
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
const sorted = [...group].sort((a, b) => a.a - b.a);
|
|
449
|
+
let active = [];
|
|
450
|
+
let activeA = 0;
|
|
451
|
+
let activeB = 0;
|
|
452
|
+
for (const interval of sorted) {
|
|
453
|
+
if (active.length === 0) {
|
|
454
|
+
active = [interval];
|
|
455
|
+
activeA = interval.a;
|
|
456
|
+
activeB = interval.b;
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
if (interval.a < activeB - 1e-6) {
|
|
460
|
+
active.push(interval);
|
|
461
|
+
activeA = Math.min(activeA, interval.a);
|
|
462
|
+
activeB = Math.max(activeB, interval.b);
|
|
463
|
+
} else {
|
|
464
|
+
flush(active, activeA, activeB);
|
|
465
|
+
active = [interval];
|
|
466
|
+
activeA = interval.a;
|
|
467
|
+
activeB = interval.b;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
if (active.length > 0) flush(active, activeA, activeB);
|
|
372
471
|
}
|
|
373
|
-
if (
|
|
374
|
-
const wallById = new Map(floor.walls.map((w) => [w.id, w]));
|
|
472
|
+
if (!mergedAny) return;
|
|
375
473
|
for (const o of floor.openings) {
|
|
376
474
|
const survivor = survivorOf.get(o.wallId);
|
|
377
|
-
if (!survivor
|
|
378
|
-
const
|
|
379
|
-
if (
|
|
380
|
-
const od = normalize(sub(orig.end, orig.start));
|
|
381
|
-
const cx = orig.start[0] + od[0] * o.offset;
|
|
382
|
-
const cy = orig.start[1] + od[1] * o.offset;
|
|
475
|
+
if (!survivor) continue;
|
|
476
|
+
const center = openingCenters.get(o.id);
|
|
477
|
+
if (center) {
|
|
383
478
|
const sd = normalize(sub(survivor.end, survivor.start));
|
|
384
|
-
o.offset = (
|
|
479
|
+
o.offset = dot(sub(center, survivor.start), sd);
|
|
385
480
|
}
|
|
386
481
|
o.wallId = survivor.id;
|
|
387
482
|
}
|
|
@@ -395,32 +490,36 @@ function mergeCoincidentWalls(floor) {
|
|
|
395
490
|
*/
|
|
396
491
|
function convert(instances, fallbackName = "Untitled") {
|
|
397
492
|
const tops = flatten(instances);
|
|
398
|
-
const
|
|
399
|
-
|
|
493
|
+
const usedIds = new Set(DEFAULT_MATERIALS.map((m) => m.id));
|
|
494
|
+
const materials = DEFAULT_MATERIALS.map((m) => ({ ...m }));
|
|
495
|
+
let topMaterialIndex = 0;
|
|
496
|
+
for (const n of tops) if (n.tag === TAG.material) {
|
|
497
|
+
topMaterialIndex += 1;
|
|
498
|
+
materials.push(toMaterial(n, `material-${topMaterialIndex}`, usedIds));
|
|
499
|
+
}
|
|
400
500
|
const buildingNodes = tops.filter((n) => n.tag === TAG.building);
|
|
401
501
|
const buildings = [];
|
|
402
502
|
let units = "metric";
|
|
403
503
|
let docName = fallbackName;
|
|
404
|
-
|
|
504
|
+
(buildingNodes.length > 0 ? buildingNodes : [{
|
|
405
505
|
tag: TAG.building,
|
|
406
506
|
props: {},
|
|
407
507
|
children: tops
|
|
408
|
-
}]
|
|
409
|
-
|
|
410
|
-
const buildingId = str(bn.props, "id") ?? createId("bld");
|
|
508
|
+
}]).forEach((bn, buildingIndex) => {
|
|
509
|
+
const buildingId = idFromProps(bn.props, `building-${buildingIndex + 1}`, usedIds);
|
|
411
510
|
const name = str(bn.props, "name") ?? fallbackName;
|
|
412
511
|
if (str(bn.props, "units") === "imperial") units = "imperial";
|
|
413
512
|
docName = name;
|
|
414
|
-
const floors = flatten(bn.children).filter((c) => c.tag === TAG.floor).map((fn) => convertFloor(fn, buildingId, materials));
|
|
513
|
+
const floors = flatten(bn.children).filter((c) => c.tag === TAG.floor).map((fn, floorIndex) => convertFloor(fn, buildingId, materials, floorIndex, usedIds));
|
|
415
514
|
floors.sort((a, b) => a.elevation - b.elevation);
|
|
416
515
|
buildings.push({
|
|
417
516
|
id: buildingId,
|
|
418
517
|
name,
|
|
419
518
|
floors
|
|
420
519
|
});
|
|
421
|
-
}
|
|
520
|
+
});
|
|
422
521
|
return {
|
|
423
|
-
id:
|
|
522
|
+
id: uniqueId(`doc-${docName}`, usedIds),
|
|
424
523
|
version: MODEL_VERSION,
|
|
425
524
|
name: docName,
|
|
426
525
|
units,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/tags.ts","../src/components.tsx","../src/renderer.ts","../src/convert.ts","../src/registry.ts"],"sourcesContent":["/**\n * Internal host element tags. Users never type these — the public components\n * in `components.tsx` create them. The reconciler builds an instance tree of\n * these tags, which `convert.ts` turns into a BuildingDocument.\n */\nexport const TAG = {\n building: \"ra-building\",\n floor: \"ra-floor\",\n room: \"ra-room\",\n wall: \"ra-wall\",\n door: \"ra-door\",\n window: \"ra-window\",\n opening: \"ra-opening\",\n furniture: \"ra-furniture\",\n material: \"ra-material\",\n group: \"ra-group\",\n slab: \"ra-slab\",\n roof: \"ra-roof\",\n stairs: \"ra-stairs\",\n text: \"ra-text\",\n} as const;\n\nexport type Tag = (typeof TAG)[keyof typeof TAG];\n\n/** Side of a rectangular room a door/window attaches to. */\nexport type RoomSide = \"north\" | \"south\" | \"east\" | \"west\";\n","import { createElement, type ReactNode } from \"react\";\nimport { TAG, type RoomSide } from \"./tags.js\";\n\ntype WithChildren<T> = T & { children?: ReactNode };\nconst h = (tag: string, props: object) =>\n createElement(tag, props as Record<string, unknown>);\n\nexport interface BuildingProps {\n id?: string;\n name?: string;\n units?: \"metric\" | \"imperial\";\n}\nexport function Building(props: WithChildren<BuildingProps>) {\n return h(TAG.building, props);\n}\n\nexport interface FloorProps {\n id?: string;\n name?: string;\n elevation?: number;\n height?: number;\n}\nexport function Floor(props: WithChildren<FloorProps>) {\n return h(TAG.floor, props);\n}\n\nexport interface RoomProps {\n id?: string;\n name?: string;\n /** Top-left corner X (metres, X increases right). */\n x?: number;\n /** Top-left corner Y (metres, Y increases down). */\n y?: number;\n /** Extent along X. */\n width?: number;\n /** Extent along Y. */\n depth?: number;\n height?: number;\n wallThickness?: number;\n floorMaterial?: string;\n ceilingMaterial?: string;\n usage?: string;\n}\nexport function Room(props: WithChildren<RoomProps>) {\n return h(TAG.room, props);\n}\n\nexport interface WallProps {\n id?: string;\n from: [number, number];\n to: [number, number];\n thickness?: number;\n height?: number;\n materialId?: string;\n}\nexport function Wall(props: WallProps) {\n return h(TAG.wall, props);\n}\n\nexport interface OpeningCommonProps {\n id?: string;\n /** Which side of the parent room this attaches to. */\n wall?: RoomSide;\n /** Distance along the wall centerline from its start corner. */\n offset?: number;\n width?: number;\n height?: number;\n sillHeight?: number;\n}\nexport function Door(props: OpeningCommonProps) {\n return h(TAG.door, props);\n}\nexport function Window(props: OpeningCommonProps) {\n return h(TAG.window, props);\n}\nexport function Opening(props: OpeningCommonProps) {\n return h(TAG.opening, props);\n}\n\nexport interface FurnitureProps {\n id?: string;\n type: string;\n x?: number;\n y?: number;\n z?: number;\n rotation?: number;\n scaleX?: number;\n scaleY?: number;\n scaleZ?: number;\n assetId?: string;\n}\nexport function Furniture(props: FurnitureProps) {\n return h(TAG.furniture, props);\n}\n/** Alias used inside reusable room modules. */\nexport const Fixture = Furniture;\n\nexport interface MaterialProps {\n id: string;\n name?: string;\n category?: string;\n baseColor: string;\n roughness?: number;\n metalness?: number;\n opacity?: number;\n textureUrl?: string;\n}\nexport function Material(props: MaterialProps) {\n return h(TAG.material, props);\n}\n\nexport function Group(props: WithChildren<{ id?: string }>) {\n return h(TAG.group, props);\n}\n\n// Reserved primitives — accepted in the tree, modelled minimally for the MVP.\nexport function Slab(props: WithChildren<{ id?: string }>) {\n return h(TAG.slab, props);\n}\nexport function Roof(props: WithChildren<{ id?: string; type?: string }>) {\n return h(TAG.roof, props);\n}\nexport function Stairs(props: WithChildren<{ id?: string }>) {\n return h(TAG.stairs, props);\n}\n","import Reconciler from \"react-reconciler\";\nimport type { ReactElement } from \"react\";\n\n/** A node in the intermediate instance tree built by the reconciler. */\nexport interface Instance {\n tag: string;\n props: Record<string, unknown>;\n children: Instance[];\n}\n\nexport interface Container {\n children: Instance[];\n}\n\nfunction stripChildren(props: Record<string, unknown>): Record<string, unknown> {\n const { children, ...rest } = props;\n void children;\n return rest;\n}\n\n// react-reconciler's types are notoriously strict; the host config is plain.\nconst hostConfig: any = {\n supportsMutation: true,\n supportsPersistence: false,\n supportsHydration: false,\n isPrimaryRenderer: false,\n noTimeout: -1,\n now: () => 0,\n\n getRootHostContext: () => ({}),\n getChildHostContext: (parent: unknown) => parent,\n getPublicInstance: (instance: Instance) => instance,\n\n prepareForCommit: () => null,\n resetAfterCommit: () => {},\n preparePortalMount: () => {},\n\n createInstance(tag: string, props: Record<string, unknown>): Instance {\n return { tag, props: stripChildren(props), children: [] };\n },\n\n createTextInstance(text: string): Instance {\n return { tag: \"ra-text\", props: { text }, children: [] };\n },\n\n appendInitialChild(parent: Instance, child: Instance) {\n parent.children.push(child);\n },\n appendChild(parent: Instance, child: Instance) {\n parent.children.push(child);\n },\n appendChildToContainer(container: Container, child: Instance) {\n container.children.push(child);\n },\n\n insertBefore(parent: Instance, child: Instance, before: Instance) {\n const i = parent.children.indexOf(before);\n parent.children.splice(i, 0, child);\n },\n insertInContainerBefore(container: Container, child: Instance, before: Instance) {\n const i = container.children.indexOf(before);\n container.children.splice(i, 0, child);\n },\n\n removeChild(parent: Instance, child: Instance) {\n parent.children = parent.children.filter((c) => c !== child);\n },\n removeChildFromContainer(container: Container, child: Instance) {\n container.children = container.children.filter((c) => c !== child);\n },\n\n finalizeInitialChildren: () => false,\n shouldSetTextContent: () => false,\n clearContainer(container: Container) {\n container.children = [];\n },\n\n prepareUpdate: () => true,\n commitUpdate(instance: Instance, _payload: unknown, _tag: string, _old: unknown, newProps: Record<string, unknown>) {\n instance.props = stripChildren(newProps);\n },\n commitTextUpdate(instance: Instance, _old: string, text: string) {\n instance.props = { text };\n },\n\n getCurrentEventPriority: () => 16,\n detachDeletedInstance: () => {},\n prepareScopeUpdate: () => {},\n getInstanceFromScope: () => null,\n getInstanceFromNode: () => null,\n beforeActiveInstanceBlur: () => {},\n afterActiveInstanceBlur: () => {},\n scheduleTimeout: setTimeout,\n cancelTimeout: clearTimeout,\n};\n\nconst reconciler = Reconciler(hostConfig);\n\nconst LegacyRoot = 0;\n\n/**\n * Render a React element tree through the React Arch reconciler and return the\n * resulting intermediate instance tree. Synchronous (legacy root) so the tree\n * is fully built when this returns.\n */\nexport function renderToInstances(element: ReactElement): Instance[] {\n const container: Container = { children: [] };\n const root = reconciler.createContainer(\n container,\n LegacyRoot,\n null,\n false,\n null,\n \"react-arch\",\n (error: unknown) => {\n // Surface render errors loudly; the studio shows them as diagnostics.\n console.error(\"[react-arch] render error\", error);\n },\n null,\n );\n reconciler.updateContainer(element, root, null, null);\n return container.children;\n}\n","import { createId, round, type Units, type Vec2 } from \"@react-arch/shared\";\nimport { normalize, sub } from \"@react-arch/geometry\";\nimport {\n DEFAULT_MATERIALS,\n MODEL_VERSION,\n type Building,\n type BuildingDocument,\n type BuildingObject,\n type Floor,\n type Material,\n type Opening,\n type Room,\n type Wall,\n} from \"@react-arch/core\";\nimport { TAG, type RoomSide } from \"./tags.js\";\nimport type { Instance } from \"./renderer.js\";\n\nfunction num(props: Record<string, unknown>, key: string, fallback: number): number {\n const v = props[key];\n return typeof v === \"number\" && Number.isFinite(v) ? v : fallback;\n}\nfunction str(props: Record<string, unknown>, key: string): string | undefined {\n const v = props[key];\n return typeof v === \"string\" ? v : undefined;\n}\nfunction vec2(v: unknown): Vec2 | undefined {\n if (Array.isArray(v) && v.length === 2 && typeof v[0] === \"number\" && typeof v[1] === \"number\") {\n return [v[0], v[1]];\n }\n return undefined;\n}\n\n/** Expand transparent <Group> nodes and drop text nodes. */\nfunction flatten(nodes: Instance[]): Instance[] {\n const out: Instance[] = [];\n for (const n of nodes) {\n if (n.tag === TAG.text) continue;\n if (n.tag === TAG.group) out.push(...flatten(n.children));\n else out.push(n);\n }\n return out;\n}\n\nfunction toMaterial(node: Instance): Material {\n const p = node.props;\n return {\n id: str(p, \"id\") ?? createId(\"mat\"),\n name: str(p, \"name\") ?? \"Material\",\n category: (str(p, \"category\") as Material[\"category\"]) ?? \"custom\",\n baseColor: str(p, \"baseColor\") ?? \"#cccccc\",\n roughness: typeof p.roughness === \"number\" ? p.roughness : undefined,\n metalness: typeof p.metalness === \"number\" ? p.metalness : undefined,\n opacity: typeof p.opacity === \"number\" ? p.opacity : undefined,\n textureUrl: str(p, \"textureUrl\"),\n };\n}\n\ninterface OpeningDefaults {\n width: number;\n height: number;\n sill: number;\n}\nconst OPENING_DEFAULTS: Record<string, OpeningDefaults> = {\n door: { width: 0.9, height: 2.1, sill: 0 },\n window: { width: 1.2, height: 1.4, sill: 0.9 },\n opening: { width: 1.0, height: 2.1, sill: 0 },\n};\n\nfunction toObject(node: Instance, floorId: string): BuildingObject {\n const p = node.props;\n return {\n id: str(p, \"id\") ?? createId(\"object\"),\n floorId,\n type: str(p, \"type\") ?? \"object\",\n position: [num(p, \"x\", 0), num(p, \"y\", 0), num(p, \"z\", 0)],\n rotation: [0, 0, num(p, \"rotation\", 0)],\n scale: [num(p, \"scaleX\", 1), num(p, \"scaleY\", 1), num(p, \"scaleZ\", 1)],\n assetId: str(p, \"assetId\"),\n };\n}\n\nfunction convertFloor(node: Instance, buildingId: string, materials: Material[]): Floor {\n const p = node.props;\n const floor: Floor = {\n id: str(p, \"id\") ?? createId(\"floor\"),\n buildingId,\n name: str(p, \"name\") ?? \"Floor\",\n elevation: num(p, \"elevation\", 0),\n height: num(p, \"height\", 2.8),\n visible: true,\n locked: false,\n walls: [],\n rooms: [],\n openings: [],\n objects: [],\n };\n\n const makeWall = (start: Vec2, end: Vec2, thickness: number, materialId?: string): Wall => {\n const w: Wall = {\n id: createId(\"wall\"),\n floorId: floor.id,\n start,\n end,\n thickness,\n height: floor.height,\n materialId,\n };\n floor.walls.push(w);\n return w;\n };\n\n for (const child of flatten(node.children)) {\n switch (child.tag) {\n case TAG.material:\n materials.push(toMaterial(child));\n break;\n\n case TAG.wall: {\n const from = vec2(child.props.from) ?? [0, 0];\n const to = vec2(child.props.to) ?? [0, 0];\n const w = makeWall(from, to, num(child.props, \"thickness\", 0.2), str(child.props, \"materialId\"));\n if (str(child.props, \"id\")) w.id = str(child.props, \"id\")!;\n if (typeof child.props.height === \"number\") w.height = child.props.height;\n break;\n }\n\n case TAG.room: {\n const x = num(child.props, \"x\", 0);\n const y = num(child.props, \"y\", 0);\n const w = num(child.props, \"width\", 4);\n const d = num(child.props, \"depth\", 4);\n const thickness = num(child.props, \"wallThickness\", 0.2);\n const polygon: Vec2[] = [\n [x, y],\n [x + w, y],\n [x + w, y + d],\n [x, y + d],\n ];\n const room: Room = {\n id: str(child.props, \"id\") ?? createId(\"room\"),\n floorId: floor.id,\n name: str(child.props, \"name\") ?? \"Room\",\n polygon,\n floorMaterialId: str(child.props, \"floorMaterial\"),\n ceilingMaterialId: str(child.props, \"ceilingMaterial\"),\n usageType: str(child.props, \"usage\"),\n height: typeof child.props.height === \"number\" ? child.props.height : undefined,\n };\n floor.rooms.push(room);\n\n // Generate perimeter walls. Offsets increase in a natural reading\n // direction per side (L→R for horizontal, T→B for vertical).\n const sides: Record<RoomSide, Wall> = {\n north: makeWall([x, y], [x + w, y], thickness),\n south: makeWall([x, y + d], [x + w, y + d], thickness),\n west: makeWall([x, y], [x, y + d], thickness),\n east: makeWall([x + w, y], [x + w, y + d], thickness),\n };\n room.boundaryWallIds = Object.values(sides).map((s) => s.id);\n\n for (const o of flatten(child.children)) {\n // Furniture/fixtures are commonly declared inside a room.\n if (o.tag === TAG.furniture) {\n floor.objects.push(toObject(o, floor.id));\n continue;\n }\n if (o.tag !== TAG.door && o.tag !== TAG.window && o.tag !== TAG.opening) continue;\n const type = o.tag === TAG.door ? \"door\" : o.tag === TAG.window ? \"window\" : \"opening\";\n const def = OPENING_DEFAULTS[type]!;\n const side = (str(o.props, \"wall\") as RoomSide) ?? \"south\";\n const wall = sides[side] ?? sides.south;\n const wallLen = side === \"north\" || side === \"south\" ? w : d;\n const opening: Opening = {\n id: str(o.props, \"id\") ?? createId(\"opening\"),\n floorId: floor.id,\n wallId: wall.id,\n type,\n offset: num(o.props, \"offset\", wallLen / 2),\n width: num(o.props, \"width\", def.width),\n height: num(o.props, \"height\", def.height),\n sillHeight: num(o.props, \"sillHeight\", def.sill),\n };\n floor.openings.push(opening);\n }\n break;\n }\n\n case TAG.furniture:\n floor.objects.push(toObject(child, floor.id));\n break;\n\n default:\n // slab / roof / stairs are reserved; ignored for the MVP model.\n break;\n }\n }\n\n mergeCoincidentWalls(floor);\n return floor;\n}\n\n/**\n * Two adjacent rooms each generate their own perimeter walls, producing a pair\n * of coincident walls on their shared edge. Without merging, a door declared on\n * one room only cuts that room's wall and the neighbour's wall stays solid\n * behind it — the opening never passes through (and the walls z-fight in 3D).\n *\n * This collapses coincident, equal-thickness walls into one survivor and\n * re-points openings (re-projecting their offset) and room boundaries onto it,\n * so an interior door becomes a real passage between the rooms.\n */\nfunction mergeCoincidentWalls(floor: Floor): void {\n const key = (w: Wall): string => {\n const a: Vec2 = [round(w.start[0]), round(w.start[1])];\n const b: Vec2 = [round(w.end[0]), round(w.end[1])];\n // Order-insensitive so reversed walls share a key.\n const [p, q] = a[0] < b[0] || (a[0] === b[0] && a[1] <= b[1]) ? [a, b] : [b, a];\n return `${p[0]},${p[1]}|${q[0]},${q[1]}|${round(w.thickness)}`;\n };\n\n const groups = new Map<string, Wall[]>();\n for (const w of floor.walls) {\n const k = key(w);\n const g = groups.get(k);\n if (g) g.push(w);\n else groups.set(k, [w]);\n }\n\n const survivors: Wall[] = [];\n const survivorOf = new Map<string, Wall>(); // any wall id -> survivor wall\n for (const group of groups.values()) {\n const survivor = group[0]!;\n survivors.push(survivor);\n for (const w of group) survivorOf.set(w.id, survivor);\n }\n\n if (survivors.length === floor.walls.length) return; // nothing coincident\n\n const wallById = new Map(floor.walls.map((w) => [w.id, w]));\n for (const o of floor.openings) {\n const survivor = survivorOf.get(o.wallId);\n if (!survivor || survivor.id === o.wallId) continue;\n const orig = wallById.get(o.wallId);\n if (orig) {\n // World centre of the opening on its original wall.\n const od = normalize(sub(orig.end, orig.start));\n const cx = orig.start[0] + od[0] * o.offset;\n const cy = orig.start[1] + od[1] * o.offset;\n // Offset of that point along the survivor (handles reversed direction).\n const sd = normalize(sub(survivor.end, survivor.start));\n o.offset = (cx - survivor.start[0]) * sd[0] + (cy - survivor.start[1]) * sd[1];\n }\n o.wallId = survivor.id;\n }\n\n for (const r of floor.rooms) {\n if (r.boundaryWallIds) {\n r.boundaryWallIds = Array.from(\n new Set(r.boundaryWallIds.map((id) => survivorOf.get(id)?.id ?? id)),\n );\n }\n }\n\n floor.walls = survivors;\n}\n\n/**\n * Convert a rendered instance tree into the canonical BuildingDocument.\n * `fallbackName` is used when the <Building> has no `name` prop (e.g. the\n * registered composition name).\n */\nexport function convert(instances: Instance[], fallbackName = \"Untitled\"): BuildingDocument {\n const tops = flatten(instances);\n const materials: Material[] = [...DEFAULT_MATERIALS];\n for (const n of tops) if (n.tag === TAG.material) materials.push(toMaterial(n));\n\n const buildingNodes = tops.filter((n) => n.tag === TAG.building);\n const buildings: Building[] = [];\n let units: Units = \"metric\";\n let docName = fallbackName;\n\n const sources = buildingNodes.length > 0 ? buildingNodes : [{ tag: TAG.building, props: {}, children: tops }];\n\n for (const bn of sources) {\n const buildingId = str(bn.props, \"id\") ?? createId(\"bld\");\n const name = str(bn.props, \"name\") ?? fallbackName;\n if (str(bn.props, \"units\") === \"imperial\") units = \"imperial\";\n docName = name;\n const floors = flatten(bn.children)\n .filter((c) => c.tag === TAG.floor)\n .map((fn) => convertFloor(fn, buildingId, materials));\n // Keep floors ordered by elevation for stable stacking.\n floors.sort((a, b) => a.elevation - b.elevation);\n buildings.push({ id: buildingId, name, floors });\n }\n\n return {\n id: createId(\"doc\"),\n version: MODEL_VERSION,\n name: docName,\n units,\n buildings,\n materials,\n assets: [],\n metadata: { source: \"react\" },\n };\n}\n","import { createElement, useEffect, type ComponentType, type ReactElement } from \"react\";\nimport type { BuildingDocument } from \"@react-arch/core\";\nimport { renderToInstances } from \"./renderer.js\";\nimport { convert } from \"./convert.js\";\n\nexport interface BuildingComposition {\n id: string;\n name: string;\n component: ComponentType<Record<string, unknown>>;\n defaultProps?: Record<string, unknown>;\n}\n\n// --- module-level registry (Remotion-style) -------------------------------\n\nconst compositions = new Map<string, BuildingComposition>();\nconst listeners = new Set<() => void>();\nlet rootComponent: ComponentType | null = null;\n// Cached, referentially-stable snapshot for useSyncExternalStore consumers.\nlet snapshot: BuildingComposition[] = [];\nlet version = 0;\n\nfunction emit(): void {\n snapshot = [...compositions.values()];\n version += 1;\n for (const fn of listeners) fn();\n}\n\n/** Increments whenever the registry changes (incl. hot-reload re-registration). */\nexport function getCompositionsVersion(): number {\n return version;\n}\n\nexport function __registerComposition(c: BuildingComposition): void {\n compositions.set(c.id, c);\n emit();\n}\nexport function __unregisterComposition(id: string): void {\n compositions.delete(id);\n emit();\n}\n\nexport function getCompositions(): BuildingComposition[] {\n return snapshot;\n}\nexport function subscribeCompositions(fn: () => void): () => void {\n listeners.add(fn);\n return () => listeners.delete(fn);\n}\n\n/**\n * Register the root component (mirrors Remotion's registerRoot). The Studio\n * mounts this so its <Composition> children register themselves.\n */\nexport function registerRoot(component: ComponentType): void {\n rootComponent = component;\n emit();\n}\nexport function getRoot(): ComponentType | null {\n return rootComponent;\n}\n\n/**\n * Declares a building composition. Renders nothing visible; on mount it\n * registers itself into the module registry the Studio reads.\n */\nexport function Composition(props: BuildingComposition): null {\n const { id, name, component, defaultProps } = props;\n useEffect(() => {\n __registerComposition({ id, name, component, defaultProps });\n return () => __unregisterComposition(id);\n }, [id, name, component, defaultProps]);\n return null;\n}\n\n// --- rendering -------------------------------------------------------------\n\n/** Render any React Arch element tree to the canonical model. */\nexport function renderToDocument(element: ReactElement, fallbackName?: string): BuildingDocument {\n return convert(renderToInstances(element), fallbackName);\n}\n\n/** Render a registered composition (component + its default props) to a model. */\nexport function renderComposition(comp: BuildingComposition): BuildingDocument {\n const element = createElement(comp.component, comp.defaultProps ?? {});\n return renderToDocument(element, comp.name);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/tags.ts","../src/components.tsx","../src/renderer.ts","../src/convert.ts","../src/registry.ts"],"sourcesContent":["/**\n * Internal host element tags. Users never type these — the public components\n * in `components.tsx` create them. The reconciler builds an instance tree of\n * these tags, which `convert.ts` turns into a BuildingDocument.\n */\nexport const TAG = {\n building: \"ra-building\",\n floor: \"ra-floor\",\n room: \"ra-room\",\n wall: \"ra-wall\",\n door: \"ra-door\",\n window: \"ra-window\",\n opening: \"ra-opening\",\n furniture: \"ra-furniture\",\n material: \"ra-material\",\n group: \"ra-group\",\n slab: \"ra-slab\",\n roof: \"ra-roof\",\n stairs: \"ra-stairs\",\n text: \"ra-text\",\n} as const;\n\nexport type Tag = (typeof TAG)[keyof typeof TAG];\n\n/** Side of a rectangular room a door/window attaches to. */\nexport type RoomSide = \"north\" | \"south\" | \"east\" | \"west\";\n","import { createElement, type ReactNode } from \"react\";\nimport { TAG, type RoomSide } from \"./tags.js\";\n\ntype WithChildren<T> = T & { children?: ReactNode };\nconst h = (tag: string, props: object) =>\n createElement(tag, props as Record<string, unknown>);\n\nexport interface BuildingProps {\n id?: string;\n name?: string;\n units?: \"metric\" | \"imperial\";\n}\nexport function Building(props: WithChildren<BuildingProps>) {\n return h(TAG.building, props);\n}\n\nexport interface FloorProps {\n id?: string;\n name?: string;\n elevation?: number;\n height?: number;\n}\nexport function Floor(props: WithChildren<FloorProps>) {\n return h(TAG.floor, props);\n}\n\nexport interface RoomProps {\n id?: string;\n name?: string;\n /** Top-left corner X (metres, X increases right). */\n x?: number;\n /** Top-left corner Y (metres, Y increases down). */\n y?: number;\n /** Extent along X. */\n width?: number;\n /** Extent along Y. */\n depth?: number;\n height?: number;\n wallThickness?: number;\n floorMaterial?: string;\n ceilingMaterial?: string;\n usage?: string;\n}\nexport function Room(props: WithChildren<RoomProps>) {\n return h(TAG.room, props);\n}\n\nexport interface WallProps {\n id?: string;\n from: [number, number];\n to: [number, number];\n thickness?: number;\n height?: number;\n materialId?: string;\n}\nexport function Wall(props: WallProps) {\n return h(TAG.wall, props);\n}\n\nexport interface OpeningCommonProps {\n id?: string;\n /** Which side of the parent room this attaches to. */\n wall?: RoomSide;\n /** Distance along the wall centerline from its start corner. */\n offset?: number;\n width?: number;\n height?: number;\n sillHeight?: number;\n}\nexport function Door(props: OpeningCommonProps) {\n return h(TAG.door, props);\n}\nexport function Window(props: OpeningCommonProps) {\n return h(TAG.window, props);\n}\nexport function Opening(props: OpeningCommonProps) {\n return h(TAG.opening, props);\n}\n\nexport interface FurnitureProps {\n id?: string;\n type: string;\n x?: number;\n y?: number;\n z?: number;\n rotation?: number;\n scaleX?: number;\n scaleY?: number;\n scaleZ?: number;\n assetId?: string;\n}\nexport function Furniture(props: FurnitureProps) {\n return h(TAG.furniture, props);\n}\n/** Alias used inside reusable room modules. */\nexport const Fixture = Furniture;\n\nexport interface MaterialProps {\n id: string;\n name?: string;\n category?: string;\n baseColor: string;\n roughness?: number;\n metalness?: number;\n opacity?: number;\n textureUrl?: string;\n}\nexport function Material(props: MaterialProps) {\n return h(TAG.material, props);\n}\n\nexport function Group(props: WithChildren<{ id?: string }>) {\n return h(TAG.group, props);\n}\n\n// Reserved primitives — accepted in the tree, modelled minimally for the MVP.\nexport function Slab(props: WithChildren<{ id?: string }>) {\n return h(TAG.slab, props);\n}\nexport function Roof(props: WithChildren<{ id?: string; type?: string }>) {\n return h(TAG.roof, props);\n}\nexport function Stairs(props: WithChildren<{ id?: string }>) {\n return h(TAG.stairs, props);\n}\n","import Reconciler from \"react-reconciler\";\nimport type { ReactElement } from \"react\";\n\n/** A node in the intermediate instance tree built by the reconciler. */\nexport interface Instance {\n tag: string;\n props: Record<string, unknown>;\n children: Instance[];\n}\n\nexport interface Container {\n children: Instance[];\n}\n\nfunction stripChildren(props: Record<string, unknown>): Record<string, unknown> {\n const { children, ...rest } = props;\n void children;\n return rest;\n}\n\n// react-reconciler's types are notoriously strict; the host config is plain.\nconst hostConfig: any = {\n supportsMutation: true,\n supportsPersistence: false,\n supportsHydration: false,\n isPrimaryRenderer: false,\n noTimeout: -1,\n now: () => 0,\n\n getRootHostContext: () => ({}),\n getChildHostContext: (parent: unknown) => parent,\n getPublicInstance: (instance: Instance) => instance,\n\n prepareForCommit: () => null,\n resetAfterCommit: () => {},\n preparePortalMount: () => {},\n\n createInstance(tag: string, props: Record<string, unknown>): Instance {\n return { tag, props: stripChildren(props), children: [] };\n },\n\n createTextInstance(text: string): Instance {\n return { tag: \"ra-text\", props: { text }, children: [] };\n },\n\n appendInitialChild(parent: Instance, child: Instance) {\n parent.children.push(child);\n },\n appendChild(parent: Instance, child: Instance) {\n parent.children.push(child);\n },\n appendChildToContainer(container: Container, child: Instance) {\n container.children.push(child);\n },\n\n insertBefore(parent: Instance, child: Instance, before: Instance) {\n const i = parent.children.indexOf(before);\n parent.children.splice(i, 0, child);\n },\n insertInContainerBefore(container: Container, child: Instance, before: Instance) {\n const i = container.children.indexOf(before);\n container.children.splice(i, 0, child);\n },\n\n removeChild(parent: Instance, child: Instance) {\n parent.children = parent.children.filter((c) => c !== child);\n },\n removeChildFromContainer(container: Container, child: Instance) {\n container.children = container.children.filter((c) => c !== child);\n },\n\n finalizeInitialChildren: () => false,\n shouldSetTextContent: () => false,\n clearContainer(container: Container) {\n container.children = [];\n },\n\n prepareUpdate: () => true,\n commitUpdate(instance: Instance, _payload: unknown, _tag: string, _old: unknown, newProps: Record<string, unknown>) {\n instance.props = stripChildren(newProps);\n },\n commitTextUpdate(instance: Instance, _old: string, text: string) {\n instance.props = { text };\n },\n\n getCurrentEventPriority: () => 16,\n detachDeletedInstance: () => {},\n prepareScopeUpdate: () => {},\n getInstanceFromScope: () => null,\n getInstanceFromNode: () => null,\n beforeActiveInstanceBlur: () => {},\n afterActiveInstanceBlur: () => {},\n scheduleTimeout: setTimeout,\n cancelTimeout: clearTimeout,\n};\n\nconst reconciler = Reconciler(hostConfig);\n\nconst LegacyRoot = 0;\n\n/**\n * Render a React element tree through the React Arch reconciler and return the\n * resulting intermediate instance tree. Synchronous (legacy root) so the tree\n * is fully built when this returns.\n */\nexport function renderToInstances(element: ReactElement): Instance[] {\n const container: Container = { children: [] };\n const root = reconciler.createContainer(\n container,\n LegacyRoot,\n null,\n false,\n null,\n \"react-arch\",\n (error: unknown) => {\n // Surface render errors loudly; the studio shows them as diagnostics.\n console.error(\"[react-arch] render error\", error);\n },\n null,\n );\n reconciler.updateContainer(element, root, null, null);\n return container.children;\n}\n","import { round, type Units, type Vec2 } from \"@react-arch/shared\";\nimport { dot, normal, normalize, scale, sub } from \"@react-arch/geometry\";\nimport {\n DEFAULT_MATERIALS,\n MODEL_VERSION,\n type Building,\n type BuildingDocument,\n type BuildingObject,\n type Floor,\n type Material,\n type Opening,\n type Room,\n type Wall,\n} from \"@react-arch/core\";\nimport { TAG, type RoomSide } from \"./tags.js\";\nimport type { Instance } from \"./renderer.js\";\n\nfunction num(props: Record<string, unknown>, key: string, fallback: number): number {\n const v = props[key];\n return typeof v === \"number\" && Number.isFinite(v) ? v : fallback;\n}\nfunction str(props: Record<string, unknown>, key: string): string | undefined {\n const v = props[key];\n return typeof v === \"string\" ? v : undefined;\n}\nfunction vec2(v: unknown): Vec2 | undefined {\n if (Array.isArray(v) && v.length === 2 && typeof v[0] === \"number\" && typeof v[1] === \"number\") {\n return [v[0], v[1]];\n }\n return undefined;\n}\n\nfunction idPart(value: unknown, fallback = \"item\"): string {\n const raw = typeof value === \"string\" && value.trim() ? value : fallback;\n return raw.toLowerCase().replace(/[^a-z0-9_-]+/g, \"-\").replace(/^-+|-+$/g, \"\") || fallback;\n}\n\nfunction uniqueId(base: string, used: Set<string>): string {\n let id = idPart(base);\n let suffix = 2;\n while (used.has(id)) {\n id = `${idPart(base)}-${suffix}`;\n suffix += 1;\n }\n used.add(id);\n return id;\n}\n\nfunction idFromProps(props: Record<string, unknown>, base: string, used: Set<string>): string {\n const explicit = str(props, \"id\");\n if (explicit) {\n used.add(explicit);\n return explicit;\n }\n return uniqueId(base, used);\n}\n\n/** Expand transparent <Group> nodes and drop text nodes. */\nfunction flatten(nodes: Instance[]): Instance[] {\n const out: Instance[] = [];\n for (const n of nodes) {\n if (n.tag === TAG.text) continue;\n if (n.tag === TAG.group) out.push(...flatten(n.children));\n else out.push(n);\n }\n return out;\n}\n\nfunction toMaterial(node: Instance, fallbackId: string, usedIds: Set<string>): Material {\n const p = node.props;\n return {\n id: idFromProps(p, fallbackId, usedIds),\n name: str(p, \"name\") ?? \"Material\",\n category: (str(p, \"category\") as Material[\"category\"]) ?? \"custom\",\n baseColor: str(p, \"baseColor\") ?? \"#cccccc\",\n roughness: typeof p.roughness === \"number\" ? p.roughness : undefined,\n metalness: typeof p.metalness === \"number\" ? p.metalness : undefined,\n opacity: typeof p.opacity === \"number\" ? p.opacity : undefined,\n textureUrl: str(p, \"textureUrl\"),\n };\n}\n\ninterface OpeningDefaults {\n width: number;\n height: number;\n sill: number;\n}\nconst OPENING_DEFAULTS: Record<string, OpeningDefaults> = {\n door: { width: 0.9, height: 2.1, sill: 0 },\n window: { width: 1.2, height: 1.4, sill: 0.9 },\n opening: { width: 1.0, height: 2.1, sill: 0 },\n};\n\nfunction toObject(node: Instance, floorId: string, fallbackId: string, usedIds: Set<string>): BuildingObject {\n const p = node.props;\n return {\n id: idFromProps(p, fallbackId, usedIds),\n floorId,\n type: str(p, \"type\") ?? \"object\",\n position: [num(p, \"x\", 0), num(p, \"y\", 0), num(p, \"z\", 0)],\n rotation: [0, 0, num(p, \"rotation\", 0)],\n scale: [num(p, \"scaleX\", 1), num(p, \"scaleY\", 1), num(p, \"scaleZ\", 1)],\n assetId: str(p, \"assetId\"),\n };\n}\n\nfunction convertFloor(\n node: Instance,\n buildingId: string,\n materials: Material[],\n floorIndex: number,\n usedIds: Set<string>,\n): Floor {\n const p = node.props;\n const floor: Floor = {\n id: idFromProps(p, `${buildingId}-floor-${floorIndex + 1}`, usedIds),\n buildingId,\n name: str(p, \"name\") ?? \"Floor\",\n elevation: num(p, \"elevation\", 0),\n height: num(p, \"height\", 2.8),\n visible: true,\n locked: false,\n walls: [],\n rooms: [],\n openings: [],\n objects: [],\n };\n\n let wallIndex = 0;\n let materialIndex = 0;\n let objectIndex = 0;\n\n const makeWall = (start: Vec2, end: Vec2, thickness: number, materialId: string | undefined, idBase: string, explicitId?: string): Wall => {\n const w: Wall = {\n id: explicitId ? (usedIds.add(explicitId), explicitId) : uniqueId(idBase, usedIds),\n floorId: floor.id,\n start,\n end,\n thickness,\n height: floor.height,\n materialId,\n };\n floor.walls.push(w);\n return w;\n };\n\n for (const child of flatten(node.children)) {\n switch (child.tag) {\n case TAG.material:\n materialIndex += 1;\n materials.push(toMaterial(child, `${floor.id}-material-${materialIndex}`, usedIds));\n break;\n\n case TAG.wall: {\n const from = vec2(child.props.from) ?? [0, 0];\n const to = vec2(child.props.to) ?? [0, 0];\n wallIndex += 1;\n const w = makeWall(from, to, num(child.props, \"thickness\", 0.2), str(child.props, \"materialId\"), `${floor.id}-wall-${wallIndex}`, str(child.props, \"id\"));\n if (typeof child.props.height === \"number\") w.height = child.props.height;\n break;\n }\n\n case TAG.room: {\n const roomIndex = floor.rooms.length + 1;\n const x = num(child.props, \"x\", 0);\n const y = num(child.props, \"y\", 0);\n const w = num(child.props, \"width\", 4);\n const d = num(child.props, \"depth\", 4);\n const thickness = num(child.props, \"wallThickness\", 0.2);\n const roomId = idFromProps(child.props, `${floor.id}-room-${roomIndex}`, usedIds);\n const polygon: Vec2[] = [\n [x, y],\n [x + w, y],\n [x + w, y + d],\n [x, y + d],\n ];\n const room: Room = {\n id: roomId,\n floorId: floor.id,\n name: str(child.props, \"name\") ?? \"Room\",\n polygon,\n floorMaterialId: str(child.props, \"floorMaterial\"),\n ceilingMaterialId: str(child.props, \"ceilingMaterial\"),\n usageType: str(child.props, \"usage\"),\n height: typeof child.props.height === \"number\" ? child.props.height : undefined,\n };\n floor.rooms.push(room);\n\n // Generate perimeter walls. Offsets increase in a natural reading\n // direction per side (L→R for horizontal, T→B for vertical).\n const sides: Record<RoomSide, Wall> = {\n north: makeWall([x, y], [x + w, y], thickness, undefined, `${room.id}-wall-north`),\n south: makeWall([x, y + d], [x + w, y + d], thickness, undefined, `${room.id}-wall-south`),\n west: makeWall([x, y], [x, y + d], thickness, undefined, `${room.id}-wall-west`),\n east: makeWall([x + w, y], [x + w, y + d], thickness, undefined, `${room.id}-wall-east`),\n };\n room.boundaryWallIds = Object.values(sides).map((s) => s.id);\n\n let roomOpeningIndex = 0;\n let roomObjectIndex = 0;\n for (const o of flatten(child.children)) {\n // Furniture/fixtures are commonly declared inside a room.\n if (o.tag === TAG.furniture) {\n objectIndex += 1;\n roomObjectIndex += 1;\n floor.objects.push(toObject(o, floor.id, `${room.id}-object-${roomObjectIndex}`, usedIds));\n continue;\n }\n if (o.tag !== TAG.door && o.tag !== TAG.window && o.tag !== TAG.opening) continue;\n const type = o.tag === TAG.door ? \"door\" : o.tag === TAG.window ? \"window\" : \"opening\";\n const def = OPENING_DEFAULTS[type]!;\n const side = (str(o.props, \"wall\") as RoomSide) ?? \"south\";\n const wall = sides[side] ?? sides.south;\n const wallLen = side === \"north\" || side === \"south\" ? w : d;\n roomOpeningIndex += 1;\n const opening: Opening = {\n id: idFromProps(o.props, `${room.id}-${type}-${side}-${roomOpeningIndex}`, usedIds),\n floorId: floor.id,\n wallId: wall.id,\n type,\n offset: num(o.props, \"offset\", wallLen / 2),\n width: num(o.props, \"width\", def.width),\n height: num(o.props, \"height\", def.height),\n sillHeight: num(o.props, \"sillHeight\", def.sill),\n };\n floor.openings.push(opening);\n }\n break;\n }\n\n case TAG.furniture:\n objectIndex += 1;\n floor.objects.push(toObject(child, floor.id, `${floor.id}-object-${objectIndex}`, usedIds));\n break;\n\n default:\n // slab / roof / stairs are reserved; ignored for the MVP model.\n break;\n }\n }\n\n mergeCoincidentWalls(floor);\n return floor;\n}\n\n/**\n * Two adjacent rooms each generate their own perimeter walls, producing a pair\n * of coincident walls on their shared edge. Without merging, a door declared on\n * one room only cuts that room's wall and the neighbour's wall stays solid\n * behind it — the opening never passes through (and the walls z-fight in 3D).\n *\n * This collapses coincident, equal-thickness walls into one survivor and\n * re-points openings (re-projecting their offset) and room boundaries onto it,\n * so an interior door becomes a real passage between the rooms.\n */\nfunction mergeCoincidentWalls(floor: Floor): void {\n interface WallInterval {\n wall: Wall;\n d: Vec2;\n n: Vec2;\n lineOffset: number;\n a: number;\n b: number;\n }\n\n const intervalOf = (w: Wall): WallInterval => {\n let d = normalize(sub(w.end, w.start));\n if (d[0] < 0 || (d[0] === 0 && d[1] < 0)) d = scale(d, -1);\n const n = normal(d);\n const lineOffset = dot(w.start, n);\n const t0 = dot(w.start, d);\n const t1 = dot(w.end, d);\n return { wall: w, d, n, lineOffset, a: Math.min(t0, t1), b: Math.max(t0, t1) };\n };\n\n const key = (i: WallInterval): string => {\n if (i.d[0] === 0 && i.d[1] === 0) {\n return `point:${round(i.wall.start[0])},${round(i.wall.start[1])}|${round(i.wall.thickness)}`;\n }\n return `${round(i.d[0])},${round(i.d[1])}|${round(i.lineOffset)}|${round(i.wall.thickness)}`;\n };\n\n const pointAt = (i: WallInterval, t: number): Vec2 => [\n i.d[0] * t + i.n[0] * i.lineOffset,\n i.d[1] * t + i.n[1] * i.lineOffset,\n ];\n\n const oldWallById = new Map(\n floor.walls.map((w) => [w.id, { start: [...w.start] as Vec2, end: [...w.end] as Vec2 }]),\n );\n const openingCenters = new Map<string, Vec2>();\n for (const o of floor.openings) {\n const w = oldWallById.get(o.wallId);\n if (!w) continue;\n const d = normalize(sub(w.end, w.start));\n openingCenters.set(o.id, [w.start[0] + d[0] * o.offset, w.start[1] + d[1] * o.offset]);\n }\n\n const groups = new Map<string, WallInterval[]>();\n for (const w of floor.walls) {\n const interval = intervalOf(w);\n const k = key(interval);\n const g = groups.get(k);\n if (g) g.push(interval);\n else groups.set(k, [interval]);\n }\n\n const survivors: Wall[] = [];\n const survivorOf = new Map<string, Wall>(); // any wall id -> survivor wall\n let mergedAny = false;\n\n const flush = (active: WallInterval[], a: number, b: number) => {\n const survivor = active[0]!.wall;\n if (active.length > 1) {\n survivor.start = pointAt(active[0]!, a);\n survivor.end = pointAt(active[0]!, b);\n mergedAny = true;\n }\n survivors.push(survivor);\n for (const i of active) survivorOf.set(i.wall.id, survivor);\n };\n\n for (const group of groups.values()) {\n if (group.length === 1) {\n const only = group[0]!;\n survivors.push(only.wall);\n survivorOf.set(only.wall.id, only.wall);\n continue;\n }\n\n const sorted = [...group].sort((a, b) => a.a - b.a);\n let active: WallInterval[] = [];\n let activeA = 0;\n let activeB = 0;\n for (const interval of sorted) {\n if (active.length === 0) {\n active = [interval];\n activeA = interval.a;\n activeB = interval.b;\n continue;\n }\n if (interval.a < activeB - 1e-6) {\n active.push(interval);\n activeA = Math.min(activeA, interval.a);\n activeB = Math.max(activeB, interval.b);\n } else {\n flush(active, activeA, activeB);\n active = [interval];\n activeA = interval.a;\n activeB = interval.b;\n }\n }\n if (active.length > 0) flush(active, activeA, activeB);\n }\n\n if (!mergedAny) return;\n\n for (const o of floor.openings) {\n const survivor = survivorOf.get(o.wallId);\n if (!survivor) continue;\n const center = openingCenters.get(o.id);\n if (center) {\n // Offset of the original world centre along the survivor.\n const sd = normalize(sub(survivor.end, survivor.start));\n o.offset = dot(sub(center, survivor.start), sd);\n }\n o.wallId = survivor.id;\n }\n\n for (const r of floor.rooms) {\n if (r.boundaryWallIds) {\n r.boundaryWallIds = Array.from(\n new Set(r.boundaryWallIds.map((id) => survivorOf.get(id)?.id ?? id)),\n );\n }\n }\n\n floor.walls = survivors;\n}\n\n/**\n * Convert a rendered instance tree into the canonical BuildingDocument.\n * `fallbackName` is used when the <Building> has no `name` prop (e.g. the\n * registered composition name).\n */\nexport function convert(instances: Instance[], fallbackName = \"Untitled\"): BuildingDocument {\n const tops = flatten(instances);\n const usedIds = new Set(DEFAULT_MATERIALS.map((m) => m.id));\n const materials: Material[] = DEFAULT_MATERIALS.map((m) => ({ ...m }));\n let topMaterialIndex = 0;\n for (const n of tops) {\n if (n.tag === TAG.material) {\n topMaterialIndex += 1;\n materials.push(toMaterial(n, `material-${topMaterialIndex}`, usedIds));\n }\n }\n\n const buildingNodes = tops.filter((n) => n.tag === TAG.building);\n const buildings: Building[] = [];\n let units: Units = \"metric\";\n let docName = fallbackName;\n\n const sources = buildingNodes.length > 0 ? buildingNodes : [{ tag: TAG.building, props: {}, children: tops }];\n\n sources.forEach((bn, buildingIndex) => {\n const buildingId = idFromProps(bn.props, `building-${buildingIndex + 1}`, usedIds);\n const name = str(bn.props, \"name\") ?? fallbackName;\n if (str(bn.props, \"units\") === \"imperial\") units = \"imperial\";\n docName = name;\n const floors = flatten(bn.children)\n .filter((c) => c.tag === TAG.floor)\n .map((fn, floorIndex) => convertFloor(fn, buildingId, materials, floorIndex, usedIds));\n // Keep floors ordered by elevation for stable stacking.\n floors.sort((a, b) => a.elevation - b.elevation);\n buildings.push({ id: buildingId, name, floors });\n });\n\n return {\n id: uniqueId(`doc-${docName}`, usedIds),\n version: MODEL_VERSION,\n name: docName,\n units,\n buildings,\n materials,\n assets: [],\n metadata: { source: \"react\" },\n };\n}\n","import { createElement, useEffect, type ComponentType, type ReactElement } from \"react\";\nimport type { BuildingDocument } from \"@react-arch/core\";\nimport { renderToInstances } from \"./renderer.js\";\nimport { convert } from \"./convert.js\";\n\nexport interface BuildingComposition {\n id: string;\n name: string;\n component: ComponentType<Record<string, unknown>>;\n defaultProps?: Record<string, unknown>;\n}\n\n// --- module-level registry (Remotion-style) -------------------------------\n\nconst compositions = new Map<string, BuildingComposition>();\nconst listeners = new Set<() => void>();\nlet rootComponent: ComponentType | null = null;\n// Cached, referentially-stable snapshot for useSyncExternalStore consumers.\nlet snapshot: BuildingComposition[] = [];\nlet version = 0;\n\nfunction emit(): void {\n snapshot = [...compositions.values()];\n version += 1;\n for (const fn of listeners) fn();\n}\n\n/** Increments whenever the registry changes (incl. hot-reload re-registration). */\nexport function getCompositionsVersion(): number {\n return version;\n}\n\nexport function __registerComposition(c: BuildingComposition): void {\n compositions.set(c.id, c);\n emit();\n}\nexport function __unregisterComposition(id: string): void {\n compositions.delete(id);\n emit();\n}\n\nexport function getCompositions(): BuildingComposition[] {\n return snapshot;\n}\nexport function subscribeCompositions(fn: () => void): () => void {\n listeners.add(fn);\n return () => listeners.delete(fn);\n}\n\n/**\n * Register the root component (mirrors Remotion's registerRoot). The Studio\n * mounts this so its <Composition> children register themselves.\n */\nexport function registerRoot(component: ComponentType): void {\n rootComponent = component;\n emit();\n}\nexport function getRoot(): ComponentType | null {\n return rootComponent;\n}\n\n/**\n * Declares a building composition. Renders nothing visible; on mount it\n * registers itself into the module registry the Studio reads.\n */\nexport function Composition(props: BuildingComposition): null {\n const { id, name, component, defaultProps } = props;\n useEffect(() => {\n __registerComposition({ id, name, component, defaultProps });\n return () => __unregisterComposition(id);\n }, [id, name, component, defaultProps]);\n return null;\n}\n\n// --- rendering -------------------------------------------------------------\n\n/** Render any React Arch element tree to the canonical model. */\nexport function renderToDocument(element: ReactElement, fallbackName?: string): BuildingDocument {\n return convert(renderToInstances(element), fallbackName);\n}\n\n/** Render a registered composition (component + its default props) to a model. */\nexport function renderComposition(comp: BuildingComposition): BuildingDocument {\n const element = createElement(comp.component, comp.defaultProps ?? {});\n return renderToDocument(element, comp.name);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-arch/react",
|
|
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",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"react-reconciler": "^0.29.2",
|
|
16
|
-
"@react-arch/core": "0.1.
|
|
17
|
-
"@react-arch/
|
|
18
|
-
"@react-arch/
|
|
16
|
+
"@react-arch/core": "0.1.3",
|
|
17
|
+
"@react-arch/shared": "0.1.3",
|
|
18
|
+
"@react-arch/geometry": "0.1.3"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"react": "^18.3.0"
|