@snaptrude/plugin-core 0.10.0 → 1.0.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 (229) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +187 -3
  3. package/api-manifest.json +929 -25
  4. package/dist/api/analysis/daylight.d.ts +5 -5
  5. package/dist/api/analysis/solar.d.ts +2 -2
  6. package/dist/api/core/camera/index.d.ts +463 -0
  7. package/dist/api/core/camera/index.d.ts.map +1 -1
  8. package/dist/api/core/geom/create/index.d.ts +942 -101
  9. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  10. package/dist/api/core/geom/query/brep.d.ts +59 -2
  11. package/dist/api/core/geom/query/brep.d.ts.map +1 -1
  12. package/dist/api/core/geom/query/curve.d.ts +59 -35
  13. package/dist/api/core/geom/query/curve.d.ts.map +1 -1
  14. package/dist/api/core/geom/query/edge.d.ts +2 -2
  15. package/dist/api/core/geom/query/face.d.ts +105 -0
  16. package/dist/api/core/geom/query/face.d.ts.map +1 -1
  17. package/dist/api/core/geom/update/contour.d.ts +10 -2
  18. package/dist/api/core/geom/update/contour.d.ts.map +1 -1
  19. package/dist/api/core/geom/update/curve.d.ts +5 -5
  20. package/dist/api/core/geom/update/profile.d.ts +3 -1
  21. package/dist/api/core/geom/update/profile.d.ts.map +1 -1
  22. package/dist/api/core/handles/index.d.ts +4 -2
  23. package/dist/api/core/handles/index.d.ts.map +1 -1
  24. package/dist/api/core/index.d.ts +4 -4
  25. package/dist/api/core/index.d.ts.map +1 -1
  26. package/dist/api/core/io/import/index.d.ts +3 -1
  27. package/dist/api/core/io/import/index.d.ts.map +1 -1
  28. package/dist/api/core/layers.d.ts +377 -255
  29. package/dist/api/core/layers.d.ts.map +1 -1
  30. package/dist/api/core/mode/index.d.ts +19 -7
  31. package/dist/api/core/mode/index.d.ts.map +1 -1
  32. package/dist/api/core/project/index.d.ts +68 -1
  33. package/dist/api/core/project/index.d.ts.map +1 -1
  34. package/dist/api/core/proposals/index.d.ts +4 -3
  35. package/dist/api/core/proposals/index.d.ts.map +1 -1
  36. package/dist/api/core/storeys/index.d.ts +31 -2
  37. package/dist/api/core/storeys/index.d.ts.map +1 -1
  38. package/dist/api/core/storeys/layers.d.ts +408 -0
  39. package/dist/api/core/storeys/layers.d.ts.map +1 -0
  40. package/dist/api/core/tags.d.ts +84 -3
  41. package/dist/api/core/tags.d.ts.map +1 -1
  42. package/dist/api/core/zoom/index.d.ts +13 -0
  43. package/dist/api/core/zoom/index.d.ts.map +1 -1
  44. package/dist/api/design/bim.d.ts +299 -0
  45. package/dist/api/design/bim.d.ts.map +1 -0
  46. package/dist/api/design/boolean/index.d.ts +2 -0
  47. package/dist/api/design/boolean/index.d.ts.map +1 -1
  48. package/dist/api/design/catalog.d.ts +320 -0
  49. package/dist/api/design/catalog.d.ts.map +1 -0
  50. package/dist/api/design/create/bulk-items.d.ts +269 -0
  51. package/dist/api/design/create/bulk-items.d.ts.map +1 -0
  52. package/dist/api/design/create/grids.d.ts +132 -0
  53. package/dist/api/design/create/grids.d.ts.map +1 -0
  54. package/dist/api/design/create/index.d.ts +752 -78
  55. package/dist/api/design/create/index.d.ts.map +1 -1
  56. package/dist/api/design/create/opening-fields.d.ts +38 -0
  57. package/dist/api/design/create/opening-fields.d.ts.map +1 -0
  58. package/dist/api/design/delete/index.d.ts +5 -0
  59. package/dist/api/design/delete/index.d.ts.map +1 -1
  60. package/dist/api/design/dimensions.d.ts +427 -0
  61. package/dist/api/design/dimensions.d.ts.map +1 -0
  62. package/dist/api/design/doors/index.d.ts +24 -23
  63. package/dist/api/design/doors/index.d.ts.map +1 -1
  64. package/dist/api/design/family.d.ts +1446 -0
  65. package/dist/api/design/family.d.ts.map +1 -0
  66. package/dist/api/design/furniture/index.d.ts +33 -0
  67. package/dist/api/design/furniture/index.d.ts.map +1 -1
  68. package/dist/api/design/grids.d.ts +237 -0
  69. package/dist/api/design/grids.d.ts.map +1 -0
  70. package/dist/api/design/index.d.ts +30 -0
  71. package/dist/api/design/index.d.ts.map +1 -1
  72. package/dist/api/design/networks.d.ts +1703 -0
  73. package/dist/api/design/networks.d.ts.map +1 -0
  74. package/dist/api/design/query/geometry/index.d.ts +33 -5
  75. package/dist/api/design/query/geometry/index.d.ts.map +1 -1
  76. package/dist/api/design/query/grids.d.ts +287 -0
  77. package/dist/api/design/query/grids.d.ts.map +1 -0
  78. package/dist/api/design/query/index.d.ts +143 -34
  79. package/dist/api/design/query/index.d.ts.map +1 -1
  80. package/dist/api/design/query/spaces.d.ts +5 -5
  81. package/dist/api/design/selection/index.d.ts +12 -12
  82. package/dist/api/design/types/index.d.ts +40 -24
  83. package/dist/api/design/types/index.d.ts.map +1 -1
  84. package/dist/api/design/update/index.d.ts +412 -8
  85. package/dist/api/design/update/index.d.ts.map +1 -1
  86. package/dist/api/design/visibility.d.ts +28 -0
  87. package/dist/api/design/visibility.d.ts.map +1 -1
  88. package/dist/api/design/windows/index.d.ts +8 -8
  89. package/dist/api/design/windows/index.d.ts.map +1 -1
  90. package/dist/api/entity/buildableEnvelope.d.ts +84 -2
  91. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
  92. package/dist/api/entity/referenceLine.d.ts +13 -1
  93. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  94. package/dist/api/entity/space.d.ts +12 -12
  95. package/dist/api/entity/story.d.ts +4 -4
  96. package/dist/api/presentation/aiInspiration.d.ts +24 -24
  97. package/dist/api/presentation/annotate.d.ts +38 -22
  98. package/dist/api/presentation/annotate.d.ts.map +1 -1
  99. package/dist/api/presentation/camera.d.ts +265 -0
  100. package/dist/api/presentation/camera.d.ts.map +1 -0
  101. package/dist/api/presentation/drawingContract.d.ts +32 -0
  102. package/dist/api/presentation/drawingContract.d.ts.map +1 -0
  103. package/dist/api/presentation/drawings.d.ts +3523 -0
  104. package/dist/api/presentation/drawings.d.ts.map +1 -0
  105. package/dist/api/presentation/export.d.ts +23 -5
  106. package/dist/api/presentation/export.d.ts.map +1 -1
  107. package/dist/api/presentation/graphics.d.ts +419 -0
  108. package/dist/api/presentation/graphics.d.ts.map +1 -0
  109. package/dist/api/presentation/index.d.ts +66 -12
  110. package/dist/api/presentation/index.d.ts.map +1 -1
  111. package/dist/api/presentation/placedViews.d.ts +116 -16
  112. package/dist/api/presentation/placedViews.d.ts.map +1 -1
  113. package/dist/api/presentation/sections.d.ts +461 -0
  114. package/dist/api/presentation/sections.d.ts.map +1 -0
  115. package/dist/api/presentation/shapes.d.ts +2 -2
  116. package/dist/api/presentation/sheets.d.ts +175 -19
  117. package/dist/api/presentation/sheets.d.ts.map +1 -1
  118. package/dist/api/presentation/standards.d.ts +590 -0
  119. package/dist/api/presentation/standards.d.ts.map +1 -0
  120. package/dist/api/presentation/viewPresets.d.ts +222 -0
  121. package/dist/api/presentation/viewPresets.d.ts.map +1 -0
  122. package/dist/api/presentation/views.d.ts +144 -9
  123. package/dist/api/presentation/views.d.ts.map +1 -1
  124. package/dist/api/presentation/walkthroughs.d.ts +1350 -0
  125. package/dist/api/presentation/walkthroughs.d.ts.map +1 -0
  126. package/dist/api/program/departments.d.ts +58 -2
  127. package/dist/api/program/departments.d.ts.map +1 -1
  128. package/dist/api/program/index.d.ts +16 -6
  129. package/dist/api/program/index.d.ts.map +1 -1
  130. package/dist/api/program/labels.d.ts +355 -0
  131. package/dist/api/program/labels.d.ts.map +1 -0
  132. package/dist/api/program/metadata.d.ts +328 -0
  133. package/dist/api/program/metadata.d.ts.map +1 -0
  134. package/dist/api/program/site.d.ts +4 -4
  135. package/dist/api/program/spreadsheet.d.ts +267 -4
  136. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  137. package/dist/api/workspace/index.d.ts +49 -2
  138. package/dist/api/workspace/index.d.ts.map +1 -1
  139. package/dist/errors/codes.d.ts +3 -1
  140. package/dist/errors/codes.d.ts.map +1 -1
  141. package/dist/handles.d.ts +32 -3
  142. package/dist/handles.d.ts.map +1 -1
  143. package/dist/index.cjs +6539 -2804
  144. package/dist/index.cjs.map +1 -1
  145. package/dist/index.d.ts +2 -0
  146. package/dist/index.d.ts.map +1 -1
  147. package/dist/index.js +6121 -2801
  148. package/dist/index.js.map +1 -1
  149. package/dist/massParameters.d.ts +287 -0
  150. package/dist/massParameters.d.ts.map +1 -0
  151. package/dist/massParameters.ops.d.ts +138 -0
  152. package/dist/massParameters.ops.d.ts.map +1 -0
  153. package/package.json +14 -13
  154. package/scripts/check-dist-fresh.mjs +22 -0
  155. package/scripts/generate-manifest.mjs +5 -0
  156. package/scripts/generate-manifest.test.mjs +14 -3
  157. package/src/api/core/camera/index.ts +446 -1
  158. package/src/api/core/geom/create/index.ts +1037 -102
  159. package/src/api/core/geom/query/brep.ts +60 -2
  160. package/src/api/core/geom/query/curve.ts +26 -2
  161. package/src/api/core/geom/query/edge.ts +2 -2
  162. package/src/api/core/geom/query/face.ts +109 -4
  163. package/src/api/core/geom/update/contour.ts +10 -2
  164. package/src/api/core/geom/update/profile.ts +2 -0
  165. package/src/api/core/handles/index.ts +3 -2
  166. package/src/api/core/index.ts +4 -4
  167. package/src/api/core/io/import/index.ts +11 -3
  168. package/src/api/core/layers.ts +380 -173
  169. package/src/api/core/mode/index.ts +19 -7
  170. package/src/api/core/project/index.ts +62 -1
  171. package/src/api/core/proposals/index.ts +4 -3
  172. package/src/api/core/storeys/index.ts +34 -2
  173. package/src/api/core/storeys/layers.ts +339 -0
  174. package/src/api/core/tags.ts +76 -0
  175. package/src/api/core/zoom/index.ts +13 -0
  176. package/src/api/design/bim.ts +210 -0
  177. package/src/api/design/boolean/index.ts +2 -0
  178. package/src/api/design/catalog.ts +203 -0
  179. package/src/api/design/create/bulk-items.ts +294 -0
  180. package/src/api/design/create/grids.ts +137 -0
  181. package/src/api/design/create/index.ts +823 -114
  182. package/src/api/design/create/opening-fields.ts +40 -0
  183. package/src/api/design/delete/index.ts +5 -0
  184. package/src/api/design/dimensions.ts +453 -0
  185. package/src/api/design/doors/index.ts +64 -41
  186. package/src/api/design/family.ts +1342 -0
  187. package/src/api/design/furniture/index.ts +34 -0
  188. package/src/api/design/grids.ts +237 -0
  189. package/src/api/design/index.ts +49 -4
  190. package/src/api/design/networks.ts +607 -0
  191. package/src/api/design/query/geometry/index.ts +35 -4
  192. package/src/api/design/query/grids.ts +197 -0
  193. package/src/api/design/query/index.ts +105 -3
  194. package/src/api/design/types/index.ts +31 -24
  195. package/src/api/design/update/index.ts +398 -4
  196. package/src/api/design/visibility.ts +34 -0
  197. package/src/api/design/windows/index.ts +40 -22
  198. package/src/api/entity/buildableEnvelope.ts +77 -2
  199. package/src/api/entity/referenceLine.ts +25 -12
  200. package/src/api/presentation/annotate.ts +90 -58
  201. package/src/api/presentation/camera.ts +289 -0
  202. package/src/api/presentation/drawingContract.ts +70 -0
  203. package/src/api/presentation/drawings.ts +1179 -0
  204. package/src/api/presentation/export.ts +32 -6
  205. package/src/api/presentation/graphics.ts +324 -0
  206. package/src/api/presentation/index.ts +73 -14
  207. package/src/api/presentation/placedViews.ts +119 -28
  208. package/src/api/presentation/sections.ts +420 -0
  209. package/src/api/presentation/sheets.ts +181 -20
  210. package/src/api/presentation/standards.ts +445 -0
  211. package/src/api/presentation/viewPresets.ts +241 -0
  212. package/src/api/presentation/views.ts +81 -10
  213. package/src/api/presentation/walkthroughs.ts +1201 -0
  214. package/src/api/program/departments.ts +54 -2
  215. package/src/api/program/index.ts +16 -6
  216. package/src/api/program/labels.ts +332 -0
  217. package/src/api/program/metadata.ts +364 -0
  218. package/src/api/program/spreadsheet.ts +282 -0
  219. package/src/api/workspace/index.ts +51 -2
  220. package/src/errors/codes.ts +7 -0
  221. package/src/handles.ts +42 -3
  222. package/src/index.ts +2 -0
  223. package/src/massParameters.ops.ts +246 -0
  224. package/src/massParameters.ts +427 -0
  225. package/test/drawingContract.test.mjs +288 -0
  226. package/test/errors.test.mjs +1 -0
  227. package/test/massParameters.test.mjs +952 -0
  228. package/test/paperPensContract.test.mjs +75 -0
  229. package/test/presentationViewSettings.test.mjs +85 -0
