@snaptrude/plugin-core 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/api-manifest.full.json +6442 -0
  3. package/api-manifest.json +2029 -128
  4. package/dist/api/core/camera/index.d.ts +208 -0
  5. package/dist/api/core/camera/index.d.ts.map +1 -0
  6. package/dist/api/core/comment/index.d.ts +105 -2
  7. package/dist/api/core/comment/index.d.ts.map +1 -1
  8. package/dist/api/core/geom/create/index.d.ts +13 -13
  9. package/dist/api/core/geom/delete/index.d.ts +8 -2
  10. package/dist/api/core/geom/delete/index.d.ts.map +1 -1
  11. package/dist/api/core/geom/query/arc.d.ts +5 -5
  12. package/dist/api/core/geom/query/brep.d.ts +18 -18
  13. package/dist/api/core/geom/query/circle.d.ts +18 -18
  14. package/dist/api/core/geom/query/contour.d.ts +20 -20
  15. package/dist/api/core/geom/query/curve.d.ts +49 -49
  16. package/dist/api/core/geom/query/edge.d.ts +5 -5
  17. package/dist/api/core/geom/query/face.d.ts +16 -16
  18. package/dist/api/core/geom/query/halfedge.d.ts +8 -8
  19. package/dist/api/core/geom/query/profile.d.ts +19 -19
  20. package/dist/api/core/geom/query/vertex.d.ts +8 -8
  21. package/dist/api/core/geom/update/contour.d.ts +14 -14
  22. package/dist/api/core/geom/update/curve.d.ts +7 -7
  23. package/dist/api/core/geom/update/profile.d.ts +16 -16
  24. package/dist/api/core/handles/index.d.ts +210 -0
  25. package/dist/api/core/handles/index.d.ts.map +1 -0
  26. package/dist/api/core/index.d.ts +15 -0
  27. package/dist/api/core/index.d.ts.map +1 -1
  28. package/dist/api/core/io/export/index.d.ts +132 -0
  29. package/dist/api/core/io/export/index.d.ts.map +1 -0
  30. package/dist/api/core/io/import/index.d.ts +1 -1
  31. package/dist/api/core/io/index.d.ts +5 -0
  32. package/dist/api/core/io/index.d.ts.map +1 -1
  33. package/dist/api/core/layers.d.ts +7 -7
  34. package/dist/api/core/proposals/index.d.ts +65 -9
  35. package/dist/api/core/proposals/index.d.ts.map +1 -1
  36. package/dist/api/core/user.d.ts +44 -0
  37. package/dist/api/core/user.d.ts.map +1 -0
  38. package/dist/api/design/boolean/index.d.ts +4 -4
  39. package/dist/api/design/create/index.d.ts +139 -44
  40. package/dist/api/design/create/index.d.ts.map +1 -1
  41. package/dist/api/design/doors/index.d.ts +36 -0
  42. package/dist/api/design/doors/index.d.ts.map +1 -1
  43. package/dist/api/design/edit/index.d.ts +1 -1
  44. package/dist/api/design/erase/index.d.ts +2 -2
  45. package/dist/api/design/furniture/index.d.ts +114 -3
  46. package/dist/api/design/furniture/index.d.ts.map +1 -1
  47. package/dist/api/design/index.d.ts +10 -0
  48. package/dist/api/design/index.d.ts.map +1 -1
  49. package/dist/api/design/materials/index.d.ts +111 -14
  50. package/dist/api/design/materials/index.d.ts.map +1 -1
  51. package/dist/api/design/query/index.d.ts +31 -1
  52. package/dist/api/design/query/index.d.ts.map +1 -1
  53. package/dist/api/design/query/spaces.d.ts +5 -5
  54. package/dist/api/design/transform/index.d.ts +83 -14
  55. package/dist/api/design/transform/index.d.ts.map +1 -1
  56. package/dist/api/design/types/index.d.ts +181 -0
  57. package/dist/api/design/types/index.d.ts.map +1 -0
  58. package/dist/api/design/update/index.d.ts +335 -2
  59. package/dist/api/design/update/index.d.ts.map +1 -1
  60. package/dist/api/design/visibility.d.ts +98 -0
  61. package/dist/api/design/visibility.d.ts.map +1 -0
  62. package/dist/api/entity/referenceLine.d.ts +2 -2
  63. package/dist/api/entity/space.d.ts +19 -19
  64. package/dist/api/entity/story.d.ts +128 -15
  65. package/dist/api/entity/story.d.ts.map +1 -1
  66. package/dist/api/presentation/annotate.d.ts +448 -0
  67. package/dist/api/presentation/annotate.d.ts.map +1 -0
  68. package/dist/api/presentation/diagrams.d.ts +49 -8
  69. package/dist/api/presentation/diagrams.d.ts.map +1 -1
  70. package/dist/api/presentation/export.d.ts +104 -0
  71. package/dist/api/presentation/export.d.ts.map +1 -0
  72. package/dist/api/presentation/index.d.ts +38 -0
  73. package/dist/api/presentation/index.d.ts.map +1 -1
  74. package/dist/api/presentation/sheets.d.ts +410 -13
  75. package/dist/api/presentation/sheets.d.ts.map +1 -1
  76. package/dist/api/presentation/views.d.ts +165 -10
  77. package/dist/api/presentation/views.d.ts.map +1 -1
  78. package/dist/api/program/areas.d.ts +63 -3
  79. package/dist/api/program/areas.d.ts.map +1 -1
  80. package/dist/api/program/cores.d.ts +3 -99
  81. package/dist/api/program/cores.d.ts.map +1 -1
  82. package/dist/api/program/index.d.ts +2 -2
  83. package/dist/api/program/index.d.ts.map +1 -1
  84. package/dist/api/program/layout.d.ts +172 -12
  85. package/dist/api/program/layout.d.ts.map +1 -1
  86. package/dist/api/program/site.d.ts +11 -8
  87. package/dist/api/program/site.d.ts.map +1 -1
  88. package/dist/api/program/spreadsheet.d.ts +105 -13
  89. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  90. package/dist/handles.d.ts +64 -25
  91. package/dist/handles.d.ts.map +1 -1
  92. package/dist/index.cjs +2316 -1644
  93. package/dist/index.cjs.map +1 -1
  94. package/dist/index.js +2224 -1639
  95. package/dist/index.js.map +1 -1
  96. package/package.json +1 -1
  97. package/src/api/core/camera/index.ts +212 -0
  98. package/src/api/core/comment/index.ts +120 -2
  99. package/src/api/core/geom/delete/index.ts +6 -0
  100. package/src/api/core/handles/index.ts +233 -0
  101. package/src/api/core/index.ts +15 -0
  102. package/src/api/core/io/export/index.ts +124 -0
  103. package/src/api/core/io/index.ts +5 -0
  104. package/src/api/core/proposals/index.ts +71 -11
  105. package/src/api/core/user.ts +46 -0
  106. package/src/api/design/create/index.ts +166 -36
  107. package/src/api/design/doors/index.ts +40 -0
  108. package/src/api/design/furniture/index.ts +127 -3
  109. package/src/api/design/index.ts +10 -0
  110. package/src/api/design/materials/index.ts +157 -30
  111. package/src/api/design/query/index.ts +33 -7
  112. package/src/api/design/transform/index.ts +89 -12
  113. package/src/api/design/types/index.ts +156 -0
  114. package/src/api/design/update/index.ts +402 -6
  115. package/src/api/design/visibility.ts +109 -0
  116. package/src/api/entity/story.ts +141 -15
  117. package/src/api/presentation/annotate.ts +360 -0
  118. package/src/api/presentation/diagrams.ts +53 -8
  119. package/src/api/presentation/export.ts +104 -0
  120. package/src/api/presentation/index.ts +46 -0
  121. package/src/api/presentation/sheets.ts +346 -13
  122. package/src/api/presentation/views.ts +164 -12
  123. package/src/api/program/areas.ts +57 -6
  124. package/src/api/program/cores.ts +3 -91
  125. package/src/api/program/index.ts +2 -2
  126. package/src/api/program/layout.ts +182 -12
  127. package/src/api/program/site.ts +11 -8
  128. package/src/api/program/spreadsheet.ts +125 -29
  129. package/src/handles.ts +77 -13
  130. package/tsconfig.json +7 -2
