@snaptrude/plugin-core 0.9.7 → 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/CHANGELOG.md +11 -0
- package/api-manifest.json +222 -4
- package/dist/api/core/tags.d.ts +81 -0
- package/dist/api/core/tags.d.ts.map +1 -1
- package/dist/api/design/create/bulk-items.d.ts +14 -6
- package/dist/api/design/create/bulk-items.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +41 -18
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/create/opening-fields.d.ts +10 -2
- package/dist/api/design/create/opening-fields.d.ts.map +1 -1
- package/dist/api/design/doors/index.d.ts +20 -13
- package/dist/api/design/doors/index.d.ts.map +1 -1
- package/dist/api/program/departments.d.ts +58 -2
- package/dist/api/program/departments.d.ts.map +1 -1
- package/dist/api/program/index.d.ts +16 -6
- package/dist/api/program/index.d.ts.map +1 -1
- package/dist/api/program/labels.d.ts +355 -0
- package/dist/api/program/labels.d.ts.map +1 -0
- package/dist/api/program/metadata.d.ts +328 -0
- package/dist/api/program/metadata.d.ts.map +1 -0
- package/dist/api/program/spreadsheet.d.ts +263 -0
- package/dist/api/program/spreadsheet.d.ts.map +1 -1
- package/dist/index.cjs +1084 -833
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1039 -833
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
- package/src/api/core/tags.ts +76 -0
- package/src/api/design/create/bulk-items.ts +10 -6
- package/src/api/design/create/index.ts +43 -24
- package/src/api/design/create/opening-fields.ts +10 -2
- package/src/api/design/doors/index.ts +20 -13
- package/src/api/program/departments.ts +54 -2
- package/src/api/program/index.ts +16 -6
- package/src/api/program/labels.ts +332 -0
- package/src/api/program/metadata.ts +364 -0
- package/src/api/program/spreadsheet.ts +282 -0
- package/api-manifest.full.json +0 -8442
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snaptrude/plugin-core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -16,17 +16,6 @@
|
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"ts-morph": "^28.0.0",
|
|
21
|
-
"tsup": "^8.5.1",
|
|
22
|
-
"typescript": "^5.5.4"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"zod": "^4.3.6"
|
|
26
|
-
},
|
|
27
|
-
"peerDependencies": {
|
|
28
|
-
"zod": "^3.25.0 || ^4.0.0"
|
|
29
|
-
},
|
|
30
19
|
"scripts": {
|
|
31
20
|
"check-types": "tsc --noEmit",
|
|
32
21
|
"build": "tsup --clean",
|
|
@@ -37,5 +26,16 @@
|
|
|
37
26
|
"generate:manifest:check": "node scripts/generate-manifest.mjs --check",
|
|
38
27
|
"generate:manifest:all": "node scripts/generate-manifest.mjs --all",
|
|
39
28
|
"generate:manifest:all:check": "node scripts/generate-manifest.mjs --all --check"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"ts-morph": "^28.0.0",
|
|
32
|
+
"tsup": "^8.5.1",
|
|
33
|
+
"typescript": "^5.5.4"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"zod": "^4.3.6"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"zod": "^3.25.0 || ^4.0.0"
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|
package/src/api/core/tags.ts
CHANGED
|
@@ -163,6 +163,40 @@ export abstract class PluginCoreTagsApi {
|
|
|
163
163
|
componentId: ComponentHandle,
|
|
164
164
|
): PluginApiReturn<PluginCoreTagsGetTagsForComponentResult>
|
|
165
165
|
|
|
166
|
+
/**
|
|
167
|
+
* List the tags carried by many components in one call.
|
|
168
|
+
*
|
|
169
|
+
* The plural of {@linkcode PluginCoreTagsApi.listForComponent}: pass
|
|
170
|
+
* `componentIds` to read specific components (unknown ids are skipped), or
|
|
171
|
+
* omit it to read **every** taggable component (Mass/Floor space) in the
|
|
172
|
+
* project. Each entry carries the component id and its tags — one per tagged
|
|
173
|
+
* category, with the tag's `color` — so a plugin can color every space by a
|
|
174
|
+
* chosen category's tag in a single round-trip.
|
|
175
|
+
*
|
|
176
|
+
* @param componentIds - Optional `Component.id`s to read; omit for all spaces.
|
|
177
|
+
* @returns A {@linkcode PluginCoreTagsListForComponentsResult} with a
|
|
178
|
+
* `components` array, one entry per component (in input order when
|
|
179
|
+
* `componentIds` is given).
|
|
180
|
+
*
|
|
181
|
+
* @performance One round-trip for any number of components — use this instead of a `listForComponent` loop.
|
|
182
|
+
*
|
|
183
|
+
* @examplePrompt Get the tags of every space with their colors
|
|
184
|
+
* @examplePrompt List the tags on all rooms so I can color them by Occupancy
|
|
185
|
+
* @examplePrompt Which tag does each selected space carry?
|
|
186
|
+
*
|
|
187
|
+
* # Example
|
|
188
|
+
* ```ts
|
|
189
|
+
* const { components } = await snaptrude.core.tags.listForComponents()
|
|
190
|
+
* for (const c of components) {
|
|
191
|
+
* const occupancy = c.tags.find((t) => t.categoryName === "Occupancy")
|
|
192
|
+
* if (occupancy) paint(c.componentId, occupancy.color)
|
|
193
|
+
* }
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
public abstract listForComponents(
|
|
197
|
+
componentIds?: ComponentHandle[],
|
|
198
|
+
): PluginApiReturn<PluginCoreTagsListForComponentsResult>
|
|
199
|
+
|
|
166
200
|
/**
|
|
167
201
|
* List the components carrying a given tag or category.
|
|
168
202
|
*
|
|
@@ -588,6 +622,48 @@ export type PluginCoreTagsGetTagsForComponentResult = z.infer<
|
|
|
588
622
|
typeof PluginCoreTagsGetTagsForComponentResult
|
|
589
623
|
>
|
|
590
624
|
|
|
625
|
+
/**
|
|
626
|
+
* Arguments for {@linkcode PluginCoreTagsApi.listForComponents}.
|
|
627
|
+
*
|
|
628
|
+
* | Property | Type | Description |
|
|
629
|
+
* |---|---|---|
|
|
630
|
+
* | `componentIds` | `ComponentHandle[]?` | Components to read; omit for every taggable component |
|
|
631
|
+
*/
|
|
632
|
+
export const PluginCoreTagsListForComponentsArgs = z.object({
|
|
633
|
+
componentIds: z.array(ComponentHandle).optional(),
|
|
634
|
+
})
|
|
635
|
+
export type PluginCoreTagsListForComponentsArgs = z.infer<
|
|
636
|
+
typeof PluginCoreTagsListForComponentsArgs
|
|
637
|
+
>
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* One component's tags, for {@linkcode PluginCoreTagsApi.listForComponents}.
|
|
641
|
+
*
|
|
642
|
+
* | Property | Type | Description |
|
|
643
|
+
* |---|---|---|
|
|
644
|
+
* | `componentId` | `ComponentHandle` | The component's id |
|
|
645
|
+
* | `tags` | {@linkcode PluginCoreComponentTag}`[]` | Its tags, one per tagged category (empty when none) |
|
|
646
|
+
*/
|
|
647
|
+
export const PluginCoreComponentTags = z.object({
|
|
648
|
+
componentId: ComponentHandle,
|
|
649
|
+
tags: z.array(PluginCoreComponentTag),
|
|
650
|
+
})
|
|
651
|
+
export type PluginCoreComponentTags = z.infer<typeof PluginCoreComponentTags>
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Result of {@linkcode PluginCoreTagsApi.listForComponents}.
|
|
655
|
+
*
|
|
656
|
+
* | Property | Type | Description |
|
|
657
|
+
* |---|---|---|
|
|
658
|
+
* | `components` | {@linkcode PluginCoreComponentTags}`[]` | One entry per component |
|
|
659
|
+
*/
|
|
660
|
+
export const PluginCoreTagsListForComponentsResult = z.object({
|
|
661
|
+
components: z.array(PluginCoreComponentTags),
|
|
662
|
+
})
|
|
663
|
+
export type PluginCoreTagsListForComponentsResult = z.infer<
|
|
664
|
+
typeof PluginCoreTagsListForComponentsResult
|
|
665
|
+
>
|
|
666
|
+
|
|
591
667
|
/**
|
|
592
668
|
* Arguments for {@linkcode PluginCoreTagsApi.listComponents}. Provide exactly one
|
|
593
669
|
* of `tagId`, `categoryId`. `untagged` is valid only with `categoryId`.
|
|
@@ -77,15 +77,17 @@ export type PluginCreateFloorItems = z.infer<typeof PluginCreateFloorItems>
|
|
|
77
77
|
* One door to place via {@linkcode PluginDesignCreateApi.doors} — the same
|
|
78
78
|
* fields as a `"door"` {@linkcode PluginDesignCreateOpeningOptions}, so the
|
|
79
79
|
* size overrides singular {@linkcode PluginDesignCreateApi.door} lacks are
|
|
80
|
-
* available per item. `facing`
|
|
81
|
-
*
|
|
80
|
+
* available per item. `facing` and `hinge` are WORLD POINTS, not directions:
|
|
81
|
+
* `facing` on the side of the wall the door swings open to, `hinge` near the
|
|
82
|
+
* jamb it is hinged on. Rejects unknown fields.
|
|
82
83
|
*
|
|
83
84
|
* | Property | Type | Description |
|
|
84
85
|
* |---|---|---|
|
|
85
86
|
* | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
|
|
86
87
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
|
|
87
88
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
88
|
-
* | `facing` | {@linkcode Vec3Handle}? | World point on the side the door
|
|
89
|
+
* | `facing` | {@linkcode Vec3Handle}? | World point on the side the door swings open to (default engine-chosen) |
|
|
90
|
+
* | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the door is hinged on (default the catalog item's authored side) |
|
|
89
91
|
* | `label` | `string`? | Instance name (optional) |
|
|
90
92
|
* | `width` | `number`? | Width override (Snaptrude units, > 0; default the catalog item's) |
|
|
91
93
|
* | `height` | `number`? | Height override (Snaptrude units, > 0; default the catalog item's) |
|
|
@@ -106,8 +108,9 @@ export type PluginCreateDoorItems = z.infer<typeof PluginCreateDoorItems>
|
|
|
106
108
|
* One window to place via {@linkcode PluginDesignCreateApi.windows} — the same
|
|
107
109
|
* fields as a `"window"` {@linkcode PluginDesignCreateOpeningOptions}.
|
|
108
110
|
* `sillHeight` is a nonnegative Snaptrude-unit distance from the host wall's
|
|
109
|
-
* base to the BOTTOM of the window, not to its center. `facing`
|
|
110
|
-
*
|
|
111
|
+
* base to the BOTTOM of the window, not to its center. `facing` and `hinge`
|
|
112
|
+
* are WORLD POINTS, not directions: `facing` on the side of the wall the
|
|
113
|
+
* window opens to, `hinge` near the jamb it is hinged on. Rejects unknown
|
|
111
114
|
* fields.
|
|
112
115
|
*
|
|
113
116
|
* | Property | Type | Description |
|
|
@@ -115,7 +118,8 @@ export type PluginCreateDoorItems = z.infer<typeof PluginCreateDoorItems>
|
|
|
115
118
|
* | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
|
|
116
119
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
|
|
117
120
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
118
|
-
* | `facing` | {@linkcode Vec3Handle}? | World point on the side the window
|
|
121
|
+
* | `facing` | {@linkcode Vec3Handle}? | World point on the side the window opens to (default engine-chosen) |
|
|
122
|
+
* | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the window is hinged on (default the catalog item's authored side) |
|
|
119
123
|
* | `label` | `string`? | Instance name (optional) |
|
|
120
124
|
* | `width` | `number`? | Width override (Snaptrude units, > 0; default the catalog item's) |
|
|
121
125
|
* | `height` | `number`? | Height override (Snaptrude units, > 0; default the catalog item's) |
|
|
@@ -753,12 +753,15 @@ export abstract class PluginDesignCreateApi {
|
|
|
753
753
|
* @param catalogId - Library id: team `_id` or general `fullName`
|
|
754
754
|
* @param hostWall - The wall to host the door
|
|
755
755
|
* @param position - World point projected onto the wall to locate the opening
|
|
756
|
-
* @param options - Optional placement options: `label` — instance name
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
*
|
|
760
|
-
*
|
|
761
|
-
*
|
|
756
|
+
* @param options - Optional placement options: `label` — instance name;
|
|
757
|
+
* `hinge` — world point near the jamb the door is hinged on (the door is
|
|
758
|
+
* reflected along the wall so its hinged jamb is the one nearer this
|
|
759
|
+
* point; default the catalog item's authored hinge side)
|
|
760
|
+
* @param facing - World point on the side of the wall the door swings open
|
|
761
|
+
* to (the room it opens into — where the plan symbol draws the swing arc).
|
|
762
|
+
* Any point clearly on that side works (e.g. the room's center). Default:
|
|
763
|
+
* the engine picks a side (nondeterministic when `position` sits on the
|
|
764
|
+
* wall centerline).
|
|
762
765
|
* @returns the {@linkcode ComponentHandle} of the placed door
|
|
763
766
|
* @throws if the catalog id is unknown, the host is not a wall, the source
|
|
764
767
|
* mesh fails to load, or the projected point falls **outside** the host wall
|
|
@@ -769,6 +772,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
769
772
|
* @examplePrompt Insert the entrance door into this wall
|
|
770
773
|
* @examplePrompt Add a door to the wall and call it Entry-01
|
|
771
774
|
* @examplePrompt Add a door that opens into the living room
|
|
775
|
+
* @examplePrompt Put a door here hinged on the north jamb
|
|
772
776
|
*
|
|
773
777
|
* # Example
|
|
774
778
|
* ```ts
|
|
@@ -788,6 +792,14 @@ export abstract class PluginDesignCreateApi {
|
|
|
788
792
|
* undefined,
|
|
789
793
|
* await snaptrude.core.math.vec3.new(3, 0, 9),
|
|
790
794
|
* )
|
|
795
|
+
* // …and hinged on the jamb nearest a point (here the +x end of the opening):
|
|
796
|
+
* const hingedRight = await snaptrude.design.create.door(
|
|
797
|
+
* entry.id,
|
|
798
|
+
* wall,
|
|
799
|
+
* await snaptrude.core.math.vec3.new(3, 0, 5),
|
|
800
|
+
* { hinge: await snaptrude.core.math.vec3.new(3.5, 0, 5) },
|
|
801
|
+
* await snaptrude.core.math.vec3.new(3, 0, 9),
|
|
802
|
+
* )
|
|
791
803
|
* ```
|
|
792
804
|
*
|
|
793
805
|
* @performance For MORE THAN ONE door, call `design.create.doors(items[])` — one host
|
|
@@ -798,7 +810,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
798
810
|
catalogId: string,
|
|
799
811
|
hostWall: ComponentHandle,
|
|
800
812
|
position: Vec3Handle,
|
|
801
|
-
options?: { label?: string },
|
|
813
|
+
options?: { label?: string; hinge?: Vec3Handle },
|
|
802
814
|
facing?: Vec3Handle,
|
|
803
815
|
): PluginApiReturn<ComponentHandle>
|
|
804
816
|
|
|
@@ -821,8 +833,8 @@ export abstract class PluginDesignCreateApi {
|
|
|
821
833
|
* @returns the placed doors as {@linkcode ComponentHandle}`[]`, in input order
|
|
822
834
|
* @throws `VALIDATION` if the items fail the schema (empty array, more than
|
|
823
835
|
* 1000 items, unknown fields, a non-positive `width`/`height`);
|
|
824
|
-
* `HANDLE_INVALID` if a `position` or `
|
|
825
|
-
* released; `PRECONDITION_FAILED` if a catalog id is unknown, a `hostWall`
|
|
836
|
+
* `HANDLE_INVALID` if a `position`, `facing` or `hinge` handle is unknown
|
|
837
|
+
* or released; `PRECONDITION_FAILED` if a catalog id is unknown, a `hostWall`
|
|
826
838
|
* is not a wall / is locked / is not in the active proposal, the projected
|
|
827
839
|
* point falls outside its host wall, or a door tool is active;
|
|
828
840
|
* `OPERATION_FAILED` if a source mesh fails to load or placement fails
|
|
@@ -870,11 +882,14 @@ export abstract class PluginDesignCreateApi {
|
|
|
870
882
|
* @param catalogId - Library id: team `_id` or general `fullName`
|
|
871
883
|
* @param hostWall - The wall to host the window
|
|
872
884
|
* @param position - World point projected onto the wall to locate the opening
|
|
873
|
-
* @param options - Optional placement options: `label` — instance name
|
|
874
|
-
*
|
|
875
|
-
*
|
|
876
|
-
*
|
|
877
|
-
*
|
|
885
|
+
* @param options - Optional placement options: `label` — instance name;
|
|
886
|
+
* `hinge` — world point near the jamb the window is hinged on (same rule
|
|
887
|
+
* as {@linkcode PluginDesignCreateApi.door}; default the catalog item's
|
|
888
|
+
* authored side)
|
|
889
|
+
* @param facing - World point on the side of the wall the window opens to
|
|
890
|
+
* (matters for asymmetric windows, e.g. casement swing) — same convention
|
|
891
|
+
* as {@linkcode PluginDesignCreateApi.door}. Default: the engine picks a
|
|
892
|
+
* side (nondeterministic when `position` sits on the centerline).
|
|
878
893
|
* @returns the {@linkcode ComponentHandle} of the placed window
|
|
879
894
|
* @throws if the catalog id is unknown, the host is not a wall, the source
|
|
880
895
|
* mesh fails to load, or the projected point falls **outside** the host wall
|
|
@@ -906,7 +921,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
906
921
|
catalogId: string,
|
|
907
922
|
hostWall: ComponentHandle,
|
|
908
923
|
position: Vec3Handle,
|
|
909
|
-
options?: { label?: string },
|
|
924
|
+
options?: { label?: string; hinge?: Vec3Handle },
|
|
910
925
|
facing?: Vec3Handle,
|
|
911
926
|
): PluginApiReturn<ComponentHandle>
|
|
912
927
|
|
|
@@ -931,8 +946,8 @@ export abstract class PluginDesignCreateApi {
|
|
|
931
946
|
* @returns the placed windows as {@linkcode ComponentHandle}`[]`, in input order
|
|
932
947
|
* @throws `VALIDATION` if the items fail the schema (empty array, more than
|
|
933
948
|
* 1000 items, unknown fields, a non-positive `width`/`height`, a negative
|
|
934
|
-
* `sillHeight`); `HANDLE_INVALID` if a `position` or `
|
|
935
|
-
* unknown or released; `PRECONDITION_FAILED` if a catalog id is unknown, a
|
|
949
|
+
* `sillHeight`); `HANDLE_INVALID` if a `position`, `facing` or `hinge`
|
|
950
|
+
* handle is unknown or released; `PRECONDITION_FAILED` if a catalog id is unknown, a
|
|
936
951
|
* `hostWall` is not a wall / is locked / is not in the active proposal, the
|
|
937
952
|
* projected point falls outside its host wall, or a window tool is active;
|
|
938
953
|
* `OPERATION_FAILED` if a source mesh fails to load or placement fails
|
|
@@ -975,7 +990,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
975
990
|
* its center. Placement is asynchronous and committed as one undoable creation.
|
|
976
991
|
*
|
|
977
992
|
* @param options - Opening kind, catalog and host references, placement, and
|
|
978
|
-
* optional facing, label, and dimensions
|
|
993
|
+
* optional facing (swing side), hinge (hinged jamb), label, and dimensions
|
|
979
994
|
* @returns the {@linkcode ComponentHandle} of the placed door or window
|
|
980
995
|
* @throws if the options are invalid, the catalog id is unknown, the host is
|
|
981
996
|
* not a wall, loading fails, or the opening cannot be placed on the host
|
|
@@ -1576,7 +1591,8 @@ export type PluginDesignCreateFurnitureArgs = z.infer<
|
|
|
1576
1591
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
|
|
1577
1592
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
1578
1593
|
* | `label` | `string`? | Instance name (optional) |
|
|
1579
|
-
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door
|
|
1594
|
+
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the door swings open to (default engine-chosen) |
|
|
1595
|
+
* | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the door is hinged on (default the catalog item's authored side) |
|
|
1580
1596
|
*/
|
|
1581
1597
|
export const PluginDesignCreateDoorArgs = z.object({
|
|
1582
1598
|
catalogId: z.string().min(1),
|
|
@@ -1584,12 +1600,13 @@ export const PluginDesignCreateDoorArgs = z.object({
|
|
|
1584
1600
|
position: Vec3Handle,
|
|
1585
1601
|
label: z.string().optional(),
|
|
1586
1602
|
facing: Vec3Handle.optional(),
|
|
1603
|
+
hinge: Vec3Handle.optional(),
|
|
1587
1604
|
})
|
|
1588
1605
|
export type PluginDesignCreateDoorArgs = z.infer<
|
|
1589
1606
|
typeof PluginDesignCreateDoorArgs
|
|
1590
1607
|
>
|
|
1591
|
-
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
|
|
1592
|
-
// door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
|
|
1608
|
+
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg, hinge rides in options:
|
|
1609
|
+
// door(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label?, hinge? }, facing?: Vec3Handle)
|
|
1593
1610
|
|
|
1594
1611
|
// ---------------------------------------------------------------------------
|
|
1595
1612
|
// window
|
|
@@ -1604,7 +1621,8 @@ export type PluginDesignCreateDoorArgs = z.infer<
|
|
|
1604
1621
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
|
|
1605
1622
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
1606
1623
|
* | `label` | `string`? | Instance name (optional) |
|
|
1607
|
-
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window
|
|
1624
|
+
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the window opens to (default engine-chosen) |
|
|
1625
|
+
* | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the window is hinged on (default the catalog item's authored side) |
|
|
1608
1626
|
*/
|
|
1609
1627
|
export const PluginDesignCreateWindowArgs = z.object({
|
|
1610
1628
|
catalogId: z.string().min(1),
|
|
@@ -1612,12 +1630,13 @@ export const PluginDesignCreateWindowArgs = z.object({
|
|
|
1612
1630
|
position: Vec3Handle,
|
|
1613
1631
|
label: z.string().optional(),
|
|
1614
1632
|
facing: Vec3Handle.optional(),
|
|
1633
|
+
hinge: Vec3Handle.optional(),
|
|
1615
1634
|
})
|
|
1616
1635
|
export type PluginDesignCreateWindowArgs = z.infer<
|
|
1617
1636
|
typeof PluginDesignCreateWindowArgs
|
|
1618
1637
|
>
|
|
1619
|
-
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
|
|
1620
|
-
// window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
|
|
1638
|
+
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg, hinge rides in options:
|
|
1639
|
+
// window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label?, hinge? }, facing?: Vec3Handle)
|
|
1621
1640
|
|
|
1622
1641
|
// ---------------------------------------------------------------------------
|
|
1623
1642
|
// opening
|
|
@@ -6,14 +6,21 @@ import { ComponentHandle, Vec3Handle } from "../../../handles"
|
|
|
6
6
|
* {@linkcode PluginDesignCreateOpeningOptions} and by the bulk item schemas in
|
|
7
7
|
* `bulk-items.ts`, so singular and plural openings validate identically.
|
|
8
8
|
*
|
|
9
|
-
* `facing`
|
|
9
|
+
* `facing` and `hinge` are WORLD POINTS, not directions: `facing` sits on the
|
|
10
|
+
* side of the wall the leaf swings open to (where the plan symbol draws the
|
|
11
|
+
* swing arc); `hinge` sits near the jamb the leaf is hinged on — the item is
|
|
12
|
+
* reflected along the wall so its hinged jamb is the one nearer that point.
|
|
13
|
+
* Either may be omitted (engine-chosen side / the catalog item's authored
|
|
14
|
+
* hinge side). Neither has a visible effect on symmetric items such as
|
|
15
|
+
* sliders or fixed windows.
|
|
10
16
|
*
|
|
11
17
|
* | Property | Type | Description |
|
|
12
18
|
* |---|---|---|
|
|
13
19
|
* | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
|
|
14
20
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the opening |
|
|
15
21
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
16
|
-
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the opening
|
|
22
|
+
* | `facing` | {@linkcode Vec3Handle}? | World point on the side of the wall the opening swings open to (default engine-chosen) |
|
|
23
|
+
* | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the opening is hinged on (default the catalog item's authored side) |
|
|
17
24
|
* | `label` | `string`? | Instance name (optional) |
|
|
18
25
|
* | `width` | `number`? | Width override (Snaptrude units, > 0; default the catalog item's) |
|
|
19
26
|
* | `height` | `number`? | Height override (Snaptrude units, > 0; default the catalog item's) |
|
|
@@ -23,6 +30,7 @@ export const PluginOpeningBaseOptions = {
|
|
|
23
30
|
hostWall: ComponentHandle,
|
|
24
31
|
position: Vec3Handle,
|
|
25
32
|
facing: Vec3Handle.optional(),
|
|
33
|
+
hinge: Vec3Handle.optional(),
|
|
26
34
|
label: z.string().optional(),
|
|
27
35
|
width: z.number().finite().positive().optional(),
|
|
28
36
|
height: z.number().finite().positive().optional(),
|
|
@@ -8,9 +8,11 @@ import { PluginDesignChangeResult } from "../lock"
|
|
|
8
8
|
* `design.create.door`; generic reads (`listDoors`/`getHost`/`getProperties`) live at
|
|
9
9
|
* `design.query.*`. Door targets are {@linkcode ComponentHandle}s.
|
|
10
10
|
*
|
|
11
|
-
* `getSwingDirection` is a DERIVED read (no persisted field) — computed from the
|
|
12
|
-
* mesh
|
|
13
|
-
*
|
|
11
|
+
* `getSwingDirection` is a DERIVED read (no persisted field) — computed from the placed
|
|
12
|
+
* mesh's orientation: stand on the side the door swings open to, facing it; `'left'`
|
|
13
|
+
* when the hinged jamb is on your left. `mirror` reflects the door about one of its own
|
|
14
|
+
* axes (undoable, one command): `'x'` flips the swing side, `'z'` swaps the hinged jamb;
|
|
15
|
+
* `setType` is intentionally absent (the engine has no in-place re-type —
|
|
14
16
|
* it would require delete+recreate).
|
|
15
17
|
*
|
|
16
18
|
* The **catalog** reads (`listCatalogGroups`/`listCatalog`/`getCatalogItem`/`exists`)
|
|
@@ -154,9 +156,11 @@ export abstract class PluginDesignDoorsApi {
|
|
|
154
156
|
public abstract getSupportFloor(door: ComponentHandle): PluginApiReturn<ComponentHandle | null>
|
|
155
157
|
|
|
156
158
|
/**
|
|
157
|
-
* Get a door's swing (hinge) handedness
|
|
158
|
-
*
|
|
159
|
-
*
|
|
159
|
+
* Get a door's swing (hinge) handedness. Stand on the side the door swings
|
|
160
|
+
* open to, facing the door: `'left'` when the hinged jamb is on your left,
|
|
161
|
+
* `'right'` when it is on your right. Derived from the placed mesh's
|
|
162
|
+
* orientation (the same reflection `mirror` and the `hinge` placement option
|
|
163
|
+
* apply), not a persisted field.
|
|
160
164
|
*
|
|
161
165
|
* @param door The door to query
|
|
162
166
|
* @returns `'left'` / `'right'`, or `null` if indeterminate
|
|
@@ -178,11 +182,13 @@ export abstract class PluginDesignDoorsApi {
|
|
|
178
182
|
): PluginApiReturn<"left" | "right" | null>
|
|
179
183
|
|
|
180
184
|
/**
|
|
181
|
-
* Mirror a door
|
|
182
|
-
* other side
|
|
185
|
+
* Mirror a door about its own axes. `'x'` (default) flips the swing side —
|
|
186
|
+
* the door opens to the other side of the wall; `'z'` swaps the hinged jamb
|
|
187
|
+
* (left-hand ↔ right-hand, same swing side); `'y'` turns it upside down.
|
|
188
|
+
* Undoable as a single command.
|
|
183
189
|
*
|
|
184
190
|
* @param door The door to mirror
|
|
185
|
-
* @param axis Reflection axis (optional; default `'x'` — the swing-flip axis)
|
|
191
|
+
* @param axis Reflection axis (optional; default `'x'` — the swing-flip axis; `'z'` — the hinge-jamb axis)
|
|
186
192
|
* @returns The affected door(s)
|
|
187
193
|
*
|
|
188
194
|
* @examplePrompt Flip this door's swing
|
|
@@ -193,10 +199,11 @@ export abstract class PluginDesignDoorsApi {
|
|
|
193
199
|
*
|
|
194
200
|
* # Example
|
|
195
201
|
* ```ts
|
|
196
|
-
* // Flip the selected door's swing — axis defaults to "x"
|
|
197
|
-
* // axis); pass "y" or "z" to reflect across a different axis
|
|
202
|
+
* // Flip the selected door's swing side — axis defaults to "x"
|
|
198
203
|
* const [door] = await snaptrude.design.query.listDoors({ isSelected: true })
|
|
199
204
|
* const { affected } = await snaptrude.design.doors.mirror(door)
|
|
205
|
+
* // …or swap the hinged jamb instead (keeps the swing side)
|
|
206
|
+
* await snaptrude.design.doors.mirror(door, "z")
|
|
200
207
|
* ```
|
|
201
208
|
*/
|
|
202
209
|
public abstract mirror(
|
|
@@ -369,7 +376,7 @@ export const PluginDoorDimensions = z.object({
|
|
|
369
376
|
})
|
|
370
377
|
export type PluginDoorDimensions = z.infer<typeof PluginDoorDimensions>
|
|
371
378
|
|
|
372
|
-
/** Mirror axis — tokens mirror the engine `FlipDirection` verbatim
|
|
379
|
+
/** Mirror axis — tokens mirror the engine `FlipDirection` verbatim: `'x'` flips the swing side, `'z'` swaps the hinged jamb, `'y'` turns the door upside down. */
|
|
373
380
|
export const PluginMirrorAxis = z.enum(["x", "y", "z"])
|
|
374
381
|
export type PluginMirrorAxis = z.infer<typeof PluginMirrorAxis>
|
|
375
382
|
|
|
@@ -379,7 +386,7 @@ export type PluginMirrorAxis = z.infer<typeof PluginMirrorAxis>
|
|
|
379
386
|
* | Property | Type | Description |
|
|
380
387
|
* |---|---|---|
|
|
381
388
|
* | `door` | {@linkcode ComponentHandle} | The door to mirror |
|
|
382
|
-
* | `axis` | {@linkcode PluginMirrorAxis} | Reflection axis (optional; default `'x'` — the swing-flip axis) |
|
|
389
|
+
* | `axis` | {@linkcode PluginMirrorAxis} | Reflection axis (optional; default `'x'` — the swing-flip axis; `'z'` — the hinge-jamb axis) |
|
|
383
390
|
*/
|
|
384
391
|
export const PluginDesignDoorMirrorArgs = z.object({
|
|
385
392
|
door: ComponentHandle,
|
|
@@ -7,7 +7,7 @@ import { ComponentHandle } from "../../handles"
|
|
|
7
7
|
* Program departments — read the department groupings of the active program.
|
|
8
8
|
*
|
|
9
9
|
* In program mode a **department** is a named, colored grouping of spaces with an
|
|
10
|
-
* optional area **target
|
|
10
|
+
* optional gross area **target** and a unit **count** target. This is the program-planning view of departments
|
|
11
11
|
* (their identity, color, and target area); the underlying space geometry is read
|
|
12
12
|
* and edited through the geometry namespaces, not here.
|
|
13
13
|
*
|
|
@@ -203,6 +203,33 @@ export abstract class PluginProgramDepartmentsApi {
|
|
|
203
203
|
units?: PluginAreaUnit,
|
|
204
204
|
): PluginApiReturn<PluginProgramDepartmentsSetTargetAreaResult>
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Set a department's target unit count.
|
|
208
|
+
*
|
|
209
|
+
* The number of units (program blocks) the department is planned for — the
|
|
210
|
+
* count twin of {@linkcode PluginProgramDepartmentsApi.setTargetArea}, stored
|
|
211
|
+
* beside the gross area target on the department. Read it back from
|
|
212
|
+
* {@linkcode PluginProgramDepartmentsApi.get} (`targetCount`).
|
|
213
|
+
*
|
|
214
|
+
* @param departmentId - The id of the department whose count to set.
|
|
215
|
+
* @param targetCount - The target number of units (a non-negative integer).
|
|
216
|
+
* @returns The updated {@linkcode PluginProgramDepartment} with its `units`.
|
|
217
|
+
* @throws If no department has the given id.
|
|
218
|
+
*
|
|
219
|
+
* @examplePrompt Set the Bedrooms department unit count to 12
|
|
220
|
+
* @examplePrompt The program needs 4 clinic blocks — update the department count
|
|
221
|
+
* @examplePrompt Update the target count for department dep_123
|
|
222
|
+
*
|
|
223
|
+
* # Example
|
|
224
|
+
* ```ts
|
|
225
|
+
* await snaptrude.program.departments.setTargetCount("dep_123", 12)
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
public abstract setTargetCount(
|
|
229
|
+
departmentId: string,
|
|
230
|
+
targetCount: number,
|
|
231
|
+
): PluginApiReturn<PluginProgramDepartmentsSetTargetCountResult>
|
|
232
|
+
|
|
206
233
|
/**
|
|
207
234
|
* Delete a department.
|
|
208
235
|
*
|
|
@@ -239,13 +266,15 @@ export abstract class PluginProgramDepartmentsApi {
|
|
|
239
266
|
* | `id` | `string` | Unique department id |
|
|
240
267
|
* | `name` | `string` | Display name |
|
|
241
268
|
* | `color` | `string` | CSS hex color string (e.g. `"#b5e1dc"`) |
|
|
242
|
-
* | `targetArea` | `number \| null` |
|
|
269
|
+
* | `targetArea` | `number \| null` | Gross target area in the response's `units`, or `null` if no target is set |
|
|
270
|
+
* | `targetCount` | `number` | Target number of units / program blocks (`0` when unset) |
|
|
243
271
|
*/
|
|
244
272
|
export const PluginProgramDepartment = z.object({
|
|
245
273
|
id: z.string(),
|
|
246
274
|
name: z.string(),
|
|
247
275
|
color: z.string(),
|
|
248
276
|
targetArea: z.number().nullable(),
|
|
277
|
+
targetCount: z.number(),
|
|
249
278
|
})
|
|
250
279
|
export type PluginProgramDepartment = z.infer<typeof PluginProgramDepartment>
|
|
251
280
|
|
|
@@ -434,6 +463,29 @@ export type PluginProgramDepartmentsSetTargetAreaResult = z.infer<
|
|
|
434
463
|
typeof PluginProgramDepartmentsSetTargetAreaResult
|
|
435
464
|
>
|
|
436
465
|
|
|
466
|
+
/**
|
|
467
|
+
* Arguments for {@linkcode PluginProgramDepartmentsApi.setTargetCount}.
|
|
468
|
+
*
|
|
469
|
+
* | Property | Type | Description |
|
|
470
|
+
* |---|---|---|
|
|
471
|
+
* | `departmentId` | `string` | The id of the department whose count to set |
|
|
472
|
+
* | `targetCount` | `number` | Target number of units (non-negative integer) |
|
|
473
|
+
*/
|
|
474
|
+
export const PluginProgramDepartmentsSetTargetCountArgs = z.object({
|
|
475
|
+
departmentId: z.string(),
|
|
476
|
+
targetCount: z.number().int().nonnegative(),
|
|
477
|
+
})
|
|
478
|
+
export type PluginProgramDepartmentsSetTargetCountArgs = z.infer<
|
|
479
|
+
typeof PluginProgramDepartmentsSetTargetCountArgs
|
|
480
|
+
>
|
|
481
|
+
|
|
482
|
+
/** Result of {@linkcode PluginProgramDepartmentsApi.setTargetCount} — the updated record with `units`. */
|
|
483
|
+
export const PluginProgramDepartmentsSetTargetCountResult =
|
|
484
|
+
PluginProgramDepartmentRecord
|
|
485
|
+
export type PluginProgramDepartmentsSetTargetCountResult = z.infer<
|
|
486
|
+
typeof PluginProgramDepartmentsSetTargetCountResult
|
|
487
|
+
>
|
|
488
|
+
|
|
437
489
|
/**
|
|
438
490
|
* Arguments for {@linkcode PluginProgramDepartmentsApi.delete}.
|
|
439
491
|
*
|
package/src/api/program/index.ts
CHANGED
|
@@ -7,22 +7,26 @@ import { PluginProgramSiteApi } from "./site"
|
|
|
7
7
|
import { PluginProgramCoresApi } from "./cores"
|
|
8
8
|
import { PluginProgramClassificationApi } from "./classification"
|
|
9
9
|
import { PluginProgramAreasApi } from "./areas"
|
|
10
|
+
import { PluginProgramMetadataApi } from "./metadata"
|
|
11
|
+
import { PluginProgramLabelsApi } from "./labels"
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Program-mode planning APIs.
|
|
13
15
|
*
|
|
14
16
|
* The program is the space-planning layer: department groupings with area targets,
|
|
15
|
-
* the
|
|
16
|
-
* that render program/takeoff data to
|
|
17
|
-
* *plan* (intent + targets); the geometry
|
|
18
|
-
* through the geometry namespaces.
|
|
17
|
+
* the labels (program rows) inside them, the metrics that track allocated area
|
|
18
|
+
* against those targets, and the reports that render program/takeoff data to
|
|
19
|
+
* spreadsheet sheets. Reads describe the *plan* (intent + targets); the geometry
|
|
20
|
+
* that realizes the plan is authored through the geometry namespaces.
|
|
19
21
|
*
|
|
20
22
|
* - {@linkcode PluginProgramApi.departments} — Read & edit program departments (groupings + targets)
|
|
23
|
+
* - {@linkcode PluginProgramApi.labels} — Read & edit program labels (program rows: per-type area/count targets)
|
|
24
|
+
* - {@linkcode PluginProgramApi.metadata} — Read & edit program metadata (custom columns) on spaces
|
|
21
25
|
* - {@linkcode PluginProgramApi.adjacency} — Read & compute the department/space adjacency matrix
|
|
22
26
|
* - {@linkcode PluginProgramApi.layout} — Arrange/pack spaces in the envelope
|
|
23
27
|
* - {@linkcode PluginProgramApi.metrics} — Read the area-program summary
|
|
24
28
|
* - {@linkcode PluginProgramApi.areas} — FAR / built-up-area rollup and groupings
|
|
25
|
-
* - {@linkcode PluginProgramApi.spreadsheet} — Render program data to sheets
|
|
29
|
+
* - {@linkcode PluginProgramApi.spreadsheet} — Render program data to sheets, custom grouped sheets, read back
|
|
26
30
|
* - {@linkcode PluginProgramApi.site} — Read site/plot context and read/update Site Analysis
|
|
27
31
|
* - {@linkcode PluginProgramApi.cores} — Read & predicate vertical-circulation cores (reads only)
|
|
28
32
|
* - {@linkcode PluginProgramApi.classification} — Classification catalog + display tags
|
|
@@ -32,6 +36,10 @@ import { PluginProgramAreasApi } from "./areas"
|
|
|
32
36
|
export abstract class PluginProgramApi {
|
|
33
37
|
/** Program departments — groupings, area targets, and space assignment. See {@linkcode PluginProgramDepartmentsApi}. */
|
|
34
38
|
public abstract departments: PluginProgramDepartmentsApi
|
|
39
|
+
/** Program labels — the program rows with per-type area/count targets. See {@linkcode PluginProgramLabelsApi}. */
|
|
40
|
+
public abstract labels: PluginProgramLabelsApi
|
|
41
|
+
/** Program metadata — custom columns and their per-space values. See {@linkcode PluginProgramMetadataApi}. */
|
|
42
|
+
public abstract metadata: PluginProgramMetadataApi
|
|
35
43
|
/** Adjacency matrix — read & compute proximity relationships. See {@linkcode PluginProgramAdjacencyApi}. */
|
|
36
44
|
public abstract adjacency: PluginProgramAdjacencyApi
|
|
37
45
|
/** Arrange/pack spaces in the envelope (async job family). See {@linkcode PluginProgramLayoutApi}. */
|
|
@@ -40,7 +48,7 @@ export abstract class PluginProgramApi {
|
|
|
40
48
|
public abstract metrics: PluginProgramMetricsApi
|
|
41
49
|
/** FAR / built-up-area rollup and groupings. See {@linkcode PluginProgramAreasApi}. */
|
|
42
50
|
public abstract areas: PluginProgramAreasApi
|
|
43
|
-
/** Spreadsheet reports — render tables to sheets,
|
|
51
|
+
/** Spreadsheet reports — render tables to sheets, custom grouped sheets, export, read back. See {@linkcode PluginProgramSpreadsheetApi}. */
|
|
44
52
|
public abstract spreadsheet: PluginProgramSpreadsheetApi
|
|
45
53
|
/** Site/plot context and persisted Site Analysis. See {@linkcode PluginProgramSiteApi}. */
|
|
46
54
|
public abstract site: PluginProgramSiteApi
|
|
@@ -61,3 +69,5 @@ export * from "./site"
|
|
|
61
69
|
export * from "./cores"
|
|
62
70
|
export * from "./classification"
|
|
63
71
|
export * from "./areas"
|
|
72
|
+
export * from "./metadata"
|
|
73
|
+
export * from "./labels"
|