@@ -1,13 +1,19 @@
1
1
  import * as z from "zod";
2
2
  import { PluginApiReturn } from "../../../types";
3
- import { BrepHandle, ComponentHandle, ContourHandle, ProfileHandle, Vec3Handle } from "../../../handles";
3
+ import { BrepHandle, ComponentHandle, ContourHandle, LineHandle, CurveHandle, ProfileHandle, Vec3Handle } from "../../../handles";
4
+ import { PluginGridStyleOptions } from "./grids";
4
5
  import { PluginSpaceType, PluginMassType, PluginDepartmentId } from "../../entity/space";
5
- import { PluginBuildableEnvelopePolygonVertex, PluginBuildableEnvelopeSetbackTier, PluginBuildableEnvelopeVerticalCap, PluginBuildableEnvelopeCreateResult } from "../../entity/buildableEnvelope";
6
+ import { PluginBuildableEnvelopePolygonVertex, PluginBuildableEnvelopeSetbackTier, PluginBuildableEnvelopeVerticalCap, PluginBuildableEnvelopeCreateResult, PluginDesignCreateBuildableEnvelopeFromSiteResult } from "../../entity/buildableEnvelope";
7
+ import type { PluginCreateDoorItem, PluginCreateFloorItem, PluginCreateFurnitureItem, PluginCreateVoidItem, PluginCreateWallRunItem, PluginCreateWindowItem } from "./bulk-items";
8
+ import { PluginWallTopProfile } from "./bulk-items";
9
+ import { PluginWallType } from "../types";
10
+ import { PluginFamilyPlacement, PluginFamilyFloorOptions, PluginFamilySlabOptions, PluginFamilyCeilingOptions, PluginFamilyValues } from "../catalog";
6
11
  /**
7
12
  * `design.create.*` — author new scene-committed BIM entities.
8
13
  *
9
14
  * Every creator takes geometry handles + scalars and returns a
10
- * {@linkcode ComponentHandle} (or `ComponentHandle[]` for plural creators) — the
15
+ * {@linkcode ComponentHandle} (or `ComponentHandle[]` for plural creators;
16
+ * `wallRuns` returns one `ComponentHandle[]` per run) — the
11
17
  * `Component.id` of the created entity, resolvable across the rest of the
12
18
  * `design.*` surface. Creation is an undoable host call; it **throws** on failure
13
19
  * (no `Result` wrapper — consistent with `core.geom.create.*`).
@@ -15,9 +21,17 @@ import { PluginBuildableEnvelopePolygonVertex, PluginBuildableEnvelopeSetbackTie
15
21
  * Footprint objects take a {@linkcode ContourHandle} (outer profile + holes);
16
22
  * build one with `snaptrude.core.geom.create.contourFromProfile(s)`.
17
23
  *
18
- * `door`/`window` place a catalog item into a host wall (the world point is
24
+ * Family overloads take `{ type, values? }` from `design.catalog`. The family supplies
25
+ * construction; the contour or axis supplies instance geometry. Geometry uses SU,
26
+ * while family length overrides use mm and angles use degrees. Omitted parameters
27
+ * retain family defaults; shared/type, formula and geometry-bound overrides are refused.
28
+ * Placement never publishes a definition. Unsupported references or geometry fail before mutation.
29
+ *
30
+ * `door`/`window` place a parametric family into a host wall (the world point is
19
31
  * projected onto the wall face to locate the opening; the wall is re-cut in one
20
- * undo entry) and throw if the point projects outside the wall. `smartLayout` is
32
+ * undo entry) and throw if the point projects outside the wall. Voids
33
+ * (`void`/`voids`) are the third hosted child: holes through slabs, floors,
34
+ * roofs and ceilings. `smartLayout` is
21
35
  * the one creator returning a grouped {@linkcode PluginSmartLayoutResult} rather
22
36
  * than a handle — it clones an in-scene template into one or more target spaces,
23
37
  * merging every target into a single undo batch (see its JSDoc).
@@ -148,6 +162,9 @@ export declare abstract class PluginDesignCreateApi {
148
162
  * Create a **slab** by extruding a footprint contour by `thickness`
149
163
  * (default direction: down).
150
164
  *
165
+ * To cut a hole in an EXISTING one, use `design.create.void`; a contour hole
166
+ * here is baked into the footprint.
167
+ *
151
168
  * @param contour - Footprint (outer + holes)
152
169
  * @param thickness - Slab thickness (> 0)
153
170
  * @param direction - Extrusion direction (default `"down"`)
@@ -168,15 +185,28 @@ export declare abstract class PluginDesignCreateApi {
168
185
  * const slab = await snaptrude.design.create.slab(contour, 0.15, "down", "Plinth")
169
186
  * ```
170
187
  */
171
- abstract slab(contour: ContourHandle, thickness: number, direction?: "up" | "down", slabType?: PluginSlabType): PluginApiReturn<ComponentHandle>;
188
+ abstract slab(...args: [
189
+ contour: ContourHandle,
190
+ thickness: number,
191
+ direction?: "up" | "down",
192
+ slabType?: PluginSlabType
193
+ ] | [contour: ContourHandle, options: PluginFamilySlabOptions]): PluginApiReturn<ComponentHandle>;
172
194
  /**
173
195
  * Create a **floor** by extruding a footprint contour by `thickness`
174
196
  * (extruded upward).
175
197
  *
198
+ * The native family overload takes `{ type, values?, position? }`. Contour
199
+ * geometry uses SU; family values use mm. The family supplies layer thickness.
200
+ * PG2 can split or merge the footprint, so both overloads return an array.
201
+ * A merge into an existing floor can return no newly created handles.
202
+ *
203
+ * To cut a hole in an EXISTING one, use `design.create.void`; a contour hole
204
+ * here is baked into the footprint.
205
+ *
176
206
  * @param contour - Footprint (outer + holes)
177
207
  * @param thickness - Floor thickness (> 0)
178
208
  * @param position - Offset from origin
179
- * @returns the {@linkcode ComponentHandle} of the created floor
209
+ * @returns Newly created {@linkcode ComponentHandle}s; an empty array after a merge
180
210
  * @throws if the contour is invalid or the thickness is not positive
181
211
  *
182
212
  * @examplePrompt Create a floor from this room outline
@@ -190,12 +220,56 @@ export declare abstract class PluginDesignCreateApi {
190
220
  * const contour = await snaptrude.core.geom.create.contourFromProfile(rect)
191
221
  * const floor = await snaptrude.design.create.floor(contour, 0.1)
192
222
  * ```
223
+ *
224
+ * @performance For dimensional floors, `design.create.floors(items[])` uses one
225
+ * host round-trip and one undo entry. That bulk method does not accept native
226
+ * family options; use this method for a family-backed floor.
193
227
  */
