@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
@@ -28,14 +28,18 @@ export const PluginSpacePropertyUpdates = z.object({
28
28
  areaClass: PluginAreaClass.optional(),
29
29
  departmentId: PluginDepartmentId.optional(),
30
30
  })
31
- export type PluginSpacePropertyUpdates = z.infer<typeof PluginSpacePropertyUpdates>
31
+ export type PluginSpacePropertyUpdates = z.infer<
32
+ typeof PluginSpacePropertyUpdates
33
+ >
32
34
 
33
35
  /** Geometry replacement for a space — re-extrude a profile. */
34
36
  export const PluginSpaceGeometryUpdate = z.object({
35
37
  profile: ProfileHandle,
36
38
  extrudeHeight: z.number(),
37
39
  })
38
- export type PluginSpaceGeometryUpdate = z.infer<typeof PluginSpaceGeometryUpdate>
40
+ export type PluginSpaceGeometryUpdate = z.infer<
41
+ typeof PluginSpaceGeometryUpdate
42
+ >
39
43
 
40
44
  /** One space to update via {@linkcode PluginDesignUpdateApi.spaces}. */
41
45
  export const PluginUpdateSpaceItem = z.object({
@@ -106,7 +110,9 @@ export const PluginStaircaseParamUpdates = z
106
110
  message:
107
111
  "PluginStaircaseParamUpdates requires at least one field to change",
108
112
  })
109
- export type PluginStaircaseParamUpdates = z.infer<typeof PluginStaircaseParamUpdates>
113
+ export type PluginStaircaseParamUpdates = z.infer<
114
+ typeof PluginStaircaseParamUpdates
115
+ >
110
116
 
