@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
@@ -2,23 +2,54 @@ import * as z from "zod"
2
2
  import { PluginApiReturn } from "../../types"
3
3
 
4
4
  /**
5
- * Presentation diagrams — place diagram images onto sheets.
5
+ * Presentation diagrams — generate program diagrams from the model, and place
6
+ * diagram images onto sheets.
6
7
  *
7
- * {@linkcode PluginPresentationDiagramsApi.place} drops diagram images (by
8
- * URL) onto a sheet and returns the created canvas shape ids (requires Present
9
- * mode to be open). Adjacency data itself is read and computed via
8
+ * {@linkcode PluginPresentationDiagramsApi.generateProgram} runs the Present-mode
9
+ * **Program** action: it reads the project's spaces and departments and creates
10
+ * new layout sheets holding the generated diagram graphics.
11
+ * {@linkcode PluginPresentationDiagramsApi.place} drops ready diagram images (by
12
+ * URL) onto an existing sheet and returns the created canvas shape ids. Both
13
+ * require Present mode to be open. Adjacency data itself is read and computed via
10
14
  * `program.adjacency` (see {@linkcode PluginProgramAdjacencyApi}).
11
15
  *
12
- * A future one-step spec-based `place` which would render a diagram spec
13
- * and place it in a single call — awaits a public generator from the
14
- * documentation engine; until that generator exists, `place` takes ready
15
- * image `urls` (we do not ship a spec-based `place` that would only throw).
16
+ * There is intentionally no `generateAdjacency`: the host's adjacency generator
17
+ * runs its sheet-creation task fire-and-forget internally, so a single call
18
+ * cannot return the sheets it creates. Use the Present-mode Adjacency menu for
19
+ * those, then `place` a pre-rendered adjacency image if you need it via the API.
16
20
  *
17
21
  * Accessed via `snaptrude.presentation.diagrams`.
18
22
  */