194
- abstract floor(contour: ContourHandle, thickness: number, position?: Vec3Handle): PluginApiReturn<ComponentHandle>;
228
+ abstract floor(...args: [contour: ContourHandle, thickness: number, position?: Vec3Handle] | [contour: ContourHandle, options: PluginFamilyFloorOptions]): PluginApiReturn<ComponentHandle[]>;
229
+ /**
230
+ * Create **many floors** in one undoable operation (bulk plural of
231
+ * {@linkcode floor}). Each item extrudes its own footprint contour (outer
232
+ * profile + holes) upward by its own `thickness`, at its own optional
233
+ * position offset. Validate-all-or-throw; one command.
234
+ *
235
+ * @param items - One {@linkcode PluginCreateFloorItem} per floor to create
236
+ * (≥1, ≤1000)
237
+ * @returns the created floors as {@linkcode ComponentHandle}`[]`, in input order
238
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
239
+ * 1000 items, a non-positive thickness) or a contour is degenerate;
240
+ * `HANDLE_INVALID` if a `contour` or `position` handle is unknown or
241
+ * released; `OPERATION_FAILED` if extrusion fails (nothing is created —
242
+ * `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the
243
+ * plugin may not write.
244
+ *
245
+ * @examplePrompt Create floors for all these room outlines at once
246
+ * @examplePrompt Add a floor to every space in one operation
247
+ * @examplePrompt Bulk create the floor plates for this building
248
+ * @examplePrompt Lay 100mm floors across these five footprints in one undo step
249
+ * @examplePrompt Create the ground and first floor slabs together
250
+ *
251
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
252
+ * entry. Always prefer this over calling `design.create.floor` in a loop: build the
253
+ * full `items[]` array first (all contours and offsets up front), then make one call.
254
+ *
255
+ * # Example
256
+ * ```ts
257
+ * const rect = await snaptrude.core.geom.create.profileRect(5, 4)
258
+ * const contour = await snaptrude.core.geom.create.contourFromProfile(rect)
259
+ * const [ground, upper] = await snaptrude.design.create.floors([
260
+ * { contour, thickness: 0.1 },
261
+ * { contour, thickness: 0.1, position: await snaptrude.core.math.vec3.new(0, 3, 0) },
262
+ * ])
263
+ * ```
264
+ */
265
+ abstract floors(items: PluginCreateFloorItem[]): PluginApiReturn<ComponentHandle[]>;
195
266
  /**
196
267
  * Create a **roof** by extruding a footprint contour by `thickness`. Created
197
268
  * flat (extruded downward); pitch/slope is a separate post-creation edit.
198
269
  *
270
+ * To cut a hole in an EXISTING one, use `design.create.void`; a contour hole
271
+ * here is baked into the footprint.
272
+ *
199
273
  * @param contour - Footprint (outer + holes)
200
274
  * @param thickness - Roof-slab thickness (> 0)
201
275
  * @returns the {@linkcode ComponentHandle} of the created roof
@@ -213,11 +287,14 @@ export declare abstract class PluginDesignCreateApi {
213
287
  * const roof = await snaptrude.design.create.roof(contour, 0.2)
214
288
  * ```
215
289
  */
216
- abstract roof(contour: ContourHandle, thickness: number): PluginApiReturn<ComponentHandle>;
290
+ abstract roof(contour: ContourHandle, thickness: number | PluginFamilyPlacement): PluginApiReturn<ComponentHandle>;
217
291
  /**
218
292
  * Create a **ceiling** by extruding a footprint contour by `thickness`, lifted
219
293
  * `heightFromFloor` above the floor.
220
294
  *
295
+ * To cut a hole in an EXISTING one, use `design.create.void`; a contour hole
296
+ * here is baked into the footprint.
297
+ *
221
298
  * @param contour - Footprint (outer + holes)
222
299
  * @param thickness - Ceiling thickness (> 0)
223
300
  * @param heightFromFloor - Lift above the floor (default 0)
@@ -236,7 +313,7 @@ export declare abstract class PluginDesignCreateApi {
236
313
  * const ceiling = await snaptrude.design.create.ceiling(contour, 0.05, 2.8)
237
314
  * ```
238
315
  */
239
- abstract ceiling(contour: ContourHandle, thickness: number, heightFromFloor?: number): PluginApiReturn<ComponentHandle>;
316
+ abstract ceiling(...args: [contour: ContourHandle, thickness: number, heightFromFloor?: number] | [contour: ContourHandle, options: PluginFamilyCeilingOptions]): PluginApiReturn<ComponentHandle>;
240
317
  /**
241
318
  * Create a **column** by extruding a cross-section contour upward by `height`
242
319
  * from a base `position`. The column is built to EXACTLY `height` — unlike
@@ -264,7 +341,12 @@ export declare abstract class PluginDesignCreateApi {
264
341
  * const column = await snaptrude.design.create.column(base, crossSection, 3)
265
342
  * ```
266
343
  */
267
- abstract column(position: Vec3Handle, crossSection: ContourHandle, height: number, directionUp?: Vec3Handle): PluginApiReturn<ComponentHandle>;
344
+ abstract column(...args: [
345
+ position: Vec3Handle,
346
+ crossSection: ContourHandle,
347
+ height: number,
348
+ directionUp?: Vec3Handle
349
+ ] | [axis: LineHandle, options: PluginFamilyPlacement]): PluginApiReturn<ComponentHandle>;
268
350
  /**
269
351
  * Create a **beam** by extruding a cross-section contour along `direction` by
270
352
  * `length`. Matches the Snaptrude beam tool's semantics: the beam body hangs
@@ -305,7 +387,7 @@ export declare abstract class PluginDesignCreateApi {
305
387
  * const beam = await snaptrude.design.create.beam(section, 6, alongX)
306
388
  * ```
307
389
  */
308
- abstract beam(section: ContourHandle, length: number, direction?: Vec3Handle): PluginApiReturn<ComponentHandle>;
390
+ abstract beam(...args: [section: ContourHandle, length: number, direction?: Vec3Handle] | [axis: LineHandle, options: PluginFamilyPlacement]): PluginApiReturn<ComponentHandle>;
309
391
  /**
310
392
  * Create a connected run of **walls** from a profile — one wall per curve in
311
393
  * the profile's chain, with mitred corners at shared endpoints.
@@ -314,21 +396,27 @@ export declare abstract class PluginDesignCreateApi {
314
396
  * @param height - Wall height (default engine default)
315
397
  * @param thickness - Wall thickness (default: the `wallType`'s total layer
316
398
  * thickness when `wallType` is given, else the engine default)
317
- * @param wallType - Wall type to build with — the same searchable list the
318
- * Draw tab's Wall Type dropdown offers. Pass a name from
319
- * `design.types.list("wall")` (the summary's `label`, or its `"wall:…"` id).
320
- * Drives the wall's construction layers and default material, and — when
321
- * `thickness` is omitted — its total layer thickness. Default: the engine's
322
- * generic wall.
399
+ * @param wallType - Legacy label/`wall:` id, or the exact `nativeFamily`
400
+ * `{ id, version }` pin from `design.types.list("wall")`. Native pins are
401
+ * authorized on every use; selecting a family in Draw is not registration.
402
+ * Native pins support straight horizontal centerlines and flat tops only.
403
+ * Omit thickness for native pins; a conflicting explicit thickness rejects.
404
+ * Default: the engine's generic wall.
323
405
  * @param storey - Target storey (integer: `1` ground, `2` first floor, `-1`
324
406
  * basement — same convention as `design.create.space`). The walls are
325
407
  * assigned to it and lifted to its base elevation, all inside the same
326
408
  * single undo entry. The storey must already exist
327
409
  * (`core.storeys.create` first). Default: geometry-derived — a profile
328
410
  * drawn at y = 0 lands on storey 1; the ACTIVE storey is NOT consulted.
411
+ * @param topProfiles - Optional top edge per curve of `profile` (same order):
412
+ * a {@linkcode PluginWallTopProfile} makes that wall raked / gabled; `null`
413
+ * or a missing entry keeps it flat at `height`. Straight curves only. Such
414
+ * walls are non-parametric (see {@linkcode PluginWallTopProfile}).
329
415
  * @returns a {@linkcode ComponentHandle}`[]` (one per wall), in profile order
330
416
  * @throws if the profile is empty, `wallType` names no wall type in the
331
- * project, `storey` does not exist, or wall creation fails
417
+ * project, `storey` does not exist, `topProfiles` has more entries than the
418
+ * profile has curves or names an arc curve, a top profile drops to the wall
419
+ * base at a mitred corner, or wall creation fails
332
420
  *
333
421
  * @examplePrompt Draw walls along this centerline
334
422
  * @examplePrompt Create 3m high, 200mm thick walls from these points
@@ -337,6 +425,9 @@ export declare abstract class PluginDesignCreateApi {
337
425
  * @examplePrompt Add walls with mitred corners along the path
338
426
  * @examplePrompt Draw brick walls with plaster along this outline
339
427
  * @examplePrompt Build the perimeter in exposed concrete walls
428
+ * @examplePrompt Create a raked wall that slopes from 3m to 5m
429
+ * @examplePrompt Build a gable end wall with the ridge in the middle
430
+ * @examplePrompt Draw a wall with a sloped top edge
340
431
  *
341
432
  * # Example
342
433
  * ```ts
@@ -352,9 +443,77 @@ export declare abstract class PluginDesignCreateApi {
352
443
  * const brickWalls = await snaptrude.design.create.walls(
353
444
  * centerlines, 3, undefined, brick.label,
354
445
  * )
446
+ * // …a raked wall (3m at the start, 5m at the end) on a single centerline:
447
+ * const run = await snaptrude.core.geom.create.profileFromCurves([
448
+ * await snaptrude.core.geom.create.line(await v.new(0, 0, 10), await v.new(8, 0, 10)),
449
+ * ])
450
+ * const [raked] = await snaptrude.design.create.walls(run, undefined, 0.2, undefined, undefined, [
451
+ * [{ along: 0, height: 3 }, { along: 1, height: 5 }],
452
+ * ])
355
453
  * ```
454
+ *
455
+ * @performance For MORE THAN ONE run, call `design.create.wallRuns(items[])` — one
456
+ * host round-trip and ONE undo entry for every run in the batch. Looping this
457
+ * single-run creator is N round-trips and N undo entries.
356
458
  */