111
117
  /**
112
118
  * Arguments for {@linkcode PluginDesignUpdateApi.staircase}.
@@ -120,7 +126,111 @@ export const PluginDesignUpdateStaircaseArgs = z.object({
120
126
  staircases: z.array(ComponentHandle),
121
127
  params: PluginStaircaseParamUpdates,
122
128
  })
123
- export type PluginDesignUpdateStaircaseArgs = z.infer<typeof PluginDesignUpdateStaircaseArgs>
129
+ export type PluginDesignUpdateStaircaseArgs = z.infer<
130
+ typeof PluginDesignUpdateStaircaseArgs
131
+ >
132
+
133
+ /**
134
+ * Sparse edits for a wall (all optional; at least one required). Only the
135
+ * fields you provide change. Dimensions are in **engine units** (the same
136
+ * convention as `design.doors.setWidth`). Consumed by
137
+ * {@linkcode PluginDesignUpdateApi.wall}.
138
+ *
139
+ * | Property | Type | Description |
140
+ * |---|---|---|
141
+ * | `thickness` | `number`? | Wall thickness, engine units (> 0) |
142
+ * | `height` | `number`? | Wall height, engine units (> 0) |
143
+ * | `type` | `string`? | Convert the wall to another wall type — a name (or `wall:`-prefixed id) from `design.types.list("wall")` |
144
+ */
145
+ export const PluginWallUpdates = z
146
+ .object({
147
+ thickness: z.number().positive().optional(),
148
+ height: z.number().positive().optional(),
149
+ type: z.string().trim().min(1).optional(),
150
+ })
151
+ .refine((p) => Object.keys(p).length > 0, {
152
+ message: "PluginWallUpdates requires at least one field to change",
153
+ })
154
+ export type PluginWallUpdates = z.infer<typeof PluginWallUpdates>
155
+
156
+ /**
157
+ * Sparse dimension edits for a slab-family element (slab / floor / roof /
158
+ * ceiling). All values are engine units, the same convention as
159
+ * `design.doors.setWidth`. Consumed by {@linkcode PluginDesignUpdateApi.slab},
160
+ * `floor`, `roof`, and `ceiling`.
161
+ *
162
+ * `overhang` is only available on **slabs and roofs** (the panel's Overhang
163
+ * slider) — floors and ceilings reject it with `PRECONDITION_FAILED`.
164
+ *
165
+ * | Property | Type | Description |
166
+ * |---|---|---|
167
+ * | `thickness` | `number`? | Element thickness, engine units (> 0) |
168
+ * | `overhang` | `number`? | Absolute overhang offset, engine units (slab / roof only) |
169
+ */
170
+ export const PluginSlabUpdates = z
171
+ .object({
172
+ thickness: z.number().positive().optional(),
173
+ overhang: z.number().optional(),
174
+ })
175
+ .refine((p) => Object.keys(p).length > 0, {
176
+ message: "PluginSlabUpdates requires at least one field to change",
177
+ })
178
+ export type PluginSlabUpdates = z.infer<typeof PluginSlabUpdates>
179
+
180
+ /** Arguments for {@linkcode PluginDesignUpdateApi.wall}. */
181
+ export const PluginDesignUpdateWallArgs = z.object({
182
+ component: ComponentHandle,
183
+ updates: PluginWallUpdates,
184
+ })
185
+ export type PluginDesignUpdateWallArgs = z.infer<
186
+ typeof PluginDesignUpdateWallArgs
187
+ >
188
+
189
+ /**
190
+ * Arguments for the slab-family updaters —
191
+ * {@linkcode PluginDesignUpdateApi.slab}, `floor`, `roof`, `ceiling`.
192
+ */
193
+ export const PluginDesignUpdateSlabArgs = z.object({
194
+ component: ComponentHandle,
195
+ updates: PluginSlabUpdates,
196
+ })
197
+ export type PluginDesignUpdateSlabArgs = z.infer<
198
+ typeof PluginDesignUpdateSlabArgs
199
+ >
200
+
201
+ /** Arguments for {@linkcode PluginDesignUpdateApi.setElevation}. */
202
+ export const PluginDesignSetElevationArgs = z.object({
203
+ component: ComponentHandle,
204
+ elevation: z.number(),
205
+ })
206
+ export type PluginDesignSetElevationArgs = z.infer<
207
+ typeof PluginDesignSetElevationArgs
208
+ >
209
+
210
+ /** Arguments for {@linkcode PluginDesignUpdateApi.setBaseOffset}. */
211
+ export const PluginDesignSetBaseOffsetArgs = z.object({
212
+ component: ComponentHandle,
213
+ offset: z.number(),
214
+ })
215
+ export type PluginDesignSetBaseOffsetArgs = z.infer<
216
+ typeof PluginDesignSetBaseOffsetArgs
217
+ >
218
+
219
+ /**
220
+ * Arguments for {@linkcode PluginDesignUpdateApi.setStorey}.
221
+ *
222
+ * | Property | Type | Description |
223
+ * |---|---|---|
224
+ * | `components` | {@linkcode ComponentHandle}`[]` | The components to reassign |
225
+ * | `storey` | `number` | Target integer storey number (`entity.story` convention; must exist) |
226
+ */
227
+ export const PluginDesignSetStoreyArgs = z.object({
228
+ components: z.array(ComponentHandle),
229
+ storey: z.number().int(),
230
+ })
231
+ export type PluginDesignSetStoreyArgs = z.infer<
232
+ typeof PluginDesignSetStoreyArgs
233
+ >
124
234
 
125
235
  /**
126
236
  * `snaptrude.design.update` — edit existing scene entities (properties + geometry).
@@ -169,7 +279,10 @@ export abstract class PluginDesignUpdateApi {
169
279
  * }
170
280
  * ```
171
281
  */
172
- public abstract setLabel(component: ComponentHandle, label: string): PluginApiReturn<boolean>
282
+ public abstract setLabel(
283
+ component: ComponentHandle,
284
+ label: string,
285
+ ): PluginApiReturn<boolean>
173
286
 
174
287
  /**
175
288
  * Update a single space (room) — change its properties (room label, space
@@ -231,7 +344,9 @@ export abstract class PluginDesignUpdateApi {
231
344
  * console.log(results.map((r) => r.spaceId))
232
345
  * ```
233
346
  */
