sysml-diagram 0.21.0 → 0.21.1

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
@@ -161733,9 +161733,16 @@ function nameOf(node) {
161733
161733
  const name = node?.name;
161734
161734
  if (typeof name === "string" && name.length > 0)
161735
161735
  return name;
161736
- if (node?.$type === "FeatureRedefinitionShorthand") {
161737
- const leading = node.preRelationships?.[0]?.targets?.[0];
161738
- return leading ? lastSegment(leading) : void 0;
161736
+ const relational = node;
161737
+ for (const relationship of [
161738
+ ...relational?.preRelationships ?? [],
161739
+ ...relational?.relationships ?? []
161740
+ ]) {
161741
+ if (relationship.kind !== ":>>" && relationship.kind !== "redefines")
161742
+ continue;
161743
+ const target = relationship.targets?.[0];
161744
+ if (target)
161745
+ return lastSegment(target);
161739
161746
  }
161740
161747
  if (node?.$type === "FeatureShorthand") {
161741
161748
  const text = node.$cstNode?.text;
@@ -161752,9 +161759,16 @@ function nameOf(node) {
161752
161759
  return void 0;
161753
161760
  }
161754
161761
  function unwrap(node) {
161755
- if (node.$type !== "PrefixMetadataMember")
161756
- return node;
161757
- return node.element ?? node;
161762
+ let current2 = node;
161763
+ const seen = /* @__PURE__ */ new Set();
161764
+ while ((current2.$type === "PrefixMetadataMember" || current2.$type === "MemberPrefixDecl") && !seen.has(current2)) {
161765
+ seen.add(current2);
161766
+ const element = current2.element;
161767
+ if (!element)
161768
+ break;
161769
+ current2 = element;
161770
+ }
161771
+ return current2;
161758
161772
  }
161759
161773
  function directNamedChildren(node) {
161760
161774
  const result = [];
@@ -161785,12 +161799,32 @@ function isSelfReference(candidate, node) {
161785
161799
  function lastSegment(path10) {
161786
161800
  return path10.split(/::|\./u).pop() ?? path10;
161787
161801
  }
161802
+ function simpleRelationName(path10) {
161803
+ let quoted = false;
161804
+ for (let index2 = 0; index2 < path10.length; index2 += 1) {
161805
+ const char = path10[index2];
161806
+ if (quoted) {
161807
+ if (char === "\\")
161808
+ index2 += 1;
161809
+ else if (char === "'")
161810
+ quoted = false;
161811
+ continue;
161812
+ }
161813
+ if (char === "'")
161814
+ quoted = true;
161815
+ else if (char === "." || char === ":" && path10[index2 + 1] === ":")
161816
+ return void 0;
161817
+ }
161818
+ const withoutMultiplicity = path10.replace(/\s*\[[^\]]*\]\s*$/u, "").trim();
161819
+ return withoutMultiplicity ? canonicalEscapedName(withoutMultiplicity) : void 0;
161820
+ }
161788
161821
  var FeaturePathResolver = class {
161789
161822
  indexManager;
161790
161823
  descriptions;
161791
161824
  documents;
161792
161825
  locator;
161793
161826
  snapshots = /* @__PURE__ */ new WeakMap();
161827
+ resolvingSpecializations = /* @__PURE__ */ new Set();
161794
161828
  constructor(services) {
161795
161829
  this.indexManager = services?.shared.workspace.IndexManager;
161796
161830
  this.descriptions = services?.workspace.AstNodeDescriptionProvider;
@@ -161893,6 +161927,14 @@ var FeaturePathResolver = class {
161893
161927
  }
161894
161928
  return result;
161895
161929
  }
161930
+ /** Semantic owners reached through typing and specialization. This is used
161931
+ * when an anonymous redefinition has no keyword from which to recover its
161932
+ * feature kind. */
161933
+ // REQ-364: recover the semantic kind of an anonymous local redefinition.
161934
+ inheritedOwners(node) {
161935
+ const root4 = ast_utils_exports.getDocument(node).parseResult.value;
161936
+ return this.typedAndSpecializedOwners(node, this.snapshot(root4));
161937
+ }
161896
161938
  segmentsOf(node) {
161897
161939
  const cst = node.$cstNode;
161898
161940
  if (!cst)
@@ -162038,20 +162080,45 @@ var FeaturePathResolver = class {
162038
162080
  return typed;
162039
162081
  }
162040
162082
  specializationTargets(node, snapshot) {
162083
+ if (this.resolvingSpecializations.has(node))
162084
+ return [];
162085
+ this.resolvingSpecializations.add(node);
162041
162086
  const relNode = node;
162042
162087
  const result = [];
162043
- for (const relation of [...relNode.preRelationships ?? [], ...relNode.relationships ?? []]) {
162044
- if (!relation.kind || !SPECIALIZATION_KINDS.has(relation.kind))
162045
- continue;
162046
- for (const target of relation.targets ?? []) {
162047
- const description = this.pickDescription(snapshot.byName.get(target)) ?? this.pickDescription(snapshot.byName.get(lastSegment(target)));
162048
- const resolved = this.nodeOf(description);
162049
- if (resolved)
162050
- result.push(resolved);
162088
+ try {
162089
+ for (const relation of [...relNode.preRelationships ?? [], ...relNode.relationships ?? []]) {
162090
+ if (!relation.kind || !SPECIALIZATION_KINDS.has(relation.kind))
162091
+ continue;
162092
+ for (const target of relation.targets ?? []) {
162093
+ const simple = simpleRelationName(target);
162094
+ const scoped = simple ? this.scopedSpecializationTarget(node, simple, snapshot) : void 0;
162095
+ const description = scoped ? void 0 : this.pickDescription(snapshot.byName.get(target), node) ?? this.pickDescription(snapshot.byName.get(lastSegment(target)), node);
162096
+ const resolved = scoped ?? this.nodeOf(description);
162097
+ if (resolved)
162098
+ result.push(resolved);
162099
+ }
162051
162100
  }
162101
+ } finally {
162102
+ this.resolvingSpecializations.delete(node);
162052
162103
  }
162053
162104
  return result;
162054
162105
  }
162106
+ /** A simple feature specialization is resolved in the visible inventory of
162107
+ * its lexical owner. Only an absent scoped match may fall back to the global
162108
+ * index, which prevents an unrelated same-named feature from winning. */
162109
+ scopedSpecializationTarget(node, name, snapshot) {
162110
+ for (let scope = node.$container; scope; scope = scope.$container) {
162111
+ const local = directNamedChildren(scope).find((candidate) => candidate !== node && nameOf(candidate) === name);
162112
+ if (local)
162113
+ return local;
162114
+ for (const owner of this.typedAndSpecializedOwners(scope, snapshot)) {
162115
+ const inherited = directNamedChildren(owner).find((candidate) => candidate !== node && nameOf(candidate) === name);
162116
+ if (inherited)
162117
+ return inherited;
162118
+ }
162119
+ }
162120
+ return void 0;
162121
+ }
162055
162122
  memberInventoryKnown(node, snapshot) {
162056
162123
  const record = node;
162057
162124
  if (record.isDef === true || node.$type === "ClassDecl" || node.$type === "StructDecl" || node.$type === "EnumDecl" || node.$type === "DatatypeDecl" || node.$type === "FunctionDecl" || node.$type === "PredicateDecl") {
@@ -162243,14 +162310,21 @@ function sourceOf2(node, uri) {
162243
162310
  return { uri, range };
162244
162311
  }
162245
162312
  }
162313
+ function isAstDescendantOrSelf(node, ancestor) {
162314
+ for (let current2 = node; current2; current2 = current2.$container) {
162315
+ if (current2 === ancestor)
162316
+ return true;
162317
+ }
162318
+ return false;
162319
+ }
162246
162320
  function ivEditMeta(part, instanceId, definition, localUsage, localPath, uri) {
162247
- const declarationId = qnameOf(part) || instanceId;
162321
+ const declarationId = nameOf2(part) ? qnameOf(part) || instanceId : instanceId;
162248
162322
  const definitionId = definition ? qnameOf(definition) : void 0;
162249
162323
  const localUsageId = localUsage ? qnameOf(localUsage) : void 0;
162250
162324
  return {
162251
162325
  instanceId,
162252
162326
  declarationId,
162253
- declarationName: nameOf2(part),
162327
+ declarationName: effectiveNameOf(part),
162254
162328
  declarationSource: sourceOf2(part, uri),
162255
162329
  definitionId,
162256
162330
  definitionName: definition ? nameOf2(definition) : void 0,
@@ -162259,7 +162333,10 @@ function ivEditMeta(part, instanceId, definition, localUsage, localPath, uri) {
162259
162333
  localUsageName: localUsage ? nameOf2(localUsage) : void 0,
162260
162334
  localUsageSource: localUsage ? sourceOf2(localUsage, uri) : void 0,
162261
162335
  localUsagePath: [...localPath],
162262
- expandedFromDefinition: declarationId !== instanceId
162336
+ expandedFromDefinition: declarationId !== instanceId,
162337
+ // A named declaration remains local even when an anonymous `:>>`
162338
+ // wrapper removes its name from the rendered occurrence path.
162339
+ localDeclaration: !!nameOf2(part) && !!localUsage && isAstDescendantOrSelf(part, localUsage)
162263
162340
  };
162264
162341
  }
162265
162342
  var nameOf2 = (node) => {
@@ -162466,6 +162543,16 @@ function specializationTargets(node) {
162466
162543
  }
162467
162544
  return out;
162468
162545
  }
162546
+ function featureInheritanceTargets(node) {
162547
+ const n2 = node;
162548
+ const out = [];
162549
+ for (const rel2 of [...n2.preRelationships ?? [], ...n2.relationships ?? []]) {
162550
+ if (rel2.kind === ":>" || rel2.kind === ":>>" || rel2.kind === "specializes" || rel2.kind === "subsets" || rel2.kind === "redefines") {
162551
+ out.push(...rel2.targets ?? []);
162552
+ }
162553
+ }
162554
+ return out;
162555
+ }
162469
162556
  function specializationFamily(node) {
162470
162557
  const n2 = node;
162471
162558
  const isDef = n2.isDef === true;
@@ -162562,9 +162649,11 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
162562
162649
  if (hit)
162563
162650
  cache.models.delete(cacheKey);
162564
162651
  const model = this.computeDiagramModel(document2, root4, rootSymbol, kind, preferFileOverview, gridPreset, matrixRelationship);
162652
+ const externalRoots = this.externalRootsOf(model, document2.uri.toString());
162653
+ model.dependencies = [document2.uri.toString(), ...externalRoots.keys()];
162565
162654
  cache.models.set(cacheKey, {
162566
162655
  model,
162567
- externalRoots: this.externalRootsOf(model, document2.uri.toString()),
162656
+ externalRoots,
162568
162657
  indexEpoch: this.indexEpoch
162569
162658
  });
162570
162659
  return model;
@@ -162586,21 +162675,24 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
162586
162675
  if (source?.uri && source.uri !== anchorUri)
162587
162676
  uris.add(source.uri);
162588
162677
  };
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);
162678
+ const seen = /* @__PURE__ */ new Set();
162679
+ const addSources = (value) => {
162680
+ if (!value || typeof value !== "object" || seen.has(value))
162681
+ return;
162682
+ seen.add(value);
162683
+ if (Array.isArray(value)) {
162684
+ for (const item of value)
162685
+ addSources(item);
162686
+ return;
162687
+ }
162688
+ const record = value;
162689
+ if (typeof record.uri === "string" && record.range && typeof record.range === "object") {
162690
+ add(record);
162691
+ }
162692
+ for (const nested of Object.values(record))
162693
+ addSources(nested);
162694
+ };
162695
+ addSources(model);
162604
162696
  return new Map([...uris].map((uri) => [uri, this.externalDocumentRoot(uri)]));
162605
162697
  }
162606
162698
  computeDiagramModel(document2, root4, rootSymbol, kind, preferFileOverview, gridPreset = "requirements", matrixRelationship = "allocation") {
@@ -162926,7 +163018,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
162926
163018
  if (local)
162927
163019
  return local;
162928
163020
  const declaringIndex = this.localIndex(this.documentRootOf(scope));
162929
- for (const inherited of this.inheritedTypesOf(scope, declaringIndex)) {
163021
+ for (const inherited of this.inheritedFeatureOwnersOf(scope, declaringIndex)) {
162930
163022
  const inheritedMember = membersOf(inherited).find((member) => nameOf2(member) === unrooted);
162931
163023
  if (inheritedMember)
162932
163024
  return inheritedMember;
@@ -162991,6 +163083,98 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
162991
163083
  }
162992
163084
  return chain;
162993
163085
  }
163086
+ // REQ-061/REQ-192/REQ-364 - the effective feature owners inherited by a
163087
+ // definition or usage. A redefining usage specializes both its explicit type
163088
+ // and the feature it redefines. The latter can contribute its own body and its
163089
+ // type's complete inventory, so following only typing definitions turns an
163090
+ // anonymous `part :>> inheritedPart` into an empty leaf.
163091
+ inheritedFeatureOwnersOf(node, index2) {
163092
+ const chain = [];
163093
+ const seen = /* @__PURE__ */ new Set([node]);
163094
+ const queue = [];
163095
+ const add = (candidate) => {
163096
+ if (!candidate || seen.has(candidate))
163097
+ return;
163098
+ seen.add(candidate);
163099
+ chain.push(candidate);
163100
+ queue.push(candidate);
163101
+ };
163102
+ const addTargets = (owner) => {
163103
+ for (const target of featureInheritanceTargets(owner)) {
163104
+ add(this.resolveFeatureInheritanceTarget(owner, target, index2));
163105
+ }
163106
+ };
163107
+ if (node.isDef === true)
163108
+ addTargets(node);
163109
+ else {
163110
+ add(this.resolveType(node, index2));
163111
+ addTargets(node);
163112
+ }
163113
+ while (queue.length > 0) {
163114
+ const owner = queue.shift();
163115
+ if (owner.isDef !== true)
163116
+ add(this.resolveType(owner, index2));
163117
+ addTargets(owner);
163118
+ }
163119
+ return chain;
163120
+ }
163121
+ /** Declaration that an anonymous local redefinition specializes. Direct edits
163122
+ * in definition-sync mode address this feature, while child insertion still
163123
+ * addresses the feature's typing definition. */
163124
+ synchronizationDeclarationOf(node, index2) {
163125
+ if (nameOf2(node))
163126
+ return node;
163127
+ const wanted = effectiveNameOf(node);
163128
+ return this.inheritedFeatureOwnersOf(node, index2).find((candidate) => candidate.isDef !== true && effectiveNameOf(candidate) === wanted && (isPartDecl(node) ? isPartDecl(candidate) : isPortDecl(node) ? isPortDecl(candidate) : true));
163129
+ }
163130
+ /** Resolve a usage specialization in its feature scope. A simple `:>> x`
163131
+ * names a sibling supplied by the containing usage or one of its types. A
163132
+ * global simple-name lookup can select the redeclaration itself or an
163133
+ * unrelated namesake, so the containing feature inventory is checked first. */
163134
+ resolveFeatureInheritanceTarget(owner, target, index2) {
163135
+ const path10 = this.resolvedFeatureInheritancePath(owner, target);
163136
+ if (path10.qualified) {
163137
+ return path10.target === owner ? void 0 : path10.target;
163138
+ }
163139
+ if (owner.isDef !== true) {
163140
+ const wanted = lastSeg(target);
163141
+ const container = owner.$container;
163142
+ if (container) {
163143
+ for (const source of [container, ...this.inheritedFeatureOwnersOf(container, index2)]) {
163144
+ const inherited = membersOf(source).find((member) => member !== owner && effectiveNameOf(member) === wanted);
163145
+ if (inherited)
163146
+ return inherited;
163147
+ }
163148
+ }
163149
+ }
163150
+ const resolved = path10.target ?? this.resolveSpecializationTarget(owner, target, index2);
163151
+ return resolved === owner ? void 0 : resolved;
163152
+ }
163153
+ /** Resolve a relationship target through the shared feature path service.
163154
+ * Qualified paths must retain every segment because a last-segment lookup can
163155
+ * select an unrelated sibling with the same name. */
163156
+ resolvedFeatureInheritancePath(owner, target) {
163157
+ const relationships = [
163158
+ ...owner.preRelationships ?? [],
163159
+ ...owner.relationships ?? []
163160
+ ];
163161
+ const resolver = this.annotationPathResolver(owner);
163162
+ for (const relationship of relationships) {
163163
+ if (!relationship.kind || ![":>", ":>>", "specializes", "subsets", "redefines"].includes(relationship.kind))
163164
+ continue;
163165
+ for (const [occurrence, written] of (relationship.targets ?? []).entries()) {
163166
+ if (written !== target)
163167
+ continue;
163168
+ const resolution = resolver.resolvePropertyPath(relationship, "targets", occurrence);
163169
+ const segment = resolution.segments.at(-1);
163170
+ return {
163171
+ qualified: resolution.segments.length > 1,
163172
+ target: segment?.target ?? this.annotationDescriptionNode(owner, segment?.description)
163173
+ };
163174
+ }
163175
+ }
163176
+ return { qualified: /::|\./u.test(target) };
163177
+ }
162994
163178
  // issue #233 (PR #239 review) — one supertype path, resolved. A specialization
162995
163179
  // target is path TEXT in this grammar, not a cross-reference, so there is no
162996
163180
  // linked node to prefer the way `resolveType` prefers `typing.type.ref`; the
@@ -163466,7 +163650,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
163466
163650
  return this.collectGeometry(node, index2).length > 0;
163467
163651
  }
163468
163652
  hasRenderablePorts(node, index2) {
163469
- return [node, ...this.inheritedTypesOf(node, index2)].some((source) => membersOf(source).some((m) => isPortDecl(m) && m.isDef !== true));
163653
+ return [node, ...this.inheritedFeatureOwnersOf(node, index2)].some((source) => membersOf(source).some((m) => isPortDecl(m) && m.isDef !== true));
163470
163654
  }
163471
163655
  // REQ-192, issue #233 — the named part usages a part shows when expanded: its
163472
163656
  // own and the ones it inherits, through its typing definition or a `:>`
@@ -163474,7 +163658,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
163474
163658
  // The predicate form of `childUsagesOf`, so an anchor that only INHERITS
163475
163659
  // internals is recognised as having them.
163476
163660
  hasNestedPartUsages(node, index2) {
163477
- return [node, ...this.inheritedTypesOf(node, index2)].some((source) => this.nestedUsages(source, isPartDecl).some((n2) => nameOf2(n2) !== void 0));
163661
+ return [node, ...this.inheritedFeatureOwnersOf(node, index2)].some((source) => this.nestedUsages(source, isPartDecl).some((n2) => nameOf2(n2) !== void 0));
163478
163662
  }
163479
163663
  nestedUsages(node, guard) {
163480
163664
  return membersOf(node).filter((m) => guard(m) && m.isDef !== true);
@@ -164144,7 +164328,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164144
164328
  const childUsagesOf = (part) => {
164145
164329
  const out = this.nestedUsages(part, isPartDecl);
164146
164330
  const have = new Set(out.map(effectiveNameOf).filter((x) => !!x));
164147
- for (const source of this.inheritedTypesOf(part, index2)) {
164331
+ for (const source of this.inheritedFeatureOwnersOf(part, index2)) {
164148
164332
  for (const usage of this.nestedUsages(source, isPartDecl)) {
164149
164333
  const nm = effectiveNameOf(usage);
164150
164334
  if (nm !== void 0) {
@@ -164157,7 +164341,27 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164157
164341
  }
164158
164342
  return out;
164159
164343
  };
164160
- const effectiveMembersOf = (part) => [part, ...this.inheritedTypesOf(part, index2)].flatMap((source) => membersOf(source));
164344
+ const effectiveMembersOf = (part) => {
164345
+ const effective = [];
164346
+ const claimedNames = /* @__PURE__ */ new Set();
164347
+ for (const source of [part, ...this.inheritedFeatureOwnersOf(part, index2)]) {
164348
+ for (const member of membersOf(source)) {
164349
+ const relationship = member;
164350
+ const emptyPrefixFlow = member.$type === "FlowStmt" && relationship.target !== void 0 && relationship.source === void 0;
164351
+ const emptyPrefixInterface = isInterfaceDecl(member) && relationship.target !== void 0 && relationship.connect === void 0;
164352
+ const namedRelationship = isConnectorDecl(member) || isConnectionDecl(member) || isInterfaceDecl(member) && !emptyPrefixInterface || member.$type === "BindingDecl" || member.$type === "FlowStmt" && !emptyPrefixFlow;
164353
+ if (namedRelationship) {
164354
+ const names = [nameOf2(member), redefinedNameOf(member)].filter((name) => name !== void 0);
164355
+ if (names.some((name) => claimedNames.has(name)))
164356
+ continue;
164357
+ for (const name of names)
164358
+ claimedNames.add(name);
164359
+ }
164360
+ effective.push(member);
164361
+ }
164362
+ }
164363
+ return effective;
164364
+ };
164161
164365
  const childResolver = (childInfos, self2, actionInfos = []) => {
164162
164366
  const localPort = /* @__PURE__ */ new Map();
164163
164367
  const actionPort = /* @__PURE__ */ new Map();
@@ -164235,14 +164439,22 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164235
164439
  return { resolve: resolve8, actionPinIds };
164236
164440
  };
164237
164441
  const renderInstance = (part, instanceId, parentFrame, seenTypes, depth, inheritedLocalUsage, inheritedLocalPath = []) => {
164238
- const ports = this.portsOf(part, index2, uri, instanceId).ports;
164239
- const typeDef = part.isDef === true ? void 0 : this.resolveType(part, index2);
164442
+ const typeDef = part.isDef === true ? void 0 : this.resolveType(part, index2) ?? this.inheritedFeatureOwnersOf(part, index2).find((owner) => owner.isDef === true);
164240
164443
  const typeQ = typeDef ? qnameOf(typeDef) : void 0;
164241
- const declarationId = qnameOf(part) || instanceId;
164242
- const projected = declarationId !== instanceId;
164444
+ const declarationId = nameOf2(part) ? qnameOf(part) || instanceId : instanceId;
164445
+ const projected = nameOf2(part) === void 0 || declarationId !== instanceId;
164243
164446
  const localUsage = part.isDef !== true && !projected ? part : inheritedLocalUsage;
164244
164447
  const localPath = part.isDef !== true && !projected ? [] : inheritedLocalPath;
164245
- const editMeta = ivEditMeta(part, instanceId, typeDef, localUsage, localPath, uri);
164448
+ const ports = this.portsOf(part, index2, uri, instanceId, localUsage).ports;
164449
+ const syncDeclaration = this.synchronizationDeclarationOf(part, index2);
164450
+ const editMeta = {
164451
+ ...ivEditMeta(part, instanceId, typeDef, localUsage, localPath, uri),
164452
+ ...syncDeclaration && syncDeclaration !== part ? {
164453
+ syncDeclarationId: qnameOf(syncDeclaration),
164454
+ syncDeclarationName: effectiveNameOf(syncDeclaration),
164455
+ syncDeclarationSource: sourceOf2(syncDeclaration, uri)
164456
+ } : {}
164457
+ };
164246
164458
  const children2 = depth < 8 && !(typeQ !== void 0 && seenTypes.has(typeQ)) ? childUsagesOf(part) : [];
164247
164459
  const concretePerformPath = (statement, target) => {
164248
164460
  if (!this.isAnonymousBehaviorReference(statement)) {
@@ -164286,16 +164498,31 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164286
164498
  }).filter((entry, i, list) => list.findIndex((other) => other.key === entry.key) === i) : [];
164287
164499
  const performedActionInfos = performedActions.map(({ act, pinSource, pathSegments, name, key }) => {
164288
164500
  const id2 = `${instanceId}::__perform_${key}`;
164501
+ const inheritedFromDefinition = !!localUsage && !isAstDescendantOrSelf(act, localUsage);
164502
+ const syncDeclaration2 = this.synchronizationDeclarationOf(act, index2);
164289
164503
  return {
164290
164504
  act,
164291
164505
  name,
164292
164506
  id: id2,
164293
164507
  pathSegments,
164294
- pins: this.actionPinPorts(pinSource, id2, index2, uri)
164508
+ pins: this.actionPinPorts(pinSource, id2, index2, uri),
164509
+ meta: {
164510
+ ...ivEditMeta(act, id2, void 0, localUsage, [...localPath, name], uri),
164511
+ ivAction: true,
164512
+ // A performed action projected from a typed part belongs
164513
+ // to the shared definition. Local IV edits cannot safely
164514
+ // materialize an action redefinition yet.
164515
+ ivInheritedAction: inheritedFromDefinition,
164516
+ ...syncDeclaration2 && syncDeclaration2 !== act ? {
164517
+ syncDeclarationId: qnameOf(syncDeclaration2),
164518
+ syncDeclarationName: effectiveNameOf(syncDeclaration2),
164519
+ syncDeclarationSource: sourceOf2(syncDeclaration2, uri)
164520
+ } : {}
164521
+ }
164295
164522
  };
164296
164523
  });
164297
164524
  const emitOwnedActions = (frameOf) => {
164298
- for (const { act, name, id: actId, pins } of performedActionInfos) {
164525
+ for (const { act, name, id: actId, pins, meta } of performedActionInfos) {
164299
164526
  nodes.push({
164300
164527
  id: actId,
164301
164528
  name,
@@ -164307,7 +164534,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164307
164534
  ports: pins,
164308
164535
  frame: frameOf,
164309
164536
  source: sourceOf2(act, uri),
164310
- meta: { ivAction: true }
164537
+ meta
164311
164538
  });
164312
164539
  }
164313
164540
  };
@@ -164334,7 +164561,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164334
164561
  }
164335
164562
  emitOwnedActions(instanceId);
164336
164563
  const resolver = childResolver(childInfos, { usage: part, id: instanceId }, performedActionInfos);
164337
- this.emitInterconnectEdges(effectiveMembersOf(part), resolver.resolve, children2, index2, uri, nodes, edges, eRef, instanceId, resolver.actionPinIds);
164564
+ this.emitInterconnectEdges(effectiveMembersOf(part), resolver.resolve, children2, index2, uri, nodes, edges, eRef, instanceId, resolver.actionPinIds, part);
164338
164565
  } else {
164339
164566
  nodes.push({
164340
164567
  id: instanceId,
@@ -164350,12 +164577,37 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164350
164577
  source: sourceOf2(part, uri),
164351
164578
  meta: editMeta
164352
164579
  });
164580
+ const resolver = childResolver([], { usage: part, id: instanceId });
164581
+ this.emitInterconnectEdges(effectiveMembersOf(part), resolver.resolve, [], index2, uri, nodes, edges, eRef, instanceId, resolver.actionPinIds, part);
164353
164582
  }
164354
164583
  };
164355
164584
  const packageOfRoot = (root4) => enclosingPackage(root4) ?? scope;
164585
+ const rootBaseId = (root4) => qnameOf(root4) || nameOf2(root4) || `__root_${root4.$cstNode?.offset ?? 0}__`;
164586
+ const rootsByBaseId = /* @__PURE__ */ new Map();
164587
+ for (const root4 of roots) {
164588
+ const base = rootBaseId(root4);
164589
+ rootsByBaseId.set(base, [...rootsByBaseId.get(base) ?? [], root4]);
164590
+ }
164591
+ const rootOccurrenceIds = /* @__PURE__ */ new Map();
164592
+ for (const [base, sameNameRoots] of rootsByBaseId) {
164593
+ if (sameNameRoots.length === 1) {
164594
+ rootOccurrenceIds.set(sameNameRoots[0], base);
164595
+ continue;
164596
+ }
164597
+ const discriminatorCounts = /* @__PURE__ */ new Map();
164598
+ const inSourceOrder = [...sameNameRoots].sort((a2, b) => (a2.$cstNode?.offset ?? 0) - (b.$cstNode?.offset ?? 0));
164599
+ for (const root4 of inSourceOrder) {
164600
+ const semanticIdentity = [typeText(root4), ...featureInheritanceTargets(root4)].filter((part) => !!part).join("_") || root4.$type;
164601
+ const discriminator = semanticIdentity.replace(/[^A-Za-z0-9_]+/gu, "_").replace(/^_+|_+$/gu, "") || "part";
164602
+ const occurrence = discriminatorCounts.get(discriminator) ?? 0;
164603
+ discriminatorCounts.set(discriminator, occurrence + 1);
164604
+ const suffix = occurrence === 0 ? discriminator : `${discriminator}_${occurrence + 1}`;
164605
+ rootOccurrenceIds.set(root4, `${base}::__occurrence_${suffix}`);
164606
+ }
164607
+ }
164356
164608
  const rootInfos = [];
164357
164609
  for (const root4 of roots) {
164358
- const id2 = qnameOf(root4) || nameOf2(root4) || `__root_${nodes.length + frames.length}__`;
164610
+ const id2 = rootOccurrenceIds.get(root4) ?? rootBaseId(root4);
164359
164611
  renderInstance(root4, id2, opts.packageFrames ? ensurePkgFrame(enclosingPackage(root4)) : void 0, /* @__PURE__ */ new Set(), 0, root4.isDef === true ? void 0 : root4, []);
164360
164612
  rootInfos.push({ usage: root4, id: id2, pkg: packageOfRoot(root4) });
164361
164613
  }
@@ -164364,7 +164616,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164364
164616
  const localInfos = rootInfos.filter((r) => r.pkg === pkg && r.usage.isDef !== true);
164365
164617
  const localRoots = localInfos.map((r) => r.usage);
164366
164618
  const resolver = childResolver(localInfos);
164367
- this.emitInterconnectEdges(membersOf(pkg), resolver.resolve, localRoots, index2, uri, nodes, edges, eRef, void 0, resolver.actionPinIds);
164619
+ this.emitInterconnectEdges(membersOf(pkg), resolver.resolve, localRoots, index2, uri, nodes, edges, eRef, void 0, resolver.actionPinIds, pkg);
164368
164620
  }
164369
164621
  }
164370
164622
  return { nodes, edges, frames };
@@ -164397,8 +164649,23 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164397
164649
  // single Interconnection View (called once over the anchor's whole subtree)
164398
164650
  // and the package overview (called once per container part, tagging any
164399
164651
  // synthetic n-ary dot with that container's frame id).
164400
- emitInterconnectEdges(members, resolveEnd, parts, index2, uri, nodes, edges, eRef, frameId, actionPinIds = /* @__PURE__ */ new Set()) {
164652
+ emitInterconnectEdges(members, resolveEnd, parts, index2, uri, nodes, edges, eRef, frameId, actionPinIds = /* @__PURE__ */ new Set(), memberOwner) {
164401
164653
  const memberList2 = [...members];
164654
+ const relationshipFields = (source) => {
164655
+ let directMember = source;
164656
+ while (directMember.$container && directMember.$container !== memberOwner) {
164657
+ directMember = directMember.$container;
164658
+ }
164659
+ const inherited = !!memberOwner && directMember.$container !== memberOwner;
164660
+ const meta = {
164661
+ ...inherited ? { ivInheritedRelation: true } : {},
164662
+ ...frameId ? { ivRelationshipOwnerId: frameId } : {}
164663
+ };
164664
+ return {
164665
+ source: sourceOf2(source, uri),
164666
+ ...Object.keys(meta).length > 0 ? { meta } : {}
164667
+ };
164668
+ };
164402
164669
  const supportsEndpoints = (kind, ids) => {
164403
164670
  const pinCount = ids.filter((id2) => actionPinIds.has(id2)).length;
164404
164671
  if (pinCount === 0)
@@ -164424,7 +164691,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164424
164691
  label,
164425
164692
  endLabelFrom: multText(resolvedEnds[0].end),
164426
164693
  endLabelTo: multText(resolvedEnds[1].end),
164427
- source: sourceOf2(src, uri)
164694
+ ...relationshipFields(src)
164428
164695
  });
164429
164696
  return;
164430
164697
  }
@@ -164441,7 +164708,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164441
164708
  isDef: false,
164442
164709
  label,
164443
164710
  endLabelTo: multText(end),
164444
- source: sourceOf2(src, uri)
164711
+ ...relationshipFields(src)
164445
164712
  });
164446
164713
  }
164447
164714
  };
@@ -164486,7 +164753,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164486
164753
  to: endId,
164487
164754
  kind: "connect",
164488
164755
  endLabelTo: multText(end),
164489
- source: sourceOf2(m, uri)
164756
+ ...relationshipFields(m)
164490
164757
  });
164491
164758
  }
164492
164759
  }
@@ -164506,7 +164773,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164506
164773
  // REQ-179 — connector end multiplicities (`connect [1] a to [0..*] b;`)
164507
164774
  endLabelFrom: multText(srcEnd),
164508
164775
  endLabelTo: multText(tgtEnd),
164509
- source: sourceOf2(m, uri)
164776
+ ...relationshipFields(m)
164510
164777
  });
