@snaptrude/plugin-core 0.0.0-dev-20260908074328 → 0.0.0-dev-20260921132444

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 (95) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +52 -16
  3. package/dist/api/core/io/import/index.d.ts +3 -1
  4. package/dist/api/core/io/import/index.d.ts.map +1 -1
  5. package/dist/api/core/mode/index.d.ts +19 -7
  6. package/dist/api/core/mode/index.d.ts.map +1 -1
  7. package/dist/api/core/tags.d.ts +81 -0
  8. package/dist/api/core/tags.d.ts.map +1 -1
  9. package/dist/api/design/create/bulk-items.d.ts +185 -0
  10. package/dist/api/design/create/bulk-items.d.ts.map +1 -0
  11. package/dist/api/design/create/grids.d.ts +132 -0
  12. package/dist/api/design/create/grids.d.ts.map +1 -0
  13. package/dist/api/design/create/index.d.ts +424 -51
  14. package/dist/api/design/create/index.d.ts.map +1 -1
  15. package/dist/api/design/create/opening-fields.d.ts +37 -0
  16. package/dist/api/design/create/opening-fields.d.ts.map +1 -0
  17. package/dist/api/design/delete/index.d.ts +6 -20
  18. package/dist/api/design/delete/index.d.ts.map +1 -1
  19. package/dist/api/design/dimensions.d.ts +427 -0
  20. package/dist/api/design/dimensions.d.ts.map +1 -0
  21. package/dist/api/design/doors/index.d.ts +20 -13
  22. package/dist/api/design/doors/index.d.ts.map +1 -1
  23. package/dist/api/design/family.d.ts +73 -5
  24. package/dist/api/design/family.d.ts.map +1 -1
  25. package/dist/api/design/grids.d.ts +237 -0
  26. package/dist/api/design/grids.d.ts.map +1 -0
  27. package/dist/api/design/index.d.ts +9 -0
  28. package/dist/api/design/index.d.ts.map +1 -1
  29. package/dist/api/design/query/grids.d.ts +287 -0
  30. package/dist/api/design/query/grids.d.ts.map +1 -0
  31. package/dist/api/design/query/index.d.ts +29 -2
  32. package/dist/api/design/query/index.d.ts.map +1 -1
  33. package/dist/api/design/query/spaces.d.ts +0 -61
  34. package/dist/api/design/query/spaces.d.ts.map +1 -1
  35. package/dist/api/design/update/index.d.ts +74 -0
  36. package/dist/api/design/update/index.d.ts.map +1 -1
  37. package/dist/api/entity/space.d.ts +0 -3
  38. package/dist/api/entity/space.d.ts.map +1 -1
  39. package/dist/api/presentation/annotate.d.ts +2 -2
  40. package/dist/api/presentation/placedViews.d.ts +1 -35
  41. package/dist/api/presentation/placedViews.d.ts.map +1 -1
  42. package/dist/api/presentation/shapes.d.ts +2 -2
  43. package/dist/api/presentation/sheets.d.ts +2 -20
  44. package/dist/api/presentation/sheets.d.ts.map +1 -1
  45. package/dist/api/program/departments.d.ts +58 -2
  46. package/dist/api/program/departments.d.ts.map +1 -1
  47. package/dist/api/program/index.d.ts +16 -6
  48. package/dist/api/program/index.d.ts.map +1 -1
  49. package/dist/api/program/labels.d.ts +355 -0
  50. package/dist/api/program/labels.d.ts.map +1 -0
  51. package/dist/api/program/metadata.d.ts +328 -0
  52. package/dist/api/program/metadata.d.ts.map +1 -0
  53. package/dist/api/program/spreadsheet.d.ts +263 -0
  54. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  55. package/dist/api/workspace/index.d.ts +49 -2
  56. package/dist/api/workspace/index.d.ts.map +1 -1
  57. package/dist/errors/codes.d.ts +3 -8
  58. package/dist/errors/codes.d.ts.map +1 -1
  59. package/dist/handles.d.ts +19 -0
  60. package/dist/handles.d.ts.map +1 -1
  61. package/dist/index.cjs +2489 -1941
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.js +2395 -1936
  64. package/dist/index.js.map +1 -1
  65. package/package.json +1 -1
  66. package/src/api/core/io/import/index.ts +11 -3
  67. package/src/api/core/mode/index.ts +19 -7
  68. package/src/api/core/tags.ts +76 -0
  69. package/src/api/design/create/bulk-items.ts +186 -0
  70. package/src/api/design/create/grids.ts +137 -0
  71. package/src/api/design/create/index.ts +472 -70
  72. package/src/api/design/create/opening-fields.ts +37 -0
  73. package/src/api/design/delete/index.ts +5 -20
  74. package/src/api/design/dimensions.ts +453 -0
  75. package/src/api/design/doors/index.ts +20 -13
  76. package/src/api/design/family.ts +51 -4
  77. package/src/api/design/grids.ts +237 -0
  78. package/src/api/design/index.ts +10 -0
  79. package/src/api/design/query/grids.ts +197 -0
  80. package/src/api/design/query/index.ts +27 -2
  81. package/src/api/design/query/spaces.ts +0 -68
  82. package/src/api/design/update/index.ts +53 -0
  83. package/src/api/entity/space.ts +0 -2
  84. package/src/api/presentation/placedViews.ts +1 -29
  85. package/src/api/presentation/sheets.ts +3 -19
  86. package/src/api/program/departments.ts +54 -2
  87. package/src/api/program/index.ts +16 -6
  88. package/src/api/program/labels.ts +332 -0
  89. package/src/api/program/metadata.ts +364 -0
  90. package/src/api/program/spreadsheet.ts +282 -0
  91. package/src/api/workspace/index.ts +51 -2
  92. package/src/errors/codes.ts +2 -30
  93. package/src/handles.ts +24 -0
  94. package/test/errors.test.mjs +0 -4
  95. package/snaptrude-plugin-core-0.11.0.tgz +0 -0
