@snaptrude/plugin-core 0.9.16-networks-20261012.1 → 0.9.17

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 (88) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/api-manifest.json +9711 -0
  3. package/dist/api/analysis/daylight.d.ts +5 -5
  4. package/dist/api/analysis/solar.d.ts +2 -2
  5. package/dist/api/core/camera/index.d.ts +0 -29
  6. package/dist/api/core/camera/index.d.ts.map +1 -1
  7. package/dist/api/core/zoom/index.d.ts +0 -13
  8. package/dist/api/core/zoom/index.d.ts.map +1 -1
  9. package/dist/api/design/create/bulk-items.d.ts +21 -40
  10. package/dist/api/design/create/bulk-items.d.ts.map +1 -1
  11. package/dist/api/design/create/index.d.ts +97 -120
  12. package/dist/api/design/create/index.d.ts.map +1 -1
  13. package/dist/api/design/create/opening-fields.d.ts +12 -13
  14. package/dist/api/design/create/opening-fields.d.ts.map +1 -1
  15. package/dist/api/design/doors/index.d.ts +24 -18
  16. package/dist/api/design/doors/index.d.ts.map +1 -1
  17. package/dist/api/design/family.d.ts +27 -797
  18. package/dist/api/design/family.d.ts.map +1 -1
  19. package/dist/api/design/index.d.ts +0 -16
  20. package/dist/api/design/index.d.ts.map +1 -1
  21. package/dist/api/design/query/index.d.ts +30 -30
  22. package/dist/api/design/selection/index.d.ts +10 -10
  23. package/dist/api/design/types/index.d.ts +24 -40
  24. package/dist/api/design/types/index.d.ts.map +1 -1
  25. package/dist/api/design/update/index.d.ts +3 -40
  26. package/dist/api/design/update/index.d.ts.map +1 -1
  27. package/dist/api/design/windows/index.d.ts +8 -8
  28. package/dist/api/design/windows/index.d.ts.map +1 -1
  29. package/dist/api/presentation/aiInspiration.d.ts +10 -10
  30. package/dist/api/presentation/annotate.d.ts +22 -38
  31. package/dist/api/presentation/annotate.d.ts.map +1 -1
  32. package/dist/api/presentation/export.d.ts +5 -23
  33. package/dist/api/presentation/export.d.ts.map +1 -1
  34. package/dist/api/presentation/index.d.ts +21 -32
  35. package/dist/api/presentation/index.d.ts.map +1 -1
  36. package/dist/api/presentation/placedViews.d.ts +6 -106
  37. package/dist/api/presentation/placedViews.d.ts.map +1 -1
  38. package/dist/api/presentation/sections.d.ts +461 -0
  39. package/dist/api/presentation/sections.d.ts.map +1 -0
  40. package/dist/api/presentation/shapes.d.ts +2 -2
  41. package/dist/api/presentation/sheets.d.ts +19 -175
  42. package/dist/api/presentation/sheets.d.ts.map +1 -1
  43. package/dist/api/presentation/views.d.ts +5 -103
  44. package/dist/api/presentation/views.d.ts.map +1 -1
  45. package/dist/api/presentation/walkthroughs.d.ts +6 -6
  46. package/dist/index.cjs +2434 -3619
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.js +2421 -3501
  49. package/dist/index.js.map +1 -1
  50. package/package.json +1 -1
  51. package/scripts/generate-manifest.mjs +0 -5
  52. package/src/api/core/camera/index.ts +0 -29
  53. package/src/api/core/zoom/index.ts +0 -13
  54. package/src/api/design/create/bulk-items.ts +16 -23
  55. package/src/api/design/create/index.ts +119 -129
  56. package/src/api/design/create/opening-fields.ts +12 -15
  57. package/src/api/design/doors/index.ts +42 -58
  58. package/src/api/design/family.ts +32 -662
  59. package/src/api/design/index.ts +4 -34
  60. package/src/api/design/types/index.ts +24 -31
  61. package/src/api/design/update/index.ts +3 -41
  62. package/src/api/design/windows/index.ts +22 -40
  63. package/src/api/presentation/annotate.ts +58 -90
  64. package/src/api/presentation/export.ts +6 -32
  65. package/src/api/presentation/index.ts +23 -39
  66. package/src/api/presentation/placedViews.ts +28 -119
  67. package/src/api/presentation/sections.ts +420 -0
  68. package/src/api/presentation/sheets.ts +20 -181
  69. package/src/api/presentation/views.ts +6 -46
  70. package/dist/api/design/bim.d.ts +0 -209
  71. package/dist/api/design/bim.d.ts.map +0 -1
  72. package/dist/api/design/catalog.d.ts +0 -320
  73. package/dist/api/design/catalog.d.ts.map +0 -1
  74. package/dist/api/design/networks.d.ts +0 -1703
  75. package/dist/api/design/networks.d.ts.map +0 -1
  76. package/dist/api/presentation/drawingContract.d.ts +0 -32
  77. package/dist/api/presentation/drawingContract.d.ts.map +0 -1
  78. package/dist/api/presentation/drawings.d.ts +0 -3523
  79. package/dist/api/presentation/drawings.d.ts.map +0 -1
  80. package/dist/api/presentation/viewPresets.d.ts +0 -222
  81. package/dist/api/presentation/viewPresets.d.ts.map +0 -1
  82. package/src/api/design/bim.ts +0 -121
  83. package/src/api/design/catalog.ts +0 -203
  84. package/src/api/design/networks.ts +0 -607
  85. package/src/api/presentation/drawingContract.ts +0 -70
  86. package/src/api/presentation/drawings.ts +0 -1179
  87. package/src/api/presentation/viewPresets.ts +0 -241
  88. package/test/drawingContract.test.mjs +0 -288