357
- abstract walls(profile: ProfileHandle, height?: number, thickness?: number, wallType?: string, storey?: number): PluginApiReturn<ComponentHandle[]>;
459
+ abstract walls(profile: ProfileHandle, height?: number, thickness?: number, wallType?: PluginWallType, storey?: number, topProfiles?: (PluginWallTopProfile | null)[], values?: PluginFamilyValues): PluginApiReturn<ComponentHandle[]>;
460
+ /**
461
+ * Create **many wall runs** in one undoable operation (bulk plural of
462
+ * {@linkcode walls}). Each item is one full run — a wall per curve in that
463
+ * item's profile chain, mitred at shared endpoints. Junctions resolve within a
464
+ * run, not between runs. Each item carries its own
465
+ * dimensions, `wallType` and `storey`, so a single call can build a whole
466
+ * floor plate or several storeys at once. Per-curve `topProfiles` make raked
467
+ * or gabled walls (see {@linkcode PluginWallTopProfile}). Validate-all-or-throw;
468
+ * one command.
469
+ *
470
+ * @param items - One {@linkcode PluginCreateWallRunItem} per run to create
471
+ * (≥1, ≤1000)
472
+ * @returns one {@linkcode ComponentHandle}`[]` per item, in input order —
473
+ * each inner array holding that run's walls in profile-curve order
474
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
475
+ * 1000 items, a non-positive height or thickness, a zero-length curve);
476
+ * `HANDLE_INVALID` if a `profile` handle is unknown or released;
477
+ * `PRECONDITION_FAILED` if a profile has no curves, `wallType` names no
478
+ * wall type in the project, or `storey` does not exist;
479
+ * `OPERATION_FAILED` if wall creation fails (nothing is created —
480
+ * `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the
481
+ * plugin may not write.
482
+ *
483
+ * @examplePrompt Draw all the walls of this floor plan at once
484
+ * @examplePrompt Build every room's perimeter in one operation
485
+ * @examplePrompt Bulk create wall runs from these centerlines
486
+ * @examplePrompt Create the walls for both storeys in a single undo step
487
+ * @examplePrompt Turn these polylines into 200mm brick walls together
488
+ * @examplePrompt Import these raked walls with their top profiles in one go
489
+ *
490
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
491
+ * entry. Always prefer this over calling `design.create.walls` in a loop: build the
492
+ * full `items[]` array first (all profiles up front), then make one call.
493
+ *
494
+ * # Example
495
+ * ```ts
496
+ * const v = snaptrude.core.math.vec3
497
+ * const ground = await snaptrude.core.geom.create.profileFromLinePoints([
498
+ * await v.new(0, 0, 0),
499
+ * await v.new(8, 0, 0),
500
+ * await v.new(8, 0, 6),
501
+ * ])
502
+ * const upper = await snaptrude.core.geom.create.profileFromLinePoints([
503
+ * await v.new(0, 0, 0),
504
+ * await v.new(8, 0, 0),
505
+ * ])
506
+ * const [groundWalls, upperWalls] = await snaptrude.design.create.wallRuns([
507
+ * { profile: ground, height: 3, thickness: 0.2 },
508
+ * { profile: upper, height: 3, storey: 2 },
509
+ * // one gable wall: 3m at both ends, 5m ridge in the middle
510
+ * { profile: upper, thickness: 0.2, storey: 3,
511
+ * topProfiles: [[{ along: 0, height: 3 }, { along: 0.5, height: 5 }, { along: 1, height: 3 }]] },
512
+ * ])
513
+ * console.log(groundWalls.length, "walls on the ground floor")
514
+ * ```
515
+ */
516
+ abstract wallRuns(items: PluginCreateWallRunItem[]): PluginApiReturn<ComponentHandle[][]>;
358
517
  /**
359
518
  * Create a **staircase** from a parametric preset, placed at a point.
360
519
  *
@@ -397,8 +556,14 @@ export declare abstract class PluginDesignCreateApi {
397
556
  * every created line.
398
557
  *
399
558
  * @param profile - Ordered curve chain (centerlines)
400
- * @param color - Hex color `"#RRGGBB"` (default white)
401
- * @param thickness - Line thickness (default 1)
559
+ * Prefer `{ styleId: "wide" }`: the project style's pen/pattern and native
560
+ * legacy mirror are saved in the creation command, as one undo step. styleId
561
+ * requires Paper Pens; unstyled legacy creation works with the feature off.
562
+ * Do not mix options with trailing positional arguments, or styleId with
563
+ * legacy thickness/style. The old positional signature remains supported.
564
+ *
565
+ * @param colorOrOptions - Options, or legacy hex color `"#RRGGBB"`.
566
+ * @param thickness - Legacy line thickness (default 1)
402
567
  * @param style - Line style (default `SOLID`)
403
568
  * @param gridTag - Grid tag label (default `"A"`)
404
569
  * @returns a {@linkcode ComponentHandle}`[]` (one per curve), in profile order
@@ -425,7 +590,113 @@ export declare abstract class PluginDesignCreateApi {
425
590
  * )
426
591
  * ```
427
592
  */
428
- abstract referenceLines(profile: ProfileHandle, color?: string, thickness?: number, style?: PluginReferenceLineStyle, gridTag?: string): PluginApiReturn<ComponentHandle[]>;
593
+ abstract referenceLines(profile: ProfileHandle, colorOrOptions?: string | PluginReferenceLineOptions, thickness?: number, style?: PluginReferenceLineStyle, gridTag?: string): PluginApiReturn<ComponentHandle[]>;
594
+ /**
595
+ * Create a free rectangular **structural grid** — one grid group with two
596
+ * perpendicular line families (`linesX` lines spaced `spacingX` apart, and
597
+ * `linesY` lines spaced `spacingY` apart) on the active storey. One undoable
598
+ * creation.
599
+ *
600
+ * Units: spacings in Snaptrude units; `angle` in degrees (CCW about +Y,
601
+ * default 0). Without `center` the grid is centred on the current viewport
602
+ * (the native tool's behavior) — pass `center` for deterministic placement.
603
+ *
604
+ * @param linesX - Line count of the first family (integer ≥ 1)
605
+ * @param linesY - Line count of the second family (integer ≥ 1)
606
+ * @param spacingX - First-family spacing (Snaptrude units, > 0)
607
+ * @param spacingY - Second-family spacing (Snaptrude units, > 0)
608
+ * @param options - `angle`, `center`, and {@linkcode PluginGridStyleOptions}
609
+ * @returns the created grid group's {@linkcode ComponentHandle}
610
+ *
611
+ * @examplePrompt Create a 5 by 8 structural grid with 6 metre spacing
612
+ * @examplePrompt Add a column grid rotated 30 degrees
613
+ * @examplePrompt Set up a structural grid at the site origin
614
+ *
615
+ * # Example
616
+ * ```ts
617
+ * const centre = await snaptrude.core.math.vec3.new(0, 0, 0)
618
+ * const grid = await snaptrude.design.create.grid(5, 8, 6, 6, { center: centre })
619
+ * ```
620
+ */
621
+ abstract grid(linesX: number, linesY: number, spacingX: number, spacingY: number, options?: {
622
+ angle?: number;
623
+ center?: Vec3Handle;
624
+ } & PluginGridStyleOptions): PluginApiReturn<ComponentHandle>;
625
+ /**
626
+ * Create a **structural grid from a single curve** — one grid group holding
627
+ * one wing with one line (the draw tool's output). The curve may be a line
628
+ * or an arc; circles are rejected with `VALIDATION`. Undoable.
629
+ *
630
+ * @param curve - The grid line's geometry ({@linkcode CurveHandle}, world space)
631
+ * @param options - `tag` (defaults to the draw tool's next tag) and
632
+ * {@linkcode PluginGridStyleOptions}
633
+ * @returns the created grid group's {@linkcode ComponentHandle}
634
+ *
635
+ * @examplePrompt Draw a grid line from A to B
636
+ * @examplePrompt Add a curved grid line through these points
637
+ * @examplePrompt Create grid line "C" along this wall
638
+ *
639
+ * # Example
640
+ * ```ts
641
+ * const { vec3 } = snaptrude.core.math
642
+ * const from = await vec3.new(0, 0, 0)
643
+ * const to = await vec3.new(30, 0, 0)
644
+ * const curve = await snaptrude.core.geom.create.line(from, to)
645
+ * const grid = await snaptrude.design.create.gridFromCurve(curve, { tag: "A" })
646
+ * ```
647
+ */
648
+ abstract gridFromCurve(curve: CurveHandle, options?: {
649
+ tag?: string;
650
+ } & PluginGridStyleOptions): PluginApiReturn<ComponentHandle>;
651
+ /**
652
+ * Generate **structural grids fitted to mass footprints** — one grid group
653
+ * per footprint cluster, with counts and orientation derived from each
654
+ * footprint's geometry and the given spacings. All created groups commit as
655
+ * ONE undoable unit.
656
+ *
657
+ * Lenient like the native tool: masses without an extractable footprint
658
+ * (no B-rep, degenerate top face) are skipped; throws `VALIDATION` only when
659
+ * NONE of the given masses yields a footprint.
660
+ *
661
+ * @param masses - Masses whose footprints seat the grids
662
+ * @param spacingX - First-family spacing (Snaptrude units, > 0)
663
+ * @param spacingY - Second-family spacing (Snaptrude units, > 0)
664
+ * @param options - {@linkcode PluginGridStyleOptions}
665
+ * @returns the created grid groups' {@linkcode ComponentHandle}`[]`
666
+ *
667
+ * @examplePrompt Generate grids for the selected masses
668
+ * @examplePrompt Auto-generate a 6m structural grid on this building
669
+ * @examplePrompt Fit column grids to every mass on this storey
670
+ *
671
+ * # Example
672
+ * ```ts
673
+ * const masses = await snaptrude.design.query.listMasses({ storeys: [1] })
674
+ * const grids = await snaptrude.design.create.gridsFromMasses(masses, 6, 6)
675
+ * ```
676
+ */
677
+ abstract gridsFromMasses(masses: ComponentHandle[], spacingX: number, spacingY: number, options?: PluginGridStyleOptions): PluginApiReturn<ComponentHandle[]>;
678
+ /**
679
+ * Create **columns at every grid-line intersection** of the given grid
680
+ * groups, sized `width` × `depth` and oriented to the grid axes, on the
681
+ * grids' storey. All columns commit as ONE undoable unit.
682
+ *
683
+ * @param grids - Grid groups whose intersections seat the columns
684
+ * @param width - Column width (Snaptrude units, > 0)
685
+ * @param depth - Column depth (Snaptrude units, > 0)
686
+ * @returns the created columns' {@linkcode ComponentHandle}`[]`
687
+ * @throws `VALIDATION` when an id does not resolve to a grid group;
688
+ * `OPERATION_FAILED` when the grids have no line intersections
689
+ *
690
+ * @examplePrompt Generate columns on this grid
691
+ * @examplePrompt Place 450mm square columns at every grid intersection
692
+ *
693
+ * # Example
694
+ * ```ts
695
+ * const grids = await snaptrude.design.query.listGrids()
696
+ * const columns = await snaptrude.design.create.columnsFromGrids(grids, 0.45, 0.45)
697
+ * ```
698
+ */
699
+ abstract columnsFromGrids(grids: ComponentHandle[], width: number, depth: number): PluginApiReturn<ComponentHandle[]>;
429
700
  /**
430
701
  * Place a **furniture** item from the project library at a world position.
431
702
  *
@@ -444,15 +715,19 @@ export declare abstract class PluginDesignCreateApi {
444
715
  * `position.y` (the same surface-flush contract as interactive drag-drop) —
445
716
  * pass the floor/storey elevation to stand furniture on it; never add half
446
717
  * the item's height yourself.
447
- * @param options - Optional placement options: `label` — instance name
448
- * (default auto `${name}Ins${n}`); `createNewSourceMesh` — emit a
449
- * source-mesh creation command (default `true`)
718
+ * @param options - Optional placement options: `label` — instance name and
719
+ * readable label (`design.query.getLabel`; default auto `${name}Ins${n}`);
720
+ * `createNewSourceMesh` — legacy flag, kept for compatibility. The host owns
721
+ * source-mesh persistence: a catalog source is recorded exactly once, by the
722
+ * first placement that brings it in, and this flag cannot skip that record.
450
723
  * @param angleInDegrees - Optional signed rotation about the vertical axis, in
451
724
  * degrees (same convention as {@linkcode PluginDesignTransformApi.rotate}).
452
725
  * Applied at creation time so it is part of the placement's single undo entry.
453
726
  * Default: the item's own (unrotated) orientation.
454
727
  * @returns the {@linkcode ComponentHandle} of the placed furniture instance
455
- * @throws if the catalog id is unknown, the source mesh fails to load, or placement fails
728
+ * @throws if the catalog id is unknown, the source mesh fails to load, or placement fails;
729
+ * `PRECONDITION_FAILED` (`details.engineCode: "TOOL_ACTIVE"`) while the interactive
730
+ * furniture tool is active — finish or cancel it first
456
731
  *
457
732
  * @examplePrompt Place a chair from the library at this spot
458
733
  * @examplePrompt Add a sofa from the furniture catalog to the living room
@@ -476,33 +751,76 @@ export declare abstract class PluginDesignCreateApi {
476
751
  * 90,
477
752
  * )
478
753
  * ```
754
+ *
755
+ * @performance For MORE THAN ONE item, call `design.create.furnitureItems(items[])` —
756
+ * one host round-trip and ONE undo entry, and a catalog source shared by several
757
+ * items is fetched once. Looping this single-item creator is N round-trips.
479
758
  */
