@snaptrude/plugin-core 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/api-manifest.full.json +7703 -0
  3. package/api-manifest.json +2946 -259
  4. package/dist/api/analysis/daylight.d.ts +603 -0
  5. package/dist/api/analysis/daylight.d.ts.map +1 -0
  6. package/dist/api/analysis/heatmaps.d.ts +438 -14
  7. package/dist/api/analysis/heatmaps.d.ts.map +1 -1
  8. package/dist/api/analysis/index.d.ts +15 -0
  9. package/dist/api/analysis/index.d.ts.map +1 -1
  10. package/dist/api/analysis/solar.d.ts +249 -0
  11. package/dist/api/analysis/solar.d.ts.map +1 -0
  12. package/dist/api/analysis/weather.d.ts +193 -0
  13. package/dist/api/analysis/weather.d.ts.map +1 -0
  14. package/dist/api/core/camera/index.d.ts +245 -0
  15. package/dist/api/core/camera/index.d.ts.map +1 -0
  16. package/dist/api/core/comment/index.d.ts +105 -2
  17. package/dist/api/core/comment/index.d.ts.map +1 -1
  18. package/dist/api/core/geom/create/index.d.ts +331 -14
  19. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  20. package/dist/api/core/geom/delete/index.d.ts +8 -2
  21. package/dist/api/core/geom/delete/index.d.ts.map +1 -1
  22. package/dist/api/core/geom/query/arc.d.ts +5 -5
  23. package/dist/api/core/geom/query/brep.d.ts +18 -18
  24. package/dist/api/core/geom/query/circle.d.ts +18 -18
  25. package/dist/api/core/geom/query/contour.d.ts +20 -20
  26. package/dist/api/core/geom/query/curve.d.ts +49 -49
  27. package/dist/api/core/geom/query/edge.d.ts +5 -5
  28. package/dist/api/core/geom/query/face.d.ts +16 -16
  29. package/dist/api/core/geom/query/halfedge.d.ts +8 -8
  30. package/dist/api/core/geom/query/profile.d.ts +19 -19
  31. package/dist/api/core/geom/query/vertex.d.ts +8 -8
  32. package/dist/api/core/geom/update/contour.d.ts +14 -14
  33. package/dist/api/core/geom/update/curve.d.ts +7 -7
  34. package/dist/api/core/geom/update/profile.d.ts +16 -16
  35. package/dist/api/core/handles/index.d.ts +210 -0
  36. package/dist/api/core/handles/index.d.ts.map +1 -0
  37. package/dist/api/core/index.d.ts +24 -0
  38. package/dist/api/core/index.d.ts.map +1 -1
  39. package/dist/api/core/io/export/index.d.ts +134 -0
  40. package/dist/api/core/io/export/index.d.ts.map +1 -0
  41. package/dist/api/core/io/import/index.d.ts +62 -1
  42. package/dist/api/core/io/import/index.d.ts.map +1 -1
  43. package/dist/api/core/io/index.d.ts +5 -0
  44. package/dist/api/core/io/index.d.ts.map +1 -1
  45. package/dist/api/core/layers.d.ts +7 -7
  46. package/dist/api/core/mode/index.d.ts +99 -0
  47. package/dist/api/core/mode/index.d.ts.map +1 -0
  48. package/dist/api/core/proposals/index.d.ts +65 -9
  49. package/dist/api/core/proposals/index.d.ts.map +1 -1
  50. package/dist/api/core/storeys/index.d.ts +251 -0
  51. package/dist/api/core/storeys/index.d.ts.map +1 -0
  52. package/dist/api/core/tags.d.ts +24 -0
  53. package/dist/api/core/tags.d.ts.map +1 -1
  54. package/dist/api/core/user.d.ts +44 -0
  55. package/dist/api/core/user.d.ts.map +1 -0
  56. package/dist/api/core/zoom/index.d.ts +4 -0
  57. package/dist/api/core/zoom/index.d.ts.map +1 -1
  58. package/dist/api/design/boolean/index.d.ts +4 -4
  59. package/dist/api/design/create/index.d.ts +253 -47
  60. package/dist/api/design/create/index.d.ts.map +1 -1
  61. package/dist/api/design/delete/index.d.ts +3 -0
  62. package/dist/api/design/delete/index.d.ts.map +1 -1
  63. package/dist/api/design/doors/index.d.ts +36 -0
  64. package/dist/api/design/doors/index.d.ts.map +1 -1
  65. package/dist/api/design/edit/index.d.ts +1 -1
  66. package/dist/api/design/erase/index.d.ts +2 -2
  67. package/dist/api/design/furniture/index.d.ts +114 -3
  68. package/dist/api/design/furniture/index.d.ts.map +1 -1
  69. package/dist/api/design/index.d.ts +10 -0
  70. package/dist/api/design/index.d.ts.map +1 -1
  71. package/dist/api/design/materials/index.d.ts +111 -14
  72. package/dist/api/design/materials/index.d.ts.map +1 -1
  73. package/dist/api/design/query/geometry/index.d.ts +112 -0
  74. package/dist/api/design/query/geometry/index.d.ts.map +1 -1
  75. package/dist/api/design/query/index.d.ts +35 -1
  76. package/dist/api/design/query/index.d.ts.map +1 -1
  77. package/dist/api/design/query/referenceLines.d.ts +45 -0
  78. package/dist/api/design/query/referenceLines.d.ts.map +1 -0
  79. package/dist/api/design/query/spaces.d.ts +178 -5
  80. package/dist/api/design/query/spaces.d.ts.map +1 -1
  81. package/dist/api/design/transform/index.d.ts +95 -14
  82. package/dist/api/design/transform/index.d.ts.map +1 -1
  83. package/dist/api/design/types/index.d.ts +181 -0
  84. package/dist/api/design/types/index.d.ts.map +1 -0
  85. package/dist/api/design/update/index.d.ts +385 -2
  86. package/dist/api/design/update/index.d.ts.map +1 -1
  87. package/dist/api/design/visibility.d.ts +98 -0
  88. package/dist/api/design/visibility.d.ts.map +1 -0
  89. package/dist/api/entity/buildableEnvelope.d.ts +4 -0
  90. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
  91. package/dist/api/entity/referenceLine.d.ts +10 -2
  92. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  93. package/dist/api/entity/space.d.ts +19 -19
  94. package/dist/api/entity/story.d.ts +148 -15
  95. package/dist/api/entity/story.d.ts.map +1 -1
  96. package/dist/api/index.d.ts +5 -0
  97. package/dist/api/index.d.ts.map +1 -1
  98. package/dist/api/presentation/annotate.d.ts +448 -0
  99. package/dist/api/presentation/annotate.d.ts.map +1 -0
  100. package/dist/api/presentation/diagrams.d.ts +49 -8
  101. package/dist/api/presentation/diagrams.d.ts.map +1 -1
  102. package/dist/api/presentation/export.d.ts +108 -0
  103. package/dist/api/presentation/export.d.ts.map +1 -0
  104. package/dist/api/presentation/import.d.ts +6 -0
  105. package/dist/api/presentation/import.d.ts.map +1 -1
  106. package/dist/api/presentation/index.d.ts +47 -0
  107. package/dist/api/presentation/index.d.ts.map +1 -1
  108. package/dist/api/presentation/placedViews.d.ts +370 -0
  109. package/dist/api/presentation/placedViews.d.ts.map +1 -0
  110. package/dist/api/presentation/shapes.d.ts +481 -0
  111. package/dist/api/presentation/shapes.d.ts.map +1 -0
  112. package/dist/api/presentation/sheets.d.ts +410 -13
  113. package/dist/api/presentation/sheets.d.ts.map +1 -1
  114. package/dist/api/presentation/views.d.ts +165 -10
  115. package/dist/api/presentation/views.d.ts.map +1 -1
  116. package/dist/api/program/areas.d.ts +63 -3
  117. package/dist/api/program/areas.d.ts.map +1 -1
  118. package/dist/api/program/cores.d.ts +3 -99
  119. package/dist/api/program/cores.d.ts.map +1 -1
  120. package/dist/api/program/index.d.ts +2 -2
  121. package/dist/api/program/index.d.ts.map +1 -1
  122. package/dist/api/program/layout.d.ts +172 -12
  123. package/dist/api/program/layout.d.ts.map +1 -1
  124. package/dist/api/program/site.d.ts +105 -8
  125. package/dist/api/program/site.d.ts.map +1 -1
  126. package/dist/api/program/spreadsheet.d.ts +365 -41
  127. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  128. package/dist/api/workspace/index.d.ts +460 -0
  129. package/dist/api/workspace/index.d.ts.map +1 -0
  130. package/dist/handles.d.ts +64 -25
  131. package/dist/handles.d.ts.map +1 -1
  132. package/dist/index.cjs +3210 -1671
  133. package/dist/index.cjs.map +1 -1
  134. package/dist/index.js +3008 -1666
  135. package/dist/index.js.map +1 -1
  136. package/package.json +3 -2
  137. package/scripts/generate-manifest.mjs +45 -0
  138. package/src/api/analysis/daylight.ts +470 -0
  139. package/src/api/analysis/heatmaps.ts +444 -17
  140. package/src/api/analysis/index.ts +15 -0
  141. package/src/api/analysis/solar.ts +237 -0
  142. package/src/api/analysis/weather.ts +179 -0
  143. package/src/api/core/camera/index.ts +251 -0
  144. package/src/api/core/comment/index.ts +120 -2
  145. package/src/api/core/geom/create/index.ts +344 -1
  146. package/src/api/core/geom/delete/index.ts +6 -0
  147. package/src/api/core/handles/index.ts +233 -0
  148. package/src/api/core/index.ts +24 -0
  149. package/src/api/core/io/export/index.ts +126 -0
  150. package/src/api/core/io/import/index.ts +64 -0
  151. package/src/api/core/io/index.ts +5 -0
  152. package/src/api/core/mode/index.ts +96 -0
  153. package/src/api/core/proposals/index.ts +71 -11
  154. package/src/api/core/storeys/index.ts +279 -0
  155. package/src/api/core/tags.ts +27 -0
  156. package/src/api/core/user.ts +46 -0
  157. package/src/api/core/zoom/index.ts +4 -0
  158. package/src/api/design/create/index.ts +303 -36
  159. package/src/api/design/delete/index.ts +3 -0
  160. package/src/api/design/doors/index.ts +40 -0
  161. package/src/api/design/furniture/index.ts +127 -3
  162. package/src/api/design/index.ts +10 -0
  163. package/src/api/design/materials/index.ts +157 -30
  164. package/src/api/design/query/geometry/index.ts +125 -3
  165. package/src/api/design/query/index.ts +37 -7
  166. package/src/api/design/query/referenceLines.ts +52 -0
  167. package/src/api/design/query/spaces.ts +143 -0
  168. package/src/api/design/transform/index.ts +101 -12
  169. package/src/api/design/types/index.ts +156 -0
  170. package/src/api/design/update/index.ts +467 -6
  171. package/src/api/design/visibility.ts +109 -0
  172. package/src/api/entity/buildableEnvelope.ts +4 -0
  173. package/src/api/entity/referenceLine.ts +8 -0
  174. package/src/api/entity/story.ts +161 -15
  175. package/src/api/index.ts +5 -0
  176. package/src/api/presentation/annotate.ts +360 -0
  177. package/src/api/presentation/diagrams.ts +53 -8
  178. package/src/api/presentation/export.ts +108 -0
  179. package/src/api/presentation/import.ts +6 -0
  180. package/src/api/presentation/index.ts +55 -0
  181. package/src/api/presentation/placedViews.ts +363 -0
  182. package/src/api/presentation/shapes.ts +274 -0
  183. package/src/api/presentation/sheets.ts +346 -13
  184. package/src/api/presentation/views.ts +164 -12
  185. package/src/api/program/areas.ts +57 -6
  186. package/src/api/program/cores.ts +3 -91
  187. package/src/api/program/index.ts +2 -2
  188. package/src/api/program/layout.ts +182 -12
  189. package/src/api/program/site.ts +106 -8
  190. package/src/api/program/spreadsheet.ts +376 -35
  191. package/src/api/workspace/index.ts +516 -0
  192. package/src/handles.ts +77 -13
  193. package/tsconfig.json +7 -2