@@ -1,13 +1,16 @@
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, CurveHandle, ProfileHandle, Vec3Handle } from "../../../handles";
4
+ import { PluginGridStyleOptions } from "./grids";
4
5
  import { PluginSpaceType, PluginMassType, PluginDepartmentId } from "../../entity/space";
5
6
  import { PluginBuildableEnvelopePolygonVertex, PluginBuildableEnvelopeSetbackTier, PluginBuildableEnvelopeVerticalCap, PluginBuildableEnvelopeCreateResult } from "../../entity/buildableEnvelope";
7
+ import type { PluginCreateDoorItem, PluginCreateFloorItem, PluginCreateFurnitureItem, PluginCreateWallRunItem, PluginCreateWindowItem } from "./bulk-items";
6
8
  /**
7
9
  * `design.create.*` — author new scene-committed BIM entities.
8
10
  *
9
11
  * Every creator takes geometry handles + scalars and returns a
10
- * {@linkcode ComponentHandle} (or `ComponentHandle[]` for plural creators) — the
12
+ * {@linkcode ComponentHandle} (or `ComponentHandle[]` for plural creators;
13
+ * `wallRuns` returns one `ComponentHandle[]` per run) — the
11
14
  * `Component.id` of the created entity, resolvable across the rest of the
12
15
  * `design.*` surface. Creation is an undoable host call; it **throws** on failure
13
16
  * (no `Result` wrapper — consistent with `core.geom.create.*`).
@@ -173,26 +176,11 @@ export declare abstract class PluginDesignCreateApi {
173
176
  * Create a **floor** by extruding a footprint contour by `thickness`
174
177
  * (extruded upward).
175
178
  *
176
- * The parametric engine owns floor topology and may resolve the request
177
- * differently than asked: drawing against existing floors can **split** the
178
- * footprint into several floors, or **merge** it into a pre-existing
179
- * neighbour (that floor's region grows; nothing new is created). The call
180
- * honors the engine's resolution and returns **every floor that covers the
181
- * requested footprint after the operation** — the newly created floor(s),
182
- * and/or the pre-existing floor that absorbed it. The array is never empty
183
- * on success; a lone independently-created floor comes back as `[floor]`.
184
- *
185
- * **Breaking change in 0.11.0** — previously returned a single
186
- * {@linkcode ComponentHandle}; callers must switch to the array (the first
187
- * element preserves the old single-floor behavior for simple creates).
188
- *
189
179
  * @param contour - Footprint (outer + holes)
190
180
  * @param thickness - Floor thickness (> 0)
191
181
  * @param position - Offset from origin
192
- * @returns the {@linkcode ComponentHandle}s of every floor covering the
193
- * requested footprint after parametric resolution (created and/or absorbing)
194
- * @throws if the contour is invalid, the thickness is not positive, or the
195
- * engine rejected the operation (nothing covers the footprint)
182
+ * @returns the {@linkcode ComponentHandle} of the created floor
183
+ * @throws if the contour is invalid or the thickness is not positive
196
184
  *
197
185
  * @examplePrompt Create a floor from this room outline
198
186
  * @examplePrompt Add a 100mm thick floor over the footprint
@@ -203,10 +191,51 @@ export declare abstract class PluginDesignCreateApi {
203
191
  * ```ts
204
192
  * const rect = await snaptrude.core.geom.create.profileRect(5, 4)
205
193
  * const contour = await snaptrude.core.geom.create.contourFromProfile(rect)
206
- * const [floor, ...siblings] = await snaptrude.design.create.floor(contour, 0.1)
194
+ * const floor = await snaptrude.design.create.floor(contour, 0.1)
195
+ * ```
196
+ *
197
+ * @performance For MORE THAN ONE floor, call `design.create.floors(items[])` — one
198
+ * host round-trip and ONE undo entry for the whole batch. Looping this single-floor
199
+ * creator is N round-trips and N undo entries.
200
+ */
201
+ abstract floor(contour: ContourHandle, thickness: number, position?: Vec3Handle): PluginApiReturn<ComponentHandle>;
202
+ /**
203
+ * Create **many floors** in one undoable operation (bulk plural of
204
+ * {@linkcode floor}). Each item extrudes its own footprint contour (outer
205
+ * profile + holes) upward by its own `thickness`, at its own optional
206
+ * position offset. Validate-all-or-throw; one command.
207
+ *
208
+ * @param items - One {@linkcode PluginCreateFloorItem} per floor to create
209
+ * (≥1, ≤1000)
210
+ * @returns the created floors as {@linkcode ComponentHandle}`[]`, in input order
211
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
212
+ * 1000 items, a non-positive thickness) or a contour is degenerate;
213
+ * `HANDLE_INVALID` if a `contour` or `position` handle is unknown or
214
+ * released; `OPERATION_FAILED` if extrusion fails (nothing is created —
215
+ * `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the
216
+ * plugin may not write.
217
+ *
218
+ * @examplePrompt Create floors for all these room outlines at once
219
+ * @examplePrompt Add a floor to every space in one operation
220
+ * @examplePrompt Bulk create the floor plates for this building
221
+ * @examplePrompt Lay 100mm floors across these five footprints in one undo step
222
+ * @examplePrompt Create the ground and first floor slabs together
223
+ *
224
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
225
+ * entry. Always prefer this over calling `design.create.floor` in a loop: build the
226
+ * full `items[]` array first (all contours and offsets up front), then make one call.
227
+ *
228
+ * # Example
229
+ * ```ts
230
+ * const rect = await snaptrude.core.geom.create.profileRect(5, 4)
231
+ * const contour = await snaptrude.core.geom.create.contourFromProfile(rect)
232
+ * const [ground, upper] = await snaptrude.design.create.floors([
233
+ * { contour, thickness: 0.1 },
234
+ * { contour, thickness: 0.1, position: await snaptrude.core.math.vec3.new(0, 3, 0) },
235
+ * ])
207
236
  * ```
208
237
  */