164511
164778
  }
164512
164779
  }
@@ -164524,7 +164791,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164524
164791
  to,
164525
164792
  kind: "flow",
164526
164793
  label: this.flowPayloadText(fm) ?? typeText(m) ?? nameOf2(m),
164527
- source: sourceOf2(m, uri)
164794
+ ...relationshipFields(m)
164528
164795
  });
164529
164796
  }
164530
164797
  } else if (m.$type === "BindStmt" || m.$type === "BindingConnectorStmt" || m.$type === "BindingDecl") {
@@ -164547,7 +164814,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164547
164814
  // of its own (issue #120 review).
164548
164815
  endLabelFrom: multText(leftEnd) ?? multText(bn),
164549
164816
  endLabelTo: multText(rightEnd),
164550
- source: sourceOf2(m, uri)
164817
+ ...relationshipFields(m)
164551
164818
  });
164552
164819
  }
164553
164820
  } else if (isInterfaceDecl(m) && m.isDef !== true) {
@@ -164570,7 +164837,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164570
164837
  label,
164571
164838
  endLabelFrom: multText(clause.source),
164572
164839
  endLabelTo: multText(clause.target),
164573
- source: sourceOf2(m, uri)
164840
+ ...relationshipFields(m)
164574
164841
  });
164575
164842
  }
