@draftably/editor 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/assets/engine.worker-iJs-dOtM.js +8071 -0
  2. package/dist/element.js +27 -16
  3. package/dist/index.js +12154 -11312
  4. package/dist/types/src/components/scene/EdgeView.d.ts +2 -0
  5. package/dist/types/src/components/scene/Lifelines.d.ts +4 -3
  6. package/dist/types/src/components/session-context.d.ts +9 -2
  7. package/dist/types/src/dsl/compile.d.ts +2 -0
  8. package/dist/types/src/dsl/sequence-layout.d.ts +87 -0
  9. package/dist/types/src/dsl/source-edits.d.ts +2 -0
  10. package/dist/types/src/dsl/syntax.d.ts +8 -2
  11. package/dist/types/src/dsl/translate.d.ts +1 -1
  12. package/dist/types/src/editor/internal.d.ts +9 -2
  13. package/dist/types/src/editor/mount.d.ts +13 -6
  14. package/dist/types/src/engines/explorer-engine.d.ts +63 -0
  15. package/dist/types/src/engines/layout/arrange.d.ts +36 -0
  16. package/dist/types/src/engines/layout/compute.d.ts +7 -0
  17. package/dist/types/src/engines/layout/forces.d.ts +8 -0
  18. package/dist/types/src/engines/layout/grid.d.ts +10 -0
  19. package/dist/types/src/engines/layout/intent.d.ts +14 -0
  20. package/dist/types/src/engines/layout/layered.d.ts +5 -0
  21. package/dist/types/src/engines/layout/objective.d.ts +6 -0
  22. package/dist/types/src/engines/layout/packing.d.ts +7 -0
  23. package/dist/types/src/engines/layout/report.d.ts +7 -0
  24. package/dist/types/src/engines/layout/scene.d.ts +53 -0
  25. package/dist/types/src/engines/layout/seed.d.ts +3 -0
  26. package/dist/types/src/engines/layout/separation.d.ts +17 -0
  27. package/dist/types/src/engines/layout/settings.d.ts +6 -0
  28. package/dist/types/src/engines/layout/topology.d.ts +18 -0
  29. package/dist/types/src/engines/layout/trees.d.ts +8 -0
  30. package/dist/types/src/engines/layout/types.d.ts +133 -0
  31. package/dist/types/src/engines/layout/util.d.ts +19 -0
  32. package/dist/types/src/engines/layout-engine.d.ts +15 -0
  33. package/dist/types/src/engines/routing/compute.d.ts +6 -0
  34. package/dist/types/src/engines/routing/conflicts.d.ts +36 -0
  35. package/dist/types/src/engines/routing/context.d.ts +37 -0
  36. package/dist/types/src/engines/routing/cost.d.ts +13 -0
  37. package/dist/types/src/engines/routing/doglegs.d.ts +16 -0
  38. package/dist/types/src/engines/routing/find.d.ts +6 -0
  39. package/dist/types/src/engines/routing/geometry.d.ts +24 -0
  40. package/dist/types/src/engines/routing/heap.d.ts +20 -0
  41. package/dist/types/src/engines/routing/improve.d.ts +7 -0
  42. package/dist/types/src/engines/routing/nudge.d.ts +7 -0
  43. package/dist/types/src/engines/routing/paths.d.ts +8 -0
  44. package/dist/types/src/engines/routing/planned.d.ts +7 -0
  45. package/dist/types/src/engines/routing/ports.d.ts +10 -0
  46. package/dist/types/src/engines/routing/repair.d.ts +9 -0
  47. package/dist/types/src/engines/routing/score.d.ts +12 -0
  48. package/dist/types/src/engines/routing/search.d.ts +16 -0
  49. package/dist/types/src/engines/routing/settings.d.ts +4 -0
  50. package/dist/types/src/engines/routing/sidepairs.d.ts +20 -0
  51. package/dist/types/src/engines/routing/tidy-ports.d.ts +13 -0
  52. package/dist/types/src/engines/routing/tidy.d.ts +10 -0
  53. package/dist/types/src/engines/routing/tuning.d.ts +9 -0
  54. package/dist/types/src/engines/routing/types.d.ts +157 -0
  55. package/dist/types/src/engines/routing-engine.d.ts +20 -0
  56. package/dist/types/src/engines/sculpt-engine.d.ts +87 -0
  57. package/dist/types/src/lib/engine-tasks.d.ts +4 -4
  58. package/dist/types/src/model/appearance.d.ts +18 -2
  59. package/dist/types/src/model/edits.d.ts +19 -0
  60. package/dist/types/src/model/labels.d.ts +23 -0
  61. package/dist/types/src/model/markers.d.ts +7 -0
  62. package/dist/types/src/model/note.d.ts +11 -2
  63. package/dist/types/src/model/routes.d.ts +5 -3
  64. package/dist/types/src/model/status.d.ts +18 -0
  65. package/dist/types/src/model/types.d.ts +20 -1
  66. package/dist/types/src/runtime/color-scheme.d.ts +15 -0
  67. package/dist/types/src/runtime/host.d.ts +34 -2
  68. package/dist/types/src/runtime/page-shared.d.ts +1 -1
  69. package/dist/types/src/runtime/schemes.d.ts +2 -0
  70. package/dist/types/src/runtime/svg-renderer.d.ts +9 -4
  71. package/dist/types/src/runtime/types.d.ts +7 -0
  72. package/dist/types/src/state/active-session.d.ts +9 -2
  73. package/dist/types/src/state/canvas-commands.d.ts +37 -0
  74. package/dist/types/src/state/session/actions.d.ts +2 -0
  75. package/dist/types/src/state/session/emphasis.d.ts +3 -0
  76. package/dist/types/src/state/session/file-session.d.ts +1 -1
  77. package/dist/types/src/state/session/index.d.ts +14 -2
  78. package/dist/types/src/state/session/layout.d.ts +1 -1
  79. package/dist/types/src/state/session/scene.d.ts +11 -9
  80. package/dist/types/src/state/session/sculpt.d.ts +1 -1
  81. package/package.json +1 -1
  82. package/dist/assets/engine.worker-C6o2x40z.js +0 -7609