209
- abstract floor(contour: ContourHandle, thickness: number, position?: Vec3Handle): PluginApiReturn<ComponentHandle[]>;
238
+ abstract floors(items: PluginCreateFloorItem[]): PluginApiReturn<ComponentHandle[]>;
210
239
  /**
211
240
  * Create a **roof** by extruding a footprint contour by `thickness`. Created
212
241
  * flat (extruded downward); pitch/slope is a separate post-creation edit.
@@ -341,13 +370,7 @@ export declare abstract class PluginDesignCreateApi {
341
370
  * single undo entry. The storey must already exist
342
371
  * (`core.storeys.create` first). Default: geometry-derived — a profile
343
372
  * drawn at y = 0 lands on storey 1; the ACTIVE storey is NOT consulted.
344
- * @returns the actually-created wall {@linkcode ComponentHandle}s. The
345
- * parametric engine owns wall topology — curves touching existing walls
346
- * may merge into or split against them, so the returned count can differ
347
- * from the input curve count. Profile-ordered 1:1 matches come first,
348
- * then the remaining merged/split products in creation order. Re-query
349
- * (e.g. `design.query.spaces.listGeneratedBim`) rather than assuming a
350
- * wall per input curve.
373
+ * @returns a {@linkcode ComponentHandle}`[]` (one per wall), in profile order
351
374
  * @throws if the profile is empty, `wallType` names no wall type in the
352
375
  * project, `storey` does not exist, or wall creation fails
353
376
  *
@@ -374,8 +397,63 @@ export declare abstract class PluginDesignCreateApi {
374
397
  * centerlines, 3, undefined, brick.label,
375
398
  * )
376
399
  * ```
400
+ *
401
+ * @performance For MORE THAN ONE run, call `design.create.wallRuns(items[])` — one
402
+ * host round-trip and ONE undo entry for every run in the batch. Looping this
403
+ * single-run creator is N round-trips and N undo entries.
377
404
  */
378
405
  abstract walls(profile: ProfileHandle, height?: number, thickness?: number, wallType?: string, storey?: number): PluginApiReturn<ComponentHandle[]>;
406
+ /**
407
+ * Create **many wall runs** in one undoable operation (bulk plural of
408
+ * {@linkcode walls}). Each item is one full run — a wall per curve in that
409
+ * item's profile chain, mitred at shared endpoints. Junctions resolve within a
410
+ * run, not between runs. Each item carries its own
411
+ * dimensions, `wallType` and `storey`, so a single call can build a whole
412
+ * floor plate or several storeys at once. Validate-all-or-throw; one command.
413
+ *
414
+ * @param items - One {@linkcode PluginCreateWallRunItem} per run to create
415
+ * (≥1, ≤1000)
416
+ * @returns one {@linkcode ComponentHandle}`[]` per item, in input order —
417
+ * each inner array holding that run's walls in profile-curve order
418
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
419
+ * 1000 items, a non-positive height or thickness, a zero-length curve);
420
+ * `HANDLE_INVALID` if a `profile` handle is unknown or released;
421
+ * `PRECONDITION_FAILED` if a profile has no curves, `wallType` names no
422
+ * wall type in the project, or `storey` does not exist;
423
+ * `OPERATION_FAILED` if wall creation fails (nothing is created —
424
+ * `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the
425
+ * plugin may not write.
426
+ *
427
+ * @examplePrompt Draw all the walls of this floor plan at once
428
+ * @examplePrompt Build every room's perimeter in one operation
429
+ * @examplePrompt Bulk create wall runs from these centerlines
430
+ * @examplePrompt Create the walls for both storeys in a single undo step
431
+ * @examplePrompt Turn these polylines into 200mm brick walls together
432
+ *
433
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
434
+ * entry. Always prefer this over calling `design.create.walls` in a loop: build the
435
+ * full `items[]` array first (all profiles up front), then make one call.
436
+ *
437
+ * # Example
438
+ * ```ts
439
+ * const v = snaptrude.core.math.vec3
440
+ * const ground = await snaptrude.core.geom.create.profileFromLinePoints([
441
+ * await v.new(0, 0, 0),
442
+ * await v.new(8, 0, 0),
443
+ * await v.new(8, 0, 6),
444
+ * ])
445
+ * const upper = await snaptrude.core.geom.create.profileFromLinePoints([
446
+ * await v.new(0, 0, 0),
447
+ * await v.new(8, 0, 0),
448
+ * ])
449
+ * const [groundWalls, upperWalls] = await snaptrude.design.create.wallRuns([
450
+ * { profile: ground, height: 3, thickness: 0.2 },
451
+ * { profile: upper, height: 3, storey: 2 },
452
+ * ])
453
+ * console.log(groundWalls.length, "walls on the ground floor")
454
+ * ```
455
+ */
456
+ abstract wallRuns(items: PluginCreateWallRunItem[]): PluginApiReturn<ComponentHandle[][]>;
379
457
  /**
380
458
  * Create a **staircase** from a parametric preset, placed at a point.
381
459
  *
@@ -447,6 +525,112 @@ export declare abstract class PluginDesignCreateApi {
447
525
  * ```
448
526
  */
449
527
  abstract referenceLines(profile: ProfileHandle, color?: string, thickness?: number, style?: PluginReferenceLineStyle, gridTag?: string): PluginApiReturn<ComponentHandle[]>;
