@snaptrude/plugin-core 0.9.9 → 0.9.11

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 (34) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/api-manifest.json +76 -390
  3. package/dist/api/core/mode/index.d.ts +19 -7
  4. package/dist/api/core/mode/index.d.ts.map +1 -1
  5. package/dist/api/design/create/grids.d.ts +132 -0
  6. package/dist/api/design/create/grids.d.ts.map +1 -0
  7. package/dist/api/design/create/index.d.ts +109 -1
  8. package/dist/api/design/create/index.d.ts.map +1 -1
  9. package/dist/api/design/grids.d.ts +237 -0
  10. package/dist/api/design/grids.d.ts.map +1 -0
  11. package/dist/api/design/index.d.ts +4 -0
  12. package/dist/api/design/index.d.ts.map +1 -1
  13. package/dist/api/design/query/grids.d.ts +287 -0
  14. package/dist/api/design/query/grids.d.ts.map +1 -0
  15. package/dist/api/design/query/index.d.ts +29 -0
  16. package/dist/api/design/query/index.d.ts.map +1 -1
  17. package/dist/api/design/update/index.d.ts +74 -0
  18. package/dist/api/design/update/index.d.ts.map +1 -1
  19. package/dist/api/workspace/index.d.ts +49 -2
  20. package/dist/api/workspace/index.d.ts.map +1 -1
  21. package/dist/index.cjs +2163 -1968
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.js +2143 -1973
  24. package/dist/index.js.map +1 -1
  25. package/package.json +13 -13
  26. package/src/api/core/mode/index.ts +19 -7
  27. package/src/api/design/create/grids.ts +137 -0
  28. package/src/api/design/create/index.ts +131 -0
  29. package/src/api/design/grids.ts +237 -0
  30. package/src/api/design/index.ts +5 -0
  31. package/src/api/design/query/grids.ts +197 -0
  32. package/src/api/design/query/index.ts +27 -0
  33. package/src/api/design/update/index.ts +53 -0
  34. package/src/api/workspace/index.ts +51 -2