@@ -50,14 +50,21 @@ export abstract class PluginDesignCreateApi {
50
50
  * @param spaceType - Space-type classification (default `Room`)
51
51
  * @param massType - Mass-type classification (default `Room`)
52
52
  * @param departmentId - Department assignment (default department)
53
+ * @param storey - Target storey number to place the space on — the same integer
54
+ * `entity.story` uses (`1` ground, `2` first floor, `-1` basement). Default:
55
+ * the active storey. Folds an `entity.story.setActive` call into the create,
56
+ * placing the space at that storey's floor elevation (any `position` offset is
57
+ * applied on top). Throws if no storey has that value.
53
58
  * @returns the {@linkcode ComponentHandle} of the created space
54
- * @throws if the contour is invalid or the height is not positive
59
+ * @throws if the contour is invalid, the height is not positive, or the target
60
+ * storey does not exist
55
61
  *
56
62
  * @examplePrompt Create a room called Living Room that's 3m tall from this outline
57
63
  * @examplePrompt Add a new space on the current storey using this footprint
58
64
  * @examplePrompt Make a bedroom here and assign it to the Residential department
59
65
  * @examplePrompt Extrude this closed outline into a 10 foot high room
60
66
  * @examplePrompt Can you create a Kitchen space from the sketch I just drew?
67
+ * @examplePrompt Create a bedroom on the second floor from this outline
61
68
  *
62
69
  * # Example
63
70
  * ```ts
@@ -70,6 +77,10 @@ export abstract class PluginDesignCreateApi {
70
77
  * ])
71
78
  * const contour = await snaptrude.core.geom.create.contourFromProfile(outer)
72
79
  * const space = await snaptrude.design.create.space(contour, 3, "Living")
80
+ * // …place one directly on the second floor (no setActive dance):
81
+ * const upstairs = await snaptrude.design.create.space(
82
+ * contour, 3, "Bedroom", undefined, undefined, undefined, undefined, 2,
83
+ * )
73
84
  * ```