234
- public abstract spaces(items: PluginUpdateSpaceItem[]): PluginApiReturn<PluginSpaceUpdateResult[]>
347
+ public abstract spaces(
348
+ items: PluginUpdateSpaceItem[],
349
+ ): PluginApiReturn<PluginSpaceUpdateResult[]>
235
350
 
236
351
  /**
237
352
  * Update the parameters of one or more staircases — riser, tread, width,
@@ -281,4 +396,285 @@ export abstract class PluginDesignUpdateApi {
281
396
  staircases: ComponentHandle[],
282
397
  params: PluginStaircaseParamUpdates,
283
398
  ): PluginApiReturn<PluginDesignChangeResult>
399
+
400
+ /**
401
+ * Edit a **wall** — its thickness and/or height (the same command the
402
+ * properties panel's Thickness/Height fields drive) and/or its **wall type**
403
+ * (the panel's Wall Types dropdown: converts the wall to another type,
404
+ * rebuilding its layer stack and materials). Sparse: only the fields you
405
+ * provide change. Undoable; the geometry rebuilds and any dimension lines
406
+ * refresh. Stacked-wall companions and hosted fenestration are handled
407
+ * exactly as the panel does.
408
+ *
409
+ * Thickness/height are in **engine units** (the same convention as
410
+ * `design.doors.setWidth`) and must be `> 0`. Shrinking a wall past its
411
+ * openings is rejected by the engine (the wall is skipped with no change).
412
+ * `type` accepts a type name from `design.types.list("wall")` (or its
413
+ * `wall:`-prefixed id); when combined with dimensions, the type conversion
414
+ * is applied first so an explicit thickness/height wins over the type's
415
+ * defaults. Re-applying the wall's current type is a no-op.
416
+ *
417
+ * Throws when the handle is not a wall, when the wall is locked, when the
418
+ * handle is gone/forged, when `type` names an unknown wall type, when the
419
+ * engine rejects the conversion (e.g. a curved wall thinner than the new
420
+ * type's minimum thickness), or when no field is provided.
421
+ *
422
+ * A type conversion (and a thickness edit on a parametric wall) REBUILDS the
423
+ * wall, replacing it with a new component: the input handle is then dead
424
+ * (further calls throw HANDLE_INVALID) and `affected[0]` carries the
425
+ * replacement's handle — use it for any follow-up calls.
426
+ *
427
+ * @param component - The wall to edit
428
+ * @param updates - Sparse {@linkcode PluginWallUpdates} (at least one field)
429
+ * @returns the affected wall — after a rebuild, the REPLACEMENT wall's handle
430
+ *
431
+ * @examplePrompt Make this wall 230mm thick
432
+ * @examplePrompt Set the selected wall's height to 3 metres
433
+ * @examplePrompt Thicken every exterior wall to 300
434
+ * @examplePrompt Change this wall to a Glass Wall
435
+ * @examplePrompt Convert all the partitions on this floor to Brick Wall
436
+ *
437
+ * # Example
438
+ * ```ts
439
+ * // Convert every wall on storey 1 to the first listed wall type
440
+ * const [wallType] = await snaptrude.design.types.list("wall")
441
+ * const walls = await snaptrude.design.query.listWalls({ storeys: [1] })
442
+ * for (const wall of walls) {
443
+ * await snaptrude.design.update.wall(wall, { type: wallType.id })
444
+ * }
445
+ * ```
446
+ */
447
+ public abstract wall(
448
+ component: ComponentHandle,
449
+ updates: PluginWallUpdates,
450
+ ): PluginApiReturn<PluginDesignChangeResult>
451
+
452
+ /**
453
+ * Edit a **slab's** thickness and/or overhang — the same commands the
454
+ * properties panel's Thickness field and Overhang slider drive. Sparse: only
455
+ * the fields you provide change. Undoable; the slab rebuilds and dimension
456
+ * lines refresh. Both values are in **engine units** (the same convention as
457
+ * `design.doors.setWidth`); thickness must be `> 0`, overhang is an absolute
458
+ * offset (negative insets the slab) and re-applying the current overhang is
459
+ * a no-op.
460
+ *
461
+ * Throws when the handle is not a slab, when it is locked, when the handle is
462
+ * gone/forged, when `overhang` is set on a slab that has no overhang (plinth /
463
+ * basement slabs, or overhang disabled), or when no field is provided.
464
+ *
465
+ * @param component - The slab to edit
466
+ * @param updates - Sparse {@linkcode PluginSlabUpdates} (at least one field)
467
+ * @returns the affected slab
468
+ *
469
+ * @examplePrompt Set this slab's thickness to 250mm
470
+ * @examplePrompt Make the floor slab 300 thick
471
+ * @examplePrompt Give this slab a 200 overhang
472
+ * @examplePrompt Remove the overhang on every slab on level 2
473
+ *
474
+ * # Example
475
+ * ```ts
476
+ * const [slab] = await snaptrude.design.query.listSlabs()
477
+ * await snaptrude.design.update.slab(slab, { thickness: 250, overhang: 200 })
478
+ * ```
479
+ */
480
+ public abstract slab(
481
+ component: ComponentHandle,
482
+ updates: PluginSlabUpdates,
483
+ ): PluginApiReturn<PluginDesignChangeResult>
484
+
485
+ /**
486
+ * Edit a **floor's** thickness — the slab-family updater for floors (shares
487
+ * the slab thickness command). Undoable. Thickness is in **engine units**
488
+ * (the `design.doors.setWidth` convention) and must be `> 0`. Floors have no
489
+ * Overhang control, so `overhang` is rejected with `PRECONDITION_FAILED`.
490
+ *
491
+ * Throws when the handle is not a floor, when it is locked, when the handle
492
+ * is gone/forged, when `overhang` is provided, or when no field is provided.
493
+ *
494
+ * @param component - The floor to edit
495
+ * @param updates - {@linkcode PluginSlabUpdates} (a `thickness`)
496
+ * @returns the affected floor
497
+ *
498
+ * @examplePrompt Make this floor 200mm thick
499
+ * @examplePrompt Set every floor to a 250 thickness
500
+ * @examplePrompt Thicken the ground floor slab to 300
501
+ *
502
+ * # Example
503
+ * ```ts
504
+ * const [floor] = await snaptrude.design.query.listFloors()
505
+ * await snaptrude.design.update.floor(floor, { thickness: 200 })
506
+ * ```
507
+ */
508
+ public abstract floor(
509
+ component: ComponentHandle,
510
+ updates: PluginSlabUpdates,
511
+ ): PluginApiReturn<PluginDesignChangeResult>
512
+
513
+ /**
514
+ * Edit a **roof's** thickness and/or overhang — the same commands the roof
515
+ * panel's Thickness field and Overhang slider drive (shares the slab-family
516
+ * machinery). Sparse: only the fields you provide change. Undoable. Both
517
+ * values are in **engine units** (the `design.doors.setWidth` convention);
518
+ * thickness must be `> 0`, overhang is an absolute offset (negative insets
519
+ * the roof) and re-applying the current overhang is a no-op.
520
+ *
521
+ * Throws when the handle is not a roof, when it is locked, when the handle is
522
+ * gone/forged, when `overhang` is set on a roof whose overhang is disabled,
523
+ * or when no field is provided.
524
+ *
525
+ * @param component - The roof to edit
526
+ * @param updates - Sparse {@linkcode PluginSlabUpdates} (at least one field)
527
+ * @returns the affected roof
528
+ *
529
+ * @examplePrompt Make this roof 300mm thick
530
+ * @examplePrompt Set the roof slab thickness to 250
531
+ * @examplePrompt Give the roof a 600 overhang
532
+ * @examplePrompt Pull the roof overhang back to 0
533
+ *
534
+ * # Example
535
+ * ```ts
536
+ * const [roof] = await snaptrude.design.query.listRoofs()
537
+ * await snaptrude.design.update.roof(roof, { overhang: 600 })
538
+ * ```
539
+ */
540
+ public abstract roof(
541
+ component: ComponentHandle,
542
+ updates: PluginSlabUpdates,
543
+ ): PluginApiReturn<PluginDesignChangeResult>
544
+
545
+ /**
546
+ * Edit a **ceiling's** thickness — the slab-family updater for ceilings
547
+ * (shares the slab thickness command). Undoable. Thickness is in **engine
548
+ * units** (the `design.doors.setWidth` convention) and must be `> 0`.
549
+ * Ceilings have no Overhang control, so `overhang` is rejected with
550
+ * `PRECONDITION_FAILED`.
551
+ *
552
+ * Throws when the handle is not a ceiling, when it is locked, when the handle
553
+ * is gone/forged, when `overhang` is provided, or when no field is provided.
554
+ *
555
+ * @param component - The ceiling to edit
556
+ * @param updates - {@linkcode PluginSlabUpdates} (a `thickness`)
557
+ * @returns the affected ceiling
558
+ *
559
+ * @examplePrompt Make this ceiling 150mm thick
560
+ * @examplePrompt Set every ceiling to a 100 thickness
561
+ * @examplePrompt Thicken the ceiling to 200
562
+ *
563
+ * # Example
564
+ * ```ts
565
+ * const [ceiling] = await snaptrude.design.query.listCeilings()
566
+ * await snaptrude.design.update.ceiling(ceiling, { thickness: 150 })
567
+ * ```
568
+ */
569
+ public abstract ceiling(
570
+ component: ComponentHandle,
571
+ updates: PluginSlabUpdates,
572
+ ): PluginApiReturn<PluginDesignChangeResult>
573
+
574
+ /**
575
+ * Set a component's **absolute world elevation** — moves it vertically so its
576
+ * base (the bounding-box bottom, world Y) lands at `elevation`. Composed over
577
+ * the canonical command-backed move machinery, so it is undoable and persisted
578
+ * exactly like dragging the element up or down; per-type invariants (e.g. a
579
+ * staircase's base offset) stay in sync. `elevation` is in **engine units**
580
+ * (the `design.doors.setWidth` convention). Re-applying the current elevation
581
+ * is a no-op.
582
+ *
583
+ * Throws when the component is locked or the handle is gone/forged.
584
+ *
585
+ * @param component - The component to move vertically
586
+ * @param elevation - Target world elevation of the component's base (engine units)
587
+ * @returns the affected component
588
+ *
589
+ * @examplePrompt Set this element's elevation to 3000
590
+ * @examplePrompt Raise this mass so its base sits at 3 metres
591
+ * @examplePrompt Drop the selected slab to elevation 0
592
+ * @examplePrompt Put this staircase's base at 3200
593
+ *
594
+ * # Example
595
+ * ```ts
596
+ * // Sit the roof slab exactly at the top of a 3m storey
597
+ * const [roof] = await snaptrude.design.query.listRoofs()
598
+ * await snaptrude.design.update.setElevation(roof, 3000)
599
+ * ```
600
+ */
601
+ public abstract setElevation(
602
+ component: ComponentHandle,
603
+ elevation: number,
604
+ ): PluginApiReturn<PluginDesignChangeResult>
605
+
606
+ /**
607
+ * Set a component's **base offset** — its vertical distance above its own
608
+ * storey's base level. Moves the component so its base lands at
609
+ * `storeyBase + offset`, composed over the same command-backed move machinery
610
+ * as {@linkcode setElevation} (undoable, persisted, per-type invariants kept
611
+ * in sync). Use this instead of {@linkcode setElevation} when you want an
612
+ * offset relative to the storey rather than an absolute world height.
613
+ * `offset` is in **engine units** (the `design.doors.setWidth` convention);
614
+ * `0` sits the base flush with the storey base. Re-applying the current
615
+ * offset is a no-op.
616
+ *
617
+ * Throws when the component is locked, when it has no storey to offset from,
618
+ * or when the handle is gone/forged.
619
+ *
620
+ * @param component - The component to offset
621
+ * @param offset - Distance of the component's base above its storey base (engine units)
622
+ * @returns the affected component
623
+ *
624
+ * @examplePrompt Lift this element 300 above its floor
625
+ * @examplePrompt Set this staircase's base offset to 0
626
+ * @examplePrompt Raise the selected mass 500 off the storey base
627
+ * @examplePrompt Offset this slab 150 above the floor level
628
+ *
629
+ * # Example
630
+ * ```ts
631
+ * const [stair] = await snaptrude.design.query.listStaircases()
632
+ * await snaptrude.design.update.setBaseOffset(stair, 0)
633
+ * ```
634
+ */
635
+ public abstract setBaseOffset(
636
+ component: ComponentHandle,
637
+ offset: number,
638
+ ): PluginApiReturn<PluginDesignChangeResult>
639
+
640
+ /**
641
+ * Reassign one or more components to another **storey** — the same operation
642
+ * as the properties panel's Story dropdown, and it works across element kinds
643
+ * exactly like the panel (walls, slabs, masses, furniture, staircases, ...).
644
+ * Each component is moved vertically to the target storey's level (per-kind
645
+ * placement rules — e.g. a slab sits at the storey base, a wall on it) and
646
+ * its storey assignment, children, and dimension lines update together as
647
+ * **one undoable operation**.
648
+ *
649
+ * `storey` is an integer storey number in the `entity.story` convention
650
+ * (`1` is the ground storey, `-1` the first basement; `0` does not exist)
651
+ * and **must already exist** in each component's building — this call never
652
+ * creates storeys (use `entity.story.create` first). Components already on
653
+ * the target storey are skipped (no-op) and are not echoed in `affected`.
654
+ *
655
+ * Throws when the target storey does not exist, when any component is
656
+ * locked, or when a handle is gone/forged — all before anything moves
657
+ * (all-or-nothing).
658
+ *
659
+ * @param components - The components to reassign
660
+ * @param storey - Target storey number (integer, `entity.story` convention)
661
+ * @returns the components actually reassigned
662
+ *
663
+ * @examplePrompt Move this sofa to storey 2
664
+ * @examplePrompt Put the selected walls on the first basement level
665
+ * @examplePrompt Send everything on this storey up one level
666
+ * @examplePrompt Reassign these slabs to storey 3
667
+ *
668
+ * # Example
669
+ * ```ts
670
+ * // Move the current selection up to storey 2
671
+ * const selection = await snaptrude.design.selection.get()
672
+ * const { affected } = await snaptrude.design.update.setStorey(selection, 2)
673
+ * console.log("moved", affected.length, "components")
674
+ * ```
675
+ */
676
+ public abstract setStorey(
677
+ components: ComponentHandle[],
678
+ storey: number,
679
+ ): PluginApiReturn<PluginDesignChangeResult>
284
680
  }
