@principal-ai/subsystems-react 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/stories/Subsystem/ComponentGraph/aggregateFixture.d.ts +5 -0
  6. package/dist/stories/Subsystem/ComponentGraph/aggregateFixture.d.ts.map +1 -0
  7. package/dist/stories/Subsystem/ComponentGraph/aggregateFixture.js +4 -0
  8. package/dist/stories/Subsystem/ComponentGraph/aggregateFixture.js.map +1 -0
  9. package/dist/stories/Subsystem/ComponentGraph/aggregateViewFixture.d.ts +5 -0
  10. package/dist/stories/Subsystem/ComponentGraph/aggregateViewFixture.d.ts.map +1 -0
  11. package/dist/stories/Subsystem/ComponentGraph/aggregateViewFixture.js +4 -0
  12. package/dist/stories/Subsystem/ComponentGraph/aggregateViewFixture.js.map +1 -0
  13. package/dist/stories/Subsystem/ComponentGraph/composedFixture.d.ts +5 -0
  14. package/dist/stories/Subsystem/ComponentGraph/composedFixture.d.ts.map +1 -0
  15. package/dist/stories/Subsystem/ComponentGraph/composedFixture.js +4 -0
  16. package/dist/stories/Subsystem/ComponentGraph/composedFixture.js.map +1 -0
  17. package/dist/subsystem/SubsystemAggregateGraph.d.ts +70 -0
  18. package/dist/subsystem/SubsystemAggregateGraph.d.ts.map +1 -0
  19. package/dist/subsystem/SubsystemAggregateGraph.js +385 -0
  20. package/dist/subsystem/SubsystemAggregateGraph.js.map +1 -0
  21. package/dist/subsystem/model.d.ts +7 -0
  22. package/dist/subsystem/model.d.ts.map +1 -1
  23. package/dist/subsystem/model.js +65 -1
  24. package/dist/subsystem/model.js.map +1 -1
  25. package/package.json +1 -1
  26. package/src/index.ts +8 -0
  27. package/src/stories/Subsystem/ComponentDeclarationAudit.stories.tsx +13 -13
  28. package/src/stories/Subsystem/ComponentGraph/AggregateFrameGraph.stories.tsx +61 -0
  29. package/src/stories/Subsystem/ComponentGraph/AggregateGraph.stories.tsx +61 -0
  30. package/src/stories/Subsystem/ComponentGraph/Appearance.stories.tsx +17 -17
  31. package/src/stories/Subsystem/ComponentGraph/Basics.stories.tsx +2 -2
  32. package/src/stories/Subsystem/ComponentGraph/Captures.stories.tsx +3 -3
  33. package/src/stories/Subsystem/ComponentGraph/ComposedGraph.stories.tsx +73 -0
  34. package/src/stories/Subsystem/ComponentGraph/Constructs.stories.tsx +6 -6
  35. package/src/stories/Subsystem/ComponentGraph/CustomEntities.stories.tsx +8 -8
  36. package/src/stories/Subsystem/ComponentGraph/DetailPanel.stories.tsx +11 -11
  37. package/src/stories/Subsystem/ComponentGraph/Flows.stories.tsx +6 -6
  38. package/src/stories/Subsystem/ComponentGraph/FrameworkStereotype.stories.tsx +10 -10
  39. package/src/stories/Subsystem/ComponentGraph/ModuleBadges.stories.tsx +6 -6
  40. package/src/stories/Subsystem/ComponentGraph/Modules.stories.tsx +17 -17
  41. package/src/stories/Subsystem/ComponentGraph/NodeAnatomy.stories.tsx +16 -16
  42. package/src/stories/Subsystem/ComponentGraph/Packages.stories.tsx +12 -12
  43. package/src/stories/Subsystem/ComponentGraph/Processes.stories.tsx +1 -1
  44. package/src/stories/Subsystem/ComponentGraph/Proposed.stories.tsx +10 -10
  45. package/src/stories/Subsystem/ComponentGraph/Scenarios.stories.tsx +69 -69
  46. package/src/stories/Subsystem/ComponentGraph/Spotlights.stories.tsx +27 -27
  47. package/src/stories/Subsystem/ComponentGraph/aggregateFixture.ts +8 -0
  48. package/src/stories/Subsystem/ComponentGraph/aggregateViewFixture.ts +8 -0
  49. package/src/stories/Subsystem/ComponentGraph/composedFixture.ts +9 -0
  50. package/src/subsystem/SubsystemAggregateGraph.tsx +607 -0
  51. package/src/subsystem/model.test.ts +63 -0
  52. package/src/subsystem/model.ts +65 -1