@@ -4,6 +4,8 @@ export interface EdgeViewProps {
4
4
  doc: Diagram;
5
5
  route: DrawnRoute;
6
6
  selected?: boolean;
7
+ /** In a sequence: the selected message answers this one, or this one answers it. */
8
+ paired?: boolean;
7
9
  interactive?: boolean;
8
10
  /** Its label is being edited in place, so the drawn label hides. */
9
11
  editing?: boolean;
@@ -6,10 +6,11 @@ export declare function Lifelines(props: {
6
6
  rect: (id: string) => NodeLayout | undefined;
7
7
  }): import("solid-js").JSX.Element;
8
8
  /**
9
- * A sequence diagram's panel (`part="panel"`, under the groups) or its phase bands
10
- * (`part="phases"`, over the groups' column bands), as the SVG export draws them.
9
+ * A sequence diagram's panel (`part="panel"`, under the groups), its phase bands
10
+ * (`part="phases"`, over the groups' column bands) or its activation bars (`part="bars"`, over
11
+ * the lifelines), as the SVG export draws them.
11
12
  */
12
13
  export declare function SequenceBackdrop(props: {
13
14
  doc: Diagram;
14
- part: 'panel' | 'phases';
15
+ part: 'panel' | 'phases' | 'bars';
15
16
  }): import("solid-js").JSX.Element;
@@ -213,6 +213,8 @@ export declare const useSessionIfAny: () => ({
213
213
  tail?: import("../model/markers").EndMarker;
214
214
  emphasis: boolean;
215
215
  dashed: boolean;
216
+ message?: import("../model/markers").MessageKind;
217
+ replyTo?: string;
216
218
  status?: import("../model/status").Status;
217
219
  spot?: import("../model/status").Spot;
218
220
  }[];
@@ -221,7 +223,7 @@ export declare const useSessionIfAny: () => ({
221
223
  routingReport: () => import("../engines/routing-engine").RoutingReport;
222
224
  blockedRouteIds: () => string[];
223
225
  sceneBounds: () => import("../model/types").Rect;
224
- viewerFrame: () => {
226
+ viewerFrame: import("solid-js").Accessor<{
225
227
  x: number;
226
228
  y: number;
227
229
  w: number;
@@ -265,7 +267,7 @@ export declare const useSessionIfAny: () => ({
265
267
  h: number;
266
268
  };
267
269
  notes: import("../model/note").PlacedNote[];
268
- };
270
+ }>;
269
271
  } & {
270
272
  states: () => import("../model/appearance").EmphasisState[];
271
273
  activeState: () => string | null;
@@ -274,6 +276,9 @@ export declare const useSessionIfAny: () => ({
274
276
  showState: (id: string | null) => void;
275
277
  stepState: (by: 1 | -1) => boolean;
276
278
  drawnDoc: () => import("../model/types").Diagram;
279
+ dark: import("solid-js").Accessor<boolean>;
280
+ setDark: import("solid-js").Setter<boolean>;
281
+ drawnAppearance: () => import("../model/appearance").DiagramAppearance;
277
282
  } & {
278
283
  tool: import("solid-js").Accessor<import("../state/session/editor").Tool>;
279
284
  setToolSignal: import("solid-js").Setter<import("../state/session/editor").Tool>;
@@ -400,6 +405,8 @@ export declare const useSessionIfAny: () => ({
400
405
  fitSelectedContainer: () => void;
401
406
  toggleCollapse: (id?: string | undefined) => void;
402
407
  reverseSelectedEdge: () => void;
408
+ insertEvent: (where: "before" | "after") => string | undefined;
409
+ moveEvent: (by: -1 | 1) => void;
403
410
  resetSelectedBends: () => void;
404
411
  setLayoutIntent: (role: import("../model/types").IntentRole, id: string | null, placement?: import("../model/types").IntentPlacement) => void;
405
412
  markSelectedAs: (role: import("../model/types").IntentRole) => void;
@@ -49,6 +49,8 @@ export interface SceneEdge extends ModelEdge {
49
49
  plan?: Planned;
50
50
  /** A sequence message: the height of its row; it is drawn straight between lifelines there. */
51
51
  row?: number;
52
+ /** A message between distant lanes: the middle of the gap its label sits in. */
53
+ labelX?: number;
52
54
  }
53
55
  export interface Scene {
54
56
  model: Model;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The arithmetic of a sequence diagram's layout, apart from the scene it is applied to: where a
3
+ * label that spans several lanes sits, where each lane stands, and how tall each phase is.
4
+ * `sequenced` in `compile.ts` measures the text and calls these.
5
+ */
6
+ /** A lower bound on a lane's centre: at least `room` past the centre of lane `from`. */
7
+ export type Hold = {
8
+ from: number;
9
+ room: number;
10
+ };
11
+ /**
12
+ * The gap a distant message's label sits in, so it crosses no lifeline between its two ends.
13
+ * `base` holds the lane centres that the headers alone give. The choice prefers a gap inside one
14
+ * band, so the label covers no band's border, then a gap that already has room, then the gap
15
+ * nearest the middle of the message, then the left one. Returns the left lane of the gap.
16
+ */
17
+ export declare function labelSlot(base: number[], a: number, b: number, room: number, across: (lane: number) => boolean): number;
18
+ /**
19
+ * Lane centres from left to right: each lane takes the header gap from its neighbour, or what
20
+ * holds it away from an earlier lane, if that is more.
21
+ */
22
+ export declare function laneCentres(first: number, gaps: number[], holds: Hold[][]): number[];
23
+ /** What one event draws round its row: how far above it and how far below. */
24
+ export type EventInk = {
25
+ id: string;
26
+ /** The phase that lists the event, if one does. */
27
+ phase?: string;
28
+ /** Height of the label above the line; 0 with no label or for a self-message. */
29
+ label: number;
30
+ /** Ink above and below the row. */
31
+ above: number;
32
+ below: number;
33
+ /** A self-message or a local action: the row after it must clear its ink. */
34
+ tall: boolean;
35
+ /** How far the event runs on down its lifeline, which the next row starts from. */
36
+ drop: number;
37
+ };
38
+ export type RowRules = {
39
+ /** Least distance between two rows. */
40
+ row: number;
41
+ /** Room between a tall event's ink and the next event's ink. */
42
+ clear: number;
43
+ /** Room between a phase band's edge and the ink inside it. */
44
+ pad: number;
45
+ /** Room between two phase bands. */
46
+ gap: number;
47
+ };
48
+ /**
49
+ * Rows from top to bottom, starting under the headers at `top`. A phase is one block: its band
50
+ * starts `gap` under what came before, holds its events with `pad` round them, and is at least
51
+ * as tall as its title needs. Events outside every phase keep the plain row rule.
52
+ */
53
+ export declare function eventRows(events: EventInk[], top: number, titleHeight: (phase: string) => number, rules: RowRules): {
54
+ rows: Map<string, number>;
55
+ bands: Map<string, {
56
+ y: number;
57
+ h: number;
58
+ }>;
59
+ end: number;
60
+ };
61
+ /** An event as activation bars read it: who sends to whom, its kind, and what it answers. */
62
+ export type SequenceEvent = {
63
+ id: string;
64
+ source: string;
65
+ target: string;
66
+ message?: string;
67
+ replyTo?: string;
68
+ };
69
+ /**
70
+ * A stretch in which a participant is at work on a call: from the event at index `start` to
71
+ * the one at `end`, or a short stub when `end` is unset. `level` is 0, or more when the
72
+ * participant took the call while another of its bars was open.
73
+ */
74
+ export type ActivationSpan = {
75
+ lane: string;
76
+ call: string;
77
+ start: number;
78
+ end?: number;
79
+ level: number;
80
+ };
81
+ /**
82
+ * The activation bars of a sequence, read from its calls and their replies. A bar opens where a
83
+ * participant receives a `call` from another and closes at the last reply that answers that
84
+ * call. A call with no reply closes at the participant's next message to another, and without
85
+ * one it is a stub. A call a participant sends to itself opens no bar.
86
+ */
87
+ export declare function activationSpans(events: SequenceEvent[]): ActivationSpan[];
@@ -8,6 +8,8 @@ export declare const statements: (doc: SourceDoc) => Statement[];
8
8
  export declare function statement(command: string, args: Word[], attrs?: Array<[string, Word]>): Statement;
9
9
  /** The `node` or `group` declaration of an object. */
10
10
  export declare const declaration: (doc: SourceDoc, id: string) => Statement | undefined;
11
+ /** A statement that makes a connection: an `edge`, or a sequence's `action`. */
12
+ export declare const isEdge: (s: Statement) => boolean;
11
13
  export declare const edgeStatement: (doc: SourceDoc, id: string) => Statement | undefined;
12
14
  export declare const layoutStatement: (doc: SourceDoc, scope: string) => Statement | undefined;
13
15
  export declare function getAttr(s: Statement, key: string): Word | undefined;
@@ -6,7 +6,7 @@
6
6
  * keeps every comment and unrelated statement.
7
7
  */
8
8
  import { type DiagramAppearance, type Shade } from '../model/appearance';
9
- import { type EndMarker } from '../model/markers';
9
+ import { type EndMarker, type MessageKind } from '../model/markers';
10
10
  import type { Status } from '../model/status';
11
11
  import type { ColorKey, LayoutAlgorithmId, LayoutSettings, PortSide, RoutingSettings, ShapeKind } from '../model/types';
12
12
  export declare class DslError extends Error {
@@ -131,9 +131,13 @@ export interface ModelEdge {
131
131
  tail?: EndMarker;
132
132
  /** `constraint=false`: drawn and routed, but layout doesn't rank or order by it. */
133
133
  constraint?: false;
134
+ /** Sequence diagrams: `message=`, or `action` for an `action` line. */
135
+ message?: MessageKind;
136
+ /** `answers=`: the earlier message a reply answers. */
137
+ replyTo?: string;
134
138
  line: number;
135
139
  }
136
- /** A layout engine run cold over a scope's subtree; see `src/engines/layout-engine.js`. */
140
+ /** A layout engine run cold over a scope's subtree; see `src/engines/layout-engine.ts`. */
137
141
  export interface EngineRecipe {
138
142
  algorithm: LayoutAlgorithmId;
139
143
  params: Partial<LayoutSettings>;
@@ -160,6 +164,8 @@ export interface ModelLayout {
160
164
  /** With `unit`: the width of one unit, and whether unit numbers run above the first row. */
161
165
  unitWidth?: number;
162
166
  ruler?: boolean;
167
+ /** `sequence` only: draw a bar on a participant's lifeline while it is at work on a call. */
168
+ activations?: true;
163
169
  /** `flow` only: whether a long run of ranks folds into bands. Engines take `fold` as a param. */
164
170
  fold: 'auto' | 'never';
165
171
  /** Root only: the image shape to aim for; compile tries direction and folding to get closest. */
@@ -7,7 +7,7 @@
7
7
  * write snaps back when the source is reprojected, so nothing unsaved looks saved. Changes the
8
8
  * file cannot express are rejected outright.
9
9
  */
10
- import type { DiagramAppearance } from '../model/appearance';
10
+ import { type DiagramAppearance } from '../model/appearance';
11
11
  import type { Diagram } from '../model/types';
12
12
  import { type Scene } from './compile';
13
13
  import { type SourceDoc } from './syntax';
@@ -207,6 +207,8 @@ export declare const sessions: WeakMap<object, {
207
207
  tail?: import("../model/markers").EndMarker;
208
208
  emphasis: boolean;
209
209
  dashed: boolean;
210
+ message?: import("../model/markers").MessageKind;
211
+ replyTo?: string;
210
212
  status?: import("../model/status").Status;
211
213
  spot?: import("../model/status").Spot;
212
214
  }[];
@@ -215,7 +217,7 @@ export declare const sessions: WeakMap<object, {
215
217
  routingReport: () => import("../engines/routing-engine").RoutingReport;
216
218
  blockedRouteIds: () => string[];
217
219
  sceneBounds: () => import("../model/types").Rect;
218
- viewerFrame: () => {
220
+ viewerFrame: import("solid-js").Accessor<{
219
221
  x: number;
220
222
  y: number;
221
223
  w: number;
@@ -259,7 +261,7 @@ export declare const sessions: WeakMap<object, {
259
261
  h: number;
260
262
  };
261
263
  notes: import("../model/note").PlacedNote[];
262
- };
264
+ }>;
263
265
  } & {
264
266
  states: () => import("../model/appearance").EmphasisState[];
265
267
  activeState: () => string | null;
@@ -268,6 +270,9 @@ export declare const sessions: WeakMap<object, {
268
270
  showState: (id: string | null) => void;
269
271
  stepState: (by: 1 | -1) => boolean;
270
272
  drawnDoc: () => import("../model/types").Diagram;
273
+ dark: import("solid-js").Accessor<boolean>;
274
+ setDark: import("solid-js").Setter<boolean>;
275
+ drawnAppearance: () => import("../model/appearance").DiagramAppearance;
271
276
  } & {
272
277
  tool: import("solid-js").Accessor<import("../state/session/editor").Tool>;
273
278
  setToolSignal: import("solid-js").Setter<import("../state/session/editor").Tool>;
@@ -394,6 +399,8 @@ export declare const sessions: WeakMap<object, {
394
399
  fitSelectedContainer: () => void;
395
400
  toggleCollapse: (id?: string | undefined) => void;
396
401
  reverseSelectedEdge: () => void;
402
+ insertEvent: (where: "before" | "after") => string | undefined;
403
+ moveEvent: (by: -1 | 1) => void;
397
404
  resetSelectedBends: () => void;
398
405
  setLayoutIntent: (role: import("../model/types").IntentRole, id: string | null, placement?: import("../model/types").IntentPlacement) => void;
399
406
  markSelectedAs: (role: import("../model/types").IntentRole) => void;
@@ -3,6 +3,7 @@ import { type Camera, type CameraReason, type FrameOptions, type MoveResult } fr
3
3
  import { type Geometry } from '../runtime/geometry';
4
4
  import { type Anchor, type DraftSlot } from '../runtime/anchors';
5
5
  import type { Diagnostic } from '../runtime/types';
6
+ import type { EditorUpdate } from '../runtime/host';
6
7
  import '../styles/app.css';
7
8
  /** The options a host sets on `<draft-editor>`: every mount option but the text and `onChange`. */
8
9
  export type EditorOptions = Pick<SessionOptions, 'storageKey' | 'openLink' | 'confirm' | 'onInteract'> & {
@@ -21,12 +22,21 @@ export interface EditorEvents {
21
22
  anchors: {
22
23
  anchors: readonly Anchor[];
23
24
  };
24
- /** Slot warnings: an unknown slot, or content larger than its node. */
25
+ /** A source that does not parse (`DRAFT_PARSE`), then slot warnings: an unknown slot, or content larger than its node. */
25
26
  diagnostics: {
26
27
  revision: number;
27
28
  diagnostics: readonly Diagnostic[];
28
29
  stale: boolean;
29
30
  };
31
+ /** Each update's result, from the first text on. */
32
+ update: EditorUpdateResult;
33
+ /** A link mark was pressed. `preventDefault()` stops the editor opening it. */
34
+ link: {
35
+ itemId: string;
36
+ href: string;
37
+ target: '_blank';
38
+ preventDefault(): void;
39
+ };
30
40
  camera: {
31
41
  camera: Camera;
32
42
  reason: CameraReason;
@@ -45,11 +55,8 @@ export interface EditorEvents {
45
55
  preventDefault(): void;
46
56
  };
47
57
  }
48
- /** An editor update's outcome. The editor draws in its own session, so it has no SVG value. */
49
- export type EditorUpdateResult = {
50
- status: 'committed' | 'error' | 'destroyed';
51
- revision: number;
52
- };
58
+ /** An editor update's outcome: `EditorUpdate` in `@draftably/runtime/host`. */
59
+ export type EditorUpdateResult = EditorUpdate;
53
60
  /** The editor's handle: the viewer's camera, plus editing. */
54
61
  export interface MountedEditor {
55
62
  /** Resolves once the first text is drawn. */
@@ -0,0 +1,63 @@
1
+ import type { Diagram, LayoutAlgorithmId, LayoutIntent } from '../model/types.ts';
2
+ import type { LayoutReport, LayoutScope } from './layout-engine.ts';
3
+ import type { PriorRoute, RouteInput, RoutingResult } from './routing-engine.ts';
4
+ export type ParamValue = string | number | boolean;
5
+ export interface ParamDefinition {
6
+ name: string;
7
+ values: ParamValue[];
8
+ passOnly?: boolean;
9
+ }
10
+ export type ComparisonMode = 'layout' | 'routing';
11
+ export type ComparisonRun = 'rebuild' | 'warm' | 'pass';
12
+ export interface ComparisonConfig {
13
+ mode: ComparisonMode;
14
+ /** Engines, the suggested routing alternatives, or a grid of parameter values. */
15
+ kind: 'algorithms' | 'routes' | 'parameters';
16
+ algorithm: LayoutAlgorithmId;
17
+ algorithms: LayoutAlgorithmId[];
18
+ axisA: string;
19
+ valuesA: string;
20
+ axisB: string;
21
+ valuesB: string;
22
+ run: ComparisonRun;
23
+ maxIterations: number;
24
+ scope: LayoutScope;
25
+ autoPorts: boolean;
26
+ selected: string[];
27
+ containerId?: string;
28
+ fixedIds: string[];
29
+ intent: LayoutIntent;
30
+ viewport: {
31
+ w: number;
32
+ h: number;
33
+ };
34
+ priorRoutes: PriorRoute[];
35
+ }
36
+ export interface CandidateSpec {
37
+ key: string;
38
+ title: string;
39
+ subtitle: string;
40
+ patch: Record<string, ParamValue>;
41
+ }
42
+ export interface CandidateResult {
43
+ spec: CandidateSpec;
44
+ document: Diagram;
45
+ report: LayoutReport | null;
46
+ routing: RoutingResult;
47
+ }
48
+ declare function parseValues(key: string, text: string, mode?: ComparisonMode): ParamValue[];
49
+ declare function effectiveParams(algorithm: LayoutAlgorithmId, run: ComparisonRun): Record<string, ParamDefinition>;
50
+ declare function specs(config: ComparisonConfig): CandidateSpec[];
51
+ /** The scene as the router sees it: collapsed groups stand in for their members. */
52
+ declare function sceneInput(doc: Diagram): RouteInput;
53
+ declare function candidate(baseline: Diagram, spec: CandidateSpec, config: ComparisonConfig): Promise<CandidateResult>;
54
+ export declare const ExplorerLab: {
55
+ layoutParams: Record<string, ParamDefinition>;
56
+ routeParams: Record<string, ParamDefinition>;
57
+ parseValues: typeof parseValues;
58
+ effectiveParams: typeof effectiveParams;
59
+ specs: typeof specs;
60
+ sceneInput: typeof sceneInput;
61
+ candidate: typeof candidate;
62
+ };
63
+ export {};
@@ -0,0 +1,36 @@
1
+ import type { DiagramEdge, Direction } from '../../model/types.ts';
2
+ import type { Scene } from './scene.ts';
3
+ import type { Centres, Item, LayoutIntent, Point, Rect, Topology } from './types.ts';
4
+ /** A link with an end outside the solve, or between two of its items: `a` and `b` are the items that own its ends. */
5
+ export interface BoundaryLink extends DiagramEdge {
6
+ a: string | null;
7
+ b: string | null;
8
+ }
9
+ /** What one solve of one container's children shares with its force, separation and packing steps. */
10
+ export interface Batch {
11
+ parentId: string | null;
12
+ direction: Direction;
13
+ items: Item[];
14
+ byId: Map<string, Item>;
15
+ t: Topology;
16
+ localIntent: LayoutIntent;
17
+ boundaryLinks: BoundaryLink[];
18
+ /** Hop counts, for the stress solve only. */
19
+ distances: Map<string, Map<string, number>> | null;
20
+ target: Centres | null;
21
+ /** The inside of the parent's frame, or null at the top level. */
22
+ container: Rect | null;
23
+ availableAspect: number;
24
+ /** Each item's centre when the solve began. */
25
+ origin: Centres;
26
+ anchor: number;
27
+ baseCenter: Point;
28
+ pairGap(a: Item, b: Item): number;
29
+ /** Copies the document's positions back onto the items. */
30
+ sync(): void;
31
+ }
32
+ /**
33
+ * Solves the children of one container: builds the target for the chosen algorithm, runs the
34
+ * force ticks, and keeps the best state by collisions first and energy second.
35
+ */
36
+ export declare function arrange(scene: Scene, activeIds: string[], parentId: string | null, direction: Direction): Promise<void>;
@@ -0,0 +1,7 @@
1
+ import type { Diagram } from '../../model/types.ts';
2
+ import type { LayoutOptions, LayoutResult } from './types.ts';
3
+ /**
4
+ * Lays out a copy of `input`. A pass moves boxes at most `maxMove` from where they are; a rebuild
5
+ * starts from a seed. Pins, fixed frames and the scope bound what may move.
6
+ */
7
+ export declare function compute(input: Diagram, opts?: LayoutOptions): Promise<LayoutResult>;
@@ -0,0 +1,8 @@
1
+ import type { Batch } from './arrange.ts';
2
+ import type { Scene } from './scene.ts';
3
+ /** The force on each item for one tick, by ID; `degree` is the weight of the links behind it. */
4
+ export declare function tickForces(scene: Scene, batch: Batch): Map<string, {
5
+ x: number;
6
+ y: number;
7
+ degree: number;
8
+ }>;
@@ -0,0 +1,10 @@
1
+ import type { Centres, Item, Rect, Settings } from './types.ts';
2
+ /** Items in ID order on a grid of even cells, near the wanted aspect. */
3
+ export declare function seedGrid(items: Item[], s: Settings, aspect: number): Centres;
4
+ /** The nearest free cell of a grid round the current centre, closest matches first. */
5
+ export declare function gridTarget(items: Item[], s: Settings, aspect: number): Centres;
6
+ /**
7
+ * Shifts a target onto the drawing: onto the container's corner, the mean of the fixed items, a
8
+ * fixed origin for a rebuild (`canonical`), or else the items' current centre.
9
+ */
10
+ export declare function alignTarget(map: Centres, items: Item[], container: Rect | null, canonical?: boolean): Centres;
@@ -0,0 +1,14 @@
1
+ import type { IntentPlacement, IntentRole } from '../../model/types.ts';
2
+ import type { Centres, Item, LayoutIntent } from './types.ts';
3
+ export type Hint = {
4
+ id: string;
5
+ placement: IntentPlacement;
6
+ };
7
+ /** The hints of an intent with their roles, in the order the intent holds them. */
8
+ export declare const hintsOf: (intent: LayoutIntent) => Array<[IntentRole, Hint]>;
9
+ /** Where in the drawing's box each placement puts a shape, as fractions of its free width and height. */
10
+ export declare const placements: Record<IntentPlacement, [number, number]>;
11
+ /** A checked start and end hint. Throws on an unknown shape, an unknown placement, or one shape in both roles. */
12
+ export declare function normalizeIntent(raw?: unknown, validIds?: Set<string> | null): LayoutIntent;
13
+ /** The centre each hinted item should reach, inside the items' current box. */
14
+ export declare function hintTargets(items: Item[], intent: LayoutIntent): Centres;
@@ -0,0 +1,5 @@
1
+ import type { Centres, Item, Settings, Topology } from './types.ts';
2
+ /** Straight centre-to-centre crossings between a candidate placement's edges. */
3
+ export declare function sketchCrossings(t: Topology, map: Centres): number;
4
+ /** Ranks as columns (or rows), ordered by barycentre sweeps, folded into bands when that fits the aspect better. */
5
+ export declare function layeredTarget(items: Item[], t: Topology, s: Settings, aspect: number): Centres;
@@ -0,0 +1,6 @@
1
+ import type { Centres, Item, Settings, Topology } from './types.ts';
2
+ /**
3
+ * The energy a solve lowers: hint and target errors, link lengths by algorithm, overlap area and
4
+ * forward links that run backwards. `compoundEnergy` adds the cross-boundary links of a compound solve.
5
+ */
6
+ export declare function objective(items: Item[], t: Topology, s: Settings, distances: Map<string, Map<string, number>> | null, target: Centres | null, compoundEnergy: (() => number) | null): number;
@@ -0,0 +1,7 @@
1
+ import type { Batch } from './arrange.ts';
2
+ import type { Scene } from './scene.ts';
3
+ /**
4
+ * After a rebuild that left overlaps inside a fixed frame: place the movable items one at a time
5
+ * at the free spot nearest their target, in up to four orders. Moves them only when one order fits.
6
+ */
7
+ export declare function packIntoFrame(scene: Scene, batch: Batch, collisions: number): void;
@@ -0,0 +1,7 @@
1
+ import type { Scene } from './scene.ts';
2
+ import type { LayoutResult, LayoutScope } from './types.ts';
3
+ /**
4
+ * Ends a run: holds each move to the pass limit and rounds it, rejects a pass that added
5
+ * overlaps, writes the settings back, and builds the report.
6
+ */
7
+ export declare function finish(scene: Scene, scope: LayoutScope, started: number, authoredRootId: string): LayoutResult;
@@ -0,0 +1,53 @@
1
+ import type { DiagramGroup, DiagramNode, Direction, NodeLayout } from '../../model/types.ts';
2
+ import type { Diagram, LayoutMetrics, LayoutOptions, Settings, SolverStop, TraceFrame } from './types.ts';
3
+ /** A shape or group ID, or nothing for the top level. */
4
+ export type ParentId = string | null | undefined;
5
+ /** Counters and findings that every solve of one layout run adds to. */
6
+ export interface Run {
7
+ batchCount: number;
8
+ totalIterations: number;
9
+ /** Which hierarchy sweep is running; odd sweeps of a compound layout go top down. */
10
+ hierarchyPhase: number;
11
+ stops: SolverStop[];
12
+ warnings: Set<string>;
13
+ /** Containers whose children a rebuild has already placed from a seed. */
14
+ seeded: Set<string | null>;
15
+ }
16
+ /**
17
+ * One layout run's view of the document: the hierarchy, what is fixed or hidden, and the only
18
+ * ways a solve may move or measure boxes. `doc` is the copy the run changes; `original` keeps the
19
+ * geometry it started from.
20
+ */
21
+ export declare function createScene(input: Diagram, doc: Diagram, s: Settings, opts: LayoutOptions): {
22
+ doc: Diagram;
23
+ original: Record<string, NodeLayout>;
24
+ nodeIndex: Map<string, number>;
25
+ s: Settings;
26
+ opts: LayoutOptions;
27
+ run: Run;
28
+ aspect: number;
29
+ intent: Partial<Record<import("../../model/types.ts").IntentRole, {
30
+ id: string;
31
+ placement: import("../../model/types.ts").IntentPlacement;
32
+ }>>;
33
+ compound: boolean;
34
+ globalTopology: import("./types.ts").Topology<import("../../model/types.ts").DiagramEdge>;
35
+ groups: Map<string, DiagramGroup>;
36
+ entities: Map<string, DiagramNode | DiagramGroup>;
37
+ pos: Record<string, NodeLayout>;
38
+ child: (id: ParentId) => (DiagramNode | DiagramGroup)[];
39
+ parent: (id: string) => string | undefined;
40
+ inheritedDirection: (id: ParentId) => Direction;
41
+ descend: (id: string) => string[];
42
+ branch: (id: ParentId) => boolean;
43
+ fixed: (id: string) => boolean;
44
+ visible: (id: string) => boolean;
45
+ padded: (id: string) => NodeLayout;
46
+ move: (id: string, dx: number, dy: number) => void;
47
+ resizeAuto: (id: string) => void;
48
+ metrics: () => LayoutMetrics;
49
+ before: LayoutMetrics;
50
+ trace: TraceFrame[];
51
+ captureTrace: (phase: string, force?: boolean) => void;
52
+ };
53
+ export type Scene = ReturnType<typeof createScene>;
@@ -0,0 +1,3 @@
1
+ import type { Direction } from '../../model/types.ts';
2
+ import type { Scene } from './scene.ts';
3
+ export declare function seedHierarchy(scene: Scene, pid: string | null, direction: Direction): void;
@@ -0,0 +1,17 @@
1
+ import type { Batch } from './arrange.ts';
2
+ import type { Scene } from './scene.ts';
3
+ import type { Axis, Item } from './types.ts';
4
+ /**
5
+ * The guarded moves of one solve: a move that keeps an item in its frame and inside the pass's
6
+ * movement limit, the room an item has along one axis, and the pairwise pass that pushes
7
+ * overlapping items apart.
8
+ */
9
+ export declare function createSeparation(scene: Scene, batch: Batch): {
10
+ constrainedMove: (p: Item, dx: number, dy: number) => void;
11
+ axisCapacity: (p: Item, axis: Axis, sign: number) => number;
12
+ separate: (rounds?: number) => void;
13
+ collisions: () => {
14
+ n: number;
15
+ a: number;
16
+ };
17
+ };
@@ -0,0 +1,6 @@
1
+ import type { LayoutSettings } from '../../model/types.ts';
2
+ import type { LayoutAlgorithm } from './types.ts';
3
+ export declare const ALGORITHMS: LayoutAlgorithm[];
4
+ export declare const defaults: LayoutSettings;
5
+ /** Checked settings: defaults under `values`, old names mapped, numbers held to their ranges. */
6
+ export declare function settings(values?: object): LayoutSettings;
@@ -0,0 +1,18 @@
1
+ import type { LayoutIntent, Link, Settings, Topology } from './types.ts';
2
+ /**
3
+ * The link structure of one solve: neighbours, feedback links, longest-path ranks and connected
4
+ * parts. Links stay as given; a feedback link is only left out of the ranks.
5
+ */
6
+ export declare function topology<E extends Link>(items: Array<{
7
+ id: string;
8
+ }>, edges: E[], intent?: LayoutIntent): Topology<E>;
9
+ /** Hop counts between every pair of items that links join. */
10
+ export declare function shortestPaths(t: Topology): Map<string, Map<string, number>>;
11
+ export interface Forest {
12
+ roots: string[];
13
+ parent: Map<string, string>;
14
+ kids: Map<string, string[]>;
15
+ depth: Map<string, number>;
16
+ }
17
+ /** A breadth-first spanning forest: from the chosen root, then every source, then the rest. */
18
+ export declare function forest(t: Topology, s: Settings): Forest;
@@ -0,0 +1,8 @@
1
+ import type { Centres, Item, Link, Settings, Topology } from './types.ts';
2
+ /** A span-based tree: each subtree gets its own width and parents sit over their children. */
3
+ export declare function treeTarget(items: Item[], t: Topology, s: Settings): Centres;
4
+ /** Rings round each root by depth. No solve reaches it: see `Settings`. */
5
+ export declare function radialTarget(items: Item[], t: Topology, s: Settings): Centres;
6
+ export declare function bilateralTarget(items: Item[], t: Topology, s: Settings): Centres | null;
7
+ /** Which way a forward link should run: 1, -1 on the far side of a centred start, 0 across it. */
8
+ export declare function forwardSign(t: Topology, e: Link): number;