lineadraw 0.1.0 → 0.2.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 +1180 -787
- package/package.json +18 -18
package/lineadraw.d.ts
CHANGED
|
@@ -1,787 +1,1180 @@
|
|
|
1
|
-
// GENERATED — do not edit. Typings for the virtual "lineadraw" and
|
|
2
|
-
// "lineadraw/helpers" modules block scripts import from, emitted from
|
|
3
|
-
// packages/core/src/blocks/{blockTypes,blockHelpers}.ts. Regenerate with:
|
|
4
|
-
// npm run gen:lineadraw-dts -w @lineadraw/core
|
|
5
|
-
|
|
6
|
-
declare module "lineadraw" {
|
|
7
|
-
/** A 2D point (mm, y-up). Point-valued fields also accept [x, y]. */
|
|
8
|
-
export type Vec2 = {
|
|
9
|
-
x: number;
|
|
10
|
-
y: number;
|
|
11
|
-
};
|
|
12
|
-
export type Vec2Like = Vec2 | readonly [number, number];
|
|
13
|
-
/** Polyline vertex; bulge = tan(sweep/4), 0 = straight. Accepts [x, y, bulge?]. */
|
|
14
|
-
export type PolylineVertexLike = {
|
|
15
|
-
x: number;
|
|
16
|
-
y: number;
|
|
17
|
-
bulge?: number;
|
|
18
|
-
} | readonly [number, number, number?];
|
|
19
|
-
/** Style overrides children may carry (otherwise inherited from the instance). */
|
|
20
|
-
export type BaseStyle = {
|
|
21
|
-
/** #rrggbb; absent = by layer. */
|
|
22
|
-
color?: string;
|
|
23
|
-
/** Line type; absent = by layer. */
|
|
24
|
-
lineType?: string;
|
|
25
|
-
/** Dash-pattern length multiplier; absent = 1. */
|
|
26
|
-
lineTypeScale?: number;
|
|
27
|
-
/** Line weight in mm; absent = by layer. */
|
|
28
|
-
lineWidth?: number;
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* T plus the shared style fields, FLATTENED (the homomorphic map forces the
|
|
32
|
-
* intersection to resolve): hovers then list every member inline instead of
|
|
33
|
-
* the opaque `BaseStyle & { … }` — the block editor has no expand-type
|
|
34
|
-
* affordance, so the alias display is all a script author gets.
|
|
35
|
-
*/
|
|
36
|
-
type Styled<T> = {
|
|
37
|
-
[K in keyof (T & BaseStyle)]: (T & BaseStyle)[K];
|
|
38
|
-
} & {};
|
|
39
|
-
export type Line = Styled<{
|
|
40
|
-
type: "line";
|
|
41
|
-
a: Vec2Like;
|
|
42
|
-
b: Vec2Like;
|
|
43
|
-
}>;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}>;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
scale?: number;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
type
|
|
197
|
-
type: "
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
*
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
type
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
*/
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
}
|
|
604
|
-
type
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
/**
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
/**
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
*/
|
|
742
|
-
|
|
743
|
-
/**
|
|
744
|
-
|
|
745
|
-
/**
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
/**
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
/**
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1
|
+
// GENERATED — do not edit. Typings for the virtual "lineadraw" and
|
|
2
|
+
// "lineadraw/helpers" modules block scripts import from, emitted from
|
|
3
|
+
// packages/core/src/blocks/{blockTypes,blockHelpers}.ts. Regenerate with:
|
|
4
|
+
// npm run gen:lineadraw-dts -w @lineadraw/core
|
|
5
|
+
|
|
6
|
+
declare module "lineadraw" {
|
|
7
|
+
/** A 2D point (mm, y-up). Point-valued fields also accept [x, y]. */
|
|
8
|
+
export type Vec2 = {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
};
|
|
12
|
+
export type Vec2Like = Vec2 | readonly [number, number];
|
|
13
|
+
/** Polyline vertex; bulge = tan(sweep/4), 0 = straight. Accepts [x, y, bulge?]. */
|
|
14
|
+
export type PolylineVertexLike = {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
bulge?: number;
|
|
18
|
+
} | readonly [number, number, number?];
|
|
19
|
+
/** Style overrides children may carry (otherwise inherited from the instance). */
|
|
20
|
+
export type BaseStyle = {
|
|
21
|
+
/** #rrggbb; absent = by layer. */
|
|
22
|
+
color?: string;
|
|
23
|
+
/** Line type; absent = by layer. */
|
|
24
|
+
lineType?: string;
|
|
25
|
+
/** Dash-pattern length multiplier; absent = 1. */
|
|
26
|
+
lineTypeScale?: number;
|
|
27
|
+
/** Line weight in mm; absent = by layer. */
|
|
28
|
+
lineWidth?: number;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* T plus the shared style fields, FLATTENED (the homomorphic map forces the
|
|
32
|
+
* intersection to resolve): hovers then list every member inline instead of
|
|
33
|
+
* the opaque `BaseStyle & { … }` — the block editor has no expand-type
|
|
34
|
+
* affordance, so the alias display is all a script author gets.
|
|
35
|
+
*/
|
|
36
|
+
type Styled<T> = {
|
|
37
|
+
[K in keyof (T & BaseStyle)]: (T & BaseStyle)[K];
|
|
38
|
+
} & {};
|
|
39
|
+
export type Line = Styled<{
|
|
40
|
+
type: "line";
|
|
41
|
+
a: Vec2Like;
|
|
42
|
+
b: Vec2Like;
|
|
43
|
+
}>;
|
|
44
|
+
/** A point: paints as a round dot whose diameter is the lineWidth. */
|
|
45
|
+
export type Point = Styled<{
|
|
46
|
+
type: "point";
|
|
47
|
+
p: Vec2Like;
|
|
48
|
+
}>;
|
|
49
|
+
export type Polyline = Styled<{
|
|
50
|
+
type: "polyline";
|
|
51
|
+
/** At least 2 vertices. */
|
|
52
|
+
points: readonly PolylineVertexLike[];
|
|
53
|
+
closed?: boolean;
|
|
54
|
+
}>;
|
|
55
|
+
export type Circle = Styled<{
|
|
56
|
+
type: "circle";
|
|
57
|
+
center: Vec2Like;
|
|
58
|
+
radius: number;
|
|
59
|
+
}>;
|
|
60
|
+
/** Runs CCW from startAngle to endAngle (radians; DXF ARC convention). */
|
|
61
|
+
export type Arc = Styled<{
|
|
62
|
+
type: "arc";
|
|
63
|
+
center: Vec2Like;
|
|
64
|
+
radius: number;
|
|
65
|
+
startAngle: number;
|
|
66
|
+
endAngle: number;
|
|
67
|
+
}>;
|
|
68
|
+
/** majorAxis = endpoint vector from center; ratio = minor/major in (0, 1]. */
|
|
69
|
+
export type Ellipse = Styled<{
|
|
70
|
+
type: "ellipse";
|
|
71
|
+
center: Vec2Like;
|
|
72
|
+
majorAxis: Vec2Like;
|
|
73
|
+
ratio: number;
|
|
74
|
+
startAngle?: number;
|
|
75
|
+
endAngle?: number;
|
|
76
|
+
}>;
|
|
77
|
+
export type Hatch = Styled<{
|
|
78
|
+
type: "hatch";
|
|
79
|
+
/** loops[0] = outer boundary, the rest are holes (even-odd). */
|
|
80
|
+
loops: readonly {
|
|
81
|
+
points: readonly PolylineVertexLike[];
|
|
82
|
+
}[];
|
|
83
|
+
fill?: {
|
|
84
|
+
kind: "solid";
|
|
85
|
+
} | {
|
|
86
|
+
kind: "lines";
|
|
87
|
+
angle: number;
|
|
88
|
+
spacing: number;
|
|
89
|
+
};
|
|
90
|
+
/** Pattern spacing multiplier. */
|
|
91
|
+
scale?: number;
|
|
92
|
+
}>;
|
|
93
|
+
export type Text = Styled<{
|
|
94
|
+
type: "text";
|
|
95
|
+
position: Vec2Like;
|
|
96
|
+
content: string;
|
|
97
|
+
rotation?: number;
|
|
98
|
+
/** Where the text SITS relative to the point. */
|
|
99
|
+
hAlign?: "left" | "center" | "right";
|
|
100
|
+
vAlign?: "bottom" | "center" | "top";
|
|
101
|
+
/** Word-wrap / frame width in mm (before `scale`); absent = no wrapping. */
|
|
102
|
+
width?: number;
|
|
103
|
+
frame?: "none" | "rectangle" | "bottom";
|
|
104
|
+
/** MLEADER-style arrow polylines pointing at the text (arrowhead at [0]). */
|
|
105
|
+
leaderLines?: readonly (readonly Vec2Like[])[];
|
|
106
|
+
/** Style overrides; absent keys inherit the document text style. */
|
|
107
|
+
styleOverride?: {
|
|
108
|
+
font?: string;
|
|
109
|
+
widthFactor?: number;
|
|
110
|
+
/** Cap height in mm (before `scale`). */
|
|
111
|
+
textHeight?: number;
|
|
112
|
+
arrowSize?: number;
|
|
113
|
+
arrowType?: "filled" | "open" | "tick" | "dot" | "none";
|
|
114
|
+
};
|
|
115
|
+
/** Size multiplier for height + arrow size. */
|
|
116
|
+
scale?: number;
|
|
117
|
+
}>;
|
|
118
|
+
export type Dimension = Styled<{
|
|
119
|
+
type: "dimension";
|
|
120
|
+
kind?: "linear" | "angular" | "radial" | "diameter";
|
|
121
|
+
/** linear: 2+ chained points (measured point to point); angular: [vertex, a, b]; radial: [center, p]; diameter: [p1, p2]. */
|
|
122
|
+
points: readonly Vec2Like[];
|
|
123
|
+
/** Dimension line offset from the kind's anchor (points[0]; diameter: the
|
|
124
|
+
* points' midpoint). anchor + offset lies on the dimension line (angular:
|
|
125
|
+
* on the arc; radial/diameter: at the text). */
|
|
126
|
+
offset: Vec2Like;
|
|
127
|
+
textOverride?: string;
|
|
128
|
+
styleOverride?: {
|
|
129
|
+
textHeight?: number;
|
|
130
|
+
arrowSize?: number;
|
|
131
|
+
arrowType?: "filled" | "open" | "tick" | "dot" | "none";
|
|
132
|
+
/** "short" = a 2×overshoot tick across the dimension line. */
|
|
133
|
+
extensionType?: "long" | "short";
|
|
134
|
+
extensionOffset?: number;
|
|
135
|
+
extensionOvershoot?: number;
|
|
136
|
+
textOffset?: number;
|
|
137
|
+
precision?: number;
|
|
138
|
+
};
|
|
139
|
+
/** Annotation size multiplier (text/arrows/offsets). */
|
|
140
|
+
scale?: number;
|
|
141
|
+
}>;
|
|
142
|
+
/** Nested block instance (inputs may hold points, never object references). */
|
|
143
|
+
export type Block = Styled<{
|
|
144
|
+
type: "block";
|
|
145
|
+
definitionId: string;
|
|
146
|
+
/** Applied last, about the pivot (the first input point). */
|
|
147
|
+
rotation?: number;
|
|
148
|
+
scale?: number;
|
|
149
|
+
params?: Record<string, number | string | boolean>;
|
|
150
|
+
/** Input points in the PARENT's local coords; the first is the pivot. */
|
|
151
|
+
inputs?: readonly Vec2Like[];
|
|
152
|
+
}>;
|
|
153
|
+
export type ModelObject = Line | Point | Polyline | Circle | Arc | Ellipse | Hatch | Text | Dimension | Block;
|
|
154
|
+
/** Identity + shared style fields every stored object carries. */
|
|
155
|
+
export type StoredObjectBase = {
|
|
156
|
+
id: string;
|
|
157
|
+
layerId: string;
|
|
158
|
+
/** #rrggbb override; absent = by layer. */
|
|
159
|
+
color?: string;
|
|
160
|
+
lineType?: string;
|
|
161
|
+
lineTypeScale?: number;
|
|
162
|
+
lineWidth?: number;
|
|
163
|
+
/** Paint opacity 0..1; absent = opaque. */
|
|
164
|
+
opacity?: number;
|
|
165
|
+
};
|
|
166
|
+
/** Flattens base + per-type fields so hovers list every member inline
|
|
167
|
+
* (same trick as Styled<T> for the authoring DTOs). */
|
|
168
|
+
type StoredShape<T> = {
|
|
169
|
+
[K in keyof (T & StoredObjectBase)]: (T & StoredObjectBase)[K];
|
|
170
|
+
} & {};
|
|
171
|
+
/** Stored polyline vertex — bulge always present (default 0 applied). */
|
|
172
|
+
export type StoredPolylineVertex = {
|
|
173
|
+
x: number;
|
|
174
|
+
y: number;
|
|
175
|
+
bulge: number;
|
|
176
|
+
};
|
|
177
|
+
export type StoredLine = StoredShape<{
|
|
178
|
+
type: "line";
|
|
179
|
+
a: Vec2;
|
|
180
|
+
b: Vec2;
|
|
181
|
+
}>;
|
|
182
|
+
export type StoredPoint = StoredShape<{
|
|
183
|
+
type: "point";
|
|
184
|
+
p: Vec2;
|
|
185
|
+
}>;
|
|
186
|
+
export type StoredPolyline = StoredShape<{
|
|
187
|
+
type: "polyline";
|
|
188
|
+
points: readonly StoredPolylineVertex[];
|
|
189
|
+
closed: boolean;
|
|
190
|
+
}>;
|
|
191
|
+
export type StoredCircle = StoredShape<{
|
|
192
|
+
type: "circle";
|
|
193
|
+
center: Vec2;
|
|
194
|
+
radius: number;
|
|
195
|
+
}>;
|
|
196
|
+
export type StoredArc = StoredShape<{
|
|
197
|
+
type: "arc";
|
|
198
|
+
center: Vec2;
|
|
199
|
+
radius: number;
|
|
200
|
+
startAngle: number;
|
|
201
|
+
endAngle: number;
|
|
202
|
+
}>;
|
|
203
|
+
export type StoredEllipse = StoredShape<{
|
|
204
|
+
type: "ellipse";
|
|
205
|
+
center: Vec2;
|
|
206
|
+
majorAxis: Vec2;
|
|
207
|
+
ratio: number;
|
|
208
|
+
startAngle: number;
|
|
209
|
+
endAngle: number;
|
|
210
|
+
}>;
|
|
211
|
+
export type StoredHatchFill = {
|
|
212
|
+
kind: "solid";
|
|
213
|
+
} | {
|
|
214
|
+
kind: "pattern";
|
|
215
|
+
name: string;
|
|
216
|
+
angle: number;
|
|
217
|
+
scale: number;
|
|
218
|
+
} | {
|
|
219
|
+
kind: "lines";
|
|
220
|
+
angle: number;
|
|
221
|
+
spacing: number;
|
|
222
|
+
};
|
|
223
|
+
export type StoredHatch = StoredShape<{
|
|
224
|
+
type: "hatch";
|
|
225
|
+
/** loops[0] = outer boundary, the rest are holes (even-odd). */
|
|
226
|
+
loops: readonly {
|
|
227
|
+
points: readonly StoredPolylineVertex[];
|
|
228
|
+
}[];
|
|
229
|
+
fill: StoredHatchFill;
|
|
230
|
+
scale: number;
|
|
231
|
+
}>;
|
|
232
|
+
export type StoredText = StoredShape<{
|
|
233
|
+
type: "text";
|
|
234
|
+
position: Vec2;
|
|
235
|
+
content: string;
|
|
236
|
+
leaderLines: readonly (readonly Vec2[])[];
|
|
237
|
+
/** Word-wrap / frame width in mm; absent = no wrapping. */
|
|
238
|
+
width?: number;
|
|
239
|
+
hAlign: "left" | "center" | "right";
|
|
240
|
+
vAlign: "bottom" | "center" | "top";
|
|
241
|
+
frame?: "none" | "rectangle" | "bottom";
|
|
242
|
+
styleId?: string;
|
|
243
|
+
/** Only the keys the user actually overrode on this text. */
|
|
244
|
+
styleOverride?: {
|
|
245
|
+
font?: string;
|
|
246
|
+
widthFactor?: number;
|
|
247
|
+
textHeight?: number;
|
|
248
|
+
arrowType?: "filled" | "open" | "tick" | "dot" | "none";
|
|
249
|
+
arrowSize?: number;
|
|
250
|
+
};
|
|
251
|
+
rotation: number;
|
|
252
|
+
scale: number;
|
|
253
|
+
}>;
|
|
254
|
+
export type StoredDimension = StoredShape<{
|
|
255
|
+
type: "dimension";
|
|
256
|
+
kind: "linear" | "angular" | "radial" | "diameter";
|
|
257
|
+
points: readonly Vec2[];
|
|
258
|
+
offset: Vec2;
|
|
259
|
+
textOverride?: string;
|
|
260
|
+
styleId?: string;
|
|
261
|
+
/** Only the keys the user actually overrode on this dimension. */
|
|
262
|
+
styleOverride?: {
|
|
263
|
+
font?: string;
|
|
264
|
+
widthFactor?: number;
|
|
265
|
+
textHeight?: number;
|
|
266
|
+
textOffset?: number;
|
|
267
|
+
arrowType?: "filled" | "open" | "tick" | "dot" | "none";
|
|
268
|
+
arrowSize?: number;
|
|
269
|
+
extensionType?: "long" | "short";
|
|
270
|
+
extensionOffset?: number;
|
|
271
|
+
extensionOvershoot?: number;
|
|
272
|
+
precision?: number;
|
|
273
|
+
};
|
|
274
|
+
scale: number;
|
|
275
|
+
}>;
|
|
276
|
+
export type StoredBlock = StoredShape<{
|
|
277
|
+
type: "block";
|
|
278
|
+
definitionId: string;
|
|
279
|
+
rotation: number;
|
|
280
|
+
scale: number;
|
|
281
|
+
params: Readonly<Record<string, number | string | boolean>>;
|
|
282
|
+
/** World points and/or referenced object ids, in pick order. */
|
|
283
|
+
inputs: readonly (Vec2 | string)[];
|
|
284
|
+
}>;
|
|
285
|
+
/** Paper-space window into model space; exists only in layout spaces. */
|
|
286
|
+
export type StoredViewport = StoredShape<{
|
|
287
|
+
type: "viewport";
|
|
288
|
+
rect: {
|
|
289
|
+
x: number;
|
|
290
|
+
y: number;
|
|
291
|
+
w: number;
|
|
292
|
+
h: number;
|
|
293
|
+
};
|
|
294
|
+
modelCenter: Vec2;
|
|
295
|
+
/** Drawing-scale denominator (model mm per paper mm); 1:50 => 50. */
|
|
296
|
+
scale: number;
|
|
297
|
+
locked: boolean;
|
|
298
|
+
hiddenLayerIds: readonly string[];
|
|
299
|
+
}>;
|
|
300
|
+
/** Raster reference; pixels live in the document's assets map. */
|
|
301
|
+
export type StoredImage = StoredShape<{
|
|
302
|
+
type: "image";
|
|
303
|
+
assetId: string;
|
|
304
|
+
origin: Vec2;
|
|
305
|
+
width: number;
|
|
306
|
+
height: number;
|
|
307
|
+
rotation: number;
|
|
308
|
+
}>;
|
|
309
|
+
/** Any object as stored in the document — what reads hand to scripts. */
|
|
310
|
+
export type StoredObject = StoredLine | StoredPoint | StoredPolyline | StoredCircle | StoredArc | StoredEllipse | StoredHatch | StoredText | StoredDimension | StoredBlock | StoredViewport | StoredImage;
|
|
311
|
+
/**
|
|
312
|
+
* One choice of a "Select" parameter: the value (what scripts receive) with
|
|
313
|
+
* an optional properties-panel label. A plain string is shorthand for
|
|
314
|
+
* `{ value }`.
|
|
315
|
+
*/
|
|
316
|
+
export type ParameterOption = string | {
|
|
317
|
+
value: string;
|
|
318
|
+
label?: string;
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* One entry of the module's optional `params` export — the block's
|
|
322
|
+
* parameters table. `name` is the key scripts read from `params`, `label`
|
|
323
|
+
* the properties-panel caption (defaults to the name).
|
|
324
|
+
*/
|
|
325
|
+
export type ParamDef = {
|
|
326
|
+
name: string;
|
|
327
|
+
label?: string;
|
|
328
|
+
type: "number";
|
|
329
|
+
default: number;
|
|
330
|
+
min?: number;
|
|
331
|
+
max?: number;
|
|
332
|
+
} | {
|
|
333
|
+
name: string;
|
|
334
|
+
label?: string;
|
|
335
|
+
type: "string";
|
|
336
|
+
default: string;
|
|
337
|
+
} | {
|
|
338
|
+
name: string;
|
|
339
|
+
label?: string;
|
|
340
|
+
type: "boolean";
|
|
341
|
+
default: boolean;
|
|
342
|
+
} | {
|
|
343
|
+
name: string;
|
|
344
|
+
label?: string;
|
|
345
|
+
type: "enum";
|
|
346
|
+
default: string;
|
|
347
|
+
options: readonly ParameterOption[];
|
|
348
|
+
};
|
|
349
|
+
/**
|
|
350
|
+
* The block's parameters table — what the `params` member of a BlockSpec
|
|
351
|
+
* declares (or its function form returns).
|
|
352
|
+
*/
|
|
353
|
+
export type BlockParamDefs = readonly ParamDef[];
|
|
354
|
+
/** What the script's `draw` export must return. */
|
|
355
|
+
export type BlockScriptResult = ModelObject[];
|
|
356
|
+
/** The value an enum option denotes (its string, or `value` of the record form). */
|
|
357
|
+
type OptionValue<O extends ParameterOption> = O extends string ? O : O extends {
|
|
358
|
+
value: infer V extends string;
|
|
359
|
+
} ? V : never;
|
|
360
|
+
/** The runtime value type of one `params` table entry. */
|
|
361
|
+
type ParamValue<Q extends ParamDef> = Q extends {
|
|
362
|
+
type: "enum";
|
|
363
|
+
} ? OptionValue<Q["options"][number]> : Q extends {
|
|
364
|
+
type: "number";
|
|
365
|
+
} ? number : Q extends {
|
|
366
|
+
type: "boolean";
|
|
367
|
+
} ? boolean : string;
|
|
368
|
+
/**
|
|
369
|
+
* The values record a params table produces: each entry's `name` maps to
|
|
370
|
+
* its runtime value type (number/string/boolean, or the enum's option
|
|
371
|
+
* union). This is what `draw`/`place`/`paramVisibility` receive as
|
|
372
|
+
* `params` — inside defineBlock the table type is inferred, so authors
|
|
373
|
+
* never spell this out. Unwraps the function form of `params`; a non-table
|
|
374
|
+
* type (an already-derived values record, or the open BlockParams default)
|
|
375
|
+
* passes through unchanged.
|
|
376
|
+
*/
|
|
377
|
+
export type ParamValues<P> = P extends () => infer R ? ParamValues<R> : P extends readonly (infer Q extends ParamDef)[] ? {
|
|
378
|
+
readonly [E in Q as E["name"]]: ParamValue<E>;
|
|
379
|
+
} : P;
|
|
380
|
+
|
|
381
|
+
// ——— Script contract ———
|
|
382
|
+
|
|
383
|
+
// #region BlockParams
|
|
384
|
+
/**
|
|
385
|
+
* The open fallback for a block's parameter values, by name. Inside
|
|
386
|
+
* defineBlock the precise per-parameter types are inferred from the
|
|
387
|
+
* `params` member, so this record is only what untyped contexts see.
|
|
388
|
+
*/
|
|
389
|
+
export interface BlockParams {
|
|
390
|
+
readonly [name: string]: string | number | boolean;
|
|
391
|
+
}
|
|
392
|
+
// #endregion BlockParams
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* The inputs `place` acquired at insertion, in pick order: points or
|
|
396
|
+
* object ids (what `pickObject` resolved). This is the STORED form —
|
|
397
|
+
* by the time they reach `draw`, ids have been resolved (see
|
|
398
|
+
* ResolvedInput).
|
|
399
|
+
*/
|
|
400
|
+
export type BlockInputs = readonly (Vec2 | string)[];
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* A referenced document object as `draw` receives it: the STORED record
|
|
404
|
+
* (schema output — defaults applied, points always {x, y}, id/layerId
|
|
405
|
+
* present; see StoredObject), localized against the instance pivot like
|
|
406
|
+
* every point input. Null when the reference no longer resolves (the
|
|
407
|
+
* object was deleted) — handle it or throw (a throw shows as the
|
|
408
|
+
* instance's evaluation error).
|
|
409
|
+
*/
|
|
410
|
+
export type ResolvedObject = StoredObject | null;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* How one stored input arrives at `draw`: points pass through
|
|
414
|
+
* (pivot-localized), object ids resolve to the referenced object (or
|
|
415
|
+
* null). Distributes over Vec2 | string for untyped positions.
|
|
416
|
+
*/
|
|
417
|
+
export type ResolvedInput<T> = T extends string
|
|
418
|
+
? ResolvedObject
|
|
419
|
+
: T extends Vec2
|
|
420
|
+
? T
|
|
421
|
+
: Vec2 | ResolvedObject;
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* ResolvedInput applied position-wise. Homomorphic over the bare type
|
|
425
|
+
* parameter ON PURPOSE — inlining `keyof Awaited<R>` into PlaceInputs
|
|
426
|
+
* would map over the array's methods too and destroy tuple-ness.
|
|
427
|
+
*/
|
|
428
|
+
export type ResolveInputs<T extends BlockInputs> = {
|
|
429
|
+
readonly [K in keyof T]: ResolvedInput<T[K]>;
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* The argument of an interactive `place` — runs once at insertion;
|
|
434
|
+
* await the pickers for whatever inputs the block needs and return them
|
|
435
|
+
* as an array (catch the pick rejection to end an open-ended collection
|
|
436
|
+
* when the user presses Escape). `params` holds the DEFAULT values (the
|
|
437
|
+
* instance doesn't exist yet).
|
|
438
|
+
*/
|
|
439
|
+
export interface PlaceProps<P = BlockParams> {
|
|
440
|
+
params: ParamValues<P>;
|
|
441
|
+
pickPoint: (label?: string) => Promise<Vec2>;
|
|
442
|
+
pickObject: (label?: string) => Promise<string>;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// ——— defineBlock ———
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* What the `place` member of a BlockSpec accepts: an array of point
|
|
449
|
+
* labels — the runtime picks one point per label, in order — or the same
|
|
450
|
+
* interactive function a module-level `place` export would be.
|
|
451
|
+
*/
|
|
452
|
+
export type PlaceSpec<P = BlockParams> =
|
|
453
|
+
| readonly string[]
|
|
454
|
+
| ((props: PlaceProps<P>) => BlockInputs | Promise<BlockInputs>);
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* The shape `previewInputs` must have for a given `place` member: a
|
|
458
|
+
* label-array place pins the exact tuple length; otherwise any inputs
|
|
459
|
+
* array. Points accept [x, y] tuples for authoring ergonomics.
|
|
460
|
+
*/
|
|
461
|
+
export type PreviewInputs<Pl> = Pl extends readonly string[]
|
|
462
|
+
? { readonly [K in keyof Pl]: Vec2Like }
|
|
463
|
+
: readonly (Vec2Like | string)[];
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* The inputs `draw` receives for a given `place` member: a label tuple
|
|
467
|
+
* maps to a Vec2 tuple of the same length, a function contributes its
|
|
468
|
+
* (awaited) return type with every position RESOLVED (string → the
|
|
469
|
+
* referenced object or null, see ResolvedInput), and an absent `place`
|
|
470
|
+
* is the single "Insertion point" pick. The undefined case is checked
|
|
471
|
+
* FIRST and non-distributively: without strictNullChecks (e.g. a lax
|
|
472
|
+
* host config), `undefined extends readonly string[]` is true and the
|
|
473
|
+
* homomorphic mapped type would collapse to `undefined`.
|
|
474
|
+
*/
|
|
475
|
+
export type PlaceInputs<Pl> = [Pl] extends [undefined]
|
|
476
|
+
? readonly [Vec2]
|
|
477
|
+
: Pl extends readonly string[]
|
|
478
|
+
? { readonly [K in keyof Pl]: Vec2 }
|
|
479
|
+
: Pl extends (...args: never) => infer R
|
|
480
|
+
? Awaited<R> extends BlockInputs
|
|
481
|
+
? ResolveInputs<Awaited<R>>
|
|
482
|
+
: readonly (Vec2 | ResolvedObject)[]
|
|
483
|
+
: readonly [Vec2];
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* One block as a single object: the same members the module-level
|
|
487
|
+
* exports declare, gathered so TypeScript infers ACROSS them — `params`
|
|
488
|
+
* types `draw`'s params, `place` types `draw`'s inputs — with no
|
|
489
|
+
* typeof / satisfies / as-const annotations. See defineBlock.
|
|
490
|
+
*/
|
|
491
|
+
export interface BlockSpec<
|
|
492
|
+
P extends BlockParamDefs = readonly [],
|
|
493
|
+
Pl extends PlaceSpec<P> | undefined = undefined,
|
|
494
|
+
> {
|
|
495
|
+
id: string;
|
|
496
|
+
name: string;
|
|
497
|
+
version?: string;
|
|
498
|
+
description?: string;
|
|
499
|
+
tags?: readonly string[];
|
|
500
|
+
authors?: readonly string[];
|
|
501
|
+
/**
|
|
502
|
+
* Ids of block definitions `draw` emits instances of (e.g.
|
|
503
|
+
* `["@lineadraw/axis"]`). Install, copy/paste, and export bundle the
|
|
504
|
+
* declared closure; the save-time dry run rejects emitted instances
|
|
505
|
+
* that are not declared here.
|
|
506
|
+
*/
|
|
507
|
+
dependencies?: readonly string[];
|
|
508
|
+
/** The parameter table, or a function returning it (data-at-end). */
|
|
509
|
+
params?: P | (() => P);
|
|
510
|
+
/**
|
|
511
|
+
* Per-parameter visibility from the current values — pure, re-run per
|
|
512
|
+
* properties-panel render. Names omitted stay visible; `false` hides
|
|
513
|
+
* the row (the hidden value is KEPT and still reaches `draw`).
|
|
514
|
+
*/
|
|
515
|
+
paramVisibility?: (props: {
|
|
516
|
+
params: ParamValues<P>;
|
|
517
|
+
}) => Partial<Record<keyof ParamValues<P> & string, boolean>>;
|
|
518
|
+
/** Point labels (fixed picks) or an interactive function (see PlaceSpec). */
|
|
519
|
+
place?: Pl;
|
|
520
|
+
/**
|
|
521
|
+
* Optional inputs used for the block's PREVIEW (panel/Library
|
|
522
|
+
* thumbnails, marketplace cards, save-time dry run) instead of the
|
|
523
|
+
* generic stand-in picks — curate them so the preview shows the block
|
|
524
|
+
* at its best. Same shape `place` produces; points accept [x, y];
|
|
525
|
+
* object-id strings resolve to a stand-in line in previews.
|
|
526
|
+
*/
|
|
527
|
+
previewInputs?: PreviewInputs<Pl>;
|
|
528
|
+
/**
|
|
529
|
+
* Children in block-LOCAL coordinates (pure, runs per evaluation).
|
|
530
|
+
* The first point input is the pivot; `inputs` arrive localized
|
|
531
|
+
* against it, and the instance's rotation/scale apply last, about it.
|
|
532
|
+
* Object picks arrive as the referenced object itself (pivot-local,
|
|
533
|
+
* re-evaluated whenever it changes) or null once deleted.
|
|
534
|
+
*/
|
|
535
|
+
draw: (props: {
|
|
536
|
+
params: ParamValues<P>;
|
|
537
|
+
inputs: PlaceInputs<Pl>;
|
|
538
|
+
}) => BlockScriptResult;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* The recommended way to author a block: one call, one object, full
|
|
543
|
+
* inference — no `typeof params`, no `satisfies`, no `as const`.
|
|
544
|
+
*
|
|
545
|
+
* import { defineBlock } from "lineadraw";
|
|
546
|
+
*
|
|
547
|
+
* export default defineBlock({
|
|
548
|
+
* id: "…",
|
|
549
|
+
* name: "Surface",
|
|
550
|
+
* params: [
|
|
551
|
+
* { name: "type", type: "enum", default: "rock", options: ["rock", "ground"] },
|
|
552
|
+
* ],
|
|
553
|
+
* place: ["Start point", "End point"],
|
|
554
|
+
* draw: ({ params, inputs: [start, end] }) => {
|
|
555
|
+
* params.type; // "rock" | "ground"
|
|
556
|
+
* return [{ type: "line", a: start, b: end }];
|
|
557
|
+
* },
|
|
558
|
+
* });
|
|
559
|
+
*
|
|
560
|
+
* At runtime defineBlock is the identity function. The module-level
|
|
561
|
+
* export form remains fully supported — a default-exported BlockSpec and
|
|
562
|
+
* plain named exports describe the same block.
|
|
563
|
+
*/
|
|
564
|
+
export function defineBlock<
|
|
565
|
+
const P extends BlockParamDefs = readonly [],
|
|
566
|
+
const L extends readonly string[] | undefined = undefined,
|
|
567
|
+
>(spec: BlockSpec<P, L>): BlockSpec<P, L>;
|
|
568
|
+
// Function-form place: the props type is concrete (from P) and only the
|
|
569
|
+
// RETURN is inferred — inferring a whole context-sensitive function into
|
|
570
|
+
// a type parameter would fall back to its default.
|
|
571
|
+
export function defineBlock<
|
|
572
|
+
const P extends BlockParamDefs = readonly [],
|
|
573
|
+
const R extends BlockInputs | Promise<BlockInputs> = BlockInputs,
|
|
574
|
+
>(
|
|
575
|
+
spec: BlockSpec<P, (props: PlaceProps<P>) => R>,
|
|
576
|
+
): BlockSpec<P, (props: PlaceProps<P>) => R>;
|
|
577
|
+
|
|
578
|
+
// ——— Commands (macro scripts) ———
|
|
579
|
+
|
|
580
|
+
/** An axis-aligned box in world mm. */
|
|
581
|
+
export type Box = { minX: number; minY: number; maxX: number; maxY: number };
|
|
582
|
+
|
|
583
|
+
/** Filters for CommandDocument.query — all present filters AND together. */
|
|
584
|
+
export interface ObjectQuery {
|
|
585
|
+
ids?: readonly string[];
|
|
586
|
+
type?: ModelObject["type"];
|
|
587
|
+
/** Layer name or id. */
|
|
588
|
+
layer?: string;
|
|
589
|
+
/** #rrggbb override (objects without one inherit from their layer). */
|
|
590
|
+
color?: string;
|
|
591
|
+
lineType?: string;
|
|
592
|
+
/** Substring match on text content. */
|
|
593
|
+
content?: string;
|
|
594
|
+
/** Bounds intersect this box. */
|
|
595
|
+
bbox?: Box;
|
|
596
|
+
/** Bounds entirely inside this box. */
|
|
597
|
+
inside?: Box;
|
|
598
|
+
/** Geometry within `tol` mm of `point`. */
|
|
599
|
+
near?: { point: Vec2Like; tol: number };
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/** A STORED object as query() returns it (see StoredObject — schema
|
|
603
|
+
* output: defaults applied, points always {x, y}, identity present). */
|
|
604
|
+
export type ExistingObject = StoredObject;
|
|
605
|
+
|
|
606
|
+
/** Per-object measurements; null where the type has no natural value. */
|
|
607
|
+
export type Measurement = {
|
|
608
|
+
bbox: Box | null;
|
|
609
|
+
length: number | null;
|
|
610
|
+
area: number | null;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* The document as command scripts see it — the same session surface the
|
|
615
|
+
* agent tools are written against. Angles are RADIANS, point-valued
|
|
616
|
+
* arguments accept {x, y} or [x, y], `layer` resolves by name or id.
|
|
617
|
+
* Object mutations target the ACTIVE space. Methods throw on invalid
|
|
618
|
+
* input (an uncaught throw cancels the command and rolls its edits back).
|
|
619
|
+
*/
|
|
620
|
+
export interface CommandDocument {
|
|
621
|
+
/** Add objects (each may carry `layer` — a name — instead of an id);
|
|
622
|
+
* returns the created ids. */
|
|
623
|
+
add(
|
|
624
|
+
objects: readonly (ModelObject & { layer?: string })[],
|
|
625
|
+
opts?: { layout?: string },
|
|
626
|
+
): string[];
|
|
627
|
+
/** Apply per-object patches (`{ id, ...changedFields }`). */
|
|
628
|
+
update(entries: readonly ({ id: string } & Record<string, unknown>)[]): void;
|
|
629
|
+
/** Delete by id (unknown ids are skipped); returns how many went. */
|
|
630
|
+
remove(ids: readonly string[]): number;
|
|
631
|
+
move(ids: readonly string[], delta: Vec2Like): void;
|
|
632
|
+
rotate(ids: readonly string[], angleRad: number, center?: Vec2Like): void;
|
|
633
|
+
scale(ids: readonly string[], factor: number, center?: Vec2Like): void;
|
|
634
|
+
mirror(ids: readonly string[], axisA: Vec2Like, axisB: Vec2Like): void;
|
|
635
|
+
/** Duplicate displaced by delta; returns the new ids. */
|
|
636
|
+
copy(ids: readonly string[], delta: Vec2Like): string[];
|
|
637
|
+
/** count TOTAL copies at multiples of delta; returns the new ids. */
|
|
638
|
+
array(ids: readonly string[], count: number, delta: Vec2Like): string[];
|
|
639
|
+
/** Filtered MODEL-space objects. */
|
|
640
|
+
query(filter: ObjectQuery): ExistingObject[];
|
|
641
|
+
/** bbox / curve length / enclosed area of one object. */
|
|
642
|
+
measure(id: string): Measurement;
|
|
643
|
+
listLayers(): {
|
|
644
|
+
id: string;
|
|
645
|
+
name: string;
|
|
646
|
+
current: boolean;
|
|
647
|
+
[key: string]: unknown;
|
|
648
|
+
}[];
|
|
649
|
+
/** Create a layer (unique name); returns its id. */
|
|
650
|
+
addLayer(
|
|
651
|
+
props: { name: string; color?: string } & Record<string, unknown>,
|
|
652
|
+
): string;
|
|
653
|
+
updateLayer(nameOrId: string, patch: Record<string, unknown>): void;
|
|
654
|
+
/** Remove an EMPTY, non-current layer. */
|
|
655
|
+
removeLayer(nameOrId: string): void;
|
|
656
|
+
setCurrentLayer(nameOrId: string): void;
|
|
657
|
+
/** Create a paper layout; returns its id. `scale` accepts "1:50". */
|
|
658
|
+
createLayout(
|
|
659
|
+
name: string,
|
|
660
|
+
opts: {
|
|
661
|
+
sheet?: "A4" | "A3" | "A2" | "A1" | "A0" | { width: number; height: number };
|
|
662
|
+
orientation?: "portrait" | "landscape";
|
|
663
|
+
scale?: string;
|
|
664
|
+
},
|
|
665
|
+
): string;
|
|
666
|
+
/** Counts by type/layer, bbox, layer + layout names. */
|
|
667
|
+
summary(): Record<string, unknown>;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* What `run` receives. The pickers and `prompt` REJECT when the user
|
|
672
|
+
* cancels (Escape) — let that propagate to abort the command (all edits
|
|
673
|
+
* roll back), or catch it to finish an open-ended collection gracefully.
|
|
674
|
+
*/
|
|
675
|
+
export interface CommandContext {
|
|
676
|
+
document: CommandDocument;
|
|
677
|
+
/** Await one snapped world point. */
|
|
678
|
+
pickPoint(label?: string): Promise<Vec2>;
|
|
679
|
+
/** Await one object click; resolves the object's id. */
|
|
680
|
+
pickObject(label?: string): Promise<string>;
|
|
681
|
+
/** Ids currently selected — a snapshot; call again after changes. */
|
|
682
|
+
selection(): string[];
|
|
683
|
+
setSelection(ids: readonly string[]): void;
|
|
684
|
+
/** Await a typed value from a small input dialog. */
|
|
685
|
+
prompt(
|
|
686
|
+
message: string,
|
|
687
|
+
options?: { initial?: string; placeholder?: string },
|
|
688
|
+
): Promise<string>;
|
|
689
|
+
showToast(message: string, kind?: "info" | "success" | "error"): void;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/** One user command (macro): identity, metadata, and the `run` body. */
|
|
693
|
+
export interface CommandSpec {
|
|
694
|
+
id: string;
|
|
695
|
+
name: string;
|
|
696
|
+
description?: string;
|
|
697
|
+
version?: string;
|
|
698
|
+
authors?: readonly string[];
|
|
699
|
+
tags?: readonly string[];
|
|
700
|
+
/**
|
|
701
|
+
* The macro body. The whole call is ONE undo step: mutations apply
|
|
702
|
+
* live while it runs; cancelling (Escape during a pick/prompt) or an
|
|
703
|
+
* uncaught error rolls everything back.
|
|
704
|
+
*/
|
|
705
|
+
run(ctx: CommandContext): void | Promise<void>;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* The way to author a user command: one call, one object. At runtime
|
|
710
|
+
* defineCommand is the identity function.
|
|
711
|
+
*
|
|
712
|
+
* import { defineCommand } from "lineadraw";
|
|
713
|
+
*
|
|
714
|
+
* export default defineCommand({
|
|
715
|
+
* id: "…",
|
|
716
|
+
* name: "Number the selected texts",
|
|
717
|
+
* run: async ({ document, prompt, selection, showToast }) => {
|
|
718
|
+
* const start = Number(await prompt("First number", { initial: "1" }));
|
|
719
|
+
* const texts = document
|
|
720
|
+
* .query({ ids: selection(), type: "text" });
|
|
721
|
+
* texts.forEach((t, i) =>
|
|
722
|
+
* document.update([{ id: t.id, content: String(start + i) }]),
|
|
723
|
+
* );
|
|
724
|
+
* showToast(`Numbered ${texts.length} texts`, "success");
|
|
725
|
+
* },
|
|
726
|
+
* });
|
|
727
|
+
*/
|
|
728
|
+
export function defineCommand(spec: CommandSpec): CommandSpec;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
declare module "lineadraw/helpers" {
|
|
732
|
+
/** A 2D point (mm, y-up). A type ALIAS so editor hovers expand its shape. */
|
|
733
|
+
export type Vec2 = {
|
|
734
|
+
x: number;
|
|
735
|
+
y: number;
|
|
736
|
+
};
|
|
737
|
+
/** [0, 1, ..., n-1] — handy for repeating geometry. */
|
|
738
|
+
export const range: (n: number) => number[];
|
|
739
|
+
/** Point at `distance` from `p` in direction `angle` (radians, CCW). */
|
|
740
|
+
export const polar: (angle: number, distance: number, p?: Vec2) => Vec2;
|
|
741
|
+
/** Radians → degrees. */
|
|
742
|
+
export const toDeg: (r: number) => number;
|
|
743
|
+
/** Degrees → radians. */
|
|
744
|
+
export const toRad: (d: number) => number;
|
|
745
|
+
/** Length of a vector/point. */
|
|
746
|
+
export const len: (p: Vec2) => number;
|
|
747
|
+
/** Distance between two points. */
|
|
748
|
+
export const dist: (a: Vec2, b: Vec2) => number;
|
|
749
|
+
/** Vector/point sum. */
|
|
750
|
+
export const add: (a: Vec2, b: Vec2) => Vec2;
|
|
751
|
+
/** Vector/point difference (a − b). */
|
|
752
|
+
export const sub: (a: Vec2, b: Vec2) => Vec2;
|
|
753
|
+
/** Scale a vector by a factor. */
|
|
754
|
+
export const scale: (p: Vec2, s: number) => Vec2;
|
|
755
|
+
/** Unit vector (a zero vector stays zero). */
|
|
756
|
+
export const norm: (p: Vec2) => Vec2;
|
|
757
|
+
/** Dot product. */
|
|
758
|
+
export const dot: (a: Vec2, b: Vec2) => number;
|
|
759
|
+
/** Rotate vector by `angle` (radians, CCW). */
|
|
760
|
+
export const rotate: (p: Vec2, angle: number) => Vec2;
|
|
761
|
+
/**
|
|
762
|
+
* All helpers as one object — what migration-wrapped legacy scripts receive
|
|
763
|
+
* via `import { helpers } from "lineadraw"`. New scripts import the named
|
|
764
|
+
* functions from "lineadraw/helpers" instead.
|
|
765
|
+
*/
|
|
766
|
+
export const helpers: Readonly<{
|
|
767
|
+
range: (n: number) => number[];
|
|
768
|
+
polar: (angle: number, distance: number, p?: Vec2) => Vec2;
|
|
769
|
+
toDeg: (r: number) => number;
|
|
770
|
+
toRad: (d: number) => number;
|
|
771
|
+
len: (p: Vec2) => number;
|
|
772
|
+
dist: (a: Vec2, b: Vec2) => number;
|
|
773
|
+
add: (a: Vec2, b: Vec2) => Vec2;
|
|
774
|
+
sub: (a: Vec2, b: Vec2) => Vec2;
|
|
775
|
+
scale: (p: Vec2, s: number) => Vec2;
|
|
776
|
+
norm: (p: Vec2) => Vec2;
|
|
777
|
+
dot: (a: Vec2, b: Vec2) => number;
|
|
778
|
+
rotate: (p: Vec2, angle: number) => Vec2;
|
|
779
|
+
}>;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// The same declarations again at GLOBAL scope, so scripts can annotate
|
|
783
|
+
// without importing. Structurally identical to the "lineadraw" exports, so the
|
|
784
|
+
// two mix freely. Requires a DOM-less lib (blocks/tsconfig and the in-app
|
|
785
|
+
// editor both use lib es2022) — with lib.dom, `Text` would collide.
|
|
786
|
+
/** A 2D point (mm, y-up). Point-valued fields also accept [x, y]. */
|
|
787
|
+
type Vec2 = {
|
|
788
|
+
x: number;
|
|
789
|
+
y: number;
|
|
790
|
+
};
|
|
791
|
+
type Vec2Like = Vec2 | readonly [number, number];
|
|
792
|
+
/** Polyline vertex; bulge = tan(sweep/4), 0 = straight. Accepts [x, y, bulge?]. */
|
|
793
|
+
type PolylineVertexLike = {
|
|
794
|
+
x: number;
|
|
795
|
+
y: number;
|
|
796
|
+
bulge?: number;
|
|
797
|
+
} | readonly [number, number, number?];
|
|
798
|
+
/** Style overrides children may carry (otherwise inherited from the instance). */
|
|
799
|
+
type BaseStyle = {
|
|
800
|
+
/** #rrggbb; absent = by layer. */
|
|
801
|
+
color?: string;
|
|
802
|
+
/** Line type; absent = by layer. */
|
|
803
|
+
lineType?: string;
|
|
804
|
+
/** Dash-pattern length multiplier; absent = 1. */
|
|
805
|
+
lineTypeScale?: number;
|
|
806
|
+
/** Line weight in mm; absent = by layer. */
|
|
807
|
+
lineWidth?: number;
|
|
808
|
+
};
|
|
809
|
+
/**
|
|
810
|
+
* T plus the shared style fields, FLATTENED (the homomorphic map forces the
|
|
811
|
+
* intersection to resolve): hovers then list every member inline instead of
|
|
812
|
+
* the opaque `BaseStyle & { … }` — the block editor has no expand-type
|
|
813
|
+
* affordance, so the alias display is all a script author gets.
|
|
814
|
+
*/
|
|
815
|
+
type Styled<T> = {
|
|
816
|
+
[K in keyof (T & BaseStyle)]: (T & BaseStyle)[K];
|
|
817
|
+
} & {};
|
|
818
|
+
type Line = Styled<{
|
|
819
|
+
type: "line";
|
|
820
|
+
a: Vec2Like;
|
|
821
|
+
b: Vec2Like;
|
|
822
|
+
}>;
|
|
823
|
+
/** A point: paints as a round dot whose diameter is the lineWidth. */
|
|
824
|
+
type Point = Styled<{
|
|
825
|
+
type: "point";
|
|
826
|
+
p: Vec2Like;
|
|
827
|
+
}>;
|
|
828
|
+
type Polyline = Styled<{
|
|
829
|
+
type: "polyline";
|
|
830
|
+
/** At least 2 vertices. */
|
|
831
|
+
points: readonly PolylineVertexLike[];
|
|
832
|
+
closed?: boolean;
|
|
833
|
+
}>;
|
|
834
|
+
type Circle = Styled<{
|
|
835
|
+
type: "circle";
|
|
836
|
+
center: Vec2Like;
|
|
837
|
+
radius: number;
|
|
838
|
+
}>;
|
|
839
|
+
/** Runs CCW from startAngle to endAngle (radians; DXF ARC convention). */
|
|
840
|
+
type Arc = Styled<{
|
|
841
|
+
type: "arc";
|
|
842
|
+
center: Vec2Like;
|
|
843
|
+
radius: number;
|
|
844
|
+
startAngle: number;
|
|
845
|
+
endAngle: number;
|
|
846
|
+
}>;
|
|
847
|
+
/** majorAxis = endpoint vector from center; ratio = minor/major in (0, 1]. */
|
|
848
|
+
type Ellipse = Styled<{
|
|
849
|
+
type: "ellipse";
|
|
850
|
+
center: Vec2Like;
|
|
851
|
+
majorAxis: Vec2Like;
|
|
852
|
+
ratio: number;
|
|
853
|
+
startAngle?: number;
|
|
854
|
+
endAngle?: number;
|
|
855
|
+
}>;
|
|
856
|
+
type Hatch = Styled<{
|
|
857
|
+
type: "hatch";
|
|
858
|
+
/** loops[0] = outer boundary, the rest are holes (even-odd). */
|
|
859
|
+
loops: readonly {
|
|
860
|
+
points: readonly PolylineVertexLike[];
|
|
861
|
+
}[];
|
|
862
|
+
fill?: {
|
|
863
|
+
kind: "solid";
|
|
864
|
+
} | {
|
|
865
|
+
kind: "lines";
|
|
866
|
+
angle: number;
|
|
867
|
+
spacing: number;
|
|
868
|
+
};
|
|
869
|
+
/** Pattern spacing multiplier. */
|
|
870
|
+
scale?: number;
|
|
871
|
+
}>;
|
|
872
|
+
type Text = Styled<{
|
|
873
|
+
type: "text";
|
|
874
|
+
position: Vec2Like;
|
|
875
|
+
content: string;
|
|
876
|
+
rotation?: number;
|
|
877
|
+
/** Where the text SITS relative to the point. */
|
|
878
|
+
hAlign?: "left" | "center" | "right";
|
|
879
|
+
vAlign?: "bottom" | "center" | "top";
|
|
880
|
+
/** Word-wrap / frame width in mm (before `scale`); absent = no wrapping. */
|
|
881
|
+
width?: number;
|
|
882
|
+
frame?: "none" | "rectangle" | "bottom";
|
|
883
|
+
/** MLEADER-style arrow polylines pointing at the text (arrowhead at [0]). */
|
|
884
|
+
leaderLines?: readonly (readonly Vec2Like[])[];
|
|
885
|
+
/** Style overrides; absent keys inherit the document text style. */
|
|
886
|
+
styleOverride?: {
|
|
887
|
+
font?: string;
|
|
888
|
+
widthFactor?: number;
|
|
889
|
+
/** Cap height in mm (before `scale`). */
|
|
890
|
+
textHeight?: number;
|
|
891
|
+
arrowSize?: number;
|
|
892
|
+
arrowType?: "filled" | "open" | "tick" | "dot" | "none";
|
|
893
|
+
};
|
|
894
|
+
/** Size multiplier for height + arrow size. */
|
|
895
|
+
scale?: number;
|
|
896
|
+
}>;
|
|
897
|
+
type Dimension = Styled<{
|
|
898
|
+
type: "dimension";
|
|
899
|
+
kind?: "linear" | "angular" | "radial" | "diameter";
|
|
900
|
+
/** linear: 2+ chained points (measured point to point); angular: [vertex, a, b]; radial: [center, p]; diameter: [p1, p2]. */
|
|
901
|
+
points: readonly Vec2Like[];
|
|
902
|
+
/** Dimension line offset from the kind's anchor (points[0]; diameter: the
|
|
903
|
+
* points' midpoint). anchor + offset lies on the dimension line (angular:
|
|
904
|
+
* on the arc; radial/diameter: at the text). */
|
|
905
|
+
offset: Vec2Like;
|
|
906
|
+
textOverride?: string;
|
|
907
|
+
styleOverride?: {
|
|
908
|
+
textHeight?: number;
|
|
909
|
+
arrowSize?: number;
|
|
910
|
+
arrowType?: "filled" | "open" | "tick" | "dot" | "none";
|
|
911
|
+
/** "short" = a 2×overshoot tick across the dimension line. */
|
|
912
|
+
extensionType?: "long" | "short";
|
|
913
|
+
extensionOffset?: number;
|
|
914
|
+
extensionOvershoot?: number;
|
|
915
|
+
textOffset?: number;
|
|
916
|
+
precision?: number;
|
|
917
|
+
};
|
|
918
|
+
/** Annotation size multiplier (text/arrows/offsets). */
|
|
919
|
+
scale?: number;
|
|
920
|
+
}>;
|
|
921
|
+
/** Nested block instance (inputs may hold points, never object references). */
|
|
922
|
+
type Block = Styled<{
|
|
923
|
+
type: "block";
|
|
924
|
+
definitionId: string;
|
|
925
|
+
/** Applied last, about the pivot (the first input point). */
|
|
926
|
+
rotation?: number;
|
|
927
|
+
scale?: number;
|
|
928
|
+
params?: Record<string, number | string | boolean>;
|
|
929
|
+
/** Input points in the PARENT's local coords; the first is the pivot. */
|
|
930
|
+
inputs?: readonly Vec2Like[];
|
|
931
|
+
}>;
|
|
932
|
+
type ModelObject = Line | Point | Polyline | Circle | Arc | Ellipse | Hatch | Text | Dimension | Block;
|
|
933
|
+
/** Identity + shared style fields every stored object carries. */
|
|
934
|
+
type StoredObjectBase = {
|
|
935
|
+
id: string;
|
|
936
|
+
layerId: string;
|
|
937
|
+
/** #rrggbb override; absent = by layer. */
|
|
938
|
+
color?: string;
|
|
939
|
+
lineType?: string;
|
|
940
|
+
lineTypeScale?: number;
|
|
941
|
+
lineWidth?: number;
|
|
942
|
+
/** Paint opacity 0..1; absent = opaque. */
|
|
943
|
+
opacity?: number;
|
|
944
|
+
};
|
|
945
|
+
/** Flattens base + per-type fields so hovers list every member inline
|
|
946
|
+
* (same trick as Styled<T> for the authoring DTOs). */
|
|
947
|
+
type StoredShape<T> = {
|
|
948
|
+
[K in keyof (T & StoredObjectBase)]: (T & StoredObjectBase)[K];
|
|
949
|
+
} & {};
|
|
950
|
+
/** Stored polyline vertex — bulge always present (default 0 applied). */
|
|
951
|
+
type StoredPolylineVertex = {
|
|
952
|
+
x: number;
|
|
953
|
+
y: number;
|
|
954
|
+
bulge: number;
|
|
955
|
+
};
|
|
956
|
+
type StoredLine = StoredShape<{
|
|
957
|
+
type: "line";
|
|
958
|
+
a: Vec2;
|
|
959
|
+
b: Vec2;
|
|
960
|
+
}>;
|
|
961
|
+
type StoredPoint = StoredShape<{
|
|
962
|
+
type: "point";
|
|
963
|
+
p: Vec2;
|
|
964
|
+
}>;
|
|
965
|
+
type StoredPolyline = StoredShape<{
|
|
966
|
+
type: "polyline";
|
|
967
|
+
points: readonly StoredPolylineVertex[];
|
|
968
|
+
closed: boolean;
|
|
969
|
+
}>;
|
|
970
|
+
type StoredCircle = StoredShape<{
|
|
971
|
+
type: "circle";
|
|
972
|
+
center: Vec2;
|
|
973
|
+
radius: number;
|
|
974
|
+
}>;
|
|
975
|
+
type StoredArc = StoredShape<{
|
|
976
|
+
type: "arc";
|
|
977
|
+
center: Vec2;
|
|
978
|
+
radius: number;
|
|
979
|
+
startAngle: number;
|
|
980
|
+
endAngle: number;
|
|
981
|
+
}>;
|
|
982
|
+
type StoredEllipse = StoredShape<{
|
|
983
|
+
type: "ellipse";
|
|
984
|
+
center: Vec2;
|
|
985
|
+
majorAxis: Vec2;
|
|
986
|
+
ratio: number;
|
|
987
|
+
startAngle: number;
|
|
988
|
+
endAngle: number;
|
|
989
|
+
}>;
|
|
990
|
+
type StoredHatchFill = {
|
|
991
|
+
kind: "solid";
|
|
992
|
+
} | {
|
|
993
|
+
kind: "pattern";
|
|
994
|
+
name: string;
|
|
995
|
+
angle: number;
|
|
996
|
+
scale: number;
|
|
997
|
+
} | {
|
|
998
|
+
kind: "lines";
|
|
999
|
+
angle: number;
|
|
1000
|
+
spacing: number;
|
|
1001
|
+
};
|
|
1002
|
+
type StoredHatch = StoredShape<{
|
|
1003
|
+
type: "hatch";
|
|
1004
|
+
/** loops[0] = outer boundary, the rest are holes (even-odd). */
|
|
1005
|
+
loops: readonly {
|
|
1006
|
+
points: readonly StoredPolylineVertex[];
|
|
1007
|
+
}[];
|
|
1008
|
+
fill: StoredHatchFill;
|
|
1009
|
+
scale: number;
|
|
1010
|
+
}>;
|
|
1011
|
+
type StoredText = StoredShape<{
|
|
1012
|
+
type: "text";
|
|
1013
|
+
position: Vec2;
|
|
1014
|
+
content: string;
|
|
1015
|
+
leaderLines: readonly (readonly Vec2[])[];
|
|
1016
|
+
/** Word-wrap / frame width in mm; absent = no wrapping. */
|
|
1017
|
+
width?: number;
|
|
1018
|
+
hAlign: "left" | "center" | "right";
|
|
1019
|
+
vAlign: "bottom" | "center" | "top";
|
|
1020
|
+
frame?: "none" | "rectangle" | "bottom";
|
|
1021
|
+
styleId?: string;
|
|
1022
|
+
/** Only the keys the user actually overrode on this text. */
|
|
1023
|
+
styleOverride?: {
|
|
1024
|
+
font?: string;
|
|
1025
|
+
widthFactor?: number;
|
|
1026
|
+
textHeight?: number;
|
|
1027
|
+
arrowType?: "filled" | "open" | "tick" | "dot" | "none";
|
|
1028
|
+
arrowSize?: number;
|
|
1029
|
+
};
|
|
1030
|
+
rotation: number;
|
|
1031
|
+
scale: number;
|
|
1032
|
+
}>;
|
|
1033
|
+
type StoredDimension = StoredShape<{
|
|
1034
|
+
type: "dimension";
|
|
1035
|
+
kind: "linear" | "angular" | "radial" | "diameter";
|
|
1036
|
+
points: readonly Vec2[];
|
|
1037
|
+
offset: Vec2;
|
|
1038
|
+
textOverride?: string;
|
|
1039
|
+
styleId?: string;
|
|
1040
|
+
/** Only the keys the user actually overrode on this dimension. */
|
|
1041
|
+
styleOverride?: {
|
|
1042
|
+
font?: string;
|
|
1043
|
+
widthFactor?: number;
|
|
1044
|
+
textHeight?: number;
|
|
1045
|
+
textOffset?: number;
|
|
1046
|
+
arrowType?: "filled" | "open" | "tick" | "dot" | "none";
|
|
1047
|
+
arrowSize?: number;
|
|
1048
|
+
extensionType?: "long" | "short";
|
|
1049
|
+
extensionOffset?: number;
|
|
1050
|
+
extensionOvershoot?: number;
|
|
1051
|
+
precision?: number;
|
|
1052
|
+
};
|
|
1053
|
+
scale: number;
|
|
1054
|
+
}>;
|
|
1055
|
+
type StoredBlock = StoredShape<{
|
|
1056
|
+
type: "block";
|
|
1057
|
+
definitionId: string;
|
|
1058
|
+
rotation: number;
|
|
1059
|
+
scale: number;
|
|
1060
|
+
params: Readonly<Record<string, number | string | boolean>>;
|
|
1061
|
+
/** World points and/or referenced object ids, in pick order. */
|
|
1062
|
+
inputs: readonly (Vec2 | string)[];
|
|
1063
|
+
}>;
|
|
1064
|
+
/** Paper-space window into model space; exists only in layout spaces. */
|
|
1065
|
+
type StoredViewport = StoredShape<{
|
|
1066
|
+
type: "viewport";
|
|
1067
|
+
rect: {
|
|
1068
|
+
x: number;
|
|
1069
|
+
y: number;
|
|
1070
|
+
w: number;
|
|
1071
|
+
h: number;
|
|
1072
|
+
};
|
|
1073
|
+
modelCenter: Vec2;
|
|
1074
|
+
/** Drawing-scale denominator (model mm per paper mm); 1:50 => 50. */
|
|
1075
|
+
scale: number;
|
|
1076
|
+
locked: boolean;
|
|
1077
|
+
hiddenLayerIds: readonly string[];
|
|
1078
|
+
}>;
|
|
1079
|
+
/** Raster reference; pixels live in the document's assets map. */
|
|
1080
|
+
type StoredImage = StoredShape<{
|
|
1081
|
+
type: "image";
|
|
1082
|
+
assetId: string;
|
|
1083
|
+
origin: Vec2;
|
|
1084
|
+
width: number;
|
|
1085
|
+
height: number;
|
|
1086
|
+
rotation: number;
|
|
1087
|
+
}>;
|
|
1088
|
+
/** Any object as stored in the document — what reads hand to scripts. */
|
|
1089
|
+
type StoredObject = StoredLine | StoredPoint | StoredPolyline | StoredCircle | StoredArc | StoredEllipse | StoredHatch | StoredText | StoredDimension | StoredBlock | StoredViewport | StoredImage;
|
|
1090
|
+
/**
|
|
1091
|
+
* One choice of a "Select" parameter: the value (what scripts receive) with
|
|
1092
|
+
* an optional properties-panel label. A plain string is shorthand for
|
|
1093
|
+
* `{ value }`.
|
|
1094
|
+
*/
|
|
1095
|
+
type ParameterOption = string | {
|
|
1096
|
+
value: string;
|
|
1097
|
+
label?: string;
|
|
1098
|
+
};
|
|
1099
|
+
/**
|
|
1100
|
+
* One entry of the module's optional `params` export — the block's
|
|
1101
|
+
* parameters table. `name` is the key scripts read from `params`, `label`
|
|
1102
|
+
* the properties-panel caption (defaults to the name).
|
|
1103
|
+
*/
|
|
1104
|
+
type ParamDef = {
|
|
1105
|
+
name: string;
|
|
1106
|
+
label?: string;
|
|
1107
|
+
type: "number";
|
|
1108
|
+
default: number;
|
|
1109
|
+
min?: number;
|
|
1110
|
+
max?: number;
|
|
1111
|
+
} | {
|
|
1112
|
+
name: string;
|
|
1113
|
+
label?: string;
|
|
1114
|
+
type: "string";
|
|
1115
|
+
default: string;
|
|
1116
|
+
} | {
|
|
1117
|
+
name: string;
|
|
1118
|
+
label?: string;
|
|
1119
|
+
type: "boolean";
|
|
1120
|
+
default: boolean;
|
|
1121
|
+
} | {
|
|
1122
|
+
name: string;
|
|
1123
|
+
label?: string;
|
|
1124
|
+
type: "enum";
|
|
1125
|
+
default: string;
|
|
1126
|
+
options: readonly ParameterOption[];
|
|
1127
|
+
};
|
|
1128
|
+
/**
|
|
1129
|
+
* The block's parameters table — what the `params` member of a BlockSpec
|
|
1130
|
+
* declares (or its function form returns).
|
|
1131
|
+
*/
|
|
1132
|
+
type BlockParamDefs = readonly ParamDef[];
|
|
1133
|
+
/** What the script's `draw` export must return. */
|
|
1134
|
+
type BlockScriptResult = ModelObject[];
|
|
1135
|
+
/** The value an enum option denotes (its string, or `value` of the record form). */
|
|
1136
|
+
type OptionValue<O extends ParameterOption> = O extends string ? O : O extends {
|
|
1137
|
+
value: infer V extends string;
|
|
1138
|
+
} ? V : never;
|
|
1139
|
+
/** The runtime value type of one `params` table entry. */
|
|
1140
|
+
type ParamValue<Q extends ParamDef> = Q extends {
|
|
1141
|
+
type: "enum";
|
|
1142
|
+
} ? OptionValue<Q["options"][number]> : Q extends {
|
|
1143
|
+
type: "number";
|
|
1144
|
+
} ? number : Q extends {
|
|
1145
|
+
type: "boolean";
|
|
1146
|
+
} ? boolean : string;
|
|
1147
|
+
/**
|
|
1148
|
+
* The values record a params table produces: each entry's `name` maps to
|
|
1149
|
+
* its runtime value type (number/string/boolean, or the enum's option
|
|
1150
|
+
* union). This is what `draw`/`place`/`paramVisibility` receive as
|
|
1151
|
+
* `params` — inside defineBlock the table type is inferred, so authors
|
|
1152
|
+
* never spell this out. Unwraps the function form of `params`; a non-table
|
|
1153
|
+
* type (an already-derived values record, or the open BlockParams default)
|
|
1154
|
+
* passes through unchanged.
|
|
1155
|
+
*/
|
|
1156
|
+
type ParamValues<P> = P extends () => infer R ? ParamValues<R> : P extends readonly (infer Q extends ParamDef)[] ? {
|
|
1157
|
+
readonly [E in Q as E["name"]]: ParamValue<E>;
|
|
1158
|
+
} : P;
|
|
1159
|
+
|
|
1160
|
+
// Script-contract globals: aliases into the module (not re-declarations),
|
|
1161
|
+
// so the in-app editor's BlockParams substitution flows through them.
|
|
1162
|
+
declare type BlockParams = import("lineadraw").BlockParams;
|
|
1163
|
+
declare type BlockInputs = import("lineadraw").BlockInputs;
|
|
1164
|
+
declare type ResolvedObject = import("lineadraw").ResolvedObject;
|
|
1165
|
+
declare type ResolvedInput<T> = import("lineadraw").ResolvedInput<T>;
|
|
1166
|
+
declare type PlaceProps<P = BlockParams> = import("lineadraw").PlaceProps<P>;
|
|
1167
|
+
declare type PlaceSpec<P = BlockParams> = import("lineadraw").PlaceSpec<P>;
|
|
1168
|
+
declare type PlaceInputs<Pl> = import("lineadraw").PlaceInputs<Pl>;
|
|
1169
|
+
declare type PreviewInputs<Pl> = import("lineadraw").PreviewInputs<Pl>;
|
|
1170
|
+
declare type BlockSpec<
|
|
1171
|
+
P extends import("lineadraw").BlockParamDefs = readonly [],
|
|
1172
|
+
Pl extends PlaceSpec<P> | undefined = undefined,
|
|
1173
|
+
> = import("lineadraw").BlockSpec<P, Pl>;
|
|
1174
|
+
declare type Box = import("lineadraw").Box;
|
|
1175
|
+
declare type ObjectQuery = import("lineadraw").ObjectQuery;
|
|
1176
|
+
declare type ExistingObject = import("lineadraw").ExistingObject;
|
|
1177
|
+
declare type Measurement = import("lineadraw").Measurement;
|
|
1178
|
+
declare type CommandDocument = import("lineadraw").CommandDocument;
|
|
1179
|
+
declare type CommandContext = import("lineadraw").CommandContext;
|
|
1180
|
+
declare type CommandSpec = import("lineadraw").CommandSpec;
|