sysml-diagram 0.20.3 → 0.21.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/out/main.js CHANGED
@@ -162498,8 +162498,37 @@ function disjointTargets(node) {
162498
162498
  return out;
162499
162499
  }
162500
162500
  var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
162501
+ shared;
162501
162502
  perParseCache = /* @__PURE__ */ new WeakMap();
162502
162503
  featurePaths = new FeaturePathResolver();
162504
+ annotationFeaturePaths = /* @__PURE__ */ new Map();
162505
+ indexEpoch = 0;
162506
+ // REQ-210 — Annotation graphics
162507
+ // Shared services are optional so pure single-document tests stay cheap. In
162508
+ // production they provide both workspace documents and the linker's private
162509
+ // lazy library documents used by inherited members.
162510
+ constructor(shared) {
162511
+ this.shared = shared;
162512
+ shared?.workspace.DocumentBuilder.onBuildPhase(DocumentState.IndexedContent, () => {
162513
+ this.indexEpoch += 1;
162514
+ });
162515
+ }
162516
+ externalDocumentRoot(uri) {
162517
+ if (!this.shared)
162518
+ return void 0;
162519
+ const parsed = URI2.parse(uri);
162520
+ try {
162521
+ const services = this.shared.ServiceRegistry.getServices(parsed);
162522
+ const linker = services.references.Linker;
162523
+ const linked = linker.resolveDocumentRoot?.(parsed);
162524
+ if (linked)
162525
+ return linked;
162526
+ } catch {
162527
+ }
162528
+ if (!this.shared.workspace.LangiumDocuments.hasDocument(parsed))
162529
+ return void 0;
162530
+ return this.shared.workspace.LangiumDocuments.getDocument(parsed)?.parseResult?.value;
162531
+ }
162503
162532
  perParse(root4) {
162504
162533
  let entry = this.perParseCache.get(root4);
162505
162534
  if (!entry) {
@@ -162528,12 +162557,52 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
162528
162557
  const key = `${kind}\0${preferFileOverview ? "F" : "-"}\0${rootSymbol ?? ""}`;
162529
162558
  const cacheKey = kind === "grv" ? `${key}::${gridPreset}${gridPreset === "matrix" ? `::${matrixRelationship}` : ""}` : key;
162530
162559
  const hit = cache.models.get(cacheKey);
162560
+ if (hit && hit.indexEpoch === this.indexEpoch && this.externalRootsAreCurrent(hit.externalRoots))
162561
+ return hit.model;
162531
162562
  if (hit)
162532
- return hit;
162563
+ cache.models.delete(cacheKey);
162533
162564
  const model = this.computeDiagramModel(document2, root4, rootSymbol, kind, preferFileOverview, gridPreset, matrixRelationship);
162534
- cache.models.set(cacheKey, model);
162565
+ cache.models.set(cacheKey, {
162566
+ model,
162567
+ externalRoots: this.externalRootsOf(model, document2.uri.toString()),
162568
+ indexEpoch: this.indexEpoch
162569
+ });
162535
162570
  return model;
162536
162571
  }
162572
+ // REQ-210 — Annotation graphics
162573
+ // A model may project members and notes from another document. The anchor's
162574
+ // parse identity does not change when that source file is edited, so validate
162575
+ // those dependency roots before returning a warm per-anchor cache entry.
162576
+ externalRootsAreCurrent(roots) {
162577
+ for (const [uri, root4] of roots) {
162578
+ if (this.externalDocumentRoot(uri) !== root4)
162579
+ return false;
162580
+ }
162581
+ return true;
162582
+ }
162583
+ externalRootsOf(model, anchorUri) {
162584
+ const uris = /* @__PURE__ */ new Set();
162585
+ const add = (source) => {
162586
+ if (source?.uri && source.uri !== anchorUri)
162587
+ uris.add(source.uri);
162588
+ };
162589
+ for (const node of model.nodes) {
162590
+ add(node.source);
162591
+ for (const port of node.ports ?? [])
162592
+ add(port.source);
162593
+ }
162594
+ for (const frame2 of model.frames ?? []) {
162595
+ add(frame2.source);
162596
+ for (const port of frame2.ports ?? [])
162597
+ add(port.source);
162598
+ }
162599
+ add(model.ivBoundary?.source);
162600
+ for (const port of model.ivBoundary?.ports ?? [])
162601
+ add(port.source);
162602
+ for (const edge of model.edges)
162603
+ add(edge.source);
162604
+ return new Map([...uris].map((uri) => [uri, this.externalDocumentRoot(uri)]));
162605
+ }
162537
162606
  computeDiagramModel(document2, root4, rootSymbol, kind, preferFileOverview, gridPreset = "requirements", matrixRelationship = "allocation") {
162538
162607
  const uri = document2.uri.toString();
162539
162608
  const empty2 = (note) => ({
@@ -162549,28 +162618,126 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
162549
162618
  return empty2(`No anchor element found for the ${kind.toUpperCase()} view.`);
162550
162619
  const ctx = { uri, index: index2, anchor, gridPreset, matrixRelationship };
162551
162620
  const overview = isPackage(anchor) || isDocument(anchor);
162552
- switch (kind) {
162553
- case "gv":
162554
- return this.buildGeneralView(ctx);
162555
- case "iv":
162556
- return overview ? this.buildInterconnectionOverview(ctx) : this.buildInterconnectionView(ctx);
162557
- case "afv":
162558
- return overview ? this.buildActionFlowOverview(ctx) : this.buildActionFlowView(ctx);
162559
- case "stv":
162560
- return overview ? this.buildStateTransitionOverview(ctx) : this.buildStateTransitionView(ctx);
162561
- case "sv":
162562
- return overview ? this.buildSequenceOverview(ctx) : this.buildSequenceView(ctx);
162563
- case "cv":
162564
- return this.buildCaseView(ctx);
162565
- case "gev":
162566
- return overview ? this.buildGeometryOverview(ctx) : this.buildGeometryView(ctx);
162567
- case "grv":
162568
- return this.buildGridView(ctx);
162569
- case "bv":
162570
- return this.buildBrowserView(ctx);
162571
- default:
162572
- return empty2(`Unsupported diagram kind ${kind}.`);
162621
+ const build = () => {
162622
+ switch (kind) {
162623
+ case "gv":
162624
+ return this.buildGeneralView(ctx);
162625
+ case "iv":
162626
+ return overview ? this.buildInterconnectionOverview(ctx) : this.buildInterconnectionView(ctx);
162627
+ case "afv":
162628
+ return overview ? this.buildActionFlowOverview(ctx) : this.buildActionFlowView(ctx);
162629
+ case "stv":
162630
+ return overview ? this.buildStateTransitionOverview(ctx) : this.buildStateTransitionView(ctx);
162631
+ case "sv":
162632
+ return overview ? this.buildSequenceOverview(ctx) : this.buildSequenceView(ctx);
162633
+ case "cv":
162634
+ return this.buildCaseView(ctx);
162635
+ case "gev":
162636
+ return overview ? this.buildGeometryOverview(ctx) : this.buildGeometryView(ctx);
162637
+ case "grv":
162638
+ return this.buildGridView(ctx);
162639
+ case "bv":
162640
+ return this.buildBrowserView(ctx);
162641
+ default:
162642
+ return empty2(`Unsupported diagram kind ${kind}.`);
162643
+ }
162644
+ };
162645
+ return this.withNotes(build(), root4, index2, uri);
162646
+ }
162647
+ // REQ-210 — Annotation graphics
162648
+ // issue #229: attach the modeled notes of every DRAWN element to that
162649
+ // element, on every view.
162650
+ //
162651
+ // The General View builds its own richer annotation pass (comment + rep +
162652
+ // metadata, with package placement), the Browser View lists annotations as
162653
+ // tree rows, and the Grid View is a table, so all three are left untouched.
162654
+ // Every other view gets its notes here, once, after the builder (and its
162655
+ // overview tiling / id prefixing) has settled the final node ids.
162656
+ //
162657
+ // A `comment` is always a note. A `doc` documents its owner and already has
162658
+ // a textual home in that owner's `doc` compartment (issue #107), so it only
162659
+ // becomes a note on the views that draw no compartments at all.
162660
+ withNotes(model, root4, index2, uri) {
162661
+ if (model.kind === "gv" || model.kind === "bv" || model.kind === "grv")
162662
+ return model;
162663
+ const docAsNote = model.kind === "sv" || model.kind === "gev";
162664
+ const drawn = /* @__PURE__ */ new Map();
162665
+ const externalUris = /* @__PURE__ */ new Set();
162666
+ const key = (source) => source && `${source.uri}:${source.range.start.line}:${source.range.start.character}`;
162667
+ const claim = (source, target) => {
162668
+ const k = key(source);
162669
+ if (!k)
162670
+ return;
162671
+ if (source && source.uri !== uri)
162672
+ externalUris.add(source.uri);
162673
+ const list = drawn.get(k);
162674
+ if (list)
162675
+ list.push(target);
162676
+ else
162677
+ drawn.set(k, [target]);
162678
+ };
162679
+ for (const n2 of model.nodes) {
162680
+ claim(n2.source, { id: n2.id, parent: n2.parent, frame: n2.frame });
162681
+ for (const port of n2.ports ?? []) {
162682
+ claim(port.source, { id: port.id, parent: n2.parent, frame: n2.frame, port: true });
162683
+ }
162684
+ }
162685
+ for (const f of model.frames ?? []) {
162686
+ claim(f.source, { id: f.id, frame: f.id });
162687
+ for (const port of f.ports ?? []) {
162688
+ claim(port.source, { id: port.id, frame: f.id, port: true });
162689
+ }
162690
+ }
162691
+ if (model.ivBoundary) {
162692
+ claim(model.ivBoundary.source, { id: model.ivBoundary.id, frame: model.ivBoundary.id });
162693
+ for (const port of model.ivBoundary.ports ?? []) {
162694
+ claim(port.source, { id: port.id, frame: model.ivBoundary.id, port: true });
162695
+ }
162696
+ }
162697
+ if (!drawn.size)
162698
+ return model;
162699
+ const nodes = [...model.nodes];
162700
+ const edges = [...model.edges];
162701
+ let noteCount = 0;
162702
+ let edgeCount = edges.length;
162703
+ const note = (annotation) => {
162704
+ const targets = drawn.get(key(sourceOf2(annotation.owner, uri)) ?? "")?.filter((target) => annotation.keyword !== "doc" || docAsNote || target.port);
162705
+ if (!targets?.length)
162706
+ return;
162707
+ for (const target of targets) {
162708
+ const id2 = `__note_${noteCount++}__`;
162709
+ nodes.push({
162710
+ id: id2,
162711
+ name: annotation.label,
162712
+ keyword: annotation.keyword,
162713
+ isDef: false,
162714
+ shape: "annotation",
162715
+ type: annotation.body,
162716
+ // Sit in the same container as the element the note is about,
162717
+ // so the note travels with it instead of floating at the root.
162718
+ ...target.parent ? { parent: target.parent } : {},
162719
+ ...target.frame ? { frame: target.frame } : {},
162720
+ source: sourceOf2(annotation.annotation, uri)
162721
+ });
162722
+ edges.push({
162723
+ id: `e${edgeCount++}`,
162724
+ from: id2,
162725
+ to: target.id,
162726
+ kind: "annotation",
162727
+ source: sourceOf2(annotation.annotation, uri)
162728
+ });
162729
+ }
162730
+ };
162731
+ for (const annotation of this.semanticAnnotations(root4, index2))
162732
+ note(annotation);
162733
+ for (const externalUri of externalUris) {
162734
+ const externalRoot = this.externalDocumentRoot(externalUri);
162735
+ if (externalRoot) {
162736
+ for (const annotation of this.semanticAnnotations(externalRoot, this.localIndex(externalRoot)))
162737
+ note(annotation);
162738
+ }
162573
162739
  }
162740
+ return noteCount ? { ...model, nodes, edges } : model;
162574
162741
  }
162575
162742
  // REQ-224 — Detect the file/anchor-specific view kinds that will render
162576
162743
  // substantive diagram content. The extension uses this to limit the
@@ -162649,6 +162816,132 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
162649
162816
  cache.contents = contents;
162650
162817
  return contents;
162651
162818
  }
162819
+ // REQ-210 — Annotation graphics
162820
+ // Keep the whole-document filter out of each view build. Target resolution
162821
+ // remains live because the workspace index can become more complete without
162822
+ // reparsing the document.
162823
+ annotationMembers(root4) {
162824
+ const cache = this.perParse(root4);
162825
+ if (cache.annotations)
162826
+ return cache.annotations;
162827
+ const comments = [];
162828
+ const docs = [];
162829
+ for (const node of [root4, ...this.rootContents(root4)]) {
162830
+ if (node.$type === "CommentStmt")
162831
+ comments.push(node);
162832
+ else if (node.$type === "DocCommentMember")
162833
+ docs.push(node);
162834
+ }
162835
+ cache.annotations = { comments, docs };
162836
+ return cache.annotations;
162837
+ }
162838
+ // REQ-210 — Annotation graphics
162839
+ // Resolve a document's modeled annotations once for every workspace-index
162840
+ // epoch. Different diagram kinds then only match semantic owners to their
162841
+ // rendered source identities instead of walking and resolving the AST again.
162842
+ semanticAnnotations(root4, index2) {
162843
+ const cache = this.perParse(root4);
162844
+ if (cache.semanticAnnotations?.epoch === this.indexEpoch)
162845
+ return cache.semanticAnnotations.values;
162846
+ const members = this.annotationMembers(root4);
162847
+ const values2 = [];
162848
+ for (const comment of members.comments) {
162849
+ const rawTargets = comment.targets ?? [];
162850
+ const owners = rawTargets.length ? this.commentTargets(comment, index2) : [comment.$container];
162851
+ for (const owner of owners) {
162852
+ if (!owner)
162853
+ continue;
162854
+ values2.push({
162855
+ annotation: comment,
162856
+ owner,
162857
+ keyword: "comment",
162858
+ label: nameOf2(comment) ?? "comment",
162859
+ body: annotationText(trailingBlockBody(comment))
162860
+ });
162861
+ }
162862
+ }
162863
+ for (const doc of members.docs) {
162864
+ if (!doc.$container)
162865
+ continue;
162866
+ values2.push({
162867
+ annotation: doc,
162868
+ owner: doc.$container,
162869
+ keyword: "doc",
162870
+ label: nameOf2(doc) ?? "doc",
162871
+ body: annotationText(docCommentBody(doc))
162872
+ });
162873
+ }
162874
+ cache.semanticAnnotations = { epoch: this.indexEpoch, values: values2 };
162875
+ return values2;
162876
+ }
162877
+ annotationPathResolver(node) {
162878
+ if (!this.shared)
162879
+ return this.featurePaths;
162880
+ try {
162881
+ const services = this.shared.ServiceRegistry.getServices(ast_utils_exports.getDocument(node).uri);
162882
+ let resolver = this.annotationFeaturePaths.get(services);
162883
+ if (!resolver) {
162884
+ resolver = new FeaturePathResolver(services);
162885
+ this.annotationFeaturePaths.set(services, resolver);
162886
+ }
162887
+ return resolver;
162888
+ } catch {
162889
+ return this.featurePaths;
162890
+ }
162891
+ }
162892
+ annotationDescriptionNode(context, description) {
162893
+ if (!description)
162894
+ return void 0;
162895
+ if (!this.shared)
162896
+ return description.node;
162897
+ try {
162898
+ const services = this.shared.ServiceRegistry.getServices(ast_utils_exports.getDocument(context).uri);
162899
+ const linker = services.references.Linker;
162900
+ return linker.resolveIndexedNode?.(description) ?? description.node;
162901
+ } catch {
162902
+ return description.node;
162903
+ }
162904
+ }
162905
+ // REQ-210 — Annotation graphics
162906
+ /** Resolve every `comment about` target by semantic path identity. */
162907
+ commentTargets(comment, index2) {
162908
+ const rawTargets = comment.targets ?? [];
162909
+ if (!rawTargets.length)
162910
+ return [];
162911
+ const root4 = this.documentRootOf(comment);
162912
+ const all = [root4, ...this.rootContents(root4)];
162913
+ const resolver = this.annotationPathResolver(comment);
162914
+ const resolved = rawTargets.map((raw, occurrence) => {
162915
+ const segment = resolver.resolvePropertyPath(comment, "targets", occurrence).segments.at(-1);
162916
+ const linked = segment?.target ?? this.annotationDescriptionNode(comment, segment?.description);
162917
+ if (linked)
162918
+ return linked;
162919
+ const path10 = this.featurePath(raw)?.trim();
162920
+ if (!path10)
162921
+ return void 0;
162922
+ const unrooted = path10.replace(/^\s*\$\s*::\s*/u, "");
162923
+ if (!/::|\./u.test(unrooted)) {
162924
+ for (let scope = comment.$container; scope; scope = scope.$container) {
162925
+ const local = membersOf(scope).find((member) => member !== comment && nameOf2(member) === unrooted);
162926
+ if (local)
162927
+ return local;
162928
+ const declaringIndex = this.localIndex(this.documentRootOf(scope));
162929
+ for (const inherited of this.inheritedTypesOf(scope, declaringIndex)) {
162930
+ const inheritedMember = membersOf(inherited).find((member) => nameOf2(member) === unrooted);
162931
+ if (inheritedMember)
162932
+ return inheritedMember;
162933
+ }
162934
+ }
162935
+ return index2.get(unrooted);
162936
+ }
162937
+ const qualified = all.filter((candidate) => {
162938
+ const qname = qnameOf(candidate);
162939
+ return qname.length > 0 && pathMatchesQName(unrooted, qname);
162940
+ });
162941
+ return qualified.length === 1 ? qualified[0] : void 0;
162942
+ }).filter((target) => target !== void 0);
162943
+ return [...new Set(resolved)];
162944
+ }
162652
162945
  // REQ-192/REQ-193 — prefer Langium's linked typing target. The diagram's
162653
162946
  // local index deliberately contains only the active document, so consulting
162654
162947
  // it alone drops structure declared in an imported workspace/library file
@@ -163723,8 +164016,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
163723
164016
  }
163724
164017
  }
163725
164018
  let annotationCount = 0;
163726
- const annotate = (m, keyword, label, detail, target) => {
163727
- const owner = target ?? m.$container;
164019
+ const annotate = (m, keyword, label, detail, targets) => {
163728
164020
  const annId = `__annotation_${annotationCount++}__`;
163729
164021
  nodes.push({
163730
164022
  id: annId,
@@ -163736,17 +164028,33 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
163736
164028
  ...packageOf2(m),
163737
164029
  source: sourceOf2(m, uri)
163738
164030
  });
163739
- if (owner && ids.has(owner)) {
163740
- edges.push({ id: `e${e++}`, from: annId, to: ids.get(owner), kind: "annotation", source: sourceOf2(m, uri) });
164031
+ const owners = targets?.length ? targets : m.$container ? [m.$container] : [];
164032
+ for (const owner of new Set(owners)) {
164033
+ if (!ids.has(owner))
164034
+ continue;
164035
+ edges.push({
164036
+ id: `e${e++}`,
164037
+ from: annId,
164038
+ to: ids.get(owner),
164039
+ kind: "annotation",
164040
+ source: sourceOf2(m, uri)
164041
+ });
164042
+ }
164043
+ };
164044
+ const drawnAnnotationTarget = (target) => {
164045
+ for (let current2 = target; current2; current2 = current2.$container) {
164046
+ if (ids.has(current2))
164047
+ return current2;
163741
164048
  }
164049
+ return void 0;
163742
164050
  };
163743
164051
  for (const m of all) {
163744
164052
  if (m.$type === "CommentStmt") {
163745
- const targets = m.targets ?? [];
163746
- const target = targets.length ? byName.get(lastSeg(String(this.featurePath(targets[0]) ?? ""))) : void 0;
163747
- if (targets.length && !target)
164053
+ const rawTargets = m.targets ?? [];
164054
+ const targets = rawTargets.length ? this.commentTargets(m, index2).map(drawnAnnotationTarget).filter((target) => target !== void 0) : void 0;
164055
+ if (rawTargets.length && !targets?.length)
163748
164056
  continue;
163749
- annotate(m, "comment", nameOf2(m) ?? "comment", annotationText(trailingBlockBody(m)), target);
164057
+ annotate(m, "comment", nameOf2(m) ?? "comment", annotationText(trailingBlockBody(m)), targets);
163750
164058
  } else if (m.$type === "RepStmt") {
163751
164059
  const lang = `language "${String(m.language ?? "")}"`;
163752
164060
  const body = annotationText(trailingBlockBody(m));
@@ -163757,7 +164065,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
163757
164065
  continue;
163758
164066
  const body = annotationText(docCommentBody(m));
163759
164067
  if (body)
163760
- annotate(m, "doc", nameOf2(m) ?? "doc", body, owner);
164068
+ annotate(m, "doc", nameOf2(m) ?? "doc", body, owner ? [owner] : void 0);
163761
164069
  } else if (isMetadataDecl(m) && m.isDef !== true && (nameOf2(m) || typeText(m)) && !ids.has(m)) {
163762
164070
  const attrs = metadataAttrsText(m);
163763
164071
  const detail = typeText(m) ? `${typeText(m)}${attrs ? ` { ${attrs} }` : ""}` : attrs;
@@ -178003,6 +178311,20 @@ var SysmlLinker = class extends DefaultLinker {
178003
178311
  resolveIndexedNode(nodeDescription) {
178004
178312
  return this.loadAstNode(nodeDescription);
178005
178313
  }
178314
+ // REQ-210 — Annotation graphics
178315
+ /**
178316
+ * Return the parsed root for a live workspace or lazily loaded library file.
178317
+ * Diagram projection uses this to collect annotations declared beside an
178318
+ * inherited member without adding standard-library files to the workspace.
178319
+ */
178320
+ resolveDocumentRoot(uri) {
178321
+ const live = this.langiumDocuments().getDocument(uri)?.parseResult?.value;
178322
+ if (live)
178323
+ return live;
178324
+ if (!isStandardLibraryUri(uri))
178325
+ return void 0;
178326
+ return this.parsedLibraryDocument(uri)?.parseResult?.value;
178327
+ }
178006
178328
  /** Parse (once) the standard-library file a precomputed description points at.
178007
178329
  * Prefers an already-live workspace document when one exists (runtime-loaded
178008
178330
  * library, or the user opened the file) so there is never a second copy. */
@@ -182200,6 +182522,7 @@ function portLabelPlacement(side, x, y, label, half = PORT_GLYPH_HALF, alongHalf
182200
182522
  }
182201
182523
  var SEQ_MSG_TOP = 76;
182202
182524
  var SEQ_MSG_GAP = 46;
182525
+ var SEQ_NOTE_GAP = 40;
182203
182526
  function sequenceSlotBoundaryY(slot) {
182204
182527
  return SEQ_MSG_TOP + (slot - 0.5) * SEQ_MSG_GAP;
182205
182528
  }
@@ -182298,6 +182621,12 @@ function gvNodeCategory(node) {
182298
182621
  };
182299
182622
  return alias[k] ?? "other";
182300
182623
  }
182624
+ function withoutOrphanedAnnotations(original, nodes, edges) {
182625
+ const originallyAttached = new Set(original.edges.filter((edge) => edge.kind === "annotation").map((edge) => edge.from));
182626
+ if (originallyAttached.size === 0) return nodes;
182627
+ const stillAttached = new Set(edges.filter((edge) => edge.kind === "annotation").map((edge) => edge.from));
182628
+ return nodes.filter((node) => node.shape !== "annotation" || !originallyAttached.has(node.id) || stillAttached.has(node.id));
182629
+ }
182301
182630
  function applyGvFilters(model, hidden) {
182302
182631
  if (model.kind !== "gv" || hidden.size === 0) return model;
182303
182632
  const nodes = model.nodes.filter((n2) => n2.shape === "package" || !hidden.has(gvNodeCategory(n2)));
@@ -182308,7 +182637,7 @@ function applyGvFilters(model, hidden) {
182308
182637
  for (const p of n2.ports ?? []) keptIds.add(p.id);
182309
182638
  }
182310
182639
  const edges = model.edges.filter((e) => keptIds.has(e.from) && keptIds.has(e.to));
182311
- return { ...model, nodes, edges };
182640
+ return { ...model, nodes: withoutOrphanedAnnotations(model, nodes, edges), edges };
182312
182641
  }
182313
182642
  var PAD = 10;
182314
182643
  var NODE_W = 168;
@@ -182805,9 +183134,10 @@ function applyCaseDefs(model, show) {
182805
183134
  if (hidden.size === 0) return model;
182806
183135
  const edges = model.edges.filter((e) => !hidden.has(e.from) && !hidden.has(e.to));
182807
183136
  const retainedEndpoints = new Set(edges.flatMap((edge) => [edge.from, edge.to]));
183137
+ const nodes = model.nodes.filter((n2) => !hidden.has(n2.id) && (n2.meta?.cvAuxiliary !== true || retainedEndpoints.has(n2.id)));
182808
183138
  return {
182809
183139
  ...model,
182810
- nodes: model.nodes.filter((n2) => !hidden.has(n2.id) && (n2.meta?.cvAuxiliary !== true || retainedEndpoints.has(n2.id))),
183140
+ nodes: withoutOrphanedAnnotations(model, nodes, edges),
182811
183141
  edges
182812
183142
  };
182813
183143
  }
@@ -182887,7 +183217,7 @@ function applyBehaviorFilters(model, filters) {
182887
183217
  ...nextFrames.flatMap((f) => (f.ports ?? []).map((p) => p.id))
182888
183218
  ]);
182889
183219
  const edges = model.edges.filter((e) => !(model.kind === "afv" && !filters.definedBy && e.kind === "definedBy") && !hiddenPortIds.has(e.from) && !hiddenPortIds.has(e.to) && liveIds.has(e.from) && liveIds.has(e.to));
182890
- return { ...model, frames: nextFrames, nodes, edges };
183220
+ return { ...model, frames: nextFrames, nodes: withoutOrphanedAnnotations(model, nodes, edges), edges };
182891
183221
  }
182892
183222
  function collapseIvModel(model, hiddenInternals) {
182893
183223
  const frames = model.frames ?? [];
@@ -183496,6 +183826,7 @@ var GEO_TARGET_H = 520;
183496
183826
  var GEO_DEF_W = 400;
183497
183827
  var GEO_DEF_H = 300;
183498
183828
  var GEO_STRIP_GAP = 16;
183829
+ var GEO_STRIP_INSET = 16;
183499
183830
  var GEO_FRAME_ID = "__geoframe__";
183500
183831
  var GEO_EMPTY_W = 560;
183501
183832
  var GEO_EMPTY_H = 320;
@@ -183564,7 +183895,7 @@ function layoutGeometry(nodes, edges, meta) {
183564
183895
  const frame2 = makeGeoFrameNode(kind, GEO_EMPTY_W, GEO_EMPTY_H, {
183565
183896
  geoEmpty: { hLabel: axes.h ?? "x", vLabel: axes.v ?? "z", unit }
183566
183897
  });
183567
- placeStrip(strip, GEO_MARGIN_LEFT + 16, GEO_EMPTY_H + GEO_STRIP_GAP);
183898
+ placeStrip(strip, GEO_MARGIN_LEFT + GEO_STRIP_INSET, GEO_EMPTY_H + GEO_STRIP_GAP);
183568
183899
  return { nodes: [frame2, ...strip], edges };
183569
183900
  }
183570
183901
  const is3d = placed.some((n2) => n2.data.node.geo.shape !== void 0 || n2.data.node.geo.z !== void 0);
@@ -195490,13 +195821,18 @@ var SEQ_EVENT_GAP = 22;
195490
195821
  function layoutSequence(nodes, edges, overrides) {
195491
195822
  const ov = overrides ?? {};
195492
195823
  const lifelines = nodes.filter((n2) => n2.data.node?.shape === "lifeline").sort((a2, b) => Number(a2.data.node?.meta?.order ?? 0) - Number(b.data.node?.meta?.order ?? 0));
195824
+ const lifelineIds = new Set(lifelines.map((n2) => n2.id));
195825
+ const noteNodes = nodes.filter((n2) => n2.data.node?.shape === "annotation");
195826
+ const isMessage = (edge) => edge.data?.edge.kind === "message" && lifelineIds.has(edge.source) && lifelineIds.has(edge.target);
195827
+ const nonMessageEdges = edges.filter((edge) => !isMessage(edge));
195828
+ const msgs = edges.filter(isMessage);
195493
195829
  const slotFor = (e, i) => {
195494
195830
  const s = e.data?.edge.meta?.slot;
195495
195831
  return typeof s === "number" && Number.isFinite(s) && s >= 0 ? s : i;
195496
195832
  };
195497
- const msgY = edges.map((e, i) => MSG_TOP + slotFor(e, i) * MSG_GAP);
195498
- const lastMsgY = edges.length ? Math.max(...msgY) : MSG_TOP;
195499
- let maxSlot = edges.length ? Math.max(...edges.map(slotFor)) : -1;
195833
+ const msgY = msgs.map((e, i) => MSG_TOP + slotFor(e, i) * MSG_GAP);
195834
+ const lastMsgY = msgs.length ? Math.max(...msgY) : MSG_TOP;
195835
+ let maxSlot = msgs.length ? Math.max(...msgs.map(slotFor)) : -1;
195500
195836
  const eventBase = lastMsgY + 22;
195501
195837
  let maxEventY = 0;
195502
195838
  const eventsByLifeline = /* @__PURE__ */ new Map();
@@ -195519,7 +195855,7 @@ function layoutSequence(nodes, edges, overrides) {
195519
195855
  baseX.push(cursorX);
195520
195856
  cursorX += n2.data.w + LIFELINE_MIN_GAP;
195521
195857
  }
195522
- const msgHandles = edges.map((_edge, i) => ({ id: `m${i}`, y: msgY[i] }));
195858
+ const msgHandles = msgs.map((_edge, i) => ({ id: `m${i}`, y: msgY[i] }));
195523
195859
  const insertHandles = Array.from({ length: Math.max(maxSlot, -1) + 2 }, (_2, k) => ({
195524
195860
  id: `d${k}`,
195525
195861
  y: sequenceSlotBoundaryY(k),
@@ -195530,7 +195866,7 @@ function layoutSequence(nodes, edges, overrides) {
195530
195866
  const w = n2.data.w;
195531
195867
  const x = overrideFor(n2, ov)?.x ?? baseX[i];
195532
195868
  xOf.set(n2.id, x + w / 2);
195533
- const ys = edges.map((e, idx) => e.source === n2.id || e.target === n2.id ? msgY[idx] : void 0).filter((y) => y != null);
195869
+ const ys = msgs.map((e, idx) => e.source === n2.id || e.target === n2.id ? msgY[idx] : void 0).filter((y) => y != null);
195534
195870
  const activation = ys.length ? { from: Math.min(...ys) - 6, to: Math.max(...ys) + 6 } : void 0;
195535
195871
  return {
195536
195872
  ...n2,
@@ -195549,7 +195885,7 @@ function layoutSequence(nodes, edges, overrides) {
195549
195885
  draggable: true
195550
195886
  };
195551
195887
  });
195552
- const outEdges = edges.map((e, i) => {
195888
+ const outEdges = msgs.map((e, i) => {
195553
195889
  const y = msgY[i];
195554
195890
  return {
195555
195891
  ...e,
@@ -195586,7 +195922,21 @@ function layoutSequence(nodes, edges, overrides) {
195586
195922
  const h = Math.max(40, bottom - top);
195587
195923
  return { ...n2, position: { x: left, y: top }, width: w, height: h, data: { ...n2.data, w, h }, zIndex: 0 };
195588
195924
  });
195589
- return { nodes: [...fragmentNodes, ...out], edges: outEdges, height: bodyH };
195925
+ const noteX = out.length ? Math.max(...out.map((node) => node.position.x + (node.width ?? node.data.w))) + SEQ_NOTE_GAP : 20 + SEQ_NOTE_GAP;
195926
+ let noteY = MSG_TOP;
195927
+ const placedNotes = noteNodes.map((n2) => {
195928
+ const o = overrideFor(n2, ov);
195929
+ const y = o?.y ?? noteY;
195930
+ noteY = Math.max(noteY, y + n2.data.h + SEQ_NOTE_GAP);
195931
+ return { ...n2, position: { x: o?.x ?? noteX, y }, draggable: true };
195932
+ });
195933
+ const sequenceNodes = [...fragmentNodes, ...out, ...placedNotes];
195934
+ assignEdgeSides(sequenceNodes, nonMessageEdges);
195935
+ return {
195936
+ nodes: sequenceNodes,
195937
+ edges: [...outEdges, ...nonMessageEdges],
195938
+ height: Math.max(bodyH, noteY)
195939
+ };
195590
195940
  }
195591
195941
  var TILE_PAD = 22;
195592
195942
  var TILE_HEADER = 38;
@@ -195650,7 +196000,12 @@ async function layoutTiledOverview(model, nodes, edges, args) {
195650
196000
  }));
195651
196001
  const localOverrides = overrideSubset(members, args.overrides);
195652
196002
  const meta = tileMeta[frame2.id];
195653
- const laidPromise = model.kind === "sv" ? Promise.resolve(layoutSequence(detached, tileEdges, localOverrides)) : model.kind === "gev" ? Promise.resolve(layoutGeometry(detached, tileEdges, meta ?? model.meta)) : layoutFlow(detached, tileEdges, {
196003
+ const laidPromise = model.kind === "sv" ? Promise.resolve(layoutSequence(detached, tileEdges, localOverrides)) : model.kind === "gev" ? Promise.resolve(layoutGeometryWithAnnotationEdges(
196004
+ detached,
196005
+ tileEdges,
196006
+ meta ?? model.meta,
196007
+ args.connectPointSpacing
196008
+ )) : layoutFlow(detached, tileEdges, {
195654
196009
  ...args,
195655
196010
  overrides: localOverrides,
195656
196011
  kind: args.kind ?? model.kind,
@@ -196104,13 +196459,25 @@ async function layoutBands(nodes, edges, overrides, direction = "TB", connectPoi
196104
196459
  assignEdgeSides(all, edges, false, connectPointSpacing);
196105
196460
  return { nodes: all, edges };
196106
196461
  }
196462
+ function layoutGeometryWithAnnotationEdges(nodes, edges, meta, connectPointSpacing = CONNECT_POINT_SPACING_DEFAULT) {
196463
+ const laid = layoutGeometry(nodes, edges, meta);
196464
+ assignEdgeSides(
196465
+ laid.nodes,
196466
+ laid.edges.filter((edge) => edge.data?.edge.kind === "annotation"),
196467
+ false,
196468
+ connectPointSpacing
196469
+ );
196470
+ return laid;
196471
+ }
196107
196472
  async function layoutDiagram(model, nodes, edges, args) {
196108
196473
  const { kind, direction, overrides, connectPointSpacing } = args;
196109
196474
  if (model.meta?.groupMode === "tiled-h" || model.meta?.groupMode === "tiled-v") {
196110
196475
  return layoutTiledOverview(model, nodes, edges, { direction, overrides, kind, connectPointSpacing });
196111
196476
  }
196112
196477
  const profile2 = profileFor(kind);
196113
- if (profile2.layout === "geometry") return layoutGeometry(nodes, edges, model.meta);
196478
+ if (profile2.layout === "geometry") {
196479
+ return layoutGeometryWithAnnotationEdges(nodes, edges, model.meta, connectPointSpacing);
196480
+ }
196114
196481
  if (profile2.layout === "sequence") return layoutSequence(nodes, edges, overrides);
196115
196482
  if (kind === "gv" && (args.gvMode ?? "group") === "group") {
196116
196483
  return layoutBands(nodes, edges, overrides, direction, connectPointSpacing);
@@ -198610,7 +198977,7 @@ function getViewState(sc, anchor, kind) {
198610
198977
  }
198611
198978
 
198612
198979
  // src/node-markup.tsx
198613
- var import_react10 = __toESM(require_react(), 1);
198980
+ var import_react11 = __toESM(require_react(), 1);
198614
198981
  var import_server = __toESM(require_server_node(), 1);
198615
198982
 
198616
198983
  // ../extension/src/webview/diagram/flow/context.ts
@@ -198661,7 +199028,7 @@ function useDiagram() {
198661
199028
  }
198662
199029
 
198663
199030
  // ../extension/src/webview/diagram/flow/nodes.tsx
198664
- var import_react8 = __toESM(require_react());
199031
+ var import_react9 = __toESM(require_react());
198665
199032
 
198666
199033
  // ../extension/src/webview/diagram/derive.ts
198667
199034
  function edgeKindLabel(kind) {
@@ -199014,6 +199381,7 @@ var DIRECT_NAME_RE = new RegExp(`^${DIRECT_NAME_SEGMENT}$`);
199014
199381
  var DIRECT_PATH_RE = new RegExp(`^${DIRECT_NAME_SEGMENT}(?:\\.${DIRECT_NAME_SEGMENT})*$`);
199015
199382
  function isWritableRelationEndpoint(endpoint) {
199016
199383
  if (!endpoint) return false;
199384
+ if (endpoint.shape === "annotation") return false;
199017
199385
  if (pseudostateEndpointPath(endpoint.keyword)) return true;
199018
199386
  if (!endpoint.source || /^__flow_\d+__(?:\.|$)/u.test(endpoint.id)) return false;
199019
199387
  if (!endpoint.name.trim() && ["if", "while", "loop", "for"].includes(endpoint.keyword.trim().toLowerCase())) return true;
@@ -199034,6 +199402,7 @@ var TERMINAL_RELATION = "finish";
199034
199402
  function relationToolsForNode(keyword, viewKind, shape) {
199035
199403
  const { base, isDefinition, isDecision } = normalizedElementKeyword(keyword);
199036
199404
  const tools = TOOLBOX[viewKind]?.relations ?? [];
199405
+ if (shape === "annotation") return [];
199037
199406
  if (viewKind === "afv" && ["if", "while", "loop", "for"].includes(base)) {
199038
199407
  return tools.filter((tool) => tool.kind === "terminate");
199039
199408
  }
@@ -199110,6 +199479,12 @@ function relationToolsForNode(keyword, viewKind, shape) {
199110
199479
  var import_react7 = __toESM(require_react());
199111
199480
  var import_jsx_runtime3 = __toESM(require_jsx_runtime());
199112
199481
  var ptStr = (pts) => pts.map((p) => `${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(" ");
199482
+ var GEO_HANDLE_POSITION = {
199483
+ top: Position3.Top,
199484
+ right: Position3.Right,
199485
+ bottom: Position3.Bottom,
199486
+ left: Position3.Left
199487
+ };
199113
199488
  function niceStep(range, target = 5) {
199114
199489
  if (!(range > 0)) return 1;
199115
199490
  const raw = range / target;
@@ -199324,7 +199699,7 @@ function GeoShapeNode({ id: id2, data, selected: selected2 }) {
199324
199699
  const origin = data.origin;
199325
199700
  const iso = data.geo3d && node.geo && origin;
199326
199701
  const approx = node.geo?.approx;
199327
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
199702
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
199328
199703
  "div",
199329
199704
  {
199330
199705
  className: `rf-node rf-geo${selected2 ? " selected" : ""}${approx ? " dgeo-approx" : ""}`,
@@ -199334,19 +199709,38 @@ function GeoShapeNode({ id: id2, data, selected: selected2 }) {
199334
199709
  e.stopPropagation();
199335
199710
  ctx.onContextNode(id2, e.clientX, e.clientY);
199336
199711
  },
199337
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "rf-node-svg", width: w, height: h, style: { overflow: "visible" }, children: [
199338
- iso ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
199339
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("g", { className: `dgeo3d-node${selected2 ? " selected" : ""}`, transform: `translate(${-origin.x},${-origin.y})`, children: geoShapeBody(node, data.geo3d) }),
199340
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { className: "dgeo3d-name", x: w / 2, y: -3, textAnchor: "middle", children: node.name })
199341
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
199342
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { className: `dnode-rect${selected2 ? " selected" : ""}`, x: 0, y: 0, width: w, height: h, rx: node.isDef ? 0 : 12 }),
199343
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { className: "dnode-label", x: w / 2, y: h / 2 + 3, textAnchor: "middle", children: node.name })
199712
+ children: [
199713
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "rf-node-svg", width: w, height: h, style: { overflow: "visible" }, children: [
199714
+ iso ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
199715
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("g", { className: `dgeo3d-node${selected2 ? " selected" : ""}`, transform: `translate(${-origin.x},${-origin.y})`, children: geoShapeBody(node, data.geo3d) }),
199716
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { className: "dgeo3d-name", x: w / 2, y: -3, textAnchor: "middle", children: node.name })
199717
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
199718
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { className: `dnode-rect${selected2 ? " selected" : ""}`, x: 0, y: 0, width: w, height: h, rx: node.isDef ? 0 : 12 }),
199719
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { className: "dnode-label", x: w / 2, y: h / 2 + 3, textAnchor: "middle", children: node.name })
199720
+ ] }),
199721
+ approx ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("text", { className: "dgeo-approx-mark", x: w - 2, y: -3, textAnchor: "end", children: [
199722
+ "\u26A0",
199723
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${node.name}: ${approx}` })
199724
+ ] }) : null
199344
199725
  ] }),
199345
- approx ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("text", { className: "dgeo-approx-mark", x: w - 2, y: -3, textAnchor: "end", children: [
199346
- "\u26A0",
199347
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${node.name}: ${approx}` })
199348
- ] }) : null
199349
- ] })
199726
+ PORT_DOCK_SIDES.flatMap((side) => (data.edgeSideAnchors?.[side] ?? []).map((offset2) => {
199727
+ const point = sidePoint(side, offset2, w, h);
199728
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
199729
+ Handle,
199730
+ {
199731
+ type: "target",
199732
+ id: sideAnchorHandleId(side, offset2),
199733
+ position: GEO_HANDLE_POSITION[side],
199734
+ style: { left: point.x, top: point.y, transform: "translate(-50%,-50%)" },
199735
+ className: "rf-handle rf-handle-side",
199736
+ isConnectable: true,
199737
+ isConnectableStart: false,
199738
+ isConnectableEnd: true
199739
+ },
199740
+ `${side}-${offset2}`
199741
+ );
199742
+ }))
199743
+ ]
199350
199744
  }
199351
199745
  );
199352
199746
  }
@@ -199475,8 +199869,8 @@ function mountedNodeSidePointOffsets(data, side, connectable, exposeAll) {
199475
199869
  function useMountedHandleRegistration(id2, sideOffsets) {
199476
199870
  const mountedKey = mountedHandleKey(sideOffsets);
199477
199871
  const updateNodeInternals2 = useUpdateNodeInternals();
199478
- const lastKeyRef = (0, import_react8.useRef)(mountedKey);
199479
- (0, import_react8.useEffect)(() => {
199872
+ const lastKeyRef = (0, import_react9.useRef)(mountedKey);
199873
+ (0, import_react9.useEffect)(() => {
199480
199874
  if (lastKeyRef.current === mountedKey) return;
199481
199875
  lastKeyRef.current = mountedKey;
199482
199876
  updateNodeInternals2(id2);
@@ -199493,9 +199887,9 @@ var SIDE_NORMAL = {
199493
199887
  };
199494
199888
  var clampOffset = (v) => Math.max(0.06, Math.min(0.94, v));
199495
199889
  function usePortDrag(containerRef, w, h, topReserve, onPortMove, onPortPreview, onSelect) {
199496
- const [dragId, setDragId] = (0, import_react8.useState)(void 0);
199497
- const gestureRef = (0, import_react8.useRef)(void 0);
199498
- (0, import_react8.useEffect)(() => () => gestureRef.current?.abort(), []);
199890
+ const [dragId, setDragId] = (0, import_react9.useState)(void 0);
199891
+ const gestureRef = (0, import_react9.useRef)(void 0);
199892
+ (0, import_react9.useEffect)(() => () => gestureRef.current?.abort(), []);
199499
199893
  const onPortPointerDown = (portId, e, origin, draggable = true) => {
199500
199894
  if (e.button !== 0) return;
199501
199895
  e.stopPropagation();
@@ -200170,8 +200564,8 @@ function ContainerControls({
200170
200564
  ] });
200171
200565
  }
200172
200566
  function InlineEditor({ initial, mode, elementKind, onCommit, onCancel, w }) {
200173
- const ref = (0, import_react8.useRef)(null);
200174
- (0, import_react8.useEffect)(() => {
200567
+ const ref = (0, import_react9.useRef)(null);
200568
+ (0, import_react9.useEffect)(() => {
200175
200569
  const el2 = ref.current;
200176
200570
  if (el2) {
200177
200571
  el2.focus();
@@ -200269,7 +200663,7 @@ function shapeBody(node, data) {
200269
200663
  var CLIP_EXEMPT = /* @__PURE__ */ new Set(["fork", "join", "dot", "initial", "final", "terminate", "lifeline", "actor"]);
200270
200664
  function NodeBody({ node, data, selectedPortId, hoveredPortId, movingPortId, connectTargetPortId, connectTargetPortSide, showPortConnectStart, onPortSelect, onPortContext }) {
200271
200665
  const { w, h } = data;
200272
- const rawId = (0, import_react8.useId)();
200666
+ const rawId = (0, import_react9.useId)();
200273
200667
  const clipId = `dnode-clip-${rawId.replace(/[^a-zA-Z0-9_-]/g, "")}`;
200274
200668
  const clip = !CLIP_EXEMPT.has(node.shape) || data.kind === "gv" && node.shape === "actor";
200275
200669
  const elementColorClass = diagramElementColorClass(diagramElementColorTypeForNode(node.shape, node.keyword));
@@ -200316,7 +200710,7 @@ function SysmlNode({ id: id2, data, draggable, selected: selected2, width, heigh
200316
200710
  const internalNoun = INTERNAL_NOUN[data.kind] ?? "internal parts";
200317
200711
  const featureCompartmentsVisible = node.meta?.featureCompartmentsVisible === true;
200318
200712
  const featureCompartmentHeight = featureBandTopReserve(data);
200319
- const containerRef = (0, import_react8.useRef)(null);
200713
+ const containerRef = (0, import_react9.useRef)(null);
200320
200714
  const portSource = (pid) => {
200321
200715
  const p = node.ports?.find((pp) => pp.id === pid);
200322
200716
  ctx.onPortSelected?.();
@@ -200343,8 +200737,8 @@ function SysmlNode({ id: id2, data, draggable, selected: selected2, width, heigh
200343
200737
  const nodeSideStartable = directRelation !== void 0 && data.kind !== "sv" && node.shape !== "lifeline" && !isPackageEndpoint(node.shape, node.keyword);
200344
200738
  const selectedPortId = useInteraction(ctx.store, (s) => typeof s.selectedId === "string" && myPortIds.includes(s.selectedId) ? s.selectedId : void 0);
200345
200739
  const dropClass = useDropState(ctx.store, id2);
200346
- const [hoveredPortId, setHoveredPortId] = (0, import_react8.useState)(void 0);
200347
- const [sidePointsHovered, setSidePointsHovered] = (0, import_react8.useState)(false);
200740
+ const [hoveredPortId, setHoveredPortId] = (0, import_react9.useState)(void 0);
200741
+ const [sidePointsHovered, setSidePointsHovered] = (0, import_react9.useState)(false);
200348
200742
  const isPackageNode = isPackageEndpoint(node.shape, node.keyword);
200349
200743
  const sideConnectable = data.kind !== "sv" && !isPackageNode;
200350
200744
  const perimeterControl = keepsPerimeterSidePointsMounted(node.shape);
@@ -200655,7 +201049,7 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
200655
201049
  const h = height ?? data.h;
200656
201050
  const partitionKindFull = isExhibitLane ? "\xABexhibited by\xBB" : "\xABperformer\xBB";
200657
201051
  const partitionKindShown = fitKind(partitionKindFull, Math.max(1, w - 20));
200658
- const rawClipId = (0, import_react8.useId)();
201052
+ const rawClipId = (0, import_react9.useId)();
200659
201053
  const clipId = `dframe-clip-${rawClipId.replace(/[^a-zA-Z0-9_-]/g, "")}`;
200660
201054
  const structuredPrefix = `\xAB${structuredKeyword}\xBB`;
200661
201055
  const structuredConditionShown = structuredCondition ? fitText(structuredCondition, Math.max(1, w - 24 - structuredPrefix.length * 9 * 0.78), 11) : "";
@@ -200683,7 +201077,7 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
200683
201077
  performer: frame2.meta?.performerLane === true,
200684
201078
  structured: frame2.meta?.structuredControl === true
200685
201079
  }));
200686
- const containerRef = (0, import_react8.useRef)(null);
201080
+ const containerRef = (0, import_react9.useRef)(null);
200687
201081
  const portSource = (pid) => {
200688
201082
  ctx.onPortSelected?.();
200689
201083
  ctx.onReveal(frame2.ports?.find((p) => p.id === pid)?.source, pid);
@@ -200711,8 +201105,8 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
200711
201105
  const selectedPortId = useInteraction(ctx.store, (s) => typeof s.selectedId === "string" && myPortIds.includes(s.selectedId) ? s.selectedId : void 0);
200712
201106
  const dropClass = useDropState(ctx.store, id2);
200713
201107
  const editing = useInteraction(ctx.store, (s) => s.editing?.nodeId === id2 && !s.editing?.at && !s.editing?.edgeId ? s.editing : void 0);
200714
- const [hoveredPortId, setHoveredPortId] = (0, import_react8.useState)(void 0);
200715
- const [sidePointsHovered, setSidePointsHovered] = (0, import_react8.useState)(false);
201108
+ const [hoveredPortId, setHoveredPortId] = (0, import_react9.useState)(void 0);
201109
+ const [sidePointsHovered, setSidePointsHovered] = (0, import_react9.useState)(false);
200716
201110
  const sideConnectable = data.kind !== "sv" && !isPackageFrame && !isPartitionLane && !isOuterViewFrame;
200717
201111
  const sideOffsets = isPartitionLane ? SIDES.map(() => []) : SIDES.map((side) => mountedNodeSidePointOffsets(
200718
201112
  data,
@@ -201100,12 +201494,12 @@ function SeqFragmentNode({ data, width, height }) {
201100
201494
  ] }) });
201101
201495
  }
201102
201496
  var nodeTypes = {
201103
- sysml: (0, import_react8.memo)(SysmlNode),
201104
- frame: (0, import_react8.memo)(FrameNode),
201105
- lane: (0, import_react8.memo)(LaneNode),
201106
- seqfragment: (0, import_react8.memo)(SeqFragmentNode),
201107
- geo: (0, import_react8.memo)(GeoShapeNode),
201108
- geoframe: (0, import_react8.memo)(GeoFrameNode)
201497
+ sysml: (0, import_react9.memo)(SysmlNode),
201498
+ frame: (0, import_react9.memo)(FrameNode),
201499
+ lane: (0, import_react9.memo)(LaneNode),
201500
+ seqfragment: (0, import_react9.memo)(SeqFragmentNode),
201501
+ geo: (0, import_react9.memo)(GeoShapeNode),
201502
+ geoframe: (0, import_react9.memo)(GeoFrameNode)
201109
201503
  };
201110
201504
 
201111
201505
  // src/node-markup.tsx
@@ -201169,13 +201563,13 @@ function renderNodeBody(node, lineStyle, index2) {
201169
201563
  width: node.width ?? node.measured?.width ?? node.data.w,
201170
201564
  height: node.height ?? node.measured?.height ?? node.data.h
201171
201565
  };
201172
- const markup = (0, import_server.renderToStaticMarkup)((0, import_react10.createElement)(
201566
+ const markup = (0, import_server.renderToStaticMarkup)((0, import_react11.createElement)(
201173
201567
  ReactFlowProvider,
201174
201568
  null,
201175
- (0, import_react10.createElement)(
201569
+ (0, import_react11.createElement)(
201176
201570
  DiagramContext.Provider,
201177
201571
  { value: exportContext(lineStyle) },
201178
- (0, import_react10.createElement)(Component, props)
201572
+ (0, import_react11.createElement)(Component, props)
201179
201573
  )
201180
201574
  ));
201181
201575
  const inner = extractNodeSvgInner(markup);
@@ -201355,7 +201749,7 @@ async function runExport(command) {
201355
201749
  const root4 = command.workspace ? path8.resolve(command.workspace) : findWorkspaceRoot(file);
201356
201750
  const settings = diagramSettingsFor(readProjectConfig(root4));
201357
201751
  const sideCar = command.autoLayout ? emptySideCar() : readSideCar(root4, file);
201358
- const provider = new SysmlDiagramModelProvider();
201752
+ const provider = new SysmlDiagramModelProvider(services.shared);
201359
201753
  const kinds = command.all ? CANVAS_KINDS.filter((kind) => provider.buildAvailableDiagramKinds(document2, command.anchor).some((available) => available.kind === kind)) : [command.view ?? settings.defaultKind];
201360
201754
  const written = [];
201361
201755
  const empty2 = [];
@@ -201383,7 +201777,7 @@ async function runExport(command) {
201383
201777
  }
201384
201778
 
201385
201779
  // src/main.ts
201386
- var VERSION2 = true ? "0.20.3" : "dev";
201780
+ var VERSION2 = true ? "0.21.0" : "dev";
201387
201781
  function display(file) {
201388
201782
  const rel2 = path9.relative(process.cwd(), file);
201389
201783
  return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;