480
759
  abstract furniture(catalogId: string, position: Vec3Handle, options?: {
481
760
  label?: string;
482
761
  createNewSourceMesh?: boolean;
483
762
  }, angleInDegrees?: number): PluginApiReturn<ComponentHandle>;
484
763
  /**
485
- * Place a **door** from the catalog into a host wall.
764
+ * Place **many furniture items** in one undoable operation (bulk plural of
765
+ * {@linkcode furniture}). Each item names a catalog id and an absolute world
766
+ * position (`position.y` is the REST elevation — the same grounding contract
767
+ * as the singular creator), with optional label and rotation. A catalog
768
+ * source shared by several items is fetched and recorded once for the whole
769
+ * batch, so the host — not the caller — owns source persistence (there is no
770
+ * per-item `createNewSourceMesh`). Validate-all-or-throw; one command.
771
+ *
772
+ * @param items - One {@linkcode PluginCreateFurnitureItem} per instance to
773
+ * place (≥1, ≤1000)
774
+ * @returns the placed instances as {@linkcode ComponentHandle}`[]`, in input order
775
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
776
+ * 1000 items); `HANDLE_INVALID` if a `position` handle is unknown or
777
+ * released; `PRECONDITION_FAILED` if a catalog id is unknown, a furniture
778
+ * tool is active, or a parametric group is active (exit it first, or place
779
+ * items one at a time with `furniture`); `OPERATION_FAILED` if a source
780
+ * mesh fails to load or placement fails (nothing is created —
781
+ * `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the plugin may not write.
782
+ *
783
+ * @examplePrompt Place all the desks for this office at once
784
+ * @examplePrompt Furnish every bedroom in one operation
785
+ * @examplePrompt Bulk place these chairs around the table
786
+ * @examplePrompt Add the whole furniture layout in a single undo step
787
+ * @examplePrompt Drop twenty copies of this chair at these positions
788
+ *
789
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
790
+ * entry, and each distinct catalog source loads once. Always prefer this over
791
+ * calling `design.create.furniture` in a loop: build the full `items[]` array
792
+ * first (all positions and angles up front), then make one call.
793
+ *
794
+ * # Example
795
+ * ```ts
796
+ * const v = snaptrude.core.math.vec3
797
+ * const [chair] = await snaptrude.design.furniture.listCatalog()
798
+ * const placed = await snaptrude.design.create.furnitureItems([
799
+ * { catalogId: chair.id, position: await v.new(3, 0, 5), label: "Chair-01" },
800
+ * { catalogId: chair.id, position: await v.new(4, 0, 5), angleInDegrees: 90 },
801
+ * { catalogId: chair.id, position: await v.new(5, 0, 5), angleInDegrees: 180 },
802
+ * ])
803
+ * ```
804
+ */
805
+ abstract furnitureItems(items: PluginCreateFurnitureItem[]): PluginApiReturn<ComponentHandle[]>;
806
+ /**
807
+ * Place a parametric **door** family into a host wall.
486
808
  *
487
- * Identified by a **catalog (library) id** — the team object's stable `_id`
488
- * or the general library's `fullName`. Discover ids with
809
+ * Identified by a saved **family definition id**. Discover ids with
489
810
  * {@linkcode PluginDesignDoorsApi.listCatalog}. The world `position` is
490
811
  * projected onto the host wall's face to locate the opening; the wall is
491
812
  * re-cut and the door hosted in a single undo entry. Placement is
492
- * asynchronous (the source mesh is fetched if not cached).
813
+ * asynchronous. Values and host bindings are evaluated before the first cut.
493
814
  *
494
- * @param catalogId - Library id: team `_id` or general `fullName`
815
+ * @param familyId - Hosted door definition ID; legacy mesh catalog IDs are not accepted
495
816
  * @param hostWall - The wall to host the door
496
817
  * @param position - World point projected onto the wall to locate the opening
497
- * @param options - Optional placement options: `label` — instance name
498
- * @param facing - World point selecting which side of the wall the door faces
499
- * (the room it opens into) — the same convention as approaching the wall
500
- * from that side with the cursor in the interactive tool. Any point clearly
501
- * on that side works (e.g. the room's center). Default: the engine picks a
502
- * side (nondeterministic when `position` sits on the wall centerline).
818
+ * @param options - `version` pins the definition. `values` sets authored parameters
819
+ * (numeric lengths in SU, or unit strings). `label` names the instance.
820
+ * `hinge` selects the declared `hand` enum: local -X is left, +X is right.
821
+ * @param facing - World point selecting local +Z; omitted uses the picked face
503
822
  * @returns the {@linkcode ComponentHandle} of the placed door
504
- * @throws if the catalog id is unknown, the host is not a wall, the source
505
- * mesh fails to load, or the projected point falls **outside** the host wall
823
+ * @throws if the family/category/parameters are invalid, or placement or cutting fails
506
824
  *
507
825
  * @examplePrompt Add a door to this wall here
508
826
  * @examplePrompt Place a sliding door on the selected wall
@@ -510,6 +828,7 @@ export declare abstract class PluginDesignCreateApi {
510
828
  * @examplePrompt Insert the entrance door into this wall
511
829
  * @examplePrompt Add a door to the wall and call it Entry-01
512
830
  * @examplePrompt Add a door that opens into the living room
831
+ * @examplePrompt Put a door here hinged on the north jamb
513
832
  *
514
833
  * # Example
515
834
  * ```ts
@@ -529,32 +848,90 @@ export declare abstract class PluginDesignCreateApi {
529
848
  * undefined,
530
849
  * await snaptrude.core.math.vec3.new(3, 0, 9),
531
850
  * )
851
+ * // …and hinged on the jamb nearest a point (here the +x end of the opening):
852
+ * const hingedRight = await snaptrude.design.create.door(
853
+ * entry.id,
854
+ * wall,
855
+ * await snaptrude.core.math.vec3.new(3, 0, 5),
856
+ * { hinge: await snaptrude.core.math.vec3.new(3.5, 0, 5) },
857
+ * await snaptrude.core.math.vec3.new(3, 0, 9),
858
+ * )
532
859
  * ```
860
+ *
861
+ * @performance For MORE THAN ONE door, call `design.create.doors(items[])` — one host
862
+ * round-trip and ONE undo entry, with each host wall re-cut once per opening inside
863
+ * that single call. Looping this single-door creator is N round-trips.
533
864
  */
