lineadraw 0.9.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/README.md +137 -14
- package/dist/{chunk-BQCSFVAF.js → chunk-YYJAXJOY.js} +4037 -1180
- package/dist/chunk-YYJAXJOY.js.map +1 -0
- package/dist/{exportDxf-T2RTSTH5.js → exportDxf-C4CLQCC3.js} +2 -2
- package/dist/sdk.d.ts +259 -42
- package/dist/sdk.js +127 -66
- package/dist/sdk.js.map +1 -1
- package/lineadraw.d.ts +505 -37
- package/package.json +2 -2
- package/templates/README.md +6 -4
- package/dist/chunk-BQCSFVAF.js.map +0 -1
- /package/dist/{exportDxf-T2RTSTH5.js.map → exportDxf-C4CLQCC3.js.map} +0 -0
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.
|
|
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" {
|
|
@@ -204,9 +205,12 @@ declare module "lineadraw" {
|
|
|
204
205
|
/** Applied last, about the pivot (the first input point). */
|
|
205
206
|
rotation?: number;
|
|
206
207
|
scale?: number;
|
|
207
|
-
params?: Record<string, number | string | boolean | readonly number[] | readonly string[]>;
|
|
208
|
-
/** Input points in the PARENT's local coords
|
|
209
|
-
|
|
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[]>>;
|
|
210
214
|
}>;
|
|
211
215
|
/** A table cell: plain text, or text with merge / alignment / style. */
|
|
212
216
|
export type TableCellInput = string | {
|
|
@@ -302,7 +306,7 @@ declare module "lineadraw" {
|
|
|
302
306
|
modelCenter?: Vec2Like;
|
|
303
307
|
/** Drawing-scale denominator (model mm per paper mm); 1:50 => 50. */
|
|
304
308
|
scale?: number;
|
|
305
|
-
/** Pinned: no pan/zoom-through, no move/resize
|
|
309
|
+
/** Pinned: no pan/zoom-through, no move/resize handles. */
|
|
306
310
|
locked?: boolean;
|
|
307
311
|
/** Layer ids hidden in this viewport only. */
|
|
308
312
|
hiddenLayerIds?: readonly string[];
|
|
@@ -448,9 +452,10 @@ declare module "lineadraw" {
|
|
|
448
452
|
definitionId: string;
|
|
449
453
|
rotation: number;
|
|
450
454
|
scale: number;
|
|
451
|
-
params: Readonly<Record<string, number | string | boolean | readonly number[] | readonly string[]>>;
|
|
452
|
-
/** World points and/or referenced object ids
|
|
453
|
-
|
|
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[]>>;
|
|
454
459
|
}>;
|
|
455
460
|
/** Paper-space window into model space; exists only in layout spaces. */
|
|
456
461
|
export type Viewport = ObjectShape<{
|
|
@@ -641,6 +646,12 @@ declare module "lineadraw" {
|
|
|
641
646
|
* value: it never appears in the `params` record `draw` receives.
|
|
642
647
|
* `name` stays the unique key (paramVisibility can hide it by name). */
|
|
643
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 & {
|
|
644
655
|
type: "label";
|
|
645
656
|
})
|
|
646
657
|
/** Layout only: 2–3 compact params on one panel row, each item's label a
|
|
@@ -711,12 +722,147 @@ declare module "lineadraw" {
|
|
|
711
722
|
* declares (or a block's function form returns).
|
|
712
723
|
*/
|
|
713
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).
|
|
805
|
+
*/
|
|
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[];
|
|
714
853
|
/** The value an enum option denotes (its string, or `value` of the record form). */
|
|
715
854
|
type OptionValue<O extends ParamOption> = O extends string ? O : O extends {
|
|
716
855
|
value: infer V extends string;
|
|
717
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
|
+
};
|
|
718
861
|
/** The runtime value type of one `params` table entry. */
|
|
719
862
|
type ParamValue<Q extends ParamDef> = Q extends {
|
|
863
|
+
type: "data";
|
|
864
|
+
default: infer D;
|
|
865
|
+
} ? D : Q extends {
|
|
720
866
|
type: "enum";
|
|
721
867
|
} ? OptionValue<Q["options"][number]> : Q extends {
|
|
722
868
|
type: "number";
|
|
@@ -889,6 +1035,9 @@ declare module "lineadraw" {
|
|
|
889
1035
|
authors?: readonly string[];
|
|
890
1036
|
tags?: readonly string[];
|
|
891
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;
|
|
892
1041
|
};
|
|
893
1042
|
/** A command module's identity/metadata (from its exports). */
|
|
894
1043
|
export type CommandInfo = {
|
|
@@ -898,8 +1047,11 @@ declare module "lineadraw" {
|
|
|
898
1047
|
version?: string;
|
|
899
1048
|
authors?: readonly string[];
|
|
900
1049
|
tags?: readonly string[];
|
|
901
|
-
/** Declared
|
|
902
|
-
|
|
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;
|
|
903
1055
|
/** Declared parameters (same table as a block's), prompted or supplied
|
|
904
1056
|
* before `run`. */
|
|
905
1057
|
params?: readonly ParamDef[];
|
|
@@ -1271,10 +1423,43 @@ declare module "lineadraw" {
|
|
|
1271
1423
|
label?: string;
|
|
1272
1424
|
referencePoint?: Vec2Like;
|
|
1273
1425
|
}): Promise<Vec2>;
|
|
1274
|
-
/** 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). */
|
|
1275
1428
|
pickObject(opts?: {
|
|
1276
1429
|
label?: string;
|
|
1430
|
+
types?: readonly ModelObject["type"][];
|
|
1277
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>>;
|
|
1278
1463
|
/** Await a typed value from a small input dialog. */
|
|
1279
1464
|
prompt(message: string, opts?: {
|
|
1280
1465
|
initial?: string;
|
|
@@ -1286,20 +1471,21 @@ declare module "lineadraw" {
|
|
|
1286
1471
|
/** Trigger a command by id — like the user pressing its hotkey. A macro
|
|
1287
1472
|
* takes its declared `inputs` / `params` up front (params passed skip its
|
|
1288
1473
|
* params dialog). */
|
|
1289
|
-
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>;
|
|
1290
1475
|
}
|
|
1291
1476
|
/**
|
|
1292
1477
|
* What `run` receives. `document` is the Drawing; `editor` the interactive
|
|
1293
|
-
* surface when there is one; `inputs`
|
|
1294
|
-
*
|
|
1295
|
-
* caller)
|
|
1296
|
-
*
|
|
1297
|
-
*
|
|
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).
|
|
1298
1484
|
*/
|
|
1299
|
-
export interface CommandContext<P = Readonly<Record<string, unknown
|
|
1485
|
+
export interface CommandContext<P = Readonly<Record<string, unknown>>, I = readonly Vec2[]> {
|
|
1300
1486
|
document: Drawing;
|
|
1301
1487
|
editor?: EditorSurface;
|
|
1302
|
-
inputs:
|
|
1488
|
+
inputs: I;
|
|
1303
1489
|
params: P;
|
|
1304
1490
|
}
|
|
1305
1491
|
|
|
@@ -1371,9 +1557,164 @@ declare module "lineadraw" {
|
|
|
1371
1557
|
export interface PlaceProps<P = BlockParams> {
|
|
1372
1558
|
params: ParamValues<P>;
|
|
1373
1559
|
pickPoint: (label?: string) => Promise<Vec2>;
|
|
1374
|
-
pickObject: (
|
|
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;
|
|
1375
1610
|
}
|
|
1376
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;
|
|
1634
|
+
}
|
|
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
|
+
|
|
1377
1718
|
// ——— defineBlock ———
|
|
1378
1719
|
|
|
1379
1720
|
/**
|
|
@@ -1423,6 +1764,7 @@ declare module "lineadraw" {
|
|
|
1423
1764
|
export interface BlockSpec<
|
|
1424
1765
|
P extends ParamDefs = readonly [],
|
|
1425
1766
|
Pl extends PlaceSpec<P> | undefined = undefined,
|
|
1767
|
+
I extends InputDefs | undefined = undefined,
|
|
1426
1768
|
> {
|
|
1427
1769
|
id: string;
|
|
1428
1770
|
name: string;
|
|
@@ -1447,16 +1789,58 @@ declare module "lineadraw" {
|
|
|
1447
1789
|
paramVisibility?: (props: {
|
|
1448
1790
|
params: ParamValues<P>;
|
|
1449
1791
|
}) => Partial<Record<keyof ParamValues<P> & string, boolean>>;
|
|
1450
|
-
/**
|
|
1451
|
-
|
|
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;
|
|
1452
1808
|
/**
|
|
1453
1809
|
* Optional inputs used for the block's PREVIEW (panel/Library
|
|
1454
1810
|
* thumbnails, marketplace cards, save-time dry run) instead of the
|
|
1455
1811
|
* generic stand-in picks — curate them so the preview shows the block
|
|
1456
|
-
* at its best. Same shape `place` produces
|
|
1457
|
-
* object-id strings resolve to
|
|
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.
|
|
1458
1815
|
*/
|
|
1459
|
-
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
|
+
>[];
|
|
1460
1844
|
/**
|
|
1461
1845
|
* Children in block-LOCAL coordinates (pure, runs per evaluation).
|
|
1462
1846
|
* The first point input is the pivot; `inputs` arrive localized
|
|
@@ -1466,12 +1850,51 @@ declare module "lineadraw" {
|
|
|
1466
1850
|
*/
|
|
1467
1851
|
draw: (props: {
|
|
1468
1852
|
params: ParamValues<P>;
|
|
1469
|
-
inputs: PlaceInputs<Pl>;
|
|
1853
|
+
inputs: [I] extends [InputDefs] ? DrawInputs<I> : PlaceInputs<Pl>;
|
|
1470
1854
|
/** The document's text / dimension styles by id — for blocks that
|
|
1471
1855
|
* lay out with real text sizes. Pass a picked id on to children as
|
|
1472
1856
|
* `styleId` to let them follow the style. */
|
|
1473
1857
|
styles: BlockStyles;
|
|
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[];
|
|
1474
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;
|
|
1475
1898
|
}
|
|
1476
1899
|
|
|
1477
1900
|
/**
|
|
@@ -1510,13 +1933,21 @@ declare module "lineadraw" {
|
|
|
1510
1933
|
>(
|
|
1511
1934
|
spec: BlockSpec<P, (props: PlaceProps<P>) => R>,
|
|
1512
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>;
|
|
1513
1941
|
|
|
1514
1942
|
// ——— Commands (macro scripts) ———
|
|
1515
1943
|
// Drawing / EditorSurface / CommandContext are emitted from scriptTypes.ts
|
|
1516
1944
|
// above (the script-facing mirror of core's real interfaces).
|
|
1517
1945
|
|
|
1518
1946
|
/** One user command (macro): identity, metadata, and the `run` body. */
|
|
1519
|
-
export interface CommandSpec<
|
|
1947
|
+
export interface CommandSpec<
|
|
1948
|
+
P extends ParamDefs = readonly [],
|
|
1949
|
+
I extends readonly string[] | CommandInputDefs = readonly [],
|
|
1950
|
+
> {
|
|
1520
1951
|
id: string;
|
|
1521
1952
|
name: string;
|
|
1522
1953
|
description?: string;
|
|
@@ -1524,13 +1955,24 @@ declare module "lineadraw" {
|
|
|
1524
1955
|
authors?: readonly string[];
|
|
1525
1956
|
tags?: readonly string[];
|
|
1526
1957
|
/**
|
|
1527
|
-
*
|
|
1528
|
-
*
|
|
1529
|
-
*
|
|
1530
|
-
*
|
|
1531
|
-
*
|
|
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.
|
|
1966
|
+
*/
|
|
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.
|
|
1532
1974
|
*/
|
|
1533
|
-
|
|
1975
|
+
requiresEditor?: boolean;
|
|
1534
1976
|
/**
|
|
1535
1977
|
* Parameters the command needs — the same table a block's `params`
|
|
1536
1978
|
* declares (number / string / boolean / enum / label rows), or a
|
|
@@ -1546,7 +1988,7 @@ declare module "lineadraw" {
|
|
|
1546
1988
|
* uncaught error rolls everything back. A return value is handed to
|
|
1547
1989
|
* the caller (the agent tool / CLI) — the editor ignores it.
|
|
1548
1990
|
*/
|
|
1549
|
-
run(ctx: CommandContext<ParamValues<P>>): unknown;
|
|
1991
|
+
run(ctx: CommandContext<ParamValues<P>, CommandInputs<I>>): unknown;
|
|
1550
1992
|
}
|
|
1551
1993
|
|
|
1552
1994
|
/**
|
|
@@ -1572,9 +2014,10 @@ declare module "lineadraw" {
|
|
|
1572
2014
|
* },
|
|
1573
2015
|
* });
|
|
1574
2016
|
*/
|
|
1575
|
-
export function defineCommand<
|
|
1576
|
-
|
|
1577
|
-
|
|
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>;
|
|
1578
2021
|
}
|
|
1579
2022
|
|
|
1580
2023
|
declare module "lineadraw/helpers" {
|
|
@@ -1607,4 +2050,29 @@ declare module "lineadraw/helpers" {
|
|
|
1607
2050
|
export const dot: (a: Vec2, b: Vec2) => number;
|
|
1608
2051
|
/** Rotate vector by `angle` (radians, CCW). */
|
|
1609
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
|
+
}[];
|
|
2066
|
+
/**
|
|
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.
|
|
2071
|
+
*/
|
|
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[];
|
|
1610
2078
|
}
|