yarramate 1.24.0 → 1.25.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 (27) hide show
  1. package/dist/adapters/visual/protocol-contract.d.ts +19 -0
  2. package/dist/adapters/visual/session-server.js +16 -4
  3. package/dist/adapters/visual/wire.d.ts +9 -1
  4. package/dist/notation/archimate.d.ts +6 -1
  5. package/dist/notation/archimate.js +9 -4
  6. package/dist/visual-app/assets/elk-worker.min-D8OVqK8T.js +22 -0
  7. package/dist/visual-app/assets/elk.bundled-CLux5E_P.js +24 -0
  8. package/dist/visual-app/assets/index-DGkU2CSB.js +369 -0
  9. package/dist/visual-app/index.html +1 -1
  10. package/dist/visual-app-lib/editor.js +30289 -29571
  11. package/dist/visual-app-lib/types/adapters/visual/protocol-contract.d.ts +19 -0
  12. package/dist/visual-app-lib/types/adapters/visual/wire.d.ts +9 -1
  13. package/dist/visual-app-lib/types/notation/archimate.d.ts +6 -1
  14. package/dist/visual-app-lib/types/visual-app/edge-routes.d.ts +17 -1
  15. package/dist/visual-app-lib/types/visual-app/elk-layout.d.ts +42 -5
  16. package/dist/visual-app-lib/types/visual-app/graph-canvas.d.ts +35 -5
  17. package/dist/visual-app-lib/types/visual-app/kind-icons.d.ts +1 -1
  18. package/dist/visual-app-lib/types/visual-app/layout-controls.d.ts +12 -6
  19. package/dist/visual-app-lib/types/visual-app/mount.d.ts +12 -0
  20. package/dist/visual-app-lib/types/visual-app/save-view.d.ts +15 -6
  21. package/dist/visual-app-lib/types/visual-app/style-presets.d.ts +39 -0
  22. package/dist/visual-app-lib/types/visual-app/workspace-state.d.ts +9 -0
  23. package/docs/CONSUMING-YARRAMATE.md +9 -0
  24. package/package.json +1 -1
  25. package/schema/yarramate-visual-event.schema.json +10 -0
  26. package/schema/yarramate-visual-layout.schema.json +31 -0
  27. package/dist/visual-app/assets/index-wKXrkA2V.js +0 -392
@@ -267,6 +267,23 @@ export interface VisualLayoutPositions {
267
267
  readonly y: number;
268
268
  };
269
269
  }
270
+ /**
271
+ * The routes the canvas was drawing when a layout was saved (ADR 0147), keyed
272
+ * by relationship id: absolute canvas coordinates from the source end, both
273
+ * endpoints included, and where along the route the label sits. Saved WITH
274
+ * the positions, because a route is only right for the positions it was
275
+ * computed for: a reader who moved one subject keeps every other edge's
276
+ * route, and only the moved subject's edges fall back to a straight line.
277
+ */
278
+ export interface VisualLayoutRoutes {
279
+ readonly [relationshipId: string]: {
280
+ readonly points: readonly {
281
+ readonly x: number;
282
+ readonly y: number;
283
+ }[];
284
+ readonly labelAt: number | null;
285
+ };
286
+ }
270
287
  /**
271
288
  * A change to a projection document, staged rather than written (ADR 0103).
272
289
  *
@@ -332,6 +349,8 @@ export interface VisualLayoutSavePayload {
332
349
  */
333
350
  readonly folded?: readonly string[];
334
351
  readonly unfolded?: readonly string[];
352
+ /** The routes in force at save time (ADR 0147); absent when nothing was routed. */
353
+ readonly routes?: VisualLayoutRoutes;
335
354
  }