534
- abstract door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: {
865
+ abstract door(familyId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: {
535
866
  label?: string;
867
+ hinge?: Vec3Handle;
868
+ version?: number;
869
+ values?: Record<string, number | string>;
536
870
  }, facing?: Vec3Handle): PluginApiReturn<ComponentHandle>;
537
871
  /**
538
- * Place a **window** from the catalog into a host wall.
872
+ * Place **many doors** into host walls in one undoable operation (bulk plural
873
+ * of {@linkcode door}). Each item carries its own family id, host wall,
874
+ * world position, and optional `facing`, `label`, `width` and `height` — the
875
+ * same fields as a `"door"` {@linkcode PluginDesignCreateOpeningOptions}.
876
+ * Validate-all-or-throw; one command.
877
+ *
878
+ * The wall keeps its identity. Several items may use the same host.
879
+ * Width and height set named recipe parameters, not mesh scale. The recipe's
880
+ * evaluated hole can include frame allowances. A failed item rolls back the batch.
881
+ *
882
+ * @param items - One {@linkcode PluginCreateDoorItem} per door to place
883
+ * (≥1, ≤1000)
884
+ * @returns the placed doors as {@linkcode ComponentHandle}`[]`, in input order
885
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
886
+ * 1000 items, unknown fields, a non-positive `width`/`height`);
887
+ * `HANDLE_INVALID` if a `position`, `facing` or `hinge` handle is unknown
888
+ * or released; `PRECONDITION_FAILED` if the family cannot be resolved or saved,
889
+ * or a host is locked / is not in the active proposal;
890
+ * `OPERATION_FAILED` if placement, containment, overlap checks or cutting fail
891
+ * (nothing is created — `details.itemIndex` is the failing item);
892
+ * `METHOD_NOT_PERMITTED` if the plugin may not write.
893
+ *
894
+ * @examplePrompt Add doors to all of these walls at once
895
+ * @examplePrompt Place a door in every room in one operation
896
+ * @examplePrompt Bulk add the entrance doors from this schedule
897
+ * @examplePrompt Put three doors on this wall in a single undo step
898
+ * @examplePrompt Add all the doors for this floor plan together
899
+ *
900
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
901
+ * entry. Always prefer this over
902
+ * calling `design.create.door` in a loop: build the full `items[]` array first
903
+ * (all host walls and points up front), then make one call.
539
904
  *
540
- * Identified by a **catalog (library) id** — the team object's stable `_id`
541
- * or the general library's `fullName`. Discover ids with
905
+ * # Example
906
+ * ```ts
907
+ * const v = snaptrude.core.math.vec3
908
+ * const [wall] = await snaptrude.design.query.listWalls({ isSelected: true })
909
+ * const [entry] = await snaptrude.design.doors.listCatalog()
910
+ * const [front, side] = await snaptrude.design.create.doors([
911
+ * { familyId: entry.id, hostWall: wall, position: await v.new(2, 0, 5), label: "D-01" },
912
+ * { familyId: entry.id, hostWall: wall, position: await v.new(6, 0, 5), values: { width: "1200mm" } },
913
+ * ])
914
+ * // The host still resolves after both cuts:
915
+ * const currentWall = await snaptrude.design.query.getHost(front)
916
+ * ```
917
+ */
918
+ abstract doors(items: PluginCreateDoorItem[]): PluginApiReturn<ComponentHandle[]>;
919
+ /**
920
+ * Place a parametric **window** family into a host wall.
921
+ *
922
+ * Identified by a saved **family definition id**. Discover ids with
542
923
  * {@linkcode PluginDesignWindowsApi.listCatalog}. The world `position` is
543
924
  * projected onto the host wall's face to locate the opening; the wall is
544
925
  * re-cut and the window hosted in a single undo entry. Placement is
545
- * asynchronous (the source mesh is fetched if not cached).
926
+ * asynchronous. The sill parameter determines elevation; position Y is ignored.
546
927
  *
547
- * @param catalogId - Library id: team `_id` or general `fullName`
928
+ * @param familyId - Hosted window definition ID; legacy mesh catalog IDs are not accepted
548
929
  * @param hostWall - The wall to host the window
549
930
  * @param position - World point projected onto the wall to locate the opening
550
- * @param options - Optional placement options: `label` — instance name
551
- * @param facing - World point selecting which side of the wall the window
552
- * faces (matters for asymmetric windows, e.g. casement swing) — same
553
- * convention as {@linkcode PluginDesignCreateApi.door}. Default: the engine
554
- * picks a side (nondeterministic when `position` sits on the centerline).
931
+ * @param options - `version`, `values`, `label`, and parameter-driven `hinge`, as for door
932
+ * @param facing - World point selecting local +Z; omitted uses the picked face
555
933
  * @returns the {@linkcode ComponentHandle} of the placed window
556
- * @throws if the catalog id is unknown, the host is not a wall, the source
557
- * mesh fails to load, or the projected point falls **outside** the host wall
934
+ * @throws if the family/category/parameters are invalid, or placement or cutting fails
558
935
  *
559
936
  * @examplePrompt Add a window to this wall here
560
937
  * @examplePrompt Place a casement window on the selected wall
@@ -574,35 +951,227 @@ export declare abstract class PluginDesignCreateApi {
574
951
  * { label: "Win-01" },
575
952
  * )
576
953
  * ```
954
+ *
955
+ * @performance For MORE THAN ONE window, call `design.create.windows(items[])` — one
956
+ * host round-trip and ONE undo entry, with each host wall re-cut once per opening
957
+ * inside that single call. Looping this single-window creator is N round-trips.
577
958
  */
578
- abstract window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: {
959
+ abstract window(familyId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: {
579
960
  label?: string;
961
+ hinge?: Vec3Handle;
962
+ version?: number;
963
+ values?: Record<string, number | string>;
580
964
  }, facing?: Vec3Handle): PluginApiReturn<ComponentHandle>;
581
965
  /**
582
- * Place a catalog **door or window** into a host wall with optional size overrides.
966
+ * Place **many windows** into host walls in one undoable operation (bulk
967
+ * plural of {@linkcode window}). Each item carries its own family id, host
968
+ * wall, world position, and optional `facing`, `label`, `width`, `height` and
969
+ * `sillHeight` — the same fields as a `"window"`
970
+ * {@linkcode PluginDesignCreateOpeningOptions}. `sillHeight` is measured from
971
+ * the host wall base to the BOTTOM of the window. Validate-all-or-throw; one
972
+ * command.
973
+ *
974
+ * Hosts keep their identity. Width, height and sillHeight set the declared
975
+ * width, height and sill parameters before the first cut. No mesh scaling occurs.
976
+ *
977
+ * @param items - One {@linkcode PluginCreateWindowItem} per window to place
978
+ * (≥1, ≤1000)
979
+ * @returns the placed windows as {@linkcode ComponentHandle}`[]`, in input order
980
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
981
+ * 1000 items, unknown fields, a non-positive `width`/`height`, a negative
982
+ * `sillHeight`); `HANDLE_INVALID` if a `position`, `facing` or `hinge`
983
+ * handle is unknown or released; `PRECONDITION_FAILED` if the family cannot be
984
+ * resolved or saved, or a host is locked / is not in the active proposal;
985
+ * `OPERATION_FAILED` if placement, containment, overlap checks or cutting fail
986
+ * (nothing is created — `details.itemIndex` is the failing item);
987
+ * `METHOD_NOT_PERMITTED` if the plugin may not write.
988
+ *
989
+ * @examplePrompt Add windows along this whole facade at once
990
+ * @examplePrompt Place a window in every bedroom in one operation
991
+ * @examplePrompt Bulk add the windows from this schedule
992
+ * @examplePrompt Put four windows on this wall in a single undo step
993
+ * @examplePrompt Add all the windows with a 0.9m sill height together
994
+ *
995
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
996
+ * entry. Always prefer this over
997
+ * calling `design.create.window` in a loop: build the full `items[]` array first
998
+ * (all host walls and points up front), then make one call.
999
+ *
1000
+ * # Example
1001
+ * ```ts
1002
+ * const v = snaptrude.core.math.vec3
1003
+ * const [wall] = await snaptrude.design.query.listWalls({ isSelected: true })
1004
+ * const [casement] = await snaptrude.design.windows.listCatalog()
1005
+ * const placed = await snaptrude.design.create.windows([
1006
+ * { familyId: casement.id, hostWall: wall, position: await v.new(2, 0, 5), values: { sill: "900mm" } },
1007
+ * { familyId: casement.id, hostWall: wall, position: await v.new(5, 0, 5), values: { sill: "900mm" } },
1008
+ * ])
1009
+ * const currentWall = await snaptrude.design.query.getHost(placed[0])
1010
+ * ```
1011
+ */
1012
+ abstract windows(items: PluginCreateWindowItem[]): PluginApiReturn<ComponentHandle[]>;
1013
+ /**
1014
+ * Cut a **void** — a hole, opening or shaft — through an existing FLAT slab,
1015
+ * floor, roof or ceiling. The void is a selectable child object of its host
1016
+ * (the "Void" of the Draw Void tool). It always cuts the full host thickness.
1017
+ * It can be moved with `design.transform.move` (a move that would leave the
1018
+ * host is shortened without a report) and removed with
1019
+ * `design.delete.entities`; to resize, delete it and cut a new one
1020
+ * (`design.update.space` refuses a void).
1021
+ *
1022
+ * Give the outline **in plan** (all points at one height): its height is
1023
+ * ignored, and it is dropped straight onto the host's top face, so one outline
1024
+ * works on every storey. Keep it at least 25.4 mm (0.1 SU) inside the host
1025
+ * edge and away from other voids; merge overlapping holes into one outline.
1026
+ * Straight segments and arcs only (no splines).
1027
+ *
1028
+ * **A room has a floor finish AND a structural slab that overlap in plan; a
1029
+ * void in one does not cut the other, so a through-opening needs one void in
1030
+ * each.**
1031
+ *
1032
+ * `getEntityType` reports a void as `"void"`. Use `design.query.listVoids`
1033
+ * or `listByType("void")`; `listMasses` excludes voids. `getHost` and
1034
+ * `listChildren(host)` expose the host relationship, including after a copy.
1035
+ * Authored parametric families with a cut relationship keep their family
1036
+ * identity; discover those through family queries instead.
1037
+ *
1038
+ * Call it as `snaptrude.design.create.void(...)`; `void` is a reserved word and
1039
+ * cannot be destructured. Voids in walls, on sloped, generated or multi-plane
1040
+ * roofs, and on instanced hosts are not available yet; for a door or window
1041
+ * use `design.create.door` / `window`. To make a NEW slab that already has a
1042
+ * fixed hole, pass a contour with holes to `design.create.slab`; that hole is
1043
+ * part of the footprint, not an object. For a contour's outer loop, pass
1044
+ * `core.geom.query.contour.getOuterProfile(contour)`.
1045
+ *
1046
+ * # Example
1047
+ * ```ts
1048
+ * const m = 1000 / 254 // metres → Snaptrude units (SU)
1049
+ * const [slab] = await snaptrude.design.query.listByType("slab", { isSelected: true })
1050
+ * const center = await snaptrude.core.math.vec3.new(10 * m, 0, 5 * m) // plan point; y is ignored
1051
+ * const outline = await snaptrude.core.geom.create.profileRect(2 * m, 2 * m, center) // 2 m x 2 m
1052
+ * const hole = await snaptrude.design.create.void(slab, outline)
1053
+ * ```
1054
+ *
1055
+ * A round hole is two arcs (a circle handle is not a profile):
1056
+ * ```ts
1057
+ * const m = 1000 / 254
1058
+ * const { vec3 } = snaptrude.core.math
1059
+ * const g = snaptrude.core.geom.create
1060
+ * const r = 0.5 * m // 1 m diameter
1061
+ * const centre = await vec3.new(10 * m, 0, 5 * m)
1062
+ * const axis = await vec3.new(0, -1, 0)
1063
+ * const east = await vec3.new(10 * m + r, 0, 5 * m)
1064
+ * const west = await vec3.new(10 * m - r, 0, 5 * m)
1065
+ * const round = await g.profileFromCurves([await g.arc(east, west, centre, axis), await g.arc(west, east, centre, axis)])
1066
+ * await snaptrude.design.create.void(slab, round) // never destructure `void`
1067
+ * ```
1068
+ *
1069
+ * @param host - The slab, floor, roof or ceiling to cut through
1070
+ * @param outline - Closed, flat plan outline (world SU); its height is ignored
1071
+ * @returns the {@linkcode ComponentHandle} of the new void
1072
+ * @throws `VALIDATION` if the outline is open, crosses itself, is not flat or
1073
+ * has a spline, or the arguments are the wrong handle kinds or swapped;
1074
+ * `HANDLE_INVALID` if a handle is unknown or released or the host was
1075
+ * deleted; `HANDLE_STALE` if the host was rebuilt (re-query it);
1076
+ * `PRECONDITION_FAILED` if the
1077
+ * host is a wall or not a slab/floor/roof/ceiling, is sloped, instanced, in
1078
+ * another building, locked, outside the active proposal, a generated roof or
1079
+ * not a single plate, or there is no active structure (`engineCode`
1080
+ * `NO_ACTIVE_STRUCTURE`); `OPERATION_FAILED` with `engineCode`
1081
+ * `VOID_DOES_NOT_FIT` when the outline crosses the host edge, overlaps a void
1082
+ * or hole, is closer than 25.4 mm to either, or the fit could not be checked,
1083
+ * or another `engineCode` when the cut failed (nothing is created, except
1084
+ * `PUBLISH_FAILED` with a hint that the voids are in the scene: undo, then
1085
+ * retry); `METHOD_NOT_PERMITTED` if the plugin may not write.
1086
+ *
1087
+ * @examplePrompt Cut a hole in this slab
1088
+ * @examplePrompt Add a 1.2m by 2.4m stair opening in the first-floor slab
1089
+ * @examplePrompt Make a 600 x 600 service penetration in the floor for the riser
1090
+ * @examplePrompt Put a skylight opening through the roof
1091
+ * @examplePrompt Cut a round 1m duct hole in the slab
1092
+ * @examplePrompt Make a cut-out in the ceiling for the light well
1093
+ * @examplePrompt Add a double-height atrium void in the level 2 floor
1094
+ *
1095
+ * @performance Single-void creator. For MORE THAN ONE void, call
1096
+ * `design.create.voids(items[])`: one host round-trip, ONE undo entry, one cut
1097
+ * per host.
1098
+ */
1099
+ abstract void(host: ComponentHandle, outline: ProfileHandle): PluginApiReturn<ComponentHandle>;
1100
+ /**
1101
+ * Cut **many voids** (holes, openings, shafts) through slabs, floors, roofs
1102
+ * and ceilings in one undoable operation (bulk plural of {@linkcode void}).
1103
+ * Items may share a host or use different hosts — one shaft outline on every
1104
+ * storey's slab AND floor is one call. Validate-all-or-throw: one item whose
1105
+ * host does not contain the outline rejects the whole batch, so pass only the
1106
+ * hosts that contain it; `details.itemIndex` names the failing item (for two
1107
+ * overlapping items of the batch, the earlier one). At most 50 voids per host
1108
+ * and 200 in all per call. Same outline rules as {@linkcode void}: plan outline, 25.4 mm
1109
+ * (0.1 SU) clearance, floor AND slab are separate hosts. Call it as
1110
+ * `snaptrude.design.create.voids(...)`.
1111
+ *
1112
+ * # Example
1113
+ * ```ts
1114
+ * const m = 1000 / 254
1115
+ * // The user selects the slabs AND floors the shaft passes through; every one must contain the outline.
1116
+ * const hosts = [
1117
+ * ...(await snaptrude.design.query.listByType("slab", { isSelected: true })),
1118
+ * ...(await snaptrude.design.query.listByType("floor", { isSelected: true })),
1119
+ * ]
1120
+ * const centre = await snaptrude.core.math.vec3.new(12 * m, 0, -6 * m)
1121
+ * const shaft = await snaptrude.core.geom.create.profileRect(2 * m, 2 * m, centre)
1122
+ * const holes = await snaptrude.design.create.voids(hosts.map((host) => ({ host, outline: shaft })))
1123
+ * ```
1124
+ *
1125
+ * @param items - One {@linkcode PluginCreateVoidItem} per void (≥1, ≤200; ≤50 per host)
1126
+ * @returns the new voids as {@linkcode ComponentHandle}`[]`, in input order
1127
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
1128
+ * 1000 items, unknown fields), an outline is invalid (as for
1129
+ * {@linkcode void}), more than 50 items share one host, or there are more
1130
+ * than 200 items; plus every code {@linkcode void} throws, each with
1131
+ * `details.itemIndex`. Nothing is created on any failure, except
1132
+ * `PUBLISH_FAILED` (as for {@linkcode void}).
1133
+ *
1134
+ * @examplePrompt Cut a lift shaft through every floor slab of the core
1135
+ * @examplePrompt Cut a 2m x 2m shaft through all the slabs at this location
1136
+ * @examplePrompt Make stair openings in all the floors above the staircases
1137
+ * @examplePrompt Make holes in the roof for these three skylights
1138
+ * @examplePrompt Cut openings in each storey's slab matching this outline
1139
+ * @examplePrompt Punch the same riser penetration through every floor at once
1140
+ *
1141
+ * @performance ONE host round-trip, ONE undo entry, ONE cut per host. Never call
1142
+ * `void` in a loop. Runs synchronously on the main thread: 50 voids on one
1143
+ * host take about 1 s, and the time grows with the number of hosts (caps:
1144
+ * 50 per host, 200 per call).
1145
+ */
1146
+ abstract voids(items: PluginCreateVoidItem[]): PluginApiReturn<ComponentHandle[]>;
1147
+ /**
1148
+ * Place a parametric **door or window** into a host wall with parameter overrides.
583
1149
  *
584
1150
  * The world `position` is projected onto the host wall to locate the opening.
585
1151
  * All supplied dimensions use Snaptrude engine units. Window `sillHeight` is
586
1152
  * measured from the host wall base to the bottom of the window, not to
587
1153
  * its center. Placement is asynchronous and committed as one undoable creation.
588
1154
  *
589
- * @param options - Opening kind, catalog and host references, placement, and
590
- * optional facing, label, and dimensions
1155
+ * Wall only. For a hole in a slab, floor or roof use `design.create.void`.
1156
+ *
1157
+ * @param options - Opening kind, family and host references, placement, and
1158
+ * optional facing (swing side), hinge (hinged jamb), label, and dimensions
591
1159
  * @returns the {@linkcode ComponentHandle} of the placed door or window
592
- * @throws if the options are invalid, the catalog id is unknown, the host is
1160
+ * @throws if the options are invalid, the family id is unknown, the host is
593
1161
  * not a wall, loading fails, or the opening cannot be placed on the host
594
1162
  *
595
1163
  * @examplePrompt Add a 1m wide door to this wall here
596
1164
  * @examplePrompt Place a window with a 0.9m sill height on the selected wall
597
1165
  *
598
- * @performance Single-opening creator — use it for one hosted opening. A plural
599
- * API is intentionally unavailable until host placement can be atomic.
1166
+ * @performance Single-opening creator — use it for one hosted opening. For MORE
1167
+ * THAN ONE, call `design.create.doors(items[])` / `design.create.windows(items[])`:
1168
+ * the same per-item fields, one host round-trip, ONE undo entry.
600
1169
  *
601
1170
  * # Example
602
1171
  * ```ts
603
1172
  * const opening = await snaptrude.design.create.opening({
604
1173
  * kind: "window",
605
- * catalogId: windowType.id,
1174
+ * familyId: windowType.id,
606
1175
  * hostWall: wall,
607
1176
  * position: await snaptrude.core.math.vec3.new(3, 0, 5),
608
1177
  * width: 1.2,
@@ -778,6 +1347,32 @@ export declare abstract class PluginDesignCreateApi {
778
1347
  * ```
779
1348
  */
780
1349
  abstract buildableEnvelope(sitePolygon: PluginBuildableEnvelopePolygonVertex[], lengthUnit: "ft" | "m", setbacks: PluginBuildableEnvelopeSetbackTier[], verticalCap: PluginBuildableEnvelopeVerticalCap, floorToFloor: number, farRatio?: number, lotCoverageMaxPct?: number): PluginApiReturn<PluginBuildableEnvelopeCreateResult>;
1350
+ /**
1351
+ * Create a default buildable envelope for an existing site — the same as the
1352
+ * right panel's "Create Buildable Envelope" button. Front, side and rear
1353
+ * distances are seeded from Site Analysis or the Program sheet, with a 10 ft
1354
+ * fallback, and the envelope is linked to the site. Call it only after the
1355
+ * user agrees (for example when `design.update.siteEdge` throws
1356
+ * `NO_BUILDABLE_ENVELOPE`).
1357
+ *
1358
+ * @param siteId - Site component id, from `program.site.listEdges()`.
1359
+ * @returns A {@linkcode PluginDesignCreateBuildableEnvelopeFromSiteResult}
1360
+ * with the `buildableEnvelopeId` of the created envelope.
1361
+ * @throws `HANDLE_INVALID` for an unknown `siteId`. `PRECONDITION_FAILED`
1362
+ * (`details.reason: "SITE_HAS_ENVELOPE"`) when the site already has an
1363
+ * envelope.
1364
+ *
1365
+ * @examplePrompt Create a buildable envelope for this site with default setbacks
1366
+ * @examplePrompt Add the zoning envelope to my site
1367
+ *
1368
+ * # Example
1369
+ * ```ts
1370
+ * const [{ siteId }] = (await snaptrude.program.site.listEdges()).sites
1371
+ * const { buildableEnvelopeId } =
1372
+ * await snaptrude.design.create.buildableEnvelopeFromSite(siteId)
1373
+ * ```
1374
+ */
1375
+ abstract buildableEnvelopeFromSite(siteId: string): PluginApiReturn<PluginDesignCreateBuildableEnvelopeFromSiteResult>;
781
1376
  }
782
1377
  /**
783
1378
  * Line style of a reference line (mirrors the engine `ReferenceLineMode` verbatim).
@@ -880,11 +1475,11 @@ export declare const PluginDesignCreateSpaceArgs: z.ZodObject<{
880
1475
  Parking: "Parking";
881
1476
  }>>;
882
1477
  massType: z.ZodOptional<z.ZodEnum<{
1478
+ Furniture: "Furniture";
883
1479
  Room: "Room";
884
1480
  Plinth: "Plinth";
885
1481
  Void: "Void";
886
1482
  Pergola: "Pergola";
887
- Furniture: "Furniture";
888
1483
  "Facade element": "Facade element";
889
1484
  "Generic mass": "Generic mass";
890
1485
  Department: "Department";
@@ -919,11 +1514,11 @@ export declare const PluginDesignCreateMassArgs: z.ZodObject<{
919
1514
  label: z.ZodOptional<z.ZodString>;
920
1515
  position: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
921
1516
  massType: z.ZodOptional<z.ZodEnum<{
1517
+ Furniture: "Furniture";
922
1518
  Room: "Room";
923
1519
  Plinth: "Plinth";
924
1520
  Void: "Void";
925
1521
  Pergola: "Pergola";
926
- Furniture: "Furniture";
927
1522
  "Facade element": "Facade element";
928
1523
  "Generic mass": "Generic mass";
929
1524
  Department: "Department";
@@ -1055,15 +1650,24 @@ export type PluginDesignCreateBeamArgs = z.infer<typeof PluginDesignCreateBeamAr
1055
1650
  * | `profile` | {@linkcode ProfileHandle} | Ordered curve chain (wall centerlines) |
1056
1651
  * | `height` | `number`? | Wall height (default engine default) |
1057
1652
  * | `thickness` | `number`? | Wall thickness (default: `wallType`'s total layer thickness when given, else engine default) |
1058
- * | `wallType` | `string`? | Wall type name from `design.types.list("wall")` — layers/material/thickness defaults (default generic) |
1653
+ * | `wallType` | {@linkcode PluginWallType}? | Legacy name/id or exact native `{ id, version }` pin from `design.types.list("wall")` (default generic) |
1059
1654
  * | `storey` | `number`? | Target storey (integer, must exist) — walls assigned + lifted to its base in the same undo entry (default: geometry-derived) |
1655
+ * | `topProfiles` | ({@linkcode PluginWallTopProfile} \| `null`)[]? | Top edge per curve (same order); `null`/missing = flat at `height`. Straight curves only |
1060
1656
  */
1061
1657
  export declare const PluginDesignCreateWallsArgs: z.ZodObject<{
1062
1658
  profile: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"profile">, string>>;
1063
1659
  height: z.ZodOptional<z.ZodNumber>;
1064
1660
  thickness: z.ZodOptional<z.ZodNumber>;
1065
- wallType: z.ZodOptional<z.ZodString>;
1661
+ wallType: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
1662
+ id: z.ZodString;
1663
+ version: z.ZodNumber;
1664
+ }, z.core.$strip>]>>;
1066
1665
  storey: z.ZodOptional<z.ZodNumber>;
