@diagrammo/dgmo 0.8.22 → 0.8.25

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 (90) hide show
  1. package/.claude/commands/dgmo.md +60 -72
  2. package/dist/cli.cjs +123 -116
  3. package/dist/editor.cjs +3 -2
  4. package/dist/editor.cjs.map +1 -1
  5. package/dist/editor.js +3 -2
  6. package/dist/editor.js.map +1 -1
  7. package/dist/highlight.cjs +3 -2
  8. package/dist/highlight.cjs.map +1 -1
  9. package/dist/highlight.js +3 -2
  10. package/dist/highlight.js.map +1 -1
  11. package/dist/index.cjs +1649 -442
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +196 -23
  14. package/dist/index.d.ts +196 -23
  15. package/dist/index.js +1631 -440
  16. package/dist/index.js.map +1 -1
  17. package/dist/internal.cjs +677 -0
  18. package/dist/internal.cjs.map +1 -0
  19. package/dist/internal.d.cts +267 -0
  20. package/dist/internal.d.ts +267 -0
  21. package/dist/internal.js +633 -0
  22. package/dist/internal.js.map +1 -0
  23. package/docs/guide/chart-area.md +17 -17
  24. package/docs/guide/chart-bar-stacked.md +12 -12
  25. package/docs/guide/chart-cycle.md +156 -0
  26. package/docs/guide/chart-doughnut.md +10 -10
  27. package/docs/guide/chart-funnel.md +9 -9
  28. package/docs/guide/chart-heatmap.md +10 -10
  29. package/docs/guide/chart-journey-map.md +179 -0
  30. package/docs/guide/chart-kanban.md +2 -0
  31. package/docs/guide/chart-line.md +19 -19
  32. package/docs/guide/chart-multi-line.md +16 -16
  33. package/docs/guide/chart-pie.md +11 -11
  34. package/docs/guide/chart-polar-area.md +10 -10
  35. package/docs/guide/chart-pyramid.md +111 -0
  36. package/docs/guide/chart-radar.md +9 -9
  37. package/docs/guide/chart-scatter.md +24 -27
  38. package/docs/guide/index.md +3 -3
  39. package/docs/guide/registry.json +5 -0
  40. package/docs/language-reference.md +108 -26
  41. package/fonts/Inter-Bold.ttf +0 -0
  42. package/fonts/Inter-Regular.ttf +0 -0
  43. package/fonts/LICENSE-Inter.txt +92 -0
  44. package/gallery/fixtures/bar-stacked.dgmo +12 -6
  45. package/gallery/fixtures/heatmap.dgmo +12 -6
  46. package/gallery/fixtures/multi-line.dgmo +11 -7
  47. package/gallery/fixtures/pyramid/dikw.dgmo +17 -0
  48. package/gallery/fixtures/pyramid/inverted-funnel.dgmo +16 -0
  49. package/gallery/fixtures/pyramid/minimal.dgmo +5 -0
  50. package/gallery/fixtures/quadrant.dgmo +8 -8
  51. package/gallery/fixtures/scatter.dgmo +12 -12
  52. package/package.json +14 -2
  53. package/src/boxes-and-lines/parser.ts +13 -2
  54. package/src/boxes-and-lines/renderer.ts +22 -13
  55. package/src/chart-type-scoring.ts +162 -0
  56. package/src/chart-types.ts +437 -0
  57. package/src/cli.ts +152 -101
  58. package/src/completion.ts +9 -48
  59. package/src/cycle/layout.ts +19 -28
  60. package/src/cycle/renderer.ts +59 -32
  61. package/src/cycle/types.ts +21 -0
  62. package/src/d3.ts +30 -3
  63. package/src/dgmo-router.ts +98 -73
  64. package/src/echarts.ts +1 -1
  65. package/src/editor/keywords.ts +3 -2
  66. package/src/fonts.ts +3 -2
  67. package/src/gantt/parser.ts +5 -1
  68. package/src/index.ts +37 -3
  69. package/src/infra/parser.ts +3 -3
  70. package/src/internal.ts +20 -0
  71. package/src/journey-map/layout.ts +7 -3
  72. package/src/journey-map/parser.ts +5 -1
  73. package/src/journey-map/renderer.ts +112 -47
  74. package/src/kanban/parser.ts +5 -1
  75. package/src/org/collapse.ts +82 -4
  76. package/src/org/parser.ts +1 -1
  77. package/src/org/renderer.ts +221 -4
  78. package/src/pyramid/parser.ts +172 -0
  79. package/src/pyramid/renderer.ts +684 -0
  80. package/src/pyramid/types.ts +28 -0
  81. package/src/render.ts +2 -8
  82. package/src/sequence/parser.ts +64 -22
  83. package/src/sequence/participant-inference.ts +0 -1
  84. package/src/sequence/renderer.ts +97 -265
  85. package/src/sharing.ts +0 -1
  86. package/src/sitemap/parser.ts +1 -1
  87. package/src/tech-radar/interactive.ts +54 -0
  88. package/src/utils/parsing.ts +1 -0
  89. package/src/utils/tag-groups.ts +35 -5
  90. package/src/wireframe/parser.ts +3 -1
