@snaptrude/plugin-core 0.10.0 → 1.0.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 (229) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +187 -3
  3. package/api-manifest.json +929 -25
  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 +463 -0
  7. package/dist/api/core/camera/index.d.ts.map +1 -1
  8. package/dist/api/core/geom/create/index.d.ts +942 -101
  9. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  10. package/dist/api/core/geom/query/brep.d.ts +59 -2
  11. package/dist/api/core/geom/query/brep.d.ts.map +1 -1
  12. package/dist/api/core/geom/query/curve.d.ts +59 -35
  13. package/dist/api/core/geom/query/curve.d.ts.map +1 -1
  14. package/dist/api/core/geom/query/edge.d.ts +2 -2
  15. package/dist/api/core/geom/query/face.d.ts +105 -0
  16. package/dist/api/core/geom/query/face.d.ts.map +1 -1
  17. package/dist/api/core/geom/update/contour.d.ts +10 -2
  18. package/dist/api/core/geom/update/contour.d.ts.map +1 -1
  19. package/dist/api/core/geom/update/curve.d.ts +5 -5
  20. package/dist/api/core/geom/update/profile.d.ts +3 -1
  21. package/dist/api/core/geom/update/profile.d.ts.map +1 -1
  22. package/dist/api/core/handles/index.d.ts +4 -2
  23. package/dist/api/core/handles/index.d.ts.map +1 -1
  24. package/dist/api/core/index.d.ts +4 -4
  25. package/dist/api/core/index.d.ts.map +1 -1
  26. package/dist/api/core/io/import/index.d.ts +3 -1
  27. package/dist/api/core/io/import/index.d.ts.map +1 -1
  28. package/dist/api/core/layers.d.ts +377 -255
  29. package/dist/api/core/layers.d.ts.map +1 -1
  30. package/dist/api/core/mode/index.d.ts +19 -7
  31. package/dist/api/core/mode/index.d.ts.map +1 -1
  32. package/dist/api/core/project/index.d.ts +68 -1
  33. package/dist/api/core/project/index.d.ts.map +1 -1
  34. package/dist/api/core/proposals/index.d.ts +4 -3
  35. package/dist/api/core/proposals/index.d.ts.map +1 -1
  36. package/dist/api/core/storeys/index.d.ts +31 -2
  37. package/dist/api/core/storeys/index.d.ts.map +1 -1
  38. package/dist/api/core/storeys/layers.d.ts +408 -0
  39. package/dist/api/core/storeys/layers.d.ts.map +1 -0
  40. package/dist/api/core/tags.d.ts +84 -3
  41. package/dist/api/core/tags.d.ts.map +1 -1
  42. package/dist/api/core/zoom/index.d.ts +13 -0
  43. package/dist/api/core/zoom/index.d.ts.map +1 -1
  44. package/dist/api/design/bim.d.ts +299 -0
  45. package/dist/api/design/bim.d.ts.map +1 -0
  46. package/dist/api/design/boolean/index.d.ts +2 -0
  47. package/dist/api/design/boolean/index.d.ts.map +1 -1
  48. package/dist/api/design/catalog.d.ts +320 -0
  49. package/dist/api/design/catalog.d.ts.map +1 -0
  50. package/dist/api/design/create/bulk-items.d.ts +269 -0
  51. package/dist/api/design/create/bulk-items.d.ts.map +1 -0
  52. package/dist/api/design/create/grids.d.ts +132 -0
  53. package/dist/api/design/create/grids.d.ts.map +1 -0
  54. package/dist/api/design/create/index.d.ts +752 -78
  55. package/dist/api/design/create/index.d.ts.map +1 -1
  56. package/dist/api/design/create/opening-fields.d.ts +38 -0
  57. package/dist/api/design/create/opening-fields.d.ts.map +1 -0
  58. package/dist/api/design/delete/index.d.ts +5 -0
  59. package/dist/api/design/delete/index.d.ts.map +1 -1
  60. package/dist/api/design/dimensions.d.ts +427 -0
  61. package/dist/api/design/dimensions.d.ts.map +1 -0
  62. package/dist/api/design/doors/index.d.ts +24 -23
  63. package/dist/api/design/doors/index.d.ts.map +1 -1
  64. package/dist/api/design/family.d.ts +1446 -0
  65. package/dist/api/design/family.d.ts.map +1 -0
  66. package/dist/api/design/furniture/index.d.ts +33 -0
  67. package/dist/api/design/furniture/index.d.ts.map +1 -1
  68. package/dist/api/design/grids.d.ts +237 -0
  69. package/dist/api/design/grids.d.ts.map +1 -0
  70. package/dist/api/design/index.d.ts +30 -0
  71. package/dist/api/design/index.d.ts.map +1 -1
  72. package/dist/api/design/networks.d.ts +1703 -0
  73. package/dist/api/design/networks.d.ts.map +1 -0
  74. package/dist/api/design/query/geometry/index.d.ts +33 -5
  75. package/dist/api/design/query/geometry/index.d.ts.map +1 -1
  76. package/dist/api/design/query/grids.d.ts +287 -0
  77. package/dist/api/design/query/grids.d.ts.map +1 -0
  78. package/dist/api/design/query/index.d.ts +143 -34
  79. package/dist/api/design/query/index.d.ts.map +1 -1
  80. package/dist/api/design/query/spaces.d.ts +5 -5
  81. package/dist/api/design/selection/index.d.ts +12 -12
  82. package/dist/api/design/types/index.d.ts +40 -24
  83. package/dist/api/design/types/index.d.ts.map +1 -1
  84. package/dist/api/design/update/index.d.ts +412 -8
  85. package/dist/api/design/update/index.d.ts.map +1 -1
  86. package/dist/api/design/visibility.d.ts +28 -0
  87. package/dist/api/design/visibility.d.ts.map +1 -1
  88. package/dist/api/design/windows/index.d.ts +8 -8
  89. package/dist/api/design/windows/index.d.ts.map +1 -1
  90. package/dist/api/entity/buildableEnvelope.d.ts +84 -2
  91. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
  92. package/dist/api/entity/referenceLine.d.ts +13 -1
  93. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  94. package/dist/api/entity/space.d.ts +12 -12
  95. package/dist/api/entity/story.d.ts +4 -4
  96. package/dist/api/presentation/aiInspiration.d.ts +24 -24
  97. package/dist/api/presentation/annotate.d.ts +38 -22
  98. package/dist/api/presentation/annotate.d.ts.map +1 -1
  99. package/dist/api/presentation/camera.d.ts +265 -0
  100. package/dist/api/presentation/camera.d.ts.map +1 -0
  101. package/dist/api/presentation/drawingContract.d.ts +32 -0
  102. package/dist/api/presentation/drawingContract.d.ts.map +1 -0
  103. package/dist/api/presentation/drawings.d.ts +3523 -0
  104. package/dist/api/presentation/drawings.d.ts.map +1 -0
  105. package/dist/api/presentation/export.d.ts +23 -5
  106. package/dist/api/presentation/export.d.ts.map +1 -1
  107. package/dist/api/presentation/graphics.d.ts +419 -0
  108. package/dist/api/presentation/graphics.d.ts.map +1 -0
  109. package/dist/api/presentation/index.d.ts +66 -12
  110. package/dist/api/presentation/index.d.ts.map +1 -1
  111. package/dist/api/presentation/placedViews.d.ts +116 -16
  112. package/dist/api/presentation/placedViews.d.ts.map +1 -1
  113. package/dist/api/presentation/sections.d.ts +461 -0
  114. package/dist/api/presentation/sections.d.ts.map +1 -0
  115. package/dist/api/presentation/shapes.d.ts +2 -2
  116. package/dist/api/presentation/sheets.d.ts +175 -19
  117. package/dist/api/presentation/sheets.d.ts.map +1 -1
  118. package/dist/api/presentation/standards.d.ts +590 -0
  119. package/dist/api/presentation/standards.d.ts.map +1 -0
  120. package/dist/api/presentation/viewPresets.d.ts +222 -0
  121. package/dist/api/presentation/viewPresets.d.ts.map +1 -0
  122. package/dist/api/presentation/views.d.ts +144 -9
  123. package/dist/api/presentation/views.d.ts.map +1 -1
  124. package/dist/api/presentation/walkthroughs.d.ts +1350 -0
  125. package/dist/api/presentation/walkthroughs.d.ts.map +1 -0
  126. package/dist/api/program/departments.d.ts +58 -2
  127. package/dist/api/program/departments.d.ts.map +1 -1
  128. package/dist/api/program/index.d.ts +16 -6
  129. package/dist/api/program/index.d.ts.map +1 -1
  130. package/dist/api/program/labels.d.ts +355 -0
  131. package/dist/api/program/labels.d.ts.map +1 -0
  132. package/dist/api/program/metadata.d.ts +328 -0
  133. package/dist/api/program/metadata.d.ts.map +1 -0
  134. package/dist/api/program/site.d.ts +4 -4
  135. package/dist/api/program/spreadsheet.d.ts +267 -4
  136. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  137. package/dist/api/workspace/index.d.ts +49 -2
  138. package/dist/api/workspace/index.d.ts.map +1 -1
  139. package/dist/errors/codes.d.ts +3 -1
  140. package/dist/errors/codes.d.ts.map +1 -1
  141. package/dist/handles.d.ts +32 -3
  142. package/dist/handles.d.ts.map +1 -1
  143. package/dist/index.cjs +6539 -2804
  144. package/dist/index.cjs.map +1 -1
  145. package/dist/index.d.ts +2 -0
  146. package/dist/index.d.ts.map +1 -1
  147. package/dist/index.js +6121 -2801
  148. package/dist/index.js.map +1 -1
  149. package/dist/massParameters.d.ts +287 -0
  150. package/dist/massParameters.d.ts.map +1 -0
  151. package/dist/massParameters.ops.d.ts +138 -0
  152. package/dist/massParameters.ops.d.ts.map +1 -0
  153. package/package.json +14 -13
  154. package/scripts/check-dist-fresh.mjs +22 -0
  155. package/scripts/generate-manifest.mjs +5 -0
  156. package/scripts/generate-manifest.test.mjs +14 -3
  157. package/src/api/core/camera/index.ts +446 -1
  158. package/src/api/core/geom/create/index.ts +1037 -102
  159. package/src/api/core/geom/query/brep.ts +60 -2
  160. package/src/api/core/geom/query/curve.ts +26 -2
  161. package/src/api/core/geom/query/edge.ts +2 -2
  162. package/src/api/core/geom/query/face.ts +109 -4
  163. package/src/api/core/geom/update/contour.ts +10 -2
  164. package/src/api/core/geom/update/profile.ts +2 -0
  165. package/src/api/core/handles/index.ts +3 -2
  166. package/src/api/core/index.ts +4 -4
  167. package/src/api/core/io/import/index.ts +11 -3
  168. package/src/api/core/layers.ts +380 -173
  169. package/src/api/core/mode/index.ts +19 -7
  170. package/src/api/core/project/index.ts +62 -1
  171. package/src/api/core/proposals/index.ts +4 -3
  172. package/src/api/core/storeys/index.ts +34 -2
  173. package/src/api/core/storeys/layers.ts +339 -0
  174. package/src/api/core/tags.ts +76 -0
  175. package/src/api/core/zoom/index.ts +13 -0
  176. package/src/api/design/bim.ts +210 -0
  177. package/src/api/design/boolean/index.ts +2 -0
  178. package/src/api/design/catalog.ts +203 -0
  179. package/src/api/design/create/bulk-items.ts +294 -0
  180. package/src/api/design/create/grids.ts +137 -0
  181. package/src/api/design/create/index.ts +823 -114
  182. package/src/api/design/create/opening-fields.ts +40 -0
  183. package/src/api/design/delete/index.ts +5 -0
  184. package/src/api/design/dimensions.ts +453 -0
  185. package/src/api/design/doors/index.ts +64 -41
  186. package/src/api/design/family.ts +1342 -0
  187. package/src/api/design/furniture/index.ts +34 -0
  188. package/src/api/design/grids.ts +237 -0
  189. package/src/api/design/index.ts +49 -4
  190. package/src/api/design/networks.ts +607 -0
  191. package/src/api/design/query/geometry/index.ts +35 -4
  192. package/src/api/design/query/grids.ts +197 -0
  193. package/src/api/design/query/index.ts +105 -3
  194. package/src/api/design/types/index.ts +31 -24
  195. package/src/api/design/update/index.ts +398 -4
  196. package/src/api/design/visibility.ts +34 -0
  197. package/src/api/design/windows/index.ts +40 -22
  198. package/src/api/entity/buildableEnvelope.ts +77 -2
  199. package/src/api/entity/referenceLine.ts +25 -12
  200. package/src/api/presentation/annotate.ts +90 -58
  201. package/src/api/presentation/camera.ts +289 -0
  202. package/src/api/presentation/drawingContract.ts +70 -0
  203. package/src/api/presentation/drawings.ts +1179 -0
  204. package/src/api/presentation/export.ts +32 -6
  205. package/src/api/presentation/graphics.ts +324 -0
  206. package/src/api/presentation/index.ts +73 -14
  207. package/src/api/presentation/placedViews.ts +119 -28
  208. package/src/api/presentation/sections.ts +420 -0
  209. package/src/api/presentation/sheets.ts +181 -20
  210. package/src/api/presentation/standards.ts +445 -0
  211. package/src/api/presentation/viewPresets.ts +241 -0
  212. package/src/api/presentation/views.ts +81 -10
  213. package/src/api/presentation/walkthroughs.ts +1201 -0
  214. package/src/api/program/departments.ts +54 -2
  215. package/src/api/program/index.ts +16 -6
  216. package/src/api/program/labels.ts +332 -0
  217. package/src/api/program/metadata.ts +364 -0
  218. package/src/api/program/spreadsheet.ts +282 -0
  219. package/src/api/workspace/index.ts +51 -2
  220. package/src/errors/codes.ts +7 -0
  221. package/src/handles.ts +42 -3
  222. package/src/index.ts +2 -0
  223. package/src/massParameters.ops.ts +246 -0
  224. package/src/massParameters.ts +427 -0
  225. package/test/drawingContract.test.mjs +288 -0
  226. package/test/errors.test.mjs +1 -0
  227. package/test/massParameters.test.mjs +952 -0
  228. package/test/paperPensContract.test.mjs +75 -0
  229. package/test/presentationViewSettings.test.mjs +85 -0