1666
+ topProfiles: z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodArray<z.ZodObject<{
1667
+ along: z.ZodNumber;
1668
+ height: z.ZodNumber;
1669
+ }, z.core.$strip>>>>>;
1670
+ values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>>>;
1067
1671
  }, z.core.$strip>;
1068
1672
  export type PluginDesignCreateWallsArgs = z.infer<typeof PluginDesignCreateWallsArgs>;
1069
1673
  /**
@@ -1118,7 +1722,7 @@ export type PluginDesignCreateStaircaseArgs = z.infer<typeof PluginDesignCreateS
1118
1722
  * | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
1119
1723
  * | `position` | {@linkcode Vec3Handle} | Absolute world placement point |
1120
1724
  * | `label` | `string`? | Instance name (default auto `${name}Ins${n}`) |
1121
- * | `createNewSourceMesh` | `boolean`? | Emit a source-mesh creation command (default `true`) |
1725
+ * | `createNewSourceMesh` | `boolean`? | Legacy, kept for compatibility; the host records a catalog source exactly once and this flag cannot skip it |
1122
1726
  * | `angleInDegrees` | `number`? | Rotation about the vertical axis, in degrees (default unrotated) |
1123
1727
  */
1124
1728
  export declare const PluginDesignCreateFurnitureArgs: z.ZodObject<{
@@ -1134,18 +1738,26 @@ export type PluginDesignCreateFurnitureArgs = z.infer<typeof PluginDesignCreateF
1134
1738
  *
1135
1739
  * | Property | Type | Description |
1136
1740
  * |---|---|---|
1137
- * | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
1741
+ * | `familyId` | `string` | Hosted door family definition ID |
1742
+ * | `version` | `number`? | Exact version; newest known by default |
1743
+ * | `values` | `Record<string, number \| string>`? | Parameters; numeric lengths use SU |
1138
1744
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
1139
1745
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
1140
1746
  * | `label` | `string`? | Instance name (optional) |
1141
- * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door faces (default engine-chosen) |
1747
+ * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door swings open to (default engine-chosen) |
1748
+ * | `hinge` | {@linkcode Vec3Handle}? | World point near the hinged jamb; requires hand control |
1142
1749
  */
1143
1750
  export declare const PluginDesignCreateDoorArgs: z.ZodObject<{
1144
- catalogId: z.ZodString;
1751
+ familyId: z.ZodString;
1752
+ version: z.ZodOptional<z.ZodNumber>;
1753
+ values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
1145
1754
  hostWall: z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>;
1146
1755
  position: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>;
1147
- label: z.ZodOptional<z.ZodString>;
1148
1756
  facing: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1757
+ hinge: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1758
+ label: z.ZodOptional<z.ZodString>;
1759
+ width: z.ZodOptional<z.ZodNumber>;
1760
+ height: z.ZodOptional<z.ZodNumber>;
1149
1761
  }, z.core.$strip>;
1150
1762
  export type PluginDesignCreateDoorArgs = z.infer<typeof PluginDesignCreateDoorArgs>;
1151
1763
  /**
@@ -1153,18 +1765,26 @@ export type PluginDesignCreateDoorArgs = z.infer<typeof PluginDesignCreateDoorAr
1153
1765
  *
1154
1766
  * | Property | Type | Description |
1155
1767
  * |---|---|---|
1156
- * | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
1768
+ * | `familyId` | `string` | Hosted window family definition ID |
1769
+ * | `version` | `number`? | Exact version; newest known by default |
1770
+ * | `values` | `Record<string, number \| string>`? | Parameters; numeric lengths use SU |
1157
1771
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
1158
1772
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
1159
1773
  * | `label` | `string`? | Instance name (optional) |
1160
- * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window faces (default engine-chosen) |
1774
+ * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window opens to (default engine-chosen) |
1775
+ * | `hinge` | {@linkcode Vec3Handle}? | World point near the hinged jamb; requires hand control |
1161
1776
  */
1162
1777
  export declare const PluginDesignCreateWindowArgs: z.ZodObject<{
1163
- catalogId: z.ZodString;
1778
+ familyId: z.ZodString;
1779
+ version: z.ZodOptional<z.ZodNumber>;
1780
+ values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
1164
1781
  hostWall: z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>;
1165
1782
  position: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>;
1166
- label: z.ZodOptional<z.ZodString>;
1167
1783
  facing: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1784
+ hinge: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1785
+ label: z.ZodOptional<z.ZodString>;
1786
+ width: z.ZodOptional<z.ZodNumber>;
1787
+ height: z.ZodOptional<z.ZodNumber>;
1168
1788
  }, z.core.$strip>;
1169
1789
  export type PluginDesignCreateWindowArgs = z.infer<typeof PluginDesignCreateWindowArgs>;
1170
1790
  /**
@@ -1174,20 +1794,26 @@ export type PluginDesignCreateWindowArgs = z.infer<typeof PluginDesignCreateWind
1174
1794
  * the distance from the host wall base to the bottom of the window.
1175
1795
  */
1176
1796
  export declare const PluginDesignCreateOpeningOptions: z.ZodDiscriminatedUnion<[z.ZodObject<{
1177
- catalogId: z.ZodString;
1797
+ familyId: z.ZodString;
1798
+ version: z.ZodOptional<z.ZodNumber>;
1799
+ values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
1178
1800
  hostWall: z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>;
1179
1801
  position: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>;
1180
1802
  facing: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1803
+ hinge: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1181
1804
  label: z.ZodOptional<z.ZodString>;
1182
1805
  width: z.ZodOptional<z.ZodNumber>;
1183
1806
  height: z.ZodOptional<z.ZodNumber>;
1184
1807
  kind: z.ZodLiteral<"door">;
1185
1808
  }, z.core.$strict>, z.ZodObject<{
1186
1809
  sillHeight: z.ZodOptional<z.ZodNumber>;
1187
- catalogId: z.ZodString;
1810
+ familyId: z.ZodString;
1811
+ version: z.ZodOptional<z.ZodNumber>;
1812
+ values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
1188
1813
  hostWall: z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>;
1189
1814
  position: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>;
1190
1815
  facing: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1816
+ hinge: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1191
1817
  label: z.ZodOptional<z.ZodString>;
1192
1818
  width: z.ZodOptional<z.ZodNumber>;
1193
1819
  height: z.ZodOptional<z.ZodNumber>;
@@ -1248,8 +1874,53 @@ export type PluginSmartLayoutResult = z.infer<typeof PluginSmartLayoutResult>;
1248
1874
  * | `style` | {@linkcode PluginReferenceLineStyle}? | Line style (default `SOLID`) |
1249
1875
  * | `gridTag` | `string`? | Grid tag label (default `"A"`) |
1250
1876
  */
1877
+ /**
1878
+ * Reference-line creation options. styleId selects a project pen/pattern; its
1879
+ * native legacy mirror is saved too. Omitted options preserve tool defaults.
1880
+ */
1881
+ export declare const PluginReferenceLineOptions: z.ZodObject<{
1882
+ styleId: z.ZodOptional<z.ZodEnum<{
1883
+ hidden: "hidden";
1884
+ thin: "thin";
1885
+ medium: "medium";
1886
+ wide: "wide";
1887
+ overhead: "overhead";
1888
+ demolished: "demolished";
1889
+ centerline: "centerline";
1890
+ }>>;
1891
+ color: z.ZodOptional<z.ZodString>;
1892
+ thickness: z.ZodOptional<z.ZodNumber>;
1893
+ style: z.ZodOptional<z.ZodEnum<{
1894
+ SOLID: "SOLID";
1895
+ DASHED: "DASHED";
1896
+ DOT_DASH: "DOT_DASH";
1897
+ }>>;
1898
+ }, z.core.$strict>;
1899
+ export type PluginReferenceLineOptions = z.infer<typeof PluginReferenceLineOptions>;
1900
+ /**
1901
+ * Normalized arguments. The host maps the second positional argument to either
1902
+ * the legacy color field or options; mixing those forms is rejected atomically.
1903
+ */
1251
1904
  export declare const PluginDesignCreateReferenceLinesArgs: z.ZodObject<{
1252
1905
  profile: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"profile">, string>>;
1906
+ options: z.ZodOptional<z.ZodObject<{
1907
+ styleId: z.ZodOptional<z.ZodEnum<{
1908
+ hidden: "hidden";
1909
+ thin: "thin";
1910
+ medium: "medium";
1911
+ wide: "wide";
1912
+ overhead: "overhead";
1913
+ demolished: "demolished";
1914
+ centerline: "centerline";
1915
+ }>>;
1916
+ color: z.ZodOptional<z.ZodString>;
1917
+ thickness: z.ZodOptional<z.ZodNumber>;
1918
+ style: z.ZodOptional<z.ZodEnum<{
1919
+ SOLID: "SOLID";
1920
+ DASHED: "DASHED";
1921
+ DOT_DASH: "DOT_DASH";
1922
+ }>>;
1923
+ }, z.core.$strict>>;
1253
1924
  color: z.ZodOptional<z.ZodString>;
1254
1925
  thickness: z.ZodOptional<z.ZodNumber>;
1255
1926
  style: z.ZodOptional<z.ZodEnum<{
@@ -1258,7 +1929,7 @@ export declare const PluginDesignCreateReferenceLinesArgs: z.ZodObject<{
1258
1929
  DOT_DASH: "DOT_DASH";
1259
1930
  }>>;
1260
1931
  gridTag: z.ZodOptional<z.ZodString>;
1261
- }, z.core.$strip>;
1932
+ }, z.core.$strict>;
1262
1933
  export type PluginDesignCreateReferenceLinesArgs = z.infer<typeof PluginDesignCreateReferenceLinesArgs>;
1263
1934
  /**
1264
1935
  * Copy mode for {@linkcode PluginDesignCreateApi.copy}.
@@ -1326,11 +1997,11 @@ export declare const PluginCreateSpaceItem: z.ZodObject<{
1326
1997
  Parking: "Parking";
1327
1998
  }>>;
1328
1999
  massType: z.ZodOptional<z.ZodEnum<{
2000
+ Furniture: "Furniture";
1329
2001
  Room: "Room";
1330
2002
  Plinth: "Plinth";
1331
2003
  Void: "Void";
1332
2004
  Pergola: "Pergola";
1333
- Furniture: "Furniture";
1334
2005
  "Facade element": "Facade element";
1335
2006
  "Generic mass": "Generic mass";
1336
2007
  Department: "Department";
@@ -1348,4 +2019,7 @@ export declare const PluginCreateSpaceItem: z.ZodObject<{
1348
2019
  storey: z.ZodOptional<z.ZodNumber>;
1349
2020
  }, z.core.$strip>;
1350
2021
  export type PluginCreateSpaceItem = z.infer<typeof PluginCreateSpaceItem>;
2022
+ export * from "./opening-fields";
2023
+ export * from "./bulk-items";
2024
+ export * from "./grids";
1351
2025
  //# sourceMappingURL=index.d.ts.map