164576
164843
  }
@@ -164597,7 +164864,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164597
164864
  isDef: false,
164598
164865
  label,
164599
164866
  endLabelTo: multText(end),
164600
- source: sourceOf2(m, uri)
164867
+ ...relationshipFields(m)
164601
164868
  });
164602
164869
  }
164603
164870
  }
@@ -164616,7 +164883,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164616
164883
  label,
164617
164884
  endLabelFrom: multText(clause.source),
164618
164885
  endLabelTo: multText(clause.target),
164619
- source: sourceOf2(m, uri)
164886
+ ...relationshipFields(m)
164620
164887
  });
164621
164888
  }
164622
164889
  }
@@ -164637,7 +164904,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
164637
164904
  const all = [...ast_utils_exports.streamAllContents(scope)];
164638
164905
  const isUsagePart = (n2) => isPartDecl(n2) && n2.isDef !== true && nameOf2(n2) !== void 0;
164639
164906
  const isDefPart = (n2) => isPartDecl(n2) && n2.isDef === true && nameOf2(n2) !== void 0;
164640
- const hasInternalParts = (d) => [d, ...this.inheritedTypesOf(d, index2)].some((source) => this.nestedUsages(source, isPartDecl).length > 0);
164907
+ const hasInternalParts = (d) => [d, ...this.inheritedFeatureOwnersOf(d, index2)].some((source) => this.nestedUsages(source, isPartDecl).length > 0);
164641
164908
  const insideAPart = (n2) => {
164642
164909
  let c = n2.$container;
164643
164910
  while (c && c !== scope) {
@@ -168354,7 +168621,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
168354
168621
  }
168355
168622
  // REQ-175, REQ-193 — collect a node's ports (own + inherited from its type
168356
168623
  // def) as stubs, plus a "usageName.portName" → portId resolution map.
168357
- portsOf(node, index2, uri, ownerId) {
168624
+ portsOf(node, index2, uri, ownerId, localUsage) {
168358
168625
  const ports = [];
168359
168626
  const map3 = /* @__PURE__ */ new Map();
168360
168627
  const visibleNames = /* @__PURE__ */ new Set();
@@ -168366,23 +168633,50 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
168366
168633
  const portId = parentPortId ? `${parentPortId}.${pn}` : `${ownerId}.${pn}`;
168367
168634
  const rel2 = parentPath ? `${parentPath}.${pn}` : pn;
168368
168635
  let direction = directionOf(portNode);
168369
- const portTypeDef = this.resolveType(portNode, index2);
168636
+ const inheritedOwners = this.inheritedFeatureOwnersOf(portNode, index2);
168637
+ const directPortTypeDef = this.resolveType(portNode, index2);
168638
+ const inheritedPortUsages = inheritedOwners.filter((owner) => isPortDecl(owner) && owner.isDef !== true);
168639
+ const inheritedTyping = inheritedPortUsages.map((owner) => ({ owner, type: this.resolveType(owner, index2) })).find((entry) => entry.type !== void 0);
168640
+ const portTypeDef = directPortTypeDef ?? inheritedTyping?.type ?? inheritedOwners.find((owner) => isPortDecl(owner) && owner.isDef === true);
168641
+ const inheritedDirection = inheritedPortUsages.map(directionOf).find((candidate) => candidate !== void 0);
168642
+ direction ??= inheritedDirection;
168643
+ const referenceTraitOf = (candidate) => {
168644
+ const modifiers2 = candidate.modifiers ?? [];
168645
+ if (modifiers2.includes("ref"))
168646
+ return true;
168647
+ if (modifiers2.includes("composite"))
168648
+ return false;
168649
+ return void 0;
168650
+ };
168651
+ const inheritedReference = inheritedPortUsages.map(referenceTraitOf).find((candidate) => candidate !== void 0);
168652
+ const reference = referenceTraitOf(portNode) ?? inheritedReference;
168653
+ const hasDirectTyping = portNode.typing !== void 0;
168654
+ const effectiveConjugated = hasDirectTyping ? isConjugated(portNode) : inheritedTyping ? isConjugated(inheritedTyping.owner) : false;
168370
168655
  if (!direction) {
168371
168656
  const conjugated = isConjugated(portNode);
168372
- const dirs = /* @__PURE__ */ new Set([
168373
- ...this.ownDirectedFeatureDirections(portNode, conjugated),
168374
- ...portTypeDef ? this.effectivePortDirections(portTypeDef, index2, conjugated) : []
168375
- ]);
168657
+ const dirs = this.ownDirectedFeatureDirections(portNode, conjugated);
168658
+ for (const inheritedUsage of inheritedPortUsages) {
168659
+ const inheritedConjugated = conjugated !== isConjugated(inheritedUsage);
168660
+ for (const inheritedDirection2 of this.ownDirectedFeatureDirections(inheritedUsage, inheritedConjugated)) {
168661
+ dirs.add(inheritedDirection2);
168662
+ }
168663
+ }
168664
+ const typeConjugated = directPortTypeDef ? conjugated : inheritedTyping ? conjugated !== isConjugated(inheritedTyping.owner) : conjugated;
168665
+ if (portTypeDef) {
168666
+ for (const inheritedDirection2 of this.effectivePortDirections(portTypeDef, index2, typeConjugated)) {
168667
+ dirs.add(inheritedDirection2);
168668
+ }
168669
+ }
168376
168670
  direction = dirs.size === 1 ? [...dirs][0] : dirs.size > 1 ? "inout" : void 0;
168377
168671
  }
168378
168672
  const port = {
168379
168673
  id: portId,
168380
168674
  name: pn,
168381
- type: typeText(portNode),
168675
+ type: typeText(portNode) ?? (inheritedTyping ? typeText(inheritedTyping.owner) : void 0),
168382
168676
  direction,
168383
- conjugated: isConjugated(portNode) || void 0,
168677
+ conjugated: effectiveConjugated || void 0,
168384
168678
  // REQ-194 — reference ports render with a dashed outline
168385
- ref: (portNode.modifiers ?? []).includes("ref") || void 0,
168679
+ ref: reference || void 0,
168386
168680
  isDef: portNode.isDef === true,
168387
168681
  // issue #108 — a nested port carries its parent's id so the webview
168388
168682
  // stacks it on the parent glyph and docks connectors on it.
@@ -168397,18 +168691,27 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
168397
168691
  // projection origin to choose a direct edit or a usage-local
168398
168692
  // `port :>> name { ... }` materialization.
168399
168693
  meta: {
168400
- declarationId: qnameOf(portNode) || portId,
168694
+ declarationId: nameOf2(portNode) ? qnameOf(portNode) || portId : portId,
168401
168695
  declarationName: pn,
168402
168696
  inheritedFromType,
168697
+ localDeclaration: !inheritedFromType && !!nameOf2(portNode) && !!localUsage && isAstDescendantOrSelf(portNode, localUsage),
168403
168698
  definitionId: portTypeDef ? qnameOf(portTypeDef) : void 0,
168404
168699
  definitionName: portTypeDef ? nameOf2(portTypeDef) : void 0,
168405
- definitionSource: portTypeDef ? sourceOf2(portTypeDef, uri) : void 0
168700
+ definitionSource: portTypeDef ? sourceOf2(portTypeDef, uri) : void 0,
168701
+ ...(() => {
168702
+ const syncDeclaration = this.synchronizationDeclarationOf(portNode, index2);
168703
+ return syncDeclaration && syncDeclaration !== portNode ? {
168704
+ syncDeclarationId: qnameOf(syncDeclaration),
168705
+ syncDeclarationName: effectiveNameOf(syncDeclaration),
168706
+ syncDeclarationSource: sourceOf2(syncDeclaration, uri)
168707
+ } : {};
168708
+ })()
168406
168709
  }
168407
168710
  };
168408
168711
  if (usageName)
168409
168712
  map3.set(`${usageName}.${rel2}`, portId);
168410
168713
  map3.set(`${ownerId}.${rel2}`, portId);
168411
- return { port, portTypeDef };
168714
+ return { port, portTypeDef, inheritedOwners };
168412
168715
  };
168413
168716
  const addNested = (portNode, made, inheritedFromType, path10, depth, seenTypes) => {
168414
168717
  if (depth > NESTED_PORT_MAX_DEPTH)
@@ -168420,8 +168723,8 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
168420
168723
  const nestedSources = [
168421
168724
  // declared in this port usage's body: as local as its parent is
168422
168725
  ...membersOf(portNode).map((member) => ({ member, inherited: inheritedFromType })),
168423
- // declared in the port's type: always a projection of that type
168424
- ...made.portTypeDef && !repeatedType ? membersOf(made.portTypeDef).map((member) => ({ member, inherited: true })) : []
168726
+ // every effective owner contributes its body, nearest first
168727
+ ...!repeatedType ? made.inheritedOwners.flatMap((owner) => membersOf(owner).map((member) => ({ member, inherited: true }))) : []
168425
168728
  ];
168426
168729
  for (const { member, inherited } of nestedSources) {
168427
168730
  if (!isPortDecl(member) || member.isDef === true)
@@ -168451,7 +168754,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
168451
168754
  for (const m of membersOf(node))
168452
168755
  if (isPortDecl(m) && m.isDef !== true)
168453
168756
  addPort(m, false);
168454
- for (const inherited of this.inheritedTypesOf(node, index2)) {
168757
+ for (const inherited of this.inheritedFeatureOwnersOf(node, index2)) {
168455
168758
  for (const m of membersOf(inherited))
168456
168759
  if (isPortDecl(m) && m.isDef !== true)
168457
168760
  addPort(m, true);
@@ -168554,20 +168857,20 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
168554
168857
  inheritedItems(node, index2, uri) {
168555
168858
  if (node.isDef === true)
168556
168859
  return [];
168557
- const def = this.resolveType(node, index2);
168558
- if (!def)
168559
- return [];
168560
- const localRedefined = /* @__PURE__ */ new Set();
168561
- for (const m of membersOf(node)) {
168562
- for (const rel2 of [...m.preRelationships ?? [], ...m.relationships ?? []]) {
168563
- if (rel2.kind === ":>>" || rel2.kind === "redefines") {
168564
- for (const t of rel2.targets ?? [])
168565
- localRedefined.add(lastSeg(t));
168566
- }
168860
+ const hiddenNames = new Set(membersOf(node).map(effectiveNameOf).filter((name) => name !== void 0));
168861
+ const inherited = [];
168862
+ for (const owner of this.inheritedFeatureOwnersOf(node, index2)) {
168863
+ for (const member of membersOf(owner)) {
168864
+ const name = effectiveNameOf(member);
168865
+ if (!name || hiddenNames.has(name))
168866
+ continue;
168867
+ hiddenNames.add(name);
168868
+ if (!isAttributeDecl(member) || member.isDef === true)
168869
+ continue;
168870
+ inherited.push({ member, source: sourceOf2(member, uri) });
168567
168871
  }
168568
168872
  }
168569
- const localNames = new Set(membersOf(node).map((m) => nameOf2(m)).filter(Boolean));
168570
- return membersOf(def).filter((m) => isAttributeDecl(m) && m.isDef !== true && nameOf2(m)).filter((m) => !localRedefined.has(nameOf2(m)) && !localNames.has(nameOf2(m))).map((member) => ({ member, source: sourceOf2(member, uri) }));
168873
+ return inherited;
168571
168874
  }
168572
168875
  compartmentsFor(node, uri, index2, featureRows = false, includeInherited = true) {
168573
168876
  const members = membersOf(node);
@@ -182204,7 +182507,8 @@ function portGlyphRect(g, w, h, topReserve = 0) {
182204
182507
  y: cy - height / 2,
182205
182508
  width,
182206
182509
  height,
182207
- elongated: across > natural
182510
+ elongated: across > natural,
182511
+ proxy: g.port.meta?.proxy === true
182208
182512
  };
182209
182513
  }
182210
182514
  function hostMarkAcrossShift(rect) {
@@ -182212,7 +182516,7 @@ function hostMarkAcrossShift(rect) {
182212
182516
  return -(rect.across / 2 - NESTED_PORT_HOST_CLEAR / 2);
182213
182517
  }
182214
182518
  function portDockAlongShift(rect) {
182215
- if (!rect.elongated) return 0;
182519
+ if (!rect.elongated || rect.proxy) return 0;
182216
182520
  return rect.along / 2 - NESTED_PORT_END_PAD / 2;
182217
182521
  }
182218
182522
  function portDockAt(rect, side, dockSide) {
@@ -182906,8 +183210,8 @@ function collapseNestedPorts(model, expanded2) {
182906
183210
  }).filter((e) => {
182907
183211
  if (e.from === e.to) return false;
182908
183212
  const key = `${e.from}\0${e.to}\0${e.kind}\0${e.label ?? ""}`;
182909
- if (seenEdge.has(key)) return false;
182910
- seenEdge.add(key);
183213
+ if (seenEdge.has(`${key}:${e.id}`)) return false;
183214
+ seenEdge.add(`${key}:${e.id}`);
182911
183215
  return true;
182912
183216
  });
182913
183217
  return {
@@ -182956,11 +183260,17 @@ function assignPortHandles(ports, overrides, ownerShape) {
182956
183260
  label + reserved
182957
183261
  ),
182958
183262
  across: portGlyphAcross(kidMetrics.map((k) => k.across))
183263
+ } : isProxyPort(port) ? {
183264
+ along: Math.max(
183265
+ natural,
183266
+ tw(`${port.conjugated ? "~" : ""}${port.name}`, 9) + 2 * NESTED_PORT_END_PAD + (port.direction ? NESTED_PORT_CHEVRON_RUN : 0)
183267
+ ),
183268
+ across: portGlyphAcross()
182959
183269
  } : { along: natural + reserved, across: natural };
182960
183270
  metrics.set(port.id, m);
182961
183271
  return m;
182962
183272
  };
182963
- const alongOf = (port) => hasToggle(port) ? metricsOf(port).along : void 0;
183273
+ const alongOf = (port) => hasToggle(port) || isProxyPort(port) ? metricsOf(port).along : void 0;
182964
183274
  const place = (list, side) => {
182965
183275
  const n2 = list.length;
182966
183276
  const alongs = list.map(alongOf);
@@ -183219,6 +183529,50 @@ function applyBehaviorFilters(model, filters) {
183219
183529
  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));
183220
183530
  return { ...model, frames: nextFrames, nodes: withoutOrphanedAnnotations(model, nodes, edges), edges };
183221
183531
  }
183532
+ function isProxyPort(port) {
183533
+ return port.meta?.proxy === true;
183534
+ }
183535
+ var PROXY_LAYOUT_PREFIX = "proxy:";
183536
+ function proxyPortFor(port, path10, hostId) {
183537
+ const stand = {
183538
+ ...port,
183539
+ name: path10,
183540
+ layoutKey: `${PROXY_LAYOUT_PREFIX}${hostId}:${port.layoutKey ?? port.id}`,
183541
+ meta: { ...port.meta, proxy: true, proxyFor: port.id, proxyPath: path10, proxyName: port.name }
183542
+ };
183543
+ delete stand.parentPort;
183544
+ return stand;
183545
+ }
183546
+ function proxyPathOf(port, ownerId, hostId, containerLabel, containerOf, portById) {
183547
+ const segments = [port.name];
183548
+ const seenPorts = /* @__PURE__ */ new Set([port.id]);
183549
+ for (let cur = port.parentPort; cur !== void 0 && !seenPorts.has(cur); cur = portById.get(cur)?.parentPort) {
183550
+ seenPorts.add(cur);
183551
+ const parent = portById.get(cur);
183552
+ if (!parent) break;
183553
+ segments.unshift(parent.name);
183554
+ }
183555
+ const seen = /* @__PURE__ */ new Set();
183556
+ for (let cur = ownerId; cur !== void 0 && cur !== hostId && !seen.has(cur); cur = containerOf(cur)) {
183557
+ seen.add(cur);
183558
+ const label = containerLabel(cur);
183559
+ if (label) segments.unshift(label);
183560
+ }
183561
+ return segments.join(".");
183562
+ }
183563
+ function proxyPortsByHost(referenced, hostOf, ownerOf, containerLabel, containerOf, portById) {
183564
+ const byHost = /* @__PURE__ */ new Map();
183565
+ for (const portId of referenced) {
183566
+ const host = hostOf.get(portId);
183567
+ const entry = ownerOf.get(portId);
183568
+ if (host === void 0 || entry === void 0) continue;
183569
+ const path10 = proxyPathOf(entry.port, entry.owner, host, containerLabel, containerOf, portById);
183570
+ const list = byHost.get(host);
183571
+ if (list) list.push(proxyPortFor(entry.port, path10, host));
183572
+ else byHost.set(host, [proxyPortFor(entry.port, path10, host)]);
183573
+ }
183574
+ return byHost;
183575
+ }
183222
183576
  function collapseIvModel(model, hiddenInternals) {
183223
183577
  const frames = model.frames ?? [];
183224
183578
  if (!frames.length) return model;
@@ -183248,12 +183602,72 @@ function collapseIvModel(model, hiddenInternals) {
183248
183602
  };
183249
183603
  const hiddenFrameIds = new Set(frames.filter((f) => belongsToCollapsedRoot(f.id, false)).map((f) => f.id));
183250
183604
  const hiddenNodeIds = new Set(model.nodes.filter((n2) => belongsToCollapsedRoot(n2.frame ?? n2.parent, true)).map((n2) => n2.id));
183251
- const hiddenEndpoints = /* @__PURE__ */ new Set([...hiddenFrameIds, ...hiddenNodeIds]);
183252
- for (const f of frames) if (hiddenFrameIds.has(f.id)) for (const p of f.ports ?? []) hiddenEndpoints.add(p.id);
183253
- for (const n2 of model.nodes) if (hiddenNodeIds.has(n2.id)) for (const p of n2.ports ?? []) hiddenEndpoints.add(p.id);
183605
+ const nodeById = new Map(model.nodes.map((n2) => [n2.id, n2]));
183606
+ const containerOf = (id2) => {
183607
+ const frame2 = frameById.get(id2);
183608
+ if (frame2) return frame2.parent;
183609
+ const node = nodeById.get(id2);
183610
+ return node ? node.frame ?? node.parent : void 0;
183611
+ };
183612
+ const containerLabel = (id2) => frameById.get(id2)?.label ?? nodeById.get(id2)?.name;
183613
+ const rootFor = (id2) => {
183614
+ const seen = /* @__PURE__ */ new Set();
183615
+ for (let cur = id2; cur !== void 0 && !seen.has(cur); cur = containerOf(cur)) {
183616
+ if (roots.has(cur)) return cur;
183617
+ seen.add(cur);
183618
+ }
183619
+ return void 0;
183620
+ };
183621
+ const ownerOfHiddenPort = /* @__PURE__ */ new Map();
183622
+ for (const f of frames) if (hiddenFrameIds.has(f.id)) for (const p of f.ports ?? []) ownerOfHiddenPort.set(p.id, { port: p, owner: f.id });
183623
+ for (const n2 of model.nodes) if (hiddenNodeIds.has(n2.id)) for (const p of n2.ports ?? []) ownerOfHiddenPort.set(p.id, { port: p, owner: n2.id });
183624
+ const hiddenPortById = new Map([...ownerOfHiddenPort].map(([id2, entry]) => [id2, entry.port]));
183625
+ const proxyHost = /* @__PURE__ */ new Map();
183626
+ for (const [portId, entry] of ownerOfHiddenPort) {
183627
+ const root4 = rootFor(entry.owner);
183628
+ if (root4 !== void 0) proxyHost.set(portId, root4);
183629
+ }
183630
+ const bodyDock = /* @__PURE__ */ new Map();
183631
+ for (const id2 of [...hiddenFrameIds, ...hiddenNodeIds]) {
183632
+ const root4 = rootFor(id2);
183633
+ if (root4 !== void 0) bodyDock.set(id2, root4);
183634
+ }
183635
+ const hidden = /* @__PURE__ */ new Set([...hiddenFrameIds, ...hiddenNodeIds, ...ownerOfHiddenPort.keys()]);
183636
+ const containerRootOf = (id2) => proxyHost.get(id2) ?? bodyDock.get(id2);
183637
+ const seenEdge = /* @__PURE__ */ new Set();
183638
+ const edges = model.edges.filter((e) => {
183639
+ const fromRoot = containerRootOf(e.from);
183640
+ const toRoot = containerRootOf(e.to);
183641
+ if (fromRoot !== void 0 && fromRoot === toRoot) return false;
183642
+ return !(hidden.has(e.from) && fromRoot === void 0) && !(hidden.has(e.to) && toRoot === void 0);
183643
+ }).map((e) => {
183644
+ const from = bodyDock.get(e.from) ?? e.from;
183645
+ const to = bodyDock.get(e.to) ?? e.to;
183646
+ return from === e.from && to === e.to ? e : { ...e, from, to };
183647
+ }).filter((e) => {
183648
+ if (e.from === e.to) return false;
183649
+ const key = `${e.from}\0${e.to}\0${e.kind}\0${e.label ?? ""}`;
183650
+ if (seenEdge.has(`${key}:${e.id}`)) return false;
183651
+ seenEdge.add(`${key}:${e.id}`);
183652
+ return true;
183653
+ });
183654
+ const referenced = /* @__PURE__ */ new Set();
183655
+ for (const e of edges) {
183656
+ if (proxyHost.has(e.from)) referenced.add(e.from);
183657
+ if (proxyHost.has(e.to)) referenced.add(e.to);
183658
+ }
183659
+ const proxies = proxyPortsByHost(
183660
+ referenced,
183661
+ proxyHost,
183662
+ ownerOfHiddenPort,
183663
+ containerLabel,
183664
+ containerOf,
183665
+ hiddenPortById
183666
+ );
183254
183667
  const collapsedNodes = [...roots].flatMap((id2) => {
183255
183668
  const f = frameById.get(id2);
183256
183669
  if (!f) return [];
183670
+ const stand = proxies.get(id2) ?? [];
183257
183671
  return [{
183258
183672
  id: f.id,
183259
183673
  layoutKey: f.layoutKey,
@@ -183263,7 +183677,7 @@ function collapseIvModel(model, hiddenInternals) {
183263
183677
  shape: "box",
183264
183678
  type: f.type,
183265
183679
  multiplicity: f.multiplicity,
183266
- ports: f.ports,
183680
+ ports: stand.length ? [...f.ports ?? [], ...stand] : f.ports,
183267
183681
  compartments: f.compartments,
183268
183682
  frame: f.parent,
183269
183683
  source: f.source,
@@ -183274,7 +183688,7 @@ function collapseIvModel(model, hiddenInternals) {
183274
183688
  ...model,
183275
183689
  nodes: [...model.nodes.filter((n2) => !hiddenNodeIds.has(n2.id)), ...collapsedNodes],
183276
183690
  frames: frames.filter((f) => !roots.has(f.id) && !hiddenFrameIds.has(f.id)),
183277
- edges: model.edges.filter((e) => !hiddenEndpoints.has(e.from) && !hiddenEndpoints.has(e.to))
183691
+ edges
183278
183692
  };
183279
183693
  }
183280
183694
  function isCollapsibleActionFrame(frame2) {
@@ -183356,13 +183770,18 @@ function collapseActionFrames(model, hiddenInternals, isHost = isCollapsibleActi
183356
183770
  };
183357
183771
  const roots = new Set([...requested].filter((id2) => rootOf(frameById.get(id2)?.parent) === void 0));
183358
183772
  const dockOf = /* @__PURE__ */ new Map();
183773
+ const proxyHost = /* @__PURE__ */ new Map();
183774
+ const ownerOfHiddenPort = /* @__PURE__ */ new Map();
183359
183775
  const hiddenFrameIds = /* @__PURE__ */ new Set();
183360
183776
  for (const f of frames) {
183361
183777
  const root4 = roots.has(f.id) ? rootOf(f.parent) : rootOf(f.id);
183362
183778
  if (root4 === void 0) continue;
183363
183779
  hiddenFrameIds.add(f.id);
183364
183780
  dockOf.set(f.id, root4);
183365
- for (const p of f.ports ?? []) dockOf.set(p.id, root4);
183781
+ for (const p of f.ports ?? []) {
183782
+ proxyHost.set(p.id, root4);
183783
+ ownerOfHiddenPort.set(p.id, { port: p, owner: f.id });
183784
+ }
183366
183785
  }
183367
183786
  const hiddenNodeIds = /* @__PURE__ */ new Set();
183368
183787
  for (const n2 of model.nodes) {
@@ -183370,15 +183789,59 @@ function collapseActionFrames(model, hiddenInternals, isHost = isCollapsibleActi
183370
183789
  if (root4 === void 0) continue;
183371
183790
  hiddenNodeIds.add(n2.id);
183372
183791
  dockOf.set(n2.id, root4);
183373
- for (const p of n2.ports ?? []) dockOf.set(p.id, root4);
183792
+ for (const p of n2.ports ?? []) {
183793
+ proxyHost.set(p.id, root4);
183794
+ ownerOfHiddenPort.set(p.id, { port: p, owner: n2.id });
183795
+ }
183374
183796
  }
183375
183797
  for (const id2 of roots) {
183376
183798
  dockOf.delete(id2);
183377
- for (const p of frameById.get(id2)?.ports ?? []) dockOf.delete(p.id);
183799
+ for (const p of frameById.get(id2)?.ports ?? []) {
183800
+ proxyHost.delete(p.id);
183801
+ ownerOfHiddenPort.delete(p.id);
183802
+ }
183378
183803
  }
183804
+ const nodeById = new Map(model.nodes.map((n2) => [n2.id, n2]));
183805
+ const containerOf = (id2) => {
183806
+ const frame2 = frameById.get(id2);
183807
+ if (frame2) return frame2.parent;
183808
+ return nodeById.get(id2)?.frame;
183809
+ };
183810
+ const containerLabel = (id2) => frameById.get(id2)?.label ?? nodeById.get(id2)?.name;
183811
+ const hiddenPortById = new Map([...ownerOfHiddenPort].map(([id2, entry]) => [id2, entry.port]));
183812
+ const containerRootOf = (id2) => proxyHost.get(id2) ?? dockOf.get(id2);
183813
+ const seenEdge = /* @__PURE__ */ new Set();
183814
+ const edges = model.edges.filter((e) => {
183815
+ const fromRoot = containerRootOf(e.from);
183816
+ return fromRoot === void 0 || fromRoot !== containerRootOf(e.to);
183817
+ }).map((e) => {
183818
+ const from = dockOf.get(e.from) ?? e.from;
183819
+ const to = dockOf.get(e.to) ?? e.to;
183820
+ return from === e.from && to === e.to ? e : { ...e, from, to };
183821
+ }).filter((e) => {
183822
+ if (e.from === e.to) return false;
183823
+ const key = `${e.from}\0${e.to}\0${e.kind}\0${e.label ?? ""}`;
183824
+ if (seenEdge.has(`${key}:${e.id}`)) return false;
183825
+ seenEdge.add(`${key}:${e.id}`);
183826
+ return true;
183827
+ });
183828
+ const referenced = /* @__PURE__ */ new Set();
183829
+ for (const e of edges) {
183830
+ if (proxyHost.has(e.from)) referenced.add(e.from);
183831
+ if (proxyHost.has(e.to)) referenced.add(e.to);
183832
+ }
183833
+ const proxies = proxyPortsByHost(
183834
+ referenced,
183835
+ proxyHost,
183836
+ ownerOfHiddenPort,
183837
+ containerLabel,
183838
+ containerOf,
183839
+ hiddenPortById
183840
+ );
183379
183841
  const collapsedNodes = [...roots].flatMap((id2) => {
183380
183842
  const f = frameById.get(id2);
183381
183843
  if (!f) return [];
183844
+ const stand = proxies.get(id2) ?? [];
183382
183845
  return [{
183383
183846
  id: f.id,
183384
183847
  layoutKey: f.layoutKey,
@@ -183388,25 +183851,13 @@ function collapseActionFrames(model, hiddenInternals, isHost = isCollapsibleActi
183388
183851
  shape: collapsedShape,
183389
183852
  type: f.type,
183390
183853
  multiplicity: f.multiplicity,
183391
- ports: f.ports,
183854
+ ports: stand.length ? [...f.ports ?? [], ...stand] : f.ports,
183392
183855
  compartments: f.compartments,
183393
183856
  frame: f.parent,
183394
183857
  source: f.source,
183395
183858
  meta: { ...f.meta, internalsHidden: true }
183396
183859
  }];
183397
183860
  });
183398
- const seenEdge = /* @__PURE__ */ new Set();
183399
- const edges = model.edges.map((e) => {
183400
- const from = dockOf.get(e.from) ?? e.from;
183401
- const to = dockOf.get(e.to) ?? e.to;
183402
- return from === e.from && to === e.to ? e : { ...e, from, to };
183403
- }).filter((e) => {
183404
- if (e.from === e.to) return false;
183405
- const key = `${e.from} ${e.to} ${e.kind} ${e.label ?? ""}`;
183406
- if (seenEdge.has(key)) return false;
183407
- seenEdge.add(key);
183408
- return true;
183409
- });
183410
183861
  return {
183411
183862
  ...model,
183412
183863
  nodes: [...model.nodes.filter((n2) => !hiddenNodeIds.has(n2.id)), ...collapsedNodes],
@@ -183564,7 +184015,7 @@ function modelToFlow(model, opts) {
183564
184015
  const base = isGeo ? { w: 24, h: 24 } : nodeSize(canvasNode, opts.direction);
183565
184016
  const sizeOverride = ov[n2.layoutKey ?? n2.id];
183566
184017
  const compactCollapsed = canvasNode.meta?.internalsHidden === true;
183567
- const presentationOverride = compactCollapsed && sizeOverride ? { ...sizeOverride, h: void 0 } : sizeOverride;
184018
+ const presentationOverride = compactCollapsed && sizeOverride ? { ...sizeOverride, w: void 0, h: void 0 } : sizeOverride;
183568
184019
  const projectedSize = isCircularControlShape(canvasNode.shape) ? base : isForkJoinShape(canvasNode.shape) ? forkJoinSizeWithOverride(presentationOverride, opts.direction) : sizeWithOverride(
183569
184020
  base,
183570
184021
  presentationOverride,
@@ -183573,7 +184024,20 @@ function modelToFlow(model, opts) {
183573
184024
  h: visibleFeatureH > 0 ? base.h : 24
183574
184025
  }
183575
184026
  );
183576
- const size = model.kind === "gv" && canvasNode.shape !== "package" ? { ...projectedSize, w: Math.min(projectedSize.w, GV_NODE_MAX_WIDTH) } : projectedSize;
184027
+ const compactPortHandles = compactCollapsed ? assignPortHandles(canvasNode.ports, opts.portOverrides, canvasNode.shape) : [];
184028
+ const compactPortWidth = Math.max(
184029
+ portedSideLength(compactPortHandles, "top"),
184030
+ portedSideLength(compactPortHandles, "bottom")
184031
+ );
184032
+ const compactPortHeight = Math.max(
184033
+ portedSideLength(compactPortHandles, "left"),
184034
+ portedSideLength(compactPortHandles, "right")
184035
+ );
184036
+ const size = model.kind === "gv" && canvasNode.shape !== "package" ? { ...projectedSize, w: Math.min(projectedSize.w, GV_NODE_MAX_WIDTH) } : compactCollapsed ? {
184037
+ ...projectedSize,
184038
+ w: Math.max(compactPortWidth, Math.min(projectedSize.w, GV_NODE_MAX_WIDTH)),
184039
+ h: Math.max(compactPortHeight, projectedSize.h)
184040
+ } : projectedSize;
183577
184041
  const parentId = n2.frame ?? (model.kind === "gv" && n2.parent && gvPackageIds.has(n2.parent) ? n2.parent : void 0) ?? (boundary ? boundary.id : void 0);
183578
184042
  nodes.push({
183579
184043
  id: n2.id,
@@ -197549,6 +198013,12 @@ body {
197549
198013
 
197550
198014
  /* REQ-194 \u2014 port variants: dashed reference ports, direction chevrons */
197551
198015
  .dnode-port.ref { stroke-dasharray: 2 2; }
198016
+ /* REQ-400 \u2014 a PROXY stands in for a port inside collapsed contents.
198017
+ * It is drawn hollow with a fine dotted outline, so it reads as a place a
198018
+ * connector docks rather than as an element that is really on the boundary. Its
198019
+ * dot pattern is deliberately finer than the reference port's dash. */
198020
+ .dnode-port.proxy { fill: none; stroke-dasharray: 1 2; stroke-width: 1.2; }
198021
+ .dnode-port.proxy.selected { fill: var(--accent); fill-opacity: 0.35; }
197552
198022
  /* REQ-376 \u2014 an action pin takes the OUTLINE and explicit fill of the action it sits
197553
198023
  * on rather than the flow colour (user direction 2026-08-09). Its rounded corners and its
197554
198024
  * direction arrow come from the shared port path in nodes.tsx. */
@@ -198534,6 +199004,21 @@ function sizeOf(node) {
198534
199004
  h: node.measured?.height ?? node.height ?? node.data.h
198535
199005
  };
198536
199006
  }
199007
+ function exportedNodeColorClass(node) {
199008
+ const frame2 = node.data.frame;
199009
+ if (frame2) {
199010
+ return diagramElementColorClass(diagramElementColorTypeForFrame(frame2.keyword, {
199011
+ boundary: frame2.meta?.boundaryBox === true,
199012
+ exhibitor: frame2.meta?.exhibitBoundary === true,
199013
+ loop: frame2.meta?.loop === true,
199014
+ parallel: frame2.meta?.parallel === true,
199015
+ performer: frame2.meta?.performerLane === true,
199016
+ structured: frame2.meta?.structuredControl === true
199017
+ }));
199018
+ }
199019
+ const semantic = node.data.node;
199020
+ return diagramElementColorClass(semantic ? diagramElementColorTypeForNode(semantic.shape, semantic.keyword) : "default");
199021
+ }
198537
199022
  function labelExtent(text) {
198538
199023
  return { w: Math.max(8, text.length * 6.2) / 2, h: 7 };
198539
199024
  }
@@ -198569,7 +199054,7 @@ function buildDiagramSvg(options) {
198569
199054
  extend2(p.x + background.x, p.y + background.y, background.width, background.height);
198570
199055
  }
198571
199056
  const body = nodeMarkup(node);
198572
- if (body) nodeParts.push(`<g transform="translate(${Math.round(p.x)},${Math.round(p.y)})">${body}</g>`);
199057
+ if (body) nodeParts.push(`<g transform="translate(${Math.round(p.x)},${Math.round(p.y)})" class="${exportedNodeColorClass(node)}">${body}</g>`);
198573
199058
  }
198574
199059
  if (!isFinite(minX)) return null;
198575
199060
  const edgeParts = [];
@@ -198952,6 +199437,7 @@ function normalizeSideCar(value) {
198952
199437
  const next = {};
198953
199438
  if (state.mode !== void 0) next.mode = state.mode;
198954
199439
  if (state.zoom !== void 0) next.zoom = state.zoom;
199440
+ if (state.showGrid !== void 0) next.showGrid = state.showGrid;
198955
199441
  const dir = sanitizeDirection(state.direction);
198956
199442
  if (dir !== void 0) next.direction = dir;
198957
199443
  if (state.hiddenInternals !== void 0) next.hiddenInternals = state.hiddenInternals;
@@ -200373,6 +200859,7 @@ function PortGlyph({ ph, w, h, topReserve = 0, showLabels, selected: selected2,
200373
200859
  len
200374
200860
  };
200375
200861
  })() : void 0;
200862
+ const proxy = rect.proxy;
200376
200863
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
200377
200864
  "g",
200378
200865
  {
@@ -200382,7 +200869,7 @@ function PortGlyph({ ph, w, h, topReserve = 0, showLabels, selected: selected2,
200382
200869
  e.stopPropagation();
200383
200870
  onSelect(ph.port.id);
200384
200871
  } : void 0,
200385
- onContextMenu: onContext ? (e) => {
200872
+ onContextMenu: onContext && !proxy ? (e) => {
200386
200873
  e.preventDefault();
200387
200874
  e.stopPropagation();
200388
200875
  onContext(ph.port.id, e.clientX, e.clientY);
@@ -200405,7 +200892,7 @@ function PortGlyph({ ph, w, h, topReserve = 0, showLabels, selected: selected2,
200405
200892
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
200406
200893
  "rect",
200407
200894
  {
200408
- className: `dnode-port${ph.port.pin ? " pin" : ""}${ph.port.ref ? " ref" : ""}${rect.elongated ? " host" : ""}${selected2 ? " selected" : ""}${hovered ? " hovered" : ""}${moving ? " moving" : ""}${connectTargetSide ? " connect-target" : ""}`,
200895
+ className: `dnode-port${ph.port.pin ? " pin" : ""}${ph.port.ref ? " ref" : ""}${rect.elongated ? " host" : ""}${proxy ? " proxy" : ""}${selected2 ? " selected" : ""}${hovered ? " hovered" : ""}${moving ? " moving" : ""}${connectTargetSide ? " connect-target" : ""}`,
200409
200896
  x: rect.x,
200410
200897
  y: rect.y,
200411
200898
  width: rect.width,
@@ -200418,7 +200905,7 @@ function PortGlyph({ ph, w, h, topReserve = 0, showLabels, selected: selected2,
200418
200905
  d === "out" || d === "inout" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { className: "dport-dir head", d: arrowHead(1) }) : "",
200419
200906
  d === "in" || d === "inout" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { className: "dport-dir head", d: arrowHead(-1) }) : ""
200420
200907
  ] }) : "",
200421
- selected2 && connectStart && !connectTargetSide ? (() => {
200908
+ selected2 && connectStart && !connectTargetSide && !proxy ? (() => {
200422
200909
  const px = x + v.x * (half + PORT_PLUS_GAP);
200423
200910
  const py = y + v.y * (half + PORT_PLUS_GAP);
200424
200911
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { className: "dport-plus", children: [
@@ -200868,7 +201355,8 @@ function SysmlNode({ id: id2, data, draggable, selected: selected2, width, heigh
200868
201355
  node.shape === "initial" || node.shape === "final" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "rf-circular-control-hit", "aria-hidden": "true" }) : null,
200869
201356
  ports.flatMap((ph) => {
200870
201357
  const rect = portGlyphRect(ph, w, h, featureCompartmentHeight);
200871
- const startable = directRelationForHandle(data.kind, {
201358
+ const proxied = isProxyPort(ph.port);
201359
+ const startable = !proxied && directRelationForHandle(data.kind, {
200872
201360
  id: ph.port.id,
200873
201361
  name: ph.port.name,
200874
201362
  keyword: ph.port.pin ? "pin" : "port",
@@ -200889,7 +201377,8 @@ function SysmlNode({ id: id2, data, draggable, selected: selected2, width, heigh
200889
201377
  x: outer.x,
200890
201378
  y: outer.y,
200891
201379
  kind: "port",
200892
- active: revealBoth || ph.port.id === connectTargetPortId && connectTargetPortSide === ph.side,
201380
+ connectable: !proxied,
201381
+ active: !proxied && (revealBoth || ph.port.id === connectTargetPortId && connectTargetPortSide === ph.side),
200893
201382
  startable
200894
201383
  },
200895
201384
  `${ph.port.id}-out`
@@ -200902,7 +201391,8 @@ function SysmlNode({ id: id2, data, draggable, selected: selected2, width, heigh
200902
201391
  x: inner.x,
200903
201392
  y: inner.y,
200904
201393
  kind: "port",
200905
- active: revealBoth || ph.port.id === connectTargetPortId && connectTargetPortSide === innerSide,
201394
+ connectable: !proxied,
201395
+ active: !proxied && (revealBoth || ph.port.id === connectTargetPortId && connectTargetPortSide === innerSide),
200906
201396
  startable
200907
201397
  },
200908
201398
  `${ph.port.id}-in`
@@ -200912,17 +201402,21 @@ function SysmlNode({ id: id2, data, draggable, selected: selected2, width, heigh
200912
201402
  ctx.onPortMove ? ports.map((ph) => {
200913
201403
  const rect = portGlyphRect(ph, w, h, featureCompartmentHeight);
200914
201404
  const nestedChild = ph.port.parentPort !== void 0;
201405
+ const proxyPort = isProxyPort(ph.port);
200915
201406
  const strip = portInteractionStrip(rect, ph.side);
200916
201407
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
200917
201408
  "div",
200918
201409
  {
200919
201410
  className: "port-drag-hit nodrag",
200920
201411
  style: { position: "absolute", left: strip.cx, top: strip.cy, width: strip.w, height: strip.h, transform: "translate(-50%,-50%)" },
200921
- title: nestedChild ? `${ph.port.name} - click to select; drag a dot to connect (moves with its parent port)` : `${ph.port.name} - drag the centre to move along the edge; drag a dot to connect; click to select`,
201412
+ title: proxyPort ? `${ph.port.name} - a proxy for a port inside the collapsed contents; drag the centre to move it, click to select the port it stands for` : nestedChild ? `${ph.port.name} - click to select; drag a dot to connect (moves with its parent port)` : `${ph.port.name} - drag the centre to move along the edge; drag a dot to connect; click to select`,
200922
201413
  onPointerEnter: () => setHoveredPortId(ph.port.id),
200923
201414
  onPointerLeave: () => setHoveredPortId((cur) => cur === ph.port.id ? void 0 : cur),
200924
201415
  onPointerDown: (e) => onPortPointerDown(ph.port.id, e, { side: ph.side, offset: ph.offset }, !nestedChild),
200925
- onContextMenu: (e) => {
201416
+ onContextMenu: proxyPort ? (e) => {
201417
+ e.preventDefault();
201418
+ e.stopPropagation();
201419
+ } : (e) => {
200926
201420
  e.preventDefault();
200927
201421
  e.stopPropagation();
200928
201422
  ctx.onContextNode(ph.port.id, e.clientX, e.clientY);
@@ -201349,7 +201843,8 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
201349
201843
  }),
201350
201844
  showPorts ? ports.flatMap((ph) => {
201351
201845
  const rect = portGlyphRect(ph, w, h, featureCompartmentHeight);
201352
- const startable = directRelationForHandle(data.kind, {
201846
+ const proxied = isProxyPort(ph.port);
201847
+ const startable = !proxied && directRelationForHandle(data.kind, {
201353
201848
  id: ph.port.id,
201354
201849
  name: ph.port.name,
201355
201850
  keyword: ph.port.pin ? "pin" : "port",
@@ -201370,7 +201865,8 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
201370
201865
  x: outer.x,
201371
201866
  y: outer.y,
201372
201867
  kind: "port",
201373
- active: revealBoth || ph.port.id === connectTargetPortId && connectTargetPortSide === ph.side,
201868
+ connectable: !proxied,
201869
+ active: !proxied && (revealBoth || ph.port.id === connectTargetPortId && connectTargetPortSide === ph.side),
201374
201870
  startable
201375
201871
  },
201376
201872
  `${ph.port.id}-out`
@@ -201383,7 +201879,8 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
201383
201879
  x: inner.x,
201384
201880
  y: inner.y,
201385
201881
  kind: "port",
201386
- active: revealBoth || ph.port.id === connectTargetPortId && connectTargetPortSide === innerSide,
201882
+ connectable: !proxied,
201883
+ active: !proxied && (revealBoth || ph.port.id === connectTargetPortId && connectTargetPortSide === innerSide),
201387
201884
  startable
201388
201885
  },
201389
201886
  `${ph.port.id}-in`
@@ -201393,17 +201890,21 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
201393
201890
  ctx.onPortMove ? ports.map((ph) => {
201394
201891
  const rect = portGlyphRect(ph, w, h, featureCompartmentHeight);
201395
201892
  const nestedChild = ph.port.parentPort !== void 0;
201893
+ const proxyPort = isProxyPort(ph.port);
201396
201894
  const strip = portInteractionStrip(rect, ph.side);
201397
201895
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
201398
201896
  "div",
201399
201897
  {
201400
201898
  className: "port-drag-hit nodrag",
201401
201899
  style: { position: "absolute", left: strip.cx, top: strip.cy, width: strip.w, height: strip.h, transform: "translate(-50%,-50%)" },
201402
- title: nestedChild ? `${ph.port.name} - click to select; drag a dot to connect (moves with its parent port)` : `${ph.port.name} - drag the centre to move along the edge; drag a dot to connect; click to select`,
201900
+ title: proxyPort ? `${ph.port.name} - a proxy for a port inside the collapsed contents; drag the centre to move it, click to select the port it stands for` : nestedChild ? `${ph.port.name} - click to select; drag a dot to connect (moves with its parent port)` : `${ph.port.name} - drag the centre to move along the edge; drag a dot to connect; click to select`,
201403
201901
  onPointerEnter: () => setHoveredPortId(ph.port.id),
201404
201902
  onPointerLeave: () => setHoveredPortId((cur) => cur === ph.port.id ? void 0 : cur),
201405
201903
  onPointerDown: (e) => onPortPointerDown(ph.port.id, e, { side: ph.side, offset: ph.offset }, !nestedChild),
201406
- onContextMenu: (e) => {
201904
+ onContextMenu: proxyPort ? (e) => {
201905
+ e.preventDefault();
201906
+ e.stopPropagation();
201907
+ } : (e) => {
201407
201908
  e.preventDefault();
201408
201909
  e.stopPropagation();
201409
201910
  ctx.onContextNode(ph.port.id, e.clientX, e.clientY);
@@ -201777,7 +202278,7 @@ async function runExport(command) {
201777
202278
  }
201778
202279
 
201779
202280
  // src/main.ts
201780
- var VERSION2 = true ? "0.21.0" : "dev";
202281
+ var VERSION2 = true ? "0.21.1" : "dev";
201781
202282
  function display(file) {
201782
202283
  const rel2 = path9.relative(process.cwd(), file);
201783
202284
  return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;