@@ -23,7 +23,8 @@ import { PluginAreaUnit } from "./metrics"
23
23
  *
24
24
  * Plus dataset reads ({@linkcode PluginProgramSpreadsheetApi.getProgram} /
25
25
  * {@linkcode PluginProgramSpreadsheetApi.getTakeoff} — the data the render* methods
26
- * draw), sheet reads ({@linkcode PluginProgramSpreadsheetApi.listSheets} /
26
+ * draw and {@linkcode PluginProgramSpreadsheetApi.getMaterialTakeoff}, surface area
27
+ * per material), sheet reads ({@linkcode PluginProgramSpreadsheetApi.listSheets} /
27
28
  * {@linkcode PluginProgramSpreadsheetApi.getSheetData}), charts + emphasis
28
29
  * ({@linkcode PluginProgramSpreadsheetApi.addChart} /
29
30
  * {@linkcode PluginProgramSpreadsheetApi.highlightCells}), workbook file export
@@ -67,6 +68,12 @@ export abstract class PluginProgramSpreadsheetApi {
67
68
  */
68
69
  public abstract bindings: PluginProgramSpreadsheetBindingsApi
69
70
 
71
+ /**
72
+ * Plugin datasets — named, plugin-supplied row sets that bindings can render
73
+ * and auto-refresh on rerun. See {@linkcode PluginProgramSpreadsheetDatasetsApi}.
74
+ */
75
+ public abstract datasets: PluginProgramSpreadsheetDatasetsApi
76
+
70
77
  /**
71
78
  * Render a titled, formatted table onto a named sheet (create-or-replace).
72
79
  *
@@ -128,13 +135,15 @@ export abstract class PluginProgramSpreadsheetApi {
128
135
  * A specialization of the render* family: the **host pulls and projects the
129
136
  * current takeoff dataset itself** — the plugin supplies only the target
130
137
  * `sheetName`, an optional `title`, and an optional `filter`; there is **no
131
- * data argument**. Returns the same rendered-artifact record as
138
+ * data argument**. The `filter` is applied host-side to the projected rows
139
+ * before rendering. Returns the same rendered-artifact record as
132
140
  * {@linkcode PluginProgramSpreadsheetApi.render}.
133
141
  * _(Authored ahead — optional via the `spreadsheet?` mount until the host
134
142
  * round-trip is live.)_
135
143
  *
136
- * @param options - Optional `sheetName`, `title`, and `filter` (a
137
- * {@linkcode PluginProgramSpreadsheetRenderDatasetArgs}).
144
+ * @param options - Optional `sheetName`, `title`, and `filter` a
145
+ * case-insensitive substring kept when any of a row's cell values contains
146
+ * it (a {@linkcode PluginProgramSpreadsheetRenderDatasetArgs}).
138
147
  * @returns A {@linkcode PluginProgramSpreadsheetRenderResult} with the written
139
148
  * ranges and counts.
140
149
  * @throws If the takeoff cannot be rendered.
@@ -149,9 +158,11 @@ export abstract class PluginProgramSpreadsheetApi {
149
158
  * await snaptrude.program.spreadsheet.renderTakeoff({ sheetName: "Takeoff" })
150
159
  * ```
151
160
  */
152
- public abstract renderTakeoff(
153
- options?: { sheetName?: string; title?: string; filter?: string },
154
- ): PluginApiReturn<PluginProgramSpreadsheetRenderResult>
161
+ public abstract renderTakeoff(options?: {
162
+ sheetName?: string
163
+ title?: string
164
+ filter?: string
165
+ }): PluginApiReturn<PluginProgramSpreadsheetRenderResult>
155
166
 
156
167
  /**
157
168
  * Render the area program onto a sheet.
@@ -159,13 +170,15 @@ export abstract class PluginProgramSpreadsheetApi {
159
170
  * A specialization of the render* family: the **host pulls and projects the
160
171
  * current program dataset itself** (departments with area targets vs allocated)
161
172
  * — the plugin supplies only the target `sheetName`, an optional `title`, and an
162
- * optional `filter`; there is **no data argument**. Returns the same
173
+ * optional `filter`; there is **no data argument**. The `filter` is applied
174
+ * host-side to the projected rows before rendering. Returns the same
163
175
  * rendered-artifact record as {@linkcode PluginProgramSpreadsheetApi.render}.
164
176
  * _(Authored ahead — optional via the `spreadsheet?` mount until the host
165
177
  * round-trip is live.)_
166
178
  *
167
- * @param options - Optional `sheetName`, `title`, and `filter` (a
168
- * {@linkcode PluginProgramSpreadsheetRenderDatasetArgs}).
179
+ * @param options - Optional `sheetName`, `title`, and `filter` a
180
+ * case-insensitive substring kept when any of a row's cell values contains
181
+ * it (a {@linkcode PluginProgramSpreadsheetRenderDatasetArgs}).
169
182
  * @returns A {@linkcode PluginProgramSpreadsheetRenderResult} with the written
170
183
  * ranges and counts.
171
184
  * @throws If the program cannot be rendered.
@@ -180,20 +193,30 @@ export abstract class PluginProgramSpreadsheetApi {
180
193
  * await snaptrude.program.spreadsheet.renderProgram({ sheetName: "Program" })
181
194
  * ```
182
195
  */
183
- public abstract renderProgram(
184
- options?: { sheetName?: string; title?: string; filter?: string },
185
- ): PluginApiReturn<PluginProgramSpreadsheetRenderResult>
196
+ public abstract renderProgram(options?: {
197
+ sheetName?: string
198
+ title?: string
199
+ filter?: string
200
+ }): PluginApiReturn<PluginProgramSpreadsheetRenderResult>
186
201
 
187
202
  /**
188
- * Export the whole report workbook to a file (xlsx, pdf, or csv).
203
+ * Export the report workbook to a file (xlsx, pdf, or csv).
189
204
  *
190
205
  * Returns the file content as base64 so the plugin can download, upload, or
191
206
  * attach it. This is the workbook **file** export; to read cell **values** back
192
207
  * as data, use {@linkcode PluginProgramSpreadsheetApi.getSheetData} instead.
193
208
  *
194
- * @param format - The file format to export the workbook to.
195
- * @param options - Optional `fileName` (without extension); a default is used
196
- * when omitted.
209
+ * `xlsx` and `pdf` export the **whole** workbook. `csv` is inherently
210
+ * single-sheet: it serializes one sheet's used range pass `options.sheetName`
211
+ * to choose which sheet, or omit it to serialize the active sheet.
212
+ *
213
+ * For a different export intent, see `core.io.export.model` (the 3D model
214
+ * file) and `presentation.export` (Present-mode layout sheets to PDF/PNG/JPG).
215
+ *
216
+ * @param format - The file format to export to.
217
+ * @param options - Optional `fileName` (without extension; a default is used
218
+ * when omitted) and `sheetName` — the sheet to serialize for `csv`
219
+ * (ignored by `xlsx`/`pdf`, which always export the whole workbook).
197
220
  * @returns A {@linkcode PluginProgramSpreadsheetExportResult} with the file's
198
221
  * `fileName`, `mimeType`, and base64 `dataBase64`.
199
222
  * @throws If the workbook cannot be serialized to the requested format.
@@ -202,16 +225,20 @@ export abstract class PluginProgramSpreadsheetApi {
202
225
  * @examplePrompt Download the whole workbook as a PDF
203
226
  * @examplePrompt Export the program workbook to xlsx
204
227
  * @examplePrompt Save the report as a csv file
228
+ * @examplePrompt Export the Takeoff sheet as CSV
205
229
  *
206
230
  * # Example
207
231
  * ```ts
208
232
  * const file = await snaptrude.program.spreadsheet.export("xlsx")
209
233
  * // file.fileName, file.mimeType, file.dataBase64
234
+ *
235
+ * // CSV of a specific sheet:
236
+ * const csv = await snaptrude.program.spreadsheet.export("csv", { sheetName: "Takeoff" })
210
237
  * ```
211
238
  */
212
239
  public abstract export(
213
240
  format: PluginSpreadsheetExportFormat,
214
- options?: { fileName?: string },
241
+ options?: { fileName?: string; sheetName?: string },
215
242
  ): PluginApiReturn<PluginProgramSpreadsheetExportResult>
216
243
 
217
244
  /**
@@ -297,6 +324,55 @@ export abstract class PluginProgramSpreadsheetApi {
297
324
  },
298
325
  ): PluginApiReturn<PluginProgramSpreadsheetAddChartResult>
299
326
 
327
+ /**
328
+ * Place a floating image on a workbook sheet from a base64 data URI.
329
+ *
330
+ * The image is anchored at a cell's top-left corner (default `"A1"`) and
331
+ * floats over the grid (a SpreadJS floating picture — it does not occupy
332
+ * cells). Only base64 `data:image/png|jpeg|svg+xml` URIs are accepted —
333
+ * never URLs — and the URI is capped at 2 MB. Passing a `name` gives the
334
+ * picture a stable id: re-running with the same `name` replaces the previous
335
+ * picture (rerun-friendly); when omitted a name is generated.
336
+ *
337
+ * For images on Present-mode sheets (the tldraw canvas), use
338
+ * `presentation.shapes` instead — this verb places floating pictures in the
339
+ * SpreadJS workbook.
340
+ *
341
+ * @param sheetName - Sheet to place the image on.
342
+ * @param image - The image payload: a base64 `dataUri`
343
+ * (`data:image/png|jpeg|svg+xml;base64,…`, max 2 MB).
344
+ * @param options - Optional `anchorCell` (A1 notation, default `"A1"`),
345
+ * `size` in px (intrinsic size when omitted), and stable `name`
346
+ * (replace-on-rerun).
347
+ * @returns A {@linkcode PluginProgramSpreadsheetAddImageResult} with the sheet
348
+ * and the picture's name.
349
+ * @throws If the sheet does not exist, or the data URI is not an accepted
350
+ * image type or exceeds 2 MB.
351
+ *
352
+ * @examplePrompt Add my logo image to the report sheet
353
+ * @examplePrompt Place a PNG at cell B2 on the Takeoff sheet
354
+ * @examplePrompt Put an SVG diagram on a spreadsheet sheet
355
+ * @examplePrompt Insert an image into the workbook
356
+ *
357
+ * # Example
358
+ * ```ts
359
+ * const { name } = await snaptrude.program.spreadsheet.addImage(
360
+ * "Report",
361
+ * { dataUri: "data:image/png;base64,iVBORw0..." },
362
+ * { anchorCell: "B2", size: { width: 240, height: 120 }, name: "logo" },
363
+ * )
364
+ * ```
365
+ */
366
+ public abstract addImage(
367
+ sheetName: string,
368
+ image: { dataUri: string },
369
+ options?: {
370
+ anchorCell?: string
371
+ size?: { width: number; height: number }
372
+ name?: string
373
+ },
374
+ ): PluginApiReturn<PluginProgramSpreadsheetAddImageResult>
375
+
300
376
  /**
301
377
  * Highlight a range of cells (background color and optional emphasis).
302
378
  *
@@ -378,6 +454,38 @@ export abstract class PluginProgramSpreadsheetApi {
378
454
  */
379
455
  public abstract getTakeoff(): PluginApiReturn<PluginProgramSpreadsheetGetTakeoffResult>
380
456
 
457
+ /**
458
+ * Read the material take-off dataset (surface area per material, per element type).
459
+ *
460
+ * The native "Material Take-Off" quantities — the same figures the BIM Take-Off's
461
+ * *Material Take-Off* sheet lists — as render-ready rows: for each material applied
462
+ * to a wall/floor/ceiling/slab/roof family, its rolled-up **surface area** in the
463
+ * project's display units. This is the material-centric complement to
464
+ * {@linkcode PluginProgramSpreadsheetApi.getTakeoff} (which rolls up by element
465
+ * family). A read only — nothing is written and no file is downloaded.
466
+ *
467
+ * When no materials are applied (or the model is empty) the result is simply an
468
+ * empty `rows` array — not an error.
469
+ *
470
+ * @returns A {@linkcode PluginProgramSpreadsheetGetMaterialTakeoffResult} with the
471
+ * material take-off `rows`, a `rowCount`, and the `generatedAt` timestamp.
472
+ *
473
+ * @examplePrompt Get the material take-off
474
+ * @examplePrompt How much of each material is used?
475
+ * @examplePrompt Read the surface area by material
476
+ * @examplePrompt Give me the material quantities before I render them
477
+ * @examplePrompt What's in the material take-off right now?
478
+ *
479
+ * # Example
480
+ * ```ts
481
+ * const mto = await snaptrude.program.spreadsheet.getMaterialTakeoff()
482
+ * for (const row of mto.rows) {
483
+ * console.log(row.objectType, row.family, row.material, row.quantity, row.unit)
484
+ * }
485
+ * ```
486
+ */
487
+ public abstract getMaterialTakeoff(): PluginApiReturn<PluginProgramSpreadsheetGetMaterialTakeoffResult>
488
+
381
489
  // --- Sheet construction (lower-level cell writes; render is the high-level path) ---
382
490
 
383
491
  /**
@@ -597,9 +705,9 @@ export abstract class PluginProgramSpreadsheetApi {
597
705
  * await snaptrude.program.spreadsheet.recalculate()
598
706
  * ```
599
707
  */
600
- public abstract recalculate(
601
- options?: { sheetName?: string },
602
- ): PluginApiReturn<PluginProgramSpreadsheetRecalculateResult>
708
+ public abstract recalculate(options?: {
709
+ sheetName?: string
710
+ }): PluginApiReturn<PluginProgramSpreadsheetRecalculateResult>
603
711
 
604
712
  /**
605
713
  * Run a sequence of sheet operations as one atomic, undoable transaction.
@@ -689,9 +797,9 @@ export abstract class PluginProgramSpreadsheetApi {
689
797
  * const { entries } = await snaptrude.program.spreadsheet.getAuditLog({ limit: 10 })
690
798
  * ```
691
799
  */
692
- public abstract getAuditLog(
693
- options?: { limit?: number },
694
- ): PluginApiReturn<PluginProgramSpreadsheetGetAuditLogResult>
800
+ public abstract getAuditLog(options?: {
801
+ limit?: number
802
+ }): PluginApiReturn<PluginProgramSpreadsheetGetAuditLogResult>
695
803
 
696
804
  /**
697
805
  * Ping the program-mode spreadsheet bridge to check it is reachable.
@@ -839,9 +947,9 @@ export abstract class PluginProgramSpreadsheetBindingsApi {
839
947
  * await snaptrude.program.spreadsheet.bindings.refresh({ name: "takeoff" })
840
948
  * ```
841
949
  */
842
- public abstract refresh(
843
- options?: { name?: string },
844
- ): PluginApiReturn<PluginProgramSpreadsheetBindingsRefreshResult>
950
+ public abstract refresh(options?: {
951
+ name?: string
952
+ }): PluginApiReturn<PluginProgramSpreadsheetBindingsRefreshResult>
845
953
 
846
954
  /**
847
955
  * List all data bindings in the workbook.
@@ -861,6 +969,76 @@ export abstract class PluginProgramSpreadsheetBindingsApi {
861
969
  public abstract list(): PluginApiReturn<PluginProgramSpreadsheetBindingsListResult>
862
970
  }
863
971
 
972
+ /**
973
+ * Program-spreadsheet plugin datasets — named, plugin-supplied row sets stored
974
+ * alongside the workbook so bindings can render and re-render them.
975
+ *
976
+ * A dataset is uploaded with {@linkcode PluginProgramSpreadsheetDatasetsApi.set}
977
+ * (upsert by name). A binding whose source is `{ dataset: "plugin", name }`
978
+ * renders the dataset at its target anchor, and re-renders automatically every
979
+ * time the dataset is set again — the "refresh on rerun" behaviour. Accessed
980
+ * via `snaptrude.program.spreadsheet.datasets`.
981
+ */
982
+ export abstract class PluginProgramSpreadsheetDatasetsApi {
983
+ constructor() {}
984
+
985
+ /**
986
+ * Store (upsert) a named plugin dataset.
987
+ *
988
+ * Re-using a `name` replaces the dataset and automatically refreshes every
989
+ * binding whose source is `{ dataset: "plugin", name }` — no extra plugin
990
+ * calls needed to keep bound ranges current. Limits: at most 10,000 rows and
991
+ * 2 MB serialized.
992
+ *
993
+ * @param name - Dataset name (re-using a name overwrites it).
994
+ * @param columns - Column definitions (see {@linkcode PluginSpreadsheetColumn});
995
+ * their order is the column order bindings render.
996
+ * @param rows - Row objects keyed by column `key`.
997
+ * @returns A {@linkcode PluginProgramSpreadsheetDatasetsSetResult} with the
998
+ * stored row count.
999
+ * @throws If the dataset exceeds 10,000 rows or 2 MB serialized.
1000
+ *
1001
+ * @examplePrompt Store my plugin's rows as a named dataset
1002
+ * @examplePrompt Upload data the sheets can bind to and refresh
1003
+ * @examplePrompt Save a dataset for a live sheet binding
1004
+ * @examplePrompt Push my computed table so a binding keeps it fresh
1005
+ *
1006
+ * # Example
1007
+ * ```ts
1008
+ * await snaptrude.program.spreadsheet.datasets.set(
1009
+ * "costs",
1010
+ * [
1011
+ * { key: "item", header: "Item" },
1012
+ * { key: "cost", header: "Cost", align: "right" },
1013
+ * ],
1014
+ * [{ item: "Concrete", cost: 120 }],
1015
+ * )
1016
+ * ```
1017
+ */
1018
+ public abstract set(
1019
+ name: string,
1020
+ columns: PluginSpreadsheetColumn[],
1021
+ rows: Record<string, PluginSpreadsheetCell>[],
1022
+ ): PluginApiReturn<PluginProgramSpreadsheetDatasetsSetResult>
1023
+
1024
+ /**
1025
+ * List the stored plugin datasets.
1026
+ *
1027
+ * @returns A {@linkcode PluginProgramSpreadsheetDatasetsListResult} with each
1028
+ * dataset's `name`, `rowCount`, and `updatedAt` timestamp.
1029
+ *
1030
+ * @examplePrompt List my plugin datasets
1031
+ * @examplePrompt What datasets are stored for the sheets?
1032
+ * @examplePrompt Show the data sets bindings can use
1033
+ *
1034
+ * # Example
1035
+ * ```ts
1036
+ * const { datasets } = await snaptrude.program.spreadsheet.datasets.list()
1037
+ * ```
1038
+ */
1039
+ public abstract list(): PluginApiReturn<PluginProgramSpreadsheetDatasetsListResult>
1040
+ }
1041
+
864
1042
  /** A single spreadsheet cell value. */
865
1043
  export const PluginSpreadsheetCell = z.union([
866
1044
  z.string(),
@@ -977,7 +1155,7 @@ export type PluginProgramSpreadsheetRenderResult = z.infer<
977
1155
  * |---|---|---|
978
1156
  * | `sheetName` | `string?` | Target sheet name (a default is used when omitted) |
979
1157
  * | `title` | `string?` | Optional title rendered above the table |
980
- * | `filter` | `string?` | Optional dataset-filter expression to narrow the rows |
1158
+ * | `filter` | `string?` | Case-insensitive substring a row is kept when any of its cell values contains it (blank/omitted keeps every row). Not a query language. |
981
1159
  */
982
1160
  export const PluginProgramSpreadsheetRenderDatasetArgs = z.object({
983
1161
  sheetName: z.string().optional(),
@@ -999,12 +1177,14 @@ export type PluginSpreadsheetExportFormat = z.infer<
999
1177
  *
1000
1178
  * | Property | Type | Description |
1001
1179
  * |---|---|---|
1002
- * | `format` | `"xlsx" \| "pdf" \| "csv"` | The file format to export the workbook to |
1180
+ * | `format` | `"xlsx" \| "pdf" \| "csv"` | The file format to export to |
1003
1181
  * | `fileName` | `string?` | Desired file name (without extension); a default is used when omitted |
1182
+ * | `sheetName` | `string?` | For `csv`: the sheet to serialize (the active sheet when omitted). Ignored by `xlsx`/`pdf`. |
1004
1183
  */
1005
1184
  export const PluginProgramSpreadsheetExportArgs = z.object({
1006
1185
  format: PluginSpreadsheetExportFormat,
1007
1186
  fileName: z.string().optional(),
1187
+ sheetName: z.string().optional(),
1008
1188
  })
1009
1189
  export type PluginProgramSpreadsheetExportArgs = z.infer<
1010
1190
  typeof PluginProgramSpreadsheetExportArgs
@@ -1286,6 +1466,50 @@ export type PluginProgramSpreadsheetGetTakeoffResult = z.infer<
1286
1466
  typeof PluginProgramSpreadsheetGetTakeoffResult
1287
1467
  >
1288
1468
 
1469
+ /**
1470
+ * One row in the material take-off dataset. The take-off is grouped by element
1471
+ * object type + family + applied material, so each row is a rolled-up surface
1472
+ * area for that material on that family.
1473
+ *
1474
+ * | Property | Type | Description |
1475
+ * |---|---|---|
1476
+ * | `objectType` | `string` | Element object type the material sits on (`"wall"`, `"floor"`, `"ceiling"`, `"slab"`, `"roof"`) |
1477
+ * | `family` | `string` | Element family the quantity is aggregated under |
1478
+ * | `material` | `string` | Applied material name |
1479
+ * | `quantity` | `number` | Rolled-up surface area in `unit` |
1480
+ * | `unit` | `string` | Area unit (e.g. `"sq.ft"` or `"sq.m"`) |
1481
+ */
1482
+ export const PluginSpreadsheetMaterialTakeoffRow = z.object({
1483
+ objectType: z.string(),
1484
+ family: z.string(),
1485
+ material: z.string(),
1486
+ quantity: z.number(),
1487
+ unit: z.string(),
1488
+ })
1489
+ export type PluginSpreadsheetMaterialTakeoffRow = z.infer<
1490
+ typeof PluginSpreadsheetMaterialTakeoffRow
1491
+ >
1492
+
1493
+ /**
1494
+ * Result of {@linkcode PluginProgramSpreadsheetApi.getMaterialTakeoff} — the native
1495
+ * material take-off dataset (surface area per material). Empty when no materials are
1496
+ * applied.
1497
+ *
1498
+ * | Property | Type | Description |
1499
+ * |---|---|---|
1500
+ * | `rows` | {@linkcode PluginSpreadsheetMaterialTakeoffRow}`[]` | One row per object-type/family/material group |
1501
+ * | `rowCount` | `number` | Number of rows |
1502
+ * | `generatedAt` | `string` | ISO timestamp of when the dataset was read |
1503
+ */
1504
+ export const PluginProgramSpreadsheetGetMaterialTakeoffResult = z.object({
1505
+ rows: z.array(PluginSpreadsheetMaterialTakeoffRow),
1506
+ rowCount: z.number(),
1507
+ generatedAt: z.string(),
1508
+ })
1509
+ export type PluginProgramSpreadsheetGetMaterialTakeoffResult = z.infer<
1510
+ typeof PluginProgramSpreadsheetGetMaterialTakeoffResult
1511
+ >
1512
+
1289
1513
  // --- createSheet -----------------------------------------------------------
1290
1514
 
1291
1515
  /** Behaviour when {@linkcode PluginProgramSpreadsheetApi.createSheet} targets an existing sheet name. */
@@ -1915,16 +2139,18 @@ export type PluginProgramSpreadsheetTemplatesApplyResult = z.infer<
1915
2139
  // --- bindings.* ------------------------------------------------------------
1916
2140
 
1917
2141
  /**
1918
- * A binding's data source. Currently only the takeoff dataset; `program` is
1919
- * reserved for a future source.
2142
+ * A binding's data source the built-in takeoff dataset, or a named plugin
2143
+ * dataset stored via {@linkcode PluginProgramSpreadsheetDatasetsApi.set}.
1920
2144
  *
1921
2145
  * | Property | Type | Description |
1922
2146
  * |---|---|---|
1923
- * | `dataset` | `"takeoff"` | The dataset the binding pulls from |
2147
+ * | `dataset` | `"takeoff" \| "plugin"` | The dataset kind the binding pulls from |
2148
+ * | `name` | `string` | (`"plugin"` only) The stored dataset's name |
1924
2149
  */
1925
- export const PluginSpreadsheetBindingSource = z.object({
1926
- dataset: z.enum(["takeoff"]),
1927
- })
2150
+ export const PluginSpreadsheetBindingSource = z.discriminatedUnion("dataset", [
2151
+ z.object({ dataset: z.literal("takeoff") }),
2152
+ z.object({ dataset: z.literal("plugin"), name: z.string() }),
2153
+ ])
1928
2154
  export type PluginSpreadsheetBindingSource = z.infer<
1929
2155
  typeof PluginSpreadsheetBindingSource
1930
2156
  >
@@ -2073,3 +2299,118 @@ export const PluginProgramSpreadsheetBindingsListResult = z.object({
2073
2299
  export type PluginProgramSpreadsheetBindingsListResult = z.infer<
2074
2300
  typeof PluginProgramSpreadsheetBindingsListResult
2075
2301
  >
2302
+
2303
+ // --- datasets.* ------------------------------------------------------------
2304
+
2305
+ /**
2306
+ * Arguments for {@linkcode PluginProgramSpreadsheetDatasetsApi.set}.
2307
+ *
2308
+ * | Property | Type | Description |
2309
+ * |---|---|---|
2310
+ * | `name` | `string` | Dataset name (re-using a name overwrites it) |
2311
+ * | `columns` | {@linkcode PluginSpreadsheetColumn}`[]` | Column definitions (at least one) |
2312
+ * | `rows` | `Record<string, cell>[]` | Row objects keyed by column `key` (max 10,000) |
2313
+ */
2314
+ export const PluginProgramSpreadsheetDatasetsSetArgs = z.object({
2315
+ name: z.string(),
2316
+ columns: z.array(PluginSpreadsheetColumn).min(1),
2317
+ rows: z.array(z.record(z.string(), PluginSpreadsheetCell)).max(10_000),
2318
+ })
2319
+ export type PluginProgramSpreadsheetDatasetsSetArgs = z.infer<
2320
+ typeof PluginProgramSpreadsheetDatasetsSetArgs
2321
+ >
2322
+
2323
+ /**
2324
+ * Result of {@linkcode PluginProgramSpreadsheetDatasetsApi.set}.
2325
+ *
2326
+ * | Property | Type | Description |
2327
+ * |---|---|---|
2328
+ * | `name` | `string` | The stored dataset's name |
2329
+ * | `rowCount` | `number` | Number of rows stored |
2330
+ */
2331
+ export const PluginProgramSpreadsheetDatasetsSetResult = z.object({
2332
+ name: z.string(),
2333
+ rowCount: z.number(),
2334
+ })
2335
+ export type PluginProgramSpreadsheetDatasetsSetResult = z.infer<
2336
+ typeof PluginProgramSpreadsheetDatasetsSetResult
2337
+ >
2338
+
2339
+ /**
2340
+ * A stored plugin dataset's summary, for
2341
+ * {@linkcode PluginProgramSpreadsheetDatasetsApi.list}.
2342
+ *
2343
+ * | Property | Type | Description |
2344
+ * |---|---|---|
2345
+ * | `name` | `string` | Dataset name |
2346
+ * | `rowCount` | `number` | Number of rows stored |
2347
+ * | `updatedAt` | `string` | ISO timestamp of the last `set` |
2348
+ */
2349
+ export const PluginSpreadsheetDataset = z.object({
2350
+ name: z.string(),
2351
+ rowCount: z.number(),
2352
+ updatedAt: z.string(),
2353
+ })
2354
+ export type PluginSpreadsheetDataset = z.infer<typeof PluginSpreadsheetDataset>
2355
+
2356
+ /**
2357
+ * Result of {@linkcode PluginProgramSpreadsheetDatasetsApi.list}.
2358
+ *
2359
+ * | Property | Type | Description |
2360
+ * |---|---|---|
2361
+ * | `datasets` | {@linkcode PluginSpreadsheetDataset}`[]` | Every stored dataset |
2362
+ */
2363
+ export const PluginProgramSpreadsheetDatasetsListResult = z.object({
2364
+ datasets: z.array(PluginSpreadsheetDataset),
2365
+ })
2366
+ export type PluginProgramSpreadsheetDatasetsListResult = z.infer<
2367
+ typeof PluginProgramSpreadsheetDatasetsListResult
2368
+ >
2369
+
2370
+ // --- addImage --------------------------------------------------------------
2371
+
2372
+ /**
2373
+ * Arguments for {@linkcode PluginProgramSpreadsheetApi.addImage}.
2374
+ *
2375
+ * | Property | Type | Description |
2376
+ * |---|---|---|
2377
+ * | `sheetName` | `string` | Sheet to place the image on |
2378
+ * | `image` | `{ dataUri: string }` | Base64 `data:image/png\|jpeg\|svg+xml` URI (max 2 MB; URLs rejected) |
2379
+ * | `anchorCell` | `string?` | Anchor cell in A1 notation (default `"A1"`) |
2380
+ * | `size` | `{ width; height }?` | Size in px; intrinsic size when omitted |
2381
+ * | `name` | `string?` | Stable picture id — same name replaces on rerun; generated when omitted |
2382
+ */
2383
+ export const PluginProgramSpreadsheetAddImageArgs = z.object({
2384
+ sheetName: z.string(),
2385
+ image: z.object({
2386
+ dataUri: z
2387
+ .string()
2388
+ .max(2_097_152, "image.dataUri exceeds the 2 MB limit")
2389
+ .regex(
2390
+ /^data:image\/(png|jpeg|svg\+xml);base64,/,
2391
+ "image.dataUri must be a base64 data:image/png, jpeg, or svg+xml URI",
2392
+ ),
2393
+ }),
2394
+ anchorCell: z.string().optional(),
2395
+ size: z.object({ width: z.number(), height: z.number() }).optional(),
2396
+ name: z.string().optional(),
2397
+ })
2398
+ export type PluginProgramSpreadsheetAddImageArgs = z.infer<
2399
+ typeof PluginProgramSpreadsheetAddImageArgs
2400
+ >
2401
+
2402
+ /**
2403
+ * Result of {@linkcode PluginProgramSpreadsheetApi.addImage}.
2404
+ *
2405
+ * | Property | Type | Description |
2406
+ * |---|---|---|
2407
+ * | `sheetName` | `string` | The sheet the image was placed on |
2408
+ * | `name` | `string` | The picture's (stable or generated) name |
2409
+ */
2410
+ export const PluginProgramSpreadsheetAddImageResult = z.object({
2411
+ sheetName: z.string(),
2412
+ name: z.string(),
2413
+ })
2414
+ export type PluginProgramSpreadsheetAddImageResult = z.infer<
2415
+ typeof PluginProgramSpreadsheetAddImageResult
2416
+ >