@@ -0,0 +1,267 @@
1
+ type DgmoSeverity = 'error' | 'warning';
2
+ interface DgmoError {
3
+ line: number;
4
+ column?: number;
5
+ message: string;
6
+ severity: DgmoSeverity;
7
+ /**
8
+ * Optional stable diagnostic code (e.g. 'E_ARROW_SUBSTRING_IN_LABEL').
9
+ * Additive; pre-existing diagnostics omit this field and existing
10
+ * substring-on-`.message` assertions keep working unchanged.
11
+ */
12
+ code?: string;
13
+ }
14
+
15
+ /**
16
+ * Parse a data row line: everything before the last numeric token(s) is the label,
17
+ * numeric tokens at the end are the values. Supports comma-separated multi-values,
18
+ * space-separated multi-values, and comma-grouped numbers (e.g., "1,087").
19
+ *
20
+ * Examples:
21
+ * "Jan 120" → { label: "Jan", values: [120] }
22
+ * "North America 250" → { label: "North America", values: [250] }
23
+ * "Q1 10, 20, 30" → { label: "Q1", values: [10, 20, 30] }
24
+ * "Q1 10 20 30" → { label: "Q1", values: [10, 20, 30] }
25
+ * "Revenue 1,200" → { label: "Revenue", values: [1200] }
26
+ * "Revenue 3,984,078.65"→ { label: "Revenue", values: [3984078.65] }
27
+ *
28
+ * Returns null if the line has no numeric value at the end.
29
+ */
30
+ declare function parseDataRowValues(line: string, options?: {
31
+ multiValue?: boolean;
32
+ expectedValues?: number;
33
+ }): {
34
+ label: string;
35
+ values: number[];
36
+ } | null;
37
+
38
+ /** A single entry inside a tag group: `Value(color)` */
39
+ interface TagEntry {
40
+ value: string;
41
+ color: string;
42
+ lineNumber: number;
43
+ }
44
+ /** A tag group block: heading + entries */
45
+ interface TagGroup {
46
+ name: string;
47
+ alias?: string;
48
+ entries: TagEntry[];
49
+ /** Default value for nodes without explicit metadata. First entry unless another is marked `default`. */
50
+ defaultValue?: string;
51
+ lineNumber: number;
52
+ }
53
+
54
+ /** @deprecated Use `TagGroup` from `utils/tag-groups` */
55
+ type KanbanTagGroup = TagGroup;
56
+ interface KanbanCard {
57
+ id: string;
58
+ title: string;
59
+ tags: Record<string, string>;
60
+ details: string[];
61
+ lineNumber: number;
62
+ endLineNumber: number;
63
+ color?: string;
64
+ }
65
+ interface KanbanColumn {
66
+ id: string;
67
+ name: string;
68
+ wipLimit?: number;
69
+ color?: string;
70
+ metadata?: Record<string, string>;
71
+ cards: KanbanCard[];
72
+ lineNumber: number;
73
+ }
74
+ interface ParsedKanban {
75
+ type: 'kanban';
76
+ title?: string;
77
+ titleLineNumber?: number;
78
+ columns: KanbanColumn[];
79
+ tagGroups: KanbanTagGroup[];
80
+ options: Record<string, string>;
81
+ diagnostics: DgmoError[];
82
+ error: string | null;
83
+ }
84
+
85
+ /**
86
+ * Compute new file content after moving a card to a different position.
87
+ *
88
+ * @param content - original file content string
89
+ * @param parsed - parsed kanban board
90
+ * @param cardId - id of the card to move
91
+ * @param targetColumnId - id of the destination column
92
+ * @param targetIndex - position within target column (0 = first card)
93
+ * @returns new content string, or null if move is invalid
94
+ */
95
+ declare function computeCardMove(content: string, parsed: ParsedKanban, cardId: string, targetColumnId: string, targetIndex: number): string | null;
96
+ /**
97
+ * Move a card to the Archive section at the end of the file.
98
+ * Creates `== Archive ==` if it doesn't exist.
99
+ *
100
+ * @returns new content string, or null if the card is not found
101
+ */
102
+ declare function computeCardArchive(content: string, parsed: ParsedKanban, cardId: string): string | null;
103
+ /** Check if a column name is the archive column (case-insensitive). */
104
+ declare function isArchiveColumn(name: string): boolean;
105
+
106
+ /**
107
+ * Participant types that can be declared via "Name is a type" syntax.
108
+ */
109
+ type ParticipantType = 'default' | 'service' | 'database' | 'actor' | 'queue' | 'cache' | 'gateway' | 'external' | 'networking' | 'frontend';
110
+ /**
111
+ * A declared or inferred participant in the sequence diagram.
112
+ */
113
+ interface SequenceParticipant {
114
+ /** Internal identifier (e.g. "AuthService") */
115
+ id: string;
116
+ /** Display label — uses aka alias if provided, otherwise id */
117
+ label: string;
118
+ /** Participant shape type */
119
+ type: ParticipantType;
120
+ /** Source line number (1-based) */
121
+ lineNumber: number;
122
+ /** Explicit layout position override (0-based from left, negative from right) */
123
+ position?: number;
124
+ /** Pipe-delimited tag metadata (e.g. `| role: Gateway`) */
125
+ metadata?: Record<string, string>;
126
+ }
127
+ /**
128
+ * A message between two participants.
129
+ */
130
+ interface SequenceMessage {
131
+ from: string;
132
+ to: string;
133
+ label: string;
134
+ lineNumber: number;
135
+ async?: boolean;
136
+ /** Pipe-delimited tag metadata (e.g. `| c: Caching`) */
137
+ metadata?: Record<string, string>;
138
+ }
139
+ /**
140
+ * A conditional or loop block in the sequence diagram.
141
+ */
142
+ interface ElseIfBranch {
143
+ label: string;
144
+ children: SequenceElement[];
145
+ lineNumber: number;
146
+ }
147
+ interface SequenceBlock {
148
+ kind: 'block';
149
+ type: 'if' | 'loop' | 'parallel';
150
+ label: string;
151
+ children: SequenceElement[];
152
+ elseChildren: SequenceElement[];
153
+ elseIfBranches?: ElseIfBranch[];
154
+ elseLineNumber?: number;
155
+ lineNumber: number;
156
+ }
157
+ /**
158
+ * A labeled horizontal divider between message phases.
159
+ */
160
+ interface SequenceSection {
161
+ kind: 'section';
162
+ label: string;
163
+ lineNumber: number;
164
+ }
165
+ /**
166
+ * An annotation attached to a message, rendered as a folded-corner box.
167
+ */
168
+ interface SequenceNote {
169
+ kind: 'note';
170
+ text: string;
171
+ position: 'right' | 'left';
172
+ participantId: string;
173
+ lineNumber: number;
174
+ endLineNumber: number;
175
+ }
176
+ type SequenceElement = SequenceMessage | SequenceBlock | SequenceSection | SequenceNote;
177
+ /**
178
+ * A named group of participants rendered as a labeled box.
179
+ */
180
+ interface SequenceGroup {
181
+ name: string;
182
+ participantIds: string[];
183
+ lineNumber: number;
184
+ /** Pipe-delimited tag metadata (e.g. `[Backend | t: Product]`) */
185
+ metadata?: Record<string, string>;
186
+ /** Whether this group is collapsed by default */
187
+ collapsed?: boolean;
188
+ }
189
+
190
+ interface SectionMessageGroup {
191
+ section: SequenceSection;
192
+ messageIndices: number[];
193
+ }
194
+ /**
195
+ * Group messages by the top-level section that precedes them.
196
+ * Messages before the first section are ungrouped (always visible).
197
+ * Only top-level sections are collapsible — sections inside blocks are excluded.
198
+ */
199
+ declare function groupMessagesBySection(elements: SequenceElement[], messages: SequenceMessage[]): SectionMessageGroup[];
200
+ interface RenderStep {
201
+ type: 'call' | 'return';
202
+ from: string;
203
+ to: string;
204
+ label: string;
205
+ messageIndex: number;
206
+ async?: boolean;
207
+ }
208
+ /**
209
+ * Build an ordered render sequence from flat messages.
210
+ * Uses a call stack to infer where returns should be placed:
211
+ * returns appear after all nested sub-calls complete.
212
+ */
213
+ declare function buildRenderSequence(messages: SequenceMessage[]): RenderStep[];
214
+ interface Activation {
215
+ participantId: string;
216
+ startStep: number;
217
+ endStep: number;
218
+ depth: number;
219
+ }
220
+ /**
221
+ * Compute activation rectangles from render steps.
222
+ * Each call pushes onto the callee's stack; each return pops it.
223
+ */
224
+ declare function computeActivations(steps: RenderStep[]): Activation[];
225
+ /**
226
+ * Reorder participants based on explicit `position` overrides.
227
+ * Positive positions are 0-based from the left; negative positions count from the right (-1 = last).
228
+ * Unpositioned participants maintain their relative order, filling remaining slots.
229
+ */
230
+ declare function applyPositionOverrides(participants: SequenceParticipant[]): SequenceParticipant[];
231
+ /**
232
+ * Reorder participants so that members of the same group are adjacent.
233
+ * Groups are positioned at the point where their first member would naturally
234
+ * appear based on message order (first-occurrence positioning). This prevents
235
+ * groups declared at the top of the file from being placed before participants
236
+ * that appear in messages earlier.
237
+ *
238
+ * Explicit `position` overrides are handled separately by `applyPositionOverrides`.
239
+ */
240
+ declare function applyGroupOrdering(participants: SequenceParticipant[], groups: SequenceGroup[], messages?: SequenceMessage[]): SequenceParticipant[];
241
+ /**
242
+ * Build a mapping from each note's lineNumber to the lineNumber of its
243
+ * associated message (the last message before the note in document order).
244
+ * Used by the app to highlight the associated message when cursor is on a note.
245
+ */
246
+ declare function buildNoteMessageMap(elements: SequenceElement[]): Map<number, number>;
247
+
248
+ interface ArcLink {
249
+ source: string;
250
+ target: string;
251
+ value: number;
252
+ color: string | null;
253
+ lineNumber: number;
254
+ }
255
+ type ArcOrder = 'appearance' | 'name' | 'group' | 'degree';
256
+ interface ArcNodeGroup {
257
+ name: string;
258
+ nodes: string[];
259
+ color: string | null;
260
+ lineNumber: number;
261
+ }
262
+ /**
263
+ * Orders arc diagram nodes based on the selected ordering strategy.
264
+ */
265
+ declare function orderArcNodes(links: ArcLink[], order: ArcOrder, groups: ArcNodeGroup[]): string[];
266
+
267
+ export { applyGroupOrdering, applyPositionOverrides, buildNoteMessageMap, buildRenderSequence, computeActivations, computeCardArchive, computeCardMove, groupMessagesBySection, isArchiveColumn, orderArcNodes, parseDataRowValues };
@@ -0,0 +1,267 @@
1
+ type DgmoSeverity = 'error' | 'warning';
2
+ interface DgmoError {
3
+ line: number;
4
+ column?: number;
5
+ message: string;
6
+ severity: DgmoSeverity;
7
+ /**
8
+ * Optional stable diagnostic code (e.g. 'E_ARROW_SUBSTRING_IN_LABEL').
9
+ * Additive; pre-existing diagnostics omit this field and existing
10
+ * substring-on-`.message` assertions keep working unchanged.
11
+ */
12
+ code?: string;
13
+ }
14
+
15
+ /**
16
+ * Parse a data row line: everything before the last numeric token(s) is the label,
17
+ * numeric tokens at the end are the values. Supports comma-separated multi-values,
18
+ * space-separated multi-values, and comma-grouped numbers (e.g., "1,087").
19
+ *
20
+ * Examples:
21
+ * "Jan 120" → { label: "Jan", values: [120] }
22
+ * "North America 250" → { label: "North America", values: [250] }
23
+ * "Q1 10, 20, 30" → { label: "Q1", values: [10, 20, 30] }
24
+ * "Q1 10 20 30" → { label: "Q1", values: [10, 20, 30] }
25
+ * "Revenue 1,200" → { label: "Revenue", values: [1200] }
26
+ * "Revenue 3,984,078.65"→ { label: "Revenue", values: [3984078.65] }
27
+ *
28
+ * Returns null if the line has no numeric value at the end.
29
+ */
30
+ declare function parseDataRowValues(line: string, options?: {
31
+ multiValue?: boolean;
32
+ expectedValues?: number;
33
+ }): {
34
+ label: string;
35
+ values: number[];
36
+ } | null;
37
+
38
+ /** A single entry inside a tag group: `Value(color)` */
39
+ interface TagEntry {
40
+ value: string;
41
+ color: string;
42
+ lineNumber: number;
43
+ }
44
+ /** A tag group block: heading + entries */
45
+ interface TagGroup {
46
+ name: string;
47
+ alias?: string;
48
+ entries: TagEntry[];
49
+ /** Default value for nodes without explicit metadata. First entry unless another is marked `default`. */
50
+ defaultValue?: string;
51
+ lineNumber: number;
52
+ }
53
+
54
+ /** @deprecated Use `TagGroup` from `utils/tag-groups` */
55
+ type KanbanTagGroup = TagGroup;
56
+ interface KanbanCard {
57
+ id: string;
58
+ title: string;
59
+ tags: Record<string, string>;
60
+ details: string[];
61
+ lineNumber: number;
62
+ endLineNumber: number;
63
+ color?: string;
64
+ }
65
+ interface KanbanColumn {
66
+ id: string;
67
+ name: string;
68
+ wipLimit?: number;
69
+ color?: string;
70
+ metadata?: Record<string, string>;
71
+ cards: KanbanCard[];
72
+ lineNumber: number;
73
+ }
74
+ interface ParsedKanban {
75
+ type: 'kanban';
76
+ title?: string;
77
+ titleLineNumber?: number;
78
+ columns: KanbanColumn[];
79
+ tagGroups: KanbanTagGroup[];
80
+ options: Record<string, string>;
81
+ diagnostics: DgmoError[];
82
+ error: string | null;
83
+ }
84
+
85
+ /**
86
+ * Compute new file content after moving a card to a different position.
87
+ *
88
+ * @param content - original file content string
89
+ * @param parsed - parsed kanban board
90
+ * @param cardId - id of the card to move
91
+ * @param targetColumnId - id of the destination column
92
+ * @param targetIndex - position within target column (0 = first card)
93
+ * @returns new content string, or null if move is invalid
94
+ */
95
+ declare function computeCardMove(content: string, parsed: ParsedKanban, cardId: string, targetColumnId: string, targetIndex: number): string | null;
96
+ /**
97
+ * Move a card to the Archive section at the end of the file.
98
+ * Creates `== Archive ==` if it doesn't exist.
99
+ *
100
+ * @returns new content string, or null if the card is not found
101
+ */
102
+ declare function computeCardArchive(content: string, parsed: ParsedKanban, cardId: string): string | null;
103
+ /** Check if a column name is the archive column (case-insensitive). */
104
+ declare function isArchiveColumn(name: string): boolean;
105
+
106
+ /**
107
+ * Participant types that can be declared via "Name is a type" syntax.
108
+ */
109
+ type ParticipantType = 'default' | 'service' | 'database' | 'actor' | 'queue' | 'cache' | 'gateway' | 'external' | 'networking' | 'frontend';
110
+ /**
111
+ * A declared or inferred participant in the sequence diagram.
112
+ */
113
+ interface SequenceParticipant {
114
+ /** Internal identifier (e.g. "AuthService") */
115
+ id: string;
116
+ /** Display label — uses aka alias if provided, otherwise id */
117
+ label: string;
118
+ /** Participant shape type */
119
+ type: ParticipantType;
120
+ /** Source line number (1-based) */
121
+ lineNumber: number;
122
+ /** Explicit layout position override (0-based from left, negative from right) */
123
+ position?: number;
124
+ /** Pipe-delimited tag metadata (e.g. `| role: Gateway`) */
125
+ metadata?: Record<string, string>;
126
+ }
127
+ /**
128
+ * A message between two participants.
129
+ */
130
+ interface SequenceMessage {
131
+ from: string;
132
+ to: string;
133
+ label: string;
134
+ lineNumber: number;
135
+ async?: boolean;
136
+ /** Pipe-delimited tag metadata (e.g. `| c: Caching`) */
137
+ metadata?: Record<string, string>;
138
+ }
139
+ /**
140
+ * A conditional or loop block in the sequence diagram.
141
+ */
142
+ interface ElseIfBranch {
143
+ label: string;
144
+ children: SequenceElement[];
145
+ lineNumber: number;
146
+ }
147
+ interface SequenceBlock {
148
+ kind: 'block';
149
+ type: 'if' | 'loop' | 'parallel';
150
+ label: string;
151
+ children: SequenceElement[];
152
+ elseChildren: SequenceElement[];
153
+ elseIfBranches?: ElseIfBranch[];
154
+ elseLineNumber?: number;
155
+ lineNumber: number;
156
+ }
157
+ /**
158
+ * A labeled horizontal divider between message phases.
159
+ */
160
+ interface SequenceSection {
161
+ kind: 'section';
162
+ label: string;
163
+ lineNumber: number;
164
+ }
165
+ /**
166
+ * An annotation attached to a message, rendered as a folded-corner box.
167
+ */
168
+ interface SequenceNote {
169
+ kind: 'note';
170
+ text: string;
171
+ position: 'right' | 'left';
172
+ participantId: string;
173
+ lineNumber: number;
174
+ endLineNumber: number;
175
+ }
176
+ type SequenceElement = SequenceMessage | SequenceBlock | SequenceSection | SequenceNote;
177
+ /**
178
+ * A named group of participants rendered as a labeled box.
179
+ */
180
+ interface SequenceGroup {
181
+ name: string;
182
+ participantIds: string[];
183
+ lineNumber: number;
184
+ /** Pipe-delimited tag metadata (e.g. `[Backend | t: Product]`) */
185
+ metadata?: Record<string, string>;
186
+ /** Whether this group is collapsed by default */
187
+ collapsed?: boolean;
188
+ }
189
+
190
+ interface SectionMessageGroup {
191
+ section: SequenceSection;
192
+ messageIndices: number[];
193
+ }
194
+ /**
195
+ * Group messages by the top-level section that precedes them.
196
+ * Messages before the first section are ungrouped (always visible).
197
+ * Only top-level sections are collapsible — sections inside blocks are excluded.
198
+ */
199
+ declare function groupMessagesBySection(elements: SequenceElement[], messages: SequenceMessage[]): SectionMessageGroup[];
200
+ interface RenderStep {
201
+ type: 'call' | 'return';
202
+ from: string;
203
+ to: string;
204
+ label: string;
205
+ messageIndex: number;
206
+ async?: boolean;
207
+ }
208
+ /**
209
+ * Build an ordered render sequence from flat messages.
210
+ * Uses a call stack to infer where returns should be placed:
211
+ * returns appear after all nested sub-calls complete.
212
+ */
213
+ declare function buildRenderSequence(messages: SequenceMessage[]): RenderStep[];
214
+ interface Activation {
215
+ participantId: string;
216
+ startStep: number;
217
+ endStep: number;
218
+ depth: number;
219
+ }
220
+ /**
221
+ * Compute activation rectangles from render steps.
222
+ * Each call pushes onto the callee's stack; each return pops it.
223
+ */
224
+ declare function computeActivations(steps: RenderStep[]): Activation[];
225
+ /**
226
+ * Reorder participants based on explicit `position` overrides.
227
+ * Positive positions are 0-based from the left; negative positions count from the right (-1 = last).
228
+ * Unpositioned participants maintain their relative order, filling remaining slots.
229
+ */
230
+ declare function applyPositionOverrides(participants: SequenceParticipant[]): SequenceParticipant[];
231
+ /**
232
+ * Reorder participants so that members of the same group are adjacent.
233
+ * Groups are positioned at the point where their first member would naturally
234
+ * appear based on message order (first-occurrence positioning). This prevents
235
+ * groups declared at the top of the file from being placed before participants
236
+ * that appear in messages earlier.
237
+ *
238
+ * Explicit `position` overrides are handled separately by `applyPositionOverrides`.
239
+ */
240
+ declare function applyGroupOrdering(participants: SequenceParticipant[], groups: SequenceGroup[], messages?: SequenceMessage[]): SequenceParticipant[];
241
+ /**
242
+ * Build a mapping from each note's lineNumber to the lineNumber of its
243
+ * associated message (the last message before the note in document order).
244
+ * Used by the app to highlight the associated message when cursor is on a note.
245
+ */
246
+ declare function buildNoteMessageMap(elements: SequenceElement[]): Map<number, number>;
247
+
248
+ interface ArcLink {
249
+ source: string;
250
+ target: string;
251
+ value: number;
252
+ color: string | null;
253
+ lineNumber: number;
254
+ }
255
+ type ArcOrder = 'appearance' | 'name' | 'group' | 'degree';
256
+ interface ArcNodeGroup {
257
+ name: string;
258
+ nodes: string[];
259
+ color: string | null;
260
+ lineNumber: number;
261
+ }
262
+ /**
263
+ * Orders arc diagram nodes based on the selected ordering strategy.
264
+ */
265
+ declare function orderArcNodes(links: ArcLink[], order: ArcOrder, groups: ArcNodeGroup[]): string[];
266
+
267
+ export { applyGroupOrdering, applyPositionOverrides, buildNoteMessageMap, buildRenderSequence, computeActivations, computeCardArchive, computeCardMove, groupMessagesBySection, isArchiveColumn, orderArcNodes, parseDataRowValues };