@@ -0,0 +1,445 @@
1
+ import * as z from "zod"
2
+ import type { PluginApiReturn } from "../../types"
3
+ import {
4
+ PluginGraphicsAnnotationCategory,
5
+ PluginGraphicsCategory,
6
+ PluginGraphicsLineStyleId,
7
+ PluginGraphicsModelCategory,
8
+ PluginGraphicsOverrideCategory,
9
+ PluginGraphicsPatternId,
10
+ PluginGraphicsPen,
11
+ PluginGraphicsScale,
12
+ PluginGraphicsViewId,
13
+ PluginGraphicsViewKind,
14
+ } from "./graphics"
15
+
16
+ /** All widths and annotation geometry here are paper millimetres, in either project unit system. */
17
+ export const PluginStandardUnits = z.enum(["METRIC", "IMPERIAL"])
18
+ export const PluginStandardWidth = z.union([
19
+ z.literal(0),
20
+ z.number().finite().min(0.02).max(12.7),
21
+ ])
22
+ const PenKey = z.string().regex(/^(?:[1-9]|1[0-6])$/)
23
+ const ScaleKey = z.string().refine((key) => {
24
+ const value = Number(key)
25
+ return (
26
+ String(value) === key &&
27
+ Number.isInteger(value) &&
28
+ value >= 1 &&
29
+ value <= 24000
30
+ )
31
+ }, "Use a canonical integer scale denominator from 1 to 24000")
32
+ const Color = z.string().regex(/^#[0-9a-f]{6}$/i)
33
+ const TextSize = z.number().finite().min(0.5).max(25)
34
+ const HeadRadius = z.number().finite().min(2).max(25)
35
+ const DimensionLength = z.number().finite().min(0).max(10)
36
+ const TickLength = z.number().finite().min(0.5).max(6)
37
+ const Background = z.enum(["opaque", "transparent"])
38
+
39
+ /** Stored sparse line-weight tables; a missing cell inherits the pinned stock. */
40
+ const StoredLineWeights = z
41
+ .object({
42
+ model: z.record(ScaleKey, z.record(PenKey, PluginStandardWidth)).optional(),
43
+ annotation: z.record(PenKey, PluginStandardWidth).optional(),
44
+ perspective: z.record(PenKey, PluginStandardWidth).optional(),
45
+ columns: z
46
+ .object({
47
+ added: z.array(PluginGraphicsScale).optional(),
48
+ deleted: z.array(PluginGraphicsScale).optional(),
49
+ })
50
+ .strict()
51
+ .optional(),
52
+ })
53
+ .strict()
54
+ const StoredObjectStyle = z
55
+ .object({
56
+ projection: PluginGraphicsPen.optional(),
57
+ cut: PluginGraphicsPen.optional(),
58
+ color: Color.optional(),
59
+ })
60
+ .strict()
61
+ const StoredText = z
62
+ .object({
63
+ Dimension: z.object({ textMm: TextSize.optional() }).strict().optional(),
64
+ Grids: z
65
+ .object({
66
+ textMm: TextSize.optional(),
67
+ bubbleRadiusMm: HeadRadius.optional(),
68
+ })
69
+ .strict()
70
+ .optional(),
71
+ Space: z
72
+ .object({
73
+ nameTextMm: TextSize.optional(),
74
+ areaTextMm: TextSize.optional(),
75
+ })
76
+ .strict()
77
+ .optional(),
78
+ Sections: z
79
+ .object({
80
+ textMm: TextSize.optional(),
81
+ headRadiusMm: HeadRadius.optional(),
82
+ })
83
+ .strict()
84
+ .optional(),
85
+ })
86
+ .strict()
87
+ const StoredDimension = z
88
+ .object({
89
+ tickMm: TickLength.optional(),
90
+ witnessGapMm: DimensionLength.optional(),
91
+ witnessExtensionMm: DimensionLength.optional(),
92
+ lineExtensionMm: DimensionLength.optional(),
93
+ textOffsetMm: DimensionLength.optional(),
94
+ textBackground: Background.optional(),
95
+ })
96
+ .strict()
97
+ const StoredLineStyle = z
98
+ .object({
99
+ weight: PluginGraphicsPen.optional(),
100
+ pattern: PluginGraphicsPatternId.optional(),
101
+ })
102
+ .strict()
103
+
104
+ /**
105
+ * The project's stored sparse graphic standard. stockId is read-only through
106
+ * the API: update never accepts it. The native commit pins a stock when needed;
107
+ * native standard-file import preserves a validated file's stock choice.
108
+ * Omitted values inherit stock defaults; all numeric lengths are paper mm.
109
+ */
110
+ export const PluginGraphicStandard = z
111
+ .object({
112
+ stockId: z.string().optional(),
113
+ lineWeights: StoredLineWeights.optional(),
114
+ objectStyles: z
115
+ .partialRecord(PluginGraphicsCategory, StoredObjectStyle)
116
+ .optional(),
117
+ annotationText: StoredText.optional(),
118
+ // Reads retain retired stored ids (e.g. property-line); update accepts current ids only.
119
+ lineStyles: z.record(z.string(), StoredLineStyle).optional(),
120
+ dimensionStyle: StoredDimension.optional(),
121
+ })
122
+ .strict()
123
+ export type PluginGraphicStandard = z.infer<typeof PluginGraphicStandard>
124
+
125
+ /**
126
+ * Column operations for one standard update, not the stored added/deleted lists.
127
+ * Added columns copy the currently resolved column. Only listed scales can be
128
+ * columns; at least one column must remain. reset restores a whole column,
129
+ * including an added column whose individual cells have no stock default.
130
+ */
131
+ export const PluginStandardColumnPatch = z
132
+ .object({
133
+ add: z.array(PluginGraphicsScale).optional(),
134
+ delete: z.array(PluginGraphicsScale).optional(),
135
+ reset: z.array(PluginGraphicsScale).optional(),
136
+ })
137
+ .strict()
138
+ .superRefine((ops, ctx) => {
139
+ const used = new Set<number>()
140
+ for (const field of ["add", "delete", "reset"] as const) {
141
+ for (const scale of new Set(ops[field] ?? [])) {
142
+ if (used.has(scale)) {
143
+ ctx.addIssue({
144
+ code: "custom",
145
+ path: [field],
146
+ message: "A column cannot have conflicting operations in one patch",
147
+ })
148
+ }
149
+ used.add(scale)
150
+ }
151
+ }
152
+ })
153
+ export type PluginStandardColumnPatch = z.infer<
154
+ typeof PluginStandardColumnPatch
155
+ >
156
+
157
+ const ObjectStylePatch = z
158
+ .object({
159
+ projection: PluginGraphicsPen.nullable().optional(),
160
+ cut: PluginGraphicsPen.nullable().optional(),
161
+ color: Color.nullable().optional(),
162
+ })
163
+ .strict()
164
+ const ObjectStylesPatch = z
165
+ .partialRecord(PluginGraphicsCategory, ObjectStylePatch)
166
+ .superRefine((rows, ctx) => {
167
+ for (const category of PluginGraphicsAnnotationCategory.options) {
168
+ const row = rows[category]
169
+ if (row?.cut !== undefined || row?.color !== undefined) {
170
+ ctx.addIssue({
171
+ code: "custom",
172
+ path: [category],
173
+ message: "Annotation Object Styles have only a projection pen",
174
+ })
175
+ }
176
+ }
177
+ })
178
+
179
+ /**
180
+ * Sparse edits, applied atomically as one native commit. Omitted leaves stay
181
+ * unchanged; null resets a leaf through its native setter. No stockId field.
182
+ * In an imperial project, newly edited nonzero widths must be at least 0.0254 mm
183
+ * (0.001in), even though API values are always paper mm. Native file import has
184
+ * its own cross-unit normalization and does not convert physical widths.
185
+ */
186
+ export const PluginGraphicStandardPatch = z
187
+ .object({
188
+ lineWeights: z
189
+ .object({
190
+ model: z
191
+ .record(ScaleKey, z.record(PenKey, PluginStandardWidth.nullable()))
192
+ .optional(),
193
+ annotation: z.record(PenKey, PluginStandardWidth.nullable()).optional(),
194
+ perspective: z
195
+ .record(PenKey, PluginStandardWidth.nullable())
196
+ .optional(),
197
+ columns: PluginStandardColumnPatch.optional(),
198
+ })
199
+ .strict()
200
+ .optional(),
201
+ objectStyles: ObjectStylesPatch.optional(),
202
+ annotationText: z
203
+ .object({
204
+ Dimension: z
205
+ .object({ textMm: TextSize.nullable().optional() })
206
+ .strict()
207
+ .optional(),
208
+ Grids: z
209
+ .object({
210
+ textMm: TextSize.nullable().optional(),
211
+ bubbleRadiusMm: HeadRadius.nullable().optional(),
212
+ })
213
+ .strict()
214
+ .optional(),
215
+ Space: z
216
+ .object({
217
+ nameTextMm: TextSize.nullable().optional(),
218
+ areaTextMm: TextSize.nullable().optional(),
219
+ })
220
+ .strict()
221
+ .optional(),
222
+ Sections: z
223
+ .object({
224
+ textMm: TextSize.nullable().optional(),
225
+ headRadiusMm: HeadRadius.nullable().optional(),
226
+ })
227
+ .strict()
228
+ .optional(),
229
+ })
230
+ .strict()
231
+ .optional(),
232
+ lineStyles: z
233
+ .partialRecord(
234
+ PluginGraphicsLineStyleId,
235
+ z
236
+ .object({
237
+ weight: PluginGraphicsPen.nullable().optional(),
238
+ pattern: PluginGraphicsPatternId.nullable().optional(),
239
+ })
240
+ .strict(),
241
+ )
242
+ .optional(),
243
+ dimensionStyle: z
244
+ .object({
245
+ tickMm: TickLength.nullable().optional(),
246
+ witnessGapMm: DimensionLength.nullable().optional(),
247
+ witnessExtensionMm: DimensionLength.nullable().optional(),
248
+ lineExtensionMm: DimensionLength.nullable().optional(),
249
+ textOffsetMm: DimensionLength.nullable().optional(),
250
+ textBackground: Background.nullable().optional(),
251
+ })
252
+ .strict()
253
+ .optional(),
254
+ })
255
+ .strict()
256
+ export type PluginGraphicStandardPatch = z.infer<
257
+ typeof PluginGraphicStandardPatch
258
+ >
259
+
260
+ /** Reset tab ids. text resets annotation sizes and dimension geometry together, like the UI. */
261
+ export const PluginGraphicStandardTab = z.enum([
262
+ "objectStyles",
263
+ "model",
264
+ "perspective",
265
+ "annotation",
266
+ "text",
267
+ "lineStyles",
268
+ ])
269
+ export type PluginGraphicStandardTab = z.infer<typeof PluginGraphicStandardTab>
270
+
271
+ /** A pen number with its physical paper width; 0 mm means hidden. */
272
+ const PenWidth = z.object({ pen: PluginGraphicsPen, mm: PluginStandardWidth })
273
+ const ResolvedModelStyle = z.object({
274
+ projection: PluginGraphicsPen,
275
+ cut: PluginGraphicsPen.nullable(),
276
+ projectionMm: PluginStandardWidth,
277
+ cutMm: PluginStandardWidth,
278
+ color: Color,
279
+ })
280
+ const ResolvedAnnotationStyle = z.object({
281
+ projection: PluginGraphicsPen,
282
+ lineMm: PluginStandardWidth,
283
+ })
284
+ const ResolvedLineStyle = z.object({
285
+ weight: PluginGraphicsPen,
286
+ pattern: PluginGraphicsPatternId,
287
+ mm: PluginStandardWidth,
288
+ })
289
+
290
+ /**
291
+ * Native resolved values for a target view/scale. Pens are numbered 1–16;
292
+ * widths, text, dash lengths and dimension geometry are paper mm. Model pens
293
+ * use the reported nearest column (finer column wins a tie). Perspective and
294
+ * annotation pens are scale-free. Category overrides are included where the
295
+ * native canvas applies them; hidden/halftone are arrays, never engine Sets.
296
+ * A disabled free3D renderer uses legacy widths, not these configured paper pens.
297
+ */
298
+ export const PluginResolvedGraphicStandard = z.object({
299
+ viewId: z.string().nullable(),
300
+ kind: PluginGraphicsViewKind,
301
+ units: PluginStandardUnits,
302
+ stockId: z.string(),
303
+ scale: PluginGraphicsScale,
304
+ column: PluginGraphicsScale,
305
+ columns: z.array(PluginGraphicsScale).min(1),
306
+ table: z.enum(["model", "perspective"]),
307
+ featureEnabled: z.boolean(),
308
+ viewOverridesApplied: z.boolean(),
309
+ pens: z.object({
310
+ model: z.array(PenWidth).length(16),
311
+ perspective: z.array(PenWidth).length(16),
312
+ annotation: z.array(PenWidth).length(16),
313
+ }),
314
+ model: z.record(PluginGraphicsModelCategory, ResolvedModelStyle),
315
+ annotation: z.record(
316
+ PluginGraphicsAnnotationCategory,
317
+ ResolvedAnnotationStyle,
318
+ ),
319
+ lines: z.record(PluginGraphicsLineStyleId, ResolvedLineStyle),
320
+ patterns: z.record(
321
+ PluginGraphicsPatternId,
322
+ z.array(z.number().finite().nonnegative()).max(8),
323
+ ),
324
+ text: z.object({
325
+ nameMm: TextSize,
326
+ areaMm: TextSize,
327
+ dimensionMm: TextSize,
328
+ gridTextMm: TextSize,
329
+ gridBubbleRadiusMm: HeadRadius,
330
+ sectionTextMm: TextSize,
331
+ sectionHeadRadiusMm: HeadRadius,
332
+ }),
333
+ dimension: z.object({
334
+ tickMm: TickLength,
335
+ witnessGapMm: DimensionLength,
336
+ witnessExtensionMm: DimensionLength,
337
+ lineExtensionMm: DimensionLength,
338
+ textOffsetMm: DimensionLength,
339
+ opaque: z.boolean(),
340
+ }),
341
+ hidden: z.array(PluginGraphicsOverrideCategory),
342
+ halftone: z.array(PluginGraphicsOverrideCategory),
343
+ })
344
+ export type PluginResolvedGraphicStandard = z.infer<
345
+ typeof PluginResolvedGraphicStandard
346
+ >
347
+
348
+ /**
349
+ * Resolve for the current view by default. A supplied denominator previews a
350
+ * different paper scale without moving the camera or writing the saved view.
351
+ * The table defaults to model for paper views and perspective for free3D.
352
+ */
353
+ export const PluginGraphicStandardResolveOptions = z
354
+ .object({
355
+ viewId: PluginGraphicsViewId.optional(),
356
+ scale: PluginGraphicsScale.optional(),
357
+ table: z.enum(["model", "perspective"]).optional(),
358
+ })
359
+ .strict()
360
+ export type PluginGraphicStandardResolveOptions = z.infer<
361
+ typeof PluginGraphicStandardResolveOptions
362
+ >
363
+ export const PluginGraphicStandardResolveArgs = z
364
+ .object({ options: PluginGraphicStandardResolveOptions.optional() })
365
+ .strict()
366
+ export const PluginGraphicStandardUpdateArgs = z
367
+ .object({ patch: PluginGraphicStandardPatch })
368
+ .strict()
369
+ export const PluginGraphicStandardResetArgs = z
370
+ .object({ tab: PluginGraphicStandardTab.optional() })
371
+ .strict()
372
+ export const PluginGraphicStandardImportArgs = z
373
+ .object({ text: z.string() })
374
+ .strict()
375
+
376
+ /**
377
+ * Project graphic standards, shared across views and saved through the same
378
+ * undoable native commit as Object Styles. No team standard access or writes.
379
+ * Do not write stockId: update refuses it, while the native commit pins the
380
+ * appropriate stock. Validated file import follows the UI's version/stock rules.
381
+ * All writes are flag-gated; reads and export remain available with the flag off.
382
+ */
383
+ export abstract class PluginPresentationStandardsApi {
384
+ /**
385
+ * Read the stored sparse standard; omitted fields inherit stock values.
386
+ * @returns A detached settings record. stockId is read-only through this API.
387
+ */
388
+ public abstract get(): PluginApiReturn<PluginGraphicStandard>
389
+
390
+ /**
391
+ * Read the actual native resolution, including applicable view overrides.
392
+ * No camera, view, preference or project data changes.
393
+ * @param options - Target view, denominator and optional model/perspective table.
394
+ * @returns Resolved paper-mm values, or null for an unknown/inaccessible explicit view.
395
+ * @examplePrompt How thick are the wall cut lines at 1:50?
396
+ * @example await snaptrude.presentation.standards.getResolved({ scale: 50, table: "model" })
397
+ */
398
+ public abstract getResolved(
399
+ options?: PluginGraphicStandardResolveOptions,
400
+ ): PluginApiReturn<PluginResolvedGraphicStandard | null>
401
+
402
+ /**
403
+ * Apply only supplied fields as one saved, undoable native commit. Validate
404
+ * the whole patch first; invalid fields never leave a partial edit behind.
405
+ * @param patch - Sparse edits; lengths are paper mm, pens are integers 1–16.
406
+ * @returns The resulting stored sparse standard.
407
+ * @throws VALIDATION for invalid/unknown fields, imperial minima, invalid
408
+ * columns or stockId. PRECONDITION_FAILED while Paper Pens is disabled.
409
+ * @examplePrompt Make wall cut lines heavier throughout the project
410
+ * @example await snaptrude.presentation.standards.update({ objectStyles: { Walls: { cut: 6 } } })
411
+ */
412
+ public abstract update(
413
+ patch: PluginGraphicStandardPatch,
414
+ ): PluginApiReturn<PluginGraphicStandard>
415
+
416
+ /**
417
+ * Reset an editable tab, or all tabs, through the native reset functions.
418
+ * One saved undo step; stock retention/pruning follows the native commit.
419
+ * @param tab - Omit for all tabs. text includes dimension geometry.
420
+ * @returns The resulting stored standard.
421
+ */
422
+ public abstract reset(
423
+ tab?: PluginGraphicStandardTab,
424
+ ): PluginApiReturn<PluginGraphicStandard>
425
+
426
+ /**
427
+ * Serialize the native standard-file format. No browser download or save.
428
+ * The file includes its stock/version and stores widths in paper mm.
429
+ * @returns JSON text suitable for import in another project, including cross-unit import.
430
+ * @examplePrompt Export the line standard
431
+ */
432
+ public abstract export(): PluginApiReturn<string>
433
+
434
+ /**
435
+ * Import native standard-file JSON exactly as the dialog does, replacing the
436
+ * project standard in one saved undo step. Never edits team preferences.
437
+ * @param text - File text, at most 1,000,000 UTF-8 bytes.
438
+ * @returns The resulting stored standard.
439
+ * @throws VALIDATION with details.reason NOT_A_STANDARD, NEWER_STANDARD or
440
+ * STANDARD_TOO_LARGE. PRECONDITION_FAILED with reason PAPER_PENS_DISABLED
441
+ * when the feature is off. Existing project data is unchanged on failure.
442
+ * @examplePrompt Match the line weights in this standard file
443
+ */
444
+ public abstract import(text: string): PluginApiReturn<PluginGraphicStandard>
445
+ }
@@ -0,0 +1,241 @@
1
+ import * as z from "zod"
2
+ import type { PluginApiReturn } from "../../types"
3
+
4
+ /** Presets are document-local. Their ids are stable across reload; built-ins are immutable. */
5
+ export const PluginViewPreset = z.object({
6
+ id: z.string(),
7
+ name: z.string(),
8
+ builtIn: z.boolean(),
9
+ revision: z.number().int().nonnegative(),
10
+ })
11
+ export type PluginViewPreset = z.infer<typeof PluginViewPreset>
12
+ export const PluginViewPresetIdArgs = z
13
+ .object({ presetId: z.string().min(1) })
14
+ .strict()
15
+ export type PluginViewPresetIdArgs = z.infer<typeof PluginViewPresetIdArgs>
16
+ export const PluginViewPresetCreateArgs = z
17
+ .object({ name: z.string().trim().min(1), fromDrawingId: z.string().min(1) })
18
+ .strict()
19
+ export type PluginViewPresetCreateArgs = z.infer<
20
+ typeof PluginViewPresetCreateArgs
21
+ >
22
+ export const PluginViewPresetRenameArgs = PluginViewPresetIdArgs.extend({
23
+ name: z.string().trim().min(1),
24
+ })
25
+ export type PluginViewPresetRenameArgs = z.infer<
26
+ typeof PluginViewPresetRenameArgs
27
+ >
28
+ export const PluginViewPresetUpdateArgs = PluginViewPresetIdArgs.extend({
29
+ fromDrawingId: z.string().min(1),
30
+ })
31
+ export type PluginViewPresetUpdateArgs = z.infer<
32
+ typeof PluginViewPresetUpdateArgs
33
+ >
34
+ export const PluginViewPresetDeleteArgs = PluginViewPresetIdArgs.extend({
35
+ replacementId: z.string().min(1),
36
+ })
37
+ export type PluginViewPresetDeleteArgs = z.infer<
38
+ typeof PluginViewPresetDeleteArgs
39
+ >
40
+
41
+ /**
42
+ * Reusable styles for kernel-plan drawings, stored in the Present document.
43
+ *
44
+ * A preset holds every style category of a native kernel plan. A drawing is
45
+ * bound to one with {@linkcode PluginPresentationDrawingsApi.applyPreset}; its
46
+ * own style changes are overrides on top, dropped by
47
+ * {@linkcode PluginPresentationDrawingsApi.resetOverrides}. Presets apply only
48
+ * to drawings whose `drawings.getCapabilities(drawingId).presets` is `true`.
49
+ * Local title text is excluded from preset values.
50
+ *
51
+ * Presets are document-local; their ids survive reload. Built-in presets are
52
+ * immutable. Catalog writes (`create`, `copy`, `rename`, `update`, `delete`)
53
+ * are native document metadata and are **not undoable**; binding a drawing or
54
+ * changing its overrides uses Present undo. Every method requires **Present
55
+ * mode to be open** and throws `PRECONDITION_FAILED` ("Present mode is not
56
+ * open") when it is closed; no method switches tabs.
57
+ *
58
+ * Accessed via `snaptrude.presentation.viewPresets`.
59
+ */
60
+ export abstract class PluginPresentationViewPresetsApi {
61
+ /**
62
+ * List the preset catalog: built-ins first, then custom presets by name.
63
+ *
64
+ * @returns Every {@linkcode PluginViewPreset}.
65
+ * @throws `PRECONDITION_FAILED` if Present mode is not open.
66
+ *
67
+ * @examplePrompt List the available drawing style presets
68
+ * @examplePrompt Which custom presets does this presentation have?
69
+ * @examplePrompt Is there a Planning Issue preset?
70
+ *
71
+ * # Example
72
+ * ```ts
73
+ * const presets = await snaptrude.presentation.viewPresets.list()
74
+ * const custom = presets.filter((preset) => !preset.builtIn)
75
+ * ```
76
+ */
77
+ public abstract list(): PluginApiReturn<PluginViewPreset[]>
78
+
79
+ /**
80
+ * Read one preset by id.
81
+ *
82
+ * @param presetId - The preset to read.
83
+ * @returns The {@linkcode PluginViewPreset}, or `null` if no preset has that id.
84
+ * @throws `PRECONDITION_FAILED` if Present mode is not open.
85
+ *
86
+ * @examplePrompt Which preset is this drawing using?
87
+ * @examplePrompt Is this preset a built-in one?
88
+ * @examplePrompt Read the preset bound to the ground floor plan
89
+ *
90
+ * # Example
91
+ * ```ts
92
+ * const drawing = await snaptrude.presentation.drawings.get(drawingId)
93
+ * const preset = drawing?.presetId
94
+ * ? await snaptrude.presentation.viewPresets.get(drawing.presetId)
95
+ * : null
96
+ * ```
97
+ */
98
+ public abstract get(
99
+ presetId: string,
100
+ ): PluginApiReturn<PluginViewPreset | null>
101
+
102
+ /**
103
+ * Save a kernel-plan drawing's effective styles as a new custom preset and
104
+ * bind that drawing to it. Not undoable (catalog write).
105
+ *
106
+ * @param name - A unique preset name (non-empty after trimming).
107
+ * @param options - `fromDrawingId`: the kernel-plan drawing to take styles from.
108
+ * @returns The new {@linkcode PluginViewPreset}.
109
+ * @throws `VALIDATION` for an empty or duplicate name (with a hint);
110
+ * `PRECONDITION_FAILED` if Present mode is not open, the document is
111
+ * read-only, or the drawing is not a kernel vector plan (each with a
112
+ * hint); `HANDLE_INVALID` if `fromDrawingId` is not a drawing.
113
+ *
114
+ * @examplePrompt Save this drawing's styles as a new preset
115
+ * @examplePrompt Make a preset called Planning Issue from this plan
116
+ * @examplePrompt Turn my restyled drawing into a reusable style
117
+ *
118
+ * # Example
119
+ * ```ts
120
+ * const capabilities = await snaptrude.presentation.drawings.getCapabilities(drawing.id)
121
+ * if (capabilities.presets) {
122
+ * const preset = await snaptrude.presentation.viewPresets.create("Planning Issue", {
123
+ * fromDrawingId: drawing.id,
124
+ * })
125
+ * }
126
+ * ```
127
+ */
128
+ public abstract create(
129
+ name: string,
130
+ options: { fromDrawingId: string },
131
+ ): PluginApiReturn<PluginViewPreset>
132
+
133
+ /**
134
+ * Duplicate a preset under a native-generated unique name. Drawing bindings
135
+ * do not change. Not undoable (catalog write). Built-ins can be copied.
136
+ *
137
+ * @param presetId - The preset to copy.
138
+ * @returns The new custom {@linkcode PluginViewPreset}.
139
+ * @throws `PRECONDITION_FAILED` if Present mode is not open or the document
140
+ * is read-only (each with a hint); `HANDLE_INVALID` if `presetId` does not
141
+ * exist.
142
+ *
143
+ * @examplePrompt Duplicate this preset
144
+ * @examplePrompt Make an editable copy of the built-in preset
145
+ * @examplePrompt Copy the Planning Issue preset so I can change it
146
+ *
147
+ * # Example
148
+ * ```ts
149
+ * const copy = await snaptrude.presentation.viewPresets.copy(preset.id)
150
+ * await snaptrude.presentation.viewPresets.rename(copy.id, "Planning Issue B")
151
+ * ```
152
+ */
153
+ public abstract copy(presetId: string): PluginApiReturn<PluginViewPreset>
154
+
155
+ /**
156
+ * Rename a custom preset. Names must stay unique; built-ins cannot be
157
+ * renamed. Not undoable (catalog write).
158
+ *
159
+ * @param presetId - The custom preset to rename.
160
+ * @param name - The new unique name (non-empty after trimming).
161
+ * @returns The renamed {@linkcode PluginViewPreset}.
162
+ * @throws `VALIDATION` when the catalog refuses: an empty or duplicate name,
163
+ * a built-in preset, or an unknown `presetId` (with a hint);
164
+ * `PRECONDITION_FAILED` if Present mode is not open or the document is
165
+ * read-only (each with a hint).
166
+ *
167
+ * @examplePrompt Rename this preset to Client Review
168
+ * @examplePrompt Call the copied preset Planning Issue B
169
+ * @examplePrompt Change the name of my custom drawing style
170
+ *
171
+ * # Example
172
+ * ```ts
173
+ * await snaptrude.presentation.viewPresets.rename(preset.id, "Client Review")
174
+ * ```
175
+ */
176
+ public abstract rename(
177
+ presetId: string,
178
+ name: string,
179
+ ): PluginApiReturn<PluginViewPreset>
180
+
181
+ /**
182
+ * Replace a custom preset's values with the effective styles of a drawing
183
+ * already bound to it, then refresh every bound drawing. Built-ins cannot
184
+ * be updated. Not undoable (catalog write).
185
+ *
186
+ * @param presetId - The custom preset to update.
187
+ * @param options - `fromDrawingId`: a kernel-plan drawing bound to this preset.
188
+ * @returns The updated {@linkcode PluginViewPreset} (its `revision` grows).
189
+ * @throws `VALIDATION` when the catalog refuses: a built-in preset (with a
190
+ * hint); `PRECONDITION_FAILED` if Present mode is not open, the document
191
+ * is read-only, or the drawing is not a kernel vector plan bound to this
192
+ * preset (each with a hint); `HANDLE_INVALID` if `fromDrawingId` is not a
193
+ * drawing.
194
+ *
195
+ * @examplePrompt Update this preset from the current drawing styles
196
+ * @examplePrompt Push my style changes to every drawing using this preset
197
+ * @examplePrompt Save these overrides into the Planning Issue preset
198
+ *
199
+ * # Example
200
+ * ```ts
201
+ * await snaptrude.presentation.viewPresets.update(drawing.presetId!, {
202
+ * fromDrawingId: drawing.id,
203
+ * })
204
+ * ```
205
+ */
206
+ public abstract update(
207
+ presetId: string,
208
+ options: { fromDrawingId: string },
209
+ ): PluginApiReturn<PluginViewPreset>
210
+
211
+ /**
212
+ * Delete a custom preset and rebind its drawings to another existing
213
+ * preset. Built-ins cannot be deleted. Not undoable (catalog write).
214
+ *
215
+ * @param presetId - The custom preset to delete.
216
+ * @param options - `replacementId`: the existing preset its drawings move to
217
+ * (not the deleted one).
218
+ * @returns Nothing.
219
+ * @throws `VALIDATION` when the catalog refuses: a built-in or unknown
220
+ * `presetId`, or an unknown `replacementId` (with a hint);
221
+ * `PRECONDITION_FAILED` if Present mode is not open or the document is
222
+ * read-only (each with a hint).
223
+ *
224
+ * @examplePrompt Delete this preset
225
+ * @examplePrompt Remove the old style preset and switch its drawings to the default
226
+ * @examplePrompt Get rid of the Planning Issue B preset
227
+ *
228
+ * # Example
229
+ * ```ts
230
+ * const presets = await snaptrude.presentation.viewPresets.list()
231
+ * const replacement = presets.find((each) => each.builtIn)!
232
+ * await snaptrude.presentation.viewPresets.delete(customPreset.id, {
233
+ * replacementId: replacement.id,
234
+ * })
235
+ * ```
236
+ */
237
+ public abstract delete(
238
+ presetId: string,
239
+ options: { replacementId: string },
240
+ ): PluginApiReturn<void>
241
+ }