@snaptrude/plugin-core 0.9.17 → 0.9.18-networks-20261016.1

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 (213) hide show
  1. package/AGENTS.md +231 -231
  2. package/CHANGELOG.md +408 -408
  3. package/CLAUDE.md +11 -11
  4. package/dist/api/analysis/daylight.d.ts +5 -5
  5. package/dist/api/analysis/solar.d.ts +2 -2
  6. package/dist/api/core/camera/index.d.ts +29 -0
  7. package/dist/api/core/camera/index.d.ts.map +1 -1
  8. package/dist/api/core/geom/create/index.d.ts +7 -1
  9. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  10. package/dist/api/core/geom/update/contour.d.ts +8 -2
  11. package/dist/api/core/geom/update/contour.d.ts.map +1 -1
  12. package/dist/api/core/zoom/index.d.ts +13 -0
  13. package/dist/api/core/zoom/index.d.ts.map +1 -1
  14. package/dist/api/design/bim.d.ts +209 -0
  15. package/dist/api/design/bim.d.ts.map +1 -0
  16. package/dist/api/design/boolean/index.d.ts +2 -0
  17. package/dist/api/design/boolean/index.d.ts.map +1 -1
  18. package/dist/api/design/catalog.d.ts +320 -0
  19. package/dist/api/design/catalog.d.ts.map +1 -0
  20. package/dist/api/design/create/bulk-items.d.ts +65 -25
  21. package/dist/api/design/create/bulk-items.d.ts.map +1 -1
  22. package/dist/api/design/create/index.d.ts +272 -99
  23. package/dist/api/design/create/index.d.ts.map +1 -1
  24. package/dist/api/design/create/opening-fields.d.ts +13 -12
  25. package/dist/api/design/create/opening-fields.d.ts.map +1 -1
  26. package/dist/api/design/delete/index.d.ts +1 -0
  27. package/dist/api/design/delete/index.d.ts.map +1 -1
  28. package/dist/api/design/doors/index.d.ts +18 -24
  29. package/dist/api/design/doors/index.d.ts.map +1 -1
  30. package/dist/api/design/family.d.ts +797 -27
  31. package/dist/api/design/family.d.ts.map +1 -1
  32. package/dist/api/design/index.d.ts +16 -0
  33. package/dist/api/design/index.d.ts.map +1 -1
  34. package/dist/api/design/networks.d.ts +1763 -0
  35. package/dist/api/design/networks.d.ts.map +1 -0
  36. package/dist/api/design/query/index.d.ts +42 -32
  37. package/dist/api/design/query/index.d.ts.map +1 -1
  38. package/dist/api/design/selection/index.d.ts +10 -10
  39. package/dist/api/design/types/index.d.ts +40 -24
  40. package/dist/api/design/types/index.d.ts.map +1 -1
  41. package/dist/api/design/update/index.d.ts +43 -3
  42. package/dist/api/design/update/index.d.ts.map +1 -1
  43. package/dist/api/design/windows/index.d.ts +8 -8
  44. package/dist/api/design/windows/index.d.ts.map +1 -1
  45. package/dist/api/presentation/aiInspiration.d.ts +10 -10
  46. package/dist/api/presentation/annotate.d.ts +38 -22
  47. package/dist/api/presentation/annotate.d.ts.map +1 -1
  48. package/dist/api/presentation/drawingContract.d.ts +32 -0
  49. package/dist/api/presentation/drawingContract.d.ts.map +1 -0
  50. package/dist/api/presentation/drawings.d.ts +3523 -0
  51. package/dist/api/presentation/drawings.d.ts.map +1 -0
  52. package/dist/api/presentation/export.d.ts +23 -5
  53. package/dist/api/presentation/export.d.ts.map +1 -1
  54. package/dist/api/presentation/index.d.ts +32 -12
  55. package/dist/api/presentation/index.d.ts.map +1 -1
  56. package/dist/api/presentation/placedViews.d.ts +106 -6
  57. package/dist/api/presentation/placedViews.d.ts.map +1 -1
  58. package/dist/api/presentation/shapes.d.ts +2 -2
  59. package/dist/api/presentation/sheets.d.ts +175 -19
  60. package/dist/api/presentation/sheets.d.ts.map +1 -1
  61. package/dist/api/presentation/viewPresets.d.ts +222 -0
  62. package/dist/api/presentation/viewPresets.d.ts.map +1 -0
  63. package/dist/api/presentation/views.d.ts +103 -5
  64. package/dist/api/presentation/views.d.ts.map +1 -1
  65. package/dist/api/presentation/walkthroughs.d.ts +6 -6
  66. package/dist/errors/codes.d.ts +3 -1
  67. package/dist/errors/codes.d.ts.map +1 -1
  68. package/dist/index.cjs +3732 -2383
  69. package/dist/index.cjs.map +1 -1
  70. package/dist/index.js +3607 -2383
  71. package/dist/index.js.map +1 -1
  72. package/package.json +42 -42
  73. package/scripts/check-dist-fresh.mjs +22 -22
  74. package/scripts/generate-manifest.mjs +243 -238
  75. package/scripts/generate-manifest.test.mjs +303 -303
  76. package/src/api/analysis/daylight.ts +470 -470
  77. package/src/api/analysis/heatmaps.ts +683 -683
  78. package/src/api/analysis/illuminance.ts +155 -155
  79. package/src/api/analysis/index.ts +61 -61
  80. package/src/api/analysis/shadows.ts +183 -183
  81. package/src/api/analysis/solar.ts +237 -237
  82. package/src/api/analysis/sunlightHours.ts +211 -211
  83. package/src/api/analysis/sunpath.ts +83 -83
  84. package/src/api/analysis/weather.ts +179 -179
  85. package/src/api/core/buildings.ts +485 -485
  86. package/src/api/core/camera/index.ts +696 -667
  87. package/src/api/core/comment/index.ts +376 -376
  88. package/src/api/core/geom/create/index.ts +2139 -2133
  89. package/src/api/core/geom/delete/index.ts +84 -84
  90. package/src/api/core/geom/index.ts +35 -35
  91. package/src/api/core/geom/query/arc.ts +169 -169
  92. package/src/api/core/geom/query/brep.ts +621 -621
  93. package/src/api/core/geom/query/circle.ts +404 -404
  94. package/src/api/core/geom/query/contour.ts +540 -540
  95. package/src/api/core/geom/query/curve.ts +1102 -1102
  96. package/src/api/core/geom/query/edge.ts +130 -130
  97. package/src/api/core/geom/query/face.ts +508 -508
  98. package/src/api/core/geom/query/halfedge.ts +210 -210
  99. package/src/api/core/geom/query/index.ts +63 -63
  100. package/src/api/core/geom/query/profile.ts +473 -473
  101. package/src/api/core/geom/query/vertex.ts +205 -205
  102. package/src/api/core/geom/update/contour.ts +323 -317
  103. package/src/api/core/geom/update/curve.ts +209 -209
  104. package/src/api/core/geom/update/index.ts +29 -29
  105. package/src/api/core/geom/update/profile.ts +379 -379
  106. package/src/api/core/groups.ts +521 -521
  107. package/src/api/core/handles/index.ts +234 -234
  108. package/src/api/core/history/index.ts +84 -84
  109. package/src/api/core/index.ts +99 -99
  110. package/src/api/core/io/export/index.ts +126 -126
  111. package/src/api/core/io/import/index.ts +504 -504
  112. package/src/api/core/io/index.ts +42 -42
  113. package/src/api/core/io/job/index.ts +140 -140
  114. package/src/api/core/io/query/index.ts +71 -71
  115. package/src/api/core/io/terrain/index.ts +360 -360
  116. package/src/api/core/io/underlay/index.ts +705 -705
  117. package/src/api/core/layers.ts +540 -540
  118. package/src/api/core/math/index.ts +20 -20
  119. package/src/api/core/math/quat.ts +172 -172
  120. package/src/api/core/math/vec3.ts +179 -179
  121. package/src/api/core/mode/index.ts +108 -108
  122. package/src/api/core/project/index.ts +479 -479
  123. package/src/api/core/proposals/index.ts +570 -570
  124. package/src/api/core/storeys/index.ts +308 -308
  125. package/src/api/core/storeys/layers.ts +339 -339
  126. package/src/api/core/tags.ts +911 -911
  127. package/src/api/core/units/index.ts +164 -164
  128. package/src/api/core/user.ts +46 -46
  129. package/src/api/core/zoom/index.ts +64 -51
  130. package/src/api/design/bim.ts +121 -0
  131. package/src/api/design/boolean/index.ts +181 -179
  132. package/src/api/design/catalog.ts +203 -0
  133. package/src/api/design/create/bulk-items.ts +294 -254
  134. package/src/api/design/create/grids.ts +137 -137
  135. package/src/api/design/create/index.ts +2148 -1980
  136. package/src/api/design/create/opening-fields.ts +40 -37
  137. package/src/api/design/delete/index.ts +75 -74
  138. package/src/api/design/dimensions.ts +453 -453
  139. package/src/api/design/doors/index.ts +516 -500
  140. package/src/api/design/edit/index.ts +54 -54
  141. package/src/api/design/erase/index.ts +151 -151
  142. package/src/api/design/family.ts +1334 -704
  143. package/src/api/design/furniture/index.ts +319 -319
  144. package/src/api/design/grids.ts +237 -237
  145. package/src/api/design/index.ts +304 -274
  146. package/src/api/design/lock.ts +69 -69
  147. package/src/api/design/materials/index.ts +608 -608
  148. package/src/api/design/networks.ts +667 -0
  149. package/src/api/design/query/geometry/index.ts +319 -319
  150. package/src/api/design/query/grids.ts +197 -197
  151. package/src/api/design/query/index.ts +1236 -1226
  152. package/src/api/design/query/referenceLines.ts +52 -52
  153. package/src/api/design/query/spaces.ts +275 -275
  154. package/src/api/design/selection/index.ts +273 -273
  155. package/src/api/design/shared.ts +40 -40
  156. package/src/api/design/transform/index.ts +254 -254
  157. package/src/api/design/types/index.ts +163 -156
  158. package/src/api/design/update/index.ts +1024 -983
  159. package/src/api/design/visibility.ts +143 -143
  160. package/src/api/design/windows/index.ts +351 -333
  161. package/src/api/entity/buildableEnvelope.ts +322 -322
  162. package/src/api/entity/index.ts +30 -30
  163. package/src/api/entity/referenceLine.ts +235 -235
  164. package/src/api/entity/space.ts +612 -612
  165. package/src/api/entity/story.ts +517 -517
  166. package/src/api/index.ts +47 -47
  167. package/src/api/presentation/aiInspiration.ts +1116 -1116
  168. package/src/api/presentation/annotate.ts +417 -385
  169. package/src/api/presentation/camera.ts +289 -289
  170. package/src/api/presentation/diagrams.ts +194 -194
  171. package/src/api/presentation/drawingContract.ts +70 -0
  172. package/src/api/presentation/drawings.ts +1179 -0
  173. package/src/api/presentation/export.ts +134 -108
  174. package/src/api/presentation/import.ts +159 -159
  175. package/src/api/presentation/index.ts +160 -135
  176. package/src/api/presentation/placedViews.ts +1211 -1120
  177. package/src/api/presentation/sections.ts +420 -420
  178. package/src/api/presentation/shapes.ts +274 -274
  179. package/src/api/presentation/sheets.ts +746 -585
  180. package/src/api/presentation/slideshow.ts +134 -134
  181. package/src/api/presentation/tables.ts +84 -84
  182. package/src/api/presentation/viewPresets.ts +241 -0
  183. package/src/api/presentation/views.ts +713 -673
  184. package/src/api/presentation/walkthroughs.ts +1201 -1201
  185. package/src/api/program/adjacency.ts +164 -164
  186. package/src/api/program/areas.ts +408 -408
  187. package/src/api/program/classification.ts +138 -138
  188. package/src/api/program/cores.ts +83 -83
  189. package/src/api/program/departments.ts +517 -517
  190. package/src/api/program/index.ts +73 -73
  191. package/src/api/program/labels.ts +332 -332
  192. package/src/api/program/layout.ts +422 -422
  193. package/src/api/program/metadata.ts +364 -364
  194. package/src/api/program/metrics.ts +120 -120
  195. package/src/api/program/site.ts +748 -748
  196. package/src/api/program/spreadsheet.ts +2698 -2698
  197. package/src/api/workspace/index.ts +612 -612
  198. package/src/errors/codes.ts +143 -136
  199. package/src/errors/envelope.ts +75 -75
  200. package/src/errors/index.ts +21 -21
  201. package/src/errors/plugin-error.ts +134 -134
  202. package/src/handles.ts +297 -297
  203. package/src/host-utils.ts +67 -67
  204. package/src/index.ts +7 -7
  205. package/src/massParameters.ops.ts +246 -246
  206. package/src/massParameters.ts +427 -427
  207. package/src/types.ts +16 -16
  208. package/test/drawingContract.test.mjs +288 -0
  209. package/test/errors.test.mjs +185 -184
  210. package/test/massParameters.test.mjs +952 -952
  211. package/tsconfig.json +22 -22
  212. package/tsup.config.ts +12 -12
  213. package/api-manifest.json +0 -9711
