sysml-diagram 0.14.5 → 0.15.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 +974 -279
- package/out/main.js.map +3 -3
- package/package.json +1 -2
- package/resources/sysml.dimension-table.json +1 -1
package/out/main.js
CHANGED
|
@@ -161748,6 +161748,12 @@ function keywordFor(node) {
|
|
|
161748
161748
|
const parallel = isParallelState(node) ? "parallel " : "";
|
|
161749
161749
|
const leadMods = [variability, temporal].filter(Boolean);
|
|
161750
161750
|
const prefix = leadMods.length ? leadMods.map((m) => `${m} `).join("") : parallel;
|
|
161751
|
+
if (t === "BareDefDecl")
|
|
161752
|
+
return `${prefix}def`.trim();
|
|
161753
|
+
if (t === "FeatureShorthand") {
|
|
161754
|
+
const kinds = (Array.isArray(n2.usageKinds) ? n2.usageKinds : []).join(" ");
|
|
161755
|
+
return `${prefix}${kinds}`.trim() || "feature";
|
|
161756
|
+
}
|
|
161751
161757
|
if (t === "ActorDecl" || t === "SubjectDecl" || t === "StakeholderDecl")
|
|
161752
161758
|
return `${prefix}${word}`;
|
|
161753
161759
|
return def ? `${prefix}${word} def` : `${prefix}${word}`;
|
|
@@ -161756,7 +161762,39 @@ var isDefinitionKind = (node) => isPartDecl(node) || isPortDecl(node) || isItemD
|
|
|
161756
161762
|
// genuine SysML definitions (FlowConnectionDefinition / AssociationStructure /
|
|
161757
161763
|
// AllocationDefinition) and belong in the General View like any other def.
|
|
161758
161764
|
isFlowStmt(node) || isConnectorDecl(node) || isAllocationDecl(node) || isConstraintDecl(node) || isEnumDecl(node) || isStateDecl(node) || isActionDecl(node) || isCalcDecl(node) || isConcernDecl(node) || isViewDecl(node) || isViewpointDecl(node) || isRenderingDecl(node) || isMetadataDecl(node);
|
|
161759
|
-
var
|
|
161765
|
+
var isBareDefDecl = (node) => node.$type === "BareDefDecl";
|
|
161766
|
+
var isDefinitionNode = (node) => isDefinitionKind(node) && node.isDef === true || isBareDefDecl(node);
|
|
161767
|
+
var modifiersOf = (node) => {
|
|
161768
|
+
const mods = node.modifiers;
|
|
161769
|
+
return Array.isArray(mods) ? mods : [];
|
|
161770
|
+
};
|
|
161771
|
+
var portionKindOf = (node) => modifiersOf(node).find((m) => m === "timeslice" || m === "snapshot");
|
|
161772
|
+
var isIndividualOccurrence = (node) => modifiersOf(node).includes("individual");
|
|
161773
|
+
var isOccurrenceModified = (node) => portionKindOf(node) !== void 0 || isIndividualOccurrence(node);
|
|
161774
|
+
var redefinedNameOf = (node) => {
|
|
161775
|
+
const n2 = node;
|
|
161776
|
+
for (const rel2 of [...n2.preRelationships ?? [], ...n2.relationships ?? []]) {
|
|
161777
|
+
if (rel2.kind === ":>>" || rel2.kind === "redefines") {
|
|
161778
|
+
const target = (rel2.targets ?? [])[0];
|
|
161779
|
+
if (target)
|
|
161780
|
+
return lastSeg(target);
|
|
161781
|
+
}
|
|
161782
|
+
}
|
|
161783
|
+
return void 0;
|
|
161784
|
+
};
|
|
161785
|
+
var portionLabelOf = (node) => nameOf2(node) ?? (isOccurrenceModified(node) ? redefinedNameOf(node) : void 0);
|
|
161786
|
+
function diagramNodeId(node) {
|
|
161787
|
+
const name = nameOf2(node);
|
|
161788
|
+
if (name)
|
|
161789
|
+
return qnameOf(node) || name;
|
|
161790
|
+
const label = portionLabelOf(node);
|
|
161791
|
+
if (!label)
|
|
161792
|
+
return void 0;
|
|
161793
|
+
const ownerQname = qnameOf(node);
|
|
161794
|
+
return ownerQname ? `${ownerQname}::${label}` : label;
|
|
161795
|
+
}
|
|
161796
|
+
var isDeclaredEventOccurrence = (m) => isEventDecl(m) && m.isOccurrence === true;
|
|
161797
|
+
var isFeatureUsageMember = (m, owner) => isPartDecl(m) || isPortDecl(m) || isItemDecl(m) || isAttributeDecl(m) || isOccurrenceDecl(m) || isDeclaredEventOccurrence(m) || isStateDecl(m) && !isExhibitStateDecl(m) || isActionDecl(m) || isCalcDecl(m) || isConstraintDecl(m) || isRequirementDecl(m) || isConcernDecl(m) || isViewDecl(m) || isViewpointDecl(m) || isRenderingDecl(m) || isUseCaseDecl(m) || isAnalysisCaseDecl(m) || isVerificationCaseDecl(m) || isCaseDecl(m) || isConnectionDecl(m) || isInterfaceDecl(m) || isAllocationDecl(m) || isEnumDecl(m) && !isEnumDecl(owner);
|
|
161760
161798
|
function specializationTargets(node) {
|
|
161761
161799
|
const n2 = node;
|
|
161762
161800
|
const out = [];
|
|
@@ -162316,7 +162354,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
162316
162354
|
return false;
|
|
162317
162355
|
}
|
|
162318
162356
|
const scope = this.packageScopeOf(node);
|
|
162319
|
-
return [...ast_utils_exports.streamAllContents(scope)].some((n2) =>
|
|
162357
|
+
return [...ast_utils_exports.streamAllContents(scope)].some((n2) => isDefinitionNode(n2) && nameOf2(n2) || this.isViewlessUsage(n2) && this.isDirectPackageMember(n2) || isPartDecl(n2) && n2.isDef !== true && !!nameOf2(n2) && this.isDirectPackageMember(n2));
|
|
162320
162358
|
}
|
|
162321
162359
|
case "iv":
|
|
162322
162360
|
if (isPartDecl(node)) {
|
|
@@ -162387,6 +162425,8 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
162387
162425
|
// they get their graphical home as General View usage nodes — previously a
|
|
162388
162426
|
// package-level `constraint massLimitation { … }` was invisible everywhere.
|
|
162389
162427
|
isViewlessUsage(n2) {
|
|
162428
|
+
if (n2.$type === "FeatureShorthand" && isOccurrenceModified(n2) && nameOf2(n2) !== void 0)
|
|
162429
|
+
return true;
|
|
162390
162430
|
return (isConstraintDecl(n2) || isCalcDecl(n2) || isOccurrenceDecl(n2) || isItemDecl(n2) || isAttributeDecl(n2)) && n2.isDef !== true && nameOf2(n2) !== void 0;
|
|
162391
162431
|
}
|
|
162392
162432
|
isDirectPackageMember(n2) {
|
|
@@ -162411,9 +162451,9 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
162411
162451
|
const { uri, index: index2 } = ctx;
|
|
162412
162452
|
const scope = this.packageScopeOf(ctx.anchor);
|
|
162413
162453
|
const all = [...ast_utils_exports.streamAllContents(scope)];
|
|
162414
|
-
const defNodes = all.filter((n2) =>
|
|
162454
|
+
const defNodes = all.filter((n2) => isDefinitionNode(n2) && nameOf2(n2));
|
|
162415
162455
|
const packageOverview = isPackage(ctx.anchor) || isDocument(ctx.anchor);
|
|
162416
|
-
const hasOwnedMemberNode = all.some((n2) => isPackage(n2) && !!nameOf2(n2) ||
|
|
162456
|
+
const hasOwnedMemberNode = all.some((n2) => isPackage(n2) && !!nameOf2(n2) || isDefinitionNode(n2) && !!nameOf2(n2) || this.isViewlessUsage(n2) && this.isDirectPackageMember(n2) || isPartDecl(n2) && n2.isDef !== true && !!nameOf2(n2) && this.isDirectPackageMember(n2));
|
|
162417
162457
|
const packageNodes = [
|
|
162418
162458
|
...packageOverview && hasOwnedMemberNode && isPackage(scope) && nameOf2(scope) ? [scope] : [],
|
|
162419
162459
|
...all.filter((p) => isPackage(p) && nameOf2(p))
|
|
@@ -162603,16 +162643,18 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
162603
162643
|
const boundReferences = [];
|
|
162604
162644
|
for (let w = 0; w < featureWork.length; w += 1) {
|
|
162605
162645
|
const d = featureWork[w];
|
|
162606
|
-
for (const
|
|
162646
|
+
for (const raw of membersOf(d)) {
|
|
162647
|
+
const m = this.thenActionMemberNode(raw) ?? raw;
|
|
162607
162648
|
const mm = m;
|
|
162608
|
-
|
|
162649
|
+
const label = portionLabelOf(m);
|
|
162650
|
+
if (mm.isDef === true || !label)
|
|
162609
162651
|
continue;
|
|
162610
162652
|
if (directionOf(m) !== void 0)
|
|
162611
162653
|
continue;
|
|
162612
|
-
if (!isFeatureUsageMember(m, d))
|
|
162654
|
+
if (!isFeatureUsageMember(m, d) && !isOccurrenceModified(m))
|
|
162613
162655
|
continue;
|
|
162614
162656
|
const isRefMembership = (mm.modifiers ?? []).includes("ref");
|
|
162615
|
-
if (!isPartDecl(m) && !isOccurrenceDecl(m))
|
|
162657
|
+
if (!isPartDecl(m) && !isOccurrenceDecl(m) && !isOccurrenceModified(m) && !isDeclaredEventOccurrence(m))
|
|
162616
162658
|
continue;
|
|
162617
162659
|
const boundTarget = isRefMembership ? boundPartTarget(m) : void 0;
|
|
162618
162660
|
const hasBoundPath = isRefMembership && isPathExpr(mm.value);
|
|
@@ -162625,14 +162667,16 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
162625
162667
|
}
|
|
162626
162668
|
const def = this.resolveType(m, index2);
|
|
162627
162669
|
const defOnCanvas = !!(def && ids.has(def));
|
|
162628
|
-
const uid =
|
|
162670
|
+
const uid = diagramNodeId(m) ?? label;
|
|
162629
162671
|
if (!ids.has(m)) {
|
|
162630
162672
|
ids.set(m, uid);
|
|
162631
|
-
if (!byName.has(
|
|
162632
|
-
byName.set(
|
|
162673
|
+
if (!byName.has(label))
|
|
162674
|
+
byName.set(label, m);
|
|
162675
|
+
if (!byQName.has(uid))
|
|
162676
|
+
byQName.set(uid, m);
|
|
162633
162677
|
nodes.push({
|
|
162634
162678
|
id: uid,
|
|
162635
|
-
name:
|
|
162679
|
+
name: label,
|
|
162636
162680
|
keyword: keywordFor(m),
|
|
162637
162681
|
isDef: false,
|
|
162638
162682
|
shape: "box",
|
|
@@ -162657,10 +162701,16 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
162657
162701
|
id: `e${e++}`,
|
|
162658
162702
|
from: ids.get(d),
|
|
162659
162703
|
to: uid,
|
|
162660
|
-
|
|
162704
|
+
// REQ-160 — a composed `timeslice`/`snapshot` is not ordinary
|
|
162705
|
+
// feature membership: it is the temporal decomposition of the
|
|
162706
|
+
// owner's life (OMG 8.2.3.9), drawn with the hollow triangle at
|
|
162707
|
+
// the whole end. A `ref` portion still reads as a reference — it
|
|
162708
|
+
// points at a portion owned elsewhere rather than carving up this
|
|
162709
|
+
// occurrence's own lifetime.
|
|
162710
|
+
kind: isRefMembership ? "reference" : portionKindOf(m) ? "portion" : "composition",
|
|
162661
162711
|
// No label — the usage name/type read inside the box; keep
|
|
162662
162712
|
// `name` for the stable route key and Properties.
|
|
162663
|
-
name:
|
|
162713
|
+
name: label,
|
|
162664
162714
|
type: typeText(m),
|
|
162665
162715
|
source: sourceOf2(m, uri)
|
|
162666
162716
|
});
|
|
@@ -162669,6 +162719,31 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
162669
162719
|
}
|
|
162670
162720
|
}
|
|
162671
162721
|
}
|
|
162722
|
+
for (const owner of [...ids.keys()]) {
|
|
162723
|
+
const from = ids.get(owner);
|
|
162724
|
+
for (const raw of membersOf(owner)) {
|
|
162725
|
+
const m = this.thenActionMemberNode(raw) ?? raw;
|
|
162726
|
+
if (!isEventDecl(m) || m.isOccurrence === true)
|
|
162727
|
+
continue;
|
|
162728
|
+
const ev = m;
|
|
162729
|
+
const path10 = [nameOf2(m), ...ev.chainSegs].filter(Boolean).join("::");
|
|
162730
|
+
if (!path10)
|
|
162731
|
+
continue;
|
|
162732
|
+
const target = resolveDrawnByText(path10);
|
|
162733
|
+
const to = target && ids.get(target);
|
|
162734
|
+
if (!to || to === from)
|
|
162735
|
+
continue;
|
|
162736
|
+
edges.push({
|
|
162737
|
+
id: `e${e++}`,
|
|
162738
|
+
from,
|
|
162739
|
+
to,
|
|
162740
|
+
kind: "referenceSubsetting",
|
|
162741
|
+
label: "event",
|
|
162742
|
+
name: lastSeg(path10),
|
|
162743
|
+
source: sourceOf2(m, uri)
|
|
162744
|
+
});
|
|
162745
|
+
}
|
|
162746
|
+
}
|
|
162672
162747
|
for (const binding of boundReferences) {
|
|
162673
162748
|
const from = ids.get(binding.owner);
|
|
162674
162749
|
const to = ids.get(binding.target);
|
|
@@ -165863,7 +165938,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
165863
165938
|
const related = this.relatedNodes(anchor, index2);
|
|
165864
165939
|
const keepIds = /* @__PURE__ */ new Set();
|
|
165865
165940
|
for (const n2 of related) {
|
|
165866
|
-
const id2 =
|
|
165941
|
+
const id2 = diagramNodeId(n2);
|
|
165867
165942
|
if (id2)
|
|
165868
165943
|
keepIds.add(id2);
|
|
165869
165944
|
}
|
|
@@ -166073,7 +166148,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
166073
166148
|
// One registry: each compartment is defined once with the member predicate
|
|
166074
166149
|
// that fills it, emitted in a single canonical order that satisfies the
|
|
166075
166150
|
// requirement order (doc → subject → attributes → assume → require →
|
|
166076
|
-
// actors → stakeholders →
|
|
166151
|
+
// actors → stakeholders → frames, REQ-183) and the use-case order
|
|
166077
166152
|
// (subject → actors → include use cases, REQ-184). Empty compartments are
|
|
166078
166153
|
// omitted (REQ-181) — except `subject`, which is mandatory on requirement /
|
|
166079
166154
|
// use-case / verification-case definitions (REQ-183/184) and shows a
|
|
@@ -166087,7 +166162,10 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
166087
166162
|
const t = typeText(m);
|
|
166088
166163
|
return `${dir ? `${dir} ` : ""}${derived}${nameOf2(m) ?? ""}${t ? ` : ${conj}${t}` : ""}`.trim();
|
|
166089
166164
|
}
|
|
166090
|
-
/** REQ-177/REQ-187 — inherited
|
|
166165
|
+
/** REQ-177/REQ-187 — inherited attributes, dropped when redefined locally.
|
|
166166
|
+
* Their textual home is selected later by the same classifier as local
|
|
166167
|
+
* members; retaining the AST member here prevents direction/variability
|
|
166168
|
+
* from being flattened into `attributes` before classification. */
|
|
166091
166169
|
inheritedItems(node, index2, uri) {
|
|
166092
166170
|
if (node.isDef === true)
|
|
166093
166171
|
return [];
|
|
@@ -166104,22 +166182,45 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
166104
166182
|
}
|
|
166105
166183
|
}
|
|
166106
166184
|
const localNames = new Set(membersOf(node).map((m) => nameOf2(m)).filter(Boolean));
|
|
166107
|
-
return membersOf(def).filter((m) => isAttributeDecl(m) && m.isDef !== true && nameOf2(m)).filter((m) => !localRedefined.has(nameOf2(m)) && !localNames.has(nameOf2(m))).map((
|
|
166185
|
+
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) }));
|
|
166108
166186
|
}
|
|
166109
166187
|
compartmentsFor(node, uri, index2, featureRows = false, includeInherited = true) {
|
|
166110
166188
|
const members = membersOf(node);
|
|
166111
166189
|
const n2 = node;
|
|
166112
166190
|
const item = (m, text) => ({ text: text ?? this.featureText(m), source: sourceOf2(m, uri) });
|
|
166113
|
-
const
|
|
166191
|
+
const isVariantConfigMember = (m) => m.allVariants === true;
|
|
166192
|
+
const isVariantMember = (m) => modifiersOf(m).includes("variant") && !isVariantConfigMember(m);
|
|
166193
|
+
const isNonVariantMember = (m) => !isVariantMember(m) && !isVariantConfigMember(m);
|
|
166194
|
+
const isOrdinaryMember = (m) => directionOf(m) === void 0 && isNonVariantMember(m);
|
|
166195
|
+
const inherited = includeInherited ? this.inheritedItems(node, index2, uri) : [];
|
|
166196
|
+
const inheritedRows = (predicate, text = (member) => this.featureText(member)) => inherited.filter(({ member }) => predicate(member)).map(({ member, source }) => ({ text: `^${text(member)}`, source }));
|
|
166197
|
+
const usages = (guard) => members.filter((m) => guard(m) && m.isDef !== true && nameOf2(m) && isOrdinaryMember(m));
|
|
166114
166198
|
const exprText3 = (m) => (m.body?.$cstNode?.text ?? "").replace(/\s+/g, " ").trim();
|
|
166115
166199
|
const statementText = (m) => (m.$cstNode?.text ?? this.featureText(m)).replace(/\s+/g, " ").replace(/;$/, "").trim();
|
|
166200
|
+
const canonicalFeatureText = (m) => m.$type === "FeatureShorthand" || m.$type === "FeatureRedefinitionShorthand" ? statementText(m) : this.featureText(m);
|
|
166116
166201
|
const out = [];
|
|
166202
|
+
const claimedSources = /* @__PURE__ */ new Set();
|
|
166203
|
+
const sourceKey = (source) => `${source.uri}:${source.range.start.line}:${source.range.start.character}:${source.range.end.line}:${source.range.end.character}`;
|
|
166117
166204
|
const add = (title, items) => {
|
|
166118
|
-
|
|
166119
|
-
|
|
166205
|
+
const accepted = items.filter((candidate) => {
|
|
166206
|
+
if (!candidate.source)
|
|
166207
|
+
return true;
|
|
166208
|
+
const key = sourceKey(candidate.source);
|
|
166209
|
+
if (claimedSources.has(key))
|
|
166210
|
+
return false;
|
|
166211
|
+
claimedSources.add(key);
|
|
166212
|
+
return true;
|
|
166213
|
+
});
|
|
166214
|
+
if (!accepted.length)
|
|
166215
|
+
return;
|
|
166216
|
+
const existing = out.find((compartment) => compartment.title === title);
|
|
166217
|
+
if (existing)
|
|
166218
|
+
existing.items.push(...accepted);
|
|
166219
|
+
else
|
|
166220
|
+
out.push({ title, items: accepted });
|
|
166120
166221
|
};
|
|
166121
166222
|
add("doc", members.filter((m) => m.$type === "DocCommentMember").map((m) => item(m, notePreview(docCommentBody(m)) ?? "doc")));
|
|
166122
|
-
const subjects = members.filter(isSubjectDecl);
|
|
166223
|
+
const subjects = members.filter(isSubjectDecl).filter(isNonVariantMember);
|
|
166123
166224
|
const subjectMandatory = n2.isDef === true && (isRequirementDecl(node) || isUseCaseDecl(node) || isVerificationCaseDecl(node));
|
|
166124
166225
|
if (subjects.length) {
|
|
166125
166226
|
add("subject", subjects.map((s) => item(s)));
|
|
@@ -166128,34 +166229,53 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
166128
166229
|
}
|
|
166129
166230
|
add("attributes", [
|
|
166130
166231
|
...usages(isAttributeDecl).map((a2) => item(a2)),
|
|
166131
|
-
...
|
|
166232
|
+
...inheritedRows((member) => isAttributeDecl(member) && isOrdinaryMember(member))
|
|
166132
166233
|
]);
|
|
166234
|
+
const notPortion = (m) => portionKindOf(m) === void 0;
|
|
166133
166235
|
if (featureRows) {
|
|
166134
166236
|
add("ports", usages(isPortDecl).map((m) => item(m)));
|
|
166135
|
-
add("parts", usages(isPartDecl).map((m) => item(m)));
|
|
166237
|
+
add("parts", usages(isPartDecl).filter(notPortion).map((m) => item(m)));
|
|
166136
166238
|
}
|
|
166137
|
-
add("features", members.filter((m) => m.$type === "FeatureShorthand" || m.$type === "FeatureRedefinitionShorthand").map((m) => item(m,
|
|
166138
|
-
const undirected = (guard) => usages(guard)
|
|
166139
|
-
add("items", undirected(isItemDecl).map((m) => item(m)));
|
|
166140
|
-
|
|
166141
|
-
add("occurrences",
|
|
166239
|
+
add("features", members.filter((m) => m.$type === "FeatureShorthand" || m.$type === "FeatureRedefinitionShorthand").filter(isOrdinaryMember).filter((m) => !isOccurrenceModified(m)).map((m) => item(m, canonicalFeatureText(m))));
|
|
166240
|
+
const undirected = (guard) => usages(guard);
|
|
166241
|
+
add("items", undirected(isItemDecl).filter(notPortion).map((m) => item(m)));
|
|
166242
|
+
add("occurrences", undirected(isOccurrenceDecl).filter(notPortion).map((m) => item(m)));
|
|
166243
|
+
add("occurrences", members.map((m) => this.thenActionMemberNode(m) ?? m).filter(isNonVariantMember).filter((m) => isEventDecl(m) && m.isOccurrence === true && nameOf2(m)).map((m) => item(m)));
|
|
166142
166244
|
add("calcs", undirected(isCalcDecl).map((m) => item(m)));
|
|
166143
166245
|
add("constraints", undirected(isConstraintDecl).map((m) => item(m)));
|
|
166144
166246
|
add("assume constraints", members.filter((m) => m.$type === "AssumeConstraintStmt").map((m) => item(m, exprText3(m) || "assume constraint")));
|
|
166145
166247
|
add("require constraints", members.filter((m) => m.$type === "RequireConstraintStmt").map((m) => item(m, exprText3(m) || `require ${this.featurePath(m.target) ?? ""}`.trim())));
|
|
166146
|
-
add("actors", members.filter(isActorDecl).map((m) => item(m)));
|
|
166147
|
-
add("stakeholders", members.filter(isStakeholderDecl).map((m) => item(m)));
|
|
166148
|
-
add("
|
|
166248
|
+
add("actors", members.filter(isActorDecl).filter(isNonVariantMember).map((m) => item(m)));
|
|
166249
|
+
add("stakeholders", members.filter(isStakeholderDecl).filter(isNonVariantMember).map((m) => item(m)));
|
|
166250
|
+
add("frames", members.filter((m) => m.$type === "FrameMember").map((m) => item(m, this.refText(m.target) ?? "concern")));
|
|
166149
166251
|
add("include use cases", members.filter((m) => m.$type === "IncludeStmt").map((m) => item(m, this.refText(m.target) ?? "")));
|
|
166150
|
-
add("objective", members.filter(isObjectiveDecl).map((m) => item(m, nameOf2(m) ?? "objective")));
|
|
166252
|
+
add("objective", members.filter(isObjectiveDecl).filter(isNonVariantMember).map((m) => item(m, nameOf2(m) ?? "objective")));
|
|
166151
166253
|
add("verifies", members.filter((m) => m.$type === "VerifyStmt").map((m) => item(m, String(m.target ?? ""))));
|
|
166152
166254
|
add("verification methods", members.filter((m) => isMetadataDecl(m) && (typeText(m) ?? "").includes("VerificationMethod")).map((m) => item(m, typeText(m) ?? "method")));
|
|
166153
|
-
|
|
166154
|
-
|
|
166255
|
+
const behavioralParameterOwner = isActionDecl(node) || isCalcDecl(node) || isConstraintDecl(node) || isCaseDecl(node) || isAnalysisCaseDecl(node) || isVerificationCaseDecl(node) || isUseCaseDecl(node);
|
|
166256
|
+
const enclosingBehavioralParameterOwner = (() => {
|
|
166257
|
+
if (isPartDecl(node) || isPortDecl(node) || directionOf(node) === void 0)
|
|
166258
|
+
return false;
|
|
166259
|
+
let owner = node.$container;
|
|
166260
|
+
while (owner) {
|
|
166261
|
+
if (isActionDecl(owner) || isCalcDecl(owner) || isConstraintDecl(owner) || isCaseDecl(owner) || isAnalysisCaseDecl(owner) || isVerificationCaseDecl(owner) || isUseCaseDecl(owner))
|
|
166262
|
+
return true;
|
|
166263
|
+
if (isPartDecl(owner) || isPortDecl(owner))
|
|
166264
|
+
return false;
|
|
166265
|
+
owner = owner.$container;
|
|
166266
|
+
}
|
|
166267
|
+
return false;
|
|
166268
|
+
})();
|
|
166269
|
+
const directedTitle = behavioralParameterOwner || enclosingBehavioralParameterOwner ? "parameters" : "directed features";
|
|
166270
|
+
add(directedTitle, [
|
|
166271
|
+
...members.filter((m) => directionOf(m) !== void 0 && nameOf2(m)).filter((m) => !isVariantMember(m) && !isVariantConfigMember(m)).map((m) => item(m, canonicalFeatureText(m))),
|
|
166272
|
+
...inheritedRows((member) => directionOf(member) !== void 0 && isNonVariantMember(member))
|
|
166273
|
+
]);
|
|
166274
|
+
add("result", members.filter((m) => m.$type === "ReturnDecl").map((m) => item(m, `return${nameOf2(m) ? ` ${nameOf2(m)}` : ""}${typeText(m) ? ` : ${typeText(m)}` : ""}`)));
|
|
166155
166275
|
if (isConstraintDecl(node))
|
|
166156
166276
|
add("expression", exprText3(node) ? [{ text: exprText3(node), source: sourceOf2(node, uri) }] : []);
|
|
166157
|
-
const enumValueMembers = members.filter((m) => m.$type === "EnumValueDecl" && (isEnumDecl(node) || !m.typing) || isEnumDecl(node) && isEnumDecl(m) && m.isDef !== true);
|
|
166158
|
-
add("
|
|
166277
|
+
const enumValueMembers = members.filter(isNonVariantMember).filter((m) => m.$type === "EnumValueDecl" && (isEnumDecl(node) || !m.typing) || isEnumDecl(node) && isEnumDecl(m) && m.isDef !== true);
|
|
166278
|
+
add("enums", enumValueMembers.map((m) => {
|
|
166159
166279
|
const nm = nameOf2(m);
|
|
166160
166280
|
if (nm)
|
|
166161
166281
|
return item(m, nm);
|
|
@@ -166165,7 +166285,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
166165
166285
|
add("states", usages(isStateDecl).map((m) => item(m)));
|
|
166166
166286
|
const stateActions = members.map((m) => ({ m, kind: { EntryAction: "entry", DoAction: "do", ExitAction: "exit" }[m.$type] })).filter((x) => !!x.kind);
|
|
166167
166287
|
add("state actions", stateActions.map(({ m, kind }) => item(m, `${kind} ${nameOf2(m) ?? ""}`.trim())));
|
|
166168
|
-
add("
|
|
166288
|
+
add("state transition", members.filter((m) => m.$type === "TransitionDecl").map((m) => item(m, `${m.from ?? ""} \u2192 ${m.to ?? ""}`)));
|
|
166169
166289
|
add("assert constraints", members.filter((m) => m.$type === "AssertConstraintStmt").map((m) => item(m, exprText3(m) || nameOf2(m) || "assert constraint")));
|
|
166170
166290
|
add("invariants", members.filter((m) => m.$type === "InvShorthand").map((m) => {
|
|
166171
166291
|
const inv = m;
|
|
@@ -166173,15 +166293,22 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
166173
166293
|
const expr = exprText3(m);
|
|
166174
166294
|
return item(m, `${head2} { ${expr} }`.replace(/\s+/g, " ").trim());
|
|
166175
166295
|
}));
|
|
166176
|
-
add("
|
|
166296
|
+
add("actions", usages(isActionDecl).map((m) => item(m)));
|
|
166177
166297
|
add("concerns", usages(isConcernDecl).map((m) => item(m)));
|
|
166178
166298
|
add("viewpoints", usages(isViewpointDecl).map((m) => item(m)));
|
|
166179
|
-
add("exposes", members.filter((m) => m.$type === "ExposeMember").flatMap((m) => (m.paths ?? []).map((
|
|
166299
|
+
add("exposes", members.filter((m) => m.$type === "ExposeMember").flatMap((m) => (m.paths ?? []).map((path10) => item(path10, this.featurePath(path10) ?? (path10.$cstNode?.text ?? "").replace(/\s+/g, " ").trim()))));
|
|
166180
166300
|
add("filters", members.filter((m) => m.$type === "FilterMember").map((m) => item(m, (m.$cstNode?.text ?? "filter").replace(/\s+/g, " ").replace(/^filter\s*/, "").replace(/;$/, "").trim())));
|
|
166181
166301
|
add("rendering", members.filter((m) => m.$type === "RenderMember").map((m) => item(m, this.refText(m.target) ?? "")));
|
|
166182
|
-
const
|
|
166183
|
-
|
|
166184
|
-
|
|
166302
|
+
const portionMembers = members.map((m) => this.thenActionMemberNode(m) ?? m).filter(isNonVariantMember);
|
|
166303
|
+
const withPortionKind = (kind) => portionMembers.filter((m) => portionKindOf(m) === kind && portionLabelOf(m));
|
|
166304
|
+
const portionText = (m) => {
|
|
166305
|
+
const t = typeText(m);
|
|
166306
|
+
const mult = multText(m);
|
|
166307
|
+
return `${portionLabelOf(m)}${t ? ` : ${t}` : ""}${mult ? ` ${mult}` : ""}`;
|
|
166308
|
+
};
|
|
166309
|
+
add("timeslices", withPortionKind("timeslice").map((m) => item(m, portionText(m))));
|
|
166310
|
+
add("snapshots", withPortionKind("snapshot").map((m) => item(m, portionText(m))));
|
|
166311
|
+
add("individuals", portionMembers.filter((m) => m.$type === "FeatureShorthand" && isIndividualOccurrence(m) && portionKindOf(m) === void 0 && portionLabelOf(m)).map((m) => item(m, portionText(m))));
|
|
166185
166312
|
const metaBadges = [
|
|
166186
166313
|
...prefixTagsOf(node).map((t) => `#${t}`),
|
|
166187
166314
|
...members.filter((m) => m.$type === "MetadataAnnotation").map((m) => {
|
|
@@ -166192,8 +166319,15 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
166192
166319
|
})
|
|
166193
166320
|
];
|
|
166194
166321
|
add("metadata", metaBadges.map((text) => ({ text })));
|
|
166195
|
-
add("variants",
|
|
166196
|
-
|
|
166322
|
+
add("variants", [
|
|
166323
|
+
...members.filter((m) => isVariantMember(m) && nameOf2(m)).map((m) => item(m)),
|
|
166324
|
+
...inheritedRows((member) => isVariantMember(member) && !!nameOf2(member))
|
|
166325
|
+
]);
|
|
166326
|
+
const variantElementText = (member) => `${nameOf2(member) ?? ""} = all ${(member.value?.$cstNode?.text ?? "").trim()}`.trim();
|
|
166327
|
+
add("variant element usages", [
|
|
166328
|
+
...members.filter(isVariantConfigMember).map((m) => item(m, variantElementText(m))),
|
|
166329
|
+
...inheritedRows(isVariantConfigMember, variantElementText)
|
|
166330
|
+
]);
|
|
166197
166331
|
add("satisfies", members.filter((m) => m.$type === "SatisfyStmt").map((m) => item(m, String(m.target ?? ""))));
|
|
166198
166332
|
return out.length ? out : void 0;
|
|
166199
166333
|
}
|
|
@@ -166811,7 +166945,7 @@ function symbolNameFor(node) {
|
|
|
166811
166945
|
const redefined = redefinitionTargets(node)[0];
|
|
166812
166946
|
return redefined ? `:>> ${lastNameSegment(redefined)}` : void 0;
|
|
166813
166947
|
}
|
|
166814
|
-
function
|
|
166948
|
+
function isDefinitionNode2(node) {
|
|
166815
166949
|
return node.isDef === true;
|
|
166816
166950
|
}
|
|
166817
166951
|
function isInheritableFeature(node) {
|
|
@@ -166951,7 +167085,7 @@ function findNameLeaf(node, name) {
|
|
|
166951
167085
|
return void 0;
|
|
166952
167086
|
}
|
|
166953
167087
|
function inheritedFeatureSymbols(node, inheritedRange, context, seen = /* @__PURE__ */ new Set()) {
|
|
166954
|
-
if (!
|
|
167088
|
+
if (!isDefinitionNode2(node) || seen.has(node))
|
|
166955
167089
|
return [];
|
|
166956
167090
|
seen.add(node);
|
|
166957
167091
|
const symbols = [];
|
|
@@ -170579,6 +170713,26 @@ function actionOnlyConstruct(node) {
|
|
|
170579
170713
|
const keyword = CONTROL_NODE_KEYWORDS[node.$type];
|
|
170580
170714
|
return keyword ? { construct: `A '${keyword}' control node`, clause: "7.17.3" } : void 0;
|
|
170581
170715
|
}
|
|
170716
|
+
function portionKindOf2(node) {
|
|
170717
|
+
const mods = node.modifiers;
|
|
170718
|
+
if (!Array.isArray(mods))
|
|
170719
|
+
return void 0;
|
|
170720
|
+
return mods.find((m) => m === "timeslice" || m === "snapshot");
|
|
170721
|
+
}
|
|
170722
|
+
var NAMESPACE_ONLY_TYPES = /* @__PURE__ */ new Set(["Package", "Document", "NamespaceDecl"]);
|
|
170723
|
+
function owningTypeOf(node) {
|
|
170724
|
+
let owner = node.$container;
|
|
170725
|
+
while (owner && (owner.$type === "PrefixMetadataMember" || owner.$type === "ThenActionMember")) {
|
|
170726
|
+
owner = owner.$container;
|
|
170727
|
+
}
|
|
170728
|
+
if (!owner)
|
|
170729
|
+
return void 0;
|
|
170730
|
+
return NAMESPACE_ONLY_TYPES.has(owner.$type) ? void 0 : owner;
|
|
170731
|
+
}
|
|
170732
|
+
function declLabel(node, kind) {
|
|
170733
|
+
const name = node.name;
|
|
170734
|
+
return name ? `'${name}'` : `this '${kind}'`;
|
|
170735
|
+
}
|
|
170582
170736
|
var SysmlValidator = class _SysmlValidator {
|
|
170583
170737
|
indexManager;
|
|
170584
170738
|
langiumDocuments;
|
|
@@ -170802,6 +170956,7 @@ var SysmlValidator = class _SysmlValidator {
|
|
|
170802
170956
|
this.checkLanguageDisjointness(node, accept);
|
|
170803
170957
|
this.checkKermlWellFormedness(node, accept);
|
|
170804
170958
|
this.checkFilterExpressions(node, accept);
|
|
170959
|
+
this.checkOccurrencePortions(node, accept);
|
|
170805
170960
|
this.checkCrossReferences(node, accept);
|
|
170806
170961
|
this.checkAutoImportSuggestions(node, accept);
|
|
170807
170962
|
this.checkUnits(node, accept);
|
|
@@ -171685,6 +171840,49 @@ ${baseIndent}}`;
|
|
|
171685
171840
|
this.checkTypeComposition(decl, index2, accept);
|
|
171686
171841
|
}
|
|
171687
171842
|
}
|
|
171843
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
171844
|
+
// REQ-160 — occurrence portions: `timeslice` / `snapshot` well-formedness
|
|
171845
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
171846
|
+
// The declaration kinds that are NOT occurrences, so a portion of their life is
|
|
171847
|
+
// meaningless. Kept as a deny-list rather than an allow-list because nearly every
|
|
171848
|
+
// SysML usage kind IS an OccurrenceUsage (part, item, action, state, port,
|
|
171849
|
+
// connection, case, …) while the data-valued ones are few and closed: an
|
|
171850
|
+
// AttributeUsage is typed by a DataType and an enumeration is a special attribute,
|
|
171851
|
+
// neither of which has a life to carve up.
|
|
171852
|
+
static NON_OCCURRENCE_OWNER_TYPES = /* @__PURE__ */ new Set(["AttributeDecl", "EnumDecl", "EnumValueDecl", "MetadataDecl", "MultiplicityDecl"]);
|
|
171853
|
+
// REQ-160 — OMG SysML v2 §8.2.2.9 (Occurrences) with the Kernel Semantic Library
|
|
171854
|
+
// `Occurrences::TimeSlice` / `Occurrences::Snapshot`:
|
|
171855
|
+
//
|
|
171856
|
+
// SSM015 — a portion is a portion OF something. Its owning type must be an
|
|
171857
|
+
// occurrence; declared at package level (or inside an attribute /
|
|
171858
|
+
// enumeration body) there is no life for it to be a portion of.
|
|
171859
|
+
// SSM016 — `Snapshot :> TimeSlice` with a zero duration: a snapshot is the
|
|
171860
|
+
// occurrence at ONE instant. Every portion of a zero-duration
|
|
171861
|
+
// occurrence is itself zero-duration, so a snapshot may own further
|
|
171862
|
+
// snapshots but never a `timeslice`.
|
|
171863
|
+
//
|
|
171864
|
+
// Both are structural — they read modifiers and owners only — so they hold
|
|
171865
|
+
// without resolving a single cross-reference.
|
|
171866
|
+
checkOccurrencePortions(node, accept) {
|
|
171867
|
+
for (const child of ast_utils_exports.streamAllContents(node)) {
|
|
171868
|
+
const kind = portionKindOf2(child);
|
|
171869
|
+
if (!kind)
|
|
171870
|
+
continue;
|
|
171871
|
+
const label = declLabel(child, kind);
|
|
171872
|
+
const owner = owningTypeOf(child);
|
|
171873
|
+
if (!owner) {
|
|
171874
|
+
accept(severity("SSM015", "error"), `A '${kind}' is a portion of an occurrence's life, so ${label} must be declared inside an occurrence \u2014 not directly in a package.`, { node: child, code: "SSM015" });
|
|
171875
|
+
continue;
|
|
171876
|
+
}
|
|
171877
|
+
if (_SysmlValidator.NON_OCCURRENCE_OWNER_TYPES.has(owner.$type)) {
|
|
171878
|
+
accept(severity("SSM015", "error"), `A '${kind}' is a portion of an occurrence's life, and '${owner.name ?? owner.$type}' is not an occurrence.`, { node: child, code: "SSM015" });
|
|
171879
|
+
continue;
|
|
171880
|
+
}
|
|
171881
|
+
if (kind === "timeslice" && portionKindOf2(owner) === "snapshot") {
|
|
171882
|
+
accept(severity("SSM016", "error"), `A 'snapshot' is a zero-duration timeslice, so ${label} cannot be a timeslice of it \u2014 a portion of an instant is itself a snapshot.`, { node: child, code: "SSM016" });
|
|
171883
|
+
}
|
|
171884
|
+
}
|
|
171885
|
+
}
|
|
171688
171886
|
// REQ-328 — KSM008: a `filter` membership condition must be Boolean. Only a
|
|
171689
171887
|
// *definitely* non-Boolean expression is flagged — a string or numeric/quantity
|
|
171690
171888
|
// literal, or an arithmetic/range binary expression. A bare feature path is left
|
|
@@ -176534,6 +176732,7 @@ function readProjectConfig(root4) {
|
|
|
176534
176732
|
// ../extension/src/webview/diagram/flow/diagram-rules.ts
|
|
176535
176733
|
var PORT_GLYPH_SIZE = 20;
|
|
176536
176734
|
var PORT_GLYPH_HALF = PORT_GLYPH_SIZE / 2;
|
|
176735
|
+
var FEATURE_COMPARTMENT_CLEARANCE = PORT_GLYPH_HALF + 12;
|
|
176537
176736
|
var ACTION_PIN_GLYPH_SIZE = PORT_GLYPH_SIZE;
|
|
176538
176737
|
function endpointGlyphSize(endpoint) {
|
|
176539
176738
|
return endpoint.pin ? ACTION_PIN_GLYPH_SIZE : PORT_GLYPH_SIZE;
|
|
@@ -176576,18 +176775,26 @@ var DOCK_TANGENT = {
|
|
|
176576
176775
|
left: { x: 0, y: 1 },
|
|
176577
176776
|
right: { x: 0, y: 1 }
|
|
176578
176777
|
};
|
|
176579
|
-
function portGlyphRect(g, w, h) {
|
|
176580
|
-
const base = sidePoint(g.side, g.offset, w, h);
|
|
176581
|
-
const t = DOCK_TANGENT[g.side];
|
|
176582
|
-
const n2 = DOCK_NORMAL[g.side];
|
|
176583
|
-
const shift = g.shift ?? { along: 0, across: 0 };
|
|
176584
|
-
const cx = base.x + t.x * shift.along + n2.x * shift.across;
|
|
176585
|
-
const cy = base.y + t.y * shift.along + n2.y * shift.across;
|
|
176778
|
+
function portGlyphRect(g, w, h, topReserve = 0) {
|
|
176586
176779
|
const natural = endpointGlyphSize(g.port);
|
|
176587
176780
|
const along = g.along ?? natural;
|
|
176588
176781
|
const toggleRun = g.toggleRun ?? 0;
|
|
176589
176782
|
const across = g.across ?? (along - toggleRun > natural ? NESTED_PORT_HOST_ACROSS : natural);
|
|
176590
176783
|
const vertical = g.side === "left" || g.side === "right";
|
|
176784
|
+
const base = sidePoint(g.side, g.offset, w, h, topReserve);
|
|
176785
|
+
const t = DOCK_TANGENT[g.side];
|
|
176786
|
+
const n2 = DOCK_NORMAL[g.side];
|
|
176787
|
+
const shift = g.shift ?? { along: 0, across: 0 };
|
|
176788
|
+
const rawCx = base.x + t.x * shift.along + n2.x * shift.across;
|
|
176789
|
+
const rawCy = base.y + t.y * shift.along + n2.y * shift.across;
|
|
176790
|
+
const run = sideLength(g.side, w, h, topReserve);
|
|
176791
|
+
const alongCentre = vertical ? rawCy : rawCx;
|
|
176792
|
+
const rootAlong = g.rootAlong ?? along;
|
|
176793
|
+
const rootCentre = vertical ? base.y : base.x;
|
|
176794
|
+
const boundedRootCentre = topReserve > 0 && vertical ? run >= rootAlong ? Math.max(topReserve + rootAlong / 2, Math.min(topReserve + run - rootAlong / 2, rootCentre)) : topReserve + run / 2 : rootCentre;
|
|
176795
|
+
const boundedAlong = alongCentre + boundedRootCentre - rootCentre;
|
|
176796
|
+
const cx = vertical ? rawCx : boundedAlong;
|
|
176797
|
+
const cy = vertical ? boundedAlong : rawCy;
|
|
176591
176798
|
const width = vertical ? across : along;
|
|
176592
176799
|
const height = vertical ? along : across;
|
|
176593
176800
|
return {
|
|
@@ -176661,18 +176868,40 @@ var DOCK_NORMAL = {
|
|
|
176661
176868
|
bottom: { x: 0, y: 1 },
|
|
176662
176869
|
left: { x: -1, y: 0 }
|
|
176663
176870
|
};
|
|
176664
|
-
function
|
|
176871
|
+
function portSideHeight(h, topReserve = 0) {
|
|
176872
|
+
const band = Number.isFinite(topReserve) ? Math.max(0, Math.min(Math.max(0, h), topReserve)) : 0;
|
|
176873
|
+
return Math.max(0, h - band);
|
|
176874
|
+
}
|
|
176875
|
+
function sidePoint(side, offset2, w, h, topReserve = 0) {
|
|
176876
|
+
const top = h - portSideHeight(h, topReserve);
|
|
176877
|
+
const sideH = portSideHeight(h, topReserve);
|
|
176665
176878
|
switch (side) {
|
|
176666
176879
|
case "top":
|
|
176667
176880
|
return { x: w * offset2, y: 0 };
|
|
176668
176881
|
case "bottom":
|
|
176669
176882
|
return { x: w * offset2, y: h };
|
|
176670
176883
|
case "left":
|
|
176671
|
-
return { x: 0, y:
|
|
176884
|
+
return { x: 0, y: top + sideH * offset2 };
|
|
176672
176885
|
case "right":
|
|
176673
|
-
return { x: w, y:
|
|
176886
|
+
return { x: w, y: top + sideH * offset2 };
|
|
176674
176887
|
}
|
|
176675
176888
|
}
|
|
176889
|
+
function nearestPortOwnerPlacement(x, y, w, h, topReserve = 0) {
|
|
176890
|
+
const sideH = portSideHeight(h, topReserve);
|
|
176891
|
+
const top = h - sideH;
|
|
176892
|
+
const clamp3 = (value, lo, hi) => Math.max(lo, Math.min(hi, value));
|
|
176893
|
+
const distanceSq = (px, py, qx, qy) => (px - qx) ** 2 + (py - qy) ** 2;
|
|
176894
|
+
const sideY = clamp3(y, top, h);
|
|
176895
|
+
const offsetY = sideH > 0 ? (sideY - top) / sideH : 0.5;
|
|
176896
|
+
const candidates = [
|
|
176897
|
+
{ side: "left", offset: offsetY, distance: distanceSq(x, y, 0, sideY) },
|
|
176898
|
+
{ side: "right", offset: offsetY, distance: distanceSq(x, y, w, sideY) },
|
|
176899
|
+
{ side: "top", offset: w > 0 ? clamp3(x, 0, w) / w : 0.5, distance: distanceSq(x, y, clamp3(x, 0, w), 0) },
|
|
176900
|
+
{ side: "bottom", offset: w > 0 ? clamp3(x, 0, w) / w : 0.5, distance: distanceSq(x, y, clamp3(x, 0, w), h) }
|
|
176901
|
+
];
|
|
176902
|
+
const best = candidates.reduce((nearest, candidate) => candidate.distance < nearest.distance ? candidate : nearest);
|
|
176903
|
+
return { side: best.side, offset: best.offset };
|
|
176904
|
+
}
|
|
176676
176905
|
var SIDE_ANCHOR_SEP = ":";
|
|
176677
176906
|
var CONNECT_POINT_SPACING_DEFAULT = 24;
|
|
176678
176907
|
var CONNECT_POINT_SPACING_MIN = 8;
|
|
@@ -176705,12 +176934,12 @@ function centerOutOffsetOrder(offsets) {
|
|
|
176705
176934
|
function sidePointOffsetsForLength(length2, spacing) {
|
|
176706
176935
|
return sidePointOffsets(connectPointCountForLength(length2, spacing));
|
|
176707
176936
|
}
|
|
176708
|
-
function sideLength(side, w, h) {
|
|
176709
|
-
return side === "top" || side === "bottom" ? w : h;
|
|
176937
|
+
function sideLength(side, w, h, topReserve = 0) {
|
|
176938
|
+
return side === "top" || side === "bottom" ? w : portSideHeight(h, topReserve);
|
|
176710
176939
|
}
|
|
176711
176940
|
var SENDACCEPT_NOTCH = 14;
|
|
176712
|
-
function sideEffectiveLength(shape, side, w, h) {
|
|
176713
|
-
const raw = sideLength(side, w, h);
|
|
176941
|
+
function sideEffectiveLength(shape, side, w, h, topReserve = 0) {
|
|
176942
|
+
const raw = sideLength(side, w, h, topReserve);
|
|
176714
176943
|
switch (shape) {
|
|
176715
176944
|
case "usecase":
|
|
176716
176945
|
return raw * 0.82;
|
|
@@ -176725,7 +176954,7 @@ function sideEffectiveLength(shape, side, w, h) {
|
|
|
176725
176954
|
return raw;
|
|
176726
176955
|
}
|
|
176727
176956
|
}
|
|
176728
|
-
function sideSurfacePoint(shape, side, offset2, w, h) {
|
|
176957
|
+
function sideSurfacePoint(shape, side, offset2, w, h, topReserve = 0) {
|
|
176729
176958
|
const cx = w / 2;
|
|
176730
176959
|
const cy = h / 2;
|
|
176731
176960
|
switch (shape) {
|
|
@@ -176753,22 +176982,22 @@ function sideSurfacePoint(shape, side, offset2, w, h) {
|
|
|
176753
176982
|
case "send": {
|
|
176754
176983
|
if (side === "top" || side === "bottom") return { x: (w - SENDACCEPT_NOTCH) * offset2, y: side === "top" ? 0 : h };
|
|
176755
176984
|
if (side === "right") return { x: w, y: cy };
|
|
176756
|
-
return sidePoint(side, offset2, w, h);
|
|
176985
|
+
return sidePoint(side, offset2, w, h, topReserve);
|
|
176757
176986
|
}
|
|
176758
176987
|
case "accept": {
|
|
176759
176988
|
if (side === "left") return { x: SENDACCEPT_NOTCH, y: cy };
|
|
176760
|
-
return sidePoint(side, offset2, w, h);
|
|
176989
|
+
return sidePoint(side, offset2, w, h, topReserve);
|
|
176761
176990
|
}
|
|
176762
176991
|
default:
|
|
176763
|
-
return sidePoint(side, offset2, w, h);
|
|
176992
|
+
return sidePoint(side, offset2, w, h, topReserve);
|
|
176764
176993
|
}
|
|
176765
176994
|
}
|
|
176766
176995
|
function isPackageEndpoint(shape, keyword) {
|
|
176767
176996
|
if (shape === "package") return true;
|
|
176768
176997
|
return (keyword ?? "").trim().toLowerCase() === "package";
|
|
176769
176998
|
}
|
|
176770
|
-
function sidePointOffsetsFor(side, w, h, spacing, connectable, shape) {
|
|
176771
|
-
return connectable ? sidePointOffsetsForLength(sideEffectiveLength(shape, side, w, h), spacing) : [0.5];
|
|
176999
|
+
function sidePointOffsetsFor(side, w, h, spacing, connectable, shape, topReserve = 0) {
|
|
177000
|
+
return connectable ? sidePointOffsetsForLength(sideEffectiveLength(shape, side, w, h, topReserve), spacing) : [0.5];
|
|
176772
177001
|
}
|
|
176773
177002
|
function sideAnchorHandleId(side, offset2) {
|
|
176774
177003
|
return Math.abs(offset2 - 0.5) < 1e-6 ? side : `${side}${SIDE_ANCHOR_SEP}${offset2.toFixed(3)}`;
|
|
@@ -176809,6 +177038,50 @@ function clampDockSide(encoded, portSide) {
|
|
|
176809
177038
|
}
|
|
176810
177039
|
var PORT_PLUS_GAP = 7;
|
|
176811
177040
|
var PORT_PLUS_HALF = 4;
|
|
177041
|
+
var NODE_USAGE_CORNER_RADIUS = 14;
|
|
177042
|
+
var NODE_ROUNDED_USAGE_RADIUS = 20;
|
|
177043
|
+
var NODE_ROUNDED_TITLED_RADIUS = 12;
|
|
177044
|
+
function nodeCornerRadius(shape, isDef, height, titled) {
|
|
177045
|
+
if (isDef) return 0;
|
|
177046
|
+
if (shape === "action" || shape === "state") {
|
|
177047
|
+
const r = Math.min(height / 2, NODE_ROUNDED_USAGE_RADIUS);
|
|
177048
|
+
return titled ? Math.min(r, NODE_ROUNDED_TITLED_RADIUS) : r;
|
|
177049
|
+
}
|
|
177050
|
+
return NODE_USAGE_CORNER_RADIUS;
|
|
177051
|
+
}
|
|
177052
|
+
var FRAME_USAGE_CORNER_RADIUS = 12;
|
|
177053
|
+
var CONTAINER_CONTROL_SIZE = 20;
|
|
177054
|
+
var CONTAINER_CONTROL_GAP = 1;
|
|
177055
|
+
var CONTAINER_CONTROLS_RIGHT = 2;
|
|
177056
|
+
function containerControlsInset(cornerRadius) {
|
|
177057
|
+
return Math.max(CONTAINER_CONTROLS_RIGHT, Math.ceil(cornerRadius * (1 - Math.SQRT1_2)));
|
|
177058
|
+
}
|
|
177059
|
+
var CONTAINER_CONTROLS_INSET_MAX = containerControlsInset(NODE_ROUNDED_USAGE_RADIUS);
|
|
177060
|
+
var CONTAINER_TITLE_RIGHT_RESERVE = 2 * CONTAINER_CONTROL_SIZE + CONTAINER_CONTROL_GAP + CONTAINER_CONTROLS_INSET_MAX + 11;
|
|
177061
|
+
var COLLAPSED_CONTAINER_MIN_WIDTH = CONTAINER_TITLE_RIGHT_RESERVE + 48;
|
|
177062
|
+
var CONTAINER_GLYPH_VIEWBOX = 20;
|
|
177063
|
+
var CONTAINER_GLYPH_EXTENT = 11;
|
|
177064
|
+
function containerTitleArea(ownerWidth, controlsVisible) {
|
|
177065
|
+
const width = Math.max(0, ownerWidth - (controlsVisible ? CONTAINER_TITLE_RIGHT_RESERVE : 0));
|
|
177066
|
+
return { centerX: width / 2, width };
|
|
177067
|
+
}
|
|
177068
|
+
var NODE_COMPARTMENT_TOP = 30;
|
|
177069
|
+
var FRAME_TITLE_HEIGHT = NODE_COMPARTMENT_TOP;
|
|
177070
|
+
function containerTitleHeight(isFrame) {
|
|
177071
|
+
return isFrame ? FRAME_TITLE_HEIGHT : NODE_COMPARTMENT_TOP;
|
|
177072
|
+
}
|
|
177073
|
+
var CONTAINER_TITLE_KIND_BASELINE = 14;
|
|
177074
|
+
var CONTAINER_TITLE_NAME_BASELINE = 28;
|
|
177075
|
+
function containerTopReserve(bandHeight, isFrame) {
|
|
177076
|
+
return bandHeight && bandHeight > 0 ? containerTitleHeight(isFrame) + bandHeight : 0;
|
|
177077
|
+
}
|
|
177078
|
+
var COMPARTMENT_TITLE_HEIGHT = 16;
|
|
177079
|
+
var COMPARTMENT_ROW_HEIGHT = 14;
|
|
177080
|
+
var COMPARTMENT_TITLE_BASELINE = 12;
|
|
177081
|
+
var COMPARTMENT_ROW_BASELINE = 26;
|
|
177082
|
+
function compartmentBlockHeight(items) {
|
|
177083
|
+
return COMPARTMENT_TITLE_HEIGHT + items * COMPARTMENT_ROW_HEIGHT;
|
|
177084
|
+
}
|
|
176812
177085
|
function portLabelPlacement(side, x, y, label, half = PORT_GLYPH_HALF, alongHalf = half) {
|
|
176813
177086
|
const vertical = side === "left" || side === "right";
|
|
176814
177087
|
const halfX = vertical ? half : alongHalf;
|
|
@@ -176846,18 +177119,20 @@ function edgeRouteKey(e, duplicateIndex = 0) {
|
|
|
176846
177119
|
const name = e.name ?? e.label;
|
|
176847
177120
|
return `${e.kind}:${e.from}->${e.to}${name ? `:${name}` : ""}${duplicateIndex > 0 ? `~${duplicateIndex}` : ""}`;
|
|
176848
177121
|
}
|
|
176849
|
-
var GV_TREE_EDGE_KIND_LIST = ["owningMembership", "composition", "reference", "definedBy"];
|
|
177122
|
+
var GV_TREE_EDGE_KIND_LIST = ["owningMembership", "composition", "portion", "reference", "definedBy"];
|
|
176850
177123
|
var GV_TREE_EDGE_KINDS = new Set(GV_TREE_EDGE_KIND_LIST);
|
|
176851
|
-
var GV_TREE_HIERARCHY_EDGE_KIND_LIST = ["owningMembership", "composition"];
|
|
177124
|
+
var GV_TREE_HIERARCHY_EDGE_KIND_LIST = ["owningMembership", "composition", "portion"];
|
|
176852
177125
|
var GV_TREE_HIERARCHY_EDGE_KINDS = new Set(GV_TREE_HIERARCHY_EDGE_KIND_LIST);
|
|
176853
177126
|
function gvModeEdges(model, mode) {
|
|
176854
177127
|
if (mode === "group") return [];
|
|
176855
|
-
|
|
177128
|
+
const packageIds = new Set(model.nodes.filter((node) => node.shape === "package").map((node) => node.id));
|
|
177129
|
+
const drawn = (edge) => edge.kind !== "owningMembership" && !packageIds.has(edge.from) && !packageIds.has(edge.to);
|
|
177130
|
+
return model.edges.every(drawn) ? model.edges : model.edges.filter(drawn);
|
|
176856
177131
|
}
|
|
176857
177132
|
function isGvUsageNode(n2) {
|
|
176858
177133
|
return n2.meta?.gvUsage === true;
|
|
176859
177134
|
}
|
|
176860
|
-
var GV_BOXED_USAGE_COMPARTMENTS = /* @__PURE__ */ new Set(["parts", "occurrences"]);
|
|
177135
|
+
var GV_BOXED_USAGE_COMPARTMENTS = /* @__PURE__ */ new Set(["parts", "occurrences", "timeslices", "snapshots", "individuals"]);
|
|
176861
177136
|
function stripBoxedUsageCompartments(nodes) {
|
|
176862
177137
|
let changed = false;
|
|
176863
177138
|
const out = nodes.map((n2) => {
|
|
@@ -176898,7 +177173,8 @@ var GV_CATEGORIES = [
|
|
|
176898
177173
|
function gvNodeCategory(node) {
|
|
176899
177174
|
if (node.shape === "package") return "package";
|
|
176900
177175
|
if (node.shape === "annotation" || node.shape === "dot") return "annotation";
|
|
176901
|
-
const k = node.keyword.toLowerCase().trim().replace(/^(individual|timeslice|snapshot|parallel|variation|variant|abstract|ref|derived)\s
|
|
177176
|
+
const k = node.keyword.toLowerCase().trim().replace(/^(individual|timeslice|snapshot|parallel|variation|variant|abstract|ref|derived)(\s+|$)/g, "").replace(/\s+def$/, "").trim();
|
|
177177
|
+
if (k === "" || k === "def") return "item";
|
|
176902
177178
|
const alias = {
|
|
176903
177179
|
part: "part",
|
|
176904
177180
|
port: "port",
|
|
@@ -176952,9 +177228,19 @@ function twKind(text) {
|
|
|
176952
177228
|
function compartmentHeight(node) {
|
|
176953
177229
|
if (!node.compartments?.length) return 0;
|
|
176954
177230
|
let h = 0;
|
|
176955
|
-
for (const c of node.compartments) h +=
|
|
177231
|
+
for (const c of node.compartments) h += compartmentBlockHeight(c.items.length);
|
|
176956
177232
|
return h;
|
|
176957
177233
|
}
|
|
177234
|
+
function featureCompartmentBandHeight(node) {
|
|
177235
|
+
if (node?.meta?.featureCompartmentsVisible !== true || !node.compartments?.length) return 0;
|
|
177236
|
+
return compartmentHeight(node) + FEATURE_COMPARTMENT_CLEARANCE;
|
|
177237
|
+
}
|
|
177238
|
+
function frameFeatureCompartmentHeight(frame2) {
|
|
177239
|
+
return featureCompartmentBandHeight(frame2);
|
|
177240
|
+
}
|
|
177241
|
+
function featureBandTopReserve(data) {
|
|
177242
|
+
return containerTopReserve(data.featureCompartmentHeight, data.frame !== void 0);
|
|
177243
|
+
}
|
|
176958
177244
|
function titleWidth(node) {
|
|
176959
177245
|
let t = `${node.name}${node.type ? ` : ${node.type}` : ""}`;
|
|
176960
177246
|
if (node.multiplicity) t += ` ${node.multiplicity}`;
|
|
@@ -177013,10 +177299,11 @@ function nodeSize(node, direction) {
|
|
|
177013
177299
|
const sideLabelW = (side) => ph.filter((p) => p.side === side).reduce((m, p) => Math.max(m, tw(p.port.name, 9) + 18), 0);
|
|
177014
177300
|
const portsW = ph.length ? sideLabelW("left") + sideLabelW("right") + 56 : 0;
|
|
177015
177301
|
const portRows = Math.max(ph.filter((p) => p.side === "left").length, ph.filter((p) => p.side === "right").length);
|
|
177302
|
+
const titleRightReserve = node.meta?.containerControls === true || node.meta?.internalsHidden === true ? CONTAINER_TITLE_RIGHT_RESERVE : 0;
|
|
177016
177303
|
const w = Math.max(
|
|
177017
177304
|
NODE_W,
|
|
177018
|
-
titleWidth(node) + 2 * PAD,
|
|
177019
|
-
twKind(`\xAB${node.keyword}\xBB`) + 2 * PAD,
|
|
177305
|
+
titleWidth(node) + 2 * PAD + titleRightReserve,
|
|
177306
|
+
twKind(`\xAB${node.keyword}\xBB`) + 2 * PAD + titleRightReserve,
|
|
177020
177307
|
compartmentWidth(node) + 2 * PAD,
|
|
177021
177308
|
portsW,
|
|
177022
177309
|
// issue #108 — an elongated port on the top/bottom edge widens the owner,
|
|
@@ -177024,13 +177311,15 @@ function nodeSize(node, direction) {
|
|
|
177024
177311
|
portedSideLength(ph, "top"),
|
|
177025
177312
|
portedSideLength(ph, "bottom")
|
|
177026
177313
|
);
|
|
177027
|
-
const
|
|
177314
|
+
const featureH = featureCompartmentBandHeight(node);
|
|
177315
|
+
const bodyH = Math.max(
|
|
177028
177316
|
BOX_H,
|
|
177029
|
-
36 + compartmentHeight(node),
|
|
177317
|
+
featureH > 0 ? 0 : 36 + compartmentHeight(node),
|
|
177030
177318
|
portRows ? 40 + portRows * 24 + 8 : 0,
|
|
177031
177319
|
portedSideLength(ph, "left"),
|
|
177032
177320
|
portedSideLength(ph, "right")
|
|
177033
177321
|
);
|
|
177322
|
+
const h = bodyH + featureH;
|
|
177034
177323
|
return { w, h };
|
|
177035
177324
|
}
|
|
177036
177325
|
function frameMinSize(f) {
|
|
@@ -177038,13 +177327,21 @@ function frameMinSize(f) {
|
|
|
177038
177327
|
const sideLabelW = (side) => ports.filter((p) => p.side === side).reduce((m, p) => Math.max(m, tw(p.port.name, 9) + 18), 0);
|
|
177039
177328
|
const headerW = twKind(`\xAB${f.keyword}\xBB`) + tw(f.label, 11) + 28;
|
|
177040
177329
|
const portsW = sideLabelW("left") + sideLabelW("right") + 56;
|
|
177041
|
-
const
|
|
177330
|
+
const featureH = frameFeatureCompartmentHeight(f);
|
|
177331
|
+
const w = Math.max(
|
|
177332
|
+
160,
|
|
177333
|
+
headerW,
|
|
177334
|
+
portsW,
|
|
177335
|
+
...featureH > 0 ? [compartmentWidth(f) + 2 * PAD] : [],
|
|
177336
|
+
portedSideLength(ports, "top"),
|
|
177337
|
+
portedSideLength(ports, "bottom")
|
|
177338
|
+
);
|
|
177042
177339
|
const portRows = Math.max(ports.filter((p) => p.side === "left").length, ports.filter((p) => p.side === "right").length);
|
|
177043
177340
|
const h = Math.max(
|
|
177044
|
-
58,
|
|
177045
|
-
36 + portRows * 24,
|
|
177046
|
-
portedSideLength(ports, "left"),
|
|
177047
|
-
portedSideLength(ports, "right")
|
|
177341
|
+
58 + featureH,
|
|
177342
|
+
36 + portRows * 24 + featureH,
|
|
177343
|
+
featureH + portedSideLength(ports, "left"),
|
|
177344
|
+
featureH + portedSideLength(ports, "right")
|
|
177048
177345
|
);
|
|
177049
177346
|
return { w, h };
|
|
177050
177347
|
}
|
|
@@ -177180,6 +177477,7 @@ function assignPortHandles(ports, overrides) {
|
|
|
177180
177477
|
side,
|
|
177181
177478
|
offset: +(PORT_BAND_START + centre * PORT_BAND_LENGTH).toFixed(4),
|
|
177182
177479
|
along: alongs[i],
|
|
177480
|
+
rootAlong: alongs[i] ?? endpointGlyphSize(port),
|
|
177183
177481
|
across: alongs[i] === void 0 ? void 0 : metricsOf(port).across,
|
|
177184
177482
|
toggleRun: toggleRunOf(port) || void 0
|
|
177185
177483
|
};
|
|
@@ -177211,6 +177509,7 @@ function assignPortHandles(ports, overrides) {
|
|
|
177211
177509
|
side: parent.side,
|
|
177212
177510
|
offset: parent.offset,
|
|
177213
177511
|
shift: { along: (parent.shift?.along ?? 0) + slot.along, across: slot.across },
|
|
177512
|
+
rootAlong: parent.rootAlong ?? parent.along ?? endpointGlyphSize(parent.port),
|
|
177214
177513
|
...hasToggle(kid) ? { along, across, toggleRun: toggleRunOf(kid) } : {}
|
|
177215
177514
|
};
|
|
177216
177515
|
nestedHandles.push(handle);
|
|
@@ -177220,10 +177519,10 @@ function assignPortHandles(ports, overrides) {
|
|
|
177220
177519
|
for (const parent of topHandles) placeChildren(parent);
|
|
177221
177520
|
return [...topHandles, ...nestedHandles];
|
|
177222
177521
|
}
|
|
177223
|
-
function sizeWithOverride(base, o) {
|
|
177522
|
+
function sizeWithOverride(base, o, minimum = { w: 48, h: 24 }) {
|
|
177224
177523
|
return {
|
|
177225
|
-
w: o?.w !== void 0 ? Math.max(
|
|
177226
|
-
h: o?.h !== void 0 ? Math.max(
|
|
177524
|
+
w: o?.w !== void 0 ? Math.max(minimum.w, o.w) : base.w,
|
|
177525
|
+
h: o?.h !== void 0 ? Math.max(minimum.h, o.h) : base.h
|
|
177227
177526
|
};
|
|
177228
177527
|
}
|
|
177229
177528
|
function normalizeIvModel(model) {
|
|
@@ -177258,6 +177557,7 @@ function promoteIvLeafPartsToFrames(model) {
|
|
|
177258
177557
|
const existing = frames[existingIndex];
|
|
177259
177558
|
frames[existingIndex] = {
|
|
177260
177559
|
...existing,
|
|
177560
|
+
layoutKey: n2.layoutKey ?? existing.layoutKey,
|
|
177261
177561
|
label: n2.name || existing.label,
|
|
177262
177562
|
isDef: n2.isDef ?? existing.isDef,
|
|
177263
177563
|
type: n2.type ?? existing.type,
|
|
@@ -177275,6 +177575,7 @@ function promoteIvLeafPartsToFrames(model) {
|
|
|
177275
177575
|
if (isAnchor || isLeafUsagePart) {
|
|
177276
177576
|
frames.push({
|
|
177277
177577
|
id: n2.id,
|
|
177578
|
+
layoutKey: n2.layoutKey,
|
|
177278
177579
|
label: n2.name,
|
|
177279
177580
|
keyword: n2.keyword,
|
|
177280
177581
|
parent: n2.frame,
|
|
@@ -177332,13 +177633,11 @@ function applyCaseDefs(model, show) {
|
|
|
177332
177633
|
edges
|
|
177333
177634
|
};
|
|
177334
177635
|
}
|
|
177335
|
-
function collapseIvModel(model,
|
|
177636
|
+
function collapseIvModel(model, hiddenInternals) {
|
|
177336
177637
|
const frames = model.frames ?? [];
|
|
177337
177638
|
if (!frames.length) return model;
|
|
177338
177639
|
const frameById = new Map(frames.map((f) => [f.id, f]));
|
|
177339
|
-
const requested = new Set(
|
|
177340
|
-
Object.entries(collapsed).filter(([, c]) => c).map(([id2]) => id2).filter((id2) => frameById.get(id2)?.keyword !== "package" && frameById.get(id2)?.meta?.anchorFrame !== true)
|
|
177341
|
-
);
|
|
177640
|
+
const requested = new Set(frames.filter((frame2) => framePresentationEnabled(hiddenInternals, frame2, true) && isCollapsibleFrame("iv", frame2)).map((frame2) => frame2.id));
|
|
177342
177641
|
if (requested.size === 0) return model;
|
|
177343
177642
|
const hasRequestedAncestor = (id2) => {
|
|
177344
177643
|
let p = frameById.get(id2)?.parent;
|
|
@@ -177371,6 +177670,7 @@ function collapseIvModel(model, collapsed) {
|
|
|
177371
177670
|
if (!f) return [];
|
|
177372
177671
|
return [{
|
|
177373
177672
|
id: f.id,
|
|
177673
|
+
layoutKey: f.layoutKey,
|
|
177374
177674
|
name: f.label,
|
|
177375
177675
|
keyword: f.keyword,
|
|
177376
177676
|
isDef: f.isDef ?? false,
|
|
@@ -177381,7 +177681,7 @@ function collapseIvModel(model, collapsed) {
|
|
|
177381
177681
|
compartments: f.compartments,
|
|
177382
177682
|
frame: f.parent,
|
|
177383
177683
|
source: f.source,
|
|
177384
|
-
meta: { ...f.meta,
|
|
177684
|
+
meta: { ...f.meta, internalsHidden: true }
|
|
177385
177685
|
}];
|
|
177386
177686
|
});
|
|
177387
177687
|
return {
|
|
@@ -177394,22 +177694,67 @@ function collapseIvModel(model, collapsed) {
|
|
|
177394
177694
|
function isCollapsibleActionFrame(frame2) {
|
|
177395
177695
|
return frame2.meta?.compositeAction === true && frame2.meta?.anchorFrame !== true;
|
|
177396
177696
|
}
|
|
177697
|
+
function isCollapsibleStateFrame(frame2) {
|
|
177698
|
+
return frame2.meta?.composite === true && frame2.meta?.anchorFrame !== true;
|
|
177699
|
+
}
|
|
177397
177700
|
function frameStateKey(frame2) {
|
|
177398
177701
|
return frame2.layoutKey ?? frame2.id;
|
|
177399
177702
|
}
|
|
177703
|
+
function framePresentationEnabled(current2, frame2, acceptLegacyDisplayId = false, whenAbsent = false) {
|
|
177704
|
+
const key = frameStateKey(frame2);
|
|
177705
|
+
if (Object.prototype.hasOwnProperty.call(current2, key)) return current2[key] === true;
|
|
177706
|
+
if (acceptLegacyDisplayId && key !== frame2.id && Object.prototype.hasOwnProperty.call(current2, frame2.id)) {
|
|
177707
|
+
return current2[frame2.id] === true;
|
|
177708
|
+
}
|
|
177709
|
+
return whenAbsent;
|
|
177710
|
+
}
|
|
177400
177711
|
function isCollapsibleFrame(kind, frame2) {
|
|
177401
177712
|
if (frame2.meta?.anchorFrame === true) return false;
|
|
177402
177713
|
if (kind === "iv") return frame2.keyword !== "package";
|
|
177403
177714
|
if (kind === "afv") return isCollapsibleActionFrame(frame2);
|
|
177715
|
+
if (kind === "stv") return isCollapsibleStateFrame(frame2);
|
|
177404
177716
|
return false;
|
|
177405
177717
|
}
|
|
177406
|
-
function
|
|
177718
|
+
function isFeatureCompartmentNode(kind, node) {
|
|
177719
|
+
if (node.meta?.internalsHidden === true) return false;
|
|
177720
|
+
if (node.meta?.boundary === true || node.meta?.boundaryBox === true) return false;
|
|
177721
|
+
if (kind === "iv") return node.shape === "box" && /\b(?:part|item)\b/i.test(node.keyword);
|
|
177722
|
+
if (kind === "afv") return node.shape === "action";
|
|
177723
|
+
if (kind === "stv") return node.shape === "state";
|
|
177724
|
+
return false;
|
|
177725
|
+
}
|
|
177726
|
+
function applyFeatureCompartmentVisibility(model, visibleFeatureCompartments, hiddenInternals = {}) {
|
|
177727
|
+
if (!CONTAINER_PRESENTATION_KINDS.has(model.kind)) return model;
|
|
177728
|
+
const legacy = model.kind === "iv";
|
|
177729
|
+
let changed = false;
|
|
177730
|
+
const project = (host, leaf) => {
|
|
177731
|
+
const visible = framePresentationEnabled(visibleFeatureCompartments, host, legacy, leaf);
|
|
177732
|
+
const compartments = visible ? host.compartments : void 0;
|
|
177733
|
+
const internalsHidden = leaf ? framePresentationEnabled(hiddenInternals, host, legacy) : host.meta?.internalsHidden === true;
|
|
177734
|
+
if (compartments === host.compartments && host.meta?.containerControls === true && host.meta?.featureCompartmentsVisible === visible && (!leaf || host.meta?.internalsHidden === internalsHidden)) return host;
|
|
177735
|
+
changed = true;
|
|
177736
|
+
return {
|
|
177737
|
+
...host,
|
|
177738
|
+
compartments,
|
|
177739
|
+
meta: {
|
|
177740
|
+
...host.meta,
|
|
177741
|
+
containerControls: true,
|
|
177742
|
+
featureCompartmentsVisible: visible,
|
|
177743
|
+
...leaf ? { internalsHidden } : {}
|
|
177744
|
+
}
|
|
177745
|
+
};
|
|
177746
|
+
};
|
|
177747
|
+
const frames = (model.frames ?? []).map((frame2) => isCollapsibleFrame(model.kind, frame2) ? project(frame2, false) : frame2);
|
|
177748
|
+
const nodes = model.nodes.map((node) => isFeatureCompartmentNode(model.kind, node) ? project(node, true) : node);
|
|
177749
|
+
return changed ? { ...model, frames, nodes } : model;
|
|
177750
|
+
}
|
|
177751
|
+
var CONTAINER_PRESENTATION_KINDS = /* @__PURE__ */ new Set(["iv", "afv", "stv"]);
|
|
177752
|
+
function collapseActionFrames(model, hiddenInternals, isHost = isCollapsibleActionFrame, collapsedShape = "action") {
|
|
177407
177753
|
const frames = model.frames ?? [];
|
|
177408
177754
|
if (!frames.length) return model;
|
|
177409
177755
|
const frameById = new Map(frames.map((f) => [f.id, f]));
|
|
177410
|
-
const on = new Set(Object.entries(collapsed).filter(([, value]) => value).map(([key]) => key));
|
|
177411
177756
|
const requested = new Set(
|
|
177412
|
-
frames.filter((f) =>
|
|
177757
|
+
frames.filter((f) => framePresentationEnabled(hiddenInternals, f) && isHost(f)).map((f) => f.id)
|
|
177413
177758
|
);
|
|
177414
177759
|
if (requested.size === 0) return model;
|
|
177415
177760
|
const rootOf = (id2) => {
|
|
@@ -177448,17 +177793,18 @@ function collapseActionFrames(model, collapsed) {
|
|
|
177448
177793
|
if (!f) return [];
|
|
177449
177794
|
return [{
|
|
177450
177795
|
id: f.id,
|
|
177796
|
+
layoutKey: f.layoutKey,
|
|
177451
177797
|
name: f.label,
|
|
177452
177798
|
keyword: f.keyword,
|
|
177453
177799
|
isDef: f.isDef ?? false,
|
|
177454
|
-
shape:
|
|
177800
|
+
shape: collapsedShape,
|
|
177455
177801
|
type: f.type,
|
|
177456
177802
|
multiplicity: f.multiplicity,
|
|
177457
177803
|
ports: f.ports,
|
|
177458
177804
|
compartments: f.compartments,
|
|
177459
177805
|
frame: f.parent,
|
|
177460
177806
|
source: f.source,
|
|
177461
|
-
meta: { ...f.meta,
|
|
177807
|
+
meta: { ...f.meta, internalsHidden: true }
|
|
177462
177808
|
}];
|
|
177463
177809
|
});
|
|
177464
177810
|
const seenEdge = /* @__PURE__ */ new Set();
|
|
@@ -177498,8 +177844,13 @@ function modelToFlow(model, opts) {
|
|
|
177498
177844
|
model = collapseNestedPorts(model, opts.nestedPorts ?? {});
|
|
177499
177845
|
if (model.kind === "iv") model = normalizeIvModel(model);
|
|
177500
177846
|
if (model.kind === "iv" && (model.meta?.overview === true || model.meta?.unified === true)) model = promoteIvLeafPartsToFrames(model);
|
|
177501
|
-
|
|
177502
|
-
|
|
177847
|
+
const legacyPresentation = model.kind === "iv" ? opts.ivCompartments : model.kind === "afv" ? opts.collapsedActions : void 0;
|
|
177848
|
+
const hiddenInternals = opts.hiddenInternals ?? legacyPresentation ?? {};
|
|
177849
|
+
const visibleFeatureCompartments = opts.visibleFeatureCompartments ?? legacyPresentation ?? {};
|
|
177850
|
+
model = applyFeatureCompartmentVisibility(model, visibleFeatureCompartments, hiddenInternals);
|
|
177851
|
+
if (model.kind === "iv") model = collapseIvModel(model, hiddenInternals);
|
|
177852
|
+
if (model.kind === "afv") model = collapseActionFrames(model, hiddenInternals);
|
|
177853
|
+
if (model.kind === "stv") model = collapseActionFrames(model, hiddenInternals, isCollapsibleStateFrame, "state");
|
|
177503
177854
|
if (model.kind === "cv" && opts.subjectBoundary) model = applyCaseBoundary(model);
|
|
177504
177855
|
const ov = opts.overrides ?? {};
|
|
177505
177856
|
const nodes = [];
|
|
@@ -177528,7 +177879,13 @@ function modelToFlow(model, opts) {
|
|
|
177528
177879
|
}
|
|
177529
177880
|
const orderedFrames = [...frames].sort((a2, b) => frameDepth(a2.id) - frameDepth(b.id));
|
|
177530
177881
|
for (const f of orderedFrames) {
|
|
177531
|
-
const
|
|
177882
|
+
const natural = frameMinSize(f);
|
|
177883
|
+
const featureH = frameFeatureCompartmentHeight(f);
|
|
177884
|
+
const size = sizeWithOverride(
|
|
177885
|
+
natural,
|
|
177886
|
+
ov[f.layoutKey ?? f.id],
|
|
177887
|
+
{ w: 48, h: featureH > 0 ? natural.h : 24 }
|
|
177888
|
+
);
|
|
177532
177889
|
nodes.push({
|
|
177533
177890
|
id: f.id,
|
|
177534
177891
|
type: "frame",
|
|
@@ -177540,6 +177897,8 @@ function modelToFlow(model, opts) {
|
|
|
177540
177897
|
ports: assignPortHandles(f.ports, opts.portOverrides),
|
|
177541
177898
|
w: size.w,
|
|
177542
177899
|
h: size.h,
|
|
177900
|
+
featureCompartmentHeight: featureH,
|
|
177901
|
+
featureCompartmentMinHeight: featureH > 0 ? natural.h : void 0,
|
|
177543
177902
|
showPortLabels: opts.showPortLabels,
|
|
177544
177903
|
showMult: opts.showMult,
|
|
177545
177904
|
connectPointSpacing,
|
|
@@ -177591,8 +177950,16 @@ function modelToFlow(model, opts) {
|
|
|
177591
177950
|
for (const n2 of renderModelNodes) {
|
|
177592
177951
|
const canvasNode = nodeForCanvas(n2);
|
|
177593
177952
|
const isGeo = model.kind === "gev" && n2.geo !== void 0;
|
|
177953
|
+
const featureH = featureCompartmentBandHeight(n2);
|
|
177594
177954
|
const base = isGeo ? { w: 24, h: 24 } : nodeSize(canvasNode, opts.direction);
|
|
177595
|
-
const size = sizeWithOverride(
|
|
177955
|
+
const size = sizeWithOverride(
|
|
177956
|
+
base,
|
|
177957
|
+
ov[n2.layoutKey ?? n2.id],
|
|
177958
|
+
{
|
|
177959
|
+
w: canvasNode.meta?.containerControls === true || canvasNode.meta?.internalsHidden === true ? COLLAPSED_CONTAINER_MIN_WIDTH : 48,
|
|
177960
|
+
h: featureH > 0 ? base.h : 24
|
|
177961
|
+
}
|
|
177962
|
+
);
|
|
177596
177963
|
const parentId = n2.frame ?? (model.kind === "gv" && n2.parent && gvPackageIds.has(n2.parent) ? n2.parent : void 0) ?? (boundary ? boundary.id : void 0);
|
|
177597
177964
|
nodes.push({
|
|
177598
177965
|
id: n2.id,
|
|
@@ -177605,6 +177972,8 @@ function modelToFlow(model, opts) {
|
|
|
177605
177972
|
ports: assignPortHandles(n2.ports, opts.portOverrides),
|
|
177606
177973
|
w: size.w,
|
|
177607
177974
|
h: size.h,
|
|
177975
|
+
featureCompartmentHeight: featureH,
|
|
177976
|
+
featureCompartmentMinHeight: featureH > 0 ? base.h : void 0,
|
|
177608
177977
|
showPortLabels: opts.showPortLabels,
|
|
177609
177978
|
showMult: opts.showMult,
|
|
177610
177979
|
connectPointSpacing
|
|
@@ -177623,10 +177992,14 @@ function modelToFlow(model, opts) {
|
|
|
177623
177992
|
// often nearly the whole visible canvas at typical zoom, so its empty
|
|
177624
177993
|
// interior must pan the canvas rather than move the part (a click
|
|
177625
177994
|
// there still selects it — dragHandle only gates the DRAG gesture,
|
|
177626
|
-
// never click).
|
|
177627
|
-
//
|
|
177628
|
-
//
|
|
177629
|
-
|
|
177995
|
+
// never click). Every other diagram kind keeps the whole-body drag.
|
|
177996
|
+
// User report 2026-08-11 — the grabbable area was the SVG title TEXT
|
|
177997
|
+
// alone, which a part with hidden internals could barely be moved by
|
|
177998
|
+
// and which carries no move cursor: `.rf-node-header` is the same
|
|
177999
|
+
// full-width title strip a container frame has, so a part behaves the
|
|
178000
|
+
// same whether it draws its internals or not. The text selectors stay
|
|
178001
|
+
// for the title of a node whose header strip is not rendered.
|
|
178002
|
+
...model.kind === "iv" && !isGeo ? { dragHandle: ".rf-node-header, .dnode-kind, .dnode-label" } : {}
|
|
177630
178003
|
});
|
|
177631
178004
|
}
|
|
177632
178005
|
if (model.kind === "sv") {
|
|
@@ -178104,6 +178477,9 @@ async function elkLayout(elk, graph) {
|
|
|
178104
178477
|
}
|
|
178105
178478
|
var FRAME_PAD_TOP = 36;
|
|
178106
178479
|
var FRAME_PAD = 22;
|
|
178480
|
+
function frameTopPad(node) {
|
|
178481
|
+
return FRAME_PAD_TOP + frameFeatureCompartmentHeight(node.data.frame);
|
|
178482
|
+
}
|
|
178107
178483
|
var GV_DOCK_FAMILY_ORDER = /* @__PURE__ */ new Map([
|
|
178108
178484
|
["owningMembership", 0],
|
|
178109
178485
|
["composition", 1],
|
|
@@ -178748,7 +179124,7 @@ function buildElkTree(nodes, direction, kind, tree) {
|
|
|
178748
179124
|
...children2.length ? {
|
|
178749
179125
|
children: children2.map(toElk),
|
|
178750
179126
|
layoutOptions: {
|
|
178751
|
-
"elk.padding": `[top=${
|
|
179127
|
+
"elk.padding": `[top=${frameTopPad(n2)},left=${FRAME_PAD},bottom=${FRAME_PAD},right=${FRAME_PAD}]`,
|
|
178752
179128
|
...minimum,
|
|
178753
179129
|
// REQ-371 — repeat the selected axis on EVERY compound part.
|
|
178754
179130
|
// ELK does not reliably inherit a root direction into nested
|
|
@@ -178854,12 +179230,12 @@ function arrangeIvHierarchy(nodes, direction) {
|
|
|
178854
179230
|
children2.push(node);
|
|
178855
179231
|
byParent.set(key, children2);
|
|
178856
179232
|
}
|
|
178857
|
-
const arrange = (children2,
|
|
179233
|
+
const arrange = (children2, insetFor) => {
|
|
178858
179234
|
if (!children2.length) return;
|
|
178859
179235
|
const minX = Math.min(...children2.map((child) => child.position.x));
|
|
178860
179236
|
const minY = Math.min(...children2.map((child) => child.position.y));
|
|
178861
|
-
const baseX =
|
|
178862
|
-
const baseY =
|
|
179237
|
+
const baseX = insetFor ? FRAME_PAD : 0;
|
|
179238
|
+
const baseY = insetFor ? frameTopPad(insetFor) : 0;
|
|
178863
179239
|
for (const child of children2) {
|
|
178864
179240
|
child.position = {
|
|
178865
179241
|
x: child.position.x - minX + baseX,
|
|
@@ -178938,7 +179314,7 @@ function arrangeIvHierarchy(nodes, direction) {
|
|
|
178938
179314
|
frame2.data = { ...frame2.data, w: minimum.w, h: minimum.h };
|
|
178939
179315
|
const children2 = byParent.get(frame2.id) ?? [];
|
|
178940
179316
|
if (!children2.length) continue;
|
|
178941
|
-
arrange(children2,
|
|
179317
|
+
arrange(children2, frame2);
|
|
178942
179318
|
const maxX = Math.max(...children2.map((child) => child.position.x + (child.width ?? child.data.w)));
|
|
178943
179319
|
const maxY = Math.max(...children2.map((child) => child.position.y + (child.height ?? child.data.h)));
|
|
178944
179320
|
const width = Math.max(minimum.w, maxX + FRAME_PAD);
|
|
@@ -178947,7 +179323,7 @@ function arrangeIvHierarchy(nodes, direction) {
|
|
|
178947
179323
|
frame2.height = height;
|
|
178948
179324
|
frame2.data = { ...frame2.data, w: width, h: height };
|
|
178949
179325
|
}
|
|
178950
|
-
arrange(byParent.get(void 0) ?? [],
|
|
179326
|
+
arrange(byParent.get(void 0) ?? [], void 0);
|
|
178951
179327
|
}
|
|
178952
179328
|
function applyElkPositions(node, byId) {
|
|
178953
179329
|
for (const child of node.children ?? []) {
|
|
@@ -179066,7 +179442,13 @@ function nextSideAnchor(counts, offsetsCache, node, side, spacing, demand) {
|
|
|
179066
179442
|
let offsets = offsetsCache.get(key);
|
|
179067
179443
|
if (!offsets) {
|
|
179068
179444
|
const derived = sidePointOffsetsForLength(
|
|
179069
|
-
sideEffectiveLength(
|
|
179445
|
+
sideEffectiveLength(
|
|
179446
|
+
node.data.node?.shape,
|
|
179447
|
+
side,
|
|
179448
|
+
node.data.w,
|
|
179449
|
+
node.data.h,
|
|
179450
|
+
featureBandTopReserve(node.data)
|
|
179451
|
+
),
|
|
179070
179452
|
spacing
|
|
179071
179453
|
);
|
|
179072
179454
|
const needed = demand?.get(key) ?? 0;
|
|
@@ -179078,7 +179460,13 @@ function nextSideAnchor(counts, offsetsCache, node, side, spacing, demand) {
|
|
|
179078
179460
|
}
|
|
179079
179461
|
const offset2 = offsets[i % offsets.length];
|
|
179080
179462
|
if (i < offsets.length && !sidePointOffsetsForLength(
|
|
179081
|
-
sideEffectiveLength(
|
|
179463
|
+
sideEffectiveLength(
|
|
179464
|
+
node.data.node?.shape,
|
|
179465
|
+
side,
|
|
179466
|
+
node.data.w,
|
|
179467
|
+
node.data.h,
|
|
179468
|
+
featureBandTopReserve(node.data)
|
|
179469
|
+
),
|
|
179082
179470
|
spacing
|
|
179083
179471
|
).some((o) => Math.abs(o - offset2) < 1e-6)) {
|
|
179084
179472
|
const explicit = node.data.explicitSideAnchors?.[side] ?? [];
|
|
@@ -189511,7 +189899,7 @@ function dockPoint(node, handleId, byId, fallback) {
|
|
|
189511
189899
|
const ph = node.data.ports?.find((p) => p.port.id === port.portId);
|
|
189512
189900
|
if (ph) {
|
|
189513
189901
|
const dockSide = clampDockSide(port.side, ph.side);
|
|
189514
|
-
const rect = portGlyphRect(ph, w, h);
|
|
189902
|
+
const rect = portGlyphRect(ph, w, h, featureBandTopReserve(node.data));
|
|
189515
189903
|
const n2 = DOCK_NORMAL[dockSide];
|
|
189516
189904
|
const at = portDockAt(rect, ph.side, dockSide);
|
|
189517
189905
|
return { point: { x: pos.x + at.x, y: pos.y + at.y }, normal: n2 };
|
|
@@ -189519,12 +189907,19 @@ function dockPoint(node, handleId, byId, fallback) {
|
|
|
189519
189907
|
}
|
|
189520
189908
|
const structural = node.data.structuralDocks?.find((dock) => dock.id === handleId);
|
|
189521
189909
|
if (structural) {
|
|
189522
|
-
const c = sidePoint(structural.side, structural.offset, w, h);
|
|
189910
|
+
const c = sidePoint(structural.side, structural.offset, w, h, featureBandTopReserve(node.data));
|
|
189523
189911
|
return { point: { x: pos.x + c.x, y: pos.y + c.y }, normal: DOCK_NORMAL[structural.side] };
|
|
189524
189912
|
}
|
|
189525
189913
|
const sideAnchor = parseSideAnchorHandleId(handleId);
|
|
189526
189914
|
if (sideAnchor) {
|
|
189527
|
-
const c = sideSurfacePoint(
|
|
189915
|
+
const c = sideSurfacePoint(
|
|
189916
|
+
node.data.node?.shape,
|
|
189917
|
+
sideAnchor.side,
|
|
189918
|
+
sideAnchor.offset,
|
|
189919
|
+
w,
|
|
189920
|
+
h,
|
|
189921
|
+
featureBandTopReserve(node.data)
|
|
189922
|
+
);
|
|
189528
189923
|
return { point: { x: pos.x + c.x, y: pos.y + c.y }, normal: DOCK_NORMAL[sideAnchor.side] };
|
|
189529
189924
|
}
|
|
189530
189925
|
return { point: fallback };
|
|
@@ -189607,7 +190002,9 @@ function paintedRouteForEdge(edge, nodes, byId, edges = [], lineStyle = "orthogo
|
|
|
189607
190002
|
return { points: manhattanThroughPoints([sd.point, ...route, td.point], sd.normal), corner: 0 };
|
|
189608
190003
|
}
|
|
189609
190004
|
const structural = isStructuralBusEdge(edge);
|
|
189610
|
-
const
|
|
190005
|
+
const sp = sd.point;
|
|
190006
|
+
const tp = td.point;
|
|
190007
|
+
const via = fanVia(sp, tp, parallelEdgeOffset(
|
|
189611
190008
|
edge.id,
|
|
189612
190009
|
edge.source,
|
|
189613
190010
|
edge.target,
|
|
@@ -189615,6 +190012,9 @@ function paintedRouteForEdge(edge, nodes, byId, edges = [], lineStyle = "orthogo
|
|
|
189615
190012
|
edge.targetHandle,
|
|
189616
190013
|
edges
|
|
189617
190014
|
));
|
|
190015
|
+
if (via.length) {
|
|
190016
|
+
return { points: manhattanThroughPoints([sp, ...via, tp], sd.normal), corner: 0 };
|
|
190017
|
+
}
|
|
189618
190018
|
if (edgeUsesObstacleRouting(edge.data?.kind, lineStyle, structural)) {
|
|
189619
190019
|
return {
|
|
189620
190020
|
points: routeOrthogonalAroundRects(sp, tp, obstacleRects(nodes, edge.source, edge.target, byId, scene), {
|
|
@@ -189642,7 +190042,7 @@ function geometrySignature(nodes) {
|
|
|
189642
190042
|
if (n2.dragging === true || n2.resizing === true) continue;
|
|
189643
190043
|
out += `${n2.id}:${n2.parentId ?? ""}:${n2.type ?? ""}:${n2.hidden ? 1 : 0}:`;
|
|
189644
190044
|
out += `${n2.position.x},${n2.position.y},${n2.width ?? n2.measured?.width ?? n2.data.w},${n2.height ?? n2.measured?.height ?? n2.data.h}`;
|
|
189645
|
-
out += `:${n2.data.node?.shape ?? ""}:${n2.data.isBoundary ? 1 : 0}`;
|
|
190045
|
+
out += `:${n2.data.node?.shape ?? ""}:${n2.data.isBoundary ? 1 : 0}:${n2.data.featureCompartmentHeight ?? 0}`;
|
|
189646
190046
|
for (const p of n2.data.ports ?? []) {
|
|
189647
190047
|
out += `|${p.port.id},${p.side},${p.offset},${p.along ?? ""},${p.shift?.along ?? ""},${p.shift?.across ?? ""}`;
|
|
189648
190048
|
}
|
|
@@ -189762,12 +190162,15 @@ function parallelOffsetMap(edges) {
|
|
|
189762
190162
|
const groups = /* @__PURE__ */ new Map();
|
|
189763
190163
|
for (const edge of edges) {
|
|
189764
190164
|
if (isPortDocked(edge.sourceHandle) || isPortDocked(edge.targetHandle)) continue;
|
|
189765
|
-
const
|
|
190165
|
+
const forward = edge.source <= edge.target;
|
|
190166
|
+
const [a2, b] = forward ? [edge.source, edge.target] : [edge.target, edge.source];
|
|
190167
|
+
const [ha, hb] = forward ? [edge.sourceHandle ?? "", edge.targetHandle ?? ""] : [edge.targetHandle ?? "", edge.sourceHandle ?? ""];
|
|
189766
190168
|
let byTarget = groups.get(a2);
|
|
189767
190169
|
if (!byTarget) groups.set(a2, byTarget = /* @__PURE__ */ new Map());
|
|
189768
|
-
const
|
|
190170
|
+
const key = `${b}\0${ha}\0${hb}`;
|
|
190171
|
+
const group = byTarget.get(key) ?? [];
|
|
189769
190172
|
group.push(edge);
|
|
189770
|
-
byTarget.set(
|
|
190173
|
+
byTarget.set(key, group);
|
|
189771
190174
|
}
|
|
189772
190175
|
cached = /* @__PURE__ */ new Map();
|
|
189773
190176
|
for (const byTarget of groups.values()) {
|
|
@@ -189788,14 +190191,14 @@ function parallelEdgeOffset(id2, _source, _target, sourceHandle, targetHandle, e
|
|
|
189788
190191
|
if (isPortDocked(sourceHandle) || isPortDocked(targetHandle)) return 0;
|
|
189789
190192
|
return parallelOffsetMap(edges).get(id2) ?? 0;
|
|
189790
190193
|
}
|
|
189791
|
-
function
|
|
190194
|
+
function fanVia(sp, tp, off) {
|
|
189792
190195
|
const dx = tp.x - sp.x;
|
|
189793
190196
|
const dy = tp.y - sp.y;
|
|
189794
190197
|
const len = Math.hypot(dx, dy);
|
|
189795
|
-
if (!len || !off) return [
|
|
190198
|
+
if (!len || !off) return [];
|
|
189796
190199
|
const nx = -dy / len;
|
|
189797
190200
|
const ny = dx / len;
|
|
189798
|
-
return [{ x: sp.x + nx * off, y: sp.y +
|
|
190201
|
+
return [{ x: (sp.x + tp.x) / 2 + nx * off, y: (sp.y + tp.y) / 2 + ny * off }];
|
|
189799
190202
|
}
|
|
189800
190203
|
var GV_BUS_EDGE_KINDS = /* @__PURE__ */ new Set([
|
|
189801
190204
|
"owningMembership",
|
|
@@ -189845,13 +190248,14 @@ function computeEdgePath(args) {
|
|
|
189845
190248
|
live ? { x: live.targetX, y: live.targetY } : nodeCentre(targetNode, byId)
|
|
189846
190249
|
);
|
|
189847
190250
|
const route = args.route ?? edge.data?.route;
|
|
189848
|
-
const
|
|
189849
|
-
const
|
|
189850
|
-
const
|
|
190251
|
+
const sp = sd.point;
|
|
190252
|
+
const tp = td.point;
|
|
190253
|
+
const via = route?.length ? route : fanVia(sp, tp, parallelEdgeOffset(edge.id, edge.source, edge.target, edge.sourceHandle, edge.targetHandle, edges));
|
|
190254
|
+
const anchors = [sp, ...via, tp];
|
|
189851
190255
|
const common = { sourceX: sp.x, sourceY: sp.y, targetX: tp.x, targetY: tp.y };
|
|
189852
190256
|
const structural = isStructuralBusEdge(edge);
|
|
189853
190257
|
const wantsObstacles = edgeUsesObstacleRouting(edge.data?.kind, lineStyle, structural);
|
|
189854
|
-
const
|
|
190258
|
+
const guided = via.length > 0 ? lineStyle === "curved" ? { path: smoothPathThroughPoints(anchors), label: pathMidpoint(anchors), points: void 0 } : lineStyle === "straight" ? { path: pointsToPath(anchors), label: pathMidpoint(anchors), points: void 0 } : (() => {
|
|
189855
190259
|
const pts = manhattanThroughPoints(anchors, sd.normal);
|
|
189856
190260
|
return { path: pointsToPath(pts), label: pathMidpoint(pts), points: pts };
|
|
189857
190261
|
})() : void 0;
|
|
@@ -189869,8 +190273,8 @@ function computeEdgePath(args) {
|
|
|
189869
190273
|
normal: sd.normal
|
|
189870
190274
|
};
|
|
189871
190275
|
}
|
|
189872
|
-
const autoRouted = wantsObstacles && !
|
|
189873
|
-
const routed =
|
|
190276
|
+
const autoRouted = wantsObstacles && !guided && !args.dragging ? routedOrthogonalPath({ point: sp, normal: sd.normal }, { point: tp, normal: td.normal }, nodes, edge.source, edge.target) : void 0;
|
|
190277
|
+
const routed = guided ?? autoRouted;
|
|
189874
190278
|
if (routed) {
|
|
189875
190279
|
return {
|
|
189876
190280
|
path: routed.path,
|
|
@@ -189930,6 +190334,13 @@ function markersFor(kind) {
|
|
|
189930
190334
|
case "redefinition":
|
|
189931
190335
|
case "referenceSubsetting":
|
|
189932
190336
|
return { end: "url(#tri-hollow)" };
|
|
190337
|
+
// REQ-160 — temporal decomposition (OMG 8.2.3.9): an occurrence's life →
|
|
190338
|
+
// one `timeslice`/`snapshot` PORTION of it. A portion specializes the life
|
|
190339
|
+
// it is part of, so it carries the specialization triangle — at the WHOLE
|
|
190340
|
+
// end, which is where the edge starts, so the marker is a start-oriented
|
|
190341
|
+
// twin of `tri-hollow` rather than the end-oriented one.
|
|
190342
|
+
case "portion":
|
|
190343
|
+
return { start: "url(#tri-hollow-start)" };
|
|
189933
190344
|
case "flow":
|
|
189934
190345
|
case "message":
|
|
189935
190346
|
return { end: "url(#arrow-cyan)" };
|
|
@@ -190250,6 +190661,10 @@ var MARKER_DEFS_SVG = [
|
|
|
190250
190661
|
`<marker markerUnits="userSpaceOnUse" id="arrow-open-neutral" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0 0L10 5L0 10" fill="none" stroke="${GREY}" stroke-width="1.4"/></marker>`,
|
|
190251
190662
|
`<marker markerUnits="userSpaceOnUse" id="tri-accent" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0 0L10 5L0 10z" fill="${ACCENT}"/></marker>`,
|
|
190252
190663
|
`<marker markerUnits="userSpaceOnUse" id="tri-hollow" viewBox="0 0 12 12" refX="11" refY="6" markerWidth="11" markerHeight="11" orient="auto"><path d="M0 0L12 6L0 12z" fill="${BG}" stroke="${GREY}" stroke-width="1.2"/></marker>`,
|
|
190664
|
+
// REQ-160 — the portion (temporal-decomposition) triangle sits at the START of
|
|
190665
|
+
// the edge, at the whole occurrence. Same shape as `tri-hollow`, mirrored so
|
|
190666
|
+
// `orient="auto"` points it back along the line instead of down it.
|
|
190667
|
+
`<marker markerUnits="userSpaceOnUse" id="tri-hollow-start" viewBox="0 0 12 12" refX="1" refY="6" markerWidth="11" markerHeight="11" orient="auto"><path d="M12 0L0 6L12 12z" fill="${BG}" stroke="${GREY}" stroke-width="1.2"/></marker>`,
|
|
190253
190668
|
`<marker markerUnits="userSpaceOnUse" id="defined-by" viewBox="0 0 18 12" refX="17" refY="6" markerWidth="12" markerHeight="8" orient="auto"><circle cx="3.2" cy="3.6" r="1.6" fill="${GREY}"/><circle cx="3.2" cy="8.4" r="1.6" fill="${GREY}"/><path d="M7 1L17 6L7 11z" fill="${GREY}"/></marker>`,
|
|
190254
190669
|
`<marker markerUnits="userSpaceOnUse" id="owning-membership" viewBox="0 0 14 14" refX="1" refY="7" markerWidth="12" markerHeight="12" orient="auto"><circle cx="7" cy="7" r="5.2" fill="${BG}" stroke="${GREY}" stroke-width="1.2"/><path d="M3.8 7H10.2M7 3.8V10.2" fill="none" stroke="${GREY}" stroke-width="1.2"/></marker>`,
|
|
190255
190670
|
`<marker markerUnits="userSpaceOnUse" id="diamond-filled" viewBox="0 0 14 14" refX="1" refY="7" markerWidth="12" markerHeight="12" orient="auto"><path d="M0 7L7 0L14 7L7 14z" fill="${GREY}"/></marker>`,
|
|
@@ -190263,6 +190678,7 @@ var KIN_MARKER_DEFS_SVG = [
|
|
|
190263
190678
|
`<marker markerUnits="userSpaceOnUse" id="arrow-open-neutral-kin" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0 0L10 5L0 10" fill="none" stroke="${KIN}" stroke-width="1.4"/></marker>`,
|
|
190264
190679
|
`<marker markerUnits="userSpaceOnUse" id="tri-accent-kin" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0 0L10 5L0 10z" fill="${KIN}"/></marker>`,
|
|
190265
190680
|
`<marker markerUnits="userSpaceOnUse" id="tri-hollow-kin" viewBox="0 0 12 12" refX="11" refY="6" markerWidth="11" markerHeight="11" orient="auto"><path d="M0 0L12 6L0 12z" fill="${BG}" stroke="${KIN}" stroke-width="1.5"/></marker>`,
|
|
190681
|
+
`<marker markerUnits="userSpaceOnUse" id="tri-hollow-start-kin" viewBox="0 0 12 12" refX="1" refY="6" markerWidth="11" markerHeight="11" orient="auto"><path d="M12 0L0 6L12 12z" fill="${BG}" stroke="${KIN}" stroke-width="1.5"/></marker>`,
|
|
190266
190682
|
`<marker markerUnits="userSpaceOnUse" id="defined-by-kin" viewBox="0 0 18 12" refX="17" refY="6" markerWidth="12" markerHeight="8" orient="auto"><circle cx="3.2" cy="3.6" r="1.6" fill="${KIN}"/><circle cx="3.2" cy="8.4" r="1.6" fill="${KIN}"/><path d="M7 1L17 6L7 11z" fill="${KIN}"/></marker>`,
|
|
190267
190683
|
`<marker markerUnits="userSpaceOnUse" id="owning-membership-kin" viewBox="0 0 14 14" refX="1" refY="7" markerWidth="12" markerHeight="12" orient="auto"><circle cx="7" cy="7" r="5.2" fill="${BG}" stroke="${KIN}" stroke-width="1.5"/><path d="M3.8 7H10.2M7 3.8V10.2" fill="none" stroke="${KIN}" stroke-width="1.5"/></marker>`,
|
|
190268
190684
|
`<marker markerUnits="userSpaceOnUse" id="diamond-filled-kin" viewBox="0 0 14 14" refX="1" refY="7" markerWidth="12" markerHeight="12" orient="auto"><path d="M0 7L7 0L14 7L7 14z" fill="${KIN}"/></marker>`,
|
|
@@ -190408,6 +190824,9 @@ body {
|
|
|
190408
190824
|
* reading. */
|
|
190409
190825
|
.dframe-rect { fill: var(--node-surface); fill-opacity: 0.92; stroke: var(--fg-3); stroke-width: 1.2; }
|
|
190410
190826
|
.dframe-rect.container { fill-opacity: 0.16; }
|
|
190827
|
+
/* REQ-366/386 \u2014 an expanded frame remains translucent around its graphical
|
|
190828
|
+
* internals, but its optional bottom feature list is an opaque readable card. */
|
|
190829
|
+
.dfeature-band-bg { fill: var(--node-surface); }
|
|
190411
190830
|
.dframe-rect.package.library { stroke-dasharray: 5 3; }
|
|
190412
190831
|
.dframe-rect.selected { stroke: var(--accent); stroke-width: 2; }
|
|
190413
190832
|
/* RULE (diagram-rules \u2014 Frame): parallel composite-state region \u2014 dashed border. */
|
|
@@ -190452,17 +190871,6 @@ body {
|
|
|
190452
190871
|
.dnode-shape.decision { stroke: var(--yellow); }
|
|
190453
190872
|
/* REQ-006 \u2014 selected-node resize grip */
|
|
190454
190873
|
.dresize-grip { fill: var(--accent); stroke: var(--bg-1); stroke-width: 1; cursor: nwse-resize; }
|
|
190455
|
-
/* REQ-366 \u2014 local IV part presentation control in the upper-right corner.
|
|
190456
|
-
Issue #18 \u2014 a bare +/\u2212 glyph, no surrounding box; the rect stays in the
|
|
190457
|
-
markup only as an invisible, comfortably-sized click target. */
|
|
190458
|
-
.div-part-toggle { cursor: pointer; }
|
|
190459
|
-
.div-part-toggle rect { fill: transparent; stroke: none; }
|
|
190460
|
-
.div-part-toggle text {
|
|
190461
|
-
fill: var(--fg-1); font-family: var(--font-ui); font-size: 16px; font-weight: 700;
|
|
190462
|
-
pointer-events: none;
|
|
190463
|
-
}
|
|
190464
|
-
.div-part-toggle:hover text { fill: var(--accent); }
|
|
190465
|
-
|
|
190466
190874
|
/* edges (REQ-186) */
|
|
190467
190875
|
.dlink { stroke: var(--fg-2); stroke-width: 1.2; fill: none; }
|
|
190468
190876
|
.dlink.flow, .dlink.connect, .dlink.message, .dlink.interface { stroke: var(--cyan); }
|
|
@@ -190483,6 +190891,9 @@ body {
|
|
|
190483
190891
|
}
|
|
190484
190892
|
.dlink.binding { stroke: var(--yellow); stroke-width: 2.6; } /* REQ-195 \u2014 "=" binding (double-weight line) */
|
|
190485
190893
|
.dlink.specialization, .dlink.owningMembership, .dlink.composition, .dlink.association { stroke: var(--fg-2); }
|
|
190894
|
+
/* REQ-160 \u2014 temporal decomposition of an occurrence into timeslices/snapshots
|
|
190895
|
+
(OMG 8.2.3.9): a solid structural line, like the specialization it is. */
|
|
190896
|
+
.dlink.portion { stroke: var(--fg-2); }
|
|
190486
190897
|
/* REQ-094/190 \u2014 custom bound-reference overlay. A dotted directed line is
|
|
190487
190898
|
deliberately distinct from solid feature membership and its owner diamond. */
|
|
190488
190899
|
.dlink.reference { stroke: var(--fg-2); stroke-dasharray: 1 3; stroke-linecap: round; }
|
|
@@ -190842,16 +191253,23 @@ body {
|
|
|
190842
191253
|
/* REQ-190 \u2014 the direction, General-View mode, and line-style segs are icon-only:
|
|
190843
191254
|
tighter padding (see issue 146). */
|
|
190844
191255
|
.seg.seg-dir button, .seg.seg-gvmode button, .seg.seg-line-style button, .seg.seg-gridpreset button,
|
|
190845
|
-
.seg.seg-
|
|
190846
|
-
/* REQ-196 \u2014
|
|
190847
|
-
|
|
190848
|
-
|
|
190849
|
-
.seg.seg-
|
|
190850
|
-
|
|
191256
|
+
.seg.seg-visibility button, .seg.seg-presentation button { padding: 2px 6px; }
|
|
191257
|
+
/* REQ-196/200/366/386 \u2014 every visibility/presentation segment shares one
|
|
191258
|
+
treatment: visible is lit; hidden is dimmed and slashed. Semantic icon hues
|
|
191259
|
+
remain visible instead of being replaced by a solid orange active button. */
|
|
191260
|
+
.seg.seg-visibility button.on, .seg.seg-presentation button.on {
|
|
191261
|
+
background: var(--bg-active); color: var(--fg-0);
|
|
191262
|
+
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-2) 30%, transparent); }
|
|
191263
|
+
.seg.seg-visibility button:not(.on), .seg.seg-presentation button:not(.on) { opacity: 0.38; }
|
|
191264
|
+
.seg.seg-visibility button:not(.on)::after, .seg.seg-presentation button:not(.on)::after {
|
|
190851
191265
|
content: ''; position: absolute; left: 4px; right: 4px; top: 50%;
|
|
190852
|
-
border-top: 1.2px solid
|
|
191266
|
+
border-top: 1.2px solid var(--red, #e07a7a); transform: rotate(-20deg);
|
|
190853
191267
|
}
|
|
190854
|
-
.seg.seg-
|
|
191268
|
+
.seg.seg-visibility button, .seg.seg-presentation button { position: relative; }
|
|
191269
|
+
.visibility-icon.tone-structure, .presentation-icon.tone-structure { color: var(--cyan); }
|
|
191270
|
+
.visibility-icon.tone-behavior, .presentation-icon.tone-behavior { color: var(--accent); }
|
|
191271
|
+
.visibility-icon.tone-definition, .presentation-icon.tone-definition,
|
|
191272
|
+
.definition-visibility-icon { color: var(--violet); }
|
|
190855
191273
|
/* issue 156 \u2014 General View quick filters: one icon chip per element category
|
|
190856
191274
|
(parts always show). A chip stays lit in its element-type colour while its
|
|
190857
191275
|
category is VISIBLE; hiding one dims and slashes it so an engaged filter is
|
|
@@ -191089,6 +191507,12 @@ svg.react-flow__connectionline { z-index: 1; }
|
|
|
191089
191507
|
.rf-frame .rf-node-svg { pointer-events: none; }
|
|
191090
191508
|
.rf-frame .dframe-rect { pointer-events: none; }
|
|
191091
191509
|
.rf-frame-header { position: absolute; pointer-events: auto; cursor: move; }
|
|
191510
|
+
/* issue #58 / user report 2026-08-11 \u2014 the matching title strip on an
|
|
191511
|
+
* Interconnection View PART node. It is what the node's dragHandle selects, so
|
|
191512
|
+
* a part reads and moves identically whether it draws its internals (a frame) or
|
|
191513
|
+
* has them hidden (a node) \u2014 and shows the same move cursor either way, instead
|
|
191514
|
+
* of React Flow's grab hand over a body that cannot actually be dragged. */
|
|
191515
|
+
.rf-node-header { position: absolute; pointer-events: auto; cursor: move; }
|
|
191092
191516
|
/* REQ-379 \u2014 the frame's BORDER band is hover-sensitive (the interior stays
|
|
191093
191517
|
* click-through): hovering it reveals and mounts the frame's side connect points,
|
|
191094
191518
|
* which are drawn on that same border. Stroke-only hit testing, so nothing but the
|
|
@@ -191096,7 +191520,7 @@ svg.react-flow__connectionline { z-index: 1; }
|
|
|
191096
191520
|
.dframe-hover-band { stroke-width: 12; pointer-events: stroke; }
|
|
191097
191521
|
.rf-frame .dport-hit { pointer-events: auto; }
|
|
191098
191522
|
.rf-frame .react-flow__handle { pointer-events: auto; }
|
|
191099
|
-
.rf-frame .
|
|
191523
|
+
.rf-frame .dcontainer-controls { pointer-events: auto; }
|
|
191100
191524
|
.rf-frame .react-flow__resize-control { pointer-events: auto; }
|
|
191101
191525
|
.rf-node-svg { display: block; overflow: visible; }
|
|
191102
191526
|
.react-flow__node.selected { box-shadow: none; }
|
|
@@ -191293,12 +191717,29 @@ svg.react-flow__connectionline { z-index: 1; }
|
|
|
191293
191717
|
color: var(--fg-0); background: var(--bg-1); border: 1px solid var(--line-soft); border-radius: 3px; padding: 0 4px; white-space: nowrap; }
|
|
191294
191718
|
.rf-edge-label.mult { background: transparent; border: 0; color: var(--fg-2); padding: 0; }
|
|
191295
191719
|
|
|
191296
|
-
/* REQ-366
|
|
191297
|
-
*
|
|
191298
|
-
|
|
191299
|
-
|
|
191720
|
+
/* REQ-366/386 \u2014 two adjacent, independent container presentation controls.
|
|
191721
|
+
* +/\u2212 owns graphical internals; the outlined list owns textual feature
|
|
191722
|
+
* compartments. Their compact hit targets stay interactive over frame chrome.
|
|
191723
|
+
* Both marks are STROKED SVG sized to the whole button (nodes.tsx
|
|
191724
|
+
* ContainerControlGlyph), so nothing here can shift them off centre \u2014 a typed
|
|
191725
|
+
* +/\u2212 character and a bordered box drawn in CSS both did (user report
|
|
191726
|
+
* 2026-08-11). */
|
|
191727
|
+
/* The inset is set inline per shape (nodes.tsx ContainerControls): a rounded
|
|
191728
|
+
* outline needs the pair pulled in from its corner arc, a sharp one does not.
|
|
191729
|
+
* These values are the sharp-corner default. */
|
|
191730
|
+
.dcontainer-controls { position: absolute; right: ${CONTAINER_CONTROLS_RIGHT}px; top: ${CONTAINER_CONTROLS_RIGHT}px; z-index: 8;
|
|
191731
|
+
display: inline-flex; align-items: center; gap: ${CONTAINER_CONTROL_GAP}px; pointer-events: auto; }
|
|
191732
|
+
/* The BUTTON is only a hit target: no plate, no fill, in any state (user
|
|
191733
|
+
* direction 2026-08-11 \u2014 "remove that translucent thing surrounding the box I
|
|
191734
|
+
* just want the hamburger menu"). Neither does STATE live here: the mark itself
|
|
191735
|
+
* carries it \u2014 an empty box or a filled one, a + or a \u2212, at one resting colour
|
|
191736
|
+
* ("at best don't even change color"). Only the pointer feedback is a colour. */
|
|
191737
|
+
.div-part-toggle, .dfeature-toggle { width: ${CONTAINER_CONTROL_SIZE}px; height: ${CONTAINER_CONTROL_SIZE}px;
|
|
191738
|
+
padding: 0; margin: 0; border: 0; background: none; cursor: pointer; color: var(--fg-1);
|
|
191300
191739
|
display: inline-flex; align-items: center; justify-content: center; }
|
|
191301
|
-
.div-part-toggle
|
|
191740
|
+
.div-part-toggle svg, .dfeature-toggle svg { display: block; }
|
|
191741
|
+
.div-part-toggle:hover, .div-part-toggle:active, .div-part-toggle:focus-visible,
|
|
191742
|
+
.dfeature-toggle:hover, .dfeature-toggle:active, .dfeature-toggle:focus-visible { color: var(--accent); outline: none; }
|
|
191302
191743
|
|
|
191303
191744
|
/* React Flow chrome theming (controls / minimap / attribution) */
|
|
191304
191745
|
.react-flow__controls { box-shadow: 0 2px 10px rgba(0,0,0,0.35); }
|
|
@@ -191395,7 +191836,7 @@ function buildDiagramSvg(options) {
|
|
|
191395
191836
|
const { w, h } = sizeOf(node);
|
|
191396
191837
|
extend2(p.x, p.y, w, h);
|
|
191397
191838
|
for (const ph of node.data.ports ?? []) {
|
|
191398
|
-
const rect = portGlyphRect(ph, w, h);
|
|
191839
|
+
const rect = portGlyphRect(ph, w, h, featureBandTopReserve(node.data));
|
|
191399
191840
|
extend2(p.x + rect.x, p.y + rect.y, rect.width, rect.height);
|
|
191400
191841
|
if (!node.data.showPortLabels || rect.elongated) continue;
|
|
191401
191842
|
const text = `${ph.port.conjugated ? "~" : ""}${ph.port.name}`;
|
|
@@ -191538,7 +191979,7 @@ function tableToCsv(table2, order) {
|
|
|
191538
191979
|
// ../extension/src/diagram-sidecar.ts
|
|
191539
191980
|
var import_diagram_protocol2 = __toESM(require_out());
|
|
191540
191981
|
var FILE_OVERVIEW_ANCHOR = "~file";
|
|
191541
|
-
var SIDECAR_VERSION =
|
|
191982
|
+
var SIDECAR_VERSION = 4;
|
|
191542
191983
|
function emptySideCar() {
|
|
191543
191984
|
return { version: SIDECAR_VERSION, anchors: {} };
|
|
191544
191985
|
}
|
|
@@ -191593,6 +192034,20 @@ function dropOrdinalKeys(map3) {
|
|
|
191593
192034
|
}
|
|
191594
192035
|
return Object.keys(kept).length > 0 ? kept : void 0;
|
|
191595
192036
|
}
|
|
192037
|
+
function enabledEntries(value) {
|
|
192038
|
+
if (!value || typeof value !== "object") return {};
|
|
192039
|
+
return Object.fromEntries(Object.entries(value).filter(([, enabled]) => enabled === true));
|
|
192040
|
+
}
|
|
192041
|
+
function normalizeContainerPresentation(state, kind) {
|
|
192042
|
+
const legacy = state;
|
|
192043
|
+
const coupled = kind === "iv" ? enabledEntries(legacy.ivCompartments) : kind === "afv" ? enabledEntries(legacy.collapsedActions) : {};
|
|
192044
|
+
if (Object.keys(coupled).length > 0) {
|
|
192045
|
+
state.hiddenInternals = { ...coupled, ...state.hiddenInternals ?? {} };
|
|
192046
|
+
state.visibleFeatureCompartments = { ...coupled, ...state.visibleFeatureCompartments ?? {} };
|
|
192047
|
+
}
|
|
192048
|
+
delete legacy.ivCompartments;
|
|
192049
|
+
delete legacy.collapsedActions;
|
|
192050
|
+
}
|
|
191596
192051
|
function normalizeSideCar(value) {
|
|
191597
192052
|
if (!value || typeof value !== "object") return emptySideCar();
|
|
191598
192053
|
const v = value;
|
|
@@ -191601,16 +192056,36 @@ function normalizeSideCar(value) {
|
|
|
191601
192056
|
if (version >= SIDECAR_VERSION) {
|
|
191602
192057
|
for (const byKind of Object.values(anchors)) {
|
|
191603
192058
|
if (!byKind || typeof byKind !== "object") continue;
|
|
191604
|
-
for (const state of Object.
|
|
192059
|
+
for (const [kind, state] of Object.entries(byKind)) {
|
|
191605
192060
|
if (!state || typeof state !== "object") continue;
|
|
191606
192061
|
const dir = sanitizeDirection(state.direction);
|
|
191607
192062
|
if (dir === void 0) delete state.direction;
|
|
191608
192063
|
else state.direction = dir;
|
|
191609
192064
|
normalizeGridFields(state);
|
|
192065
|
+
normalizeContainerPresentation(state, kind);
|
|
191610
192066
|
}
|
|
191611
192067
|
}
|
|
191612
192068
|
return { version, anchors };
|
|
191613
192069
|
}
|
|
192070
|
+
if (version === 3) {
|
|
192071
|
+
const migrated2 = {};
|
|
192072
|
+
for (const [anchor, byKind] of Object.entries(anchors)) {
|
|
192073
|
+
if (!byKind || typeof byKind !== "object") continue;
|
|
192074
|
+
const nextByKind = {};
|
|
192075
|
+
for (const [kind, raw] of Object.entries(byKind)) {
|
|
192076
|
+
if (!raw || typeof raw !== "object") continue;
|
|
192077
|
+
const state = { ...raw };
|
|
192078
|
+
normalizeGridFields(state);
|
|
192079
|
+
const dir = sanitizeDirection(state.direction);
|
|
192080
|
+
if (dir === void 0) delete state.direction;
|
|
192081
|
+
else state.direction = dir;
|
|
192082
|
+
normalizeContainerPresentation(state, kind);
|
|
192083
|
+
nextByKind[kind] = state;
|
|
192084
|
+
}
|
|
192085
|
+
migrated2[anchor] = nextByKind;
|
|
192086
|
+
}
|
|
192087
|
+
return { version: SIDECAR_VERSION, anchors: migrated2 };
|
|
192088
|
+
}
|
|
191614
192089
|
if (version === 2) {
|
|
191615
192090
|
const migrated2 = {};
|
|
191616
192091
|
for (const [anchor, byKind] of Object.entries(anchors)) {
|
|
@@ -191629,6 +192104,7 @@ function normalizeSideCar(value) {
|
|
|
191629
192104
|
const ports = dropOrdinalKeys(state.ports);
|
|
191630
192105
|
if (ports) state.ports = ports;
|
|
191631
192106
|
else delete state.ports;
|
|
192107
|
+
normalizeContainerPresentation(state, kind);
|
|
191632
192108
|
nextByKind[kind] = state;
|
|
191633
192109
|
}
|
|
191634
192110
|
migrated2[anchor] = nextByKind;
|
|
@@ -191643,14 +192119,17 @@ function normalizeSideCar(value) {
|
|
|
191643
192119
|
if (!raw || typeof raw !== "object") continue;
|
|
191644
192120
|
const state = raw;
|
|
191645
192121
|
normalizeGridFields(state);
|
|
192122
|
+
normalizeContainerPresentation(state, kind);
|
|
191646
192123
|
const next = {};
|
|
191647
192124
|
if (state.mode !== void 0) next.mode = state.mode;
|
|
191648
192125
|
if (state.zoom !== void 0) next.zoom = state.zoom;
|
|
191649
192126
|
const dir = sanitizeDirection(state.direction);
|
|
191650
192127
|
if (dir !== void 0) next.direction = dir;
|
|
191651
|
-
if (state.
|
|
192128
|
+
if (state.hiddenInternals !== void 0) next.hiddenInternals = state.hiddenInternals;
|
|
192129
|
+
if (state.visibleFeatureCompartments !== void 0) {
|
|
192130
|
+
next.visibleFeatureCompartments = state.visibleFeatureCompartments;
|
|
192131
|
+
}
|
|
191652
192132
|
if (state.nestedPorts !== void 0) next.nestedPorts = state.nestedPorts;
|
|
191653
|
-
if (state.collapsedActions !== void 0) next.collapsedActions = state.collapsedActions;
|
|
191654
192133
|
if (state.gvMode !== void 0) next.gvMode = state.gvMode;
|
|
191655
192134
|
if (state.gvFilters !== void 0) next.gvFilters = state.gvFilters;
|
|
191656
192135
|
if (state.lineStyle !== void 0) next.lineStyle = state.lineStyle;
|
|
@@ -191726,6 +192205,7 @@ function edgeKindLabel(kind) {
|
|
|
191726
192205
|
if (kind === "composition") return "feature membership";
|
|
191727
192206
|
if (kind === "owningMembership") return "owning membership";
|
|
191728
192207
|
if (kind === "definedBy") return "defined by";
|
|
192208
|
+
if (kind === "portion") return "temporal decomposition (portion)";
|
|
191729
192209
|
return kind;
|
|
191730
192210
|
}
|
|
191731
192211
|
|
|
@@ -192374,7 +192854,8 @@ function nodeSidePointOffsets(data, side, connectable) {
|
|
|
192374
192854
|
data.h,
|
|
192375
192855
|
data.connectPointSpacing ?? CONNECT_POINT_SPACING_DEFAULT,
|
|
192376
192856
|
connectable,
|
|
192377
|
-
data.node?.shape
|
|
192857
|
+
data.node?.shape,
|
|
192858
|
+
data.featureCompartmentHeight ?? 0
|
|
192378
192859
|
);
|
|
192379
192860
|
const explicit = data.explicitSideAnchors?.[side] ?? [];
|
|
192380
192861
|
return [.../* @__PURE__ */ new Set([...derived, ...explicit])].sort((a2, b) => a2 - b);
|
|
@@ -192405,7 +192886,7 @@ var SIDE_NORMAL = {
|
|
|
192405
192886
|
left: { x: -1, y: 0 }
|
|
192406
192887
|
};
|
|
192407
192888
|
var clampOffset = (v) => Math.max(0.06, Math.min(0.94, v));
|
|
192408
|
-
function usePortDrag(containerRef, w, h, onPortMove, onPortPreview, onSelect) {
|
|
192889
|
+
function usePortDrag(containerRef, w, h, topReserve, onPortMove, onPortPreview, onSelect) {
|
|
192409
192890
|
const [dragId, setDragId] = (0, import_react8.useState)(void 0);
|
|
192410
192891
|
const onPortPointerDown = (portId, e, draggable = true) => {
|
|
192411
192892
|
if (e.button !== 0) return;
|
|
@@ -192422,12 +192903,8 @@ function usePortDrag(containerRef, w, h, onPortMove, onPortPreview, onSelect) {
|
|
|
192422
192903
|
const placement = (cx, cy) => {
|
|
192423
192904
|
const lx = rect.width ? (cx - rect.left) / rect.width * w : 0;
|
|
192424
192905
|
const ly = rect.height ? (cy - rect.top) / rect.height * h : 0;
|
|
192425
|
-
const
|
|
192426
|
-
|
|
192427
|
-
if (m === dt) return { side: "top", offset: clampOffset(lx / w) };
|
|
192428
|
-
if (m === db) return { side: "bottom", offset: clampOffset(lx / w) };
|
|
192429
|
-
if (m === dl) return { side: "left", offset: clampOffset(ly / h) };
|
|
192430
|
-
return { side: "right", offset: clampOffset(ly / h) };
|
|
192906
|
+
const nearest = nearestPortOwnerPlacement(lx, ly, w, h, topReserve);
|
|
192907
|
+
return { side: nearest.side, offset: clampOffset(nearest.offset) };
|
|
192431
192908
|
};
|
|
192432
192909
|
const move = (ev) => {
|
|
192433
192910
|
if (!moved && Math.hypot(ev.clientX - sx, ev.clientY - sy) < 4) return;
|
|
@@ -192450,18 +192927,6 @@ function usePortDrag(containerRef, w, h, onPortMove, onPortPreview, onSelect) {
|
|
|
192450
192927
|
};
|
|
192451
192928
|
return { dragId, onPortPointerDown };
|
|
192452
192929
|
}
|
|
192453
|
-
function sideXY(side, offset2, w, h) {
|
|
192454
|
-
switch (side) {
|
|
192455
|
-
case "top":
|
|
192456
|
-
return { x: w * offset2, y: 0 };
|
|
192457
|
-
case "bottom":
|
|
192458
|
-
return { x: w * offset2, y: h };
|
|
192459
|
-
case "left":
|
|
192460
|
-
return { x: 0, y: h * offset2 };
|
|
192461
|
-
case "right":
|
|
192462
|
-
return { x: w, y: h * offset2 };
|
|
192463
|
-
}
|
|
192464
|
-
}
|
|
192465
192930
|
function DualHandle({ id: id2, side, x, y, kind, active, connectable = true, startable = false, size }) {
|
|
192466
192931
|
const style2 = size !== void 0 ? { left: x, top: y, width: size, height: size, transform: "translate(-50%,-50%)" } : { left: x, top: y, transform: "translate(-50%,-50%)" };
|
|
192467
192932
|
const cls = `rf-handle rf-handle-${kind}${active ? " active" : ""}`;
|
|
@@ -192512,16 +192977,22 @@ function fitKind(s, availPx) {
|
|
|
192512
192977
|
function FullTitle({ full, shown }) {
|
|
192513
192978
|
return shown === full ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: full });
|
|
192514
192979
|
}
|
|
192515
|
-
function compartmentTops(node, top =
|
|
192980
|
+
function compartmentTops(node, top = NODE_COMPARTMENT_TOP) {
|
|
192516
192981
|
const comps = node.compartments ?? [];
|
|
192517
192982
|
const tops = [];
|
|
192518
192983
|
let acc = top;
|
|
192519
192984
|
for (const c of comps) {
|
|
192520
192985
|
tops.push(acc);
|
|
192521
|
-
acc +=
|
|
192986
|
+
acc += compartmentBlockHeight(c.items.length);
|
|
192522
192987
|
}
|
|
192523
192988
|
return { tops, comps };
|
|
192524
192989
|
}
|
|
192990
|
+
function containerBandBottom(node, top) {
|
|
192991
|
+
return top + (node.compartments ?? []).reduce((h, c) => h + compartmentBlockHeight(c.items.length), 0);
|
|
192992
|
+
}
|
|
192993
|
+
function ContainerBandRule({ w, y }) {
|
|
192994
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { className: "dcompartment-rule closing", x1: 0, y1: y, x2: w, y2: y });
|
|
192995
|
+
}
|
|
192525
192996
|
function Compartments({ node, w, top }) {
|
|
192526
192997
|
const { tops, comps } = compartmentTops(node, top);
|
|
192527
192998
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: comps.map((c, ci) => {
|
|
@@ -192529,13 +193000,13 @@ function Compartments({ node, w, top }) {
|
|
|
192529
193000
|
const title = fitKind(c.title, w - 16);
|
|
192530
193001
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { className: "dnode-compartment", children: [
|
|
192531
193002
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { className: "dcompartment-rule", x1: 0, y1: cy, x2: w, y2: cy }),
|
|
192532
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: 8, y: cy +
|
|
193003
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: 8, y: cy + COMPARTMENT_TITLE_BASELINE, children: [
|
|
192533
193004
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: c.title, shown: title }),
|
|
192534
193005
|
title
|
|
192535
193006
|
] }),
|
|
192536
193007
|
c.items.map((it, i) => {
|
|
192537
193008
|
const shown = fitText(it.text, w - 20, 10);
|
|
192538
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-label", x: 12, y: cy +
|
|
193009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-label", x: 12, y: cy + COMPARTMENT_ROW_BASELINE + i * COMPARTMENT_ROW_HEIGHT, style: { fontSize: 10 }, children: [
|
|
192539
193010
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: it.text, shown }),
|
|
192540
193011
|
shown
|
|
192541
193012
|
] }, i);
|
|
@@ -192548,37 +193019,53 @@ function variabilityMark(keyword) {
|
|
|
192548
193019
|
if (/^variant\b/.test(keyword)) return " \u25C6";
|
|
192549
193020
|
return "";
|
|
192550
193021
|
}
|
|
193022
|
+
function nodeShowsControls(node) {
|
|
193023
|
+
return node.meta?.containerControls === true;
|
|
193024
|
+
}
|
|
193025
|
+
function titleNameLine(name, type, mult, alias, availPx) {
|
|
193026
|
+
const suffixChars = (mult ? mult.length + 1 : 0) + (alias ? alias.length + 9 : 0);
|
|
193027
|
+
const budget = Math.max(6, fitChars(availPx, 11) - suffixChars);
|
|
193028
|
+
let nameShown = name;
|
|
193029
|
+
let typeShown = type;
|
|
193030
|
+
if (type) {
|
|
193031
|
+
if (name.length + 3 + type.length > budget) {
|
|
193032
|
+
const nameMax = Math.max(4, Math.min(name.length, Math.ceil(budget * 0.6)));
|
|
193033
|
+
nameShown = clipText(name, nameMax);
|
|
193034
|
+
typeShown = clipText(type, Math.max(3, budget - nameShown.length - 3));
|
|
193035
|
+
}
|
|
193036
|
+
} else {
|
|
193037
|
+
nameShown = clipText(name, budget);
|
|
193038
|
+
}
|
|
193039
|
+
return {
|
|
193040
|
+
nameShown,
|
|
193041
|
+
typeShown,
|
|
193042
|
+
full: `${name}${type ? ` : ${type}` : ""}`,
|
|
193043
|
+
shown: `${nameShown}${typeShown ? ` : ${typeShown}` : ""}`
|
|
193044
|
+
};
|
|
193045
|
+
}
|
|
192551
193046
|
function BoxBody({ node, w, h, showMult }) {
|
|
192552
|
-
const rx = node.isDef
|
|
193047
|
+
const rx = nodeCornerRadius(node.shape, node.isDef, h, false);
|
|
192553
193048
|
const cls = node.keyword.startsWith("requirement") ? "req" : "";
|
|
192554
|
-
const
|
|
193049
|
+
const titleArea = containerTitleArea(w, nodeShowsControls(node));
|
|
193050
|
+
const cx = titleArea.centerX;
|
|
192555
193051
|
const kindFull = `\xAB${node.keyword}\xBB${variabilityMark(node.keyword)}`;
|
|
192556
|
-
const kindShown = fitKind(kindFull,
|
|
192557
|
-
const avail = Math.max(24, w - 12);
|
|
193052
|
+
const kindShown = fitKind(kindFull, Math.max(24, titleArea.width - 8));
|
|
192558
193053
|
const mult = showMult && node.multiplicity ? node.multiplicity : void 0;
|
|
192559
193054
|
const alias = node.meta?.alias ? String(node.meta.alias) : void 0;
|
|
192560
|
-
const
|
|
192561
|
-
|
|
192562
|
-
|
|
192563
|
-
|
|
192564
|
-
|
|
192565
|
-
|
|
192566
|
-
|
|
192567
|
-
nameShown = clipText(node.name, nameMax);
|
|
192568
|
-
typeShown = clipText(node.type, Math.max(3, budget - nameShown.length - 3));
|
|
192569
|
-
}
|
|
192570
|
-
} else {
|
|
192571
|
-
nameShown = clipText(node.name, budget);
|
|
192572
|
-
}
|
|
192573
|
-
const fullTitle = `${node.name}${node.type ? ` : ${node.type}` : ""}`;
|
|
192574
|
-
const shownTitle = `${nameShown}${typeShown ? ` : ${typeShown}` : ""}`;
|
|
193055
|
+
const { nameShown, typeShown, full: fullTitle, shown: shownTitle } = titleNameLine(
|
|
193056
|
+
node.name,
|
|
193057
|
+
node.type,
|
|
193058
|
+
mult,
|
|
193059
|
+
alias,
|
|
193060
|
+
Math.max(24, titleArea.width - 12)
|
|
193061
|
+
);
|
|
192575
193062
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
|
|
192576
193063
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { className: `dnode-rect ${cls}`, x: 0, y: 0, width: w, height: h, rx }),
|
|
192577
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: cx, y:
|
|
193064
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: cx, y: CONTAINER_TITLE_KIND_BASELINE, textAnchor: "middle", children: [
|
|
192578
193065
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: kindFull, shown: kindShown }),
|
|
192579
193066
|
kindShown
|
|
192580
193067
|
] }),
|
|
192581
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: `dnode-label ${node.abstract ? "abstract" : ""}`, x: cx, y:
|
|
193068
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: `dnode-label ${node.abstract ? "abstract" : ""}`, x: cx, y: CONTAINER_TITLE_NAME_BASELINE, textAnchor: "middle", children: [
|
|
192582
193069
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: fullTitle, shown: shownTitle }),
|
|
192583
193070
|
nameShown,
|
|
192584
193071
|
typeShown ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
@@ -192594,41 +193081,57 @@ function BoxBody({ node, w, h, showMult }) {
|
|
|
192594
193081
|
alias
|
|
192595
193082
|
] }) : ""
|
|
192596
193083
|
] }),
|
|
192597
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Compartments, { node, w })
|
|
193084
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Compartments, { node, w }),
|
|
193085
|
+
nodeShowsControls(node) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ContainerBandRule, { w, y: containerBandBottom(node, NODE_COMPARTMENT_TOP) }) : null
|
|
192598
193086
|
] });
|
|
192599
193087
|
}
|
|
192600
|
-
function RoundedBody({ node, w, h, cls }) {
|
|
192601
|
-
const r = node.isDef ? 0 : Math.min(h / 2, 20);
|
|
193088
|
+
function RoundedBody({ node, w, h, cls, showMult }) {
|
|
192602
193089
|
const comps = node.compartments ?? [];
|
|
193090
|
+
const r = nodeCornerRadius(node.shape, node.isDef, h, comps.length > 0);
|
|
192603
193091
|
const composite = node.meta?.composite === true ? " composite" : "";
|
|
192604
193092
|
const kindFull = `\xAB${node.keyword}\xBB${node.meta?.parallel ? " \u2225" : ""}${variabilityMark(node.keyword)}`;
|
|
192605
|
-
const
|
|
192606
|
-
const
|
|
193093
|
+
const titleArea = containerTitleArea(w, nodeShowsControls(node));
|
|
193094
|
+
const cx = titleArea.centerX;
|
|
193095
|
+
const kindShown = fitKind(kindFull, Math.max(24, titleArea.width - 8));
|
|
193096
|
+
const mult = showMult && node.multiplicity ? node.multiplicity : void 0;
|
|
193097
|
+
const { nameShown, typeShown, full: fullTitle, shown: shownTitle } = titleNameLine(
|
|
193098
|
+
node.name,
|
|
193099
|
+
node.type,
|
|
193100
|
+
mult,
|
|
193101
|
+
void 0,
|
|
193102
|
+
Math.max(24, titleArea.width - 12)
|
|
193103
|
+
);
|
|
193104
|
+
const nameLine = (y) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-label", x: cx, y, textAnchor: "middle", children: [
|
|
193105
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: fullTitle, shown: shownTitle }),
|
|
193106
|
+
nameShown,
|
|
193107
|
+
typeShown ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
193108
|
+
" : ",
|
|
193109
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tspan", { className: "dnode-type", children: typeShown })
|
|
193110
|
+
] }) : "",
|
|
193111
|
+
mult ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tspan", { className: "dnode-kind", children: [
|
|
193112
|
+
" ",
|
|
193113
|
+
mult
|
|
193114
|
+
] }) : ""
|
|
193115
|
+
] });
|
|
192607
193116
|
if (comps.length > 0) {
|
|
192608
|
-
const cx = w / 2;
|
|
192609
193117
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
|
|
192610
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { className: `dnode-rect ${cls}${composite}`, x: 0, y: 0, width: w, height: h, rx:
|
|
192611
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: cx, y:
|
|
193118
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { className: `dnode-rect ${cls}${composite}`, x: 0, y: 0, width: w, height: h, rx: r }),
|
|
193119
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: cx, y: CONTAINER_TITLE_KIND_BASELINE, textAnchor: "middle", children: [
|
|
192612
193120
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: kindFull, shown: kindShown }),
|
|
192613
193121
|
kindShown
|
|
192614
193122
|
] }),
|
|
192615
|
-
|
|
192616
|
-
|
|
192617
|
-
|
|
192618
|
-
] }),
|
|
192619
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Compartments, { node, w })
|
|
193123
|
+
nameLine(CONTAINER_TITLE_NAME_BASELINE),
|
|
193124
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Compartments, { node, w }),
|
|
193125
|
+
nodeShowsControls(node) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ContainerBandRule, { w, y: containerBandBottom(node, NODE_COMPARTMENT_TOP) }) : null
|
|
192620
193126
|
] });
|
|
192621
193127
|
}
|
|
192622
193128
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
|
|
192623
193129
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { className: `dnode-rect ${cls}${composite}`, x: 0, y: 0, width: w, height: h, rx: r }),
|
|
192624
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-
|
|
192625
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: node.name, shown: nameShown }),
|
|
192626
|
-
nameShown
|
|
192627
|
-
] }),
|
|
192628
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: w / 2, y: h / 2 + 12, textAnchor: "middle", children: [
|
|
193130
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: cx, y: h / 2 - 4, textAnchor: "middle", children: [
|
|
192629
193131
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: kindFull, shown: kindShown }),
|
|
192630
193132
|
kindShown
|
|
192631
|
-
] })
|
|
193133
|
+
] }),
|
|
193134
|
+
nameLine(h / 2 + 11)
|
|
192632
193135
|
] });
|
|
192633
193136
|
}
|
|
192634
193137
|
function UseCaseBody({ node, w, h }) {
|
|
@@ -192809,8 +193312,8 @@ function LifelineBody({ node, w, lineBottom, activation, eventMarks }) {
|
|
|
192809
193312
|
] })
|
|
192810
193313
|
] });
|
|
192811
193314
|
}
|
|
192812
|
-
function PortGlyph({ ph, w, h, showLabels, selected: selected2, hovered, moving, connectTarget, connectStart, onSelect, onContext }) {
|
|
192813
|
-
const rect = portGlyphRect(ph, w, h);
|
|
193315
|
+
function PortGlyph({ ph, w, h, topReserve = 0, showLabels, selected: selected2, hovered, moving, connectTarget, connectStart, onSelect, onContext }) {
|
|
193316
|
+
const rect = portGlyphRect(ph, w, h, topReserve);
|
|
192814
193317
|
const x = rect.cx;
|
|
192815
193318
|
const y = rect.cy;
|
|
192816
193319
|
const half = rect.across / 2;
|
|
@@ -192930,12 +193433,12 @@ function PortGlyph({ ph, w, h, showLabels, selected: selected2, hovered, moving,
|
|
|
192930
193433
|
}
|
|
192931
193434
|
);
|
|
192932
193435
|
}
|
|
192933
|
-
function NestedPortToggles({ ports, w, h, onToggle }) {
|
|
193436
|
+
function NestedPortToggles({ ports, w, h, topReserve = 0, onToggle }) {
|
|
192934
193437
|
const hosts = ports.filter((ph) => ph.port.meta?.nestedHost === true);
|
|
192935
193438
|
if (!hosts.length) return null;
|
|
192936
193439
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: hosts.map((ph) => {
|
|
192937
193440
|
const expanded2 = ph.port.meta?.nestedExpanded === true;
|
|
192938
|
-
const at = nestedPortTogglePoint(portGlyphRect(ph, w, h), ph.side);
|
|
193441
|
+
const at = nestedPortTogglePoint(portGlyphRect(ph, w, h, topReserve), ph.side);
|
|
192939
193442
|
const what = ph.port.pin ? "parameters" : "ports";
|
|
192940
193443
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
192941
193444
|
"button",
|
|
@@ -192966,6 +193469,84 @@ function NestedPortToggles({ ports, w, h, onToggle }) {
|
|
|
192966
193469
|
);
|
|
192967
193470
|
}) });
|
|
192968
193471
|
}
|
|
193472
|
+
function ContainerControlGlyph({ kind, expanded: expanded2 }) {
|
|
193473
|
+
const c = CONTAINER_GLYPH_VIEWBOX / 2;
|
|
193474
|
+
const half = CONTAINER_GLYPH_EXTENT / 2;
|
|
193475
|
+
const box = CONTAINER_GLYPH_EXTENT;
|
|
193476
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193477
|
+
"svg",
|
|
193478
|
+
{
|
|
193479
|
+
className: kind === "internals" ? "internals-glyph" : "feature-list-glyph",
|
|
193480
|
+
viewBox: `0 0 ${CONTAINER_GLYPH_VIEWBOX} ${CONTAINER_GLYPH_VIEWBOX}`,
|
|
193481
|
+
width: CONTAINER_GLYPH_VIEWBOX,
|
|
193482
|
+
height: CONTAINER_GLYPH_VIEWBOX,
|
|
193483
|
+
"aria-hidden": "true",
|
|
193484
|
+
children: kind === "internals" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", children: [
|
|
193485
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: c - half, y1: c, x2: c + half, y2: c }),
|
|
193486
|
+
expanded2 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: c, y1: c - half, x2: c, y2: c + half })
|
|
193487
|
+
] }) : (
|
|
193488
|
+
// A compartment box carrying its rows while the list is HIDDEN and
|
|
193489
|
+
// empty once it is shown (user direction 2026-08-11, correcting the
|
|
193490
|
+
// first reading: "in collapsed state show hamburger menu"). Like
|
|
193491
|
+
// the `+` beside it, the mark advertises what pressing it reveals,
|
|
193492
|
+
// so no colour has to carry the state. The rows are spaced evenly
|
|
193493
|
+
// about the centre line, so the glyph reads as centred either way.
|
|
193494
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { stroke: "currentColor", fill: "none", children: [
|
|
193495
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: c - half, y: c - half, width: box, height: box, rx: 1.5, strokeWidth: "1.4" }),
|
|
193496
|
+
expanded2 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { strokeWidth: "1.2", strokeLinecap: "round", children: [
|
|
193497
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: c - half + 2.5, y1: c - 1.6, x2: c + half - 2.5, y2: c - 1.6 }),
|
|
193498
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: c - half + 2.5, y1: c + 1.6, x2: c + half - 2.5, y2: c + 1.6 })
|
|
193499
|
+
] })
|
|
193500
|
+
] })
|
|
193501
|
+
)
|
|
193502
|
+
}
|
|
193503
|
+
);
|
|
193504
|
+
}
|
|
193505
|
+
function ContainerControls({
|
|
193506
|
+
id: id2,
|
|
193507
|
+
label,
|
|
193508
|
+
internalNoun,
|
|
193509
|
+
internalsVisible,
|
|
193510
|
+
featureCompartmentsVisible,
|
|
193511
|
+
cornerRadius,
|
|
193512
|
+
onToggleInternals,
|
|
193513
|
+
onToggleFeatureCompartments
|
|
193514
|
+
}) {
|
|
193515
|
+
if (!onToggleInternals && !onToggleFeatureCompartments) return null;
|
|
193516
|
+
const inset = containerControlsInset(cornerRadius);
|
|
193517
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dcontainer-controls nodrag", style: { right: inset, top: inset }, children: [
|
|
193518
|
+
onToggleFeatureCompartments ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193519
|
+
"button",
|
|
193520
|
+
{
|
|
193521
|
+
className: "dfeature-toggle nodrag",
|
|
193522
|
+
title: `${featureCompartmentsVisible ? "Hide" : "Show"} feature compartments`,
|
|
193523
|
+
"aria-label": `${featureCompartmentsVisible ? "Hide" : "Show"} feature compartments of ${label}`,
|
|
193524
|
+
"aria-pressed": featureCompartmentsVisible,
|
|
193525
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
193526
|
+
onClick: (e) => {
|
|
193527
|
+
e.stopPropagation();
|
|
193528
|
+
onToggleFeatureCompartments(id2);
|
|
193529
|
+
},
|
|
193530
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ContainerControlGlyph, { kind: "featureList", expanded: featureCompartmentsVisible })
|
|
193531
|
+
}
|
|
193532
|
+
) : null,
|
|
193533
|
+
onToggleInternals ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193534
|
+
"button",
|
|
193535
|
+
{
|
|
193536
|
+
className: "div-part-toggle nodrag",
|
|
193537
|
+
title: `${internalsVisible ? "Hide" : "Show"} ${internalNoun}`,
|
|
193538
|
+
"aria-label": `${internalsVisible ? "Hide" : "Show"} ${internalNoun} of ${label}`,
|
|
193539
|
+
"aria-pressed": internalsVisible,
|
|
193540
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
193541
|
+
onClick: (e) => {
|
|
193542
|
+
e.stopPropagation();
|
|
193543
|
+
onToggleInternals(id2);
|
|
193544
|
+
},
|
|
193545
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ContainerControlGlyph, { kind: "internals", expanded: internalsVisible })
|
|
193546
|
+
}
|
|
193547
|
+
) : null
|
|
193548
|
+
] });
|
|
193549
|
+
}
|
|
192969
193550
|
function InlineEditor({ initial, mode, elementKind, onCommit, onCancel, w }) {
|
|
192970
193551
|
const ref = (0, import_react8.useRef)(null);
|
|
192971
193552
|
(0, import_react8.useEffect)(() => {
|
|
@@ -193011,13 +193592,18 @@ var BAND_HEADER_PX = 26;
|
|
|
193011
193592
|
var BAND_MIN_W2 = 200;
|
|
193012
193593
|
var BAND_MIN_H2 = 80;
|
|
193013
193594
|
var SMALL_GLYPH_SHAPES = /* @__PURE__ */ new Set(["initial", "final", "terminate", "dot", "fork", "join", "decision", "merge"]);
|
|
193595
|
+
var INTERNAL_NOUN = {
|
|
193596
|
+
iv: "internal parts",
|
|
193597
|
+
afv: "nested actions",
|
|
193598
|
+
stv: "sub-states"
|
|
193599
|
+
};
|
|
193014
193600
|
function shapeBody(node, data) {
|
|
193015
193601
|
const { w, h, showMult } = data;
|
|
193016
193602
|
switch (node.shape) {
|
|
193017
193603
|
case "state":
|
|
193018
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RoundedBody, { node, w, h, cls: "state" });
|
|
193604
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RoundedBody, { node, w, h, cls: "state", showMult });
|
|
193019
193605
|
case "action":
|
|
193020
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RoundedBody, { node, w, h, cls: "action" });
|
|
193606
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RoundedBody, { node, w, h, cls: "action", showMult });
|
|
193021
193607
|
case "initial":
|
|
193022
193608
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InitialBody, { w, h });
|
|
193023
193609
|
case "final":
|
|
@@ -193067,6 +193653,7 @@ function NodeBody({ node, data, selectedPortId, hoveredPortId, movingPortId, con
|
|
|
193067
193653
|
ph,
|
|
193068
193654
|
w,
|
|
193069
193655
|
h,
|
|
193656
|
+
topReserve: featureBandTopReserve(data),
|
|
193070
193657
|
showLabels: data.showPortLabels,
|
|
193071
193658
|
selected: selectedPortId === ph.port.id,
|
|
193072
193659
|
hovered: hoveredPortId === ph.port.id,
|
|
@@ -193096,15 +193683,26 @@ function SysmlNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193096
193683
|
const dim = useInteraction(ctx.store, (s) => s.matchedIds ? !s.matchedIds.has(id2) : false);
|
|
193097
193684
|
const editing = useInteraction(ctx.store, (s) => s.editing?.nodeId === id2 && !s.editing?.at && !s.editing?.edgeId ? s.editing : void 0);
|
|
193098
193685
|
const editingHere = editing !== void 0;
|
|
193099
|
-
const
|
|
193100
|
-
const
|
|
193686
|
+
const hiddenContainer = node.meta?.internalsHidden === true;
|
|
193687
|
+
const showsControls = nodeShowsControls(node);
|
|
193688
|
+
const internalNoun = INTERNAL_NOUN[data.kind] ?? "internal parts";
|
|
193689
|
+
const featureCompartmentsVisible = node.meta?.featureCompartmentsVisible === true;
|
|
193690
|
+
const featureCompartmentHeight = featureBandTopReserve(data);
|
|
193101
193691
|
const containerRef = (0, import_react8.useRef)(null);
|
|
193102
193692
|
const portSource = (pid) => {
|
|
193103
193693
|
const p = node.ports?.find((pp) => pp.id === pid);
|
|
193104
193694
|
ctx.onPortSelected?.();
|
|
193105
193695
|
ctx.onReveal(p?.source, pid);
|
|
193106
193696
|
};
|
|
193107
|
-
const { dragId, onPortPointerDown } = usePortDrag(
|
|
193697
|
+
const { dragId, onPortPointerDown } = usePortDrag(
|
|
193698
|
+
containerRef,
|
|
193699
|
+
w,
|
|
193700
|
+
h,
|
|
193701
|
+
featureCompartmentHeight,
|
|
193702
|
+
ctx.onPortMove,
|
|
193703
|
+
ctx.onPortPreview,
|
|
193704
|
+
portSource
|
|
193705
|
+
);
|
|
193108
193706
|
const ports = data.ports;
|
|
193109
193707
|
const liveData = { ...data, w, h, ports };
|
|
193110
193708
|
const directRelation = directRelationForHandle(data.kind, {
|
|
@@ -193144,7 +193742,9 @@ function SysmlNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193144
193742
|
children: [
|
|
193145
193743
|
resizable ? (() => {
|
|
193146
193744
|
const min2 = resizeMinFor(node.shape, h);
|
|
193147
|
-
|
|
193745
|
+
const minWidth = showsControls ? Math.max(min2.minWidth, COLLAPSED_CONTAINER_MIN_WIDTH) : min2.minWidth;
|
|
193746
|
+
const minHeight = Math.max(min2.minHeight, data.featureCompartmentMinHeight ?? 0);
|
|
193747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NodeResizer, { minWidth, minHeight, maxHeight: min2.maxHeight, isVisible: true, color: "var(--accent)" });
|
|
193148
193748
|
})() : null,
|
|
193149
193749
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193150
193750
|
NodeBody,
|
|
@@ -193160,12 +193760,25 @@ function SysmlNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193160
193760
|
onPortContext: ctx.onContextNode
|
|
193161
193761
|
}
|
|
193162
193762
|
),
|
|
193763
|
+
data.kind === "iv" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193764
|
+
"div",
|
|
193765
|
+
{
|
|
193766
|
+
className: "rf-node-header",
|
|
193767
|
+
title: node.name,
|
|
193768
|
+
style: {
|
|
193769
|
+
left: 0,
|
|
193770
|
+
top: 0,
|
|
193771
|
+
height: NODE_COMPARTMENT_TOP,
|
|
193772
|
+
width: containerTitleArea(w, nodeShowsControls(node)).width
|
|
193773
|
+
}
|
|
193774
|
+
}
|
|
193775
|
+
) : null,
|
|
193163
193776
|
SIDES.flatMap((side, si) => {
|
|
193164
193777
|
const n2 = SIDE_NORMAL[side];
|
|
193165
193778
|
const out = SMALL_GLYPH_SHAPES.has(node.shape) ? 9 : 0;
|
|
193166
193779
|
const offsets = sideOffsets[si];
|
|
193167
193780
|
return offsets.map((offset2, i) => {
|
|
193168
|
-
const { x, y } = sideSurfacePoint(node.shape, side, offset2, w, h);
|
|
193781
|
+
const { x, y } = sideSurfacePoint(node.shape, side, offset2, w, h, featureCompartmentHeight);
|
|
193169
193782
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193170
193783
|
DualHandle,
|
|
193171
193784
|
{
|
|
@@ -193182,7 +193795,7 @@ function SysmlNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193182
193795
|
});
|
|
193183
193796
|
}),
|
|
193184
193797
|
ports.flatMap((ph) => {
|
|
193185
|
-
const rect = portGlyphRect(ph, w, h);
|
|
193798
|
+
const rect = portGlyphRect(ph, w, h, featureCompartmentHeight);
|
|
193186
193799
|
const c = { x: rect.cx, y: rect.cy };
|
|
193187
193800
|
const startable = directRelationForHandle(data.kind, {
|
|
193188
193801
|
id: ph.port.id,
|
|
@@ -193203,7 +193816,7 @@ function SysmlNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193203
193816
|
];
|
|
193204
193817
|
}),
|
|
193205
193818
|
ctx.onPortMove ? ports.map((ph) => {
|
|
193206
|
-
const rect = portGlyphRect(ph, w, h);
|
|
193819
|
+
const rect = portGlyphRect(ph, w, h, featureCompartmentHeight);
|
|
193207
193820
|
const nestedChild = ph.port.parentPort !== void 0;
|
|
193208
193821
|
const strip = portInteractionStrip(rect, ph.side);
|
|
193209
193822
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -193237,20 +193850,27 @@ function SysmlNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193237
193850
|
}
|
|
193238
193851
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: handles });
|
|
193239
193852
|
})() : null,
|
|
193240
|
-
ctx.onToggleNestedPort ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193241
|
-
|
|
193242
|
-
"button",
|
|
193853
|
+
ctx.onToggleNestedPort ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193854
|
+
NestedPortToggles,
|
|
193243
193855
|
{
|
|
193244
|
-
|
|
193245
|
-
|
|
193246
|
-
|
|
193247
|
-
|
|
193248
|
-
|
|
193249
|
-
|
|
193250
|
-
|
|
193251
|
-
|
|
193252
|
-
|
|
193253
|
-
|
|
193856
|
+
ports,
|
|
193857
|
+
w,
|
|
193858
|
+
h,
|
|
193859
|
+
topReserve: featureCompartmentHeight,
|
|
193860
|
+
onToggle: ctx.onToggleNestedPort
|
|
193861
|
+
}
|
|
193862
|
+
) : null,
|
|
193863
|
+
showsControls ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193864
|
+
ContainerControls,
|
|
193865
|
+
{
|
|
193866
|
+
id: id2,
|
|
193867
|
+
label: node.name,
|
|
193868
|
+
internalNoun,
|
|
193869
|
+
internalsVisible: !hiddenContainer,
|
|
193870
|
+
featureCompartmentsVisible,
|
|
193871
|
+
cornerRadius: nodeCornerRadius(node.shape, node.isDef, h, (node.compartments?.length ?? 0) > 0),
|
|
193872
|
+
onToggleInternals: ctx.onToggleInternals,
|
|
193873
|
+
onToggleFeatureCompartments: ctx.onToggleFeatureCompartments
|
|
193254
193874
|
}
|
|
193255
193875
|
) : null,
|
|
193256
193876
|
editingHere && ctx.onEditCommit && ctx.onEditCancel ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -193286,6 +193906,23 @@ function packageFramePath(w, h) {
|
|
|
193286
193906
|
"Z"
|
|
193287
193907
|
].join(" ");
|
|
193288
193908
|
}
|
|
193909
|
+
function frameFeatureBandPath(w, h, bottom, radius) {
|
|
193910
|
+
const left = 1;
|
|
193911
|
+
const right = Math.max(left, w - 1);
|
|
193912
|
+
const top = 1;
|
|
193913
|
+
const end = Math.max(top, Math.min(bottom, h - 1));
|
|
193914
|
+
const r = Math.max(0, Math.min(radius, (right - left) / 2, end - top));
|
|
193915
|
+
if (r === 0) return `M ${left} ${top} H ${right} V ${end} H ${left} Z`;
|
|
193916
|
+
return [
|
|
193917
|
+
`M ${left} ${top + r}`,
|
|
193918
|
+
`Q ${left} ${top} ${left + r} ${top}`,
|
|
193919
|
+
`H ${right - r}`,
|
|
193920
|
+
`Q ${right} ${top} ${right} ${top + r}`,
|
|
193921
|
+
`V ${end}`,
|
|
193922
|
+
`H ${left}`,
|
|
193923
|
+
"Z"
|
|
193924
|
+
].join(" ");
|
|
193925
|
+
}
|
|
193289
193926
|
function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
193290
193927
|
const ctx = useDiagram();
|
|
193291
193928
|
const frame2 = data.frame;
|
|
@@ -193300,13 +193937,30 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193300
193937
|
const isPackage2 = frame2.keyword === "package";
|
|
193301
193938
|
const isLibraryPackage = isPackage2 && frame2.meta?.library === true;
|
|
193302
193939
|
const resizable = selected2 && (!isPackage2 || data.kind === "gv");
|
|
193303
|
-
const collapsible = isCollapsibleFrame(data.kind, frame2)
|
|
193940
|
+
const collapsible = isCollapsibleFrame(data.kind, frame2);
|
|
193941
|
+
const controllable = collapsible && (ctx.onToggleInternals !== void 0 || ctx.onToggleFeatureCompartments !== void 0);
|
|
193942
|
+
const internalNoun = INTERNAL_NOUN[data.kind] ?? "internal parts";
|
|
193943
|
+
const featureCompartmentsVisible = frame2.meta?.featureCompartmentsVisible === true;
|
|
193944
|
+
const featureBandHeight = data.featureCompartmentHeight ?? frameFeatureCompartmentHeight(frame2);
|
|
193945
|
+
const featureCompartmentHeight = featureBandHeight > 0 ? FRAME_TITLE_HEIGHT + featureBandHeight : 0;
|
|
193946
|
+
const bandBottom = containerBandBottom(
|
|
193947
|
+
featureBandHeight > 0 ? frame2 : { compartments: void 0 },
|
|
193948
|
+
FRAME_TITLE_HEIGHT
|
|
193949
|
+
);
|
|
193304
193950
|
const containerRef = (0, import_react8.useRef)(null);
|
|
193305
193951
|
const portSource = (pid) => {
|
|
193306
193952
|
ctx.onPortSelected?.();
|
|
193307
193953
|
ctx.onReveal(frame2.ports?.find((p) => p.id === pid)?.source, pid);
|
|
193308
193954
|
};
|
|
193309
|
-
const { dragId, onPortPointerDown } = usePortDrag(
|
|
193955
|
+
const { dragId, onPortPointerDown } = usePortDrag(
|
|
193956
|
+
containerRef,
|
|
193957
|
+
w,
|
|
193958
|
+
h,
|
|
193959
|
+
featureCompartmentHeight,
|
|
193960
|
+
ctx.onPortMove,
|
|
193961
|
+
ctx.onPortPreview,
|
|
193962
|
+
portSource
|
|
193963
|
+
);
|
|
193310
193964
|
const ports = data.ports;
|
|
193311
193965
|
const showPorts = ports.length > 0;
|
|
193312
193966
|
const isOuterViewFrame = (data.kind === "afv" || data.kind === "stv") && frame2.meta?.anchorFrame === true;
|
|
@@ -193345,32 +193999,59 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193345
193999
|
ctx.onContextNode(id2, e.clientX, e.clientY);
|
|
193346
194000
|
},
|
|
193347
194001
|
children: [
|
|
193348
|
-
resizable ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
194002
|
+
resizable ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
194003
|
+
NodeResizer,
|
|
194004
|
+
{
|
|
194005
|
+
minWidth: isPackage2 ? 180 : 80,
|
|
194006
|
+
minHeight: Math.max(isPackage2 ? 100 : 60, data.featureCompartmentMinHeight ?? 0),
|
|
194007
|
+
isVisible: true,
|
|
194008
|
+
color: "var(--accent)"
|
|
194009
|
+
}
|
|
194010
|
+
) : null,
|
|
193349
194011
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "rf-node-svg", width: w, height: h, style: { overflow: "visible" }, children: [
|
|
193350
194012
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { className: "dframe-hover-band", x: 0, y: 0, width: w, height: h, rx: 12, fill: "none", stroke: "transparent" }),
|
|
193351
194013
|
isPackage2 && data.kind === "gv" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { className: `dframe-rect package${isLibraryPackage ? " library" : ""}${data.isContainer ? " container" : ""}`, d: packageFramePath(w, h) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { className: `dframe-rect${data.isContainer ? " container" : ""}${frame2.meta?.boundaryBox === true ? " boundary" : ""}${frame2.meta?.parallel === true ? " parallel" : ""}${frame2.meta?.loop === true ? " loop" : ""}${frame2.meta?.performerLane === true ? " performer" : ""}`, x: 0, y: 0, width: w, height: h, rx: frame2.isDef === true ? 0 : 12 }),
|
|
194014
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
194015
|
+
"path",
|
|
194016
|
+
{
|
|
194017
|
+
className: "dfeature-band-bg",
|
|
194018
|
+
d: frameFeatureBandPath(w, h, bandBottom, frame2.isDef === true ? 0 : 12)
|
|
194019
|
+
}
|
|
194020
|
+
) : null,
|
|
193352
194021
|
(() => {
|
|
193353
194022
|
const kindFull = `\xAB${frame2.keyword}\xBB${isLibraryPackage ? " (standard library)" : ""}${frame2.meta?.parallel === true ? " \u2225" : ""}${variabilityMark(frame2.keyword)}`;
|
|
193354
|
-
const
|
|
193355
|
-
const
|
|
193356
|
-
const
|
|
194023
|
+
const avail = Math.max(24, containerTitleArea(w, controllable).width - 14);
|
|
194024
|
+
const kindShown = fitKind(kindFull, avail);
|
|
194025
|
+
const mult = data.showMult && frame2.multiplicity ? frame2.multiplicity : void 0;
|
|
194026
|
+
const title = titleNameLine(frame2.label, frame2.type, mult, void 0, avail);
|
|
193357
194027
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
193358
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: 10, y:
|
|
194028
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-kind", x: 10, y: CONTAINER_TITLE_KIND_BASELINE, children: [
|
|
193359
194029
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: kindFull, shown: kindShown }),
|
|
193360
194030
|
kindShown
|
|
193361
194031
|
] }),
|
|
193362
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-label", x:
|
|
193363
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full:
|
|
193364
|
-
|
|
194032
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { className: "dnode-label", x: 10, y: CONTAINER_TITLE_NAME_BASELINE, style: { fontSize: 11 }, children: [
|
|
194033
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FullTitle, { full: title.full, shown: title.shown }),
|
|
194034
|
+
title.nameShown,
|
|
194035
|
+
title.typeShown ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
194036
|
+
" : ",
|
|
194037
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tspan", { className: "dnode-type", children: title.typeShown })
|
|
194038
|
+
] }) : "",
|
|
194039
|
+
mult ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("tspan", { className: "dnode-kind", children: [
|
|
194040
|
+
" ",
|
|
194041
|
+
mult
|
|
194042
|
+
] }) : ""
|
|
193365
194043
|
] })
|
|
193366
194044
|
] });
|
|
193367
194045
|
})(),
|
|
194046
|
+
featureBandHeight > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Compartments, { node: frame2, w, top: FRAME_TITLE_HEIGHT }) : null,
|
|
194047
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ContainerBandRule, { w, y: bandBottom }) : null,
|
|
193368
194048
|
ports.map((ph) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193369
194049
|
PortGlyph,
|
|
193370
194050
|
{
|
|
193371
194051
|
ph,
|
|
193372
194052
|
w,
|
|
193373
194053
|
h,
|
|
194054
|
+
topReserve: featureCompartmentHeight,
|
|
193374
194055
|
showLabels: true,
|
|
193375
194056
|
selected: selectedPortId === ph.port.id,
|
|
193376
194057
|
hovered: hoveredPortId === ph.port.id,
|
|
@@ -193383,11 +194064,18 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193383
194064
|
ph.port.id
|
|
193384
194065
|
))
|
|
193385
194066
|
] }),
|
|
193386
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
194067
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
194068
|
+
"div",
|
|
194069
|
+
{
|
|
194070
|
+
className: "rf-frame-header",
|
|
194071
|
+
style: { left: 0, top: 0, width: "100%", height: FRAME_TITLE_HEIGHT },
|
|
194072
|
+
title: frame2.label
|
|
194073
|
+
}
|
|
194074
|
+
),
|
|
193387
194075
|
SIDES.flatMap((side, si) => {
|
|
193388
194076
|
const offsets = sideOffsets[si];
|
|
193389
194077
|
return offsets.map((offset2, i) => {
|
|
193390
|
-
const { x, y } =
|
|
194078
|
+
const { x, y } = sidePoint(side, offset2, w, h, featureCompartmentHeight);
|
|
193391
194079
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193392
194080
|
DualHandle,
|
|
193393
194081
|
{
|
|
@@ -193404,7 +194092,7 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193404
194092
|
});
|
|
193405
194093
|
}),
|
|
193406
194094
|
showPorts ? ports.flatMap((ph) => {
|
|
193407
|
-
const rect = portGlyphRect(ph, w, h);
|
|
194095
|
+
const rect = portGlyphRect(ph, w, h, featureCompartmentHeight);
|
|
193408
194096
|
const c = { x: rect.cx, y: rect.cy };
|
|
193409
194097
|
const startable = directRelationForHandle(data.kind, {
|
|
193410
194098
|
id: ph.port.id,
|
|
@@ -193425,7 +194113,7 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193425
194113
|
];
|
|
193426
194114
|
}) : null,
|
|
193427
194115
|
ctx.onPortMove ? ports.map((ph) => {
|
|
193428
|
-
const rect = portGlyphRect(ph, w, h);
|
|
194116
|
+
const rect = portGlyphRect(ph, w, h, featureCompartmentHeight);
|
|
193429
194117
|
const nestedChild = ph.port.parentPort !== void 0;
|
|
193430
194118
|
const strip = portInteractionStrip(rect, ph.side);
|
|
193431
194119
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -193447,20 +194135,27 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
193447
194135
|
`pd-${ph.port.id}`
|
|
193448
194136
|
);
|
|
193449
194137
|
}) : null,
|
|
193450
|
-
ctx.onToggleNestedPort ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
194138
|
+
ctx.onToggleNestedPort ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
194139
|
+
NestedPortToggles,
|
|
194140
|
+
{
|
|
194141
|
+
ports,
|
|
194142
|
+
w,
|
|
194143
|
+
h,
|
|
194144
|
+
topReserve: featureCompartmentHeight,
|
|
194145
|
+
onToggle: ctx.onToggleNestedPort
|
|
194146
|
+
}
|
|
194147
|
+
) : null,
|
|
193451
194148
|
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
193452
|
-
|
|
194149
|
+
ContainerControls,
|
|
193453
194150
|
{
|
|
193454
|
-
|
|
193455
|
-
|
|
193456
|
-
|
|
193457
|
-
|
|
193458
|
-
|
|
193459
|
-
|
|
193460
|
-
|
|
193461
|
-
|
|
193462
|
-
},
|
|
193463
|
-
children: "\u2212"
|
|
194151
|
+
id: id2,
|
|
194152
|
+
label: frame2.label,
|
|
194153
|
+
internalNoun,
|
|
194154
|
+
internalsVisible: true,
|
|
194155
|
+
featureCompartmentsVisible,
|
|
194156
|
+
cornerRadius: frame2.isDef === true ? 0 : FRAME_USAGE_CORNER_RADIUS,
|
|
194157
|
+
onToggleInternals: ctx.onToggleInternals,
|
|
194158
|
+
onToggleFeatureCompartments: ctx.onToggleFeatureCompartments
|
|
193464
194159
|
}
|
|
193465
194160
|
) : null,
|
|
193466
194161
|
editing && ctx.onEditCommit && ctx.onEditCancel ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -193648,9 +194343,9 @@ function resolveViewConfig(settings, view, overrides = {}) {
|
|
|
193648
194343
|
gvFilters: new Set(view?.gvFilters ?? []),
|
|
193649
194344
|
// Case View definitions are shown unless the user turned them off.
|
|
193650
194345
|
cvShowDefs: view?.cvShowDefs !== false,
|
|
193651
|
-
|
|
194346
|
+
hiddenInternals: view?.hiddenInternals ?? {},
|
|
194347
|
+
visibleFeatureCompartments: view?.visibleFeatureCompartments ?? {},
|
|
193652
194348
|
nestedPorts: view?.nestedPorts ?? {},
|
|
193653
|
-
collapsedActions: view?.collapsedActions ?? {},
|
|
193654
194349
|
showPortLabels: settings.showPortLabels,
|
|
193655
194350
|
showMultiplicities: settings.showMultiplicities,
|
|
193656
194351
|
showSubjectAsBoundaryBox: settings.showSubjectAsBoundaryBox,
|
|
@@ -193725,9 +194420,9 @@ async function renderDiagramSvg(document2, provider, options) {
|
|
|
193725
194420
|
showMult: config.showMultiplicities,
|
|
193726
194421
|
connectPointSpacing: config.connectPointSpacing,
|
|
193727
194422
|
subjectBoundary: config.showSubjectAsBoundaryBox,
|
|
193728
|
-
|
|
194423
|
+
hiddenInternals: config.hiddenInternals,
|
|
194424
|
+
visibleFeatureCompartments: config.visibleFeatureCompartments,
|
|
193729
194425
|
nestedPorts: config.nestedPorts,
|
|
193730
|
-
collapsedActions: config.collapsedActions,
|
|
193731
194426
|
overrides: config.overrides,
|
|
193732
194427
|
portOverrides: config.portOverrides,
|
|
193733
194428
|
edgeRoutes: config.edgeRoutes,
|
|
@@ -193797,7 +194492,7 @@ async function runExport(command) {
|
|
|
193797
194492
|
}
|
|
193798
194493
|
|
|
193799
194494
|
// src/main.ts
|
|
193800
|
-
var VERSION2 = true ? "0.
|
|
194495
|
+
var VERSION2 = true ? "0.15.0" : "dev";
|
|
193801
194496
|
function display(file) {
|
|
193802
194497
|
const rel2 = path9.relative(process.cwd(), file);
|
|
193803
194498
|
return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;
|