528
+ /**
529
+ * Create a free rectangular **structural grid** — one grid group with two
530
+ * perpendicular line families (`linesX` lines spaced `spacingX` apart, and
531
+ * `linesY` lines spaced `spacingY` apart) on the active storey. One undoable
532
+ * creation.
533
+ *
534
+ * Units: spacings in Snaptrude units; `angle` in degrees (CCW about +Y,
535
+ * default 0). Without `center` the grid is centred on the current viewport
536
+ * (the native tool's behavior) — pass `center` for deterministic placement.
537
+ *
538
+ * @param linesX - Line count of the first family (integer ≥ 1)
539
+ * @param linesY - Line count of the second family (integer ≥ 1)
540
+ * @param spacingX - First-family spacing (Snaptrude units, > 0)
541
+ * @param spacingY - Second-family spacing (Snaptrude units, > 0)
542
+ * @param options - `angle`, `center`, and {@linkcode PluginGridStyleOptions}
543
+ * @returns the created grid group's {@linkcode ComponentHandle}
544
+ *
545
+ * @examplePrompt Create a 5 by 8 structural grid with 6 metre spacing
546
+ * @examplePrompt Add a column grid rotated 30 degrees
547
+ * @examplePrompt Set up a structural grid at the site origin
548
+ *
549
+ * # Example
550
+ * ```ts
551
+ * const centre = await snaptrude.core.math.vec3.new(0, 0, 0)
552
+ * const grid = await snaptrude.design.create.grid(5, 8, 6, 6, { center: centre })
553
+ * ```
554
+ */
555
+ abstract grid(linesX: number, linesY: number, spacingX: number, spacingY: number, options?: {
556
+ angle?: number;
557
+ center?: Vec3Handle;
558
+ } & PluginGridStyleOptions): PluginApiReturn<ComponentHandle>;
559
+ /**
560
+ * Create a **structural grid from a single curve** — one grid group holding
561
+ * one wing with one line (the draw tool's output). The curve may be a line
562
+ * or an arc; circles are rejected with `VALIDATION`. Undoable.
563
+ *
564
+ * @param curve - The grid line's geometry ({@linkcode CurveHandle}, world space)
565
+ * @param options - `tag` (defaults to the draw tool's next tag) and
566
+ * {@linkcode PluginGridStyleOptions}
567
+ * @returns the created grid group's {@linkcode ComponentHandle}
568
+ *
569
+ * @examplePrompt Draw a grid line from A to B
570
+ * @examplePrompt Add a curved grid line through these points
571
+ * @examplePrompt Create grid line "C" along this wall
572
+ *
573
+ * # Example
574
+ * ```ts
575
+ * const { vec3 } = snaptrude.core.math
576
+ * const from = await vec3.new(0, 0, 0)
577
+ * const to = await vec3.new(30, 0, 0)
578
+ * const curve = await snaptrude.core.geom.create.line(from, to)
579
+ * const grid = await snaptrude.design.create.gridFromCurve(curve, { tag: "A" })
580
+ * ```
581
+ */
582
+ abstract gridFromCurve(curve: CurveHandle, options?: {
583
+ tag?: string;
584
+ } & PluginGridStyleOptions): PluginApiReturn<ComponentHandle>;
585
+ /**
586
+ * Generate **structural grids fitted to mass footprints** — one grid group
587
+ * per footprint cluster, with counts and orientation derived from each
588
+ * footprint's geometry and the given spacings. All created groups commit as
589
+ * ONE undoable unit.
590
+ *
591
+ * Lenient like the native tool: masses without an extractable footprint
592
+ * (no B-rep, degenerate top face) are skipped; throws `VALIDATION` only when
593
+ * NONE of the given masses yields a footprint.
594
+ *
595
+ * @param masses - Masses whose footprints seat the grids
596
+ * @param spacingX - First-family spacing (Snaptrude units, > 0)
597
+ * @param spacingY - Second-family spacing (Snaptrude units, > 0)
598
+ * @param options - {@linkcode PluginGridStyleOptions}
599
+ * @returns the created grid groups' {@linkcode ComponentHandle}`[]`
600
+ *
601
+ * @examplePrompt Generate grids for the selected masses
602
+ * @examplePrompt Auto-generate a 6m structural grid on this building
603
+ * @examplePrompt Fit column grids to every mass on this storey
604
+ *
605
+ * # Example
606
+ * ```ts
607
+ * const masses = await snaptrude.design.query.listMasses({ storeys: [1] })
608
+ * const grids = await snaptrude.design.create.gridsFromMasses(masses, 6, 6)
609
+ * ```
610
+ */
611
+ abstract gridsFromMasses(masses: ComponentHandle[], spacingX: number, spacingY: number, options?: PluginGridStyleOptions): PluginApiReturn<ComponentHandle[]>;
612
+ /**
613
+ * Create **columns at every grid-line intersection** of the given grid
614
+ * groups, sized `width` × `depth` and oriented to the grid axes, on the
615
+ * grids' storey. All columns commit as ONE undoable unit.
616
+ *
617
+ * @param grids - Grid groups whose intersections seat the columns
618
+ * @param width - Column width (Snaptrude units, > 0)
619
+ * @param depth - Column depth (Snaptrude units, > 0)
620
+ * @returns the created columns' {@linkcode ComponentHandle}`[]`
621
+ * @throws `VALIDATION` when an id does not resolve to a grid group;
622
+ * `OPERATION_FAILED` when the grids have no line intersections
623
+ *
624
+ * @examplePrompt Generate columns on this grid
625
+ * @examplePrompt Place 450mm square columns at every grid intersection
626
+ *
627
+ * # Example
628
+ * ```ts
629
+ * const grids = await snaptrude.design.query.listGrids()
630
+ * const columns = await snaptrude.design.create.columnsFromGrids(grids, 0.45, 0.45)
631
+ * ```
632
+ */
633
+ abstract columnsFromGrids(grids: ComponentHandle[], width: number, depth: number): PluginApiReturn<ComponentHandle[]>;
450
634
  /**
451
635
  * Place a **furniture** item from the project library at a world position.
452
636
  *
@@ -465,17 +649,19 @@ export declare abstract class PluginDesignCreateApi {
465
649
  * `position.y` (the same surface-flush contract as interactive drag-drop) —
466
650
  * pass the floor/storey elevation to stand furniture on it; never add half
467
651
  * the item's height yourself.
468
- * @param options - Optional placement options: `label` — instance name
469
- * (default auto `${name}Ins${n}`); `createNewSourceMesh` — emit a
470
- * source-mesh creation command (default `true`). `position.y` is always
471
- * grounded: the placed instance's bounding-box bottom rests at it (the
472
- * surface-flush grounding described above)
652
+ * @param options - Optional placement options: `label` — instance name and
653
+ * readable label (`design.query.getLabel`; default auto `${name}Ins${n}`);
654
+ * `createNewSourceMesh` — legacy flag, kept for compatibility. The host owns
655
+ * source-mesh persistence: a catalog source is recorded exactly once, by the
656
+ * first placement that brings it in, and this flag cannot skip that record.
473
657
  * @param angleInDegrees - Optional signed rotation about the vertical axis, in
474
658
  * degrees (same convention as {@linkcode PluginDesignTransformApi.rotate}).
475
659
  * Applied at creation time so it is part of the placement's single undo entry.
476
660
  * Default: the item's own (unrotated) orientation.
477
661
  * @returns the {@linkcode ComponentHandle} of the placed furniture instance
478
- * @throws if the catalog id is unknown, the source mesh fails to load, or placement fails
662
+ * @throws if the catalog id is unknown, the source mesh fails to load, or placement fails;
663
+ * `PRECONDITION_FAILED` (`details.engineCode: "TOOL_ACTIVE"`) while the interactive
664
+ * furniture tool is active — finish or cancel it first
479
665
  *
480
666
  * @examplePrompt Place a chair from the library at this spot
481
667
  * @examplePrompt Add a sofa from the furniture catalog to the living room
@@ -499,11 +685,58 @@ export declare abstract class PluginDesignCreateApi {
499
685
  * 90,
500
686
  * )
501
687
  * ```
688
+ *
689
+ * @performance For MORE THAN ONE item, call `design.create.furnitureItems(items[])` —
690
+ * one host round-trip and ONE undo entry, and a catalog source shared by several
691
+ * items is fetched once. Looping this single-item creator is N round-trips.
502
692
  */
