@septkit/ui 0.0.58 → 0.0.60

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 (22) hide show
  1. package/dist/diagram-layout/group-stack.js +13 -0
  2. package/dist/diagram-layout/grouping.js +33 -0
  3. package/dist/diagram-layout/index.js +6 -2
  4. package/dist/diagram-layout/use-diagram-layout.js +319 -0
  5. package/dist/diagram-layout/visibility-model.js +56 -0
  6. package/dist/dialecte/create-document-store.js +3 -3
  7. package/dist/external/.pnpm/{@dialecte_core@0.4.12 → @dialecte_core@0.4.16}/node_modules/@dialecte/core/dist/helpers.js +41 -41
  8. package/dist/external/.pnpm/@dialecte_core@0.4.16/node_modules/@dialecte/core/dist/index.js +3 -0
  9. package/dist/external/.pnpm/{@dialecte_core@0.4.12/node_modules/@dialecte/core/dist/project-DkMkDgld.js → @dialecte_core@0.4.16/node_modules/@dialecte/core/dist/project-nvZv2ie8.js} +797 -745
  10. package/dist/external/.pnpm/{@dialecte_core@0.4.12/node_modules/@dialecte/core/dist/utils-C5_11hqg.js → @dialecte_core@0.4.16/node_modules/@dialecte/core/dist/utils-BiEx1x59.js} +2 -2
  11. package/dist/external/.pnpm/{@dialecte_scl@0.3.15/node_modules/@dialecte/scl/dist/hooks-CLIa7kxj.js → @dialecte_scl@0.3.17/node_modules/@dialecte/scl/dist/hooks-BBGXNK0x.js} +31 -19
  12. package/dist/external/.pnpm/{@dialecte_scl@0.3.15 → @dialecte_scl@0.3.17}/node_modules/@dialecte/scl/dist/v2019C1/index.js +3 -3
  13. package/dist/index.d.ts +200 -2
  14. package/dist/index.js +6 -2
  15. package/dist/merge/build-view-model.js +17 -17
  16. package/dist/merge/merge-preflight.vue_vue_type_script_setup_true_lang.js +1 -1
  17. package/dist/merge/merge.service.js +16 -20
  18. package/dist/merge/use-merge-session.js +101 -121
  19. package/dist/ui.css +1 -1
  20. package/package.json +3 -3
  21. package/dist/external/.pnpm/@dialecte_core@0.4.12/node_modules/@dialecte/core/dist/index.js +0 -3
  22. package/dist/merge/merge-correlate.js +0 -46