19
23
  export abstract class PluginPresentationDiagramsApi {
20
24
  constructor() {}
21
25
 
26
+ /**
27
+ * Generate the program (space + department) diagrams for the current model,
28
+ * creating new layout sheets.
29
+ *
30
+ * Runs the same auto-generation as the Present-mode **Program** action: reads
31
+ * the project's spaces and departments, lays them out to scale, and creates one
32
+ * or more new sheets holding the generated diagram graphics. Unlike
33
+ * {@linkcode PluginPresentationDiagramsApi.place} (which pastes ready image URLs
34
+ * onto an existing sheet), this generates the graphics from the model and
35
+ * creates its own sheets. Requires Present mode to be open.
36
+ *
37
+ * @returns A {@linkcode PluginPresentationDiagramsGenerateResult} with the
38
+ * `sheetIds` of the sheets created.
39
+ * @throws If Present mode is not open, or the model has no spaces/departments to
40
+ * generate from.
41
+ *
42
+ * @examplePrompt Generate the program diagrams for this project
43
+ * @examplePrompt Auto-generate the space and department diagram sheets
44
+ * @examplePrompt Create the program layout sheets from the model
45
+ *
46
+ * # Example
47
+ * ```ts
48
+ * const { sheetIds } = await snaptrude.presentation.diagrams.generateProgram()
49
+ * ```
50
+ */
51
+ public abstract generateProgram(): PluginApiReturn<PluginPresentationDiagramsGenerateResult>
52
+
22
53
  /**
23
54
  * Place diagram images onto a sheet.
24
55
  *
@@ -82,3 +113,17 @@ export const PluginPresentationDiagramsPlaceResult = z.object({
82
113
  export type PluginPresentationDiagramsPlaceResult = z.infer<
83
114
  typeof PluginPresentationDiagramsPlaceResult
84
115
  >
116
+
117
+ /**
118
+ * Result of {@linkcode PluginPresentationDiagramsApi.generateProgram}.
119
+ *
120
+ * | Property | Type | Description |
121
+ * |---|---|---|
122
+ * | `sheetIds` | `string[]` | Ids of the sheets created by the generator |
123
+ */
124
+ export const PluginPresentationDiagramsGenerateResult = z.object({
125
+ sheetIds: z.array(z.string()),
126
+ })
127
+ export type PluginPresentationDiagramsGenerateResult = z.infer<
128
+ typeof PluginPresentationDiagramsGenerateResult
129
+ >
@@ -0,0 +1,108 @@
1
+ import * as z from "zod"
2
+
3
+ /**
4
+ * Presentation export — render the Present-mode layout sheets to a downloadable
5
+ * file (PDF / PNG / JPG) and hand the plugin the bytes as base64.
6
+ *
7
+ * This wraps the same pipeline the Present-mode **Export** dialog drives:
8
+ * each sheet is serialized to an SVG, then either composed into a PDF
9
+ * (svg2pdf/jspdf) or rasterized to a PNG/JPG. Nothing is written to disk
10
+ * host-side — the plugin receives the encoded bytes and decides what to do
11
+ * with them (save, upload, preview).
12
+ *
13
+ * Requires **Present mode to be open** (the documentation editor); the call
14
+ * throws `PRECONDITION_FAILED` when it is not.
15
+ *
16
+ * The result is always a uniform `{ files }` array (see
17
+ * {@linkcode PluginPresentationExportResult}):
18
+ * - `pdf` with `combine` (the default) → a single multi-page file.
19
+ * - `pdf` with `combine: false`, or any `png`/`jpg` → one file per sheet.
20
+ *
21
+ * Accessed via `snaptrude.presentation.export`.
22
+ *
23
+ * For a different export intent, see `core.io.export.model` (the 3D model as a
24
+ * GLB/OBJ/FBX/3DS file) and `program.spreadsheet.export` (the area-program /
25
+ * takeoff workbook as XLSX/PDF/CSV).
26
+ *
27
+ * The schemas and result types live here; the callable method is declared on
28
+ * {@linkcode PluginPresentationApi.export}.
29
+ */
30
+
31
+ /** Output file format: a vector `pdf`, or a rasterized `png` / `jpg`. */
32
+ export const PluginPresentationExportFormat = z.enum(["pdf", "png", "jpg"])
33
+ export type PluginPresentationExportFormat = z.infer<
34
+ typeof PluginPresentationExportFormat
35
+ >
36
+
37
+ /**
38
+ * Target pixel dimensions for a rasterized (`png`/`jpg`) export. Ignored for
39
+ * `pdf`, which stays vector and takes its size from the sheet.
40
+ *
41
+ * | Property | Type | Description |
42
+ * |---|---|---|
43
+ * | `width` | `number` | Output width in pixels |
44
+ * | `height` | `number` | Output height in pixels |
45
+ */
46
+ export const PluginPresentationExportResolution = z.object({
47
+ width: z.number().positive(),
48
+ height: z.number().positive(),
49
+ })
50
+ export type PluginPresentationExportResolution = z.infer<
51
+ typeof PluginPresentationExportResolution
52
+ >
53
+
54
+ /**
55
+ * Arguments for {@linkcode PluginPresentationApi.export}.
56
+ *
57
+ * | Property | Type | Description |
58
+ * |---|---|---|
59
+ * | `format` | `"pdf" \| "png" \| "jpg"` | Output format |
60
+ * | `sheetIds` | `string[] \| undefined` | Sheets to export (all sheets when omitted) |
61
+ * | `combine` | `boolean \| undefined` | PDF only: one multi-page file (default `true`) vs one file per sheet |
62
+ * | `resolution` | {@linkcode PluginPresentationExportResolution}` \| undefined` | Raster target size (`png`/`jpg` only) |
63
+ * | `fileName` | `string \| undefined` | Base file name (without extension) |
64
+ */
65
+ export const PluginPresentationExportArgs = z.object({
66
+ format: PluginPresentationExportFormat,
67
+ sheetIds: z.array(z.string()).optional(),
68
+ combine: z.boolean().optional(),
69
+ resolution: PluginPresentationExportResolution.optional(),
70
+ fileName: z.string().optional(),
71
+ })
72
+ export type PluginPresentationExportArgs = z.infer<
73
+ typeof PluginPresentationExportArgs
74
+ >
75
+
76
+ /**
77
+ * A single exported file.
78
+ *
79
+ * | Property | Type | Description |
80
+ * |---|---|---|
81
+ * | `fileName` | `string` | File name including extension |
82
+ * | `mimeType` | `string` | MIME type (`application/pdf`, `image/png`, `image/jpeg`) |
83
+ * | `dataBase64` | `string` | The file bytes, base64-encoded (no data-URL prefix) |
84
+ */
85
+ export const PluginPresentationExportFile = z.object({
86
+ fileName: z.string(),
87
+ mimeType: z.string(),
88
+ dataBase64: z.string(),
89
+ })
90
+ export type PluginPresentationExportFile = z.infer<
91
+ typeof PluginPresentationExportFile
92
+ >
93
+
94
+ /**
95
+ * Result of {@linkcode PluginPresentationApi.export} — always a `files` array.
96
+ * A combined PDF yields one entry; per-sheet exports yield one entry each, in
97
+ * sheet order.
98
+ *
99
+ * | Property | Type | Description |
100
+ * |---|---|---|
101
+ * | `files` | {@linkcode PluginPresentationExportFile}`[]` | The exported files |
102
+ */
103
+ export const PluginPresentationExportResult = z.object({
104
+ files: z.array(PluginPresentationExportFile),
105
+ })
106
+ export type PluginPresentationExportResult = z.infer<
107
+ typeof PluginPresentationExportResult
108
+ >
@@ -20,6 +20,9 @@ export abstract class PluginPresentationImportApi {
20
20
  /**
21
21
  * Import a reference image onto the current Present sheet.
22
22
  *
23
+ * To place the image as a **scene** underlay to trace over — on a storey,
24
+ * not the Present canvas — use `core.io.import.image` instead.
25
+ *
23
26
  * @param source - The asset to import: exactly one of `url` or `dataUrl`.
24
27
  * @param options - Optional `position` — where to place the image on the
25
28
  * sheet.
@@ -50,6 +53,9 @@ export abstract class PluginPresentationImportApi {
50
53
  *
51
54
  * Each page is converted to vector SVG and placed as a canvas shape.
52
55
  *
56
+ * To bring the PDF into the **scene** as a traceable underlay — on a storey,
57
+ * not the Present canvas — use `core.io.import.pdf` instead.
58
+ *
53
59
  * @param source - The asset to import: exactly one of `url` or `dataUrl`.
54
60
  * @param options - Optional `position` — where to place the pages on the
55
61
  * sheet.
@@ -1,8 +1,17 @@
1
+ import { PluginApiReturn } from "../../types"
1
2
  import { PluginPresentationViewsApi } from "./views"
2
3
  import { PluginPresentationAIInspirationApi } from "./aiInspiration"
3
4
  import { PluginPresentationSheetsApi } from "./sheets"
5
+ import { PluginPresentationPlacedViewsApi } from "./placedViews"
4
6
  import { PluginPresentationDiagramsApi } from "./diagrams"
7
+ import { PluginPresentationAnnotateApi } from "./annotate"
8
+ import { PluginPresentationShapesApi } from "./shapes"
5
9
  import { PluginPresentationImportApi } from "./import"
10
+ import {
11
+ PluginPresentationExportResult,
12
+ type PluginPresentationExportFormat,
13
+ type PluginPresentationExportResolution,
14
+ } from "./export"
6
15
 
7
16
  /**
8
17
  * Presentation APIs — prepare and assemble presentations.
@@ -16,6 +25,7 @@ import { PluginPresentationImportApi } from "./import"
16
25
  *
17
26
  * - {@linkcode PluginPresentationApi.views} — Saved 2D/3D views (list, get, capture, activate, create)
18
27
  * - {@linkcode PluginPresentationApi.sheets} — Layout sheets (list, get, create, place views)
28
+ * - {@linkcode PluginPresentationApi.placedViews} — Views already placed on the canvas (move, scale, crop)
19
29
  * - {@linkcode PluginPresentationApi.diagrams} — Place program/adjacency/site diagram images on sheets
20
30
  * - {@linkcode PluginPresentationApi.import} — Import reference images/PDFs onto the canvas
21
31
  * - {@linkcode PluginPresentationApi.aiInspiration} — Present-mode AI image/video generation
@@ -27,8 +37,14 @@ export abstract class PluginPresentationApi {
27
37
  public abstract views: PluginPresentationViewsApi
28
38
  /** Layout sheets — list/get/create and place views (Present mode). See {@linkcode PluginPresentationSheetsApi}. */
29
39
  public abstract sheets: PluginPresentationSheetsApi
40
+ /** Placed views — layout of the view shapes on the canvas: move/scale/setScale/setCrop (Present mode). See {@linkcode PluginPresentationPlacedViewsApi}. */
41
+ public abstract placedViews: PluginPresentationPlacedViewsApi
30
42
  /** Program/adjacency/site diagrams — place images on sheets. See {@linkcode PluginPresentationDiagramsApi}. */
31
43
  public abstract diagrams: PluginPresentationDiagramsApi
44
+ /** Annotations on Present-mode sheets — text/arrows/notes/geo shapes. See {@linkcode PluginPresentationAnnotateApi}. */
45
+ public abstract annotate: PluginPresentationAnnotateApi
46
+ /** Plugin-owned keyed shapes — upsert/remove/list so reruns update instead of duplicating. See {@linkcode PluginPresentationShapesApi}. */
47
+ public abstract shapes: PluginPresentationShapesApi
32
48
  /** Import reference images/PDFs onto the Present canvas. See {@linkcode PluginPresentationImportApi}. */
33
49
  public abstract import: PluginPresentationImportApi
34
50
  /**
@@ -37,11 +53,50 @@ export abstract class PluginPresentationApi {
37
53
  */
38
54
  public abstract aiInspiration: PluginPresentationAIInspirationApi
39
55
 
56
+ /**
57
+ * Export the presentation's layout sheets to a downloadable file (PDF / PNG /
58
+ * JPG) and return the encoded bytes as base64. Wraps the Present-mode Export
59
+ * dialog pipeline headlessly. Requires Present mode to be open.
60
+ *
61
+ * @param format - Output format: `"pdf"`, `"png"`, or `"jpg"`.
62
+ * @param options - Optional `sheetIds` (all sheets when omitted), `combine`
63
+ * (PDF only — one multi-page file vs one per sheet, default `true`),
64
+ * `resolution` (raster target size for `png`/`jpg`), and `fileName`.
65
+ * @returns A {@linkcode PluginPresentationExportResult} — always a `files`
66
+ * array (one entry for a combined PDF, one per sheet otherwise).
67
+ * @throws If Present mode is not open, a `sheetId` is unknown, or a sheet
68
+ * fails to serialize/encode.
69
+ *
70
+ * @examplePrompt Export the presentation as a PDF
71
+ * @examplePrompt Download all sheets as a single PDF
72
+ * @examplePrompt Export sheet 1 as a PNG
73
+ * @examplePrompt Save the presentation sheets as JPG images
74
+ * @examplePrompt Export these sheets to PDF at high resolution
75
+ *
76
+ * # Example
77
+ * ```ts
78
+ * const { files } = await snaptrude.presentation.export("pdf")
79
+ * ```
80
+ */
81
+ public abstract export(
82
+ format: PluginPresentationExportFormat,
83
+ options?: {
84
+ sheetIds?: string[]
85
+ combine?: boolean
86
+ resolution?: PluginPresentationExportResolution
87
+ fileName?: string
88
+ },
89
+ ): PluginApiReturn<PluginPresentationExportResult>
90
+
40
91
  constructor() {}
41
92
  }
42
93
 
43
94
  export * from "./views"
44
95
  export * from "./sheets"
96
+ export * from "./placedViews"
45
97
  export * from "./diagrams"
98
+ export * from "./annotate"
99
+ export * from "./shapes"
46
100
  export * from "./import"
47
101
  export * from "./aiInspiration"
102
+ export * from "./export"
@@ -0,0 +1,363 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../types"
3
+ import { PluginSheetPosition } from "./sheets"
4
+
5
+ /**
6
+ * Placed views — the view shapes already laid out on the Present canvas.
7
+ *
8
+ * A **placed view** is a saved view that has been dropped onto a layout sheet
9
+ * (or the open canvas) — the live linked view shape
10
+ * {@linkcode PluginPresentationSheetsApi.place} and the Present views panel's
11
+ * drag-drop create. These methods read and edit the **layout** of those
12
+ * shapes: where they sit, how big they are, their architectural scale, and
13
+ * their crop. To refresh a placed view's **content** from the current model,
14
+ * use `sheets.updatePlacedView` — content refresh lives on `sheets`,
15
+ * layout lives here.
16
+ *
17
+ * Reads (`list`) return `[]` when Present mode is closed; `get` and every
18
+ * write require Present mode to be open.
19
+ *
20
+ * Accessed via `snaptrude.presentation.placedViews`.
21
+ */
22
+ export abstract class PluginPresentationPlacedViewsApi {
23
+ constructor() {}
24
+
25
+ /**
26
+ * List the placed views in the presentation.
27
+ *
28
+ * Returns every placed view shape on the Present canvas — those nested on a
29
+ * layout sheet (with that sheet's id) and those sitting loose on the canvas
30
+ * (`sheetId: null`). Pass `sheetId` to list only the views placed on that
31
+ * sheet.
32
+ *
33
+ * @param sheetId - Optional sheet id to filter by.
34
+ * @returns A {@linkcode PluginPresentationPlacedViewsListResult} with a
35
+ * `placedViews` array (empty when Present mode is closed or nothing is
36
+ * placed).
37
+ * @throws If `sheetId` is given but is not a sheet (with Present mode open).
38
+ *
39
+ * @examplePrompt Which views are placed on this sheet?
40
+ * @examplePrompt List all the placed views in the presentation
41
+ * @examplePrompt What's laid out on sheet 2?
42
+ * @examplePrompt Show me every view on the Present canvas
43
+ *
44
+ * # Example
45
+ * ```ts
46
+ * const { placedViews } = await snaptrude.presentation.placedViews.list("sheet_1")
47
+ * ```
48
+ */
49
+ public abstract list(
50
+ sheetId?: string,
51
+ ): PluginApiReturn<PluginPresentationPlacedViewsListResult>
52
+
53
+ /**
54
+ * Get a single placed view by its shape id.
55
+ *
56
+ * `shapeId` is the id `sheets.place` returned (also reported by `list`).
57
+ *
58
+ * @param shapeId - The id of the placed view shape to read.
59
+ * @returns The matching {@linkcode PluginPlacedView}.
60
+ * @throws If Present mode is not open, or `shapeId` is unknown or is not a
61
+ * placed view.
62
+ *
63
+ * @examplePrompt Get the placed view I just dropped on the sheet
64
+ * @examplePrompt Read the position and scale of this placed view
65
+ * @examplePrompt What's the crop on shape_123?
66
+ *
67
+ * # Example
68
+ * ```ts
69
+ * const placed = await snaptrude.presentation.placedViews.get(shapeId)
70
+ * console.log(placed.position, placed.scale)
71
+ * ```
72
+ */
73
+ public abstract get(shapeId: string): PluginApiReturn<PluginPlacedView>
74
+
75
+ /**
76
+ * Move a placed view.
77
+ *
78
+ * Repositions the placed view on its sheet — `position` is the new top-left
79
+ * in sheet coordinates (page coordinates when the view is not on a sheet).
80
+ * Pass `options.sheetId` to move it onto another sheet: the view is
81
+ * reparented to that sheet and then positioned at `position` in the new
82
+ * sheet's coordinates. A grouped placed view (e.g. a sustainability 3D view
83
+ * with its legend) moves as one unit. Requires Present mode to be open.
84
+ *
85
+ * @param shapeId - The placed view shape to move.
86
+ * @param position - New top-left position (sheet-local; page coordinates
87
+ * when off-sheet).
88
+ * @param options - Optional `sheetId` — move the view onto that sheet.
89
+ * @returns The updated {@linkcode PluginPlacedView}.
90
+ * @throws If Present mode is not open, `shapeId` is unknown or is not a
91
+ * placed view, or `options.sheetId` is given but is not a sheet.
92
+ *
93
+ * @examplePrompt Move the site plan view to the top-left of sheet 2
94
+ * @examplePrompt Reposition this placed view to 100, 200
95
+ * @examplePrompt Move the hero perspective onto the cover sheet
96
+ *
97
+ * # Example
98
+ * ```ts
99
+ * await snaptrude.presentation.placedViews.move(shapeId, { x: 50, y: 50 }, {
100
+ * sheetId: "sheet_2",
101
+ * })
102
+ * ```
103
+ */
104
+ public abstract move(
105
+ shapeId: string,
106
+ position: PluginSheetPosition,
107
+ options?: { sheetId?: string },
108
+ ): PluginApiReturn<PluginPlacedView>
109
+
110
+ /**
111
+ * Resize a placed view by a uniform factor.
112
+ *
113
+ * Scales the placed view about its top-left corner — the same resize as
114
+ * dragging a corner handle, aspect ratio held. Works for 2D and 3D views;
115
+ * labels and grouped legends resize with it. For a 2D view the **printed
116
+ * architectural scale changes proportionally** (doubling the size of a
117
+ * 1:100 plan makes it a 1:50 plan) — use
118
+ * {@linkcode PluginPresentationPlacedViewsApi.setScale} to land on an exact
119
+ * standard scale instead. Requires Present mode to be open.
120
+ *
121
+ * @param shapeId - The placed view shape to resize.
122
+ * @param factor - Uniform scale factor, between `0.01` and `100`
123
+ * (`2` doubles the size, `0.5` halves it).
124
+ * @returns The updated {@linkcode PluginPlacedView}.
125
+ * @throws If Present mode is not open, `shapeId` is unknown or is not a
126
+ * placed view, or `factor` is not a finite number between 0.01 and 100.
127
+ *
128
+ * @examplePrompt Make this placed view twice as big
129
+ * @examplePrompt Shrink the placed 3D view to half its size
130
+ * @examplePrompt Scale the placed plan up by 50%
131
+ *
132
+ * # Example
133
+ * ```ts
134
+ * await snaptrude.presentation.placedViews.scale(shapeId, 2)
135
+ * ```
136
+ */
137
+ public abstract scale(
138
+ shapeId: string,
139
+ factor: number,
140
+ ): PluginApiReturn<PluginPlacedView>
141
+
142
+ /**
143
+ * Set a placed view's architectural scale.
144
+ *
145
+ * Applies a standard architectural scale — the same write the placed view's
146
+ * Scale dropdown performs. The view (and its labels) is resized about its
147
+ * top-left corner so it prints at the given scale. `scale` must be one of
148
+ * the standard values for the project's unit system (metric `10, 20, 50,
149
+ * 100, 150, 200, 250, 500, 1000`; imperial e.g. `48` for 1/4″ = 1′, `96`
150
+ * for 1/8″ = 1′, `120` for 1″ = 10′) — the same validation as
151
+ * `sheets.place`. 3D views have no architectural scale — calling this on
152
+ * one throws. Requires Present mode to be open.
153
+ *
154
+ * @param shapeId - The placed view shape to set the scale of.
155
+ * @param scale - A standard scale value for the project's unit system.
156
+ * @returns The updated {@linkcode PluginPlacedView}.
157
+ * @throws If Present mode is not open, `shapeId` is unknown or is not a
158
+ * placed view, `scale` is not a standard value for the project's unit
159
+ * system, or the placed view is a 3D view.
160
+ *
161
+ * @examplePrompt Set the plan to 1:100
162
+ * @examplePrompt Change the placed floor plan to 1:50 scale
163
+ * @examplePrompt Make this view print at quarter-inch scale
164
+ *
165
+ * # Example
166
+ * ```ts
167
+ * await snaptrude.presentation.placedViews.setScale(shapeId, 100) // 1:100
168
+ * ```
169
+ */
170
+ public abstract setScale(
171
+ shapeId: string,
172
+ scale: number,
173
+ ): PluginApiReturn<PluginPlacedView>
174
+
175
+ /**
176
+ * Crop a placed view, or clear its crop.
177
+ *
178
+ * `crop` selects the visible window as **fractions (0–1) of the uncropped
179
+ * view** — `topLeft` must be strictly less than `bottomRight` on both axes.
180
+ * The visible region stays anchored on the page (the same behavior as the
181
+ * interactive crop), labels that fall outside the crop are hidden, and the
182
+ * view's architectural scale is untouched. Pass `null` to clear the crop
183
+ * and restore the full view in its uncropped footprint (the interactive
184
+ * double-click-edge reset). The crop **survives a content refresh**
185
+ * (`sheets.updatePlacedView` recomputes it against the refreshed content
186
+ * and only clears it when the refreshed view no longer overlaps the cropped
187
+ * region). Requires Present mode to be open.
188
+ *
189
+ * @param shapeId - The placed view shape to crop.
190
+ * @param crop - The crop window ({@linkcode PluginPlacedViewCrop},
191
+ * fractions of the uncropped view), or `null` to clear.
192
+ * @returns The updated {@linkcode PluginPlacedView}.
193
+ * @throws If Present mode is not open, `shapeId` is unknown or is not a
194
+ * placed view, or `crop` is not a valid 0–1 rectangle with
195
+ * `topLeft < bottomRight` on both axes.
196
+ *
197
+ * @examplePrompt Crop the placed view to its left half
198
+ * @examplePrompt Crop this view to the top-right quarter
199
+ * @examplePrompt Remove the crop from the placed plan
200
+ *
201
+ * # Example
202
+ * ```ts
203
+ * // keep the left half of the view
204
+ * await snaptrude.presentation.placedViews.setCrop(shapeId, {
205
+ * topLeft: { x: 0, y: 0 },
206
+ * bottomRight: { x: 0.5, y: 1 },
207
+ * })
208
+ * await snaptrude.presentation.placedViews.setCrop(shapeId, null) // clear
209
+ * ```
210
+ */
211
+ public abstract setCrop(
212
+ shapeId: string,
213
+ crop: PluginPlacedViewCrop | null,
214
+ ): PluginApiReturn<PluginPlacedView>
215
+ }
216
+
217
+ /** A point in crop space — fractions (0–1) of the uncropped view. */
218
+ const PluginPlacedViewCropPoint = z.object({
219
+ x: z.number().min(0).max(1),
220
+ y: z.number().min(0).max(1),
221
+ })
222
+
223
+ /**
224
+ * A crop window on a placed view, as fractions (0–1) of the **uncropped**
225
+ * view. `topLeft` must be strictly less than `bottomRight` on both axes.
226
+ *
227
+ * | Property | Type | Description |
228
+ * |---|---|---|
229
+ * | `topLeft` | `{ x: number, y: number }` | Top-left of the visible window (fractions 0–1) |
230
+ * | `bottomRight` | `{ x: number, y: number }` | Bottom-right of the visible window (fractions 0–1) |
231
+ */
232
+ export const PluginPlacedViewCrop = z
233
+ .object({
234
+ topLeft: PluginPlacedViewCropPoint,
235
+ bottomRight: PluginPlacedViewCropPoint,
236
+ })
237
+ .refine(
238
+ (c) => c.topLeft.x < c.bottomRight.x && c.topLeft.y < c.bottomRight.y,
239
+ { message: "topLeft must be strictly less than bottomRight on both axes" },
240
+ )
241
+ export type PluginPlacedViewCrop = z.infer<typeof PluginPlacedViewCrop>
242
+
243
+ /**
244
+ * A view placed on the Present canvas.
245
+ *
246
+ * | Property | Type | Description |
247
+ * |---|---|---|
248
+ * | `shapeId` | `string` | Id of the placed view shape (the id `sheets.place` returns) |
249
+ * | `sheetId` | `string \| null` | The sheet it sits on (`null` when placed loose on the canvas) |
250
+ * | `title` | `string` | The saved view's title |
251
+ * | `viewId` | `string` | Id of the saved view it was placed from |
252
+ * | `position` | {@linkcode PluginSheetPosition} | Top-left position — sheet-local when on a sheet, page coordinates otherwise |
253
+ * | `size` | `{ width: number, height: number }` | Displayed size on the canvas |
254
+ * | `scale` | `number \| null` | Architectural scale (e.g. `100` = 1:100); `null` for 3D views |
255
+ * | `is3d` | `boolean` | Whether it is a 3D view (no architectural scale) |
256
+ * | `rotation` | `number` | Rotation in radians (nonzero only for 3D views) |
257
+ * | `crop` | {@linkcode PluginPlacedViewCrop}` \| null` | Crop window (`null` when uncropped) |
258
+ * | `isUnlinked` | `boolean` | Whether the source proposal was removed (an unlinked view no longer refreshes) |
259
+ */
260
+ export const PluginPlacedView = z.object({
261
+ shapeId: z.string(),
262
+ sheetId: z.string().nullable(),
263
+ title: z.string(),
264
+ viewId: z.string(),
265
+ position: PluginSheetPosition,
266
+ size: z.object({ width: z.number(), height: z.number() }),
267
+ scale: z.number().nullable(),
268
+ is3d: z.boolean(),
269
+ rotation: z.number(),
270
+ crop: PluginPlacedViewCrop.nullable(),
271
+ isUnlinked: z.boolean(),
272
+ })
273
+ export type PluginPlacedView = z.infer<typeof PluginPlacedView>
274
+
275
+ /** Arguments for {@linkcode PluginPresentationPlacedViewsApi.list}. */
276
+ export const PluginPresentationPlacedViewsListArgs = z.object({
277
+ sheetId: z.string().optional(),
278
+ })
279
+ export type PluginPresentationPlacedViewsListArgs = z.infer<
280
+ typeof PluginPresentationPlacedViewsListArgs
281
+ >
282
+
283
+ /** Result of {@linkcode PluginPresentationPlacedViewsApi.list}. */
284
+ export const PluginPresentationPlacedViewsListResult = z.object({
285
+ placedViews: z.array(PluginPlacedView),
286
+ })
287
+ export type PluginPresentationPlacedViewsListResult = z.infer<
288
+ typeof PluginPresentationPlacedViewsListResult
289
+ >
290
+
291
+ /** Arguments for {@linkcode PluginPresentationPlacedViewsApi.get}. */
292
+ export const PluginPresentationPlacedViewsGetArgs = z.object({
293
+ shapeId: z.string(),
294
+ })
295
+ export type PluginPresentationPlacedViewsGetArgs = z.infer<
296
+ typeof PluginPresentationPlacedViewsGetArgs
297
+ >
298
+
299
+ /**
300
+ * Arguments for {@linkcode PluginPresentationPlacedViewsApi.move}.
301
+ *
302
+ * | Property | Type | Description |
303
+ * |---|---|---|
304
+ * | `shapeId` | `string` | The placed view shape to move |
305
+ * | `position` | {@linkcode PluginSheetPosition} | New top-left position (sheet-local; page coordinates when off-sheet) |
306
+ * | `sheetId` | `string`? | Move the view onto this sheet |
307
+ */
308
+ export const PluginPresentationPlacedViewsMoveArgs = z.object({
309
+ shapeId: z.string(),
310
+ position: PluginSheetPosition,
311
+ sheetId: z.string().optional(),
312
+ })
313
+ export type PluginPresentationPlacedViewsMoveArgs = z.infer<
314
+ typeof PluginPresentationPlacedViewsMoveArgs
315
+ >
316
+
317
+ /**
318
+ * Arguments for {@linkcode PluginPresentationPlacedViewsApi.scale}.
319
+ *
320
+ * | Property | Type | Description |
321
+ * |---|---|---|
322
+ * | `shapeId` | `string` | The placed view shape to resize |
323
+ * | `factor` | `number` | Uniform scale factor (0.01–100) |
324
+ */
325
+ export const PluginPresentationPlacedViewsScaleArgs = z.object({
326
+ shapeId: z.string(),
327
+ factor: z.number().finite().min(0.01).max(100),
328
+ })
329
+ export type PluginPresentationPlacedViewsScaleArgs = z.infer<
330
+ typeof PluginPresentationPlacedViewsScaleArgs
331
+ >
332
+
333
+ /**
334
+ * Arguments for {@linkcode PluginPresentationPlacedViewsApi.setScale}.
335
+ *
336
+ * | Property | Type | Description |
337
+ * |---|---|---|
338
+ * | `shapeId` | `string` | The placed view shape to set the scale of |
339
+ * | `scale` | `number` | A standard scale value for the project's unit system |
340
+ */
341
+ export const PluginPresentationPlacedViewsSetScaleArgs = z.object({
342
+ shapeId: z.string(),
343
+ scale: z.number().positive(),
344
+ })
345
+ export type PluginPresentationPlacedViewsSetScaleArgs = z.infer<
346
+ typeof PluginPresentationPlacedViewsSetScaleArgs
347
+ >
348
+
349
+ /**
350
+ * Arguments for {@linkcode PluginPresentationPlacedViewsApi.setCrop}.
351
+ *
352
+ * | Property | Type | Description |
353
+ * |---|---|---|
354
+ * | `shapeId` | `string` | The placed view shape to crop |
355
+ * | `crop` | {@linkcode PluginPlacedViewCrop}` \| null` | The crop window, or `null` to clear |
356
+ */
357
+ export const PluginPresentationPlacedViewsSetCropArgs = z.object({
358
+ shapeId: z.string(),
359
+ crop: PluginPlacedViewCrop.nullable(),
360
+ })
361
+ export type PluginPresentationPlacedViewsSetCropArgs = z.infer<
362
+ typeof PluginPresentationPlacedViewsSetCropArgs
363
+ >