503
693
  abstract furniture(catalogId: string, position: Vec3Handle, options?: {
504
694
  label?: string;
505
695
  createNewSourceMesh?: boolean;
506
696
  }, angleInDegrees?: number): PluginApiReturn<ComponentHandle>;
697
+ /**
698
+ * Place **many furniture items** in one undoable operation (bulk plural of
699
+ * {@linkcode furniture}). Each item names a catalog id and an absolute world
700
+ * position (`position.y` is the REST elevation — the same grounding contract
701
+ * as the singular creator), with optional label and rotation. A catalog
702
+ * source shared by several items is fetched and recorded once for the whole
703
+ * batch, so the host — not the caller — owns source persistence (there is no
704
+ * per-item `createNewSourceMesh`). Validate-all-or-throw; one command.
705
+ *
706
+ * @param items - One {@linkcode PluginCreateFurnitureItem} per instance to
707
+ * place (≥1, ≤1000)
708
+ * @returns the placed instances as {@linkcode ComponentHandle}`[]`, in input order
709
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
710
+ * 1000 items); `HANDLE_INVALID` if a `position` handle is unknown or
711
+ * released; `PRECONDITION_FAILED` if a catalog id is unknown, a furniture
712
+ * tool is active, or a parametric group is active (exit it first, or place
713
+ * items one at a time with `furniture`); `OPERATION_FAILED` if a source
714
+ * mesh fails to load or placement fails (nothing is created —
715
+ * `details.itemIndex` is the failing item); `METHOD_NOT_PERMITTED` if the plugin may not write.
716
+ *
717
+ * @examplePrompt Place all the desks for this office at once
718
+ * @examplePrompt Furnish every bedroom in one operation
719
+ * @examplePrompt Bulk place these chairs around the table
720
+ * @examplePrompt Add the whole furniture layout in a single undo step
721
+ * @examplePrompt Drop twenty copies of this chair at these positions
722
+ *
723
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
724
+ * entry, and each distinct catalog source loads once. Always prefer this over
725
+ * calling `design.create.furniture` in a loop: build the full `items[]` array
726
+ * first (all positions and angles up front), then make one call.
727
+ *
728
+ * # Example
729
+ * ```ts
730
+ * const v = snaptrude.core.math.vec3
731
+ * const [chair] = await snaptrude.design.furniture.listCatalog()
732
+ * const placed = await snaptrude.design.create.furnitureItems([
733
+ * { catalogId: chair.id, position: await v.new(3, 0, 5), label: "Chair-01" },
734
+ * { catalogId: chair.id, position: await v.new(4, 0, 5), angleInDegrees: 90 },
735
+ * { catalogId: chair.id, position: await v.new(5, 0, 5), angleInDegrees: 180 },
736
+ * ])
737
+ * ```
738
+ */
739
+ abstract furnitureItems(items: PluginCreateFurnitureItem[]): PluginApiReturn<ComponentHandle[]>;
507
740
  /**
508
741
  * Place a **door** from the catalog into a host wall.
509
742
  *
@@ -517,12 +750,15 @@ export declare abstract class PluginDesignCreateApi {
517
750
  * @param catalogId - Library id: team `_id` or general `fullName`
518
751
  * @param hostWall - The wall to host the door
519
752
  * @param position - World point projected onto the wall to locate the opening
520
- * @param options - Optional placement options: `label` — instance name
521
- * @param facing - World point selecting which side of the wall the door faces
522
- * (the room it opens into) — the same convention as approaching the wall
523
- * from that side with the cursor in the interactive tool. Any point clearly
524
- * on that side works (e.g. the room's center). Default: the engine picks a
525
- * side (nondeterministic when `position` sits on the wall centerline).
753
+ * @param options - Optional placement options: `label` — instance name;
754
+ * `hinge` — world point near the jamb the door is hinged on (the door is
755
+ * reflected along the wall so its hinged jamb is the one nearer this
756
+ * point; default the catalog item's authored hinge side)
757
+ * @param facing - World point on the side of the wall the door swings open
758
+ * to (the room it opens into — where the plan symbol draws the swing arc).
759
+ * Any point clearly on that side works (e.g. the room's center). Default:
760
+ * the engine picks a side (nondeterministic when `position` sits on the
761
+ * wall centerline).
526
762
  * @returns the {@linkcode ComponentHandle} of the placed door
527
763
  * @throws if the catalog id is unknown, the host is not a wall, the source
528
764
  * mesh fails to load, or the projected point falls **outside** the host wall
@@ -533,6 +769,7 @@ export declare abstract class PluginDesignCreateApi {
533
769
  * @examplePrompt Insert the entrance door into this wall
534
770
  * @examplePrompt Add a door to the wall and call it Entry-01
535
771
  * @examplePrompt Add a door that opens into the living room
772
+ * @examplePrompt Put a door here hinged on the north jamb
536
773
  *
537
774
  * # Example
538
775
  * ```ts
@@ -552,11 +789,76 @@ export declare abstract class PluginDesignCreateApi {
552
789
  * undefined,
553
790
  * await snaptrude.core.math.vec3.new(3, 0, 9),
554
791
  * )
792
+ * // …and hinged on the jamb nearest a point (here the +x end of the opening):
793
+ * const hingedRight = await snaptrude.design.create.door(
794
+ * entry.id,
795
+ * wall,
796
+ * await snaptrude.core.math.vec3.new(3, 0, 5),
797
+ * { hinge: await snaptrude.core.math.vec3.new(3.5, 0, 5) },
798
+ * await snaptrude.core.math.vec3.new(3, 0, 9),
799
+ * )
555
800
  * ```
801
+ *
802
+ * @performance For MORE THAN ONE door, call `design.create.doors(items[])` — one host
803
+ * round-trip and ONE undo entry, with each host wall re-cut once per opening inside
804
+ * that single call. Looping this single-door creator is N round-trips.
556
805
  */