@@ -435,6 +435,40 @@ export function deriveNameFromSymbol(
435
435
  return name;
436
436
  }
437
437
 
438
+ const CONSTRUCT_PLURALS: Record<string, string> = {
439
+ class: 'classes',
440
+ function: 'functions',
441
+ method: 'methods',
442
+ interface: 'interfaces',
443
+ type_alias: 'type aliases',
444
+ enum: 'enums',
445
+ store: 'stores',
446
+ external: 'externals',
447
+ custom_entity: 'custom entities',
448
+ };
449
+
450
+ /**
451
+ * One-line summary of what a group of declarations contains, e.g.
452
+ * `6 functions · 2 classes`. Used for aggregate frame boxes, which describe
453
+ * their contents (constructs) rather than their container. Empty/blank
454
+ * constructs are ignored. At most three groups; the rest folds into `+N more`.
455
+ */
456
+ export function describeConstructBreakdown(constructs: readonly string[]): string {
457
+ const counts = new Map<string, number>();
458
+ for (const raw of constructs) {
459
+ const c = (raw ?? '').trim();
460
+ if (!c) continue;
461
+ counts.set(c, (counts.get(c) ?? 0) + 1);
462
+ }
463
+ const ranked = [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
464
+ const parts = ranked.slice(0, 3).map(([c, n]) => {
465
+ if (n === 1) return `1 ${c}`;
466
+ return `${n} ${CONSTRUCT_PLURALS[c] ?? `${c}s`}`;
467
+ });
468
+ if (ranked.length > 3) parts.push(`+${ranked.length - 3} more`);
469
+ return parts.join(' · ') || 'empty';
470
+ }
471
+
438
472
  /**
439
473
  * Human-readable purl identity — drops the `pkg:<type>/` scheme wrapper and
440
474
  * trailing version, keeping the package / owner-repo identity:
@@ -717,6 +751,30 @@ export function buildBoundaryLayoutGroups(
717
751
  );
718
752
  const keptProcessKeys = new Set(processes.map((r) => r.key));
719
753
 
754
+ // Leaves owned by a multi-member module belong to that module's frame
755
+ // exclusively. Multi-member modules are always built by ELK (never skipped
756
+ // as singletons), so letting a process/package group also list them
757
+ // directly would parent the same leaf twice and ELK throws
758
+ // ("value already present"). Mixed-process modules (common in composed
759
+ // graphs, where models frame one file under different processes) never
760
+ // nest — without this claim they land in both frames.
761
+ const claimedByModule = new Set<string>();
762
+ for (const r of modules) {
763
+ if (r.memberAliases.length >= 2) {
764
+ for (const alias of r.memberAliases) claimedByModule.add(alias);
765
+ }
766
+ }
767
+ // Same rule one level up: a leaf owned by a multi-member process frame
768
+ // must not also sit directly in a package frame. (Singleton processes
769
+ // never claim — ELK skips them and promotes the member upward, so the
770
+ // member has to stay reachable through its package or ungrouped.)
771
+ const claimedByProcess = new Set<string>();
772
+ for (const r of processes) {
773
+ if (r.memberAliases.length >= 2) {
774
+ for (const alias of r.memberAliases) claimedByProcess.add(alias);
775
+ }
776
+ }
777
+
720
778
  const moduleGroups: BoundaryLayoutGroup[] = modules.map((r) => {
721
779
  const processesOfMembers = new Set<string>();
722
780
  const packagesOfMembers = new Set<string>();
@@ -749,6 +807,7 @@ export function buildBoundaryLayoutGroups(
749
807
  const nestedModules = moduleGroups.filter((m) => m.parentId === processId);
750
808
  const nestedModuleKeys = new Set(nestedModules.map((m) => m.region.key));
751
809
  const directLeaves = r.memberAliases.filter((alias) => {
810
+ if (claimedByModule.has(alias)) return false;
752
811
  const mod = byAlias.get(alias)?.module?.trim();
753
812
  if (!mod) return true;
754
813
  return !nestedModuleKeys.has(mod);
@@ -785,7 +844,12 @@ export function buildBoundaryLayoutGroups(
785
844
  for (const m of nestedModules) {
786
845
  for (const alias of m.region.memberAliases) claimed.add(alias);
787
846
  }
788
- const directLeaves = r.memberAliases.filter((alias) => !claimed.has(alias));
847
+ const directLeaves = r.memberAliases.filter(
848
+ (alias) =>
849
+ !claimed.has(alias) &&
850
+ !claimedByModule.has(alias) &&
851
+ !claimedByProcess.has(alias),
852
+ );
789
853
  return {
790
854
  id: packageId,
791
855
  memberAliases: [