lineadraw 0.8.0 → 0.10.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.
package/lineadraw.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  // GENERATED — do not edit. Typings for the virtual "lineadraw" and
2
2
  // "lineadraw/helpers" modules block scripts import from, emitted from
3
- // packages/core/src/extensions/{scriptTypes,scriptHelpers}.ts. Regenerate with:
3
+ // packages/core/src/extensions/{scriptTypes,scriptHelpers,scriptBooleans}.ts.
4
+ // Regenerate with:
4
5
  // npm run gen:lineadraw-dts -w @lineadraw/core
5
6
 
6
7
  declare module "lineadraw" {
@@ -10,20 +11,33 @@ declare module "lineadraw" {
10
11
  y: number;
11
12
  };
12
13
  export type Vec2Like = Vec2 | readonly [number, number];
14
+ /** An axis-aligned box (mm). */
15
+ export type Box = {
16
+ minX: number;
17
+ minY: number;
18
+ maxX: number;
19
+ maxY: number;
20
+ };
21
+ /** Arrowhead styles (leaders, dimensions). */
22
+ export type ArrowType = "filled" | "open" | "tick" | "dot" | "none";
23
+ /** Print color remap: as authored, gray levels, or everything black. */
24
+ export type PrintPalette = "color" | "grayscale" | "monochrome";
13
25
  /** Polyline vertex; bulge = tan(sweep/4), 0 = straight. Accepts [x, y, bulge?]. */
14
- export type PolylineVertexLike = {
26
+ export type PolylineVertexInput = {
15
27
  x: number;
16
28
  y: number;
17
29
  bulge?: number;
18
30
  } | readonly [number, number, number?];
19
- /** Style overrides children may carry (otherwise inherited from the instance). */
20
- export type BaseStyle = {
21
- /** Id of a document layer this object sits on. For a block child: absent
22
- * = the instance's layer (the portable default; an id unknown to the
23
- * document falls back to it); a child that names another layer hides
24
- * with that layer, while its color / line type / width still follow the
25
- * instance unless it sets its own (ByBlock, as in CAD). For
26
- * `document.add`: absent = the current layer. */
31
+ /** The fields every object input may carry: its layer and the style
32
+ * overrides (otherwise by layer — or, for a block child, by the instance). */
33
+ export type ObjectInputBase = {
34
+ /** The layer, by NAME or id. Absent: `document.add` uses the current
35
+ * layer, a block child the instance's (the portable default; an unknown
36
+ * name falls back to it too). A child on another layer hides with that
37
+ * layer, while its color / line type / width still follow the instance
38
+ * unless it sets its own (ByBlock, as in CAD). */
39
+ layer?: string;
40
+ /** The layer by id only — prefer `layer`. */
27
41
  layerId?: string;
28
42
  /** #rrggbb; absent = by layer. */
29
43
  color?: string;
@@ -37,37 +51,37 @@ declare module "lineadraw" {
37
51
  opacity?: number;
38
52
  };
39
53
  /**
40
- * T plus the shared style fields, FLATTENED (the homomorphic map forces the
54
+ * T plus the shared input fields, FLATTENED (the homomorphic map forces the
41
55
  * intersection to resolve): hovers then list every member inline instead of
42
- * the opaque `BaseStyle & { … }` — the block editor has no expand-type
43
- * affordance, so the alias display is all a script author gets.
56
+ * the opaque `ObjectInputBase & { … }` — the block editor has no
57
+ * expand-type affordance, so the alias display is all a script author gets.
44
58
  */
45
- type Styled<T> = {
46
- [K in keyof (T & BaseStyle)]: (T & BaseStyle)[K];
59
+ type ObjectInputShape<T> = {
60
+ [K in keyof (T & ObjectInputBase)]: (T & ObjectInputBase)[K];
47
61
  } & {};
48
- export type Line = Styled<{
62
+ export type LineInput = ObjectInputShape<{
49
63
  type: "line";
50
64
  a: Vec2Like;
51
65
  b: Vec2Like;
52
66
  }>;
53
67
  /** A point: paints as a round dot whose diameter is the lineWidth. */
54
- export type Point = Styled<{
68
+ export type PointInput = ObjectInputShape<{
55
69
  type: "point";
56
70
  p: Vec2Like;
57
71
  }>;
58
- export type Polyline = Styled<{
72
+ export type PolylineInput = ObjectInputShape<{
59
73
  type: "polyline";
60
74
  /** At least 2 vertices. */
61
- points: readonly PolylineVertexLike[];
75
+ points: readonly PolylineVertexInput[];
62
76
  closed?: boolean;
63
77
  }>;
64
- export type Circle = Styled<{
78
+ export type CircleInput = ObjectInputShape<{
65
79
  type: "circle";
66
80
  center: Vec2Like;
67
81
  radius: number;
68
82
  }>;
69
83
  /** Runs CCW from startAngle to endAngle (radians; DXF ARC convention). */
70
- export type Arc = Styled<{
84
+ export type ArcInput = ObjectInputShape<{
71
85
  type: "arc";
72
86
  center: Vec2Like;
73
87
  radius: number;
@@ -75,7 +89,7 @@ declare module "lineadraw" {
75
89
  endAngle: number;
76
90
  }>;
77
91
  /** majorAxis = endpoint vector from center; ratio = minor/major in (0, 1]. */
78
- export type Ellipse = Styled<{
92
+ export type EllipseInput = ObjectInputShape<{
79
93
  type: "ellipse";
80
94
  center: Vec2Like;
81
95
  majorAxis: Vec2Like;
@@ -83,11 +97,11 @@ declare module "lineadraw" {
83
97
  startAngle?: number;
84
98
  endAngle?: number;
85
99
  }>;
86
- export type Hatch = Styled<{
100
+ export type HatchInput = ObjectInputShape<{
87
101
  type: "hatch";
88
102
  /** loops[0] = outer boundary, the rest are holes (even-odd). */
89
103
  loops: readonly {
90
- points: readonly PolylineVertexLike[];
104
+ points: readonly PolylineVertexInput[];
91
105
  }[];
92
106
  fill?: {
93
107
  kind: "solid";
@@ -131,7 +145,7 @@ declare module "lineadraw" {
131
145
  height?: number;
132
146
  script?: "sub" | "super";
133
147
  };
134
- export type Text = Styled<{
148
+ export type TextInput = ObjectInputShape<{
135
149
  type: "text";
136
150
  position: Vec2Like;
137
151
  content: string;
@@ -150,20 +164,11 @@ declare module "lineadraw" {
150
164
  /** The document text style to follow (name or id); absent = the first. */
151
165
  styleId?: string;
152
166
  /** Style overrides; absent keys inherit the document text style. */
153
- styleOverride?: {
154
- font?: string;
155
- widthFactor?: number;
156
- bold?: boolean;
157
- italic?: boolean;
158
- /** Cap height in mm (before `scale`). */
159
- textHeight?: number;
160
- arrowSize?: number;
161
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
162
- };
167
+ styleOverride?: TextStyleOverride;
163
168
  /** Size multiplier for height + arrow size. */
164
169
  scale?: number;
165
170
  }>;
166
- export type Dimension = Styled<{
171
+ export type DimensionInput = ObjectInputShape<{
167
172
  type: "dimension";
168
173
  kind?: "linear" | "angular" | "radial" | "diameter";
169
174
  /** linear: 2+ chained points (measured point to point); angular: [vertex, a, b]; radial: [center, p]; diameter: [p1, p2]. */
@@ -188,33 +193,27 @@ declare module "lineadraw" {
188
193
  }[];
189
194
  /** The document dimension style to follow (name or id); absent = the first. */
190
195
  styleId?: string;
191
- styleOverride?: {
192
- textHeight?: number;
193
- arrowSize?: number;
194
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
195
- /** "short" = a 2×overshoot tick across the dimension line. */
196
- extensionType?: "long" | "short";
197
- extensionOffset?: number;
198
- extensionOvershoot?: number;
199
- textOffset?: number;
200
- precision?: number;
201
- };
196
+ /** Style overrides; absent keys inherit the document dimension style. */
197
+ styleOverride?: DimStyleOverride;
202
198
  /** Annotation size multiplier (text/arrows/offsets). */
203
199
  scale?: number;
204
200
  }>;
205
201
  /** Nested block instance (inputs may hold points, never object references). */
206
- export type Block = Styled<{
202
+ export type BlockInput = ObjectInputShape<{
207
203
  type: "block";
208
204
  definitionId: string;
209
205
  /** Applied last, about the pivot (the first input point). */
210
206
  rotation?: number;
211
207
  scale?: number;
212
- params?: Record<string, number | string | boolean | readonly number[] | readonly string[]>;
213
- /** Input points in the PARENT's local coords; the first is the pivot. */
214
- inputs?: readonly Vec2Like[];
208
+ params?: Record<string, number | string | boolean | readonly number[] | readonly string[] | JsonValue>;
209
+ /** Input points in the PARENT's local coords (the first is the pivot):
210
+ * in pick order, or by input name for a block declaring an `inputs`
211
+ * table. Object ids (a `host`, picked objects) only on instances a
212
+ * script ADDS to the document — a block's own children can't reference. */
213
+ inputs?: readonly Vec2Like[] | Readonly<Record<string, Vec2Like | readonly Vec2Like[] | string | readonly string[]>>;
215
214
  }>;
216
215
  /** A table cell: plain text, or text with merge / alignment / style. */
217
- export type TableCell = string | {
216
+ export type TableCellInput = string | {
218
217
  content?: string;
219
218
  /** Character formatting over `content`. */
220
219
  spans?: readonly TextSpan[];
@@ -231,7 +230,7 @@ declare module "lineadraw" {
231
230
  };
232
231
  /** Grid of text cells hanging right/down from `position` (top-left);
233
232
  * rows grow to fit their wrapped text. */
234
- export type Table = Styled<{
233
+ export type TableInput = ObjectInputShape<{
235
234
  type: "table";
236
235
  position: Vec2Like;
237
236
  /** Column widths (mm, before `scale`). */
@@ -241,7 +240,7 @@ declare module "lineadraw" {
241
240
  minHeight?: number;
242
241
  }[];
243
242
  /** Row-major `cells[row][column]`, exactly rows × columns. */
244
- cells: readonly (readonly TableCell[])[];
243
+ cells: readonly (readonly TableCellInput[])[];
245
244
  rotation?: number;
246
245
  scale?: number;
247
246
  /** Rows above the heavier header rule. */
@@ -252,16 +251,84 @@ declare module "lineadraw" {
252
251
  styleId?: string;
253
252
  styleOverride?: TextStyleOverride;
254
253
  }>;
254
+ /** Where a reference's file lives: a path (relative to the drawing's
255
+ * folder), a url, or EMBEDDED — an asset of the document holding it (add the
256
+ * file's bytes first with `document.addAsset`). */
257
+ export type ReferenceSource = {
258
+ kind: "path";
259
+ path: string;
260
+ cacheKey?: string;
261
+ } | {
262
+ kind: "url";
263
+ url: string;
264
+ } | {
265
+ kind: "asset";
266
+ assetId: string;
267
+ };
268
+ /** A file drawn in place — a .linea, DXF, DWG, PDF page or picture (PNG /
269
+ * JPEG). The file's origin lands at `position`; a picture draws at its
270
+ * natural size (96 dpi) times `scale`. */
271
+ export type ReferenceInput = ObjectInputShape<{
272
+ type: "reference";
273
+ format: "linea" | "dxf" | "dwg" | "pdf" | "png" | "jpg";
274
+ name: string;
275
+ source: ReferenceSource;
276
+ position: Vec2Like;
277
+ /** Radians CCW about `position`. */
278
+ rotation?: number;
279
+ scale?: number;
280
+ /** Flipped left-right (x → −x) before the rotation. */
281
+ mirrored?: boolean;
282
+ /** PDF: the 1-based page, drawn as vectors or rasterized. */
283
+ pdfPage?: number;
284
+ pdfMode?: "vector" | "raster";
285
+ /** The file's layers not drawn, by name. */
286
+ hiddenLayers?: readonly string[];
287
+ hidden?: boolean;
288
+ locked?: boolean;
289
+ /** Crop rectangle in file coordinates. */
290
+ clip?: Box;
291
+ /** Content bounds in file coordinates (the frame drawn before it loads). */
292
+ extent?: Box;
293
+ }>;
294
+ /** Paper-space window into model space; only in a layout (`document.add`
295
+ * with `layout`). */
296
+ export type ViewportInput = ObjectInputShape<{
297
+ type: "viewport";
298
+ /** The frame on the sheet (mm): bottom-left corner + size. */
299
+ rect: {
300
+ x: number;
301
+ y: number;
302
+ w: number;
303
+ h: number;
304
+ };
305
+ /** The model point shown at the frame's centre. */
306
+ modelCenter?: Vec2Like;
307
+ /** Drawing-scale denominator (model mm per paper mm); 1:50 => 50. */
308
+ scale?: number;
309
+ /** Pinned: no pan/zoom-through, no move/resize handles. */
310
+ locked?: boolean;
311
+ /** Layer ids hidden in this viewport only. */
312
+ hiddenLayerIds?: readonly string[];
313
+ }>;
314
+ /** Review note pinned to a point; the editor shows a screen-fixed marker. */
315
+ export type CommentInput = ObjectInputShape<{
316
+ type: "comment";
317
+ /** Tail tip of the bubble (world/sheet mm). */
318
+ position: Vec2Like;
319
+ text?: string;
320
+ tags?: readonly string[];
321
+ }>;
255
322
  /** What a script WRITES — the union of the authoring DTOs above (what
256
- * `draw` returns, what `document.add` takes). Read results are
257
- * `StoredObject`. */
258
- export type ObjectInput = Line | Point | Polyline | Circle | Arc | Ellipse | Hatch | Text | Dimension | Block | Table;
259
- /** @deprecated The input union is `ObjectInput`; in the SDK and core
260
- * `ModelObject` is the STORED shape, so this name misled. Kept so existing
261
- * scripts compile. */
262
- export type ModelObject = ObjectInput;
323
+ * `document.add` takes). Reads return `ModelObject`. */
324
+ export type ModelObjectInput = LineInput | PointInput | PolylineInput | CircleInput | ArcInput | EllipseInput | HatchInput | TextInput | DimensionInput | BlockInput | TableInput | ViewportInput | CommentInput | ReferenceInput;
325
+ /** One child a block's `draw` may return: every input except viewports and
326
+ * comments (both are drawn only as a space's own objects — a block's would
327
+ * never show). An `asset` reference resolves in the document the instance
328
+ * lives in. */
329
+ export type BlockChildInput = Exclude<ModelObjectInput, ViewportInput | CommentInput>;
263
330
  /** Identity + shared style fields every stored object carries. */
264
- export type StoredObjectBase = {
331
+ export type ObjectBase = {
265
332
  id: string;
266
333
  layerId: string;
267
334
  /** #rrggbb override; absent = by layer. */
@@ -273,43 +340,43 @@ declare module "lineadraw" {
273
340
  opacity?: number;
274
341
  };
275
342
  /** Flattens base + per-type fields so hovers list every member inline
276
- * (same trick as Styled<T> for the authoring DTOs). */
277
- type StoredShape<T> = {
278
- [K in keyof (T & StoredObjectBase)]: (T & StoredObjectBase)[K];
343
+ * (same trick as ObjectInputShape<T> for the authoring DTOs). */
344
+ type ObjectShape<T> = {
345
+ [K in keyof (T & ObjectBase)]: (T & ObjectBase)[K];
279
346
  } & {};
280
347
  /** Stored polyline vertex — bulge always present (default 0 applied). */
281
- export type StoredPolylineVertex = {
348
+ export type PolylineVertex = {
282
349
  x: number;
283
350
  y: number;
284
351
  bulge: number;
285
352
  };
286
- export type StoredLine = StoredShape<{
353
+ export type Line = ObjectShape<{
287
354
  type: "line";
288
355
  a: Vec2;
289
356
  b: Vec2;
290
357
  }>;
291
- export type StoredPoint = StoredShape<{
358
+ export type Point = ObjectShape<{
292
359
  type: "point";
293
360
  p: Vec2;
294
361
  }>;
295
- export type StoredPolyline = StoredShape<{
362
+ export type Polyline = ObjectShape<{
296
363
  type: "polyline";
297
- points: readonly StoredPolylineVertex[];
364
+ points: readonly PolylineVertex[];
298
365
  closed: boolean;
299
366
  }>;
300
- export type StoredCircle = StoredShape<{
367
+ export type Circle = ObjectShape<{
301
368
  type: "circle";
302
369
  center: Vec2;
303
370
  radius: number;
304
371
  }>;
305
- export type StoredArc = StoredShape<{
372
+ export type Arc = ObjectShape<{
306
373
  type: "arc";
307
374
  center: Vec2;
308
375
  radius: number;
309
376
  startAngle: number;
310
377
  endAngle: number;
311
378
  }>;
312
- export type StoredEllipse = StoredShape<{
379
+ export type Ellipse = ObjectShape<{
313
380
  type: "ellipse";
314
381
  center: Vec2;
315
382
  majorAxis: Vec2;
@@ -317,7 +384,7 @@ declare module "lineadraw" {
317
384
  startAngle: number;
318
385
  endAngle: number;
319
386
  }>;
320
- export type StoredHatchFill = {
387
+ export type HatchFill = {
321
388
  kind: "solid";
322
389
  } | {
323
390
  kind: "pattern";
@@ -337,16 +404,16 @@ declare module "lineadraw" {
337
404
  color2: string;
338
405
  angle: number;
339
406
  };
340
- export type StoredHatch = StoredShape<{
407
+ export type Hatch = ObjectShape<{
341
408
  type: "hatch";
342
409
  /** loops[0] = outer boundary, the rest are holes (even-odd). */
343
410
  loops: readonly {
344
- points: readonly StoredPolylineVertex[];
411
+ points: readonly PolylineVertex[];
345
412
  }[];
346
- fill: StoredHatchFill;
413
+ fill: HatchFill;
347
414
  scale: number;
348
415
  }>;
349
- export type StoredText = StoredShape<{
416
+ export type Text = ObjectShape<{
350
417
  type: "text";
351
418
  position: Vec2;
352
419
  content: string;
@@ -359,19 +426,11 @@ declare module "lineadraw" {
359
426
  frame?: "none" | "rectangle" | "circle" | "slot" | "bottom" | "firstLine";
360
427
  styleId?: string;
361
428
  /** Only the keys the user actually overrode on this text. */
362
- styleOverride?: {
363
- font?: string;
364
- widthFactor?: number;
365
- bold?: boolean;
366
- italic?: boolean;
367
- textHeight?: number;
368
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
369
- arrowSize?: number;
370
- };
429
+ styleOverride?: TextStyleOverride;
371
430
  rotation: number;
372
431
  scale: number;
373
432
  }>;
374
- export type StoredDimension = StoredShape<{
433
+ export type Dimension = ObjectShape<{
375
434
  type: "dimension";
376
435
  kind: "linear" | "angular" | "radial" | "diameter";
377
436
  points: readonly Vec2[];
@@ -385,33 +444,21 @@ declare module "lineadraw" {
385
444
  }[];
386
445
  styleId?: string;
387
446
  /** Only the keys the user actually overrode on this dimension. */
388
- styleOverride?: {
389
- font?: string;
390
- widthFactor?: number;
391
- bold?: boolean;
392
- italic?: boolean;
393
- textHeight?: number;
394
- textOffset?: number;
395
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
396
- arrowSize?: number;
397
- extensionType?: "long" | "short";
398
- extensionOffset?: number;
399
- extensionOvershoot?: number;
400
- precision?: number;
401
- };
447
+ styleOverride?: DimStyleOverride;
402
448
  scale: number;
403
449
  }>;
404
- export type StoredBlock = StoredShape<{
450
+ export type Block = ObjectShape<{
405
451
  type: "block";
406
452
  definitionId: string;
407
453
  rotation: number;
408
454
  scale: number;
409
- params: Readonly<Record<string, number | string | boolean | readonly number[] | readonly string[]>>;
410
- /** World points and/or referenced object ids, in pick order. */
411
- inputs: readonly (Vec2 | string)[];
455
+ params: Readonly<Record<string, number | string | boolean | readonly number[] | readonly string[] | JsonValue>>;
456
+ /** World points and/or referenced object ids: in pick order, or by
457
+ * input name for a block declaring an `inputs` table. */
458
+ inputs: readonly (Vec2 | string)[] | Readonly<Record<string, Vec2 | string | readonly Vec2[] | readonly string[]>>;
412
459
  }>;
413
460
  /** Paper-space window into model space; exists only in layout spaces. */
414
- export type StoredViewport = StoredShape<{
461
+ export type Viewport = ObjectShape<{
415
462
  type: "viewport";
416
463
  rect: {
417
464
  x: number;
@@ -425,29 +472,13 @@ declare module "lineadraw" {
425
472
  locked: boolean;
426
473
  hiddenLayerIds: readonly string[];
427
474
  }>;
428
- /** Raster reference; pixels live in the document's assets map. */
429
- export type StoredImage = StoredShape<{
430
- type: "image";
431
- assetId: string;
432
- origin: Vec2;
433
- width: number;
434
- height: number;
435
- rotation: number;
436
- }>;
437
- /** A LINKED file drawn in place (an xref); the document holds only this
438
- * record — the file's content is not readable from scripts. */
439
- export type StoredReference = StoredShape<{
475
+ /** A file drawn in place — linked (an xref) or embedded in the document's
476
+ * assets; the file's content is not readable from scripts. */
477
+ export type Reference = ObjectShape<{
440
478
  type: "reference";
441
479
  format: "linea" | "dxf" | "dwg" | "pdf" | "png" | "jpg";
442
480
  name: string;
443
- source: {
444
- kind: "path";
445
- path: string;
446
- cacheKey?: string;
447
- } | {
448
- kind: "url";
449
- url: string;
450
- };
481
+ source: ReferenceSource;
451
482
  /** Where the file's origin lands. */
452
483
  position: Vec2;
453
484
  rotation: number;
@@ -462,22 +493,12 @@ declare module "lineadraw" {
462
493
  /** Locked in the References panel: drawn and snapped, never picked. */
463
494
  locked?: boolean;
464
495
  /** Crop rectangle in file coordinates. */
465
- clip?: {
466
- minX: number;
467
- minY: number;
468
- maxX: number;
469
- maxY: number;
470
- };
496
+ clip?: Box;
471
497
  /** Content bounds in file coordinates at the last load. */
472
- extent?: {
473
- minX: number;
474
- minY: number;
475
- maxX: number;
476
- maxY: number;
477
- };
498
+ extent?: Box;
478
499
  }>;
479
500
  /** Review note pinned to a point; the editor shows a screen-fixed marker. */
480
- export type StoredComment = StoredShape<{
501
+ export type Comment = ObjectShape<{
481
502
  type: "comment";
482
503
  /** Tail tip of the bubble (world/sheet mm). */
483
504
  position: Vec2;
@@ -485,17 +506,11 @@ declare module "lineadraw" {
485
506
  tags: readonly string[];
486
507
  }>;
487
508
  /** Text style keys a text, table or table cell may override. */
488
- export type TextStyleOverride = {
489
- font?: string;
490
- widthFactor?: number;
491
- bold?: boolean;
492
- italic?: boolean;
493
- textHeight?: number;
494
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
495
- arrowSize?: number;
496
- };
509
+ export type TextStyleOverride = Partial<Omit<TextStyle, "id" | "name">>;
510
+ /** Dimension style keys a dimension may override. */
511
+ export type DimStyleOverride = Partial<Omit<DimStyle, "id" | "name">>;
497
512
  /** One table cell as stored. */
498
- export type StoredTableCell = {
513
+ export type TableCell = {
499
514
  /** Plain text; "\n" = line break. */
500
515
  content: string;
501
516
  spans?: readonly TextSpan[];
@@ -511,7 +526,7 @@ declare module "lineadraw" {
511
526
  color?: string;
512
527
  };
513
528
  /** Grid of text cells hanging right/down from `position` (top-left). */
514
- export type StoredTable = StoredShape<{
529
+ export type Table = ObjectShape<{
515
530
  type: "table";
516
531
  position: Vec2;
517
532
  rotation: number;
@@ -522,7 +537,7 @@ declare module "lineadraw" {
522
537
  minHeight?: number;
523
538
  }[];
524
539
  /** Row-major `cells[row][column]`. */
525
- cells: readonly (readonly StoredTableCell[])[];
540
+ cells: readonly (readonly TableCell[])[];
526
541
  headerRows: number;
527
542
  cellMargin: number;
528
543
  borders: "all" | "outer" | "rows" | "none";
@@ -530,13 +545,13 @@ declare module "lineadraw" {
530
545
  styleOverride?: TextStyleOverride;
531
546
  }>;
532
547
  /** Any object as stored in the document — what reads hand to scripts. */
533
- export type StoredObject = StoredLine | StoredPoint | StoredPolyline | StoredCircle | StoredArc | StoredEllipse | StoredHatch | StoredText | StoredDimension | StoredBlock | StoredViewport | StoredImage | StoredComment | StoredTable | StoredReference;
548
+ export type ModelObject = Line | Point | Polyline | Circle | Arc | Ellipse | Hatch | Text | Dimension | Block | Viewport | Comment | Table | Reference;
534
549
  /**
535
550
  * One choice of a "Select" parameter: the value (what scripts receive) with
536
551
  * an optional properties-panel label. A plain string is shorthand for
537
552
  * `{ value }`.
538
553
  */
539
- export type ParameterOption = string | {
554
+ export type ParamOption = string | {
540
555
  value: string;
541
556
  label?: string;
542
557
  /** A `#rrggbb` color square before the option's label. */
@@ -613,7 +628,7 @@ declare module "lineadraw" {
613
628
  }) | (ParamBase & {
614
629
  type: "enum";
615
630
  default: string;
616
- options: readonly ParameterOption[];
631
+ options: readonly ParamOption[];
617
632
  /** "buttons": a segmented toggle group of the options (short
618
633
  * choices); falls back to the dropdown when they don't fit. */
619
634
  display?: "dropdown" | "buttons";
@@ -631,6 +646,12 @@ declare module "lineadraw" {
631
646
  * value: it never appears in the `params` record `draw` receives.
632
647
  * `name` stays the unique key (paramVisibility can hide it by name). */
633
648
  | (ParamBase & {
649
+ /** Structured data the block owns (any JSON value) — no panel row;
650
+ * edited through handles, handle menus and actions. Typed by its
651
+ * default: `default: {} as Record<string, Wall>`. */
652
+ type: "data";
653
+ default: JsonValue;
654
+ }) | (ParamBase & {
634
655
  type: "label";
635
656
  })
636
657
  /** Layout only: 2–3 compact params on one panel row, each item's label a
@@ -639,9 +660,10 @@ declare module "lineadraw" {
639
660
  type: "row";
640
661
  items: readonly RowItemDef[];
641
662
  });
642
- /** A document text style as `draw` reads it (`styles.text(id)`). Heights
643
- * and arrow sizes are mm before an object's `scale`. */
644
- export type TextStyleInfo = {
663
+ /** A document text style (`styles.text(id)` in `draw`,
664
+ * `document.listTextStyles()`). Heights and arrow sizes are mm before an
665
+ * object's `scale`. */
666
+ export type TextStyle = {
645
667
  readonly id: string;
646
668
  readonly name: string;
647
669
  readonly font: string;
@@ -649,11 +671,12 @@ declare module "lineadraw" {
649
671
  readonly bold?: boolean;
650
672
  readonly italic?: boolean;
651
673
  readonly textHeight: number;
652
- readonly arrowType: "filled" | "open" | "tick" | "dot" | "none";
674
+ readonly arrowType: ArrowType;
653
675
  readonly arrowSize: number;
654
676
  };
655
- /** A document dimension style as `draw` reads it (`styles.dim(id)`). */
656
- export type DimStyleInfo = {
677
+ /** A document dimension style (`styles.dim(id)`,
678
+ * `document.listDimStyles()`). */
679
+ export type DimStyle = {
657
680
  readonly id: string;
658
681
  readonly name: string;
659
682
  readonly font: string;
@@ -662,8 +685,9 @@ declare module "lineadraw" {
662
685
  readonly italic?: boolean;
663
686
  readonly textHeight: number;
664
687
  readonly textOffset: number;
665
- readonly arrowType: "filled" | "open" | "tick" | "dot" | "none";
688
+ readonly arrowType: ArrowType;
666
689
  readonly arrowSize: number;
690
+ /** "short" = a 2×overshoot tick across the dimension line. */
667
691
  readonly extensionType: "long" | "short";
668
692
  readonly extensionOffset: number;
669
693
  readonly extensionOvershoot: number;
@@ -673,9 +697,17 @@ declare module "lineadraw" {
673
697
  * (a deleted style, a block from another drawing) gives the document's
674
698
  * first style — the same rule a child's `styleId` follows. */
675
699
  export interface BlockStyles {
676
- text(id?: string): TextStyleInfo;
677
- dim(id?: string): DimStyleInfo;
700
+ text(id?: string): TextStyle;
701
+ dim(id?: string): DimStyle;
678
702
  }
703
+ /** A new text style: a unique name, every other field optional. */
704
+ export type TextStyleInput = {
705
+ name: string;
706
+ } & Partial<Omit<TextStyle, "id">>;
707
+ /** A new dimension style: a unique name, every other field optional. */
708
+ export type DimStyleInput = {
709
+ name: string;
710
+ } & Partial<Omit<DimStyle, "id">>;
679
711
  /** What a `row` may hold: the compact, single-line param kinds. */
680
712
  export type RowItemDef = Extract<ParamDef, {
681
713
  type: "number" | "string" | "boolean" | "enum" | "color" | "textStyle" | "dimStyle" | "font" | "lineType" | "hatchPattern";
@@ -686,18 +718,151 @@ declare module "lineadraw" {
686
718
  items: readonly (infer I)[];
687
719
  } ? I : Q;
688
720
  /**
689
- * The block's parameters table — what the `params` member of a BlockSpec
690
- * declares (or its function form returns).
721
+ * A parameters table — what the `params` member of a block or command spec
722
+ * declares (or a block's function form returns).
723
+ */
724
+ export type ParamDefs = readonly ParamDef[];
725
+ /**
726
+ * One declared input — a row of the `inputs` table a block or command
727
+ * spec declares. Inputs are read by `name` (`inputs.<name>`); `label` is
728
+ * the pick prompt. `types` limits object picks to those object types
729
+ * (empty / absent = any). Optional inputs are skipped with Enter.
730
+ */
731
+ export type InputDef = {
732
+ name: string;
733
+ label?: string;
734
+ description?: string;
735
+ type: "point";
736
+ optional?: boolean;
737
+ } | {
738
+ name: string;
739
+ label?: string;
740
+ description?: string;
741
+ type: "points";
742
+ /** Default 1. */
743
+ min?: number;
744
+ max?: number;
745
+ /** A polygon (closing segment previewed) rather than an open chain. */
746
+ closed?: boolean;
747
+ } | {
748
+ name: string;
749
+ label?: string;
750
+ description?: string;
751
+ type: "object";
752
+ types?: readonly ModelObject["type"][];
753
+ optional?: boolean;
754
+ } | {
755
+ name: string;
756
+ label?: string;
757
+ description?: string;
758
+ type: "objects";
759
+ types?: readonly ModelObject["type"][];
760
+ /** Default 1. */
761
+ min?: number;
762
+ max?: number;
763
+ } | {
764
+ name: string;
765
+ label?: string;
766
+ description?: string;
767
+ /** The block instance this one LIVES ON (a door on a floor plan): it
768
+ * draws in the host's frame and reads the host's `expose` as `host`;
769
+ * the host's `draw` sees it in `hosted`. Picked by clicking the host;
770
+ * `attach` turns the click into params. */
771
+ type: "host";
772
+ /** Accepted host DEFINITION ids (empty = any block). */
773
+ types?: readonly string[];
774
+ };
775
+ /** A custom handle's marker shape (cosmetic: triangle / arrow = "pull this
776
+ * way", diamond = "options here", plus / minus = "add / remove"). */
777
+ export type HandleShape = "square" | "circle" | "diamond" | "triangle" | "arrow" | "double-arrow" | "plus" | "minus";
778
+ /** Icons a button handle may show (lucide glyphs). */
779
+ export type HandleIcon = "plus" | "minus" | "x" | "check" | "flip-horizontal" | "flip-vertical" | "rotate-cw" | "rotate-ccw" | "refresh-cw" | "arrow-left-right" | "arrow-up-down" | "settings-2" | "ellipsis";
780
+ /** An inputs table. */
781
+ export type InputDefs = readonly InputDef[];
782
+ /** A command's inputs table: a `host` is a block-only input. */
783
+ export type CommandInputDefs = readonly Exclude<InputDef, {
784
+ type: "host";
785
+ }>[];
786
+ /** The object type an object input's `types` filter admits. */
787
+ type PickedObject<D> = D extends {
788
+ types: readonly (infer T)[];
789
+ } ? [T] extends [never] ? ModelObject : Extract<ModelObject, {
790
+ type: T;
791
+ }> : ModelObject;
792
+ type DrawInputValue<D> = D extends {
793
+ type: "point";
794
+ } ? D extends {
795
+ optional: true;
796
+ } ? Vec2 | undefined : Vec2 : D extends {
797
+ type: "points";
798
+ } ? readonly Vec2[] : D extends {
799
+ type: "object";
800
+ } ? PickedObject<D> | null : readonly PickedObject<D>[];
801
+ /**
802
+ * What a block's `draw` receives as `inputs` for a table: points
803
+ * pivot-localized, object inputs as the referenced object (pivot-local) or
804
+ * null once deleted, lists as arrays (deleted objects dropped).
691
805
  */
692
- export type BlockParamDefs = readonly ParamDef[];
693
- /** What the script's `draw` export must return. */
694
- export type BlockScriptResult = ObjectInput[];
806
+ export type DrawInputs<I extends InputDefs> = {
807
+ readonly [D in I[number] as D extends {
808
+ type: "host";
809
+ } ? never : D["name"]]: DrawInputValue<D>;
810
+ };
811
+ type StoredInputValue<D> = D extends {
812
+ type: "host";
813
+ } ? string : D extends {
814
+ type: "point";
815
+ } ? Vec2Like : D extends {
816
+ type: "points";
817
+ } ? readonly Vec2Like[] : D extends {
818
+ type: "object";
819
+ } ? string : readonly string[];
820
+ /**
821
+ * Inputs as STORED for a table (what `place` returns and `previewInputs`
822
+ * holds): points in world coords ([x, y] accepted), objects as ids.
823
+ * Optional inputs may be left out.
824
+ */
825
+ export type StoredInputs<I extends InputDefs> = {
826
+ readonly [D in I[number] as D extends {
827
+ optional: true;
828
+ } ? never : D["name"]]: StoredInputValue<D>;
829
+ } & {
830
+ readonly [D in I[number] as D extends {
831
+ optional: true;
832
+ } ? D["name"] : never]?: StoredInputValue<D>;
833
+ };
834
+ type CommandInputValue<D> = D extends {
835
+ type: "point";
836
+ } ? D extends {
837
+ optional: true;
838
+ } ? Vec2 | undefined : Vec2 : D extends {
839
+ type: "points";
840
+ } ? readonly Vec2[] : D extends {
841
+ type: "object";
842
+ } ? D extends {
843
+ optional: true;
844
+ } ? string | undefined : string : readonly string[];
845
+ /**
846
+ * What a command's `ctx.inputs` is: the points in label order for a
847
+ * labels array, a record by name for a table (objects as ids — read them
848
+ * with `document.getObject`).
849
+ */
850
+ export type CommandInputs<I> = I extends readonly string[] ? readonly Vec2[] : I extends CommandInputDefs ? {
851
+ readonly [D in I[number] as D["name"]]: CommandInputValue<D>;
852
+ } : readonly Vec2[];
695
853
  /** The value an enum option denotes (its string, or `value` of the record form). */
696
- type OptionValue<O extends ParameterOption> = O extends string ? O : O extends {
854
+ type OptionValue<O extends ParamOption> = O extends string ? O : O extends {
697
855
  value: infer V extends string;
698
856
  } ? V : never;
857
+ /** Any JSON value — what a `data` param holds. */
858
+ export type JsonValue = string | number | boolean | null | readonly JsonValue[] | {
859
+ readonly [key: string]: JsonValue;
860
+ };
699
861
  /** The runtime value type of one `params` table entry. */
700
862
  type ParamValue<Q extends ParamDef> = Q extends {
863
+ type: "data";
864
+ default: infer D;
865
+ } ? D : Q extends {
701
866
  type: "enum";
702
867
  } ? OptionValue<Q["options"][number]> : Q extends {
703
868
  type: "number";
@@ -755,17 +920,10 @@ declare module "lineadraw" {
755
920
  description?: string;
756
921
  lines: HatchPatternLine[];
757
922
  };
758
- /** An axis-aligned box in world mm. */
759
- export type Box = {
760
- minX: number;
761
- minY: number;
762
- maxX: number;
763
- maxY: number;
764
- };
765
923
  /** Filters for Drawing.query — all present filters AND together. */
766
924
  export type ObjectQuery = {
767
925
  ids?: readonly string[];
768
- type?: ObjectInput["type"];
926
+ type?: ModelObject["type"];
769
927
  /** Layer name or id. */
770
928
  layer?: string;
771
929
  /** #rrggbb override (objects without one inherit from their layer). */
@@ -773,9 +931,9 @@ declare module "lineadraw" {
773
931
  lineType?: string;
774
932
  /** Substring match on text content. */
775
933
  content?: string;
776
- /** Bounds intersect this box. */
934
+ /** Box intersect this box. */
777
935
  bbox?: Box;
778
- /** Bounds entirely inside this box. */
936
+ /** Box entirely inside this box. */
779
937
  inside?: Box;
780
938
  /** Geometry within `tol` mm of `point`. */
781
939
  near?: {
@@ -786,38 +944,87 @@ declare module "lineadraw" {
786
944
  * model space. */
787
945
  layout?: string;
788
946
  };
789
- /** A STORED object as query() returns it (see StoredObject — schema
790
- * output: defaults applied, points always {x, y}, identity present). */
791
- export type ExistingObject = StoredObject;
947
+ /** `Drawing.summary()`: counts by type / layer, extents, names. */
948
+ export type DocumentSummary = {
949
+ name: string;
950
+ objectCount: number;
951
+ byType: Record<string, number>;
952
+ byLayer: Record<string, number>;
953
+ bbox: Box | null;
954
+ layers: string[];
955
+ layouts: {
956
+ name: string;
957
+ objectCount: number;
958
+ }[];
959
+ settings: {
960
+ units: "mm" | "in";
961
+ };
962
+ };
963
+ /** What `renderSvg` draws: model space or one layout. */
964
+ export type RenderSvgOptions = {
965
+ /** Render this paper layout (name or id) instead of model space. */
966
+ layout?: string;
967
+ /** Crop to this box (world mm; sheet mm in a layout). */
968
+ bbox?: Box;
969
+ /** Padding around the content, mm (default 5). */
970
+ padding?: number;
971
+ /** Default: "color" for model space, the layout's own for a layout. */
972
+ palette?: PrintPalette;
973
+ };
974
+ export type RenderPngOptions = RenderSvgOptions & {
975
+ /** Output width in px (height follows). Default 1024. */
976
+ width?: number;
977
+ /** Background fill, e.g. "#ffffff". Default: the dark canvas. */
978
+ background?: string;
979
+ };
980
+ export type RenderPdfOptions = {
981
+ /** Layouts (names or ids) in page order; default: all of them. */
982
+ layouts?: readonly string[];
983
+ /** Override every page's print palette. */
984
+ palette?: PrintPalette;
985
+ };
792
986
  /** Per-object measurements; null where the type has no natural value. */
793
987
  export type Measurement = {
794
988
  bbox: Box | null;
795
989
  length: number | null;
796
990
  area: number | null;
797
991
  };
798
- /** A layer as stored (defaults applied) plus the current-layer flag. */
799
- export type LayerInfo = {
992
+ /** A document layer (defaults applied). */
993
+ export type Layer = {
800
994
  id: string;
801
995
  name: string;
996
+ /** #rrggbb — objects without their own color take it. */
802
997
  color: string;
998
+ /** Default line type of the layer's objects. */
803
999
  lineType: string;
1000
+ /** Default lineweight, mm. */
804
1001
  lineWidth: number;
1002
+ /** Default paint opacity 0..1. */
805
1003
  opacity: number;
806
1004
  visible: boolean;
807
1005
  locked: boolean;
1006
+ /** false = shown on screen but left out of PDF / print output. */
1007
+ print: boolean;
1008
+ };
1009
+ /** A layer as `listLayers()` returns it: plus the current-layer flag. */
1010
+ export type LayerInfo = Layer & {
808
1011
  current: boolean;
809
- [key: string]: unknown;
810
1012
  };
811
- /** A paper layout as stored: sheet metadata + its sheet-space objects. */
812
- export type LayoutInfo = {
1013
+ /** A new layer: a unique name, every other field optional. */
1014
+ export type LayerInput = {
1015
+ name: string;
1016
+ } & Partial<Omit<Layer, "id">>;
1017
+ /** A paper layout: sheet metadata + its sheet-space objects. */
1018
+ export type PaperLayout = {
813
1019
  id: string;
814
1020
  name: string;
1021
+ /** Sheet size, mm. */
815
1022
  sheet: {
816
1023
  width: number;
817
1024
  height: number;
818
1025
  };
819
- printPalette: "color" | "grayscale" | "monochrome";
820
- objects: readonly StoredObject[];
1026
+ printPalette: PrintPalette;
1027
+ objects: readonly ModelObject[];
821
1028
  };
822
1029
  /** A block module's identity/metadata (from its exports). */
823
1030
  export type BlockInfo = {
@@ -828,6 +1035,9 @@ declare module "lineadraw" {
828
1035
  authors?: readonly string[];
829
1036
  tags?: readonly string[];
830
1037
  dependencies?: readonly string[];
1038
+ /** The declared inputs table, when the block has one (instances then
1039
+ * store their inputs by name). */
1040
+ inputs?: InputDefs;
831
1041
  };
832
1042
  /** A command module's identity/metadata (from its exports). */
833
1043
  export type CommandInfo = {
@@ -837,8 +1047,11 @@ declare module "lineadraw" {
837
1047
  version?: string;
838
1048
  authors?: readonly string[];
839
1049
  tags?: readonly string[];
840
- /** Declared point inputs (labels), picked or supplied before `run`. */
841
- inputs?: readonly string[];
1050
+ /** Declared inputs, picked or supplied before `run`: point labels
1051
+ * (positional) or an inputs table (by name). */
1052
+ inputs?: readonly string[] | CommandInputDefs;
1053
+ /** Asks during the run, so headless runners refuse it. */
1054
+ requiresEditor?: boolean;
842
1055
  /** Declared parameters (same table as a block's), prompted or supplied
843
1056
  * before `run`. */
844
1057
  params?: readonly ParamDef[];
@@ -945,18 +1158,29 @@ declare module "lineadraw" {
945
1158
  index?: number;
946
1159
  };
947
1160
  /** The whole document as stored (defaults applied). */
948
- export type StoredDocument = {
1161
+ export type LineaDocument = {
949
1162
  id: string;
1163
+ type: "lineadraw";
950
1164
  version: number;
951
- layers: readonly Omit<LayerInfo, "current">[];
1165
+ settings: {
1166
+ units: "mm" | "in";
1167
+ };
1168
+ layers: readonly Layer[];
952
1169
  currentLayerId: string;
953
- objects: readonly StoredObject[];
954
- layouts: readonly LayoutInfo[];
955
- /** Raw block module sources. */
1170
+ /** Model space. */
1171
+ objects: readonly ModelObject[];
1172
+ layouts: readonly PaperLayout[];
1173
+ textStyles: readonly TextStyle[];
1174
+ dimStyles: readonly DimStyle[];
1175
+ /** The document's own line type / hatch pattern definitions. */
1176
+ lineTypes: readonly LineType[];
1177
+ hatchPatterns: readonly HatchPattern[];
1178
+ /** Embedded files: content hash → data URL. */
1179
+ assets: Readonly<Record<string, string>>;
1180
+ /** Block module sources. */
956
1181
  blockDefinitions: readonly string[];
957
- /** Raw command module sources. */
1182
+ /** Command module sources. */
958
1183
  commands: readonly string[];
959
- [key: string]: unknown;
960
1184
  };
961
1185
  /** Where a draw-order move puts the objects. */
962
1186
  export type ReorderPlacement = "front" | "back" | {
@@ -978,60 +1202,29 @@ declare module "lineadraw" {
978
1202
  /** Monotonic change counter. */
979
1203
  readonly revision: number;
980
1204
  /** The full document — a detached snapshot. */
981
- readonly document: StoredDocument;
1205
+ readonly document: LineaDocument;
982
1206
  /** Counts by type/layer, bbox, layer + layout names. */
983
- summary(): {
984
- name: string;
985
- objectCount: number;
986
- byType: Record<string, number>;
987
- byLayer: Record<string, number>;
988
- bbox: Box | null;
989
- layers: string[];
990
- layouts: {
991
- name: string;
992
- objectCount: number;
993
- }[];
994
- settings: {
995
- units: "mm" | "in";
996
- };
997
- };
1207
+ summary(): DocumentSummary;
998
1208
  /** Filtered objects — model space, or one layout via `filter.layout`. */
999
- listObjects(filter?: ObjectQuery): ExistingObject[];
1209
+ listObjects(filter?: ObjectQuery): ModelObject[];
1000
1210
  /** One object from ANY space, or undefined. */
1001
- getObject(id: string): ExistingObject | undefined;
1211
+ getObject(id: string): ModelObject | undefined;
1002
1212
  /** bbox / curve length / enclosed area of one object. */
1003
1213
  measure(id: string): Measurement;
1004
1214
  listLayers(): LayerInfo[];
1005
- listLayouts(): LayoutInfo[];
1215
+ listLayouts(): PaperLayout[];
1006
1216
  /** Compilable block definitions in this document. */
1007
1217
  listBlockDefinitions(): BlockInfo[];
1008
1218
  /** Compilable command modules travelling with this document. */
1009
1219
  listUserCommands(): CommandInfo[];
1010
1220
  /** Model space (or a layout via `layout`) as an SVG string. */
1011
- renderSvg(opts?: {
1012
- layout?: string;
1013
- bbox?: Box;
1014
- padding?: number;
1015
- palette?: "color" | "grayscale" | "monochrome";
1016
- }): string;
1221
+ renderSvg(opts?: RenderSvgOptions): string;
1017
1222
  /** Model space (or a layout) as PNG bytes — absent on hosts that can't
1018
1223
  * rasterize, so check before calling. */
1019
- renderPng?(opts?: {
1020
- layout?: string;
1021
- bbox?: Box;
1022
- padding?: number;
1023
- palette?: "color" | "grayscale" | "monochrome";
1024
- /** Output width in px (height follows). Default 1024. */
1025
- width?: number;
1026
- /** Background fill, e.g. "#ffffff". Default: the dark canvas. */
1027
- background?: string;
1028
- }): Promise<Uint8Array>;
1224
+ renderPng?(opts?: RenderPngOptions): Promise<Uint8Array>;
1029
1225
  /** Multi-page PDF of the layouts (default: all) — absent on hosts
1030
1226
  * without fonts, so check before calling. */
1031
- renderPdf?(opts?: {
1032
- layouts?: readonly string[];
1033
- palette?: "color" | "grayscale" | "monochrome";
1034
- }): Promise<Uint8Array>;
1227
+ renderPdf?(opts?: RenderPdfOptions): Promise<Uint8Array>;
1035
1228
  /** The whole document as DXF text. */
1036
1229
  toDxf(): Promise<string>;
1037
1230
  /** DWG bytes (default AC1027 — AutoCAD 2013). */
@@ -1040,10 +1233,9 @@ declare module "lineadraw" {
1040
1233
  }): Promise<Uint8Array>;
1041
1234
  /** The `.linea` file text. */
1042
1235
  toLinea(): string;
1043
- /** Add objects (each may carry `layer` — a name — instead of an id);
1044
- * returns the created ids. */
1045
- add(objects: readonly (ObjectInput & {
1046
- layer?: string;
1236
+ /** Add objects (each may carry its own `id`); returns the created ids. */
1237
+ add(objects: readonly (ModelObjectInput & {
1238
+ id?: string;
1047
1239
  })[], opts?: {
1048
1240
  layout?: string;
1049
1241
  }): string[];
@@ -1070,17 +1262,14 @@ declare module "lineadraw" {
1070
1262
  updateLayout(nameOrId: string, patch: {
1071
1263
  name?: string;
1072
1264
  sheet?: SheetSpec;
1073
- printPalette?: "color" | "grayscale" | "monochrome";
1265
+ printPalette?: PrintPalette;
1074
1266
  }): void;
1075
1267
  removeLayout(nameOrId: string): void;
1076
1268
  /** Explicit total order (names or ids) — the PDF page order. */
1077
1269
  reorderLayouts(order: readonly string[]): void;
1078
1270
  /** Create a layer (unique name); returns its id. */
1079
- addLayer(props: {
1080
- name: string;
1081
- color?: string;
1082
- } & Record<string, unknown>): string;
1083
- updateLayer(nameOrId: string, patch: Record<string, unknown>): void;
1271
+ addLayer(props: LayerInput): string;
1272
+ updateLayer(nameOrId: string, patch: Partial<LayerInput>): void;
1084
1273
  /** Remove an EMPTY, non-current layer. */
1085
1274
  removeLayer(nameOrId: string): void;
1086
1275
  /** Explicit total order (names or ids, every layer exactly once). */
@@ -1106,31 +1295,17 @@ declare module "lineadraw" {
1106
1295
  }): Promise<MarketplaceHit[]>;
1107
1296
  /** Install (or update) entries by id, dependencies first — one undo step. */
1108
1297
  installMarketplaceEntries(ids: readonly string[], marketplace?: string): Promise<MergeReport>;
1109
- listTextStyles(): ({
1110
- id: string;
1111
- name: string;
1112
- } & Record<string, unknown>)[];
1113
- listDimStyles(): ({
1114
- id: string;
1115
- name: string;
1116
- } & Record<string, unknown>)[];
1298
+ listTextStyles(): TextStyle[];
1299
+ listDimStyles(): DimStyle[];
1117
1300
  /** Create a style (unique name; unset fields take the defaults); returns
1118
1301
  * its id. Styles are addressed by name or id. */
1119
- addTextStyle(props: {
1120
- name: string;
1121
- } & Record<string, unknown>): string;
1122
- updateTextStyle(nameOrId: string, patch: Record<string, unknown>): void;
1302
+ addTextStyle(props: TextStyleInput): string;
1303
+ updateTextStyle(nameOrId: string, patch: Partial<TextStyleInput>): void;
1123
1304
  /** Remove a style no object uses (refused otherwise). */
1124
1305
  removeTextStyle(nameOrId: string): void;
1125
- addDimStyle(props: {
1126
- name: string;
1127
- } & Record<string, unknown>): string;
1128
- updateDimStyle(nameOrId: string, patch: Record<string, unknown>): void;
1306
+ addDimStyle(props: DimStyleInput): string;
1307
+ updateDimStyle(nameOrId: string, patch: Partial<DimStyleInput>): void;
1129
1308
  removeDimStyle(nameOrId: string): void;
1130
- /** @deprecated Use updateDimStyle (default here: the first style). */
1131
- setDimStyle(patch: Record<string, unknown>, styleId?: string): void;
1132
- /** @deprecated Use updateTextStyle (default here: the first style). */
1133
- setTextStyle(patch: Record<string, unknown>, styleId?: string): void;
1134
1309
  /** The document's own line type definitions (objects and layers name
1135
1310
  * them, ahead of the built-in catalogue). */
1136
1311
  listLineTypes(): LineType[];
@@ -1146,12 +1321,13 @@ declare module "lineadraw" {
1146
1321
  addHatchPatterns(patterns: readonly HatchPattern[]): void;
1147
1322
  updateHatchPattern(name: string, patch: Partial<HatchPattern>): void;
1148
1323
  removeHatchPattern(name: string): void;
1149
- /** Embed image pixels (a data URL); returns the content-keyed assetId
1150
- * that `image` objects reference. */
1324
+ /** Embed a file (a data URL — PNG, JPEG, PDF…); returns the content-keyed
1325
+ * assetId an embedded reference's `source: { kind: "asset", assetId }`
1326
+ * names. */
1151
1327
  addAsset(dataUrl: string): string;
1152
- /** Remove an asset (refused while an image references it). */
1328
+ /** Remove an asset (refused while a reference embeds it). */
1153
1329
  removeAsset(id: string): void;
1154
- /** Embedded image assets and how many images use each. */
1330
+ /** Embedded files and how many references use each. */
1155
1331
  listAssets(): {
1156
1332
  id: string;
1157
1333
  mimeType: string;
@@ -1176,7 +1352,8 @@ declare module "lineadraw" {
1176
1352
  layoutIds: string[];
1177
1353
  }>;
1178
1354
  /** Merge a PDF: vectors/text onto the current layer, or (`as: "image"`,
1179
- * not available on every host) each page as an image at true scale. */
1355
+ * not available on every host) embedded, each page a raster reference
1356
+ * at true scale. */
1180
1357
  importPdfData(data: ArrayBuffer | Uint8Array, opts?: {
1181
1358
  as?: "vectors" | "image";
1182
1359
  origin?: Vec2Like;
@@ -1246,10 +1423,43 @@ declare module "lineadraw" {
1246
1423
  label?: string;
1247
1424
  referencePoint?: Vec2Like;
1248
1425
  }): Promise<Vec2>;
1249
- /** Await one object click; resolves the object's id. */
1426
+ /** Await one object click; resolves the object's id. `types` limits
1427
+ * what can be picked (empty / absent = any). */
1250
1428
  pickObject(opts?: {
1251
1429
  label?: string;
1430
+ types?: readonly ModelObject["type"][];
1252
1431
  }): Promise<string>;
1432
+ /** Await a chain of snapped points (rubber band from the previous);
1433
+ * Enter / Esc finishes once `min` (default 1) is met, `max` ends it,
1434
+ * `closed` previews the closing segment. Rejects on cancel below `min`. */
1435
+ pickPoints(opts?: {
1436
+ label?: string;
1437
+ min?: number;
1438
+ max?: number;
1439
+ closed?: boolean;
1440
+ referencePoint?: Vec2Like;
1441
+ }): Promise<Vec2[]>;
1442
+ /** Await several object picks (each once); Enter / Esc finishes once
1443
+ * `min` (default 1) is met. Rejects on cancel below `min`. */
1444
+ pickObjects(opts?: {
1445
+ label?: string;
1446
+ types?: readonly ModelObject["type"][];
1447
+ min?: number;
1448
+ max?: number;
1449
+ }): Promise<string[]>;
1450
+ /**
1451
+ * Ask several values in ONE dialog — the same form a command's `params`
1452
+ * table shows, from a params table (number / string / boolean / enum …):
1453
+ * const { count, label } = await editor.ask(
1454
+ * [{ name: "count", type: "number", default: 3 },
1455
+ * { name: "label", type: "string", default: "A" }],
1456
+ * { title: "Array" });
1457
+ * Resolves the values typed by the table; rejects on cancel.
1458
+ */
1459
+ ask<const P extends ParamDefs>(params: P, opts?: {
1460
+ title?: string;
1461
+ description?: string;
1462
+ }): Promise<ParamValues<P>>;
1253
1463
  /** Await a typed value from a small input dialog. */
1254
1464
  prompt(message: string, opts?: {
1255
1465
  initial?: string;
@@ -1261,40 +1471,33 @@ declare module "lineadraw" {
1261
1471
  /** Trigger a command by id — like the user pressing its hotkey. A macro
1262
1472
  * takes its declared `inputs` / `params` up front (params passed skip its
1263
1473
  * params dialog). */
1264
- runCommand(id: string, inputs?: readonly Vec2Like[], params?: Readonly<Record<string, unknown>>): Promise<void>;
1474
+ runCommand(id: string, inputs?: readonly Vec2Like[] | Readonly<Record<string, Vec2Like | readonly Vec2Like[] | string | readonly string[]>>, params?: Readonly<Record<string, unknown>>): Promise<void>;
1265
1475
  }
1266
1476
  /**
1267
1477
  * What `run` receives. `document` is the Drawing; `editor` the interactive
1268
- * surface when there is one; `inputs` the points the command's declared
1269
- * `inputs` labels produced (picked in the editor, or supplied by the
1270
- * caller), in label order; `params` the values of the declared `params`
1271
- * table (asked for in a dialog in the editor, or passed by the caller;
1272
- * omitted ones take their defaults).
1478
+ * surface when there is one; `inputs` what the command's declared `inputs`
1479
+ * produced (picked in the editor — object inputs take the selection first
1480
+ * — or supplied by the caller): the points in label order for labels, a
1481
+ * record by name for a table (see CommandInputs); `params` the values of
1482
+ * the declared `params` table (asked for in a dialog in the editor, or
1483
+ * passed by the caller; omitted ones take their defaults).
1273
1484
  */
1274
- export interface CommandContext<P = Readonly<Record<string, unknown>>> {
1485
+ export interface CommandContext<P = Readonly<Record<string, unknown>>, I = readonly Vec2[]> {
1275
1486
  document: Drawing;
1276
1487
  editor?: EditorSurface;
1277
- inputs: readonly Vec2[];
1488
+ inputs: I;
1278
1489
  params: P;
1279
- /** @deprecated Use `editor.pickPoint({ label })` (throws without an editor). */
1280
- pickPoint(label?: string): Promise<Vec2>;
1281
- /** @deprecated Use `editor.pickObject({ label })`. */
1282
- pickObject(label?: string): Promise<string>;
1283
- /** @deprecated Use `editor.state().selectedIds`. */
1284
- selection(): string[];
1285
- /** @deprecated Use `editor.setSelection(ids)`. */
1286
- setSelection(ids: readonly string[]): void;
1287
- /** @deprecated Use `editor.prompt(message, options)`. */
1288
- prompt(message: string, options?: {
1289
- initial?: string;
1290
- placeholder?: string;
1291
- }): Promise<string>;
1292
- /** @deprecated Use `editor.toast(message, kind)`. */
1293
- showToast(message: string, kind?: "info" | "success" | "error"): void;
1294
1490
  }
1295
1491
 
1296
1492
  // ——— Script contract ———
1297
1493
 
1494
+ /**
1495
+ * @deprecated All "lineadraw/helpers" functions as one object — what
1496
+ * migration-wrapped legacy scripts import. Import the named functions from
1497
+ * "lineadraw/helpers" instead.
1498
+ */
1499
+ export const helpers: Readonly<typeof import("lineadraw/helpers")>;
1500
+
1298
1501
  // #region BlockParams
1299
1502
  /**
1300
1503
  * The open fallback for a block's parameter values, by name. Inside
@@ -1317,12 +1520,12 @@ declare module "lineadraw" {
1317
1520
  /**
1318
1521
  * A referenced document object as `draw` receives it: the STORED record
1319
1522
  * (schema output — defaults applied, points always {x, y}, id/layerId
1320
- * present; see StoredObject), localized against the instance pivot like
1523
+ * present; see ModelObject), localized against the instance pivot like
1321
1524
  * every point input. Null when the reference no longer resolves (the
1322
1525
  * object was deleted) — handle it or throw (a throw shows as the
1323
1526
  * instance's evaluation error).
1324
1527
  */
1325
- export type ResolvedObject = StoredObject | null;
1528
+ export type ResolvedObject = ModelObject | null;
1326
1529
 
1327
1530
  /**
1328
1531
  * How one stored input arrives at `draw`: points pass through
@@ -1354,9 +1557,164 @@ declare module "lineadraw" {
1354
1557
  export interface PlaceProps<P = BlockParams> {
1355
1558
  params: ParamValues<P>;
1356
1559
  pickPoint: (label?: string) => Promise<Vec2>;
1357
- pickObject: (label?: string) => Promise<string>;
1560
+ pickObject: (
1561
+ label?: string,
1562
+ opts?: { types?: readonly ModelObject["type"][] },
1563
+ ) => Promise<string>;
1564
+ /** A chain of points; Enter / Esc finishes once `min` (default 1) is met. */
1565
+ pickPoints: (
1566
+ label?: string,
1567
+ opts?: { min?: number; max?: number; closed?: boolean },
1568
+ ) => Promise<Vec2[]>;
1569
+ /** Several objects; Enter / Esc finishes once `min` (default 1) is met. */
1570
+ pickObjects: (
1571
+ label?: string,
1572
+ opts?: {
1573
+ types?: readonly ModelObject["type"][];
1574
+ min?: number;
1575
+ max?: number;
1576
+ },
1577
+ ) => Promise<string[]>;
1578
+ }
1579
+
1580
+ // ——— Custom handles ———
1581
+
1582
+ /** The names of a params table's NUMBER parameters. */
1583
+ export type NumberParamName<P> = {
1584
+ [K in keyof ParamValues<P>]: ParamValues<P>[K] extends number ? K : never;
1585
+ }[keyof ParamValues<P>] &
1586
+ string;
1587
+
1588
+ /**
1589
+ * What a handle's drag / click / action changes: params by name (numbers
1590
+ * are clamped to the param's min / max), and — for a block with an
1591
+ * `inputs` table — inputs by name in block-LOCAL coordinates.
1592
+ */
1593
+ export interface HandlePatch<P = BlockParams, S = never> {
1594
+ params?: Partial<ParamValues<P>>;
1595
+ inputs?: S;
1596
+ }
1597
+
1598
+ /** What a `drag` function receives — the values at drag START (not
1599
+ * compounding) plus where the cursor is, already constrained. */
1600
+ export interface HandleDragEvent<P = BlockParams, D = unknown> {
1601
+ params: ParamValues<P>;
1602
+ inputs: D;
1603
+ /** The cursor, block-local, after the handle's constraint. */
1604
+ point: Vec2;
1605
+ /** The handle's position when the drag started. */
1606
+ start: Vec2;
1607
+ /** `along`: signed distance from its origin; `around`: the angle
1608
+ * (radians); free: undefined. */
1609
+ value: number | undefined;
1610
+ }
1611
+
1612
+ /**
1613
+ * One custom handle on a selected instance, in block-LOCAL coordinates
1614
+ * (pivot at the origin, before the instance's rotation / scale). Give it
1615
+ * ONE drag behaviour — `param` (the constrained value → a number param),
1616
+ * `input` (moves a point input), or `drag` (anything else) — or mark it
1617
+ * `fixed`; `click` makes it a button (a press without a move).
1618
+ */
1619
+ /**
1620
+ * A button in a handle's hover menu, or in the instance's context menu
1621
+ * (the block's top-level `actions`). One undo step.
1622
+ */
1623
+ export interface BlockAction<P = BlockParams, D = unknown, S = never> {
1624
+ label: string;
1625
+ icon?: HandleIcon;
1626
+ /** Pick a point first (snapping as usual); `run` receives it,
1627
+ * block-local, as `point`. Esc cancels. */
1628
+ pick?: "point";
1629
+ run: (s: {
1630
+ params: ParamValues<P>;
1631
+ inputs: D;
1632
+ point?: Vec2;
1633
+ }) => HandlePatch<P, S> | undefined;
1358
1634
  }
1359
1635
 
1636
+ /** A field in a handle's hover menu: a parameter by name, or a field
1637
+ * bound to any value (one wall's thickness inside a `data` param), with
1638
+ * `set` returning what an edit changes. Each edit is one undo step. */
1639
+ export type MenuField<P = BlockParams, S = never> =
1640
+ | (keyof ParamValues<P> & string)
1641
+ | {
1642
+ /** The field: any value parameter row without name / default
1643
+ * (`{ type: "number", label: "Thickness", min: 50 }`). */
1644
+ field: Record<string, unknown> & { type: string; label?: string };
1645
+ value: unknown;
1646
+ set: (value: never) => HandlePatch<P, S> | undefined;
1647
+ };
1648
+
1649
+ interface HandleBase<P, D, S> {
1650
+ /** Stable within the instance (hover / drag continuity, tests). */
1651
+ id: string;
1652
+ /** Tooltip, and the hover menu's title. */
1653
+ label?: string;
1654
+ /** Not draggable (a button, or menu-only). */
1655
+ fixed?: boolean;
1656
+ /** The constrained value → this NUMBER param. */
1657
+ param?: NumberParamName<P>;
1658
+ drag?: (e: HandleDragEvent<P, D>) => HandlePatch<P, S> | undefined;
1659
+ /** Button behaviour: one undo step; the selection doesn't change. */
1660
+ click?: (s: {
1661
+ params: ParamValues<P>;
1662
+ inputs: D;
1663
+ }) => HandlePatch<P, S> | undefined;
1664
+ /** Fields shown in the hover menu (see MenuField). */
1665
+ menu?: readonly MenuField<P, S>[];
1666
+ /** Buttons in the hover menu. */
1667
+ actions?: readonly BlockAction<P, D, S>[];
1668
+ }
1669
+
1670
+ /**
1671
+ * One custom point handle on a selected instance, in block-LOCAL
1672
+ * coordinates (pivot at the origin, before the instance's rotation /
1673
+ * scale). Give it ONE drag behaviour — `param` (the constrained value →
1674
+ * a number param), `input` (moves a point input), or `drag` (anything
1675
+ * else) — or mark it `fixed`; `click` makes it a button.
1676
+ */
1677
+ export interface PointHandleDef<P = BlockParams, D = unknown, S = never>
1678
+ extends HandleBase<P, D, S> {
1679
+ kind?: "point";
1680
+ at: Vec2Like;
1681
+ shape?: HandleShape;
1682
+ /** Radians — points a triangle / arrow (default: the constraint axis). */
1683
+ direction?: number;
1684
+ /** Constrain to a line through `origin`; value = signed distance. */
1685
+ along?: {
1686
+ origin: Vec2Like;
1687
+ direction: Vec2Like;
1688
+ min?: number;
1689
+ max?: number;
1690
+ };
1691
+ /** Constrain to the circle through `at` around `center`; value =
1692
+ * the angle (radians). */
1693
+ around?: { center: Vec2Like };
1694
+ /** Move a point input: `"hinge"`, or one point of a list
1695
+ * (`{ name: "path", index: 2 }`). Replaces that point's default handle. */
1696
+ input?: string | { name: string; index: number };
1697
+ /** A lucide glyph drawn in the handle — the button look. */
1698
+ icon?: HandleIcon;
1699
+ }
1700
+
1701
+ /**
1702
+ * A line handle (a wall face, an offset): drawn while hovered, dragged
1703
+ * along its NORMAL by default (value = the signed offset, left of
1704
+ * from → to positive); `along` gives another direction.
1705
+ */
1706
+ export interface LineHandleDef<P = BlockParams, D = unknown, S = never>
1707
+ extends HandleBase<P, D, S> {
1708
+ kind: "line";
1709
+ from: Vec2Like;
1710
+ to: Vec2Like;
1711
+ along?: { direction: Vec2Like; min?: number; max?: number };
1712
+ }
1713
+
1714
+ export type HandleDef<P = BlockParams, D = unknown, S = never> =
1715
+ | PointHandleDef<P, D, S>
1716
+ | LineHandleDef<P, D, S>;
1717
+
1360
1718
  // ——— defineBlock ———
1361
1719
 
1362
1720
  /**
@@ -1404,8 +1762,9 @@ declare module "lineadraw" {
1404
1762
  * typeof / satisfies / as-const annotations. See defineBlock.
1405
1763
  */
1406
1764
  export interface BlockSpec<
1407
- P extends BlockParamDefs = readonly [],
1765
+ P extends ParamDefs = readonly [],
1408
1766
  Pl extends PlaceSpec<P> | undefined = undefined,
1767
+ I extends InputDefs | undefined = undefined,
1409
1768
  > {
1410
1769
  id: string;
1411
1770
  name: string;
@@ -1430,16 +1789,58 @@ declare module "lineadraw" {
1430
1789
  paramVisibility?: (props: {
1431
1790
  params: ParamValues<P>;
1432
1791
  }) => Partial<Record<keyof ParamValues<P> & string, boolean>>;
1433
- /** Point labels (fixed picks) or an interactive function (see PlaceSpec). */
1434
- place?: Pl;
1792
+ /**
1793
+ * The block's declared inputs, by name — picked in table order at
1794
+ * insertion (`points` until Enter, `objects` from the selection when
1795
+ * it fits), and read in `draw` as `inputs.<name>`. Instances store
1796
+ * them by name, so reordering or adding inputs never breaks existing
1797
+ * instances. Replaces `place` labels.
1798
+ */
1799
+ inputs?: I;
1800
+ /**
1801
+ * Point labels (fixed picks) or an interactive function (see
1802
+ * PlaceSpec). With an `inputs` table, only the function form: it
1803
+ * returns the inputs by name (for conditional or chained picks).
1804
+ */
1805
+ place?: [I] extends [InputDefs]
1806
+ ? (props: PlaceProps<P>) => StoredInputs<I> | Promise<StoredInputs<I>>
1807
+ : Pl;
1435
1808
  /**
1436
1809
  * Optional inputs used for the block's PREVIEW (panel/Library
1437
1810
  * thumbnails, marketplace cards, save-time dry run) instead of the
1438
1811
  * generic stand-in picks — curate them so the preview shows the block
1439
- * at its best. Same shape `place` produces; points accept [x, y];
1440
- * object-id strings resolve to a stand-in line in previews.
1812
+ * at its best. Same shape `place` produces (by name with an
1813
+ * `inputs` table); points accept [x, y]; object-id strings resolve to
1814
+ * a stand-in line in previews.
1441
1815
  */
1442
- previewInputs?: PreviewInputs<Pl>;
1816
+ previewInputs?: [I] extends [InputDefs] ? StoredInputs<I> : PreviewInputs<Pl>;
1817
+ /**
1818
+ * Custom handles on a selected instance — pure, block-local, re-run
1819
+ * whenever params / inputs change, so positions follow the values (a
1820
+ * width handle sits at the width). See HandleDef.
1821
+ */
1822
+ handles?: (props: {
1823
+ params: ParamValues<P>;
1824
+ inputs: [I] extends [InputDefs] ? DrawInputs<I> : PlaceInputs<Pl>;
1825
+ /** Hosted blocks: the host's `expose` result (null when this block
1826
+ * has no host). Shape it as the host documents it. */
1827
+ host: any;
1828
+ /** Hosting: what lives on this instance — each one's `expose`. */
1829
+ hosted: readonly HostedBlock[];
1830
+ }) => readonly HandleDef<
1831
+ P,
1832
+ [I] extends [InputDefs] ? DrawInputs<I> : PlaceInputs<Pl>,
1833
+ [I] extends [InputDefs] ? Partial<StoredInputs<I>> : never
1834
+ >[];
1835
+ /**
1836
+ * Actions in the instance's context menu (right-click) — e.g. "Add
1837
+ * window" with `pick: "point"`. Static records; one undo step each.
1838
+ */
1839
+ actions?: readonly BlockAction<
1840
+ P,
1841
+ [I] extends [InputDefs] ? DrawInputs<I> : PlaceInputs<Pl>,
1842
+ [I] extends [InputDefs] ? Partial<StoredInputs<I>> : never
1843
+ >[];
1443
1844
  /**
1444
1845
  * Children in block-LOCAL coordinates (pure, runs per evaluation).
1445
1846
  * The first point input is the pivot; `inputs` arrive localized
@@ -1449,12 +1850,51 @@ declare module "lineadraw" {
1449
1850
  */
1450
1851
  draw: (props: {
1451
1852
  params: ParamValues<P>;
1452
- inputs: PlaceInputs<Pl>;
1853
+ inputs: [I] extends [InputDefs] ? DrawInputs<I> : PlaceInputs<Pl>;
1453
1854
  /** The document's text / dimension styles by id — for blocks that
1454
1855
  * lay out with real text sizes. Pass a picked id on to children as
1455
1856
  * `styleId` to let them follow the style. */
1456
1857
  styles: BlockStyles;
1457
- }) => BlockScriptResult;
1858
+ /** Hosted blocks: the host's `expose` result (null when this block
1859
+ * has no host). Shape it as the host documents it. */
1860
+ host: any;
1861
+ /** Hosting: what lives on this instance — each one's `expose`. */
1862
+ hosted: readonly HostedBlock[];
1863
+ }) => BlockChildInput[];
1864
+ /**
1865
+ * Hosting (blocks living on blocks — a door on a floor plan): JSON
1866
+ * this block PUBLISHES for others to read — a host its `walls`, a
1867
+ * door its `cut`. It sees only its own params, which is what keeps
1868
+ * a host and what lives on it from looping.
1869
+ */
1870
+ expose?: (props: { params: ParamValues<P> }) => JsonValue;
1871
+ /**
1872
+ * A hosted block (one with a `host` input): turns the click on the
1873
+ * host — host-local, with the host's exposed data — into this
1874
+ * instance's params (`{ wall: "B/1-2", at: 1200 }`).
1875
+ */
1876
+ attach?: (props: {
1877
+ host: any;
1878
+ point: Vec2;
1879
+ params: ParamValues<P>;
1880
+ }) => Partial<ParamValues<P>>;
1881
+ /**
1882
+ * A hosted block's stand-in host for previews, Library / marketplace
1883
+ * thumbnails and the save-time dry run: the JSON a real host's
1884
+ * `expose` would return. The preview places the block as if its host
1885
+ * were clicked at the origin (`attach`), and `draw` gets this as
1886
+ * `host`. Add a flag (`preview: true`) to draw extra context there,
1887
+ * e.g. a stretch of wall around a door.
1888
+ */
1889
+ previewHost?: JsonValue;
1890
+ }
1891
+
1892
+ /** One block living on a host, as the host's `draw` sees it. */
1893
+ export interface HostedBlock {
1894
+ id: string;
1895
+ definitionId: string;
1896
+ /** Its `expose` result (null without one). */
1897
+ exposed: any;
1458
1898
  }
1459
1899
 
1460
1900
  /**
@@ -1481,25 +1921,33 @@ declare module "lineadraw" {
1481
1921
  * plain named exports describe the same block.
1482
1922
  */
1483
1923
  export function defineBlock<
1484
- const P extends BlockParamDefs = readonly [],
1924
+ const P extends ParamDefs = readonly [],
1485
1925
  const L extends readonly string[] | undefined = undefined,
1486
1926
  >(spec: BlockSpec<P, L>): BlockSpec<P, L>;
1487
1927
  // Function-form place: the props type is concrete (from P) and only the
1488
1928
  // RETURN is inferred — inferring a whole context-sensitive function into
1489
1929
  // a type parameter would fall back to its default.
1490
1930
  export function defineBlock<
1491
- const P extends BlockParamDefs = readonly [],
1931
+ const P extends ParamDefs = readonly [],
1492
1932
  const R extends BlockInputs | Promise<BlockInputs> = BlockInputs,
1493
1933
  >(
1494
1934
  spec: BlockSpec<P, (props: PlaceProps<P>) => R>,
1495
1935
  ): BlockSpec<P, (props: PlaceProps<P>) => R>;
1936
+ // An `inputs` table: `draw`'s inputs are typed by name from it.
1937
+ export function defineBlock<
1938
+ const P extends ParamDefs = readonly [],
1939
+ const I extends InputDefs = readonly [],
1940
+ >(spec: BlockSpec<P, undefined, I>): BlockSpec<P, undefined, I>;
1496
1941
 
1497
1942
  // ——— Commands (macro scripts) ———
1498
1943
  // Drawing / EditorSurface / CommandContext are emitted from scriptTypes.ts
1499
1944
  // above (the script-facing mirror of core's real interfaces).
1500
1945
 
1501
1946
  /** One user command (macro): identity, metadata, and the `run` body. */
1502
- export interface CommandSpec<P extends BlockParamDefs = readonly []> {
1947
+ export interface CommandSpec<
1948
+ P extends ParamDefs = readonly [],
1949
+ I extends readonly string[] | CommandInputDefs = readonly [],
1950
+ > {
1503
1951
  id: string;
1504
1952
  name: string;
1505
1953
  description?: string;
@@ -1507,13 +1955,24 @@ declare module "lineadraw" {
1507
1955
  authors?: readonly string[];
1508
1956
  tags?: readonly string[];
1509
1957
  /**
1510
- * Point inputs the command needs, as labels (`["Start", "End"]`). In
1511
- * the editor each is picked in turn before `run` (rubber-band from the
1512
- * previous pick); a headless or remote caller supplies them up front.
1513
- * They arrive as `ctx.inputs`, in this order. This is what lets one
1514
- * script run in the editor, from a shell, and from an agent alike.
1958
+ * The inputs the command needs: an inputs TABLE
1959
+ * (`[{ name: "doors", type: "objects", types: ["block"] }]`, arriving
1960
+ * as `ctx.inputs.doors`), or point labels (`["Start", "End"]`,
1961
+ * arriving as `ctx.inputs` in order). In the editor they are acquired
1962
+ * before `run` — object inputs take the current selection when it
1963
+ * fits, the rest are picked; a headless or remote caller supplies them
1964
+ * up front (by name for a table). This is what lets one script run in
1965
+ * the editor, from a shell, and from an agent alike.
1515
1966
  */
1516
- inputs?: readonly string[];
1967
+ inputs?: I;
1968
+ /**
1969
+ * The command ASKS during the run (`editor.pickPoint`, `prompt`,
1970
+ * `ask` — the next question depends on the last answer), so it can't
1971
+ * run headless: CLI / agent / SDK runners refuse it up front instead of
1972
+ * failing halfway. Leave it off for commands whose `inputs` /
1973
+ * `params` cover everything.
1974
+ */
1975
+ requiresEditor?: boolean;
1517
1976
  /**
1518
1977
  * Parameters the command needs — the same table a block's `params`
1519
1978
  * declares (number / string / boolean / enum / label rows), or a
@@ -1529,7 +1988,7 @@ declare module "lineadraw" {
1529
1988
  * uncaught error rolls everything back. A return value is handed to
1530
1989
  * the caller (the agent tool / CLI) — the editor ignores it.
1531
1990
  */
1532
- run(ctx: CommandContext<ParamValues<P>>): unknown;
1991
+ run(ctx: CommandContext<ParamValues<P>, CommandInputs<I>>): unknown;
1533
1992
  }
1534
1993
 
1535
1994
  /**
@@ -1555,9 +2014,10 @@ declare module "lineadraw" {
1555
2014
  * },
1556
2015
  * });
1557
2016
  */
1558
- export function defineCommand<const P extends BlockParamDefs = readonly []>(
1559
- spec: CommandSpec<P>,
1560
- ): CommandSpec<P>;
2017
+ export function defineCommand<
2018
+ const P extends ParamDefs = readonly [],
2019
+ const I extends readonly string[] | CommandInputDefs = readonly [],
2020
+ >(spec: CommandSpec<P, I>): CommandSpec<P, I>;
1561
2021
  }
1562
2022
 
1563
2023
  declare module "lineadraw/helpers" {
@@ -1590,1334 +2050,29 @@ declare module "lineadraw/helpers" {
1590
2050
  export const dot: (a: Vec2, b: Vec2) => number;
1591
2051
  /** Rotate vector by `angle` (radians, CCW). */
1592
2052
  export const rotate: (p: Vec2, angle: number) => Vec2;
2053
+ /** A point as scripts write it: [x, y] or { x, y }. */
2054
+ export type PointLike = readonly [number, number] | {
2055
+ readonly x: number;
2056
+ readonly y: number;
2057
+ };
2058
+ /** A polygon: one ring of points (implicitly closed), or several rings —
2059
+ * the first the outer boundary, the rest holes. */
2060
+ export type PolygonLike = readonly PointLike[] | readonly (readonly PointLike[])[];
2061
+ /** A result ring: closed implicitly (the first point is not repeated). */
2062
+ export type Ring = {
2063
+ x: number;
2064
+ y: number;
2065
+ }[];
1593
2066
  /**
1594
- * All helpers as one object — what migration-wrapped legacy scripts receive
1595
- * via `import { helpers } from "lineadraw"`. New scripts import the named
1596
- * functions from "lineadraw/helpers" instead.
2067
+ * The union of polygons: overlapping walls become one outline. Returns
2068
+ * every ring of the result — outer boundaries and holes alike. Draw them as
2069
+ * closed polylines, or hand them all to ONE hatch (`loops: rings.map((r) =>
2070
+ * ({ points: r }))`): hatches fill even-odd, so holes stay holes.
1597
2071
  */
1598
- export const helpers: Readonly<{
1599
- range: (n: number) => number[];
1600
- polar: (angle: number, distance: number, p?: Vec2) => Vec2;
1601
- toDeg: (r: number) => number;
1602
- toRad: (d: number) => number;
1603
- len: (p: Vec2) => number;
1604
- dist: (a: Vec2, b: Vec2) => number;
1605
- add: (a: Vec2, b: Vec2) => Vec2;
1606
- sub: (a: Vec2, b: Vec2) => Vec2;
1607
- scale: (p: Vec2, s: number) => Vec2;
1608
- norm: (p: Vec2) => Vec2;
1609
- dot: (a: Vec2, b: Vec2) => number;
1610
- rotate: (p: Vec2, angle: number) => Vec2;
1611
- }>;
1612
- }
1613
-
1614
- // The same declarations again at GLOBAL scope, so scripts can annotate
1615
- // without importing. Structurally identical to the "lineadraw" exports, so the
1616
- // two mix freely. Requires a DOM-less lib (blocks/tsconfig and the in-app
1617
- // editor both use lib es2022) — with lib.dom, `Text` would collide.
1618
- /** A 2D point (mm, y-up). Point-valued fields also accept [x, y]. */
1619
- type Vec2 = {
1620
- x: number;
1621
- y: number;
1622
- };
1623
- type Vec2Like = Vec2 | readonly [number, number];
1624
- /** Polyline vertex; bulge = tan(sweep/4), 0 = straight. Accepts [x, y, bulge?]. */
1625
- type PolylineVertexLike = {
1626
- x: number;
1627
- y: number;
1628
- bulge?: number;
1629
- } | readonly [number, number, number?];
1630
- /** Style overrides children may carry (otherwise inherited from the instance). */
1631
- type BaseStyle = {
1632
- /** Id of a document layer this object sits on. For a block child: absent
1633
- * = the instance's layer (the portable default; an id unknown to the
1634
- * document falls back to it); a child that names another layer hides
1635
- * with that layer, while its color / line type / width still follow the
1636
- * instance unless it sets its own (ByBlock, as in CAD). For
1637
- * `document.add`: absent = the current layer. */
1638
- layerId?: string;
1639
- /** #rrggbb; absent = by layer. */
1640
- color?: string;
1641
- /** Line type; absent = by layer. */
1642
- lineType?: string;
1643
- /** Dash-pattern length multiplier; absent = 1. */
1644
- lineTypeScale?: number;
1645
- /** Line weight in mm; absent = by layer. */
1646
- lineWidth?: number;
1647
- /** Paint opacity 0..1; absent = by layer (opaque unless the layer says). */
1648
- opacity?: number;
1649
- };
1650
- /**
1651
- * T plus the shared style fields, FLATTENED (the homomorphic map forces the
1652
- * intersection to resolve): hovers then list every member inline instead of
1653
- * the opaque `BaseStyle & { … }` — the block editor has no expand-type
1654
- * affordance, so the alias display is all a script author gets.
1655
- */
1656
- type Styled<T> = {
1657
- [K in keyof (T & BaseStyle)]: (T & BaseStyle)[K];
1658
- } & {};
1659
- type Line = Styled<{
1660
- type: "line";
1661
- a: Vec2Like;
1662
- b: Vec2Like;
1663
- }>;
1664
- /** A point: paints as a round dot whose diameter is the lineWidth. */
1665
- type Point = Styled<{
1666
- type: "point";
1667
- p: Vec2Like;
1668
- }>;
1669
- type Polyline = Styled<{
1670
- type: "polyline";
1671
- /** At least 2 vertices. */
1672
- points: readonly PolylineVertexLike[];
1673
- closed?: boolean;
1674
- }>;
1675
- type Circle = Styled<{
1676
- type: "circle";
1677
- center: Vec2Like;
1678
- radius: number;
1679
- }>;
1680
- /** Runs CCW from startAngle to endAngle (radians; DXF ARC convention). */
1681
- type Arc = Styled<{
1682
- type: "arc";
1683
- center: Vec2Like;
1684
- radius: number;
1685
- startAngle: number;
1686
- endAngle: number;
1687
- }>;
1688
- /** majorAxis = endpoint vector from center; ratio = minor/major in (0, 1]. */
1689
- type Ellipse = Styled<{
1690
- type: "ellipse";
1691
- center: Vec2Like;
1692
- majorAxis: Vec2Like;
1693
- ratio: number;
1694
- startAngle?: number;
1695
- endAngle?: number;
1696
- }>;
1697
- type Hatch = Styled<{
1698
- type: "hatch";
1699
- /** loops[0] = outer boundary, the rest are holes (even-odd). */
1700
- loops: readonly {
1701
- points: readonly PolylineVertexLike[];
1702
- }[];
1703
- fill?: {
1704
- kind: "solid";
1705
- }
1706
- /** A named pattern: the built-in catalogue (ANSI31, AR-CONC, …) or one of
1707
- * the document's own hatch patterns, by name. `angle` radians, `scale`
1708
- * multiplies the definition's mm; `origin` anchors the pattern frame
1709
- * (block-local mm; absent = the block origin). */
1710
- | {
1711
- kind: "pattern";
1712
- name: string;
1713
- angle: number;
1714
- scale: number;
1715
- origin?: Vec2Like;
1716
- } | {
1717
- kind: "lines";
1718
- angle: number;
1719
- spacing: number;
1720
- } | {
1721
- kind: "gradient";
1722
- shape?: "linear" | "radial";
1723
- color1?: string;
1724
- color2?: string;
1725
- angle?: number;
1726
- };
1727
- /** Pattern spacing multiplier. */
1728
- scale?: number;
1729
- }>;
1730
- /** Character formatting over [start, end) of a text's `content` (JS string
1731
- * indices). Absent attributes inherit the text's style; `height` is a ratio
1732
- * of its cap height. Setting `content` without `spans` drops old spans. */
1733
- type TextSpan = {
1734
- start: number;
1735
- end: number;
1736
- font?: string;
1737
- bold?: boolean;
1738
- italic?: boolean;
1739
- underline?: boolean;
1740
- /** "#rrggbb". */
1741
- color?: string;
1742
- height?: number;
1743
- script?: "sub" | "super";
1744
- };
1745
- type Text = Styled<{
1746
- type: "text";
1747
- position: Vec2Like;
1748
- content: string;
1749
- spans?: readonly TextSpan[];
1750
- rotation?: number;
1751
- /** Justification, as in AutoCAD / DXF: which edge sits on the point —
1752
- * "left" = the text runs right of it, "right" = left of it; vAlign
1753
- * "bottom" = the text sits above the point, "top" = below it. */
1754
- hAlign?: "left" | "center" | "right";
1755
- vAlign?: "bottom" | "center" | "top";
1756
- /** Word-wrap / frame width in mm (before `scale`); absent = no wrapping. */
1757
- width?: number;
1758
- frame?: "none" | "rectangle" | "circle" | "slot" | "bottom" | "firstLine";
1759
- /** MLEADER-style arrow polylines pointing at the text (arrowhead at [0]). */
1760
- leaderLines?: readonly (readonly Vec2Like[])[];
1761
- /** The document text style to follow (name or id); absent = the first. */
1762
- styleId?: string;
1763
- /** Style overrides; absent keys inherit the document text style. */
1764
- styleOverride?: {
1765
- font?: string;
1766
- widthFactor?: number;
1767
- bold?: boolean;
1768
- italic?: boolean;
1769
- /** Cap height in mm (before `scale`). */
1770
- textHeight?: number;
1771
- arrowSize?: number;
1772
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
1773
- };
1774
- /** Size multiplier for height + arrow size. */
1775
- scale?: number;
1776
- }>;
1777
- type Dimension = Styled<{
1778
- type: "dimension";
1779
- kind?: "linear" | "angular" | "radial" | "diameter";
1780
- /** linear: 2+ chained points (measured point to point); angular: [vertex, a, b]; radial: [center, p]; diameter: [p1, p2]. */
1781
- points: readonly Vec2Like[];
1782
- /** linear only: the measuring direction, radians CCW from +X. Unset =
1783
- * aligned to the points. */
1784
- rotation?: number;
1785
- /** linear: signed distance of the dimension line from points[0], positive
1786
- * to the LEFT of the measuring direction; angular: signed arc radius
1787
- * (negative = the complementary arc). Not for radial/diameter. */
1788
- offset?: number;
1789
- /** One per measured segment (linear chain: points.length − 1, others: 1).
1790
- * `along` (mm along the line from the segment origin — radial/diameter:
1791
- * from the center) and `across` (mm off the line) place the text, unset =
1792
- * automatic; `content` is the text, `{value}` = the measurement. */
1793
- labels?: readonly {
1794
- along?: number;
1795
- across?: number;
1796
- content?: string;
1797
- /** Formatting over `content` (spans covering `{value}` format it). */
1798
- spans?: readonly TextSpan[];
1799
- }[];
1800
- /** The document dimension style to follow (name or id); absent = the first. */
1801
- styleId?: string;
1802
- styleOverride?: {
1803
- textHeight?: number;
1804
- arrowSize?: number;
1805
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
1806
- /** "short" = a 2×overshoot tick across the dimension line. */
1807
- extensionType?: "long" | "short";
1808
- extensionOffset?: number;
1809
- extensionOvershoot?: number;
1810
- textOffset?: number;
1811
- precision?: number;
1812
- };
1813
- /** Annotation size multiplier (text/arrows/offsets). */
1814
- scale?: number;
1815
- }>;
1816
- /** Nested block instance (inputs may hold points, never object references). */
1817
- type Block = Styled<{
1818
- type: "block";
1819
- definitionId: string;
1820
- /** Applied last, about the pivot (the first input point). */
1821
- rotation?: number;
1822
- scale?: number;
1823
- params?: Record<string, number | string | boolean | readonly number[] | readonly string[]>;
1824
- /** Input points in the PARENT's local coords; the first is the pivot. */
1825
- inputs?: readonly Vec2Like[];
1826
- }>;
1827
- /** A table cell: plain text, or text with merge / alignment / style. */
1828
- type TableCell = string | {
1829
- content?: string;
1830
- /** Character formatting over `content`. */
1831
- spans?: readonly TextSpan[];
1832
- /** Merge from this (top-left) cell; covered cells are ignored. */
1833
- span?: {
1834
- cols: number;
1835
- rows: number;
1836
- };
1837
- hAlign?: "left" | "center" | "right";
1838
- vAlign?: "top" | "center" | "bottom";
1839
- styleId?: string;
1840
- styleOverride?: TextStyleOverride;
1841
- color?: string;
1842
- };
1843
- /** Grid of text cells hanging right/down from `position` (top-left);
1844
- * rows grow to fit their wrapped text. */
1845
- type Table = Styled<{
1846
- type: "table";
1847
- position: Vec2Like;
1848
- /** Column widths (mm, before `scale`). */
1849
- columns: readonly number[];
1850
- /** Row count, or per-row settings (`minHeight` mm floor). */
1851
- rows: number | readonly {
1852
- minHeight?: number;
1853
- }[];
1854
- /** Row-major `cells[row][column]`, exactly rows × columns. */
1855
- cells: readonly (readonly TableCell[])[];
1856
- rotation?: number;
1857
- scale?: number;
1858
- /** Rows above the heavier header rule. */
1859
- headerRows?: number;
1860
- /** Text inset from the cell edges (mm). */
1861
- cellMargin?: number;
1862
- borders?: "all" | "outer" | "rows" | "none";
1863
- styleId?: string;
1864
- styleOverride?: TextStyleOverride;
1865
- }>;
1866
- /** What a script WRITES — the union of the authoring DTOs above (what
1867
- * `draw` returns, what `document.add` takes). Read results are
1868
- * `StoredObject`. */
1869
- type ObjectInput = Line | Point | Polyline | Circle | Arc | Ellipse | Hatch | Text | Dimension | Block | Table;
1870
- /** @deprecated The input union is `ObjectInput`; in the SDK and core
1871
- * `ModelObject` is the STORED shape, so this name misled. Kept so existing
1872
- * scripts compile. */
1873
- type ModelObject = ObjectInput;
1874
- /** Identity + shared style fields every stored object carries. */
1875
- type StoredObjectBase = {
1876
- id: string;
1877
- layerId: string;
1878
- /** #rrggbb override; absent = by layer. */
1879
- color?: string;
1880
- lineType?: string;
1881
- lineTypeScale?: number;
1882
- lineWidth?: number;
1883
- /** Paint opacity 0..1; absent = opaque. */
1884
- opacity?: number;
1885
- };
1886
- /** Flattens base + per-type fields so hovers list every member inline
1887
- * (same trick as Styled<T> for the authoring DTOs). */
1888
- type StoredShape<T> = {
1889
- [K in keyof (T & StoredObjectBase)]: (T & StoredObjectBase)[K];
1890
- } & {};
1891
- /** Stored polyline vertex — bulge always present (default 0 applied). */
1892
- type StoredPolylineVertex = {
1893
- x: number;
1894
- y: number;
1895
- bulge: number;
1896
- };
1897
- type StoredLine = StoredShape<{
1898
- type: "line";
1899
- a: Vec2;
1900
- b: Vec2;
1901
- }>;
1902
- type StoredPoint = StoredShape<{
1903
- type: "point";
1904
- p: Vec2;
1905
- }>;
1906
- type StoredPolyline = StoredShape<{
1907
- type: "polyline";
1908
- points: readonly StoredPolylineVertex[];
1909
- closed: boolean;
1910
- }>;
1911
- type StoredCircle = StoredShape<{
1912
- type: "circle";
1913
- center: Vec2;
1914
- radius: number;
1915
- }>;
1916
- type StoredArc = StoredShape<{
1917
- type: "arc";
1918
- center: Vec2;
1919
- radius: number;
1920
- startAngle: number;
1921
- endAngle: number;
1922
- }>;
1923
- type StoredEllipse = StoredShape<{
1924
- type: "ellipse";
1925
- center: Vec2;
1926
- majorAxis: Vec2;
1927
- ratio: number;
1928
- startAngle: number;
1929
- endAngle: number;
1930
- }>;
1931
- type StoredHatchFill = {
1932
- kind: "solid";
1933
- } | {
1934
- kind: "pattern";
1935
- name: string;
1936
- angle: number;
1937
- scale: number;
1938
- /** World anchor of the pattern frame; absent = the drawing origin. */
1939
- origin?: Vec2;
1940
- } | {
1941
- kind: "lines";
1942
- angle: number;
1943
- spacing: number;
1944
- } | {
1945
- kind: "gradient";
1946
- shape: "linear" | "radial";
1947
- color1: string;
1948
- color2: string;
1949
- angle: number;
1950
- };
1951
- type StoredHatch = StoredShape<{
1952
- type: "hatch";
1953
- /** loops[0] = outer boundary, the rest are holes (even-odd). */
1954
- loops: readonly {
1955
- points: readonly StoredPolylineVertex[];
1956
- }[];
1957
- fill: StoredHatchFill;
1958
- scale: number;
1959
- }>;
1960
- type StoredText = StoredShape<{
1961
- type: "text";
1962
- position: Vec2;
1963
- content: string;
1964
- spans?: readonly TextSpan[];
1965
- leaderLines: readonly (readonly Vec2[])[];
1966
- /** Word-wrap / frame width in mm; absent = no wrapping. */
1967
- width?: number;
1968
- hAlign: "left" | "center" | "right";
1969
- vAlign: "bottom" | "center" | "top";
1970
- frame?: "none" | "rectangle" | "circle" | "slot" | "bottom" | "firstLine";
1971
- styleId?: string;
1972
- /** Only the keys the user actually overrode on this text. */
1973
- styleOverride?: {
1974
- font?: string;
1975
- widthFactor?: number;
1976
- bold?: boolean;
1977
- italic?: boolean;
1978
- textHeight?: number;
1979
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
1980
- arrowSize?: number;
1981
- };
1982
- rotation: number;
1983
- scale: number;
1984
- }>;
1985
- type StoredDimension = StoredShape<{
1986
- type: "dimension";
1987
- kind: "linear" | "angular" | "radial" | "diameter";
1988
- points: readonly Vec2[];
1989
- rotation?: number;
1990
- offset?: number;
1991
- labels: readonly {
1992
- along?: number;
1993
- across?: number;
1994
- content?: string;
1995
- spans?: readonly TextSpan[];
1996
- }[];
1997
- styleId?: string;
1998
- /** Only the keys the user actually overrode on this dimension. */
1999
- styleOverride?: {
2000
- font?: string;
2001
- widthFactor?: number;
2002
- bold?: boolean;
2003
- italic?: boolean;
2004
- textHeight?: number;
2005
- textOffset?: number;
2006
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
2007
- arrowSize?: number;
2008
- extensionType?: "long" | "short";
2009
- extensionOffset?: number;
2010
- extensionOvershoot?: number;
2011
- precision?: number;
2012
- };
2013
- scale: number;
2014
- }>;
2015
- type StoredBlock = StoredShape<{
2016
- type: "block";
2017
- definitionId: string;
2018
- rotation: number;
2019
- scale: number;
2020
- params: Readonly<Record<string, number | string | boolean | readonly number[] | readonly string[]>>;
2021
- /** World points and/or referenced object ids, in pick order. */
2022
- inputs: readonly (Vec2 | string)[];
2023
- }>;
2024
- /** Paper-space window into model space; exists only in layout spaces. */
2025
- type StoredViewport = StoredShape<{
2026
- type: "viewport";
2027
- rect: {
2028
- x: number;
2029
- y: number;
2030
- w: number;
2031
- h: number;
2032
- };
2033
- modelCenter: Vec2;
2034
- /** Drawing-scale denominator (model mm per paper mm); 1:50 => 50. */
2035
- scale: number;
2036
- locked: boolean;
2037
- hiddenLayerIds: readonly string[];
2038
- }>;
2039
- /** Raster reference; pixels live in the document's assets map. */
2040
- type StoredImage = StoredShape<{
2041
- type: "image";
2042
- assetId: string;
2043
- origin: Vec2;
2044
- width: number;
2045
- height: number;
2046
- rotation: number;
2047
- }>;
2048
- /** A LINKED file drawn in place (an xref); the document holds only this
2049
- * record — the file's content is not readable from scripts. */
2050
- type StoredReference = StoredShape<{
2051
- type: "reference";
2052
- format: "linea" | "dxf" | "dwg" | "pdf" | "png" | "jpg";
2053
- name: string;
2054
- source: {
2055
- kind: "path";
2056
- path: string;
2057
- cacheKey?: string;
2058
- } | {
2059
- kind: "url";
2060
- url: string;
2061
- };
2062
- /** Where the file's origin lands. */
2063
- position: Vec2;
2064
- rotation: number;
2065
- scale: number;
2066
- mirrored?: boolean;
2067
- pdfPage?: number;
2068
- pdfMode?: "vector" | "raster";
2069
- /** The file's layers not drawn, by name. */
2070
- hiddenLayers: readonly string[];
2071
- /** Switched off: not drawn. */
2072
- hidden?: boolean;
2073
- /** Locked in the References panel: drawn and snapped, never picked. */
2074
- locked?: boolean;
2075
- /** Crop rectangle in file coordinates. */
2076
- clip?: {
2077
- minX: number;
2078
- minY: number;
2079
- maxX: number;
2080
- maxY: number;
2081
- };
2082
- /** Content bounds in file coordinates at the last load. */
2083
- extent?: {
2084
- minX: number;
2085
- minY: number;
2086
- maxX: number;
2087
- maxY: number;
2088
- };
2089
- }>;
2090
- /** Review note pinned to a point; the editor shows a screen-fixed marker. */
2091
- type StoredComment = StoredShape<{
2092
- type: "comment";
2093
- /** Tail tip of the bubble (world/sheet mm). */
2094
- position: Vec2;
2095
- text: string;
2096
- tags: readonly string[];
2097
- }>;
2098
- /** Text style keys a text, table or table cell may override. */
2099
- type TextStyleOverride = {
2100
- font?: string;
2101
- widthFactor?: number;
2102
- bold?: boolean;
2103
- italic?: boolean;
2104
- textHeight?: number;
2105
- arrowType?: "filled" | "open" | "tick" | "dot" | "none";
2106
- arrowSize?: number;
2107
- };
2108
- /** One table cell as stored. */
2109
- type StoredTableCell = {
2110
- /** Plain text; "\n" = line break. */
2111
- content: string;
2112
- spans?: readonly TextSpan[];
2113
- /** Merge, on the anchor (top-left) cell; covered cells are ignored. */
2114
- span?: {
2115
- cols: number;
2116
- rows: number;
2117
- };
2118
- hAlign?: "left" | "center" | "right";
2119
- vAlign?: "top" | "center" | "bottom";
2120
- styleId?: string;
2121
- styleOverride?: TextStyleOverride;
2122
- color?: string;
2123
- };
2124
- /** Grid of text cells hanging right/down from `position` (top-left). */
2125
- type StoredTable = StoredShape<{
2126
- type: "table";
2127
- position: Vec2;
2128
- rotation: number;
2129
- scale: number;
2130
- /** Column widths (mm, before `scale`). */
2131
- columns: readonly number[];
2132
- rows: readonly {
2133
- minHeight?: number;
2134
- }[];
2135
- /** Row-major `cells[row][column]`. */
2136
- cells: readonly (readonly StoredTableCell[])[];
2137
- headerRows: number;
2138
- cellMargin: number;
2139
- borders: "all" | "outer" | "rows" | "none";
2140
- styleId?: string;
2141
- styleOverride?: TextStyleOverride;
2142
- }>;
2143
- /** Any object as stored in the document — what reads hand to scripts. */
2144
- type StoredObject = StoredLine | StoredPoint | StoredPolyline | StoredCircle | StoredArc | StoredEllipse | StoredHatch | StoredText | StoredDimension | StoredBlock | StoredViewport | StoredImage | StoredComment | StoredTable | StoredReference;
2145
- /**
2146
- * One choice of a "Select" parameter: the value (what scripts receive) with
2147
- * an optional properties-panel label. A plain string is shorthand for
2148
- * `{ value }`.
2149
- */
2150
- type ParameterOption = string | {
2151
- value: string;
2152
- label?: string;
2153
- /** A `#rrggbb` color square before the option's label. */
2154
- swatch?: string;
2155
- };
2156
- /**
2157
- * One entry of the module's optional `params` export — the block's
2158
- * parameters table. `name` is the key scripts read from `params`, `label`
2159
- * the properties-panel caption (defaults to the name).
2160
- */
2161
- /** What every params-table entry may carry: its key, panel caption and
2162
- * tooltip. */
2163
- type ParamBase = {
2164
- /** The key scripts read from `params`. */
2165
- name: string;
2166
- /** The properties-panel caption (defaults to the name). */
2167
- label?: string;
2168
- /** What the parameter means: the label's tooltip in the panel. */
2169
- hint?: string;
2170
- };
2171
- type ParamDef = (ParamBase & {
2172
- type: "number";
2173
- default: number;
2174
- min?: number;
2175
- max?: number;
2176
- /** Whole numbers only. */
2177
- integer?: boolean;
2178
- /** ArrowUp / ArrowDown increment in the panel (default 1). */
2179
- step?: number;
2180
- /** Shown inside the field before / after the value ("1:", "mm"). */
2181
- prefix?: string;
2182
- suffix?: string;
2183
- /** Standard values offered in the field's dropdown; typing stays free. */
2184
- presets?: readonly number[];
2185
- }) | (ParamBase & {
2186
- type: "string";
2187
- default: string;
2188
- placeholder?: string;
2189
- /** A textarea; Shift+Enter starts a new line. */
2190
- multiline?: boolean;
2191
- presets?: readonly string[];
2192
- }) | (ParamBase & {
2193
- type: "boolean";
2194
- default: boolean;
2195
- /** "toggle": a toggle button showing the label (compact, e.g. in a
2196
- * row beside a picker) instead of a switch. */
2197
- display?: "switch" | "toggle";
2198
- })
2199
- /** A list of numbers, edited as space-separated text with Tekla-style
2200
- * `N*d` repeats ("0 2*7200" → [0, 7200, 7200]). */
2201
- | (ParamBase & {
2202
- type: "numberList";
2203
- default: readonly number[];
2204
- /** Shown while the list is empty. */
2205
- placeholder?: string;
2206
- min?: number;
2207
- max?: number;
2208
- presets?: readonly (readonly number[])[];
2209
- })
2210
- /** A list of strings, edited as space-separated words; double quotes group
2211
- * a phrase ('A "B 2"' → ["A", "B 2"]). */
2212
- | (ParamBase & {
2213
- type: "stringList";
2214
- default: readonly string[];
2215
- /** Shown while the list is empty. */
2216
- placeholder?: string;
2217
- presets?: readonly (readonly string[])[];
2218
- })
2219
- /** A `#rrggbb` color: a swatch with a picker; presets form a palette. */
2220
- | (ParamBase & {
2221
- type: "color";
2222
- default: string;
2223
- presets?: readonly string[];
2224
- }) | (ParamBase & {
2225
- type: "enum";
2226
- default: string;
2227
- options: readonly ParameterOption[];
2228
- /** "buttons": a segmented toggle group of the options (short
2229
- * choices); falls back to the dropdown when they don't fit. */
2230
- display?: "dropdown" | "buttons";
2231
- })
2232
- /** Pickers over the document's resources; the value is an id / name.
2233
- * textStyle / dimStyle: a style id ("" or unknown = the document's first
2234
- * style — read it in draw with `styles.text(id)` / `styles.dim(id)`, or
2235
- * hand it to children as `styleId`). font: a font id ("arial"…).
2236
- * lineType / hatchPattern: a linetype / pattern name. */
2237
- | (ParamBase & {
2238
- type: "textStyle" | "dimStyle" | "font" | "lineType" | "hatchPattern";
2239
- default?: string;
2240
- })
2241
- /** A section label between rows in the properties panel. Carries no
2242
- * value: it never appears in the `params` record `draw` receives.
2243
- * `name` stays the unique key (paramVisibility can hide it by name). */
2244
- | (ParamBase & {
2245
- type: "label";
2246
- })
2247
- /** Layout only: 2–3 compact params on one panel row, each item's label a
2248
- * short prefix ("W", "H"). Values stay flat — `params.w`, `params.h`. */
2249
- | (ParamBase & {
2250
- type: "row";
2251
- items: readonly RowItemDef[];
2252
- });
2253
- /** A document text style as `draw` reads it (`styles.text(id)`). Heights
2254
- * and arrow sizes are mm before an object's `scale`. */
2255
- type TextStyleInfo = {
2256
- readonly id: string;
2257
- readonly name: string;
2258
- readonly font: string;
2259
- readonly widthFactor: number;
2260
- readonly bold?: boolean;
2261
- readonly italic?: boolean;
2262
- readonly textHeight: number;
2263
- readonly arrowType: "filled" | "open" | "tick" | "dot" | "none";
2264
- readonly arrowSize: number;
2265
- };
2266
- /** A document dimension style as `draw` reads it (`styles.dim(id)`). */
2267
- type DimStyleInfo = {
2268
- readonly id: string;
2269
- readonly name: string;
2270
- readonly font: string;
2271
- readonly widthFactor: number;
2272
- readonly bold?: boolean;
2273
- readonly italic?: boolean;
2274
- readonly textHeight: number;
2275
- readonly textOffset: number;
2276
- readonly arrowType: "filled" | "open" | "tick" | "dot" | "none";
2277
- readonly arrowSize: number;
2278
- readonly extensionType: "long" | "short";
2279
- readonly extensionOffset: number;
2280
- readonly extensionOvershoot: number;
2281
- readonly precision: number;
2282
- };
2283
- /** `draw`'s `styles`: the document's styles by id. An empty or unknown id
2284
- * (a deleted style, a block from another drawing) gives the document's
2285
- * first style — the same rule a child's `styleId` follows. */
2286
- interface BlockStyles {
2287
- text(id?: string): TextStyleInfo;
2288
- dim(id?: string): DimStyleInfo;
2289
- }
2290
- /** What a `row` may hold: the compact, single-line param kinds. */
2291
- type RowItemDef = Extract<ParamDef, {
2292
- type: "number" | "string" | "boolean" | "enum" | "color" | "textStyle" | "dimStyle" | "font" | "lineType" | "hatchPattern";
2293
- }>;
2294
- /** A table entry's value-carrying params: a row's items, else itself. */
2295
- type FlatParam<Q> = Q extends {
2296
- type: "row";
2297
- items: readonly (infer I)[];
2298
- } ? I : Q;
2299
- /**
2300
- * The block's parameters table — what the `params` member of a BlockSpec
2301
- * declares (or its function form returns).
2302
- */
2303
- type BlockParamDefs = readonly ParamDef[];
2304
- /** What the script's `draw` export must return. */
2305
- type BlockScriptResult = ObjectInput[];
2306
- /** The value an enum option denotes (its string, or `value` of the record form). */
2307
- type OptionValue<O extends ParameterOption> = O extends string ? O : O extends {
2308
- value: infer V extends string;
2309
- } ? V : never;
2310
- /** The runtime value type of one `params` table entry. */
2311
- type ParamValue<Q extends ParamDef> = Q extends {
2312
- type: "enum";
2313
- } ? OptionValue<Q["options"][number]> : Q extends {
2314
- type: "number";
2315
- } ? number : Q extends {
2316
- type: "boolean";
2317
- } ? boolean : Q extends {
2318
- type: "numberList";
2319
- } ? readonly number[] : Q extends {
2320
- type: "stringList";
2321
- } ? readonly string[] : string;
2322
- /**
2323
- * The values record a params table produces: each entry's `name` maps to
2324
- * its runtime value type (number/string/boolean, or the enum's option
2325
- * union). This is what `draw`/`place`/`paramVisibility` receive as
2326
- * `params` — inside defineBlock the table type is inferred, so authors
2327
- * never spell this out. Unwraps the function form of `params`; a non-table
2328
- * type (an already-derived values record, or the open BlockParams default)
2329
- * passes through unchanged.
2330
- */
2331
- type ParamValues<P> = P extends () => infer R ? ParamValues<R> : P extends readonly (infer Q extends ParamDef)[] ? {
2332
- readonly [E in FlatParam<Q> as E extends {
2333
- type: "label";
2334
- } ? never : E extends {
2335
- name: infer N extends string;
2336
- } ? N : never]: E extends ParamDef ? ParamValue<E> : never;
2337
- } : P;
2338
- /** A document line type definition — objects and layers name it in
2339
- * `lineType`, ahead of the built-in catalogue. */
2340
- type LineType = {
2341
- /** Case-insensitive, unique per document. */
2342
- name: string;
2343
- description?: string;
2344
- /** Signed dash cycle, mm per 1 mm of line width: >0 dash, <0 gap, 0 dot.
2345
- * Empty = continuous. */
2346
- dashesMm: number[];
2347
- };
2348
- /** One line family of a hatch pattern, in the pattern's own frame. */
2349
- type HatchPatternLine = {
2350
- /** Radians CCW. */
2351
- angle: number;
2352
- /** Base point, mm. */
2353
- origin: Vec2;
2354
- /** Shift along the line between successive lines (dash phase), mm. */
2355
- deltaX: number;
2356
- /** Perpendicular spacing between successive lines, mm. */
2357
- deltaY: number;
2358
- /** Dash cycle along the line: >0 dash, <0 gap, 0 dot; absent = solid. */
2359
- dashesMm?: number[];
2360
- };
2361
- /** A document hatch pattern definition — pattern fills name it in
2362
- * `fill.name`, ahead of the built-in catalogue. */
2363
- type HatchPattern = {
2364
- /** Case-insensitive, unique per document. */
2365
- name: string;
2366
- description?: string;
2367
- lines: HatchPatternLine[];
2368
- };
2369
- /** An axis-aligned box in world mm. */
2370
- type Box = {
2371
- minX: number;
2372
- minY: number;
2373
- maxX: number;
2374
- maxY: number;
2375
- };
2376
- /** Filters for Drawing.query — all present filters AND together. */
2377
- type ObjectQuery = {
2378
- ids?: readonly string[];
2379
- type?: ObjectInput["type"];
2380
- /** Layer name or id. */
2381
- layer?: string;
2382
- /** #rrggbb override (objects without one inherit from their layer). */
2383
- color?: string;
2384
- lineType?: string;
2385
- /** Substring match on text content. */
2386
- content?: string;
2387
- /** Bounds intersect this box. */
2388
- bbox?: Box;
2389
- /** Bounds entirely inside this box. */
2390
- inside?: Box;
2391
- /** Geometry within `tol` mm of `point`. */
2392
- near?: {
2393
- point: Vec2Like;
2394
- tol: number;
2395
- };
2396
- /** Search this paper layout's sheet objects (name or id) instead of
2397
- * model space. */
2398
- layout?: string;
2399
- };
2400
- /** A STORED object as query() returns it (see StoredObject — schema
2401
- * output: defaults applied, points always {x, y}, identity present). */
2402
- type ExistingObject = StoredObject;
2403
- /** Per-object measurements; null where the type has no natural value. */
2404
- type Measurement = {
2405
- bbox: Box | null;
2406
- length: number | null;
2407
- area: number | null;
2408
- };
2409
- /** A layer as stored (defaults applied) plus the current-layer flag. */
2410
- type LayerInfo = {
2411
- id: string;
2412
- name: string;
2413
- color: string;
2414
- lineType: string;
2415
- lineWidth: number;
2416
- opacity: number;
2417
- visible: boolean;
2418
- locked: boolean;
2419
- current: boolean;
2420
- [key: string]: unknown;
2421
- };
2422
- /** A paper layout as stored: sheet metadata + its sheet-space objects. */
2423
- type LayoutInfo = {
2424
- id: string;
2425
- name: string;
2426
- sheet: {
2427
- width: number;
2428
- height: number;
2429
- };
2430
- printPalette: "color" | "grayscale" | "monochrome";
2431
- objects: readonly StoredObject[];
2432
- };
2433
- /** A block module's identity/metadata (from its exports). */
2434
- type BlockInfo = {
2435
- id: string;
2436
- name: string;
2437
- description?: string;
2438
- version?: string;
2439
- authors?: readonly string[];
2440
- tags?: readonly string[];
2441
- dependencies?: readonly string[];
2442
- };
2443
- /** A command module's identity/metadata (from its exports). */
2444
- type CommandInfo = {
2445
- id: string;
2446
- name: string;
2447
- description?: string;
2448
- version?: string;
2449
- authors?: readonly string[];
2450
- tags?: readonly string[];
2451
- /** Declared point inputs (labels), picked or supplied before `run`. */
2452
- inputs?: readonly string[];
2453
- /** Declared parameters (same table as a block's), prompted or supplied
2454
- * before `run`. */
2455
- params?: readonly ParamDef[];
2456
- };
2457
- /** What installing module sources reports. */
2458
- /** One configured marketplace (a block / command collection). */
2459
- type MarketplaceConfig = {
2460
- kind: "builtin";
2461
- } | {
2462
- kind: "github";
2463
- spec: string;
2464
- token?: string;
2465
- } | {
2466
- kind: "folder";
2467
- folder: string;
2468
- };
2469
- /** A configured marketplace as listed — the token itself never shows. */
2470
- type MarketplaceInfo = {
2471
- key: string;
2472
- kind: "builtin" | "github" | "folder";
2473
- label: string;
2474
- spec?: string;
2475
- folder?: string;
2476
- hasToken: boolean;
2477
- };
2478
- /** A marketplace search hit: the catalog row plus where it came from and
2479
- * how it relates to this document's modules. */
2480
- type MarketplaceHit = {
2481
- kind: "block" | "command";
2482
- id: string;
2483
- name: string;
2484
- version: string;
2485
- description?: string;
2486
- tags: string[];
2487
- authors: string[];
2488
- dependencies: string[];
2489
- marketplace: MarketplaceInfo;
2490
- status: {
2491
- kind: "absent";
2492
- } | {
2493
- kind: "installed";
2494
- version?: string;
2495
- } | {
2496
- kind: "update";
2497
- from?: string;
2498
- };
2499
- };
2500
- type MergeReport = {
2501
- /** The full library after the merge. */
2502
- merged: readonly string[];
2503
- added: readonly {
2504
- script: string;
2505
- meta: {
2506
- id: string;
2507
- name: string;
2508
- };
2509
- }[];
2510
- replaced: readonly {
2511
- script: string;
2512
- meta: {
2513
- id: string;
2514
- name: string;
2515
- };
2516
- }[];
2517
- skipped: number;
2518
- rejected: readonly {
2519
- script: string;
2520
- error: string;
2521
- }[];
2522
- };
2523
- /** A sheet: a bare preset (orientation from context — landscape for a new
2524
- * layout, the current one when patching), a preset with its orientation, or
2525
- * explicit millimetres. */
2526
- type SheetSpec = "A4" | "A3" | "A2" | "A1" | "A0" | {
2527
- name: "A4" | "A3" | "A2" | "A1" | "A0";
2528
- orientation: "portrait" | "landscape";
2529
- } | {
2530
- width: number;
2531
- height: number;
2532
- };
2533
- /** What an import added (`objectIds` = the new objects). */
2534
- interface ImportReport {
2535
- objects: number;
2536
- objectIds: string[];
2072
+ export const union: (...polygons: PolygonLike[]) => Ring[];
2073
+ /** `subject` minus every clip polygon (openings cut from a wall). Same
2074
+ * result rings as `union`. */
2075
+ export const difference: (subject: PolygonLike, ...clips: PolygonLike[]) => Ring[];
2076
+ /** Where ALL the polygons overlap. Same result rings as `union`. */
2077
+ export const intersection: (...polygons: PolygonLike[]) => Ring[];
2537
2078
  }
2538
- /** Options for Drawing.addLayout. */
2539
- type LayoutSpec = {
2540
- /** Default: A3 landscape. */
2541
- sheet?: SheetSpec;
2542
- /** Viewport scale — `"1:50"` or the denominator; default: fitted. */
2543
- scale?: number | string;
2544
- /** One fitted model viewport (default), or `false` for a bare sheet. */
2545
- viewport?: {
2546
- rect?: {
2547
- x: number;
2548
- y: number;
2549
- w: number;
2550
- h: number;
2551
- };
2552
- scale?: number | string;
2553
- center?: Vec2Like;
2554
- } | false;
2555
- /** Tab position; default: append. */
2556
- index?: number;
2557
- };
2558
- /** The whole document as stored (defaults applied). */
2559
- type StoredDocument = {
2560
- id: string;
2561
- version: number;
2562
- layers: readonly Omit<LayerInfo, "current">[];
2563
- currentLayerId: string;
2564
- objects: readonly StoredObject[];
2565
- layouts: readonly LayoutInfo[];
2566
- /** Raw block module sources. */
2567
- blockDefinitions: readonly string[];
2568
- /** Raw command module sources. */
2569
- commands: readonly string[];
2570
- [key: string]: unknown;
2571
- };
2572
- /** Where a draw-order move puts the objects. */
2573
- type ReorderPlacement = "front" | "back" | {
2574
- above: string;
2575
- } | {
2576
- below: string;
2577
- };
2578
- /**
2579
- * The document as command scripts see it — the SAME `Drawing` interface
2580
- * the agent tools and the SDK use. Angles are RADIANS, point-valued
2581
- * arguments accept {x, y} or [x, y], `layer` resolves by name or id.
2582
- * Object mutations on an editor-attached drawing target the ACTIVE space.
2583
- * Methods throw on invalid input (an uncaught throw cancels the command
2584
- * and rolls its edits back). Reads return detached snapshots.
2585
- */
2586
- interface Drawing {
2587
- /** The document's own id. */
2588
- readonly id: string;
2589
- /** Monotonic change counter. */
2590
- readonly revision: number;
2591
- /** The full document — a detached snapshot. */
2592
- readonly document: StoredDocument;
2593
- /** Counts by type/layer, bbox, layer + layout names. */
2594
- summary(): {
2595
- name: string;
2596
- objectCount: number;
2597
- byType: Record<string, number>;
2598
- byLayer: Record<string, number>;
2599
- bbox: Box | null;
2600
- layers: string[];
2601
- layouts: {
2602
- name: string;
2603
- objectCount: number;
2604
- }[];
2605
- settings: {
2606
- units: "mm" | "in";
2607
- };
2608
- };
2609
- /** Filtered objects — model space, or one layout via `filter.layout`. */
2610
- listObjects(filter?: ObjectQuery): ExistingObject[];
2611
- /** One object from ANY space, or undefined. */
2612
- getObject(id: string): ExistingObject | undefined;
2613
- /** bbox / curve length / enclosed area of one object. */
2614
- measure(id: string): Measurement;
2615
- listLayers(): LayerInfo[];
2616
- listLayouts(): LayoutInfo[];
2617
- /** Compilable block definitions in this document. */
2618
- listBlockDefinitions(): BlockInfo[];
2619
- /** Compilable command modules travelling with this document. */
2620
- listUserCommands(): CommandInfo[];
2621
- /** Model space (or a layout via `layout`) as an SVG string. */
2622
- renderSvg(opts?: {
2623
- layout?: string;
2624
- bbox?: Box;
2625
- padding?: number;
2626
- palette?: "color" | "grayscale" | "monochrome";
2627
- }): string;
2628
- /** Model space (or a layout) as PNG bytes — absent on hosts that can't
2629
- * rasterize, so check before calling. */
2630
- renderPng?(opts?: {
2631
- layout?: string;
2632
- bbox?: Box;
2633
- padding?: number;
2634
- palette?: "color" | "grayscale" | "monochrome";
2635
- /** Output width in px (height follows). Default 1024. */
2636
- width?: number;
2637
- /** Background fill, e.g. "#ffffff". Default: the dark canvas. */
2638
- background?: string;
2639
- }): Promise<Uint8Array>;
2640
- /** Multi-page PDF of the layouts (default: all) — absent on hosts
2641
- * without fonts, so check before calling. */
2642
- renderPdf?(opts?: {
2643
- layouts?: readonly string[];
2644
- palette?: "color" | "grayscale" | "monochrome";
2645
- }): Promise<Uint8Array>;
2646
- /** The whole document as DXF text. */
2647
- toDxf(): Promise<string>;
2648
- /** DWG bytes (default AC1027 — AutoCAD 2013). */
2649
- toDwg(opts?: {
2650
- version?: string;
2651
- }): Promise<Uint8Array>;
2652
- /** The `.linea` file text. */
2653
- toLinea(): string;
2654
- /** Add objects (each may carry `layer` — a name — instead of an id);
2655
- * returns the created ids. */
2656
- add(objects: readonly (ObjectInput & {
2657
- layer?: string;
2658
- })[], opts?: {
2659
- layout?: string;
2660
- }): string[];
2661
- /** Apply per-object patches (`{ id, ...changedFields }`). */
2662
- update(entries: readonly ({
2663
- id: string;
2664
- } & Record<string, unknown>)[]): void;
2665
- /** Delete by id (unknown ids are skipped); returns how many went. */
2666
- remove(ids: readonly string[]): number;
2667
- /** Draw order: move the objects (bottom → top) to a placement. */
2668
- reorder(ids: readonly string[], placement: ReorderPlacement): void;
2669
- move(ids: readonly string[], delta: Vec2Like): void;
2670
- rotate(ids: readonly string[], angleRad: number, center?: Vec2Like): void;
2671
- scale(ids: readonly string[], factor: number, center?: Vec2Like): void;
2672
- mirror(ids: readonly string[], axisA: Vec2Like, axisB: Vec2Like): void;
2673
- /** Duplicate displaced by delta; returns the new ids. */
2674
- copy(ids: readonly string[], delta: Vec2Like): string[];
2675
- /** count TOTAL copies at multiples of delta; returns the new ids. */
2676
- array(ids: readonly string[], count: number, delta: Vec2Like): string[];
2677
- /** Create a paper layout; returns its id. */
2678
- addLayout(name: string, opts?: LayoutSpec): string;
2679
- /** Patch a layout's name / sheet / print palette. A bare preset keeps the
2680
- * layout's current orientation. */
2681
- updateLayout(nameOrId: string, patch: {
2682
- name?: string;
2683
- sheet?: SheetSpec;
2684
- printPalette?: "color" | "grayscale" | "monochrome";
2685
- }): void;
2686
- removeLayout(nameOrId: string): void;
2687
- /** Explicit total order (names or ids) — the PDF page order. */
2688
- reorderLayouts(order: readonly string[]): void;
2689
- /** Create a layer (unique name); returns its id. */
2690
- addLayer(props: {
2691
- name: string;
2692
- color?: string;
2693
- } & Record<string, unknown>): string;
2694
- updateLayer(nameOrId: string, patch: Record<string, unknown>): void;
2695
- /** Remove an EMPTY, non-current layer. */
2696
- removeLayer(nameOrId: string): void;
2697
- /** Explicit total order (names or ids, every layer exactly once). */
2698
- reorderLayers(order: readonly string[]): void;
2699
- setCurrentLayer(nameOrId: string): void;
2700
- /** Document-wide settings, merged over the current record. */
2701
- updateSettings(patch: {
2702
- units?: "mm" | "in";
2703
- }): void;
2704
- /** Configured marketplaces, priority order (tokens hidden). */
2705
- listMarketplaces(): MarketplaceInfo[];
2706
- /** Add marketplaces at the top of the priority list; each catalog must be
2707
- * fetchable. `{ kind: "github", spec: "owner/repo[@branch]", token? }` or
2708
- * `{ kind: "folder", folder }`. */
2709
- addMarketplaces(list: readonly MarketplaceConfig[]): Promise<MarketplaceInfo[]>;
2710
- /** Remove by key, spec, folder or label; the built-in collection stays. */
2711
- removeMarketplaces(names: readonly string[]): MarketplaceInfo[];
2712
- /** Search entries across the marketplaces, with install status. */
2713
- searchMarketplaces(q?: {
2714
- query?: string;
2715
- kind?: "block" | "command";
2716
- marketplace?: string;
2717
- }): Promise<MarketplaceHit[]>;
2718
- /** Install (or update) entries by id, dependencies first — one undo step. */
2719
- installMarketplaceEntries(ids: readonly string[], marketplace?: string): Promise<MergeReport>;
2720
- listTextStyles(): ({
2721
- id: string;
2722
- name: string;
2723
- } & Record<string, unknown>)[];
2724
- listDimStyles(): ({
2725
- id: string;
2726
- name: string;
2727
- } & Record<string, unknown>)[];
2728
- /** Create a style (unique name; unset fields take the defaults); returns
2729
- * its id. Styles are addressed by name or id. */
2730
- addTextStyle(props: {
2731
- name: string;
2732
- } & Record<string, unknown>): string;
2733
- updateTextStyle(nameOrId: string, patch: Record<string, unknown>): void;
2734
- /** Remove a style no object uses (refused otherwise). */
2735
- removeTextStyle(nameOrId: string): void;
2736
- addDimStyle(props: {
2737
- name: string;
2738
- } & Record<string, unknown>): string;
2739
- updateDimStyle(nameOrId: string, patch: Record<string, unknown>): void;
2740
- removeDimStyle(nameOrId: string): void;
2741
- /** @deprecated Use updateDimStyle (default here: the first style). */
2742
- setDimStyle(patch: Record<string, unknown>, styleId?: string): void;
2743
- /** @deprecated Use updateTextStyle (default here: the first style). */
2744
- setTextStyle(patch: Record<string, unknown>, styleId?: string): void;
2745
- /** The document's own line type definitions (objects and layers name
2746
- * them, ahead of the built-in catalogue). */
2747
- listLineTypes(): LineType[];
2748
- /** Add definitions (names unique, case-insensitive; a clash is refused). */
2749
- addLineTypes(lineTypes: readonly LineType[]): void;
2750
- updateLineType(name: string, patch: Partial<LineType>): void;
2751
- /** Remove a definition; objects still naming it fall back to the
2752
- * catalogue or continuous. */
2753
- removeLineType(name: string): void;
2754
- /** The document's own hatch pattern definitions (same model as line
2755
- * types: fills name them, ahead of the catalogue). */
2756
- listHatchPatterns(): HatchPattern[];
2757
- addHatchPatterns(patterns: readonly HatchPattern[]): void;
2758
- updateHatchPattern(name: string, patch: Partial<HatchPattern>): void;
2759
- removeHatchPattern(name: string): void;
2760
- /** Embed image pixels (a data URL); returns the content-keyed assetId
2761
- * that `image` objects reference. */
2762
- addAsset(dataUrl: string): string;
2763
- /** Remove an asset (refused while an image references it). */
2764
- removeAsset(id: string): void;
2765
- /** Embedded image assets and how many images use each. */
2766
- listAssets(): {
2767
- id: string;
2768
- mimeType: string;
2769
- bytes: number;
2770
- users: number;
2771
- }[];
2772
- /** Merge DXF text (new layers, objects, layouts); `unitOverride` = mm
2773
- * per drawing unit. */
2774
- importDxfText(text: string, opts?: {
2775
- unitOverride?: number;
2776
- }): ImportReport & {
2777
- layers: number;
2778
- layouts: number;
2779
- layoutIds: string[];
2780
- };
2781
- /** Merge DWG bytes (transcoded to DXF). */
2782
- importDwgData(data: Uint8Array, opts?: {
2783
- unitOverride?: number;
2784
- }): Promise<ImportReport & {
2785
- layers: number;
2786
- layouts: number;
2787
- layoutIds: string[];
2788
- }>;
2789
- /** Merge a PDF: vectors/text onto the current layer, or (`as: "image"`,
2790
- * not available on every host) each page as an image at true scale. */
2791
- importPdfData(data: ArrayBuffer | Uint8Array, opts?: {
2792
- as?: "vectors" | "image";
2793
- origin?: Vec2Like;
2794
- }): Promise<ImportReport & {
2795
- pageCount: number;
2796
- }>;
2797
- /** Merge block module sources into the document library. */
2798
- addBlockDefinitions(sources: readonly string[]): Promise<MergeReport>;
2799
- removeBlockDefinition(id: string): void;
2800
- addUserCommands(sources: readonly string[]): Promise<MergeReport>;
2801
- removeUserCommand(id: string): void;
2802
- /** Escape hatch: apply an already-shaped kernel op batch (validated,
2803
- * atomic, one undo step). */
2804
- applyOps(ops: readonly Record<string, unknown>[]): void;
2805
- /**
2806
- * Group edits into ONE undo step (a command run already is one; nested
2807
- * calls join it). A throw rolls back what the transaction applied.
2808
- */
2809
- transaction<T>(fn: () => T, label?: string): T;
2810
- /** Not available while a command runs (throws) — return or throw. */
2811
- undo(): boolean;
2812
- redo(): boolean;
2813
- }
2814
- /** The editor's state as a script sees it. */
2815
- type EditorState = {
2816
- documentId: string;
2817
- documentName: string;
2818
- space: "model" | {
2819
- layout: string;
2820
- };
2821
- selectedIds: string[];
2822
- readOnly: boolean;
2823
- canUndo: boolean;
2824
- canRedo: boolean;
2825
- };
2826
- /** One runnable editor command (registry entry, macro, or insert-block). */
2827
- type EditorCommandInfo = {
2828
- id: string;
2829
- label: string;
2830
- group: string;
2831
- hotkey?: string;
2832
- };
2833
- /**
2834
- * The interactive half of the context — present only when the command runs
2835
- * inside a live editor (absent when a script runs headlessly, e.g. from the
2836
- * CLI or the MCP server; branch on it). The pickers and `prompt` REJECT
2837
- * when the user cancels (Escape) — let that propagate to abort the command
2838
- * (all edits roll back), or catch it to finish an open-ended collection.
2839
- */
2840
- interface EditorSurface {
2841
- state(): EditorState;
2842
- setActiveSpace(space: "model" | {
2843
- layout: string;
2844
- }): void;
2845
- setSelection(ids: readonly string[]): void;
2846
- /** "fit" (everything in the active space), "selection", some objects'
2847
- * extents (`{ ids }`), or a window (`{ bbox }`, world mm; sheet mm in a
2848
- * layout). */
2849
- zoom(to: "fit" | "selection" | {
2850
- ids: readonly string[];
2851
- } | {
2852
- bbox: Box;
2853
- }): void;
2854
- /** Await one snapped world point; `referencePoint` enables rubber-band
2855
- * + relative typed entry from there. */
2856
- pickPoint(opts?: {
2857
- label?: string;
2858
- referencePoint?: Vec2Like;
2859
- }): Promise<Vec2>;
2860
- /** Await one object click; resolves the object's id. */
2861
- pickObject(opts?: {
2862
- label?: string;
2863
- }): Promise<string>;
2864
- /** Await a typed value from a small input dialog. */
2865
- prompt(message: string, opts?: {
2866
- initial?: string;
2867
- placeholder?: string;
2868
- }): Promise<string>;
2869
- toast(message: string, kind?: "info" | "success" | "error"): void;
2870
- /** Registry commands + macros + insert-block entries. */
2871
- listCommands(): EditorCommandInfo[];
2872
- /** Trigger a command by id — like the user pressing its hotkey. A macro
2873
- * takes its declared `inputs` / `params` up front (params passed skip its
2874
- * params dialog). */
2875
- runCommand(id: string, inputs?: readonly Vec2Like[], params?: Readonly<Record<string, unknown>>): Promise<void>;
2876
- }
2877
- /**
2878
- * What `run` receives. `document` is the Drawing; `editor` the interactive
2879
- * surface when there is one; `inputs` the points the command's declared
2880
- * `inputs` labels produced (picked in the editor, or supplied by the
2881
- * caller), in label order; `params` the values of the declared `params`
2882
- * table (asked for in a dialog in the editor, or passed by the caller;
2883
- * omitted ones take their defaults).
2884
- */
2885
- interface CommandContext<P = Readonly<Record<string, unknown>>> {
2886
- document: Drawing;
2887
- editor?: EditorSurface;
2888
- inputs: readonly Vec2[];
2889
- params: P;
2890
- /** @deprecated Use `editor.pickPoint({ label })` (throws without an editor). */
2891
- pickPoint(label?: string): Promise<Vec2>;
2892
- /** @deprecated Use `editor.pickObject({ label })`. */
2893
- pickObject(label?: string): Promise<string>;
2894
- /** @deprecated Use `editor.state().selectedIds`. */
2895
- selection(): string[];
2896
- /** @deprecated Use `editor.setSelection(ids)`. */
2897
- setSelection(ids: readonly string[]): void;
2898
- /** @deprecated Use `editor.prompt(message, options)`. */
2899
- prompt(message: string, options?: {
2900
- initial?: string;
2901
- placeholder?: string;
2902
- }): Promise<string>;
2903
- /** @deprecated Use `editor.toast(message, kind)`. */
2904
- showToast(message: string, kind?: "info" | "success" | "error"): void;
2905
- }
2906
-
2907
- // Script-contract globals: aliases into the module (not re-declarations),
2908
- // so the in-app editor's BlockParams substitution flows through them.
2909
- declare type BlockParams = import("lineadraw").BlockParams;
2910
- declare type BlockInputs = import("lineadraw").BlockInputs;
2911
- declare type ResolvedObject = import("lineadraw").ResolvedObject;
2912
- declare type ResolvedInput<T> = import("lineadraw").ResolvedInput<T>;
2913
- declare type PlaceProps<P = BlockParams> = import("lineadraw").PlaceProps<P>;
2914
- declare type PlaceSpec<P = BlockParams> = import("lineadraw").PlaceSpec<P>;
2915
- declare type PlaceInputs<Pl> = import("lineadraw").PlaceInputs<Pl>;
2916
- declare type PreviewInputs<Pl> = import("lineadraw").PreviewInputs<Pl>;
2917
- declare type BlockSpec<
2918
- P extends import("lineadraw").BlockParamDefs = readonly [],
2919
- Pl extends PlaceSpec<P> | undefined = undefined,
2920
- > = import("lineadraw").BlockSpec<P, Pl>;
2921
- declare type CommandSpec<
2922
- P extends import("lineadraw").BlockParamDefs = readonly [],
2923
- > = import("lineadraw").CommandSpec<P>;