557
806
  abstract door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: {
558
807
  label?: string;
808
+ hinge?: Vec3Handle;
559
809
  }, facing?: Vec3Handle): PluginApiReturn<ComponentHandle>;
810
+ /**
811
+ * Place **many doors** into host walls in one undoable operation (bulk plural
812
+ * of {@linkcode door}). Each item carries its own catalog id, host wall,
813
+ * world position, and optional `facing`, `label`, `width` and `height` — the
814
+ * same fields as a `"door"` {@linkcode PluginDesignCreateOpeningOptions}.
815
+ * Validate-all-or-throw; one command.
816
+ *
817
+ * As with the singular creator, placing an opening **re-cuts its host wall**:
818
+ * the wall you passed as `hostWall` stops resolving once the call returns.
819
+ * Several items MAY name the same original wall handle in one call — the host
820
+ * chains the re-cuts internally — but after the call recover the surviving
821
+ * wall with `design.query.getHost(opening)`, never by reusing the handle you
822
+ * passed in.
823
+ *
824
+ * @param items - One {@linkcode PluginCreateDoorItem} per door to place
825
+ * (≥1, ≤1000)
826
+ * @returns the placed doors as {@linkcode ComponentHandle}`[]`, in input order
827
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
828
+ * 1000 items, unknown fields, a non-positive `width`/`height`);
829
+ * `HANDLE_INVALID` if a `position`, `facing` or `hinge` handle is unknown
830
+ * or released; `PRECONDITION_FAILED` if a catalog id is unknown, a `hostWall`
831
+ * is not a wall / is locked / is not in the active proposal, the projected
832
+ * point falls outside its host wall, or a door tool is active;
833
+ * `OPERATION_FAILED` if a source mesh fails to load or placement fails
834
+ * (nothing is created — `details.itemIndex` is the failing item);
835
+ * `METHOD_NOT_PERMITTED` if the plugin may not write.
836
+ *
837
+ * @examplePrompt Add doors to all of these walls at once
838
+ * @examplePrompt Place a door in every room in one operation
839
+ * @examplePrompt Bulk add the entrance doors from this schedule
840
+ * @examplePrompt Put three doors on this wall in a single undo step
841
+ * @examplePrompt Add all the doors for this floor plan together
842
+ *
843
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
844
+ * entry, and each distinct catalog source loads once. Always prefer this over
845
+ * calling `design.create.door` in a loop: build the full `items[]` array first
846
+ * (all host walls and points up front), then make one call.
847
+ *
848
+ * # Example
849
+ * ```ts
850
+ * const v = snaptrude.core.math.vec3
851
+ * const [wall] = await snaptrude.design.query.listWalls({ isSelected: true })
852
+ * const [entry] = await snaptrude.design.doors.listCatalog()
853
+ * const [front, side] = await snaptrude.design.create.doors([
854
+ * { catalogId: entry.id, hostWall: wall, position: await v.new(2, 0, 5), label: "D-01" },
855
+ * { catalogId: entry.id, hostWall: wall, position: await v.new(6, 0, 5), width: 1.2 },
856
+ * ])
857
+ * // `wall` was re-cut twice and no longer resolves — ask the opening for its host:
858
+ * const currentWall = await snaptrude.design.query.getHost(front)
859
+ * ```
860
+ */
861
+ abstract doors(items: PluginCreateDoorItem[]): PluginApiReturn<ComponentHandle[]>;
560
862
  /**
561
863
  * Place a **window** from the catalog into a host wall.
562
864
  *
@@ -570,11 +872,14 @@ export declare abstract class PluginDesignCreateApi {
570
872
  * @param catalogId - Library id: team `_id` or general `fullName`
571
873
  * @param hostWall - The wall to host the window
572
874
  * @param position - World point projected onto the wall to locate the opening
573
- * @param options - Optional placement options: `label` — instance name
574
- * @param facing - World point selecting which side of the wall the window
575
- * faces (matters for asymmetric windows, e.g. casement swing) — same
576
- * convention as {@linkcode PluginDesignCreateApi.door}. Default: the engine
577
- * picks a side (nondeterministic when `position` sits on the centerline).
875
+ * @param options - Optional placement options: `label` — instance name;
876
+ * `hinge` — world point near the jamb the window is hinged on (same rule
877
+ * as {@linkcode PluginDesignCreateApi.door}; default the catalog item's
878
+ * authored side)
879
+ * @param facing - World point on the side of the wall the window opens to
880
+ * (matters for asymmetric windows, e.g. casement swing) — same convention
881
+ * as {@linkcode PluginDesignCreateApi.door}. Default: the engine picks a
882
+ * side (nondeterministic when `position` sits on the centerline).
578
883
  * @returns the {@linkcode ComponentHandle} of the placed window
579
884
  * @throws if the catalog id is unknown, the host is not a wall, the source
580
885
  * mesh fails to load, or the projected point falls **outside** the host wall
@@ -597,10 +902,68 @@ export declare abstract class PluginDesignCreateApi {
597
902
  * { label: "Win-01" },
598
903
  * )
599
904
  * ```
905
+ *
906
+ * @performance For MORE THAN ONE window, call `design.create.windows(items[])` — one
907
+ * host round-trip and ONE undo entry, with each host wall re-cut once per opening
908
+ * inside that single call. Looping this single-window creator is N round-trips.
600
909
  */