@@ -0,0 +1,197 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../../types"
3
+ import { CurveHandle, BBoxComponents } from "../../../handles"
4
+ import { PluginReferenceLineStyle } from "../create"
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Records
8
+ // ---------------------------------------------------------------------------
9
+
10
+ /**
11
+ * Visual properties of grid lines — the group's defaults and any per-line
12
+ * overrides share this shape (values mirror the engine's `GridLineProps`).
13
+ *
14
+ * | Property | Type | Description |
15
+ * |---|---|---|
16
+ * | `style` | {@linkcode PluginReferenceLineStyle} | Line style (`"SOLID"` \| `"DASHED"` \| `"DOT_DASH"`) |
17
+ * | `weight` | `number` | Line weight |
18
+ * | `color` | `string` | Line color as a `#rrggbb` hex string |
19
+ * | `showStart` | `boolean` | Whether the start-end tag bubble is shown |
20
+ * | `showEnd` | `boolean` | Whether the end-end tag bubble is shown |
21
+ */
22
+ export const PluginGridLineProps = z.object({
23
+ style: PluginReferenceLineStyle,
24
+ weight: z.number(),
25
+ color: z.string(),
26
+ showStart: z.boolean(),
27
+ showEnd: z.boolean(),
28
+ })
29
+ export type PluginGridLineProps = z.infer<typeof PluginGridLineProps>
30
+
31
+ /**
32
+ * One grid line within a wing.
33
+ *
34
+ * | Property | Type | Description |
35
+ * |---|---|---|
36
+ * | `curve` | {@linkcode CurveHandle} | The line's geometry in **world space** (a line or arc; read coordinates via `core.geom.curve`) |
37
+ * | `tag` | `string` | The line's grid tag (e.g. `"A"`, `"3"`) |
38
+ * | `visible` | `boolean` | Persisted per-line visibility |
39
+ * | `props` | {@linkcode PluginGridLineProps} | **Effective** visual properties (group defaults merged with this line's overrides) |
40
+ * | `overrides` | `Partial<`{@linkcode PluginGridLineProps}`>`? | This line's raw overrides, when any exist |
41
+ */
42
+ export const PluginGridLineRecord = z.object({
43
+ curve: CurveHandle,
44
+ tag: z.string(),
45
+ visible: z.boolean(),
46
+ props: PluginGridLineProps,
47
+ overrides: PluginGridLineProps.partial().optional(),
48
+ })
49
+ export type PluginGridLineRecord = z.infer<typeof PluginGridLineRecord>
50
+
51
+ /**
52
+ * One wing of a grid — a family of parallel lines sharing a local frame.
53
+ * `spacing` and `span` are measured along the wing's local axes in
54
+ * Snaptrude units; line addresses used by mutating APIs are
55
+ * `{ wing, line }` index pairs into these arrays.
56
+ *
57
+ * | Property | Type | Description |
58
+ * |---|---|---|
59
+ * | `spacing` | `number` | Nominal spacing between adjacent lines (Snaptrude units) |
60
+ * | `tagStart` | `string` | First tag of the wing's deterministic tag sequence |
61
+ * | `span` | `{ min: number; max: number }`? | Explicit family length along the wing's line axis, when baked |
62
+ * | `lines` | {@linkcode PluginGridLineRecord}`[]` | The wing's lines, in wing order (index = the `line` address) |
63
+ */
64
+ export const PluginGridWingRecord = z.object({
65
+ spacing: z.number(),
66
+ tagStart: z.string(),
67
+ span: z.object({ min: z.number(), max: z.number() }).optional(),
68
+ lines: z.array(PluginGridLineRecord),
69
+ })
70
+ export type PluginGridWingRecord = z.infer<typeof PluginGridWingRecord>
71
+
72
+ /**
73
+ * Per-storey 2D-plan visibility of a grid.
74
+ *
75
+ * | Property | Type | Description |
76
+ * |---|---|---|
77
+ * | `activeStorey` | `number` | The storey the grid belongs to |
78
+ * | `disabledOnStoreys` | `number[]` | Storeys on whose 2D plan the grid is hidden |
79
+ */
80
+ export const PluginGridStoreyVisibility = z.object({
81
+ activeStorey: z.number(),
82
+ disabledOnStoreys: z.array(z.number()),
83
+ })
84
+ export type PluginGridStoreyVisibility = z.infer<typeof PluginGridStoreyVisibility>
85
+
86
+ // ---------------------------------------------------------------------------
87
+ // get — args & result
88
+ // ---------------------------------------------------------------------------
89
+
90
+ /**
91
+ * Property names readable via {@linkcode PluginDesignQueryGridsApi.get}.
92
+ *
93
+ * | Value | Description |
94
+ * |---|---|
95
+ * | `"angle"` | World rotation about +Y, in **degrees** |
96
+ * | `"props"` | Group-level default line properties |
97
+ * | `"storeyVisibility"` | Active storey + storeys where the grid is hidden in 2D |
98
+ * | `"wings"` | Full wing/line structure with world-space curve handles |
99
+ * | `"bounds"` | World-space axis-aligned bounding box of the grid geometry |
100
+ */
101
+ export const PluginGridGetProperty = z.enum([
102
+ "angle",
103
+ "props",
104
+ "storeyVisibility",
105
+ "wings",
106
+ "bounds",
107
+ ])
108
+ export type PluginGridGetProperty = z.infer<typeof PluginGridGetProperty>
109
+
110
+ /**
111
+ * Arguments for {@linkcode PluginDesignQueryGridsApi.get}.
112
+ *
113
+ * | Property | Type | Description |
114
+ * |---|---|---|
115
+ * | `gridId` | `string` | The grid group ID to query |
116
+ * | `properties` | {@linkcode PluginGridGetProperty}`[]` | Properties to retrieve |
117
+ */
118
+ export const PluginGridGetArgs = z.object({
119
+ gridId: z.string(),
120
+ properties: z.array(PluginGridGetProperty),
121
+ })
122
+ export type PluginGridGetArgs = z.infer<typeof PluginGridGetArgs>
123
+
124
+ /**
125
+ * Result of {@linkcode PluginDesignQueryGridsApi.get} — only the requested
126
+ * properties are present.
127
+ */
128
+ export const PluginGridGetResult = z
129
+ .object({
130
+ angle: z.number(),
131
+ props: PluginGridLineProps,
132
+ storeyVisibility: PluginGridStoreyVisibility,
133
+ wings: z.array(PluginGridWingRecord),
134
+ bounds: BBoxComponents,
135
+ })
136
+ .partial()
137
+ export type PluginGridGetResult = z.infer<typeof PluginGridGetResult>
138
+
139
+ // ---------------------------------------------------------------------------
140
+ // Abstract API
141
+ // ---------------------------------------------------------------------------
142
+
143
+ /**
144
+ * `design.query.grids.*` — structural-grid-specific reads.
145
+ *
146
+ * A **grid** (grid group) is a structural/documentation grid: one or more
147
+ * *wings* (families of parallel lines with a shared local frame), each holding
148
+ * tagged grid *lines* (straight lines, or a lone arc). Enumerate grids with
149
+ * `design.query.listGrids`; read an individual grid's structure here.
150
+ *
151
+ * Lines have no stable identity of their own — mutating APIs address them
152
+ * positionally as `{ wing, line }` index pairs into the `wings` arrays
153
+ * returned by {@linkcode get}. Structural edits (adding/removing lines,
154
+ * count changes) re-index lines; re-query after mutating.
155
+ *
156
+ * Accessed via `snaptrude.design.query.grids`.
157
+ */
158
+ export abstract class PluginDesignQueryGridsApi {
159
+ constructor() {}
160
+
161
+ /**
162
+ * Get properties of a grid by its ID.
163
+ *
164
+ * Only the properties listed in `properties` are returned — unlisted
165
+ * properties will be `undefined` in the result. `wings` is the heavy
166
+ * read (it registers a world-space {@linkcode CurveHandle} per line);
167
+ * request it only when the geometry is needed.
168
+ *
169
+ * Units: `angle` is in **degrees** (positive = CCW about +Y); `spacing`,
170
+ * `span`, `bounds`, and curve coordinates are in **Snaptrude units**,
171
+ * world space.
172
+ *
173
+ * @param gridId - The unique grid group ID
174
+ * @param properties - Array of property names to retrieve. See
175
+ * {@linkcode PluginGridGetProperty}.
176
+ * @returns A partial {@linkcode PluginGridGetResult} containing only the
177
+ * requested properties
178
+ * @throws If the grid does not exist
179
+ *
180
+ * @examplePrompt What is the spacing of this grid?
181
+ * @examplePrompt Read the grid line tags on this structural grid
182
+ * @examplePrompt Get the geometry of every line in this grid
183
+ * @examplePrompt Which storeys is this grid hidden on?
184
+ *
185
+ * # Example
186
+ * ```ts
187
+ * const [grid] = await snaptrude.design.query.listGrids()
188
+ * const { wings } = await snaptrude.design.query.grids.get(grid, ["wings"])
189
+ * // wings[0].lines[0].curve is an opaque CurveHandle in world space;
190
+ * // read its coordinates via `snaptrude.core.geom.curve`.
191
+ * ```
192
+ */
193
+ public abstract get(
194
+ gridId: string,
195
+ properties: z.infer<typeof PluginGridGetProperty>[],
196
+ ): PluginApiReturn<PluginGridGetResult>
197
+ }
@@ -11,6 +11,7 @@ import { PluginStaircasePreset } from "../create"
11
11
  import { PluginDesignQueryGeometryApi } from "./geometry"