@@ -1,4 +1,4 @@
1
- //#region node_modules/.pnpm/@dialecte+core@0.4.12/node_modules/@dialecte/core/dist/utils-C5_11hqg.js
1
+ //#region node_modules/.pnpm/@dialecte+core@0.4.16/node_modules/@dialecte/core/dist/utils-BiEx1x59.js
2
2
  var e = {
3
3
  UNKNOWN: {
4
4
  code: "D0001",
@@ -229,4 +229,4 @@ function f(e) {
229
229
  return c.push(...s), c;
230
230
  }
231
231
  //#endregion
232
- export { a, u as c, c as d, i as f, l as i, o as l, e as m, f as n, r as o, t as p, d as r, s as u };
232
+ export { r as c, o as d, s as f, e as g, t as h, i as m, f as n, l as o, c as p, d as r, a as s, u };
@@ -1,5 +1,5 @@
1
- import { XSI_NAMESPACE as e } from "../../../../../@dialecte_core@0.4.12/node_modules/@dialecte/core/dist/helpers.js";
2
- //#region node_modules/.pnpm/@dialecte+scl@0.3.15/node_modules/@dialecte/scl/dist/hooks-CLIa7kxj.js
1
+ import { XSI_NAMESPACE as e } from "../../../../../@dialecte_core@0.4.16/node_modules/@dialecte/core/dist/helpers.js";
2
+ //#region node_modules/.pnpm/@dialecte+scl@0.3.17/node_modules/@dialecte/scl/dist/hooks-BBGXNK0x.js
3
3
  var t = /* @__PURE__ */ "AccessControl.AccessPoint.Address.AllocationRole.AllocationRoleRef.AnalogueWiringParameters.AnalogueWiringParametersRef.Application.ApplicationSclRef.Association.Authentication.BDA.Bay.BayType.BehaviorDescription.BehaviorDescriptionRef.BehaviorReference.BinaryWiringParameters.BinaryWiringParametersRef.BitRate.CheckoutID.ClientLN.ClientServices.CommProt.Communication.CommunicationServiceSpecifications.ConductingEquipment.ConfDataSet.ConfLNs.ConfLdName.ConfLogControl.ConfReportControl.ConfSG.ConfSigRef.ConnectedAP.ConnectivityNode.ControlRef.ControllingLNode.DA.DAI.DAS.DAType.DO.DOI.DOS.DOType.DataObjectDirectory.DataSet.DataSetDirectory.DataTypeTemplates.DynAssociation.DynDataSet.EnumType.EnumVal.EqFunction.EqSubFunction.ExtCtrl.ExtRef.FCDA.FileHandling.Function.FunctionCatRef.FunctionCategory.FunctionCategoryRef.FunctionRef.FunctionRole.FunctionRoleContent.FunctionSclRef.FunctionTemplate.FunctionalSubVariant.FunctionalVariant.FunctionalVariantGroup.FunctionalVariantRef.GOOSE.GOOSEMcSecurity.GOOSESecurity.GSE.GSEControl.GSEDir.GSESettings.GSSE.GeneralEquipment.GetCBValues.GetDataObjectDefinition.GetDataSetValue.GetDirectory.GooseParameters.GooseParametersRef.Header.History.Hitem.IED.IEDName.IEDSourceFiles.InputVar.InputVarRef.Inputs.IssuerName.KDC.L2CommParameters.L3IPv4CommParameters.L3IPv6CommParameters.LDevice.LN.LN0.LNode.LNodeDataRef.LNodeInputRef.LNodeInputs.LNodeOutputRef.LNodeOutputs.LNodeSpecNaming.LNodeType.Label.Labels.Line.Log.LogControl.LogParameters.LogParametersRef.LogSettings.MaxTime.McSecurity.MinRequestedSCDFile.MinRequestedSCDFiles.MinTime.MultiAPPerSubNet.NeutralPoint.OptFields.OutputVar.OutputVarRef.Outputs.P.PhysConn.PowerSystemRelation.PowerSystemRelationRef.PowerSystemRelations.PowerTransformer.Private.Process.ProcessEcho.ProcessResource.ProcessResourceRef.ProcessResources.Project.ProjectProcessReference.ProtNs.Protocol.ReadWrite.RedProt.ReportControl.ReportParameters.ReportParametersRef.ReportSettings.Resource.RptEnabled.SCL.SCSM.SDI.SDO.SDS.SGEdit.SMV.SMVParameters.SMVParametersRef.SMVSecurity.SMVSettings.SMVsc.SVMcSecurity.SampledValueControl.SamplesPerSec.SclFileReference.SecPerSamples.Security.Server.ServerAt.ServiceSpecifications.Services.SetDataSetValue.SettingControl.SettingGroups.SignalRole.SmpRate.SmvOpts.SourceFiles.SourceRef.SubCategory.SubCheckoutID.SubEquipment.SubFunction.SubFunctionTemplate.SubNetwork.Subject.SubscriberLNode.Substation.SupSubscription.TapChanger.Terminal.Text.TimeSyncProt.TimerActivatedControl.TransformerWinding.TrgOps.Val.ValueHandling.Variable.VariableApplyTo.VariableRef.Voltage.VoltageLevel".split("."), n = {
4
4
  AccessControl: {
5
5
  tag: "AccessControl",
@@ -19910,13 +19910,24 @@ var u = {
19910
19910
  }]
19911
19911
  }, d = Object.keys(u);
19912
19912
  new Set(d), new Set(Object.values(u).flatMap((e) => e.flatMap((e) => e.target)));
19913
- var f = {
19913
+ var f = [
19914
+ "Substation",
19915
+ "VoltageLevel",
19916
+ "Bay"
19917
+ ], p = [
19918
+ "Application",
19919
+ "Function",
19920
+ "FunctionCategory",
19921
+ "AllocationRole",
19922
+ "Variable",
19923
+ "BehaviorDescription"
19924
+ ], m = {
19914
19925
  direct: "direct",
19915
19926
  lnode: "lnode",
19916
19927
  iedAddress: "ied-address",
19917
19928
  behaviorDescription: "behavior-description",
19918
19929
  unsupported: "unsupported"
19919
- }, p = {
19930
+ }, h = {
19920
19931
  LN: [{
19921
19932
  attribute: "lnType",
19922
19933
  target: "LNodeType"
@@ -19968,7 +19979,7 @@ var f = {
19968
19979
  }
19969
19980
  }]
19970
19981
  };
19971
- function m(e) {
19982
+ function g(e) {
19972
19983
  let t = {};
19973
19984
  for (let [n, r] of Object.entries(e)) for (let e of r) {
19974
19985
  let r = t[e.resolution] ??= /* @__PURE__ */ new Map();
@@ -19983,7 +19994,7 @@ function m(e) {
19983
19994
  }
19984
19995
  return t;
19985
19996
  }
19986
- function h(e) {
19997
+ function _(e) {
19987
19998
  let t = /* @__PURE__ */ new Map();
19988
19999
  for (let [n, r] of Object.entries(e)) t.set(n, r.map((e) => ({
19989
20000
  uuidAttr: e.attribute.uuid,
@@ -19993,7 +20004,7 @@ function h(e) {
19993
20004
  })));
19994
20005
  return t;
19995
20006
  }
19996
- function g(e) {
20007
+ function v(e) {
19997
20008
  let t = /* @__PURE__ */ new Map();
19998
20009
  for (let [n, r] of Object.entries(e)) for (let e of r) {
19999
20010
  let r = t.get(e.target) ?? [];
@@ -20005,23 +20016,24 @@ function g(e) {
20005
20016
  }
20006
20017
  return t;
20007
20018
  }
20008
- m(u);
20009
- var _ = [
20010
- f.direct,
20011
- f.lnode,
20012
- f.iedAddress,
20013
- f.behaviorDescription
20019
+ g(u);
20020
+ var y = [
20021
+ m.direct,
20022
+ m.lnode,
20023
+ m.iedAddress,
20024
+ m.behaviorDescription
20014
20025
  ];
20015
- [..._, f.unsupported], h(u), new Map(Object.entries(u).flatMap(([e, t]) => t.filter((e) => e.attribute.path === "mappedDoName" || e.attribute.path === "mappedDaName").map((t) => [e, {
20026
+ [...y, m.unsupported], _(u), new Map(Object.entries(u).flatMap(([e, t]) => t.filter((e) => e.attribute.path === "mappedDoName" || e.attribute.path === "mappedDaName").map((t) => [e, {
20016
20027
  path: t.attribute.path,
20017
20028
  uuid: t.attribute.uuid
20018
20029
  }]))), [...new Set(Object.values(u).flatMap((e) => e.map((e) => e.attribute.uuid)))];
20019
- var v = new Map(Object.entries(p).map(([e, t]) => [e, [...new Set(t.map((e) => e.attribute))]])), y = g(p);
20020
- new Set(y.keys()), [...n.LNode?.attributes?.identityFields ?? [], ...v.get("LNode") ?? []], new Set(n.LNode.attributes.details.lnClass.facets.enumeration), new Set(Object.values(u).flatMap((e) => e.flatMap((e) => [e.attribute.path, e.attribute.uuid])));
20021
- function b(e) {
20030
+ var b = new Map(Object.entries(h).map(([e, t]) => [e, [...new Set(t.map((e) => e.attribute))]])), x = v(h);
20031
+ new Set(x.keys()), [...n.LNode?.attributes?.identityFields ?? [], ...b.get("LNode") ?? []], new Set(n.LNode.attributes.details.lnClass.facets.enumeration), new Set(Object.values(u).flatMap((e) => e.flatMap((e) => [e.attribute.path, e.attribute.uuid]))), [...f, ...p];
20032
+ function S(e) {
20022
20033
  switch (e.verb) {
20023
20034
  case "fsd":
20024
- case "asd": return {
20035
+ case "asd":
20036
+ case "ssd": return {
20025
20037
  rootTag: "Substation",
20026
20038
  omit: ["Communication", "IED"],
20027
20039
  include: ["DataTypeTemplates"]
@@ -20030,4 +20042,4 @@ function b(e) {
20030
20042
  }
20031
20043
  new Set(Object.values(a).map((e) => e.uri)), new Set(Object.values(a).map((e) => e.prefix).filter(Boolean));
20032
20044
  //#endregion
20033
- export { i as A, u as D, r as M, a as N, v as g, y as h, b as i, o as k, _ as m, p as v, d as w, f as y };
20045
+ export { o as A, n as F, r as N, u as O, a as P, f as S, d as T, p as b, b as g, x as h, S as i, i as j, y as m, h as v, m as y };
@@ -1,6 +1,6 @@
1
- import "../../../../../../@dialecte_core@0.4.12/node_modules/@dialecte/core/dist/index.js";
2
- import { i as e } from "../hooks-CLIa7kxj.js";
3
- //#region node_modules/.pnpm/@dialecte+scl@0.3.15/node_modules/@dialecte/scl/dist/v2019C1/index.js
1
+ import "../../../../../../@dialecte_core@0.4.16/node_modules/@dialecte/core/dist/index.js";
2
+ import { i as e } from "../hooks-BBGXNK0x.js";
3
+ //#region node_modules/.pnpm/@dialecte+scl@0.3.17/node_modules/@dialecte/scl/dist/v2019C1/index.js
4
4
  var t = {
5
5
  "cross-type-template-uuid": {
6
6
  title: "Placeholder templateUuid reused across element types",
package/dist/index.d.ts CHANGED
@@ -23,6 +23,7 @@ import { Ref } from 'vue';
23
23
  import { Scl } from '@dialecte/scl/v2019C1';
24
24
  import { ShallowRef } from 'vue';
25
25
  import { TemplateUuidWarning } from '@dialecte/scl/v2019C1';
26
+ import { TopologyStructuralTag } from '@dialecte/scl/v2019C1';
26
27
 
27
28
  declare const __VLS_component: DefineComponent<__VLS_Props, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLButtonElement>;
28
29
 
@@ -458,6 +459,13 @@ declare type AfterApplyContext = {
458
459
  result: ApplyResult;
459
460
  };
460
461
 
462
+ /**
463
+ * Seed `visibleChildIds` from the initial expand/collapse options: BFS from the
464
+ * roots, expanding a node when it is explicitly expanded or within
465
+ * `defaultOpenDepth` (unless explicitly collapsed). Mutates `recordMap`.
466
+ */
467
+ export declare function applyInitialVisibility<TRecord extends LayoutTreeRecord>(recordMap: RecordMapById<TRecord>, rootIds: string[], options: VisibilityOptions): void;
468
+
461
469
  /**
462
470
  * A fixed prefix/suffix wrapped around an editable attribute value. The user edits only
463
471
  * the "core" between them; the affix is rendered as inert adornment and re-applied on
@@ -469,6 +477,21 @@ export declare type AttributeAffix = {
469
477
  suffix?: string;
470
478
  };
471
479
 
480
+ /**
481
+ * Build the parent→child `RecordWithCache` map and the list of root ids from a
482
+ * flat record set. Pure: `record.parent` is never mutated — root status is
483
+ * derived from the relationship (no parent by default) or from the caller's
484
+ * `isRoot` predicate, so domain rules stay outside this module.
485
+ *
486
+ * Records whose parent id resolves to nothing are returned as `orphanIds` and
487
+ * treated as roots.
488
+ */
489
+ export declare function buildRecordCache<TRecord extends LayoutTreeRecord>(records: TRecord[], isRoot?: (record: TRecord) => boolean): {
490
+ recordMap: RecordMapById<TRecord>;
491
+ rootIds: string[];
492
+ orphanIds: string[];
493
+ };
494
+
472
495
  export declare const Button: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
473
496
 
474
497
  export declare const CATEGORY_ELEMENTS: Record<string, string[]>;
@@ -486,8 +509,29 @@ export declare const CodeBlock: DefineComponent<__VLS_Props_9, {}, {}, {}, {}, C
486
509
  */
487
510
  export declare function collectExpandableNodeIds(items: ExplorerNode[]): string[];
488
511
 
512
+ /** Collect all currently visible node ids (roots + recursively expanded children). */
513
+ export declare function collectVisibleIds<TRecord extends LayoutTreeRecord>(rootIds: string[], recordMap: RecordMapById<TRecord>): string[];
514
+
489
515
  export declare const Combobox: __VLS_WithTemplateSlots_3<typeof __VLS_component_3, __VLS_TemplateResult_3["slots"]>;
490
516
 
517
+ /**
518
+ * Compute synthetic group nodes for visible children.
519
+ *
520
+ * For each parent, ALL collapsed children of the same tagName (2+) form ONE
521
+ * group — a fixed "collapsed area" for that kind. Combined with the emission
522
+ * logic (which anchors the group at the kind's document position and appends
523
+ * opened siblings after it in stable expansion order), this keeps every kind's
524
+ * area in the same spot: opening or closing a member in any order moves only
525
+ * that member between the tile and the opened-area, never reshuffling the rest.
526
+ */
527
+ export declare function computeGroups<TRecord extends LayoutTreeRecord>(visibleIds: string[], recordMap: RecordMapById<TRecord>): GroupNode[];
528
+
529
+ export declare type Connection = {
530
+ id: string;
531
+ source: string;
532
+ target: string;
533
+ };
534
+
491
535
  export declare const ContextMenu: DefineComponent<__VLS_Props_16, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
492
536
  close: () => any;
493
537
  }, string, PublicProps, Readonly<__VLS_Props_16> & Readonly<{
@@ -573,6 +617,23 @@ export declare type DetailAttribute = {
573
617
  conflict?: boolean;
574
618
  };
575
619
 
620
+ export declare type DiagramLayoutOptions<TRecord extends LayoutTreeRecord, TNode, TEdge> = {
621
+ engine?: LayoutEngine;
622
+ layoutOptions?: LayoutOptions;
623
+ measuredHeightFeedback?: boolean;
624
+ /**
625
+ * Decide which records are diagram roots. Defaults to "has no parent".
626
+ * Consumers whose record set is rooted under a domain element (for example an
627
+ * SCL document root that is not itself a record) override this.
628
+ */
629
+ isRoot?: (record: TRecord) => boolean;
630
+ nodeSize: (record: TRecord, measuredHeight?: number) => LayoutSize;
631
+ groupLayout: (group: GroupNode, members: Array<RecordWithCache<TRecord>>, expanded: boolean) => GroupLayout;
632
+ toNode: (context: NodeMapperContext<TRecord>) => TNode;
633
+ toGroupNode: (context: GroupMapperContext<TRecord>) => TNode;
634
+ toEdge: (context: EdgeMapperContext) => TEdge;
635
+ };
636
+
576
637
  /**
577
638
  * Message shapes posted on a dialecte project's BroadcastChannel — the public
578
639
  * event contract of @dialecte/core. Alias of core's `ProjectChannelMessage`
@@ -649,6 +710,12 @@ export declare type DocumentProgressBarProps = {
649
710
 
650
711
  export declare const Dropdown: __VLS_WithTemplateSlots_2<typeof __VLS_component_2, __VLS_TemplateResult_2["slots"]>;
651
712
 
713
+ export declare type EdgeMapperContext = {
714
+ edge: LayoutEdge;
715
+ route: LayoutPoint[];
716
+ singleChild: boolean;
717
+ };
718
+
652
719
  /** How the UI may edit an attribute (schema-derived classifier). */
653
720
  export declare type EditableMode = 'rename' | 'free';
654
721
 
@@ -738,6 +805,63 @@ export declare type FileMeta = {
738
805
  revision: string;
739
806
  };
740
807
 
808
+ export declare type GroupLayout = LayoutSize & {
809
+ expandable: boolean;
810
+ };
811
+
812
+ export declare type GroupMapperContext<TRecord extends LayoutTreeRecord> = {
813
+ group: GroupNode;
814
+ members: Array<RecordWithCache<TRecord>>;
815
+ position: LayoutPoint;
816
+ size: LayoutSize;
817
+ expanded: boolean;
818
+ expandable: boolean;
819
+ };
820
+
821
+ export declare type GroupNode = {
822
+ id: string;
823
+ parentId: string;
824
+ tagName: string;
825
+ memberIds: string[];
826
+ };
827
+
828
+ /** Geometry of a group tile whose members stack in a single column. */
829
+ export declare type GroupStackInput = {
830
+ /** Height of each member card, in stacking order. */
831
+ memberHeights: number[];
832
+ /** Vertical gap between two member cards. */
833
+ gap: number;
834
+ /** Height of the members viewport while the tile is collapsed. */
835
+ collapsedHeight: number;
836
+ };
837
+
838
+ export declare type GroupStackMetrics = {
839
+ /** Height of all members plus the gaps between them. */
840
+ contentHeight: number;
841
+ /** Members viewport height while collapsed: the content, clamped. */
842
+ collapsedShownHeight: number;
843
+ /** Whether expanding reveals anything the collapsed viewport hides. */
844
+ expandable: boolean;
845
+ /** Whether the collapsed viewport overflows and therefore scrolls. */
846
+ scrolls: boolean;
847
+ /** Members viewport height in the requested state. */
848
+ shownHeight: number;
849
+ };
850
+
851
+ /**
852
+ * Deterministic footprint of a group tile's member stack. Shared so consumers
853
+ * cannot disagree on when a tile is expandable: the members are a single
854
+ * column, so the height is a pure function of the member heights, and a tile is
855
+ * expandable exactly when its content does not fit the collapsed viewport.
856
+ *
857
+ * Padding, header height, scrollbar gutters and per-member card heights stay
858
+ * with the consumer - this owns the stacking rule only.
859
+ */
860
+ export declare function groupStackMetrics(input: GroupStackInput, expanded: boolean): GroupStackMetrics;
861
+
862
+ /** Recursively hide all descendants of an entry. Mutates the entry subtree. */
863
+ export declare function hideDescendants<TRecord extends LayoutTreeRecord>(entry: RecordWithCache<TRecord>): void;
864
+
741
865
  /**
742
866
  * Render code to syntax-highlighted HTML using Shiki's VSCode grammars/themes.
743
867
  * The JavaScript RegExp engine is used (not the WASM/oniguruma engine) so the
@@ -751,6 +875,8 @@ export declare function highlightCode(code: string, options?: {
751
875
  lineStatuses?: readonly LineStatus[];
752
876
  }): Promise<string>;
753
877
 
878
+ export declare function isGroupId(id: string): boolean;
879
+
754
880
  export declare type LayoutDirection = 'UP' | 'DOWN' | 'LEFT' | 'RIGHT';
755
881
 
756
882
  /** A connection between nodes. Arrays mirror ELK's hyperedge model, so a
@@ -822,6 +948,26 @@ export declare type LayoutPoint = {
822
948
  y: number;
823
949
  };
824
950
 
951
+ export declare type LayoutSize = {
952
+ width: number;
953
+ height: number;
954
+ };
955
+
956
+ export declare type LayoutTreeRecord = {
957
+ id: string;
958
+ tagName: string;
959
+ parent?: LayoutTreeRelation | null;
960
+ children: Array<{
961
+ id: string;
962
+ tagName?: string;
963
+ }>;
964
+ };
965
+
966
+ export declare type LayoutTreeRelation = {
967
+ id: string;
968
+ tagName: string;
969
+ };
970
+
825
971
  export declare type LineStatus = 'added' | 'removed' | 'unchanged';
826
972
 
827
973
  /**
@@ -834,6 +980,8 @@ export declare type LiveDataDocument = {
834
980
  channelName: string;
835
981
  };
836
982
 
983
+ export declare function makeGroupId(parentId: string, tagName: string): string;
984
+
837
985
  /**
838
986
  * Per-node metadata the merge tree overlays on an `ExplorerNode` (keyed by node id).
839
987
  * The tree itself is a plain `ExplorerNode[]`; this side map drives change colour, the
@@ -879,8 +1027,8 @@ export declare type MergeSessionParams = {
879
1027
  verb: LifecycleVerb;
880
1028
  /** Operation to perform: place a new instance, or reconcile the existing one. */
881
1029
  scenario: LifecycleScenario;
882
- /** Source (template) element: a Function (fsd) or Application (asd). */
883
- sourceRef: Scl.Ref<'Function'> | Scl.Ref<'Application'>;
1030
+ /** Source (template) element: a Function (fsd), Application (asd) or topology scope (ssd). */
1031
+ sourceRef: Scl.Ref<'Function'> | Scl.Ref<'Application'> | Scl.Ref<TopologyStructuralTag>;
884
1032
  /** Target parent the instance lives under / is placed into. */
885
1033
  anchor: Scl.Ref<Scl.ElementsOf>;
886
1034
  /** Optional consumer post-step run inside the merge tx (preview + commit). */
@@ -909,6 +1057,18 @@ color: "neutral" | "primary" | "secondary" | "accent" | "info" | "success" | "wa
909
1057
  size: "xs" | "sm" | "md" | "lg" | "xl";
910
1058
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
911
1059
 
1060
+ export declare type NavNode = {
1061
+ id: string;
1062
+ x: number;
1063
+ y: number;
1064
+ parentId: string | null;
1065
+ };
1066
+
1067
+ export declare type NodeMapperContext<TRecord extends LayoutTreeRecord> = {
1068
+ entry: RecordWithCache<TRecord>;
1069
+ position: LayoutPoint;
1070
+ };
1071
+
912
1072
  /** Presentation progress: a held monotonic fraction in `[0, 1]` and its caption. */
913
1073
  export declare type ProgressDisplay = {
914
1074
  fraction: number;
@@ -933,6 +1093,14 @@ export declare type ReactiveDocument = {
933
1093
  subscribe(callback: (terminal: boolean) => void): () => void;
934
1094
  };
935
1095
 
1096
+ export declare type RecordMapById<TRecord extends LayoutTreeRecord = LayoutTreeRecord> = Record<string, RecordWithCache<TRecord>>;
1097
+
1098
+ export declare type RecordWithCache<TRecord extends LayoutTreeRecord = LayoutTreeRecord> = {
1099
+ record: TRecord;
1100
+ childrenCache: Array<RecordWithCache<TRecord>>;
1101
+ visibleChildIds: Set<string>;
1102
+ };
1103
+
936
1104
  export declare const SclExplorer: __VLS_WithTemplateSlots_5<typeof __VLS_component_5, __VLS_TemplateResult_5["slots"]>;
937
1105
 
938
1106
  export declare const SplitLayout: __VLS_WithTemplateSlots_6<typeof __VLS_component_6, __VLS_TemplateResult_6["slots"]>;
@@ -1002,6 +1170,29 @@ export declare function useActiveDocument<GenericDocument>(params: {
1002
1170
  stop: () => void;
1003
1171
  };
1004
1172
 
1173
+ export declare function useDiagramLayout<TRecord extends LayoutTreeRecord, TNode, TEdge>(options: DiagramLayoutOptions<TRecord, TNode, TEdge>): {
1174
+ flowNodes: ShallowRef<TNode[], TNode[]>;
1175
+ flowEdges: ShallowRef<TEdge[], TEdge[]>;
1176
+ navNodes: ShallowRef<NavNode[], NavNode[]>;
1177
+ groupMembersById: ShallowRef<Map<string, string[]>, Map<string, string[]>>;
1178
+ expandedGroupIds: ShallowRef<Set<string>, Set<string>>;
1179
+ orphanIds: ShallowRef<string[], string[]>;
1180
+ setRecords: (newRecords: TRecord[]) => void;
1181
+ setConnections: (newConnections: Connection[]) => void;
1182
+ reset: () => void;
1183
+ calcLayout: (visibilityOptions: VisibilityOptions) => Promise<void>;
1184
+ reCalcLayout: () => Promise<void>;
1185
+ applyMeasuredHeights: (heights: Record<string, number>) => Promise<boolean>;
1186
+ expandNode: (nodeId: string) => Promise<void>;
1187
+ collapseNode: (nodeId: string) => Promise<void>;
1188
+ toggleNode: (nodeId: string) => Promise<void>;
1189
+ toggleGroup: (groupId: string) => Promise<void>;
1190
+ hasNodeLoadedChildren: (nodeId: string) => boolean;
1191
+ addChildren: (nodeId: string, children: TRecord[]) => void;
1192
+ getRecordEntry: (id: string) => RecordWithCache<TRecord> | undefined;
1193
+ updateRecord: (id: string, patch: Partial<TRecord>) => void;
1194
+ };
1195
+
1005
1196
  /**
1006
1197
  * Listen to a dialecte project's BroadcastChannel.
1007
1198
  *
@@ -1129,6 +1320,13 @@ export declare function useProjectLiveData<T>(params: {
1129
1320
  refresh: (delay?: number) => Promise<T | undefined>;
1130
1321
  };
1131
1322
 
1323
+ /** Options that drive which nodes are initially visible. */
1324
+ export declare type VisibilityOptions = {
1325
+ expandedNodeIds: Set<string>;
1326
+ collapsedNodeIds: Set<string>;
1327
+ defaultOpenDepth: number;
1328
+ };
1329
+
1132
1330
  export declare const XmlDiff: DefineComponent<__VLS_Props_10, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_10> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
1133
1331
 
1134
1332
  export { }
package/dist/index.js CHANGED
@@ -37,6 +37,10 @@ import P from "./context-menu/context-menu.js";
37
37
  import "./context-menu/index.js";
38
38
  import F from "./split-layout/split-layout.js";
39
39
  import "./split-layout/index.js";
40
- import { createElkLayoutEngine as I } from "./diagram-layout/elk-layout-engine.js";
40
+ import { applyInitialVisibility as I, buildRecordCache as L, collectVisibleIds as R, hideDescendants as z } from "./diagram-layout/visibility-model.js";
41
+ import { groupStackMetrics as B } from "./diagram-layout/group-stack.js";
42
+ import { computeGroups as V, isGroupId as H, makeGroupId as U } from "./diagram-layout/grouping.js";
43
+ import { createElkLayoutEngine as W } from "./diagram-layout/elk-layout-engine.js";
44
+ import { useDiagramLayout as G } from "./diagram-layout/use-diagram-layout.js";
41
45
  import "./diagram-layout/index.js";
42
- export { s as Button, y as CATEGORY_ELEMENTS, T as CodeBlock, l as Combobox, P as ContextMenu, O as DecisionToggle, d as Dialog, _ as DialogHost, v as DocumentProgressBar, c as Dropdown, b as ELEMENT_TO_COLOR, x as ELEMENT_TO_ICON, k as ElementDetail, f as FeedbackDialog, N as MergeReview, A as MergeTree, u as MultiSelect, C as SclExplorer, F as SplitLayout, j as TypeNameAuthority, D as XmlDiff, S as collectExpandableNodeIds, p as createDialogHost, e as createDocumentStore, I as createElkLayoutEngine, m as dialogHostKey, E as diffLines, w as highlightCode, h as provideDialogHost, i as useActiveDocument, t as useDialecteChannel, g as useDialog, a as useDocumentProgress, o as useDocumentState, n as useLiveData, M as useMergeSession, r as useProjectLiveData };
46
+ export { s as Button, y as CATEGORY_ELEMENTS, T as CodeBlock, l as Combobox, P as ContextMenu, O as DecisionToggle, d as Dialog, _ as DialogHost, v as DocumentProgressBar, c as Dropdown, b as ELEMENT_TO_COLOR, x as ELEMENT_TO_ICON, k as ElementDetail, f as FeedbackDialog, N as MergeReview, A as MergeTree, u as MultiSelect, C as SclExplorer, F as SplitLayout, j as TypeNameAuthority, D as XmlDiff, I as applyInitialVisibility, L as buildRecordCache, S as collectExpandableNodeIds, R as collectVisibleIds, V as computeGroups, p as createDialogHost, e as createDocumentStore, W as createElkLayoutEngine, m as dialogHostKey, E as diffLines, B as groupStackMetrics, z as hideDescendants, w as highlightCode, H as isGroupId, U as makeGroupId, h as provideDialogHost, i as useActiveDocument, G as useDiagramLayout, t as useDialecteChannel, g as useDialog, a as useDocumentProgress, o as useDocumentState, n as useLiveData, M as useMergeSession, r as useProjectLiveData };
@@ -4,42 +4,42 @@ function n(e) {
4
4
  return e.instances.flatMap((e) => e.groups);
5
5
  }
6
6
  function r(e) {
7
- let { report: t, correlation: r } = e, i = /* @__PURE__ */ new Map();
8
- for (let e of n(t)) i.set(e.primary, {
7
+ let { report: t } = e, r = /* @__PURE__ */ new Map();
8
+ for (let e of n(t)) r.set(e.primary, {
9
9
  role: "primary",
10
10
  groupId: e.id
11
11
  });
12
- let a = /* @__PURE__ */ new Map();
13
- function o(e) {
14
- let t = r.get(e);
12
+ let i = /* @__PURE__ */ new Map();
13
+ function a(e) {
14
+ let t = e.appliedRef?.id;
15
15
  if (!t) return;
16
- let n = i.get(e);
17
- a.set(t, {
16
+ let n = r.get(e);
17
+ i.set(t, {
18
18
  change: e.change,
19
19
  role: n?.role ?? "plain",
20
20
  groupId: n?.groupId,
21
21
  node: e
22
22
  });
23
23
  }
24
- function s(e) {
25
- o(e);
26
- for (let t of e.children) s(t);
24
+ function o(e) {
25
+ a(e);
26
+ for (let t of e.children) o(t);
27
27
  }
28
- function c(e, t) {
28
+ function s(e, t) {
29
29
  if (e.change !== "unchanged") {
30
- let n = r.get(e);
31
- n && a.set(n, {
30
+ let n = e.appliedRef?.id;
31
+ n && i.set(n, {
32
32
  change: e.change,
33
33
  role: "companion",
34
34
  groupId: t,
35
35
  node: e
36
36
  });
37
37
  }
38
- for (let n of e.children) c(n, t);
38
+ for (let n of e.children) s(n, t);
39
39
  }
40
- for (let e of t.instances) s(e.tree);
41
- for (let e of n(t)) for (let t of e.companions) c(t, e.id);
42
- return a;
40
+ for (let e of t.instances) o(e.tree);
41
+ for (let e of n(t)) for (let t of e.companions) s(t, e.id);
42
+ return i;
43
43
  }
44
44
  async function i(t) {
45
45
  let { tree: n, changeByStagedId: r, query: i } = t, a = {
@@ -1,5 +1,5 @@
1
1
  import e from "../external/.pnpm/@lucide_vue@1.23.0_vue@3.5.39_typescript@5.8.3_/node_modules/@lucide/vue/dist/esm/icons/triangle-alert.js";
2
- import { TEMPLATE_UUID_WARNING_INFO as t } from "../external/.pnpm/@dialecte_scl@0.3.15/node_modules/@dialecte/scl/dist/v2019C1/index.js";
2
+ import { TEMPLATE_UUID_WARNING_INFO as t } from "../external/.pnpm/@dialecte_scl@0.3.17/node_modules/@dialecte/scl/dist/v2019C1/index.js";
3
3
  import { Fragment as n, computed as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createVNode as s, defineComponent as c, openBlock as l, renderList as u, toDisplayString as d, unref as f } from "vue";
4
4
  //#region lib/merge/merge-preflight.vue?vue&type=script&setup=true&lang.ts
5
5
  var p = { class: "flex h-full min-h-0 flex-col" }, m = { class: "min-h-0 flex-1 overflow-auto p-4" }, h = { class: "mx-auto max-w-2xl space-y-4" }, g = { class: "flex items-start gap-3" }, _ = { class: "border-b border-warning/25 px-3 py-2" }, v = { class: "flex items-center gap-2" }, y = { class: "badge badge-soft badge-warning badge-sm font-medium" }, b = { class: "font-semibold" }, x = { class: "mt-1 text-sm text-base-content/80" }, S = { class: "mt-1 text-sm" }, C = { class: "text-base-content/80" }, w = { class: "divide-y divide-warning/15" }, T = { class: "font-mono break-all" }, E = { class: "text-base-content/70" }, D = {
@@ -1,28 +1,24 @@
1
- import { i as e } from "../external/.pnpm/@dialecte_scl@0.3.15/node_modules/@dialecte/scl/dist/hooks-CLIa7kxj.js";
2
- import "../external/.pnpm/@dialecte_scl@0.3.15/node_modules/@dialecte/scl/dist/v2019C1/index.js";
1
+ import { i as e } from "../external/.pnpm/@dialecte_scl@0.3.17/node_modules/@dialecte/scl/dist/hooks-BBGXNK0x.js";
2
+ import "../external/.pnpm/@dialecte_scl@0.3.17/node_modules/@dialecte/scl/dist/v2019C1/index.js";
3
3
  //#region lib/merge/merge.service.ts
4
4
  async function t(e, t) {
5
5
  return e.query.lifecycle.report(t);
6
6
  }
7
7
  async function n({ doc: e, target: t, report: n, decisions: r, keepNameTypesFrom: i, afterApply: a }) {
8
- let o;
9
- return {
10
- prepared: await e.prepare(async (e) => {
11
- let s = await e.lifecycle.apply({
12
- ...t,
13
- report: n,
14
- decisions: r,
15
- keepNameTypesFrom: i
16
- });
17
- o = s.instances, await a?.(e, {
18
- target: t,
19
- report: n,
20
- decisions: r,
21
- result: s
22
- });
23
- }),
24
- applied: o
25
- };
8
+ return { prepared: await e.prepare(async (e) => {
9
+ let o = await e.lifecycle.apply({
10
+ ...t,
11
+ report: n,
12
+ decisions: r,
13
+ keepNameTypesFrom: i
14
+ });
15
+ await a?.(e, {
16
+ target: t,
17
+ report: n,
18
+ decisions: r,
19
+ result: o
20
+ });
21
+ }) };
26
22
  }
27
23
  async function r({ doc: e, target: t, report: n, decisions: r, keepNameTypesFrom: i, afterApply: a }) {
28
24
  await e.transaction(async (e) => {