74
85
  */
75
86
  public abstract space(
@@ -80,6 +91,7 @@ export abstract class PluginDesignCreateApi {
80
91
  spaceType?: PluginSpaceType,
81
92
  massType?: PluginMassType,
82
93
  departmentId?: PluginDepartmentId,
94
+ storey?: number,
83
95
  ): PluginApiReturn<ComponentHandle>
84
96
 
85
97
  /**
@@ -229,14 +241,17 @@ export abstract class PluginDesignCreateApi {
229
241
 
230
242
  /**
231
243
  * Create a **column** by extruding a cross-section contour upward by `height`
232
- * from a base `position`.
244
+ * from a base `position`. The column is built to EXACTLY `height` — unlike
245
+ * the interactive draw tool, no slab-thickness deduction is applied.
233
246
  *
234
247
  * @param position - Base point
235
248
  * @param crossSection - Column cross-section footprint
236
- * @param height - Column height (> 0)
237
- * @param directionUp - Up axis (default world up)
249
+ * @param height - Column height (> 0), built exactly
250
+ * @param directionUp - Up axis (default world up); normalized by the host, so
251
+ * magnitude does not scale the height
238
252
  * @returns the {@linkcode ComponentHandle} of the created column
239
- * @throws if the cross-section is invalid or the height is not positive
253
+ * @throws if the cross-section is invalid, the height is not positive, or the
254
+ * direction is zero / lies in the cross-section plane (degenerate extrusion)
240
255
  *
241
256
  * @examplePrompt Add a 3m tall column at this point
242
257
  * @examplePrompt Place a column at the grid intersection
@@ -260,13 +275,30 @@ export abstract class PluginDesignCreateApi {
260
275
 
261
276
  /**
262
277
  * Create a **beam** by extruding a cross-section contour along `direction` by
263
- * `length`.
278
+ * `length`. Matches the Snaptrude beam tool's semantics: the beam body hangs
279
+ * BELOW the plane the section is authored on.
280
+ *
281
+ * For a **horizontal** `direction` (the common spanning beam), author the
282
+ * section as an axis-aligned plan rectangle: its X extent is the beam's
283
+ * width, its Z extent is the beam's depth (the vertical drop). The beam runs
284
+ * `length` along `direction` starting at the section's centre, hanging below
285
+ * the authoring plane by its depth — exactly like an interactively drawn
286
+ * beam. Only axis-aligned rectangular sections are supported horizontally.
287
+ *
288
+ * For a **vertical** `direction` (the default), the section itself is
289
+ * extruded by `length`, again hanging below the authoring plane. Diagonal
290
+ * directions are rejected.
264
291
  *
265
- * @param section - Beam cross-section footprint
266
- * @param length - Beam length along `direction` (> 0)
267
- * @param direction - Extrusion axis (default world up)
292
+ * @param section - Beam cross-section, an axis-aligned rectangle in plan
293
+ * (X extent = width, Z extent = depth)
294
+ * @param length - Beam length along `direction` (> 0); direction is
295
+ * normalized by the host, so magnitude does not scale the length
296
+ * @param direction - Beam axis: horizontal for a spanning beam, or vertical
297
+ * (default world up). Diagonal directions throw.
268
298
  * @returns the {@linkcode ComponentHandle} of the created beam
269
- * @throws if the section is invalid or the length is not positive
299
+ * @throws if the section is invalid (horizontal beams: not an axis-aligned
300
+ * plan rectangle), the length is not positive, or the direction is zero or
301
+ * diagonal
270
302
  *
271
303
  * @examplePrompt Add a beam spanning 6 metres between the columns
272
304
  * @examplePrompt Create a horizontal beam along the X axis
@@ -293,15 +325,25 @@ export abstract class PluginDesignCreateApi {
293
325
  *
294
326
  * @param profile - Ordered curve chain (wall centerlines)
295
327
  * @param height - Wall height (default engine default)
296
- * @param thickness - Wall thickness (default engine default)
328
+ * @param thickness - Wall thickness (default: the `wallType`'s total layer
329
+ * thickness when `wallType` is given, else the engine default)
330
+ * @param wallType - Wall type to build with — the same searchable list the
331
+ * Draw tab's Wall Type dropdown offers. Pass a name from
332
+ * `design.types.list("wall")` (the summary's `label`, or its `"wall:…"` id).
333
+ * Drives the wall's construction layers and default material, and — when
334
+ * `thickness` is omitted — its total layer thickness. Default: the engine's
335
+ * generic wall.
297
336
  * @returns a {@linkcode ComponentHandle}`[]` (one per wall), in profile order
298
- * @throws if the profile is empty or wall creation fails
337
+ * @throws if the profile is empty, `wallType` names no wall type in the
338
+ * project, or wall creation fails
299
339
  *
300
340
  * @examplePrompt Draw walls along this centerline
301
341
  * @examplePrompt Create 3m high, 200mm thick walls from these points
302
342
  * @examplePrompt Build a wall run around the room outline
303
343
  * @examplePrompt Turn this polyline sketch into walls
304
344
  * @examplePrompt Add walls with mitred corners along the path
345
+ * @examplePrompt Draw brick walls with plaster along this outline
346
+ * @examplePrompt Build the perimeter in exposed concrete walls
305
347
  *
306
348
  * # Example
307
349
  * ```ts
@@ -312,12 +354,18 @@ export abstract class PluginDesignCreateApi {
312
354
  * await v.new(8, 0, 6),
313
355
  * ])
314
356
  * const walls = await snaptrude.design.create.walls(centerlines, 3, 0.2)
357
+ * // …built as a specific wall type (layers/material/thickness from the type):
358
+ * const [brick] = await snaptrude.design.types.list("wall")
359
+ * const brickWalls = await snaptrude.design.create.walls(
360
+ * centerlines, 3, undefined, brick.label,
361
+ * )
315
362
  * ```
316
363
  */
317
364
  public abstract walls(
318
365
  profile: ProfileHandle,
319
366
  height?: number,
320
367
  thickness?: number,
368
+ wallType?: string,
321
369
  ): PluginApiReturn<ComponentHandle[]>
322
370
 
323
371
  /**
@@ -408,14 +456,19 @@ export abstract class PluginDesignCreateApi {
408
456
  * with {@linkcode PluginDesignFurnitureApi.listCatalog}. Placement is asynchronous
409
457
  * (the source mesh is fetched if not cached) and creates one undo entry.
410
458
  *
411
- * Placed at the item's default rotation; rotate afterward via `design.transform.rotate`
412
- * on the returned handle (planned namespace).
459
+ * Placed at the item's default rotation unless `angleInDegrees` is given, which
460
+ * rotates it about the vertical axis at creation time (baked into the same undo
461
+ * entry). To rotate an existing instance instead, use `design.transform.rotate`.
413
462
  *
414
463
  * @param catalogId - Library id: team `_id` or general `fullName`
415
464
  * @param position - Absolute world placement point
416
465
  * @param options - Optional placement options: `label` — instance name
417
466
  * (default auto `${name}Ins${n}`); `createNewSourceMesh` — emit a
418
467
  * source-mesh creation command (default `true`)
468
+ * @param angleInDegrees - Optional signed rotation about the vertical axis, in
469
+ * degrees (same convention as {@linkcode PluginDesignTransformApi.rotate}).
470
+ * Applied at creation time so it is part of the placement's single undo entry.
471
+ * Default: the item's own (unrotated) orientation.
419
472
  * @returns the {@linkcode ComponentHandle} of the placed furniture instance
420
473
  * @throws if the catalog id is unknown, the source mesh fails to load, or placement fails
421
474
  *
@@ -424,6 +477,7 @@ export abstract class PluginDesignCreateApi {
424
477
  * @examplePrompt Drop a desk into the scene at 3, 0, 5
425
478
  * @examplePrompt Insert the uploaded bed model in the bedroom
426
479
  * @examplePrompt Put a table from my project library here and name it Table-01
480
+ * @examplePrompt Place a chair here rotated 90 degrees
427
481
  *
428
482
  * # Example
429
483
  * ```ts
@@ -432,12 +486,20 @@ export abstract class PluginDesignCreateApi {
432
486
  * await snaptrude.core.math.vec3.new(3, 0, 5),
433
487
  * { label: "Chair-01" },
434
488
  * )
489
+ * // …placed already turned 90° about the vertical axis:
490
+ * const turned = await snaptrude.design.create.furniture(
491
+ * "6620f1a…",
492
+ * await snaptrude.core.math.vec3.new(3, 0, 5),
493
+ * undefined,
494
+ * 90,
495
+ * )
435
496
  * ```
436
497
  */
437
498
  public abstract furniture(
438
499
  catalogId: string,
439
500
  position: Vec3Handle,
440
501
  options?: { label?: string; createNewSourceMesh?: boolean },
502
+ angleInDegrees?: number,
441
503
  ): PluginApiReturn<ComponentHandle>
442
504
 
443
505
  /**
@@ -454,6 +516,11 @@ export abstract class PluginDesignCreateApi {
454
516
  * @param hostWall - The wall to host the door
455
517
  * @param position - World point projected onto the wall to locate the opening
456
518
  * @param options - Optional placement options: `label` — instance name
519
+ * @param facing - World point selecting which side of the wall the door faces
520
+ * (the room it opens into) — the same convention as approaching the wall
521
+ * from that side with the cursor in the interactive tool. Any point clearly
522
+ * on that side works (e.g. the room's center). Default: the engine picks a
523
+ * side (nondeterministic when `position` sits on the wall centerline).
457
524
  * @returns the {@linkcode ComponentHandle} of the placed door
458
525
  * @throws if the catalog id is unknown, the host is not a wall, the source
459
526
  * mesh fails to load, or the projected point falls **outside** the host wall
@@ -463,6 +530,7 @@ export abstract class PluginDesignCreateApi {
463
530
  * @examplePrompt Put a door from the catalog at this point on the wall
464
531
  * @examplePrompt Insert the entrance door into this wall
465
532
  * @examplePrompt Add a door to the wall and call it Entry-01
533
+ * @examplePrompt Add a door that opens into the living room
466
534
  *
467
535
  * # Example
468
536
  * ```ts
@@ -474,6 +542,14 @@ export abstract class PluginDesignCreateApi {
474
542
  * await snaptrude.core.math.vec3.new(3, 0, 5),
475
543
  * { label: "Entry-01" },
476
544
  * )
545
+ * // …facing a specific side of the wall (pass a point inside that room):
546
+ * const intoKitchen = await snaptrude.design.create.door(
547
+ * entry.id,
548
+ * wall,
549
+ * await snaptrude.core.math.vec3.new(3, 0, 5),
550
+ * undefined,
551
+ * await snaptrude.core.math.vec3.new(3, 0, 9),
552
+ * )
477
553
  * ```
478
554
  */
479
555
  public abstract door(
@@ -481,6 +557,7 @@ export abstract class PluginDesignCreateApi {
481
557
  hostWall: ComponentHandle,
482
558
  position: Vec3Handle,
483
559
  options?: { label?: string },
560
+ facing?: Vec3Handle,
484
561
  ): PluginApiReturn<ComponentHandle>
485
562
 
486
563
  /**
@@ -497,6 +574,10 @@ export abstract class PluginDesignCreateApi {
497
574
  * @param hostWall - The wall to host the window
498
575
  * @param position - World point projected onto the wall to locate the opening
499
576
  * @param options - Optional placement options: `label` — instance name
577
+ * @param facing - World point selecting which side of the wall the window
578
+ * faces (matters for asymmetric windows, e.g. casement swing) — same
579
+ * convention as {@linkcode PluginDesignCreateApi.door}. Default: the engine
580
+ * picks a side (nondeterministic when `position` sits on the centerline).
500
581
  * @returns the {@linkcode ComponentHandle} of the placed window
501
582
  * @throws if the catalog id is unknown, the host is not a wall, the source
502
583
  * mesh fails to load, or the projected point falls **outside** the host wall
@@ -506,6 +587,7 @@ export abstract class PluginDesignCreateApi {
506
587
  * @examplePrompt Put a window from the catalog at this point on the wall
507
588
  * @examplePrompt Insert a window into the living room wall
508
589
  * @examplePrompt Add a window to the wall and name it Win-01
590
+ * @examplePrompt Add a casement window opening toward the garden side
509
591
  *
510
592
  * # Example
511
593
  * ```ts
@@ -524,6 +606,7 @@ export abstract class PluginDesignCreateApi {
524
606
  hostWall: ComponentHandle,
525
607
  position: Vec3Handle,
526
608
  options?: { label?: string },
609
+ facing?: Vec3Handle,
527
610
  ): PluginApiReturn<ComponentHandle>
528
611
 
529
612
  /**
@@ -619,15 +702,20 @@ export abstract class PluginDesignCreateApi {
619
702
  * Migrated from the removed `entity.space.bulkCreate`. Each item extrudes a contour
620
703
  * footprint up `height`. Validate-all-or-throw; one command. For a rectangular
621
704
  * (box) space, build the footprint with `core.geom.create.profileRect` →
622
- * `contourFromProfile`, then pass it as an item.
705
+ * `contourFromProfile`, then pass it as an item. Each item may carry its own
706
+ * `storey` (see {@linkcode PluginCreateSpaceItem}) so a single call can populate
707
+ * several floors at once.
623
708
  *
624
709
  * @param items - One {@linkcode PluginCreateSpaceItem} per space to create (≥1)
625
710
  * @returns the created spaces as {@linkcode ComponentHandle}`[]`, in input order
711
+ * @throws if any item's contour is invalid, its height is not positive, or its
712
+ * target `storey` does not exist (all-or-nothing — nothing is created)
626
713
  *
627
714
  * @examplePrompt Create several rooms at once from these footprints
628
715
  * @examplePrompt Generate all the bedrooms in one operation
629
716
  * @examplePrompt Bulk create the spaces for this floor plan
630
717
  * @examplePrompt Add three rooms with different heights in a single undo step
718
+ * @examplePrompt Create one room on the ground floor and one on the first floor
631
719
  *
632
720
  * # Example
633
721
  * ```ts
@@ -639,7 +727,9 @@ export abstract class PluginDesignCreateApi {
639
727
  * ])
640
728
  * ```
641
729
  */
642
- public abstract spaces(items: PluginCreateSpaceItem[]): PluginApiReturn<ComponentHandle[]>
730
+ public abstract spaces(
731
+ items: PluginCreateSpaceItem[],
732
+ ): PluginApiReturn<ComponentHandle[]>
643
733
  }
644
734
 
645
735
  // ---------------------------------------------------------------------------
@@ -717,6 +807,7 @@ export type PluginStaircasePreset = z.infer<typeof PluginStaircasePreset>
717
807
  * | `spaceType` | {@linkcode PluginSpaceType}? | Space-type classification (default `Room`) |
718
808
  * | `massType` | {@linkcode PluginMassType}? | Mass-type classification (default `Room`) |
719
809
  * | `departmentId` | {@linkcode PluginDepartmentId}? | Department assignment (default department) |
810
+ * | `storey` | `number`? (int) | Target storey number (default active storey) |
720
811
  */
721
812
  export const PluginDesignCreateSpaceArgs = z.object({
722
813
  contour: ContourHandle,
@@ -726,8 +817,13 @@ export const PluginDesignCreateSpaceArgs = z.object({
726
817
  spaceType: PluginSpaceType.optional(),
727
818
  massType: PluginMassType.optional(),
728
819
  departmentId: PluginDepartmentId.optional(),
820
+ storey: z.number().int().optional(),
729
821
  })
730
- export type PluginDesignCreateSpaceArgs = z.infer<typeof PluginDesignCreateSpaceArgs>
822
+ export type PluginDesignCreateSpaceArgs = z.infer<
823
+ typeof PluginDesignCreateSpaceArgs
824
+ >
825
+ // TRANSPORT: positional signature shipped — storey is the trailing 8th arg:
826
+ // space(contour, height, label?, position?, spaceType?, massType?, departmentId?, storey?)
731
827
 
732
828
  // ---------------------------------------------------------------------------
733
829
  // mass
@@ -751,7 +847,9 @@ export const PluginDesignCreateMassArgs = z.object({
751
847
  position: Vec3Handle.optional(),
752
848
  massType: PluginMassType.optional(),
753
849
  })
754
- export type PluginDesignCreateMassArgs = z.infer<typeof PluginDesignCreateMassArgs>
850
+ export type PluginDesignCreateMassArgs = z.infer<
851
+ typeof PluginDesignCreateMassArgs
852
+ >
755
853
 
756
854
  // ---------------------------------------------------------------------------
757
855
  // slab
@@ -773,7 +871,9 @@ export const PluginDesignCreateSlabArgs = z.object({
773
871
  direction: z.enum(["up", "down"]).optional(),
774
872
  slabType: PluginSlabType.optional(),
775
873
  })
776
- export type PluginDesignCreateSlabArgs = z.infer<typeof PluginDesignCreateSlabArgs>
874
+ export type PluginDesignCreateSlabArgs = z.infer<
875
+ typeof PluginDesignCreateSlabArgs
876
+ >
777
877
 
778
878
  // ---------------------------------------------------------------------------
779
879
  // floor
@@ -793,7 +893,9 @@ export const PluginDesignCreateFloorArgs = z.object({
793
893
  thickness: z.number(),
794
894
  position: Vec3Handle.optional(),
795
895
  })
796
- export type PluginDesignCreateFloorArgs = z.infer<typeof PluginDesignCreateFloorArgs>
896
+ export type PluginDesignCreateFloorArgs = z.infer<
897
+ typeof PluginDesignCreateFloorArgs
898
+ >
797
899
 
798
900
  // ---------------------------------------------------------------------------
799
901
  // roof
@@ -811,7 +913,9 @@ export const PluginDesignCreateRoofArgs = z.object({
811
913
  contour: ContourHandle,
812
914
  thickness: z.number(),
813
915
  })
814
- export type PluginDesignCreateRoofArgs = z.infer<typeof PluginDesignCreateRoofArgs>
916
+ export type PluginDesignCreateRoofArgs = z.infer<
917
+ typeof PluginDesignCreateRoofArgs
918
+ >
815
919
 
816
920
  // ---------------------------------------------------------------------------
817
921
  // ceiling
@@ -831,7 +935,9 @@ export const PluginDesignCreateCeilingArgs = z.object({
831
935
  thickness: z.number(),
832
936
  heightFromFloor: z.number().optional(),
833
937
  })
834
- export type PluginDesignCreateCeilingArgs = z.infer<typeof PluginDesignCreateCeilingArgs>
938
+ export type PluginDesignCreateCeilingArgs = z.infer<
939
+ typeof PluginDesignCreateCeilingArgs
940
+ >
835
941
 
836
942
  // ---------------------------------------------------------------------------
837
943
  // column
@@ -853,7 +959,9 @@ export const PluginDesignCreateColumnArgs = z.object({
853
959
  height: z.number(),
854
960
  directionUp: Vec3Handle.optional(),
855
961
  })
856
- export type PluginDesignCreateColumnArgs = z.infer<typeof PluginDesignCreateColumnArgs>
962
+ export type PluginDesignCreateColumnArgs = z.infer<
963
+ typeof PluginDesignCreateColumnArgs
964
+ >
857
965
 
858
966
  // ---------------------------------------------------------------------------
859
967
  // beam
@@ -873,7 +981,9 @@ export const PluginDesignCreateBeamArgs = z.object({
873
981
  length: z.number(),
874
982
  direction: Vec3Handle.optional(),
875
983
  })
876
- export type PluginDesignCreateBeamArgs = z.infer<typeof PluginDesignCreateBeamArgs>
984
+ export type PluginDesignCreateBeamArgs = z.infer<
985
+ typeof PluginDesignCreateBeamArgs
986
+ >
877
987
 
878
988
  // ---------------------------------------------------------------------------
879
989
  // walls
@@ -886,14 +996,20 @@ export type PluginDesignCreateBeamArgs = z.infer<typeof PluginDesignCreateBeamAr
886
996
  * |---|---|---|
887
997
  * | `profile` | {@linkcode ProfileHandle} | Ordered curve chain (wall centerlines) |
888
998
  * | `height` | `number`? | Wall height (default engine default) |
889
- * | `thickness` | `number`? | Wall thickness (default engine default) |
999
+ * | `thickness` | `number`? | Wall thickness (default: `wallType`'s total layer thickness when given, else engine default) |
1000
+ * | `wallType` | `string`? | Wall type name from `design.types.list("wall")` — layers/material/thickness defaults (default generic) |
890
1001
  */
891
1002
  export const PluginDesignCreateWallsArgs = z.object({
892
1003
  profile: ProfileHandle,
893
1004
  height: z.number().optional(),
894
1005
  thickness: z.number().optional(),
1006
+ wallType: z.string().min(1).optional(),
895
1007
  })
896
- export type PluginDesignCreateWallsArgs = z.infer<typeof PluginDesignCreateWallsArgs>
1008
+ export type PluginDesignCreateWallsArgs = z.infer<
1009
+ typeof PluginDesignCreateWallsArgs
1010
+ >
1011
+ // TRANSPORT: positional signature shipped — wallType is the trailing 4th arg:
1012
+ // walls(profile: ProfileHandle, height?: number, thickness?: number, wallType?: string)
897
1013
 
898
1014
  // ---------------------------------------------------------------------------
899
1015
  // staircase
@@ -934,18 +1050,20 @@ export type PluginDesignCreateStaircaseArgs = z.infer<
934
1050
  * | `position` | {@linkcode Vec3Handle} | Absolute world placement point |
935
1051
  * | `label` | `string`? | Instance name (default auto `${name}Ins${n}`) |
936
1052
  * | `createNewSourceMesh` | `boolean`? | Emit a source-mesh creation command (default `true`) |
1053
+ * | `angleInDegrees` | `number`? | Rotation about the vertical axis, in degrees (default unrotated) |
937
1054
  */
938
1055
  export const PluginDesignCreateFurnitureArgs = z.object({
939
1056
  catalogId: z.string().min(1),
940
1057
  position: Vec3Handle,
941
1058
  label: z.string().optional(),
942
1059
  createNewSourceMesh: z.boolean().optional(),
1060
+ angleInDegrees: z.number().optional(),
943
1061
  })
944
1062
  export type PluginDesignCreateFurnitureArgs = z.infer<
945
1063
  typeof PluginDesignCreateFurnitureArgs
946
1064
  >
947
- // TRANSPORT: positional signature shipped —
948
- // furniture(catalogId: string, position: Vec3Handle, options?: { label?, createNewSourceMesh? })
1065
+ // TRANSPORT: positional signature shipped — angleInDegrees is the trailing 4th arg:
1066
+ // furniture(catalogId: string, position: Vec3Handle, options?: { label?, createNewSourceMesh? }, angleInDegrees?: number)
949
1067
 
950
1068
  // ---------------------------------------------------------------------------
951
1069
  // door
@@ -960,16 +1078,20 @@ export type PluginDesignCreateFurnitureArgs = z.infer<
960
1078
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
961
1079
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
962
1080
  * | `label` | `string`? | Instance name (optional) |
1081
+ * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door faces (default engine-chosen) |
963
1082
  */
964
1083
  export const PluginDesignCreateDoorArgs = z.object({
965
1084
  catalogId: z.string().min(1),
966
1085
  hostWall: ComponentHandle,
967
1086
  position: Vec3Handle,
968
1087
  label: z.string().optional(),
1088
+ facing: Vec3Handle.optional(),
969
1089
  })
970
- export type PluginDesignCreateDoorArgs = z.infer<typeof PluginDesignCreateDoorArgs>
971
- // TRANSPORT: positional signature shipped —
972
- // door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? })
1090
+ export type PluginDesignCreateDoorArgs = z.infer<
1091
+ typeof PluginDesignCreateDoorArgs
1092
+ >
1093
+ // TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
1094
+ // door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
973
1095
 
974
1096
  // ---------------------------------------------------------------------------
975
1097
  // window
@@ -984,16 +1106,20 @@ export type PluginDesignCreateDoorArgs = z.infer<typeof PluginDesignCreateDoorAr
984
1106
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
985
1107
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
986
1108
  * | `label` | `string`? | Instance name (optional) |
1109
+ * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window faces (default engine-chosen) |
987
1110
  */
988
1111
  export const PluginDesignCreateWindowArgs = z.object({
989
1112
  catalogId: z.string().min(1),
990
1113
  hostWall: ComponentHandle,
991
1114
  position: Vec3Handle,
992
1115
  label: z.string().optional(),
1116
+ facing: Vec3Handle.optional(),
993
1117
  })
994
- export type PluginDesignCreateWindowArgs = z.infer<typeof PluginDesignCreateWindowArgs>
995
- // TRANSPORT: positional signature shipped —
996
- // window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? })
1118
+ export type PluginDesignCreateWindowArgs = z.infer<
1119
+ typeof PluginDesignCreateWindowArgs
1120
+ >
1121
+ // TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
1122
+ // window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
997
1123
 
998
1124
  // ---------------------------------------------------------------------------
999
1125
  // smartLayout
@@ -1019,7 +1145,7 @@ export const PluginSmartLayoutArgs = z
1019
1145
  })
1020
1146
  .refine(
1021
1147
  (v) =>
1022
- (v.templateGroup != null) !== ((v.templateComponents?.length ?? 0) > 0),
1148
+ (v.templateGroup != null) !== (v.templateComponents?.length ?? 0) > 0,
1023
1149
  {
1024
1150
  message:
1025
1151
  "Provide exactly one template source: templateGroup or a non-empty templateComponents",
@@ -1110,7 +1236,9 @@ export const PluginDesignCreateCopyArgs = z.object({
1110
1236
  count: z.number().int().positive().optional(),
1111
1237
  mode: PluginCopyMode.optional(),
1112
1238
  })
1113
- export type PluginDesignCreateCopyArgs = z.infer<typeof PluginDesignCreateCopyArgs>
1239
+ export type PluginDesignCreateCopyArgs = z.infer<
1240
+ typeof PluginDesignCreateCopyArgs
1241
+ >
1114
1242
  // TRANSPORT: positional signature shipped —
1115
1243
  // copy(components: ComponentHandle[], displacement: Vec3Handle, options?: { count?, mode? })
1116
1244
 
@@ -1131,6 +1259,7 @@ export type PluginDesignCreateCopyArgs = z.infer<typeof PluginDesignCreateCopyAr
1131
1259
  * | `spaceType` | `PluginSpaceType`? | Space type |
1132
1260
  * | `massType` | `PluginMassType`? | Mass type |
1133
1261
  * | `departmentId` | `PluginDepartmentId`? | Department |
1262
+ * | `storey` | `number`? (int) | Target storey number (default active storey) |
1134
1263
  */
1135
1264
  export const PluginCreateSpaceItem = z.object({
1136
1265
  contour: ContourHandle,
@@ -1140,5 +1269,6 @@ export const PluginCreateSpaceItem = z.object({
1140
1269
  spaceType: PluginSpaceType.optional(),
1141
1270
  massType: PluginMassType.optional(),
1142
1271
  departmentId: PluginDepartmentId.optional(),
1272
+ storey: z.number().int().optional(),
1143
1273
  })
1144
1274
  export type PluginCreateSpaceItem = z.infer<typeof PluginCreateSpaceItem>
@@ -105,6 +105,30 @@ export abstract class PluginDesignDoorsApi {
105
105
  */
106
106
  public abstract getHeight(door: ComponentHandle): PluginApiReturn<number | null>
107
107
 
108
+ /**
109
+ * Get a door's full dimensions in one call — width along the wall, vertical
110
+ * height, and thickness through the wall — measured in the door's local
111
+ * oriented space. Parity with {@linkcode PluginDesignWindowsApi.getDimensions}.
112
+ *
113
+ * @param door The door to query
114
+ * @returns The dimensions, or `null`
115
+ *
116
+ * @examplePrompt What are the dimensions of this door?
117
+ * @examplePrompt How big is the selected door?
118
+ * @examplePrompt Give me the width, height and depth of this door
119
+ * @examplePrompt Measure the entrance door including its thickness through the wall
120
+ *
121
+ * # Example
122
+ * ```ts
123
+ * const [door] = await snaptrude.design.query.listDoors({ isSelected: true })
124
+ * const dims = await snaptrude.design.doors.getDimensions(door)
125
+ * if (dims) console.log(dims.width, dims.height, dims.thickness)
126
+ * ```
127
+ */
128
+ public abstract getDimensions(
129
+ door: ComponentHandle
130
+ ): PluginApiReturn<PluginDoorDimensions | null>
131
+
108
132
  /**
109
133
  * Get the floor a door is hosted on — the storey/level component that
110
134
  * supports the door.
@@ -329,6 +353,22 @@ export const PluginDesignDoorArgs = z.object({
329
353
  })
330
354
  export type PluginDesignDoorArgs = z.infer<typeof PluginDesignDoorArgs>
331
355
 
356
+ /**
357
+ * A door's dimensions (engine units), symmetric with {@linkcode PluginWindowDimensions}.
358
+ *
359
+ * | Property | Type | Description |
360
+ * |---|---|---|
361
+ * | `width` | `number` | Along the wall |
362
+ * | `height` | `number` | Vertical |
363
+ * | `thickness` | `number` | Through the wall (engine `length` axis) |
364
+ */
365
+ export const PluginDoorDimensions = z.object({
366
+ width: z.number(),
367
+ height: z.number(),
368
+ thickness: z.number(),
369
+ })
370
+ export type PluginDoorDimensions = z.infer<typeof PluginDoorDimensions>
371
+
332
372
  /** Mirror axis — tokens mirror the engine `FlipDirection` verbatim (§6.1). */
333
373
  export const PluginMirrorAxis = z.enum(["x", "y", "z"])
334
374
  export type PluginMirrorAxis = z.infer<typeof PluginMirrorAxis>