12
12
  import { PluginDesignQuerySpacesApi } from "./spaces"
13
13
  import { PluginDesignQueryReferenceLinesApi } from "./referenceLines"
14
+ import { PluginDesignQueryGridsApi } from "./grids"
14
15
 
15
16
  // ---------------------------------------------------------------------------
16
17
  // Entity type vocabulary
@@ -41,6 +42,7 @@ import { PluginDesignQueryReferenceLinesApi } from "./referenceLines"
41
42
  * | `"curtainWall"` | Parametric curtain wall |
42
43
  * | `"mullion"` | Curtain-wall mullion |
43
44
  * | `"panel"` | Curtain-wall panel |
45
+ * | `"grid"` | Structural grid group |
44
46
  */
45
47
  export const PluginEntityType = z.enum([
46
48
  "wall",
@@ -60,6 +62,7 @@ export const PluginEntityType = z.enum([
60
62
  "curtainWall",
61
63
  "mullion",
62
64
  "panel",
65
+ "grid",
63
66
  ])
64
67
  export type PluginEntityType = z.infer<typeof PluginEntityType>
65
68
 
@@ -304,6 +307,8 @@ export abstract class PluginDesignQueryApi {
304
307
  public abstract spaces: PluginDesignQuerySpacesApi
305
308
  /** Reference-line-specific reads. See {@linkcode PluginDesignQueryReferenceLinesApi}. */
306
309
  public abstract referenceLines: PluginDesignQueryReferenceLinesApi
310
+ /** Structural-grid-specific reads. See {@linkcode PluginDesignQueryGridsApi}. */
311
+ public abstract grids: PluginDesignQueryGridsApi
307
312
 
308
313
  constructor() {}
309
314
 
@@ -721,6 +726,27 @@ export abstract class PluginDesignQueryApi {
721
726
  filter?: PluginEntityFilter,
722
727
  ): PluginApiReturn<ComponentHandle[]>
723
728
 
729
+ /**
730
+ * List all the structural grids (grid groups) in the project, optionally
731
+ * filtered by storey, building, selection state, or region.
732
+ *
733
+ * @param filter - an optional {@linkcode PluginEntityFilter}
734
+ * @returns grid-group {@linkcode ComponentHandle}`[]`
735
+ *
736
+ * @examplePrompt List all the structural grids in the model
737
+ * @examplePrompt How many grids are on the ground floor?
738
+ * @examplePrompt Show the grids on this storey
739
+ * @examplePrompt Which grids are currently selected?
740
+ *
741
+ * # Example
742
+ * ```ts
743
+ * const groundFloorGrids = await snaptrude.design.query.listGrids({ storeys: [1] })
744
+ * ```
745
+ */
746
+ public abstract listGrids(
747
+ filter?: PluginEntityFilter,
748
+ ): PluginApiReturn<ComponentHandle[]>
749
+
724
750
  // ── single-entity access & identity ─────────────────────────────────────────
725
751
 
726
752
  /**
@@ -1145,3 +1171,4 @@ export type PluginStoreyOutlineResult = z.infer<
1145
1171
  export * from "./geometry"
1146
1172
  export * from "./spaces"
1147
1173
  export * from "./referenceLines"
1174
+ export * from "./grids"
@@ -15,6 +15,7 @@ import {
15
15
  PluginBuildableEnvelopeVerticalCap,
16
16
  PluginBuildableEnvelopeUpdateResult,
17
17
  } from "../../entity/buildableEnvelope"
18
+ import { PluginGridStyleOptions } from "../create/grids"
18
19
 
19
20
  /**
20
21
  * Sparse property updates for a space. Only provided fields change.
@@ -238,6 +239,27 @@ export type PluginDesignSetStoreyArgs = z.infer<
238
239
  typeof PluginDesignSetStoreyArgs
239
240
  >
240
241
 
242
+ /**
243
+ * The sparse GROUP-LEVEL patch accepted by {@linkcode PluginDesignUpdateApi.grid}.
244
+ * Only provided fields change. Wing- and line-level updates live on the grids
245
+ * entity family: `design.grids.updateWings` / `design.grids.updateLines`.
246
+ */
247
+ export const PluginGridPatch = z.object({
248
+ angle: z.number().finite().optional(),
249
+ props: PluginGridStyleOptions.optional(),
250
+ storeyVisibility: z
251
+ .array(z.object({ storey: z.number().int(), visible: z.boolean() }))
252
+ .optional(),
253
+ })
254
+ export type PluginGridPatch = z.infer<typeof PluginGridPatch>
255
+
256
+ /** Arguments for {@linkcode PluginDesignUpdateApi.grid}. */
257
+ export const PluginDesignUpdateGridArgs = z.object({
258
+ grid: ComponentHandle,
259
+ patch: PluginGridPatch,
260
+ })
261
+ export type PluginDesignUpdateGridArgs = z.infer<typeof PluginDesignUpdateGridArgs>
262
+
241
263
  /**
242
264
  * `snaptrude.design.update` — edit existing scene entities (properties + geometry).
243
265
  *
@@ -290,6 +312,37 @@ export abstract class PluginDesignUpdateApi {
290
312
  label: string,
291
313
  ): PluginApiReturn<boolean>
292
314
 
315
+ /**
316
+ * Update a structural grid's **group-level** fields with a sparse patch —
317
+ * default line styling, absolute angle, and per-storey 2D visibility. Only
318
+ * provided fields change. Wing- and line-level updates live on the grids
319
+ * entity family: {@linkcode PluginDesignGridsApi.updateWings} /
320
+ * {@linkcode PluginDesignGridsApi.updateLines}.
321
+ *
322
+ * Every change routes through the exact setters the native panel uses —
323
+ * each changed field commits its own undoable command, identical to editing
324
+ * that field in the panel. `angle` is an absolute target in degrees (CCW
325
+ * about +Y).
326
+ *
327
+ * @param grid - The grid group to update
328
+ * @param patch - The sparse {@linkcode PluginGridPatch}
329
+ * @returns `true` once applied
330
+ *
331
+ * @examplePrompt Rotate the grid to 45 degrees
332
+ * @examplePrompt Make this grid's lines dashed and grey
333
+ * @examplePrompt Hide this grid on storey 3's plan
334
+ *
335
+ * # Example
336
+ * ```ts
337
+ * const [grid] = await snaptrude.design.query.listGrids()
338
+ * await snaptrude.design.update.grid(grid, { angle: 45, props: { style: "DASHED" } })
339
+ * ```
340
+ */
341
+ public abstract grid(
342
+ grid: ComponentHandle,
343
+ patch: PluginGridPatch,
344
+ ): PluginApiReturn<boolean>
345
+
293
346
  /**
294
347
  * Update a single space (room) — change its properties (room label, space
295
348
  * type, mass type, area class, department) and/or replace its geometry by
@@ -10,13 +10,16 @@ import { PluginApiReturn } from "../../types"
10
10
  * Teams are **read-only** here (no create/invite/delete in v1, a deliberate
11
11
  * safety decision); there are no folders in v1. A `projectId` is the project's
12
12
  * floorkey. Plan limits are enforced by the backend — a limit rejection surfaces
13
- * as a normal host error. It also carries the workspace-level mode switch for
13
+ * as a normal host error. It also carries the workspace-level mode switches for
14
14
  * Present mode ({@linkcode PluginWorkspaceApi.openPresentMode} /
15
- * {@linkcode PluginWorkspaceApi.closePresentMode}).
15
+ * {@linkcode PluginWorkspaceApi.closePresentMode}) and Program mode
16
+ * ({@linkcode PluginWorkspaceApi.openProgramMode} /
17
+ * {@linkcode PluginWorkspaceApi.closeProgramMode}).
16
18
  *
17
19
  * - {@linkcode PluginWorkspaceApi.projects} — Create, copy, list, read & rename projects
18
20
  * - {@linkcode PluginWorkspaceApi.teams} — Read teams and their members
19
21
  * - {@linkcode PluginWorkspaceApi.openPresentMode} / {@linkcode PluginWorkspaceApi.closePresentMode} — Open/close the Present-mode documentation editor
22
+ * - {@linkcode PluginWorkspaceApi.openProgramMode} / {@linkcode PluginWorkspaceApi.closeProgramMode} — Open/close the Program tab (the spreadsheet the `program.spreadsheet.*` calls run in)
20
23
  */
21
24
  export abstract class PluginWorkspaceApi {
22
25
  /** Projects — create, copy, list, read & rename. See {@linkcode PluginWorkspaceProjectsApi}. */
@@ -68,6 +71,52 @@ export abstract class PluginWorkspaceApi {
68
71
  */
69
72
  public abstract closePresentMode(): PluginApiReturn<void>
70
73
 
74
+ /**
75
+ * Open Program mode — the Program tab the `program.spreadsheet.*` calls run in.
76
+ *
77
+ * Runs the top bar's own Program-button sequence (remember the preference,
78
+ * open or re-link the paired Program window) and resolves only once that tab
79
+ * has connected to the editor over its channel, so a `program.spreadsheet.*`
80
+ * call issued right after this resolves finds the tab open. The open happens
81
+ * outside a user gesture, so the browser may block the pop-up; the editor
82
+ * then shows its "Allow pop-up to continue" modal and this call keeps waiting
83
+ * (up to ~90s) for the user to confirm. Idempotent — resolves immediately
84
+ * when the Program tab is already connected, and is a no-op when the plugin is
85
+ * itself running in the Program tab. Write-gated.
86
+ *
87
+ * @throws `PRECONDITION_FAILED` if the user dismisses the pop-up modal or the
88
+ * Program tab does not connect within the timeout.
89
+ *
90
+ * @examplePrompt Open program mode
91
+ * @examplePrompt Open the Program tab so I can build a custom sheet
92
+ * @examplePrompt Switch to the program spreadsheet
93
+ *
94
+ * # Example
95
+ * ```ts
96
+ * await snaptrude.workspace.openProgramMode()
97
+ * const { sheets } = await snaptrude.program.spreadsheet.listSheets()
98
+ * ```
99
+ */
100
+ public abstract openProgramMode(): PluginApiReturn<void>
101
+
102
+ /**
103
+ * Close the Program tab.
104
+ *
105
+ * Idempotent — a no-op when no Program tab is connected. Write-gated, like
106
+ * {@linkcode PluginWorkspaceApi.openProgramMode}.
107
+ *
108
+ * @throws `PRECONDITION_FAILED` if the tab is still connected after ~15s.
109
+ *
110
+ * @examplePrompt Close program mode
111
+ * @examplePrompt Close the Program tab
112
+ *
113
+ * # Example
114
+ * ```ts
115
+ * await snaptrude.workspace.closeProgramMode()
116
+ * ```
117
+ */
118
+ public abstract closeProgramMode(): PluginApiReturn<void>
119
+
71
120
  constructor() {}
72
121
  }
73
122