601
910
  abstract window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: {
602
911
  label?: string;
912
+ hinge?: Vec3Handle;
603
913
  }, facing?: Vec3Handle): PluginApiReturn<ComponentHandle>;
914
+ /**
915
+ * Place **many windows** into host walls in one undoable operation (bulk
916
+ * plural of {@linkcode window}). Each item carries its own catalog id, host
917
+ * wall, world position, and optional `facing`, `label`, `width`, `height` and
918
+ * `sillHeight` — the same fields as a `"window"`
919
+ * {@linkcode PluginDesignCreateOpeningOptions}. `sillHeight` is measured from
920
+ * the host wall base to the BOTTOM of the window. Validate-all-or-throw; one
921
+ * command.
922
+ *
923
+ * As with the singular creator, placing an opening **re-cuts its host wall**:
924
+ * the wall you passed as `hostWall` stops resolving once the call returns.
925
+ * Several items MAY name the same original wall handle in one call — the host
926
+ * chains the re-cuts internally — but after the call recover the surviving
927
+ * wall with `design.query.getHost(opening)`, never by reusing the handle you
928
+ * passed in.
929
+ *
930
+ * @param items - One {@linkcode PluginCreateWindowItem} per window to place
931
+ * (≥1, ≤1000)
932
+ * @returns the placed windows as {@linkcode ComponentHandle}`[]`, in input order
933
+ * @throws `VALIDATION` if the items fail the schema (empty array, more than
934
+ * 1000 items, unknown fields, a non-positive `width`/`height`, a negative
935
+ * `sillHeight`); `HANDLE_INVALID` if a `position`, `facing` or `hinge`
936
+ * handle is unknown or released; `PRECONDITION_FAILED` if a catalog id is unknown, a
937
+ * `hostWall` is not a wall / is locked / is not in the active proposal, the
938
+ * projected point falls outside its host wall, or a window tool is active;
939
+ * `OPERATION_FAILED` if a source mesh fails to load or placement fails
940
+ * (nothing is created — `details.itemIndex` is the failing item);
941
+ * `METHOD_NOT_PERMITTED` if the plugin may not write.
942
+ *
943
+ * @examplePrompt Add windows along this whole facade at once
944
+ * @examplePrompt Place a window in every bedroom in one operation
945
+ * @examplePrompt Bulk add the windows from this schedule
946
+ * @examplePrompt Put four windows on this wall in a single undo step
947
+ * @examplePrompt Add all the windows with a 0.9m sill height together
948
+ *
949
+ * @performance Bulk creator — the whole batch is ONE host round-trip and ONE undo
950
+ * entry, and each distinct catalog source loads once. Always prefer this over
951
+ * calling `design.create.window` in a loop: build the full `items[]` array first
952
+ * (all host walls and points up front), then make one call.
953
+ *
954
+ * # Example
955
+ * ```ts
956
+ * const v = snaptrude.core.math.vec3
957
+ * const [wall] = await snaptrude.design.query.listWalls({ isSelected: true })
958
+ * const [casement] = await snaptrude.design.windows.listCatalog()
959
+ * const placed = await snaptrude.design.create.windows([
960
+ * { catalogId: casement.id, hostWall: wall, position: await v.new(2, 0, 5), sillHeight: 0.9 },
961
+ * { catalogId: casement.id, hostWall: wall, position: await v.new(5, 0, 5), sillHeight: 0.9 },
962
+ * ])
963
+ * const currentWall = await snaptrude.design.query.getHost(placed[0])
964
+ * ```
965
+ */
966
+ abstract windows(items: PluginCreateWindowItem[]): PluginApiReturn<ComponentHandle[]>;
604
967
  /**
605
968
  * Place a catalog **door or window** into a host wall with optional size overrides.
606
969
  *
@@ -610,7 +973,7 @@ export declare abstract class PluginDesignCreateApi {
610
973
  * its center. Placement is asynchronous and committed as one undoable creation.
611
974
  *
612
975
  * @param options - Opening kind, catalog and host references, placement, and
613
- * optional facing, label, and dimensions
976
+ * optional facing (swing side), hinge (hinged jamb), label, and dimensions
614
977
  * @returns the {@linkcode ComponentHandle} of the placed door or window
615
978
  * @throws if the options are invalid, the catalog id is unknown, the host is
616
979
  * not a wall, loading fails, or the opening cannot be placed on the host
@@ -618,8 +981,9 @@ export declare abstract class PluginDesignCreateApi {
618
981
  * @examplePrompt Add a 1m wide door to this wall here
619
982
  * @examplePrompt Place a window with a 0.9m sill height on the selected wall
620
983
  *
621
- * @performance Single-opening creator — use it for one hosted opening. A plural
622
- * API is intentionally unavailable until host placement can be atomic.
984
+ * @performance Single-opening creator — use it for one hosted opening. For MORE
985
+ * THAN ONE, call `design.create.doors(items[])` / `design.create.windows(items[])`:
986
+ * the same per-item fields, one host round-trip, ONE undo entry.
623
987
  *
624
988
  * # Example
625
989
  * ```ts
@@ -1141,7 +1505,7 @@ export type PluginDesignCreateStaircaseArgs = z.infer<typeof PluginDesignCreateS
1141
1505
  * | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
1142
1506
  * | `position` | {@linkcode Vec3Handle} | Absolute world placement point |
1143
1507
  * | `label` | `string`? | Instance name (default auto `${name}Ins${n}`) |
1144
- * | `createNewSourceMesh` | `boolean`? | Emit a source-mesh creation command (default `true`) |
1508
+ * | `createNewSourceMesh` | `boolean`? | Legacy, kept for compatibility; the host records a catalog source exactly once and this flag cannot skip it |
1145
1509
  * | `angleInDegrees` | `number`? | Rotation about the vertical axis, in degrees (default unrotated) |
1146
1510
  */