@@ -1,274 +1,274 @@
1
- import * as z from "zod"
2
- import { PluginApiReturn } from "../../types"
3
- import {
4
- PluginAnnotateFill,
5
- PluginAnnotateGeoKind,
6
- PluginAnnotateTextColor,
7
- PluginAnnotateTextSize,
8
- } from "./annotate"
9
-
10
- /**
11
- * Presentation shapes — a stable, plugin-owned shape lifecycle on Present-mode
12
- * sheets.
13
- *
14
- * Where {@linkcode PluginPresentationAnnotateApi} is fire-and-forget (every call
15
- * creates a new shape), this namespace keys each shape by a caller-chosen
16
- * string, so rerunning an analysis **updates** its sheet output in place instead
17
- * of duplicating it:
18
- *
19
- * - {@linkcode PluginPresentationShapesApi.upsert} — create or update the shape for a key
20
- * - {@linkcode PluginPresentationShapesApi.remove} — delete the shape for a key
21
- * - {@linkcode PluginPresentationShapesApi.removeAll} — delete every shape owned by the calling plugin
22
- * - {@linkcode PluginPresentationShapesApi.list} — the calling plugin's shapes (key, shapeId, type)
23
- *
24
- * Shape ids are derived deterministically from the plugin id + key, so upserts
25
- * converge across collaborators. Mutations require **Present mode to be open**
26
- * (`list` is a never-throw read); each plugin sees and mutates only its own
27
- * shapes.
28
- *
29
- * Accessed via `snaptrude.presentation.shapes`.
30
- */
31
- export abstract class PluginPresentationShapesApi {
32
- constructor() {}
33
-
34
- /**
35
- * Create or update the shape for a key.
36
- *
37
- * The `shape` spec is a discriminated union over the same four annotation
38
- * kinds as `presentation.annotate` (`text`, `note`, `arrow`, `geo`), with the
39
- * same option shapes. On first call for a key the shape is created on the
40
- * target sheet (`options.sheetId`, default: the first sheet) and nested under
41
- * the sheet frame; on later calls the existing shape is updated in place —
42
- * same shape id, same sheet, one undo step. Positions/bounds are relative to
43
- * the sheet's top-left, in canvas units. Requires Present mode to be open.
44
- *
45
- * @param key - Caller-chosen stable identifier for the shape (per plugin).
46
- * @param shape - The desired shape ({@linkcode PluginPresentationShapeSpec}):
47
- * `{ type: "text" | "note" | "arrow" | "geo", ... }` with the matching
48
- * annotate options. Changing `type` for an existing key replaces the shape
49
- * (same shape id).
50
- * @param options - Optional `sheetId` — the sheet to create the shape on
51
- * (defaults to the first sheet; ignored on update, the shape stays on its
52
- * sheet).
53
- * @returns A {@linkcode PluginPresentationShapesUpsertResult} — the stable
54
- * `shapeId` and `created` (`true` on first upsert, `false` on update).
55
- * @throws If Present mode is not open, the args are invalid, or the sheet id
56
- * is unknown.
57
- *
58
- * @examplePrompt Update the analysis label on the sheet instead of adding another one
59
- * @examplePrompt Rerun the daylight report and refresh its annotations
60
- * @examplePrompt Keep one "FAR: 2.4" text on Sheet 1 that updates on each run
61
- * @examplePrompt Draw a highlight rectangle the plugin can move on the next run
62
- *
63
- * # Example
64
- * ```ts
65
- * const { shapeId, created } = await snaptrude.presentation.shapes.upsert("far-label", {
66
- * type: "text",
67
- * text: "FAR: 2.4",
68
- * position: { x: 40, y: 40 },
69
- * color: "blue",
70
- * })
71
- * ```
72
- */
73
- public abstract upsert(
74
- key: string,
75
- shape: PluginPresentationShapeSpec,
76
- options?: { sheetId?: string },
77
- ): PluginApiReturn<PluginPresentationShapesUpsertResult>
78
-
79
- /**
80
- * Delete the shape for a key.
81
- *
82
- * Removes the calling plugin's shape registered under `key`, if it exists.
83
- * Requires Present mode to be open.
84
- *
85
- * @param key - The key passed to {@linkcode PluginPresentationShapesApi.upsert}.
86
- * @returns `true` if a shape was deleted, `false` if no shape exists for the
87
- * key.
88
- * @throws If Present mode is not open or the key is invalid.
89
- *
90
- * @examplePrompt Remove the FAR label from the sheet
91
- * @examplePrompt Delete the highlight the plugin added earlier
92
- * @examplePrompt Clear the "far-label" annotation
93
- *
94
- * # Example
95
- * ```ts
96
- * const removed = await snaptrude.presentation.shapes.remove("far-label")
97
- * ```
98
- */
99
- public abstract remove(key: string): PluginApiReturn<boolean>
100
-
101
- /**
102
- * Delete every shape owned by the calling plugin.
103
- *
104
- * Removes all shapes the calling plugin has upserted (across all sheets) in
105
- * one undo step. Requires Present mode to be open.
106
- *
107
- * @returns The number of shapes deleted.
108
- * @throws If Present mode is not open.
109
- *
110
- * @examplePrompt Clear all annotations my plugin added
111
- * @examplePrompt Reset the sheet output before rerunning the analysis
112
- * @examplePrompt Remove every plugin-drawn shape
113
- *
114
- * # Example
115
- * ```ts
116
- * const deleted = await snaptrude.presentation.shapes.removeAll()
117
- * ```
118
- */
119
- public abstract removeAll(): PluginApiReturn<number>
120
-
121
- /**
122
- * List the calling plugin's shapes.
123
- *
124
- * Returns one entry per live shape the calling plugin has upserted — its
125
- * `key`, the underlying canvas `shapeId`, and the shape `type`. A never-throw
126
- * read: returns an empty list when Present mode is closed.
127
- *
128
- * @returns A {@linkcode PluginPresentationShapesListResult} with the `shapes`
129
- * array (empty when Present mode is closed).
130
- *
131
- * @examplePrompt Which annotations has my plugin placed on the sheets?
132
- * @examplePrompt List the plugin's shapes before refreshing them
133
- * @examplePrompt Check whether the FAR label already exists
134
- *
135
- * # Example
136
- * ```ts
137
- * const { shapes } = await snaptrude.presentation.shapes.list()
138
- * const hasLabel = shapes.some((s) => s.key === "far-label")
139
- * ```
140
- */
141
- public abstract list(): PluginApiReturn<PluginPresentationShapesListResult>
142
- }
143
-
144
- /**
145
- * Desired shape for {@linkcode PluginPresentationShapesApi.upsert} — a
146
- * discriminated union over the four annotate kinds, with the same option shapes
147
- * as the matching `presentation.annotate` call:
148
- *
149
- * | `type` | Payload | Mirrors |
150
- * |---|---|---|
151
- * | `"text"` | `text`, `position?`, `size?`, `color?` | `annotate.text` |
152
- * | `"note"` | `text`, `position?`, `color?`, `size?` | `annotate.note` |
153
- * | `"arrow"` | `start`, `end`, `color?`, `size?` | `annotate.arrow` |
154
- * | `"geo"` | `kind`, `bounds`, `color?`, `fill?` | `annotate.shape` |
155
- *
156
- * Positions/bounds are relative to the sheet's top-left, in canvas units.
157
- */
158
- export const PluginPresentationShapeSpec = z.discriminatedUnion("type", [
159
- z.object({
160
- type: z.literal("text"),
161
- text: z.string(),
162
- position: z.object({ x: z.number(), y: z.number() }).optional(),
163
- size: PluginAnnotateTextSize.optional(),
164
- color: PluginAnnotateTextColor.optional(),
165
- }),
166
- z.object({
167
- type: z.literal("note"),
168
- text: z.string(),
169
- position: z.object({ x: z.number(), y: z.number() }).optional(),
170
- color: PluginAnnotateTextColor.optional(),
171
- size: PluginAnnotateTextSize.optional(),
172
- }),
173
- z.object({
174
- type: z.literal("arrow"),
175
- start: z.object({ x: z.number(), y: z.number() }),
176
- end: z.object({ x: z.number(), y: z.number() }),
177
- color: PluginAnnotateTextColor.optional(),
178
- size: PluginAnnotateTextSize.optional(),
179
- }),
180
- z.object({
181
- type: z.literal("geo"),
182
- kind: PluginAnnotateGeoKind,
183
- bounds: z.object({
184
- x: z.number(),
185
- y: z.number(),
186
- w: z.number().positive(),
187
- h: z.number().positive(),
188
- }),
189
- color: PluginAnnotateTextColor.optional(),
190
- fill: PluginAnnotateFill.optional(),
191
- }),
192
- ])
193
- export type PluginPresentationShapeSpec = z.infer<
194
- typeof PluginPresentationShapeSpec
195
- >
196
-
197
- /** The shape kind of a plugin-owned shape (the `type` discriminant of {@linkcode PluginPresentationShapeSpec}). */
198
- export const PluginPresentationShapeType = z.enum([
199
- "text",
200
- "note",
201
- "arrow",
202
- "geo",
203
- ])
204
- export type PluginPresentationShapeType = z.infer<
205
- typeof PluginPresentationShapeType
206
- >
207
-
208
- /**
209
- * Arguments for {@linkcode PluginPresentationShapesApi.upsert}.
210
- *
211
- * | Property | Type | Description |
212
- * |---|---|---|
213
- * | `key` | `string` | Caller-chosen stable identifier (non-empty) |
214
- * | `shape` | {@linkcode PluginPresentationShapeSpec} | The desired shape |
215
- * | `sheetId` | `string \| undefined` | Sheet to create on (default: first sheet; ignored on update) |
216
- */
217
- export const PluginPresentationShapesUpsertArgs = z.object({
218
- key: z.string().min(1),
219
- shape: PluginPresentationShapeSpec,
220
- sheetId: z.string().optional(),
221
- })
222
- export type PluginPresentationShapesUpsertArgs = z.infer<
223
- typeof PluginPresentationShapesUpsertArgs
224
- >
225
-
226
- /**
227
- * Result of {@linkcode PluginPresentationShapesApi.upsert}.
228
- *
229
- * | Property | Type | Description |
230
- * |---|---|---|
231
- * | `shapeId` | `string` | Stable id of the canvas shape for the key |
232
- * | `created` | `boolean` | `true` if the shape was created, `false` if updated |
233
- */
234
- export const PluginPresentationShapesUpsertResult = z.object({
235
- shapeId: z.string(),
236
- created: z.boolean(),
237
- })
238
- export type PluginPresentationShapesUpsertResult = z.infer<
239
- typeof PluginPresentationShapesUpsertResult
240
- >
241
-
242
- /**
243
- * Arguments for {@linkcode PluginPresentationShapesApi.remove}.
244
- *
245
- * | Property | Type | Description |
246
- * |---|---|---|
247
- * | `key` | `string` | The key the shape was upserted under (non-empty) |
248
- */
249
- export const PluginPresentationShapesRemoveArgs = z.object({
250
- key: z.string().min(1),
251
- })
252
- export type PluginPresentationShapesRemoveArgs = z.infer<
253
- typeof PluginPresentationShapesRemoveArgs
254
- >
255
-
256
- /**
257
- * Result of {@linkcode PluginPresentationShapesApi.list}.
258
- *
259
- * | Property | Type | Description |
260
- * |---|---|---|
261
- * | `shapes` | `{ key: string; shapeId: string; type: `{@linkcode PluginPresentationShapeType}` }[]` | One entry per live plugin-owned shape |
262
- */
263
- export const PluginPresentationShapesListResult = z.object({
264
- shapes: z.array(
265
- z.object({
266
- key: z.string(),
267
- shapeId: z.string(),
268
- type: PluginPresentationShapeType,
269
- }),
270
- ),
271
- })
272
- export type PluginPresentationShapesListResult = z.infer<
273
- typeof PluginPresentationShapesListResult
274
- >
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../types"
3
+ import {
4
+ PluginAnnotateFill,
5
+ PluginAnnotateGeoKind,
6
+ PluginAnnotateTextColor,
7
+ PluginAnnotateTextSize,
8
+ } from "./annotate"
9
+
10
+ /**
11
+ * Presentation shapes — a stable, plugin-owned shape lifecycle on Present-mode
12
+ * sheets.
13
+ *
14
+ * Where {@linkcode PluginPresentationAnnotateApi} is fire-and-forget (every call
15
+ * creates a new shape), this namespace keys each shape by a caller-chosen
16
+ * string, so rerunning an analysis **updates** its sheet output in place instead
17
+ * of duplicating it:
18
+ *
19
+ * - {@linkcode PluginPresentationShapesApi.upsert} — create or update the shape for a key
20
+ * - {@linkcode PluginPresentationShapesApi.remove} — delete the shape for a key
21
+ * - {@linkcode PluginPresentationShapesApi.removeAll} — delete every shape owned by the calling plugin
22
+ * - {@linkcode PluginPresentationShapesApi.list} — the calling plugin's shapes (key, shapeId, type)
23
+ *
24
+ * Shape ids are derived deterministically from the plugin id + key, so upserts
25
+ * converge across collaborators. Mutations require **Present mode to be open**
26
+ * (`list` is a never-throw read); each plugin sees and mutates only its own
27
+ * shapes.
28
+ *
29
+ * Accessed via `snaptrude.presentation.shapes`.
30
+ */
31
+ export abstract class PluginPresentationShapesApi {
32
+ constructor() {}
33
+
34
+ /**
35
+ * Create or update the shape for a key.
36
+ *
37
+ * The `shape` spec is a discriminated union over the same four annotation
38
+ * kinds as `presentation.annotate` (`text`, `note`, `arrow`, `geo`), with the
39
+ * same option shapes. On first call for a key the shape is created on the
40
+ * target sheet (`options.sheetId`, default: the first sheet) and nested under
41
+ * the sheet frame; on later calls the existing shape is updated in place —
42
+ * same shape id, same sheet, one undo step. Positions/bounds are relative to
43
+ * the sheet's top-left, in canvas units. Requires Present mode to be open.
44
+ *
45
+ * @param key - Caller-chosen stable identifier for the shape (per plugin).
46
+ * @param shape - The desired shape ({@linkcode PluginPresentationShapeSpec}):
47
+ * `{ type: "text" | "note" | "arrow" | "geo", ... }` with the matching
48
+ * annotate options. Changing `type` for an existing key replaces the shape
49
+ * (same shape id).
50
+ * @param options - Optional `sheetId` — the sheet to create the shape on
51
+ * (defaults to the first sheet; ignored on update, the shape stays on its
52
+ * sheet).
53
+ * @returns A {@linkcode PluginPresentationShapesUpsertResult} — the stable
54
+ * `shapeId` and `created` (`true` on first upsert, `false` on update).
55
+ * @throws If Present mode is not open, the args are invalid, or the sheet id
56
+ * is unknown.
57
+ *
58
+ * @examplePrompt Update the analysis label on the sheet instead of adding another one
59
+ * @examplePrompt Rerun the daylight report and refresh its annotations
60
+ * @examplePrompt Keep one "FAR: 2.4" text on Sheet 1 that updates on each run
61
+ * @examplePrompt Draw a highlight rectangle the plugin can move on the next run
62
+ *
63
+ * # Example
64
+ * ```ts
65
+ * const { shapeId, created } = await snaptrude.presentation.shapes.upsert("far-label", {
66
+ * type: "text",
67
+ * text: "FAR: 2.4",
68
+ * position: { x: 40, y: 40 },
69
+ * color: "blue",
70
+ * })
71
+ * ```
72
+ */
73
+ public abstract upsert(
74
+ key: string,
75
+ shape: PluginPresentationShapeSpec,
76
+ options?: { sheetId?: string },
77
+ ): PluginApiReturn<PluginPresentationShapesUpsertResult>
78
+
79
+ /**
80
+ * Delete the shape for a key.
81
+ *
82
+ * Removes the calling plugin's shape registered under `key`, if it exists.
83
+ * Requires Present mode to be open.
84
+ *
85
+ * @param key - The key passed to {@linkcode PluginPresentationShapesApi.upsert}.
86
+ * @returns `true` if a shape was deleted, `false` if no shape exists for the
87
+ * key.
88
+ * @throws If Present mode is not open or the key is invalid.
89
+ *
90
+ * @examplePrompt Remove the FAR label from the sheet
91
+ * @examplePrompt Delete the highlight the plugin added earlier
92
+ * @examplePrompt Clear the "far-label" annotation
93
+ *
94
+ * # Example
95
+ * ```ts
96
+ * const removed = await snaptrude.presentation.shapes.remove("far-label")
97
+ * ```
98
+ */
99
+ public abstract remove(key: string): PluginApiReturn<boolean>
100
+
101
+ /**
102
+ * Delete every shape owned by the calling plugin.
103
+ *
104
+ * Removes all shapes the calling plugin has upserted (across all sheets) in
105
+ * one undo step. Requires Present mode to be open.
106
+ *
107
+ * @returns The number of shapes deleted.
108
+ * @throws If Present mode is not open.
109
+ *
110
+ * @examplePrompt Clear all annotations my plugin added
111
+ * @examplePrompt Reset the sheet output before rerunning the analysis
112
+ * @examplePrompt Remove every plugin-drawn shape
113
+ *
114
+ * # Example
115
+ * ```ts
116
+ * const deleted = await snaptrude.presentation.shapes.removeAll()
117
+ * ```
118
+ */
119
+ public abstract removeAll(): PluginApiReturn<number>
120
+
121
+ /**
122
+ * List the calling plugin's shapes.
123
+ *
124
+ * Returns one entry per live shape the calling plugin has upserted — its
125
+ * `key`, the underlying canvas `shapeId`, and the shape `type`. A never-throw
126
+ * read: returns an empty list when Present mode is closed.
127
+ *
128
+ * @returns A {@linkcode PluginPresentationShapesListResult} with the `shapes`
129
+ * array (empty when Present mode is closed).
130
+ *
131
+ * @examplePrompt Which annotations has my plugin placed on the sheets?
132
+ * @examplePrompt List the plugin's shapes before refreshing them
133
+ * @examplePrompt Check whether the FAR label already exists
134
+ *
135
+ * # Example
136
+ * ```ts
137
+ * const { shapes } = await snaptrude.presentation.shapes.list()
138
+ * const hasLabel = shapes.some((s) => s.key === "far-label")
139
+ * ```
140
+ */
141
+ public abstract list(): PluginApiReturn<PluginPresentationShapesListResult>
142
+ }
143
+
144
+ /**
145
+ * Desired shape for {@linkcode PluginPresentationShapesApi.upsert} — a
146
+ * discriminated union over the four annotate kinds, with the same option shapes
147
+ * as the matching `presentation.annotate` call:
148
+ *
149
+ * | `type` | Payload | Mirrors |
150
+ * |---|---|---|
151
+ * | `"text"` | `text`, `position?`, `size?`, `color?` | `annotate.text` |
152
+ * | `"note"` | `text`, `position?`, `color?`, `size?` | `annotate.note` |
153
+ * | `"arrow"` | `start`, `end`, `color?`, `size?` | `annotate.arrow` |
154
+ * | `"geo"` | `kind`, `bounds`, `color?`, `fill?` | `annotate.shape` |
155
+ *
156
+ * Positions/bounds are relative to the sheet's top-left, in canvas units.
157
+ */
158
+ export const PluginPresentationShapeSpec = z.discriminatedUnion("type", [
159
+ z.object({
160
+ type: z.literal("text"),
161
+ text: z.string(),
162
+ position: z.object({ x: z.number(), y: z.number() }).optional(),
163
+ size: PluginAnnotateTextSize.optional(),
164
+ color: PluginAnnotateTextColor.optional(),
165
+ }),
166
+ z.object({
167
+ type: z.literal("note"),
168
+ text: z.string(),
169
+ position: z.object({ x: z.number(), y: z.number() }).optional(),
170
+ color: PluginAnnotateTextColor.optional(),
171
+ size: PluginAnnotateTextSize.optional(),
172
+ }),
173
+ z.object({
174
+ type: z.literal("arrow"),
175
+ start: z.object({ x: z.number(), y: z.number() }),
176
+ end: z.object({ x: z.number(), y: z.number() }),
177
+ color: PluginAnnotateTextColor.optional(),
178
+ size: PluginAnnotateTextSize.optional(),
179
+ }),
180
+ z.object({
181
+ type: z.literal("geo"),
182
+ kind: PluginAnnotateGeoKind,
183
+ bounds: z.object({
184
+ x: z.number(),
185
+ y: z.number(),
186
+ w: z.number().positive(),
187
+ h: z.number().positive(),
188
+ }),
189
+ color: PluginAnnotateTextColor.optional(),
190
+ fill: PluginAnnotateFill.optional(),
191
+ }),
192
+ ])
193
+ export type PluginPresentationShapeSpec = z.infer<
194
+ typeof PluginPresentationShapeSpec
195
+ >
196
+
197
+ /** The shape kind of a plugin-owned shape (the `type` discriminant of {@linkcode PluginPresentationShapeSpec}). */
198
+ export const PluginPresentationShapeType = z.enum([
199
+ "text",
200
+ "note",
201
+ "arrow",
202
+ "geo",
203
+ ])
204
+ export type PluginPresentationShapeType = z.infer<
205
+ typeof PluginPresentationShapeType
206
+ >
207
+
208
+ /**
209
+ * Arguments for {@linkcode PluginPresentationShapesApi.upsert}.
210
+ *
211
+ * | Property | Type | Description |
212
+ * |---|---|---|
213
+ * | `key` | `string` | Caller-chosen stable identifier (non-empty) |
214
+ * | `shape` | {@linkcode PluginPresentationShapeSpec} | The desired shape |
215
+ * | `sheetId` | `string \| undefined` | Sheet to create on (default: first sheet; ignored on update) |
216
+ */
217
+ export const PluginPresentationShapesUpsertArgs = z.object({
218
+ key: z.string().min(1),
219
+ shape: PluginPresentationShapeSpec,
220
+ sheetId: z.string().optional(),
221
+ })
222
+ export type PluginPresentationShapesUpsertArgs = z.infer<
223
+ typeof PluginPresentationShapesUpsertArgs
224
+ >
225
+
226
+ /**
227
+ * Result of {@linkcode PluginPresentationShapesApi.upsert}.
228
+ *
229
+ * | Property | Type | Description |
230
+ * |---|---|---|
231
+ * | `shapeId` | `string` | Stable id of the canvas shape for the key |
232
+ * | `created` | `boolean` | `true` if the shape was created, `false` if updated |
233
+ */
234
+ export const PluginPresentationShapesUpsertResult = z.object({
235
+ shapeId: z.string(),
236
+ created: z.boolean(),
237
+ })
238
+ export type PluginPresentationShapesUpsertResult = z.infer<
239
+ typeof PluginPresentationShapesUpsertResult
240
+ >
241
+
242
+ /**
243
+ * Arguments for {@linkcode PluginPresentationShapesApi.remove}.
244
+ *
245
+ * | Property | Type | Description |
246
+ * |---|---|---|
247
+ * | `key` | `string` | The key the shape was upserted under (non-empty) |
248
+ */
249
+ export const PluginPresentationShapesRemoveArgs = z.object({
250
+ key: z.string().min(1),
251
+ })
252
+ export type PluginPresentationShapesRemoveArgs = z.infer<
253
+ typeof PluginPresentationShapesRemoveArgs
254
+ >
255
+
256
+ /**
257
+ * Result of {@linkcode PluginPresentationShapesApi.list}.
258
+ *
259
+ * | Property | Type | Description |
260
+ * |---|---|---|
261
+ * | `shapes` | `{ key: string; shapeId: string; type: `{@linkcode PluginPresentationShapeType}` }[]` | One entry per live plugin-owned shape |
262
+ */
263
+ export const PluginPresentationShapesListResult = z.object({
264
+ shapes: z.array(
265
+ z.object({
266
+ key: z.string(),
267
+ shapeId: z.string(),
268
+ type: PluginPresentationShapeType,
269
+ }),
270
+ ),
271
+ })
272
+ export type PluginPresentationShapesListResult = z.infer<
273
+ typeof PluginPresentationShapesListResult
274
+ >