@@ -0,0 +1,109 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../types"
3
+ import { ComponentHandle } from "../../handles"
4
+ import { PluginDesignChangeResult } from "./lock"
5
+
6
+ /**
7
+ * `snaptrude.design.visibility.*` — hide, isolate, and reveal scene entities.
8
+ *
9
+ * Visibility is a per-component user flag (the same one the "Hide" / "Isolate" /
10
+ * "Show All" toolbar and right-click actions toggle). Every method here commits
11
+ * an undoable command and echoes the affected entities as
12
+ * {@linkcode PluginDesignChangeResult}.
13
+ *
14
+ * Accessed via `snaptrude.design.visibility`.
15
+ */
16
+ export abstract class PluginDesignVisibilityApi {
17
+ constructor() {}
18
+
19
+ /**
20
+ * Hide entities from the viewport — the same as the "Hide" action. Undoable.
21
+ * Hosted door/window/void children ride along with their wall. Already-hidden
22
+ * entities stay hidden.
23
+ *
24
+ * @param components Entities to hide
25
+ * @returns The affected entities (echoing the input handles)
26
+ *
27
+ * @examplePrompt Hide the selected walls
28
+ * @examplePrompt Conceal these masses so I can see behind them
29
+ * @examplePrompt Hide every column on this floor
30
+ * @examplePrompt Make this furniture disappear from view
31
+ *
32
+ * # Example
33
+ * ```ts
34
+ * const walls = await snaptrude.design.query.listWalls({ storeys: [1] })
35
+ * const { affected } = await snaptrude.design.visibility.hide(walls)
36
+ * ```
37
+ */
38
+ public abstract hide(
39
+ components: ComponentHandle[],
40
+ ): PluginApiReturn<PluginDesignChangeResult>
41
+
42
+ /**
43
+ * Isolate entities — hide everything else so only the given entities remain
44
+ * visible (the "Isolate" / solo action). Undoable. Reverse it with
45
+ * {@linkcode PluginDesignVisibilityApi.showAll}.
46
+ *
47
+ * @param components Entities to keep visible; everything else is hidden
48
+ * @returns The isolated entities (echoing the input handles)
49
+ *
50
+ * @examplePrompt Isolate the selected room so I can focus on it
51
+ * @examplePrompt Show only these walls and hide the rest
52
+ * @examplePrompt Solo this mass
53
+ * @examplePrompt Hide everything except the staircase
54
+ *
55
+ * # Example
56
+ * ```ts
57
+ * const [room] = await snaptrude.design.selection.get()
58
+ * await snaptrude.design.visibility.isolate([room])
59
+ * ```
60
+ */
61
+ public abstract isolate(
62
+ components: ComponentHandle[],
63
+ ): PluginApiReturn<PluginDesignChangeResult>
64
+
65
+ /**
66
+ * Reveal everything hidden on the active story — the "Show All" action, which
67
+ * also exits an isolate. Undoable.
68
+ *
69
+ * @returns The entities that were made visible
70
+ *
71
+ * @examplePrompt Show everything again
72
+ * @examplePrompt Unhide all the hidden objects
73
+ * @examplePrompt Exit isolate mode
74
+ * @examplePrompt Reveal everything I hid earlier
75
+ *
76
+ * # Example
77
+ * ```ts
78
+ * const { affected } = await snaptrude.design.visibility.showAll()
79
+ * console.log(`Revealed ${affected.length} entities`)
80
+ * ```
81
+ */
82
+ public abstract showAll(): PluginApiReturn<PluginDesignChangeResult>
83
+ }
84
+
85
+ /**
86
+ * Arguments for {@linkcode PluginDesignVisibilityApi.hide}.
87
+ *
88
+ * | Property | Type | Description |
89
+ * |---|---|---|
90
+ * | `components` | {@linkcode ComponentHandle}`[]` | Entities to hide |
91
+ */
92
+ export const PluginDesignVisibilityHideArgs = z.object({
93
+ components: z.array(ComponentHandle),
94
+ })
95
+ export type PluginDesignVisibilityHideArgs = z.infer<typeof PluginDesignVisibilityHideArgs>
96
+
97
+ /**
98
+ * Arguments for {@linkcode PluginDesignVisibilityApi.isolate}.
99
+ *
100
+ * | Property | Type | Description |
101
+ * |---|---|---|
102
+ * | `components` | {@linkcode ComponentHandle}`[]` | Entities to keep visible |
103
+ */
104
+ export const PluginDesignVisibilityIsolateArgs = z.object({
105
+ components: z.array(ComponentHandle),
106
+ })
107
+ export type PluginDesignVisibilityIsolateArgs = z.infer<
108
+ typeof PluginDesignVisibilityIsolateArgs
109
+ >