1147
1511
  export declare const PluginDesignCreateFurnitureArgs: z.ZodObject<{
@@ -1161,7 +1525,8 @@ export type PluginDesignCreateFurnitureArgs = z.infer<typeof PluginDesignCreateF
1161
1525
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
1162
1526
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
1163
1527
  * | `label` | `string`? | Instance name (optional) |
1164
- * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door faces (default engine-chosen) |
1528
+ * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door swings open to (default engine-chosen) |
1529
+ * | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the door is hinged on (default the catalog item's authored side) |
1165
1530
  */
1166
1531
  export declare const PluginDesignCreateDoorArgs: z.ZodObject<{
1167
1532
  catalogId: z.ZodString;
@@ -1169,6 +1534,7 @@ export declare const PluginDesignCreateDoorArgs: z.ZodObject<{
1169
1534
  position: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>;
1170
1535
  label: z.ZodOptional<z.ZodString>;
1171
1536
  facing: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1537
+ hinge: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1172
1538
  }, z.core.$strip>;
1173
1539
  export type PluginDesignCreateDoorArgs = z.infer<typeof PluginDesignCreateDoorArgs>;
1174
1540
  /**
@@ -1180,7 +1546,8 @@ export type PluginDesignCreateDoorArgs = z.infer<typeof PluginDesignCreateDoorAr
1180
1546
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
1181
1547
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
1182
1548
  * | `label` | `string`? | Instance name (optional) |
1183
- * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window faces (default engine-chosen) |
1549
+ * | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window opens to (default engine-chosen) |
1550
+ * | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the window is hinged on (default the catalog item's authored side) |
1184
1551
  */
1185
1552
  export declare const PluginDesignCreateWindowArgs: z.ZodObject<{
1186
1553
  catalogId: z.ZodString;
@@ -1188,6 +1555,7 @@ export declare const PluginDesignCreateWindowArgs: z.ZodObject<{
1188
1555
  position: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>;
1189
1556
  label: z.ZodOptional<z.ZodString>;
1190
1557
  facing: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1558
+ hinge: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1191
1559
  }, z.core.$strip>;
1192
1560
  export type PluginDesignCreateWindowArgs = z.infer<typeof PluginDesignCreateWindowArgs>;
1193
1561
  /**
@@ -1201,6 +1569,7 @@ export declare const PluginDesignCreateOpeningOptions: z.ZodDiscriminatedUnion<[
1201
1569
  hostWall: z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>;
1202
1570
  position: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>;
1203
1571
  facing: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1572
+ hinge: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1204
1573
  label: z.ZodOptional<z.ZodString>;
1205
1574
  width: z.ZodOptional<z.ZodNumber>;
1206
1575
  height: z.ZodOptional<z.ZodNumber>;
@@ -1211,6 +1580,7 @@ export declare const PluginDesignCreateOpeningOptions: z.ZodDiscriminatedUnion<[
1211
1580
  hostWall: z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>;
1212
1581
  position: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>;
1213
1582
  facing: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1583
+ hinge: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodString>, z.ZodTransform<import("../../..").Handle<"vec3">, string>>>;
1214
1584
  label: z.ZodOptional<z.ZodString>;
1215
1585
  width: z.ZodOptional<z.ZodNumber>;
1216
1586
  height: z.ZodOptional<z.ZodNumber>;
@@ -1371,4 +1741,7 @@ export declare const PluginCreateSpaceItem: z.ZodObject<{
1371
1741
  storey: z.ZodOptional<z.ZodNumber>;
1372
1742
  }, z.core.$strip>;
1373
1743
  export type PluginCreateSpaceItem = z.infer<typeof PluginCreateSpaceItem>;
1744
+ export * from "./opening-fields";
1745
+ export * from "./bulk-items";
1746
+ export * from "./grids";
1374
1747
  //# sourceMappingURL=index.d.ts.map