@@ -1,1179 +0,0 @@
1
- import * as z from "zod"
2
- import type { PluginApiReturn } from "../../types"
3
- import {
4
- PluginPlacedView,
5
- PluginPlacedViewCrop,
6
- PluginPlacedViewStylePatch,
7
- PluginViewLineStyle,
8
- PluginPlacedViewLabel,
9
- } from "./placedViews"
10
- import { PluginSheetPosition } from "./sheets"
11
- import { PluginPresentationExportResolution } from "./export"
12
- import {
13
- PluginExportFileName,
14
- PluginStandardDrawingScale,
15
- } from "./drawingContract"
16
-
17
- /** Drawing ids are existing Present view-shape ids, stable across reload and undo. */
18
- export const PluginDrawingIdArgs = z
19
- .object({ drawingId: z.string().min(1) })
20
- .strict()
21
- export const PluginDrawingNameArgs = PluginDrawingIdArgs.extend({
22
- name: z.string().trim().min(1),
23
- })
24
- export const PluginDrawingIdsArgs = z
25
- .object({ drawingIds: z.array(z.string().min(1)).min(1).max(100) })
26
- .strict()
27
- export const PluginDrawingCreateOptions = z
28
- .object({
29
- position: PluginSheetPosition.optional(),
30
- scale: PluginStandardDrawingScale.optional(),
31
- })
32
- .strict()
33
- export type PluginDrawingCreateOptions = z.infer<
34
- typeof PluginDrawingCreateOptions
35
- >
36
- export const PluginDrawingCreateArgs = PluginDrawingCreateOptions.extend({
37
- viewId: z.string().min(1),
38
- })
39
- export type PluginDrawingCreateArgs = z.infer<typeof PluginDrawingCreateArgs>
40
- export type PluginDrawingIdArgs = z.infer<typeof PluginDrawingIdArgs>
41
- export type PluginDrawingNameArgs = z.infer<typeof PluginDrawingNameArgs>
42
- export type PluginDrawingIdsArgs = z.infer<typeof PluginDrawingIdsArgs>
43
- export const PluginDrawingScaleArgs = PluginDrawingIdArgs.extend({
44
- scale: PluginStandardDrawingScale,
45
- })
46
- export type PluginDrawingScaleArgs = z.infer<typeof PluginDrawingScaleArgs>
47
- export const PluginDrawingCropArgs = PluginDrawingIdArgs.extend({
48
- crop: PluginPlacedViewCrop.nullable(),
49
- })
50
- export type PluginDrawingCropArgs = z.infer<typeof PluginDrawingCropArgs>
51
- export const PluginDrawingPresetArgs = PluginDrawingIdArgs.extend({
52
- presetId: z.string().min(1),
53
- })
54
- export type PluginDrawingPresetArgs = z.infer<typeof PluginDrawingPresetArgs>
55
-
56
- /** Architectural scale is a denominator (100 means 1:100); positions are Present canvas units. */
57
- export const PluginDrawing = PluginPlacedView.extend({
58
- id: z.string(),
59
- presetId: z.string().nullable(),
60
- kind: z.enum(["plan", "sitePlan", "threeD", "elevation"]),
61
- direction: z.enum(["north", "east", "south", "west"]).nullable(),
62
- })
63
- export type PluginDrawing = z.infer<typeof PluginDrawing>
64
-
65
- const color = z.string().regex(/^#[0-9a-fA-F]{6}$/)
66
- const weight = z.number().finite().min(0).max(2.11)
67
- const opacity = z.number().finite().min(0).max(100)
68
- const pattern = z
69
- .object({
70
- id: z.string().min(1).optional(),
71
- scale: z.number().finite().min(0.25).max(4).optional(),
72
- color: color.optional(),
73
- background: color.optional(),
74
- weight: weight.optional(),
75
- })
76
- .strict()
77
- const face = z
78
- .object({
79
- fontStyle: z.enum(["400", "500", "700", "italic"]).optional(),
80
- fontSize: z.enum(["12px", "16px", "24px", "2.5", "3.5", "5"]).optional(),
81
- color: color.optional(),
82
- })
83
- .strict()
84
- const part = z
85
- .object({
86
- show: z.boolean().optional(),
87
- lineStyle: PluginViewLineStyle.optional(),
88
- weight: weight.optional(),
89
- })
90
- .strict()
91
- const title = z
92
- .object({
93
- show: z.boolean().optional(),
94
- text: z.string().max(2000).optional(),
95
- })
96
- .strict()
97
- const material = z
98
- .object({
99
- show: z.boolean().optional(),
100
- color: color.optional(),
101
- pattern: pattern.optional(),
102
- })
103
- .strict()
104
-
105
- /**
106
- * Vector-plan row patch. Only controls returned by getStyles are accepted for that row.
107
- * Paper weights are mm; opacity is 0–100. Nested values merge, never replace the whole row.
108
- * Presets apply to kernel plans only; other drawings use the legacy category patch.
109
- */
110
- export const PluginDrawingVectorStylePatch = z
111
- .object({
112
- hide: z.boolean().optional(),
113
- lineStyle: PluginViewLineStyle.optional(),
114
- lineColor: color.optional(),
115
- cutWidth: weight.optional(),
116
- projectionWidth: weight.optional(),
117
- weight: weight.optional(),
118
- fillMode: z.string().optional(),
119
- fillColor: color.optional(),
120
- opacity: opacity.optional(),
121
- pattern: pattern.optional(),
122
- mask: z.boolean().optional(),
123
- materials: z
124
- .object({
125
- brick: material.optional(),
126
- glass: material.optional(),
127
- concrete: material.optional(),
128
- metalFrame: material.optional(),
129
- woodFrame: material.optional(),
130
- plaster: material.optional(),
131
- paint: material.optional(),
132
- insulation: material.optional(),
133
- })
134
- .strict()
135
- .optional(),
136
- components: z
137
- .object({
138
- frame: z.boolean().optional(),
139
- leaf: z.boolean().optional(),
140
- jambs: z.boolean().optional(),
141
- glazing: z.boolean().optional(),
142
- track: z.boolean().optional(),
143
- operation: z.boolean().optional(),
144
- operationStyle: PluginViewLineStyle.optional(),
145
- })
146
- .strict()
147
- .optional(),
148
- tag: z
149
- .object({
150
- show: z.boolean().optional(),
151
- fontFamily: z.string().min(1).optional(),
152
- fontStyle: z.enum(["400", "500", "700", "italic"]).optional(),
153
- fontSize: z.enum(["12px", "16px", "24px"]).optional(),
154
- frame: z.enum(["pill", "hexagon"]).optional(),
155
- color: color.optional(),
156
- opacity: opacity.optional(),
157
- outline: weight.optional(),
158
- })
159
- .strict()
160
- .optional(),
161
- text: z
162
- .object({
163
- show: z.boolean().optional(),
164
- labels: z.boolean().optional(),
165
- areas: z.boolean().optional(),
166
- department: z.boolean().optional(),
167
- fontFamily: z.string().min(1).optional(),
168
- color: color.optional(),
169
- fontSize: z.enum(["12px", "16px", "24px"]).optional(),
170
- label: face.optional(),
171
- metrics: face.optional(),
172
- title: face.optional(),
173
- scale: face.optional(),
174
- })
175
- .strict()
176
- .optional(),
177
- detail: z
178
- .object({ show: z.boolean().optional(), weight: weight.optional() })
179
- .strict()
180
- .optional(),
181
- belowCut: part.optional(),
182
- aboveCut: part.optional(),
183
- underlay: part.optional(),
184
- walkLine: part.optional(),
185
- breakLine: part.optional(),
186
- overlay: part.optional(),
187
- title: title.optional(),
188
- proposal: title.optional(),
189
- building: title.optional(),
190
- scale: z
191
- .object({
192
- show: z.boolean().optional(),
193
- format: z.enum(["automatic", "ratio", "text"]).optional(),
194
- })
195
- .strict()
196
- .optional(),
197
- scaleBar: z
198
- .object({
199
- show: z.boolean().optional(),
200
- format: z.enum(["divided", "simple"]).optional(),
201
- length: z.enum(["1", "2", "5", "10"]).optional(),
202
- })
203
- .strict()
204
- .optional(),
205
- extension: z
206
- .object({
207
- show: z.boolean().optional(),
208
- length: z.enum(["underTitle", "fullWidth"]).optional(),
209
- weight: weight.optional(),
210
- color: color.optional(),
211
- })
212
- .strict()
213
- .optional(),
214
- position: z.enum(["bottomLeft", "bottomCentre", "topLeft"]).optional(),
215
- })
216
- .strict()
217
- export const PluginDrawingStylePatch = z.union([
218
- PluginDrawingVectorStylePatch,
219
- PluginPlacedViewStylePatch,
220
- ])
221
- export type PluginDrawingStylePatch = z.infer<typeof PluginDrawingStylePatch>
222
- export const PluginDrawingStylesArgs = PluginDrawingIdArgs.extend({
223
- category: z.string().min(1),
224
- patch: PluginDrawingStylePatch,
225
- })
226
- export type PluginDrawingStylesArgs = z.infer<typeof PluginDrawingStylesArgs>
227
-
228
- /** One selectable value exposed by a native drawing style control. */
229
- export const PluginDrawingStyleControlOption = z.object({
230
- label: z.string(),
231
- value: z.string(),
232
- })
233
- export type PluginDrawingStyleControlOption = z.infer<
234
- typeof PluginDrawingStyleControlOption
235
- >
236
-
237
- /** Numeric bounds exposed by a native drawing style control. */
238
- export const PluginDrawingStyleControlRange = z.object({
239
- min: z.number().finite(),
240
- max: z.number().finite(),
241
- step: z.number().finite().positive(),
242
- })
243
- export type PluginDrawingStyleControlRange = z.infer<
244
- typeof PluginDrawingStyleControlRange
245
- >
246
-
247
- /** Description of one editable control returned by `drawings.getStyles`. */
248
- export const PluginDrawingStyleControl = z.object({
249
- key: z.string(),
250
- kind: z.string(),
251
- options: z.array(PluginDrawingStyleControlOption).optional(),
252
- range: PluginDrawingStyleControlRange.optional(),
253
- })
254
- export type PluginDrawingStyleControl = z.infer<
255
- typeof PluginDrawingStyleControl
256
- >
257
-
258
- /**
259
- * Read values differ from write patches: legacy renderers use -1 for an unset opacity and
260
- * include the read-only `disable` flag. These values must not be echoed as an update patch.
261
- */
262
- export const PluginDrawingStyleValues = z.union([
263
- PluginDrawingVectorStylePatch,
264
- z
265
- .object({
266
- ...PluginPlacedViewStylePatch.shape,
267
- disable: z.boolean().optional(),
268
- opacity: z.number().finite().min(-1).max(100).optional(),
269
- mapOpacity: z.number().finite().min(-1).max(100).optional(),
270
- buildingOpacity: z.number().finite().min(-1).max(100).optional(),
271
- })
272
- .strict(),
273
- ])
274
- export type PluginDrawingStyleValues = z.infer<typeof PluginDrawingStyleValues>
275
-
276
- /** Read-only effective settings and editable controls for one drawing category. */
277
- export const PluginDrawingStyleCategory = z.object({
278
- category: z.string(),
279
- absent: z.boolean(),
280
- settings: PluginDrawingStyleValues,
281
- controls: z.array(PluginDrawingStyleControl),
282
- })
283
- export type PluginDrawingStyleCategory = z.infer<
284
- typeof PluginDrawingStyleCategory
285
- >
286
-
287
- /** Effective style categories and their native editing capabilities. */
288
- export const PluginDrawingStyles = z.object({
289
- categories: z.array(PluginDrawingStyleCategory),
290
- })
291
- export type PluginDrawingStyles = z.infer<typeof PluginDrawingStyles>
292
- export const PluginDrawingStatus = z.object({
293
- drawingId: z.string(),
294
- generation: z.enum(["ready", "updating", "missing"]),
295
- assetSave: z.enum(["uploading", "retrying", "uploaded", "missing"]),
296
- layout: z.enum(["pending", "ready", "unsupported"]),
297
- exportReady: z.boolean(),
298
- warnings: z.array(z.string()),
299
- })
300
- export type PluginDrawingStatus = z.infer<typeof PluginDrawingStatus>
301
- export const PluginDrawingStatusArgs = PluginDrawingIdArgs.extend({
302
- waitMs: z.number().finite().int().min(0).max(30000).optional(),
303
- })
304
- export type PluginDrawingStatusArgs = z.infer<typeof PluginDrawingStatusArgs>
305
- export const PluginDrawingExportFormat = z.enum(["pdf", "svg", "png", "jpg"])
306
- export type PluginDrawingExportFormat = z.infer<
307
- typeof PluginDrawingExportFormat
308
- >
309
- /** Renderer-specific operations and formats supported by a drawing. */
310
- export const PluginDrawingCapabilities = z.object({
311
- renderer: z.enum(["vector", "hybrid", "raster", "unknown"]),
312
- presets: z.boolean(),
313
- labelLayout: z.boolean(),
314
- architecturalScale: z.boolean(),
315
- standardScales: z.array(
316
- z.object({ label: z.string(), value: z.number().finite().positive() }),
317
- ),
318
- exportFormats: z.array(PluginDrawingExportFormat),
319
- })
320
- export type PluginDrawingCapabilities = z.infer<
321
- typeof PluginDrawingCapabilities
322
- >
323
- export const PluginDrawingExportOptions = z
324
- .object({
325
- fileName: PluginExportFileName.trim().min(1).max(200).optional(),
326
- resolution: PluginPresentationExportResolution.optional(),
327
- download: z.boolean().optional(),
328
- })
329
- .strict()
330
- export type PluginDrawingExportOptions = z.infer<
331
- typeof PluginDrawingExportOptions
332
- >
333
- export const PluginDrawingExportArgs = PluginDrawingIdArgs.extend({
334
- format: PluginDrawingExportFormat,
335
- ...PluginDrawingExportOptions.shape,
336
- })
337
- export type PluginDrawingExportArgs = z.infer<typeof PluginDrawingExportArgs>
338
- export const PluginDrawingExportResult = z.object({
339
- files: z.array(
340
- z.object({
341
- fileName: z.string(),
342
- mimeType: z.string(),
343
- byteLength: z.number(),
344
- dataBase64: z.string().optional(),
345
- }),
346
- ),
347
- downloadStarted: z.boolean(),
348
- warnings: z.array(z.string()),
349
- })
350
- export type PluginDrawingExportResult = z.infer<
351
- typeof PluginDrawingExportResult
352
- >
353
-
354
- export const PluginDrawingLabelArgs = z
355
- .object({ labelId: z.string().min(1) })
356
- .strict()
357
- export type PluginDrawingLabelArgs = z.infer<typeof PluginDrawingLabelArgs>
358
- export const PluginDrawingLabelMoveArgs = PluginDrawingLabelArgs.extend({
359
- position: PluginSheetPosition,
360
- })
361
- export type PluginDrawingLabelMoveArgs = z.infer<
362
- typeof PluginDrawingLabelMoveArgs
363
- >
364
- export const PluginDrawingLabelHiddenArgs = PluginDrawingLabelArgs.extend({
365
- hidden: z.boolean(),
366
- })
367
- export type PluginDrawingLabelHiddenArgs = z.infer<
368
- typeof PluginDrawingLabelHiddenArgs
369
- >
370
- export const PluginDrawingLabelResetArgs = PluginDrawingIdArgs.extend({
371
- scope: z.enum(["scale", "all"]).optional(),
372
- })
373
- export type PluginDrawingLabelResetArgs = z.infer<
374
- typeof PluginDrawingLabelResetArgs
375
- >
376
-
377
- /**
378
- * Collision-layout diagnostics for drawing labels, including actionable scale suggestions.
379
- * `suggestedScale` is a larger standard scale (smaller denominator) at which the label would fit.
380
- */
381
- export const PluginDrawingLabelLayout = z.object({
382
- pending: z.boolean(),
383
- pinned: z.number().int().nonnegative(),
384
- unplaced: z.array(
385
- z.object({
386
- labelId: z.string(),
387
- name: z.string(),
388
- reason: z.string(),
389
- suggestedScale: z.number().finite().positive().nullable(),
390
- }),
391
- ),
392
- duplicatesMerged: z.number().int().nonnegative(),
393
- rowsDropped: z.object({
394
- department: z.number().int().nonnegative(),
395
- area: z.number().int().nonnegative(),
396
- wrapped: z.number().int().nonnegative(),
397
- }),
398
- })
399
- export type PluginDrawingLabelLayout = z.infer<typeof PluginDrawingLabelLayout>
400
-
401
- /**
402
- * The text labels of one drawing — room names, areas, tags — and the native
403
- * label layout that fits them.
404
- *
405
- * Label ids are the text-shape ids {@linkcode PluginDrawingLabelsApi.list}
406
- * returns. Positions are drawing-local canvas units. Room-label moves and
407
- * pins are stored per architectural scale, so a label moved at 1:100 keeps
408
- * its spot at 1:100 and is laid out afresh at 1:50. Every method requires
409
- * **Present mode to be open** and throws `PRECONDITION_FAILED` ("Present mode
410
- * is not open") when it is closed; writes use native Present undo.
411
- *
412
- * Accessed via `snaptrude.presentation.drawings.labels`.
413
- */
414
- export abstract class PluginDrawingLabelsApi {
415
- /**
416
- * List every text label on a drawing, including labels the user or the
417
- * layout has hidden. An agent's own annotations under the drawing are not
418
- * labels and are not listed.
419
- *
420
- * @param drawingId - The drawing to read.
421
- * @returns The drawing's {@linkcode PluginPlacedViewLabel} rows
422
- * (`labelId`, `category`, `text`, `position`, `scale`, `hidden`).
423
- * @throws `PRECONDITION_FAILED` if Present mode is not open;
424
- * `HANDLE_INVALID` if `drawingId` is not a drawing.
425
- *
426
- * @examplePrompt List all labels in this drawing
427
- * @examplePrompt Which room labels are hidden on the ground floor drawing?
428
- * @examplePrompt Show me the text of every label on this plan
429
- *
430
- * # Example
431
- * ```ts
432
- * const labels = await snaptrude.presentation.drawings.labels.list(drawing.id)
433
- * const hidden = labels.filter((label) => label.hidden)
434
- * ```
435
- */
436
- public abstract list(
437
- drawingId: string,
438
- ): PluginApiReturn<PluginPlacedViewLabel[]>
439
-
440
- /**
441
- * Read the label-layout diagnostics of a drawing: labels that could not be
442
- * placed cleanly (each with a `suggestedScale` at which it would fit),
443
- * pinned labels, merged duplicates and dropped rows. Reading never hides a
444
- * label: an unplaced label is still shown at a best-effort position.
445
- *
446
- * @param drawingId - The drawing to read.
447
- * @returns A {@linkcode PluginDrawingLabelLayout}. `pending: true` means
448
- * fitting is still running; read again after
449
- * {@linkcode PluginPresentationDrawingsApi.getStatus} with a `waitMs`.
450
- * @throws `PRECONDITION_FAILED` if Present mode is not open;
451
- * `HANDLE_INVALID` if `drawingId` is not a drawing.
452
- *
453
- * @examplePrompt Check this drawing for overlapping labels
454
- * @examplePrompt Do all the room names fit on the ground floor drawing?
455
- * @examplePrompt Which scale would make the labels on this plan readable?
456
- *
457
- * # Example
458
- * ```ts
459
- * const layout = await snaptrude.presentation.drawings.labels.getLayout(drawing.id)
460
- * const suggested = layout.unplaced.find((row) => row.suggestedScale)?.suggestedScale
461
- * if (suggested) await snaptrude.presentation.drawings.setScale(drawing.id, suggested)
462
- * ```
463
- */
464
- public abstract getLayout(
465
- drawingId: string,
466
- ): PluginApiReturn<PluginDrawingLabelLayout>
467
-
468
- /**
469
- * Move a label within its drawing. A room label keeps the new position as a
470
- * native pin at the drawing's current architectural scale; other labels
471
- * move as plain text shapes. One Present undo step.
472
- *
473
- * @param labelId - The label to move (a `labelId` from `labels.list`).
474
- * @param position - The new position, drawing-local canvas units.
475
- * @returns The moved {@linkcode PluginPlacedViewLabel}.
476
- * @throws `VALIDATION` for a malformed position; `PRECONDITION_FAILED` if
477
- * Present mode is not open, the document is read-only, the label or its
478
- * drawing is locked, or the label has not been laid out yet (each with a
479
- * hint); `HANDLE_INVALID` if `labelId` is not a drawing label.
480
- *
481
- * @examplePrompt Move the Kitchen label up a little
482
- * @examplePrompt Put the living room name in the middle of the room
483
- * @examplePrompt Nudge this label to the left
484
- *
485
- * # Example
486
- * ```ts
487
- * const [label] = await snaptrude.presentation.drawings.labels.list(drawing.id)
488
- * await snaptrude.presentation.drawings.labels.move(label.labelId, {
489
- * x: label.position.x,
490
- * y: label.position.y - 20,
491
- * })
492
- * ```
493
- */
494
- public abstract move(
495
- labelId: string,
496
- position: z.infer<typeof PluginSheetPosition>,
497
- ): PluginApiReturn<PluginPlacedViewLabel>
498
-
499
- /**
500
- * Hide or show a label. This is the user's own visibility, independent of
501
- * labels the layout or a crop hides. One Present undo step.
502
- *
503
- * @param labelId - The label to change (a `labelId` from `labels.list`).
504
- * @param hidden - `true` to hide the label, `false` to show it.
505
- * @returns The updated {@linkcode PluginPlacedViewLabel}.
506
- * @throws `PRECONDITION_FAILED` if Present mode is not open, the document is
507
- * read-only, or the label or its drawing is locked (each with a hint);
508
- * `HANDLE_INVALID` if `labelId` is not a drawing label.
509
- *
510
- * @examplePrompt Hide the Store label on this drawing
511
- * @examplePrompt Show the corridor label again
512
- * @examplePrompt Turn off the label for the plant room
513
- *
514
- * # Example
515
- * ```ts
516
- * const labels = await snaptrude.presentation.drawings.labels.list(drawing.id)
517
- * const store = labels.find((label) => label.text.startsWith("Store"))
518
- * if (store) await snaptrude.presentation.drawings.labels.setHidden(store.labelId, true)
519
- * ```
520
- */
521
- public abstract setHidden(
522
- labelId: string,
523
- hidden: boolean,
524
- ): PluginApiReturn<PluginPlacedViewLabel>
525
-
526
- /**
527
- * Pin a room label that could not be placed cleanly at the best position
528
- * the native layout solver finds, at the current architectural scale. May
529
- * wait up to ten seconds for a reloaded drawing's fit data. One Present undo
530
- * step.
531
- *
532
- * @param labelId - An unplaced room label (a `labelId` from
533
- * `labels.getLayout(drawingId).unplaced`).
534
- * @returns `true` when the label was pinned; `false` when it was already
535
- * placed cleanly or the solver found no position (nothing changes).
536
- * @throws `PRECONDITION_FAILED` if Present mode is not open, the document is
537
- * read-only, or the label or its drawing is locked (each with a hint);
538
- * `HANDLE_INVALID` if `labelId` is not a drawing label.
539
- *
540
- * @examplePrompt Place the labels that do not fit
541
- * @examplePrompt Pin the Kitchen label where it fits best
542
- * @examplePrompt Fix the overlapping room names on this drawing
543
- *
544
- * # Example
545
- * ```ts
546
- * const { unplaced } = await snaptrude.presentation.drawings.labels.getLayout(drawing.id)
547
- * for (const row of unplaced) {
548
- * await snaptrude.presentation.drawings.labels.place(row.labelId)
549
- * }
550
- * ```
551
- */
552
- public abstract place(labelId: string): PluginApiReturn<boolean>
553
-
554
- /**
555
- * Clear room-label pins (from `move`, `place` or the user) so the native
556
- * layout places those labels again: at the current architectural scale by
557
- * default, or at every scale with `{ scope: "all" }`. One Present undo step.
558
- *
559
- * @param drawingId - The drawing whose pins to clear.
560
- * @param options - Optional `scope`: `"scale"` (default, the current scale)
561
- * or `"all"` (every scale).
562
- * @returns The number of pins cleared (`0` when there were none; nothing changes).
563
- * @throws `PRECONDITION_FAILED` if Present mode is not open, the document is
564
- * read-only, or the drawing is locked (each with a hint); `HANDLE_INVALID`
565
- * if `drawingId` is not a drawing.
566
- *
567
- * @examplePrompt Reset the label positions on this drawing
568
- * @examplePrompt Undo all my label moves at every scale
569
- * @examplePrompt Let the room labels lay themselves out again
570
- *
571
- * # Example
572
- * ```ts
573
- * const cleared = await snaptrude.presentation.drawings.labels.reset(drawing.id, {
574
- * scope: "all",
575
- * })
576
- * ```
577
- */
578
- public abstract reset(
579
- drawingId: string,
580
- options?: { scope?: "scale" | "all" },
581
- ): PluginApiReturn<number>
582
- }
583
-
584
- /**
585
- * Drawing deliverables on the Present canvas: plans, site plans, elevations
586
- * and 3D drawings generated from saved {@linkcode PluginPresentationViewsApi}
587
- * views, independent of sheet composition.
588
- *
589
- * A drawing is the native Present view shape. It needs no sheet: it can stay
590
- * loose on the canvas, be exported on its own, or be put on a sheet with
591
- * {@linkcode PluginPresentationSheetsApi.placeDrawing} (scaled down to fit).
592
- * `create` never puts a drawing on a sheet; to make a drawing of a view on a
593
- * sheet in one call use {@linkcode PluginPresentationSheetsApi.place}. Drawing ids are stable
594
- * across reload and undo. Native shape history and sync are reused: writes are
595
- * gated and use Present undo.
596
- *
597
- * **Drawings or placed views?** A drawing id is the same shape id
598
- * {@linkcode PluginPresentationPlacedViewsApi} addresses, so both namespaces
599
- * reach the same view shape. `drawings` is the drawing-deliverable surface:
600
- * kernel-plan styles and presets, label layout, status and single-drawing
601
- * export. Use it for drawings made with `drawings.create`; keep `placedViews`
602
- * for views placed with `sheets.place` and for its generic canvas-shape calls.
603
- * Do not mix the two for one shape in the same task: `drawings.setScale` also
604
- * moves a drawing clear of a neighbour it grew over, `placedViews.setScale`
605
- * does not.
606
- *
607
- * **Looking at a drawing.** These calls change drawings, not the Present
608
- * camera. To see a result, frame it and screenshot the Present canvas:
609
- * `presentation.camera.zoomTo(drawing.id)` then
610
- * `presentation.camera.capture()`. `presentation.views.capture` and
611
- * `core.camera` look at the Design (3D) canvas, not this one.
612
- *
613
- * Every method, including the catalog reads, requires **Present mode to be
614
- * open** and throws `PRECONDITION_FAILED` ("Present mode is not open") when it
615
- * is closed or closes during the call; no method switches tabs. Every
616
- * `PRECONDITION_FAILED` carries a `hint` saying what to do next. Creating does
617
- * not wait for the asset upload: read {@linkcode PluginPresentationDrawingsApi.getStatus}.
618
- * `assetSave: "uploaded"` describes the asset, not a server acknowledgement of
619
- * document sync.
620
- *
621
- * Accessed via `snaptrude.presentation.drawings`.
622
- */
623
- export abstract class PluginPresentationDrawingsApi {
624
- /** The drawing's text labels and label layout. See {@linkcode PluginDrawingLabelsApi}. */
625
- public abstract labels: PluginDrawingLabelsApi
626
-
627
- /**
628
- * Generate a drawing from a saved view. Creates the drawing beside its
629
- * source view on the canvas, never on a sheet; to put a drawing on a sheet use
630
- * `presentation.sheets.place(sheetId, viewId)` (fits it to the sheet) or
631
- * `presentation.sheets.placeDrawing(sheetId, drawingId)` (moves this drawing
632
- * onto the sheet, scaled down to fit).
633
- * Omit `position` unless the user asked for a specific place: the host puts
634
- * the new drawing next to its source view, clear of other drawings. An
635
- * explicit `position` (page coordinates, the drawing's centre) is kept and
636
- * can land on top of an existing drawing. The user's selection is left as
637
- * it was.
638
- * Changes the drawing, not the Present camera. The Present view may follow
639
- * the drawing as a courtesy to a user watching (never zooming in, not while
640
- * the camera is locked); to look at it, call
641
- * `presentation.camera.zoomTo(drawing.id)` then
642
- * `presentation.camera.capture()`.
643
- * `scale` must be a standard architectural scale denominator (100 means 1:100)
644
- * in the project's unit system; any other value is rejected. Metric: 10, 20, 50,
645
- * 100, 150, 200, 250, 500, 1000. Imperial detail: 12, 16, 24, 32, 48, 64, 96, 128,
646
- * 192, 384, 768, 1536 (1" = 1' to 1/128" = 1'; 48 is 1/4" = 1', 96 is 1/8" = 1').
647
- * Imperial site: 120, 240, 360, 480, 600, 1200, 2400, 3600, 4800 (1" = 10' to
648
- * 1" = 400'). Pick the LARGEST standard scale (smallest denominator) at which the
649
- * view still fits its frame or sheet and its room labels stay readable: for a
650
- * building floor plan that is usually 1:50 to 1:200 (1/4" = 1' to 1/16" = 1').
651
- * Never use a site-sized scale (1:500 and up, 1/64" = 1' (768) and smaller,
652
- * 1" = 20' (240) and up) for a single building plan unless the user asked for it.
653
- * `scale` applies to plans, site plans and elevations; leave it out for a 3D view.
654
- * After creating, read `labels.getLayout(drawingId)`: when labels are unplaced and carry
655
- * a `suggestedScale`, move to that larger scale with `setScale`. To apply a
656
- * preset, create first and then call `applyPreset`.
657
- *
658
- * @param viewId - The saved view to draw (an id from `presentation.views.list`).
659
- * @param options - Optional `position` (page coordinates) and `scale`
660
- * (a standard denominator).
661
- * @returns The new {@linkcode PluginDrawing}.
662
- * @throws `VALIDATION` for a non-standard `scale` (the message lists the
663
- * allowed ones); `PRECONDITION_FAILED` if Present mode is not open, the
664
- * document is read-only, or a `scale` is given for a 3D view (each with a
665
- * hint); `HANDLE_INVALID` if `viewId` is not a saved view;
666
- * `OPERATION_FAILED` if generation produced no drawing.
667
- *
668
- * @examplePrompt Create a drawing from the ground floor view
669
- * @examplePrompt Make a 1:100 plan drawing of level 2
670
- * @examplePrompt Draw the north elevation at 1/8" = 1'
671
- * @examplePrompt Put the site plan view on the Present canvas as a drawing
672
- *
673
- * # Example
674
- * ```ts
675
- * const { views } = await snaptrude.presentation.views.list()
676
- * const plan = views.find((view) => view.kind === "plan")!
677
- * const drawing = await snaptrude.presentation.drawings.create(plan.id, { scale: 100 })
678
- * await snaptrude.presentation.camera.zoomTo(drawing.id)
679
- * const { image } = await snaptrude.presentation.camera.capture()
680
- * // To put it on a sheet: await snaptrude.presentation.sheets.placeDrawing(sheet.id, drawing.id)
681
- * ```
682
- */
683
- public abstract create(
684
- viewId: string,
685
- options?: PluginDrawingCreateOptions,
686
- ): PluginApiReturn<PluginDrawing>
687
-
688
- /**
689
- * List the drawings on the current Present page, loose or on sheets.
690
- *
691
- * @returns Every {@linkcode PluginDrawing} on the page (empty when there are none).
692
- * @throws `PRECONDITION_FAILED` if Present mode is not open.
693
- *
694
- * @examplePrompt List all drawings in this presentation
695
- * @examplePrompt Which drawings are not on a sheet yet?
696
- * @examplePrompt What scale is each plan drawing at?
697
- *
698
- * # Example
699
- * ```ts
700
- * const drawings = await snaptrude.presentation.drawings.list()
701
- * const loose = drawings.filter((drawing) => !drawing.sheetId)
702
- * ```
703
- */
704
- public abstract list(): PluginApiReturn<PluginDrawing[]>
705
-
706
- /**
707
- * Read one drawing by its stable id.
708
- *
709
- * @param drawingId - The drawing to read.
710
- * @returns The {@linkcode PluginDrawing}, or `null` if no drawing has that id
711
- * (for example, it was deleted).
712
- * @throws `PRECONDITION_FAILED` if Present mode is not open.
713
- *
714
- * @examplePrompt Does the ground floor drawing still exist?
715
- * @examplePrompt What preset is this drawing using?
716
- * @examplePrompt Read the scale and crop of this drawing
717
- *
718
- * # Example
719
- * ```ts
720
- * const current = await snaptrude.presentation.drawings.get(drawing.id)
721
- * if (current) console.log(current.scale, current.presetId)
722
- * ```
723
- */
724
- public abstract get(drawingId: string): PluginApiReturn<PluginDrawing | null>
725
-
726
- /**
727
- * Duplicate a drawing with its labels and annotations (native duplication,
728
- * offset slightly from the original). One Present undo step. The copy keeps
729
- * the original's source view, scale, crop, styles and preset binding.
730
- *
731
- * @param drawingId - The drawing to copy.
732
- * @returns The new {@linkcode PluginDrawing}.
733
- * @throws `PRECONDITION_FAILED` if Present mode is not open, the document is
734
- * read-only, or the drawing is locked (each with a hint); `HANDLE_INVALID`
735
- * if `drawingId` is not a drawing; `OPERATION_FAILED` if the copy failed.
736
- *
737
- * @examplePrompt Duplicate this drawing
738
- * @examplePrompt Make a copy of the ground floor plan drawing
739
- * @examplePrompt Copy this drawing so I can try a different style
740
- *
741
- * # Example
742
- * ```ts
743
- * const copy = await snaptrude.presentation.drawings.copy(drawing.id)
744
- * await snaptrude.presentation.drawings.rename(copy.id, "Ground Floor (option B)")
745
- * ```
746
- */
747
- public abstract copy(drawingId: string): PluginApiReturn<PluginDrawing>
748
-
749
- /**
750
- * Set the drawing's own title text. The source saved view keeps its name.
751
- * One Present undo step.
752
- *
753
- * @param drawingId - The drawing to rename.
754
- * @param name - The new title (non-empty after trimming).
755
- * @returns The updated {@linkcode PluginDrawing}.
756
- * @throws `VALIDATION` for an empty name; `PRECONDITION_FAILED` if Present
757
- * mode is not open, the document is read-only, or the drawing is locked
758
- * (each with a hint); `HANDLE_INVALID` if `drawingId` is not a drawing.
759
- *
760
- * @examplePrompt Rename this drawing to Ground Floor Plan
761
- * @examplePrompt Change the title of the elevation drawing
762
- * @examplePrompt Call this drawing Level 2 General Arrangement
763
- *
764
- * # Example
765
- * ```ts
766
- * await snaptrude.presentation.drawings.rename(drawing.id, "Ground Floor Plan")
767
- * ```
768
- */
769
- public abstract rename(
770
- drawingId: string,
771
- name: string,
772
- ): PluginApiReturn<PluginDrawing>
773
-
774
- /**
775
- * Delete a drawing with its labels and annotations, as one Present undo
776
- * step. The source saved view is not deleted.
777
- *
778
- * @param drawingId - The drawing to delete.
779
- * @returns Nothing.
780
- * @throws `PRECONDITION_FAILED` if Present mode is not open, the document is
781
- * read-only, or the drawing is locked (each with a hint); `HANDLE_INVALID`
782
- * if `drawingId` is not a drawing.
783
- *
784
- * @examplePrompt Delete this drawing
785
- * @examplePrompt Remove the old elevation drawing from the canvas
786
- * @examplePrompt Get rid of the duplicate plan drawing
787
- *
788
- * # Example
789
- * ```ts
790
- * await snaptrude.presentation.drawings.delete(drawing.id)
791
- * ```
792
- */
793
- public abstract delete(drawingId: string): PluginApiReturn<void>
794
-
795
- /**
796
- * Regenerate one to 100 drawings from their source views, after the model
797
- * or the view changed. Waits for the update to finish.
798
- *
799
- * @param drawingIds - The drawings to regenerate (1 to 100 ids).
800
- * @returns One `{ drawingId, updated }` row per drawing; `updated` means the
801
- * drawing's asset actually changed, not merely that the id was submitted.
802
- * @throws `VALIDATION` for an empty list or more than 100 ids;
803
- * `PRECONDITION_FAILED` if Present mode is not open, the document is
804
- * read-only, a drawing is locked, or another drawing update is running
805
- * (each with a hint); `HANDLE_INVALID` if an id is not a drawing.
806
- *
807
- * @examplePrompt Update this drawing with my latest model changes
808
- * @examplePrompt Refresh all the drawings
809
- * @examplePrompt Regenerate the ground floor plan drawing
810
- *
811
- * # Example
812
- * ```ts
813
- * const drawings = await snaptrude.presentation.drawings.list()
814
- * const results = await snaptrude.presentation.drawings.updateContent(
815
- * drawings.map((drawing) => drawing.id),
816
- * )
817
- * ```
818
- */
819
- public abstract updateContent(
820
- drawingIds: string[],
821
- ): PluginApiReturn<{ drawingId: string; updated: boolean }[]>
822
-
823
- /**
824
- * Read what a drawing supports: its actual renderer, whether it takes
825
- * presets (native kernel plans only), label layout and an architectural
826
- * scale, the standard scales for this project, and its export formats. Read
827
- * this before preset, scale, label-layout, style or export writes instead of
828
- * inferring support from the source view.
829
- *
830
- * @param drawingId - The drawing to read.
831
- * @returns A {@linkcode PluginDrawingCapabilities}.
832
- * @throws `PRECONDITION_FAILED` if Present mode is not open;
833
- * `HANDLE_INVALID` if `drawingId` is not a drawing.
834
- *
835
- * @examplePrompt What editing capabilities does this drawing support?
836
- * @examplePrompt Can I apply a preset to this drawing?
837
- * @examplePrompt Which scales can this drawing use?
838
- *
839
- * # Example
840
- * ```ts
841
- * const capabilities = await snaptrude.presentation.drawings.getCapabilities(drawing.id)
842
- * if (capabilities.presets) {
843
- * await snaptrude.presentation.drawings.applyPreset(drawing.id, preset.id)
844
- * }
845
- * ```
846
- */
847
- public abstract getCapabilities(
848
- drawingId: string,
849
- ): PluginApiReturn<PluginDrawingCapabilities>
850
-
851
- /**
852
- * Read a drawing's generation, label-layout and asset-upload state,
853
- * optionally waiting up to `waitMs` (0 by default, at most 30,000) for it
854
- * to become export-ready and uploaded. A timeout is not an error: the
855
- * current state is returned. Read this before export or before closing
856
- * Present mode.
857
- *
858
- * @param drawingId - The drawing to read.
859
- * @param options - Optional `waitMs` (0 to 30,000 ms).
860
- * @returns A {@linkcode PluginDrawingStatus}.
861
- * @throws `VALIDATION` for a `waitMs` out of range; `PRECONDITION_FAILED` if
862
- * Present mode is not open or closes while waiting; `HANDLE_INVALID` if
863
- * `drawingId` is not a drawing.
864
- *
865
- * @examplePrompt Is this drawing ready to export?
866
- * @examplePrompt Wait for the new drawing to finish generating
867
- * @examplePrompt Has the drawing been uploaded yet?
868
- *
869
- * # Example
870
- * ```ts
871
- * const status = await snaptrude.presentation.drawings.getStatus(drawing.id, {
872
- * waitMs: 10_000,
873
- * })
874
- * if (!status.exportReady) console.warn(status.warnings)
875
- * ```
876
- */
877
- public abstract getStatus(
878
- drawingId: string,
879
- options?: { waitMs?: number },
880
- ): PluginApiReturn<PluginDrawingStatus>
881
-
882
- /**
883
- * Set a drawing's architectural scale; perspective/isometric drawings reject this.
884
- * `scale` must be a standard architectural scale denominator (100 means 1:100)
885
- * in the project's unit system; any other value is rejected. Metric: 10, 20, 50,
886
- * 100, 150, 200, 250, 500, 1000. Imperial detail: 12, 16, 24, 32, 48, 64, 96, 128,
887
- * 192, 384, 768, 1536 (1" = 1' to 1/128" = 1'; 48 is 1/4" = 1', 96 is 1/8" = 1').
888
- * Imperial site: 120, 240, 360, 480, 600, 1200, 2400, 3600, 4800 (1" = 10' to
889
- * 1" = 400'). Pick the LARGEST standard scale (smallest denominator) at which the
890
- * view still fits its frame or sheet and its room labels stay readable: for a
891
- * building floor plan that is usually 1:50 to 1:200 (1/4" = 1' to 1/16" = 1').
892
- * Never use a site-sized scale (1:500 and up, 1/64" = 1' (768) and smaller,
893
- * 1" = 20' (240) and up) for a single building plan unless the user asked for it.
894
- * A loose drawing that grows over a neighbour it did not cover before moves
895
- * to the nearest free spot, which `placedViews.setScale` does not do; an
896
- * overlap the user made stays, and a drawing on a sheet never moves.
897
- * Changes the drawing, not the Present camera. The Present view may follow
898
- * the drawing as a courtesy to a user watching (never zooming in, not while
899
- * the camera is locked); to look at it, call
900
- * `presentation.camera.zoomTo(drawing.id)` then
901
- * `presentation.camera.capture()`.
902
- *
903
- * @param drawingId - The drawing to rescale.
904
- * @param scale - A standard architectural scale denominator.
905
- * @returns The updated {@linkcode PluginDrawing}.
906
- * @throws `VALIDATION` for a non-standard `scale` (the message lists the
907
- * allowed ones); `PRECONDITION_FAILED` if Present mode is not open, the
908
- * document is read-only, the drawing is locked, or it is a 3D
909
- * (perspective/isometric) drawing (each with a hint); `HANDLE_INVALID` if
910
- * `drawingId` is not a drawing.
911
- *
912
- * @examplePrompt Set this drawing to 1:50
913
- * @examplePrompt Change the plan drawing scale to 1/4" = 1'
914
- * @examplePrompt Make the ground floor drawing bigger so the labels fit
915
- *
916
- * # Example
917
- * ```ts
918
- * const layout = await snaptrude.presentation.drawings.labels.getLayout(drawing.id)
919
- * const suggested = layout.unplaced.find((row) => row.suggestedScale)?.suggestedScale
920
- * await snaptrude.presentation.drawings.setScale(drawing.id, suggested ?? 50)
921
- * ```
922
- */
923
- public abstract setScale(
924
- drawingId: string,
925
- scale: number,
926
- ): PluginApiReturn<PluginDrawing>
927
-
928
- /**
929
- * Crop a drawing to a window of itself, or pass `null` to remove the crop.
930
- * Crop corners are 0–1 fractions of the uncropped drawing and must satisfy
931
- * `topLeft < bottomRight` on both axes. One Present undo step.
932
- * A loose drawing that grows over a neighbour it did not cover before (for
933
- * example when the crop is removed) moves to the nearest free spot, which
934
- * `placedViews.setCrop` does not do; an overlap the user made stays, and a
935
- * drawing on a sheet never moves.
936
- * Changes the drawing, not the Present camera. The Present view may follow
937
- * the drawing as a courtesy to a user watching (never zooming in, not while
938
- * the camera is locked); to look at it, call
939
- * `presentation.camera.zoomTo(drawing.id)` then
940
- * `presentation.camera.capture()`.
941
- *
942
- * @param drawingId - The drawing to crop.
943
- * @param crop - `{ topLeft, bottomRight }` normalized corners, or `null` to
944
- * remove the crop.
945
- * @returns The updated {@linkcode PluginDrawing}.
946
- * @throws `VALIDATION` for corners outside 0–1 or out of order;
947
- * `PRECONDITION_FAILED` if Present mode is not open, the document is
948
- * read-only, or the drawing is locked (each with a hint);
949
- * `HANDLE_INVALID` if `drawingId` is not a drawing.
950
- *
951
- * @examplePrompt Crop this drawing to the left half
952
- * @examplePrompt Remove the crop from the site plan drawing
953
- * @examplePrompt Show only the top-right corner of this plan
954
- *
955
- * # Example
956
- * ```ts
957
- * await snaptrude.presentation.drawings.setCrop(drawing.id, {
958
- * topLeft: { x: 0, y: 0 },
959
- * bottomRight: { x: 0.5, y: 1 },
960
- * })
961
- * await snaptrude.presentation.drawings.setCrop(drawing.id, null)
962
- * ```
963
- */
964
- public abstract setCrop(
965
- drawingId: string,
966
- crop: z.infer<typeof PluginPlacedViewCrop> | null,
967
- ): PluginApiReturn<PluginDrawing>
968
-
969
- /**
970
- * Read a drawing's effective style categories (preset plus its own
971
- * overrides) and the controls each category accepts. Always read this
972
- * before {@linkcode PluginPresentationDrawingsApi.updateStyles}: accepted
973
- * categories and controls depend on the drawing, and an `absent` category
974
- * rejects writes. Do not echo a whole `settings` record as a patch (legacy
975
- * reads may include the read-only `disable` flag and `-1` for unset opacity).
976
- *
977
- * @param drawingId - The drawing to read.
978
- * @returns A {@linkcode PluginDrawingStyles} with one row per category.
979
- * @throws `PRECONDITION_FAILED` if Present mode is not open;
980
- * `HANDLE_INVALID` if `drawingId` is not a drawing.
981
- *
982
- * @examplePrompt Show the editable styles for this drawing
983
- * @examplePrompt What line weight are the walls drawn with?
984
- * @examplePrompt Which categories can I restyle on this plan?
985
- *
986
- * # Example
987
- * ```ts
988
- * const styles = await snaptrude.presentation.drawings.getStyles(drawing.id)
989
- * const editable = styles.categories.filter((row) => !row.absent)
990
- * ```
991
- */
992
- public abstract getStyles(
993
- drawingId: string,
994
- ): PluginApiReturn<PluginDrawingStyles>
995
-
996
- /**
997
- * Merge a sparse style patch into one category of a drawing, as one Present
998
- * undo step. Nested objects merge rather than replace the row. Line and
999
- * outline weights are paper millimetres (0–2.11); opacity is 0–100; colours
1000
- * are `#rrggbb`. On a kernel plan the patch becomes the drawing's own
1001
- * overrides of its preset; other drawings take the legacy placed-view
1002
- * category patch. An absent category, an unsupported field or an invalid
1003
- * value rejects the whole write.
1004
- *
1005
- * @param drawingId - The drawing to restyle.
1006
- * @param category - A category id from `getStyles` whose `absent` is false.
1007
- * @param patch - A sparse {@linkcode PluginDrawingStylePatch} using only the
1008
- * controls `getStyles` lists for that category.
1009
- * @returns The drawing's {@linkcode PluginDrawingStyles} after the write.
1010
- * @throws `VALIDATION` for an unsupported field or a value outside its
1011
- * range; `PRECONDITION_FAILED` if Present mode is not open, the document is
1012
- * read-only, the drawing is locked, or the category is absent on this
1013
- * drawing (each with a hint); `HANDLE_INVALID` if `drawingId` is not a
1014
- * drawing.
1015
- *
1016
- * @examplePrompt Make the walls on this drawing thicker
1017
- * @examplePrompt Fill the rooms at 60% opacity with a larger hatch
1018
- * @examplePrompt Turn off the door tags on this plan
1019
- *
1020
- * # Example
1021
- * ```ts
1022
- * const styles = await snaptrude.presentation.drawings.getStyles(drawing.id)
1023
- * const space = styles.categories.find((row) => row.category === "Space")
1024
- * if (space && !space.absent && space.controls.some((control) => control.key === "opacity")) {
1025
- * await snaptrude.presentation.drawings.updateStyles(drawing.id, "Space", {
1026
- * opacity: 60,
1027
- * pattern: { scale: 1.5 },
1028
- * })
1029
- * }
1030
- * ```
1031
- */
1032
- public abstract updateStyles(
1033
- drawingId: string,
1034
- category: string,
1035
- patch: PluginDrawingStylePatch,
1036
- ): PluginApiReturn<PluginDrawingStyles>
1037
-
1038
- /**
1039
- * Bind a native kernel plan to a view preset and clear its declared
1040
- * overrides, so it takes the preset's styles. Local title, proposal and
1041
- * building text is kept. One Present undo step. Presets apply only to
1042
- * drawings whose `getCapabilities(drawingId).presets` is `true`.
1043
- *
1044
- * @param drawingId - The kernel-plan drawing to bind.
1045
- * @param presetId - The preset to apply (an id from `viewPresets.list`).
1046
- * @returns The updated {@linkcode PluginDrawing} (its `presetId` is set).
1047
- * @throws `PRECONDITION_FAILED` if Present mode is not open, the document is
1048
- * read-only, the drawing is locked, or it is not a kernel vector plan
1049
- * (each with a hint); `VALIDATION` if the catalog has no preset
1050
- * `presetId` (with a hint); `HANDLE_INVALID` if `drawingId` is not a
1051
- * drawing.
1052
- *
1053
- * @examplePrompt Apply the presentation plan preset to this drawing
1054
- * @examplePrompt Use the Planning Issue style on every plan drawing
1055
- * @examplePrompt Make this drawing look like the other plans
1056
- *
1057
- * # Example
1058
- * ```ts
1059
- * const presets = await snaptrude.presentation.viewPresets.list()
1060
- * const preset = presets.find((each) => each.name === "Planning Issue")
1061
- * if (preset) await snaptrude.presentation.drawings.applyPreset(drawing.id, preset.id)
1062
- * ```
1063
- */
1064
- public abstract applyPreset(
1065
- drawingId: string,
1066
- presetId: string,
1067
- ): PluginApiReturn<PluginDrawing>
1068
-
1069
- /**
1070
- * Drop a kernel plan's own style overrides so it matches its bound preset
1071
- * again. Local title, proposal and building text is kept. One Present undo
1072
- * step.
1073
- *
1074
- * @param drawingId - The kernel-plan drawing to reset.
1075
- * @returns The updated {@linkcode PluginDrawing}.
1076
- * @throws `PRECONDITION_FAILED` if Present mode is not open, the document is
1077
- * read-only, the drawing is locked, or it is not a kernel vector plan
1078
- * (each with a hint); `HANDLE_INVALID` if `drawingId` is not a drawing.
1079
- *
1080
- * @examplePrompt Reset this drawing to its preset styles
1081
- * @examplePrompt Undo my style changes on the ground floor plan
1082
- * @examplePrompt Clear the overrides on this drawing
1083
- *
1084
- * # Example
1085
- * ```ts
1086
- * await snaptrude.presentation.drawings.resetOverrides(drawing.id)
1087
- * ```
1088
- */
1089
- public abstract resetOverrides(
1090
- drawingId: string,
1091
- ): PluginApiReturn<PluginDrawing>
1092
-
1093
- /**
1094
- * List the hatch patterns the native pattern catalog offers. Use these ids
1095
- * in a style patch's `pattern.id` instead of inventing one.
1096
- *
1097
- * @returns `{ id, label, group }` rows, one per pattern.
1098
- * @throws `PRECONDITION_FAILED` if Present mode is not open.
1099
- *
1100
- * @examplePrompt What hatch patterns can I use?
1101
- * @examplePrompt List the brick and concrete patterns
1102
- * @examplePrompt Which fill patterns are available for rooms?
1103
- *
1104
- * # Example
1105
- * ```ts
1106
- * const patterns = await snaptrude.presentation.drawings.listPatterns()
1107
- * const brick = patterns.find((pattern) => pattern.label.toLowerCase().includes("brick"))
1108
- * ```
1109
- */
1110
- public abstract listPatterns(): PluginApiReturn<
1111
- { id: string; label: string; group: string }[]
1112
- >
1113
-
1114
- /**
1115
- * List the font families drawing text can use, from the native catalog
1116
- * (`"DEFAULT"` first). Use these names in a style patch's `fontFamily`
1117
- * instead of inventing one.
1118
- *
1119
- * @returns Font family names.
1120
- * @throws `PRECONDITION_FAILED` if Present mode is not open.
1121
- *
1122
- * @examplePrompt Which fonts can I use for drawing labels?
1123
- * @examplePrompt Is Inter available as a drawing font?
1124
- * @examplePrompt List the fonts for the title block
1125
- *
1126
- * # Example
1127
- * ```ts
1128
- * const fonts = await snaptrude.presentation.drawings.listFonts()
1129
- * const family = fonts.includes("Inter") ? "Inter" : "DEFAULT"
1130
- * ```
1131
- */
1132
- public abstract listFonts(): PluginApiReturn<string[]>
1133
-
1134
- /**
1135
- * Export one drawing, with its labels and annotations, without a sheet.
1136
- * PDF size follows the drawing's canvas bounds; SVG and PDF keep vector
1137
- * content, raster fallbacks stay raster. `resolution` applies to raster
1138
- * formats. It does not wait for the canvas to paint, so it works while the
1139
- * user is on another browser tab.
1140
- * `download: true` starts a browser download and returns metadata only
1141
- * (never send large base64 to an agent); otherwise `files` carry
1142
- * `dataBase64`. `downloadStarted` means initiated, not proof of an OS-saved
1143
- * file. Layout warnings are returned.
1144
- * `fileName` is a base name WITHOUT an extension ("Floor Pattern View", never
1145
- * "Floor Pattern View.pdf"): the host appends .pdf/.svg/.png/.jpg for the
1146
- * format, and a name ending in .pdf, .svg, .png, .jpg or .jpeg, a dot or a
1147
- * space is rejected.
1148
- *
1149
- * @param drawingId - The drawing to export.
1150
- * @param format - `"pdf"`, `"svg"`, `"png"` or `"jpg"`.
1151
- * @param options - Optional `fileName` (base name, no extension),
1152
- * `resolution` (raster formats) and `download`.
1153
- * @returns A {@linkcode PluginDrawingExportResult}: the files, whether a
1154
- * download started, and layout warnings.
1155
- * @throws `VALIDATION` for a `fileName` with an extension or ending in a dot
1156
- * or space, or a bad `resolution`; `PRECONDITION_FAILED` if Present mode is
1157
- * not open or the drawing's asset is not ready yet (each with a hint);
1158
- * `HANDLE_INVALID` if `drawingId` is not a drawing; `OPERATION_FAILED` if
1159
- * the export failed.
1160
- *
1161
- * @examplePrompt Export this drawing as a PDF
1162
- * @examplePrompt Download the ground floor plan drawing as an SVG
1163
- * @examplePrompt Save this drawing as a high-resolution PNG
1164
- *
1165
- * # Example
1166
- * ```ts
1167
- * await snaptrude.presentation.drawings.getStatus(drawing.id, { waitMs: 10_000 })
1168
- * const result = await snaptrude.presentation.drawings.export(drawing.id, "pdf", {
1169
- * fileName: "Ground Floor Plan",
1170
- * download: true,
1171
- * })
1172
- * ```
1173
- */
1174
- public abstract export(
1175
- drawingId: string,
1176
- format: PluginDrawingExportFormat,
1177
- options?: PluginDrawingExportOptions,
1178
- ): PluginApiReturn<PluginDrawingExportResult>
1179
- }