336
355
  /**
337
356
  * Terminal event payload. Every reason is the runtime's to choose: only it
@@ -456,15 +456,16 @@ export const startVisualServer = async (options) => {
456
456
  // like a broken saved view above — presentation state must never fail a
457
457
  // session.
458
458
  const layoutDir = resolve(options.cwd, ".yarramate/visual-layout");
459
- const { layouts, folds } = (() => {
459
+ const { layouts, folds, routes } = (() => {
460
460
  const layouts = {};
461
461
  const folds = {};
462
+ const routes = {};
462
463
  let entries;
463
464
  try {
464
465
  entries = readdirSync(layoutDir);
465
466
  }
466
467
  catch {
467
- return { layouts, folds };
468
+ return { layouts, folds, routes };
468
469
  }
469
470
  for (const entry of entries) {
470
471
  if (extname(entry) !== ".yaml" && extname(entry) !== ".yml")
@@ -476,6 +477,10 @@ export const startVisualServer = async (options) => {
476
477
  continue;
477
478
  const sidecar = parsed;
478
479
  layouts[sidecar.projectionId] = sidecar.positions;
480
+ // The routes the canvas was drawing when it saved (ADR 0147). A
481
+ // sidecar written before them says nothing, and the layout recomputes.
482
+ if (sidecar.routes !== undefined)
483
+ routes[sidecar.projectionId] = sidecar.routes;
479
484
  // A sidecar written before #473 has neither list, and says nothing
480
485
  // about folding rather than saying "fold nothing" - the view's own
481
486
  // default decides for it. Only a sidecar that STATES a fold overrides.
@@ -490,7 +495,7 @@ export const startVisualServer = async (options) => {
490
495
  // Skipped sidecar: presentation state must never fail a session.
491
496
  }
492
497
  }
493
- return { layouts, folds };
498
+ return { layouts, folds, routes };
494
499
  })();
495
500
  // `request.initialModel.graph` is the caller's compile (`buildVisualModelGraph`,
496
501
  // before invoking `yarramate-visual start`) and is only the fallback below:
@@ -505,6 +510,7 @@ export const startVisualServer = async (options) => {
505
510
  vocabulary: { conceptKinds: [], relationshipKinds: [] },
506
511
  layouts,
507
512
  ...(Object.keys(folds).length === 0 ? {} : { folds }),
513
+ ...(Object.keys(routes).length === 0 ? {} : { routes }),
508
514
  sourceDigests: request.initialModel.sourceDigests,
509
515
  // The request's model has no projections in it - `visual-model/v1` carries
510
516
  // a graph, not a workspace - so the fallback states nothing rather than
@@ -1424,7 +1430,7 @@ export const startVisualServer = async (options) => {
1424
1430
  // never `git commit`ed. It never asks the agent anything, so it is
1425
1431
  // answered here directly rather than through the pending queue a
1426
1432
  // poll would drain.
1427
- const { projectionId, positions, folded, unfolded } = event.payload;
1433
+ const { projectionId, positions, folded, unfolded, routes: savedRoutes } = event.payload;
1428
1434
  if (!views.some((view) => view.id === projectionId)) {
1429
1435
  sendFrame(socket, {
1430
1436
  kind: "layout-save-result",
@@ -1446,10 +1452,16 @@ export const startVisualServer = async (options) => {
1446
1452
  // sidecar written by one host is read by the other.
1447
1453
  ...(folded === undefined ? {} : { folded }),
1448
1454
  ...(unfolded === undefined ? {} : { unfolded }),
1455
+ // The routes in force, beside the positions they were computed
1456
+ // for (ADR 0147); a save with nothing routed writes none.
1457
+ ...(savedRoutes === undefined ? {} : { routes: savedRoutes }),
1449
1458
  }), "utf8");
1450
1459
  rendered = {
1451
1460
  ...rendered,
1452
1461
  layouts: { ...rendered.layouts, [projectionId]: positions },
1462
+ ...(savedRoutes === undefined
1463
+ ? {}
1464
+ : { routes: { ...rendered.routes, [projectionId]: savedRoutes } }),
1453
1465
  ...(folded === undefined && unfolded === undefined
1454
1466
  ? {}
1455
1467
  : {
@@ -1,6 +1,6 @@
1
1
  import type { CanvasGraph } from '../../graph-projection.js';
2
2
  import type { PatternMembership, PatternVacancy } from '../../compiler.js';
3
- import type { VISUAL_PROTOCOL_VERSION, VisualApplyResultPayload, VisualAuthority, VisualBrowserInput, VisualCapabilities, VisualChoicePresentPayload, VisualDiagnostic, VisualFilterResultPayload, VisualFreezeReason, VisualKindOption, VisualPatternOption, VisualLayoutPositions, VisualLayoutSaveResultPayload, VisualResponse, VisualTerminationReason, VisualViewSummary } from './protocol-contract.js';
3
+ import type { VISUAL_PROTOCOL_VERSION, VisualApplyResultPayload, VisualAuthority, VisualBrowserInput, VisualCapabilities, VisualChoicePresentPayload, VisualDiagnostic, VisualFilterResultPayload, VisualFreezeReason, VisualKindOption, VisualPatternOption, VisualLayoutPositions, VisualLayoutRoutes, VisualLayoutSaveResultPayload, VisualResponse, VisualTerminationReason, VisualViewSummary } from './protocol-contract.js';
4
4
  /**
5
5
  * Transport shapes the session server and the browser application both speak.
6
6
  *
@@ -77,6 +77,14 @@ export interface VisualRenderedModel {
77
77
  readonly unfolded: readonly string[];
78
78
  };
79
79
  };
80
+ /**
81
+ * The routes each saved layout was drawing (ADR 0147), keyed by projection
82
+ * id. A sibling of `layouts` for the reason `folds` is: a layout entry is
83
+ * positions, and widening it would reach every reader of it.
84
+ */
85
+ readonly routes?: {
86
+ readonly [projectionId: string]: VisualLayoutRoutes;
87
+ };
80
88
  /**
81
89
  * Which subject fills which slot of which instance (ADR 0131), and which
82
90
  * slots nothing fills (#447), forwarded so the browser can draw containment
@@ -55,7 +55,12 @@ export interface ConceptNotation extends ShapeMeta {
55
55
  }
56
56
  export declare const CONCEPT_NOTATION: readonly ConceptNotation[];
57
57
  export declare function conceptNotationOf(kindLabel: string): ConceptNotation | null;
58
- export declare function kindGlyphDataUriOf(kindLabel: string): string | null;
58
+ /**
59
+ * The glyph as a data URI, drawn in `ink` - the notation's own by default, or
60
+ * the light stroke a dark ground needs (ADR 0148). The stroke is the only
61
+ * thing that varies; the strokes themselves are the notation's.
62
+ */
63
+ export declare function kindGlyphDataUriOf(kindLabel: string, ink?: string): string | null;
59
64
  export interface ArrowNotation {
60
65
  readonly shape: 'none' | 'diamond' | 'triangle' | 'circle' | 'vee';
61
66
  readonly fill?: 'filled' | 'hollow';
@@ -38,10 +38,10 @@ export const ASPECT_SHAPES = {
38
38
  const KIND_SHAPE_OVERRIDES = {
39
39
  grouping: { borderStyle: 'dashed' },
40
40
  };
41
- function svg(body) {
41
+ function svg(body, ink = INK) {
42
42
  return (`<svg xmlns="http://www.w3.org/2000/svg" width="${ICON_SIZE}" height="${ICON_SIZE}" ` +
43
43
  `viewBox="0 0 ${ICON_SIZE} ${ICON_SIZE}">` +
44
- `<g fill="none" stroke="${INK}" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">${body}</g>` +
44
+ `<g fill="none" stroke="${ink}" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">${body}</g>` +
45
45
  `</svg>`);
46
46
  }
47
47
  function toDataUri(svgMarkup) {
@@ -205,9 +205,14 @@ const CONCEPT_NOTATION_BY_ID = Object.fromEntries(CONCEPT_NOTATION.map((row) =>
205
205
  export function conceptNotationOf(kindLabel) {
206
206
  return CONCEPT_NOTATION_BY_ID[kindLabel] ?? null;
207
207
  }
208
- export function kindGlyphDataUriOf(kindLabel) {
208
+ /**
209
+ * The glyph as a data URI, drawn in `ink` - the notation's own by default, or
210
+ * the light stroke a dark ground needs (ADR 0148). The stroke is the only
211
+ * thing that varies; the strokes themselves are the notation's.
212
+ */
213
+ export function kindGlyphDataUriOf(kindLabel, ink = INK) {
209
214
  const glyph = CONCEPT_NOTATION_BY_ID[kindLabel]?.glyph;
210
- return glyph == null ? null : toDataUri(svg(glyph));
215
+ return glyph == null ? null : toDataUri(svg(glyph, ink));
211
216
  }
212
217
  // The 11 rows from `graph-canvas.tsx`'s ArchiMate edge selectors (Task 11).
213
218
  const RELATIONSHIP_STYLE = {