@tellegen/svelte 0.1.0 → 0.1.2

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 (39) hide show
  1. package/dist/TellegenMap.svelte +155 -19
  2. package/dist/TellegenMap.svelte.d.ts +1 -0
  3. package/dist/TellegenMap.svelte.d.ts.map +1 -1
  4. package/dist/TellegenShell.svelte +29 -3
  5. package/dist/TellegenShell.svelte.d.ts.map +1 -1
  6. package/dist/components/AppFooter.svelte +26 -1
  7. package/dist/components/AppFooter.svelte.d.ts +5 -17
  8. package/dist/components/AppFooter.svelte.d.ts.map +1 -1
  9. package/dist/components/AppHeader.svelte +59 -1
  10. package/dist/components/AppHeader.svelte.d.ts.map +1 -1
  11. package/dist/components/BindingLines.svelte +13 -0
  12. package/dist/components/BusPicker.svelte +40 -0
  13. package/dist/components/BusPicker.svelte.d.ts +4 -1
  14. package/dist/components/BusPicker.svelte.d.ts.map +1 -1
  15. package/dist/components/ControlPanel.svelte +359 -72
  16. package/dist/components/ControlPanel.svelte.d.ts +2 -17
  17. package/dist/components/ControlPanel.svelte.d.ts.map +1 -1
  18. package/dist/components/FormulationSelector.svelte +17 -0
  19. package/dist/components/MulticonductorDetails.svelte +58 -5
  20. package/dist/components/MulticonductorDetails.svelte.d.ts.map +1 -1
  21. package/dist/components/SensitivityReadout.svelte +10 -1
  22. package/dist/components/SolveCard.svelte +2 -1
  23. package/dist/controller.svelte.d.ts +3 -0
  24. package/dist/controller.svelte.d.ts.map +1 -1
  25. package/dist/controller.svelte.js +22 -4
  26. package/dist/multiconductor.d.ts +13 -0
  27. package/dist/multiconductor.d.ts.map +1 -1
  28. package/dist/multiconductor.js +39 -9
  29. package/dist/state.svelte.d.ts +18 -0
  30. package/dist/state.svelte.d.ts.map +1 -1
  31. package/dist/state.svelte.js +22 -0
  32. package/dist/styles.css +16 -2
  33. package/dist/synthetic-layout.d.ts +3 -1
  34. package/dist/synthetic-layout.d.ts.map +1 -1
  35. package/dist/synthetic-layout.js +130 -11
  36. package/dist/transformer-icon.d.ts +16 -0
  37. package/dist/transformer-icon.d.ts.map +1 -0
  38. package/dist/transformer-icon.js +35 -0
  39. package/package.json +1 -1
@@ -291,6 +291,9 @@ export declare class Controller {
291
291
  /** Select a bus in a multiconductor case: its terminal stack and incident
292
292
  * conductors expand. Selecting is viewing detail only — no solve. */
293
293
  selectMultiBus: (caseId: string, busId: string) => void;
294
+ /** Select an edge in a multiconductor case: its conductor pairing expands in
295
+ * the panel. Mutually exclusive with the bus selection. */
296
+ selectMultiEdge: (caseId: string, edgeId: string) => void;
294
297
  /** Place a multiconductor case awaiting a center: fit its provided planar
295
298
  * coordinates when it carries them, else lay it out synthetically. */
296
299
  placeMultiCase: (lon: number, lat: number) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"controller.svelte.d.ts","sourceRoot":"","sources":["../src/lib/controller.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAQrG,OAAO,EACN,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,eAAe,EAIpB,KAAK,YAAY,EACjB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAiBN,KAAK,YAAY,EAEjB,KAAK,WAAW,EAGhB,KAAK,UAAU,EACf,MAAM,kBAAkB,CAAC;AAO1B;;qDAEqD;AACrD,KAAK,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAqDxE,YAAY,EAAE,YAAY,EAAE,CAAC;AAC7B,KAAK,iBAAiB,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,WAAW,iBAAiB;IACjC,GAAG,CAAC,EAAE,iBAAiB,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,UAAU;IACtB,GAAG,EAAE,QAAQ,CAAC;IACd,GAAG,EAAE,iBAAiB,CAAC;IACvB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAQ;IAKrC,mBAAmB,SAAK;IAGxB,gBAAgB,UAAS;IAMzB,WAAW;eAED,YAAY;qBAAe,MAAM;qBAAe,WAAW;sBAAgB,QAAQ;OACzF;IAIJ,gBAAgB,gCAAuC;IAIvD,WAAW;qBAGI,MAAM;qBACN,WAAW;eACjB,MAAM;iBACJ,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;OAEnC;IAGJ,QAAQ,SAAK;IAGb,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAQ;IAErC,iBAAiB,2BAA0C;IAE3D,cAAc,cAAkC;IAChD,WAAW,UAAiB;IAC5B,kBAAkB,gBAA+B;IACjD,cAAc,UAAgB;IAM9B,gBAAgB;gBACP,MAAM;gBACN,UAAU;wBACF,MAAM;aACP;IAMhB,WAAW,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAQ;gBAExE,GAAG,EAAE,QAAQ,EAAE,OAAO,GAAE,iBAAsB;IAO1D,aAAa,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,SAAS;IAI9C,iBAAiB,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO;IAI3C,UAAU,CAAC,CAAC,EAAE,YAAY;IAI1B,WAAW,CAAC,CAAC,EAAE,YAAY,GAAG,kBAAkB;IAIhD;;iEAE6D;IAC7D,cAAc,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO;IAIxC,mEAAmE;IACnE,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO;IAIjD,WAAW,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO;IAI5C,oBAAoB,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAA+B;IAQvF,iBAAiB,CAChB,CAAC,EAAE,YAAY,EACf,KAAK,EAAE,MAAM,GACX;QAAE,EAAE,EAAE,eAAe,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;IAsBlD,oBAAoB,CACnB,CAAC,EAAE,YAAY,EACf,QAAQ,EAAE,MAAM,GACd;QAAE,EAAE,EAAE,eAAe,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;IAoBlD,mFAAmF;IACnF,QAAQ,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM;IAIjC,sBAAsB,IAAI,GAAG,CAAC,MAAM,CAAC;IAUrC,uBAAuB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC;IASxC,yBAAyB,CAAC,EAAE,EAAE,MAAM;IAOpC,YAAY,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,IAAI;IAY1C,oBAAoB,CAAC,EAAE,EAAE,MAAM;IAWzB,QAAQ,CAAC,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA8D5E,kBAAkB,CACvB,CAAC,EAAE,YAAY,EACf,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,UAAU,GAChB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAQpC,YAAY,CAAC,CAAC,EAAE,YAAY;IAU5B,iBAAiB,CAChB,CAAC,EAAE,YAAY,EACf,GAAG,EAAE,iBAAiB,GAAG,IAAI,EAC7B,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,cAAc,CAAC,EAAE,MAAM;IAexB,WAAW,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAqB7D,iBAAiB,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgBhE,aAAa,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;IAOzD,YAAY,CACX,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,UAAU,GAAG,IAAI,EACtB,MAAM,EAAE,MAAM,GACZ;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAmB7C,cAAc,sBAGZ;IACF,iBAAiB,gDAAyD;IAE1E,YAAY;;;;;;aAWT;IAEH,cAAc,yCAAiD;IAC/D,aAAa;;;;;;;;;;aAUV;IACH,YAAY;;;;;;;;;;aAYT;IAEH,eAAe,oBAIZ;IAEH,kBAAkB,kDAIf;IAKH,eAAe,oBAMb;IAEF,cAAc,SAIZ;IACF,WAAW,SAAqE;IAChF,iBAAiB,SAQd;IAEH,YAAY;aAvGF,MAAM;aAAO,MAAM;cAAQ,MAAM;MAyGzC;IACF,SAAS,SAAmC;IAC5C,SAAS,SAAmC;IAE5C,eAAe,SAIb;IACF,iBAAiB,SAAuE;IAOxF,YAAY;;;;MAKT;IAEH,mBAAmB,2BAUhB;IAEH,WAAW,iDAIT;IACF,kBAAkB,SAA8E;IAOhG,iBAAiB,SAUf;IACF,YAAY,gBAEV;IAEF,WAAW,gBAIR;IAKH,QAAQ,SAGL;IASH,iBAAiB,gBAed;IAEH,aAAa;;;aAKV;IAEH,SAAS;;;QAMN;IACH,aAAa,UAA0E;IAEvF,UAAU,UASR;IAIF,IAAI,QAAO,OAAO,CAAC,IAAI,CAAC,CA8CtB;IAEF,eAAe,GAAU,GAAG,SAAS,EAAE,eAAa,mBAgClD;IAEF;;qFAEiF;IACjF,OAAO,CAAC,UAAU;IAKlB,YAAY,GAAU,IAAI,MAAM,mBAU9B;IAKF,OAAO,CAAC,eAAe,CAOrB;IAEF,iBAAiB,GAAU,GAAG,SAAS,EAAE,QAAQ,UAAU,mBAYzD;IAEF,aAAa,GAAI,GAAG,SAAS,UAY3B;IAEF,eAAe,GAAU,GAAG,SAAS,EAAE,QAAQ,UAAU,mBAUvD;IAEF,mBAAmB,GAAI,GAAG,SAAS,UAOjC;IAEF,cAAc,GAAU,KAAK,MAAM,EAAE,KAAK,MAAM,mBAc9C;IAEF;;;;;eAKW;IACX,OAAO,CAAC,WAAW,CAYjB;IAEF;;uDAEmD;IACnD,gBAAgB,GAAU,GAAG,SAAS,KAAG,OAAO,CAAC,IAAI,CAAC,CAYpD;IAEF,aAAa,GAAI,GAAG,SAAS,UAI3B;IAEF;;;;;;8CAM0C;IAC1C,cAAc,GAAU,GAAG,SAAS,EAAE,QAAQ,YAAY,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CA6B1E;IAEF;;4DAEwD;IACxD,OAAO,CAAC,eAAe;IAmBvB;;wEAEoE;IACpE,OAAO,CAAC,eAAe,CAKrB;IAEF,wBAAwB,GAAU,QAAQ,YAAY,EAAE,mBAwBtD;IAEF;+EAC2E;IAC3E,OAAO,CAAC,UAAU;IAOlB;;;gBAGY;IACZ,OAAO,CAAC,YAAY,CAqElB;IAEF,SAAS,GAAI,QAAQ,MAAM,EAAE,OAAO,MAAM,mBAAsD;IAEhG;;;+BAG2B;IAC3B,OAAO,CAAC,gBAAgB;IAIxB;;;;;;gFAM4E;IAC5E,OAAO,CAAC,iBAAiB,CAkDvB;IAEF,+EAA+E;IAC/E,OAAO,CAAC,IAAI;IAKZ;kFAC8E;IAC9E,UAAU,aAKR;IAEF,cAAc,GAAU,SAAS,MAAM,EAAE,OAAO,MAAM,mBA0BpD;IAEF;;mCAE+B;IAC/B,OAAO,CAAC,wBAAwB;IAMhC;gFAC4E;IAC5E,OAAO,CAAC,qBAAqB;IAa7B;kEAC8D;IAC9D,YAAY,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,EAAE,OAAM;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,mBACV;IAEtE,iBAAiB,GAChB,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,OAAM;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,mBA6B7B;IAEF,cAAc,aA2BZ;IAQF,QAAQ,GAAI,GAAG,YAAY,EAAE,QAAQ,UAAU,GAAG,IAAI,UAgHpD;IAEF,WAAW,GAAI,GAAG,SAAS,EAAE,QAAQ,UAAU,GAAG,IAAI,EAAE,YAAgB,UA+CtE;IAEF,WAAW,GAAI,OAAO,MAAM,UAY1B;IAEF,iBAAiB,GAAI,OAAO,MAAM,UAShC;IAEF,SAAS,GAAI,GAAG,YAAY,UAc1B;IAQF,iBAAiB,GAAI,GAAG,YAAY,EAAE,MAAM,WAAW,UAsBrD;IAEF;;;uDAGmD;IACnD,WAAW,GAAU,OAAO,QAAQ,GAAG,IAAI,EAAE,mBAsJ3C;IAEF;;;;2EAIuE;IACvE,OAAO,CAAC,sBAAsB,CAkB5B;IAEF;;;;;6CAKyC;IACzC,OAAO,CAAC,cAAc,CAoCpB;IAEF;gFAC4E;IAC5E,OAAO,CAAC,cAAc,CAYpB;IAEF;;yEAEqE;IACrE,OAAO,CAAC,YAAY;IAmBpB,uEAAuE;IACvE,aAAa,GAAI,GAAG,kBAAkB,UAQpC;IAEF;yEACqE;IACrE,cAAc,GAAI,QAAQ,MAAM,EAAE,OAAO,MAAM,UAQ7C;IAEF;0EACsE;IACtE,cAAc,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,UASxC;IAEF,wEAAwE;IACxE,aAAa,GAAI,GAAG,kBAAkB,UAKpC;IAEF,eAAe,GAAU,GAAG,kBAAkB,EAAE,QAAQ,UAAU,mBAIhE;IAEF;2DACuD;IACvD,SAAS,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,UAGnC;IAEF;iFAC6E;IAC7E,OAAO,CAAC,uBAAuB,CAmB7B;IAEF;;wCAEoC;IACpC,OAAO,CAAC,WAAW,CAajB;IAEF,sEAAsE;IACtE,gBAAgB,GAAU,GAAG,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CASvD;IAEF;oEACgE;IAChE,aAAa,GAAU,GAAG,YAAY,EAAE,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAaxE;IAEF,8DAA8D;IAC9D,OAAO,CAAC,YAAY;IAKpB,kBAAkB,GAAI,MAAM,eAAe,UAazC;IAOF,UAAU,GAAI,GAAG,YAAY,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,UA6BvD;IAKF,OAAO,CAAC,iBAAiB,CAAgE;IACzF,OAAO,CAAC,iBAAiB,CAAS;YAEpB,iBAAiB;IAuC/B,gBAAgB,GAAI,OAAO,MAAM,GAAG,SAAS,UAM3C;IAKF,cAAc,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,kBAAkB;IAalF,gBAAgB,GAAI,GAAG,YAAY,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,UA0DhE;IAEF,gBAAgB,GAAI,OAAO,MAAM,GAAG,SAAS,UAQ3C;IAKF,OAAO,CAAC,kBAAkB,CAA8B;IAExD,YAAY,GAAU,OAAO,MAAM,mBAmBjC;IAEF,iBAAiB,GAAI,OAAO,MAAM,UAShC;IAEF,mBAAmB,aAQjB;IAEF,aAAa,eAA0B;IACvC,mBAAmB,eAAgC;CACnD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAE3F"}
1
+ {"version":3,"file":"controller.svelte.d.ts","sourceRoot":"","sources":["../src/lib/controller.svelte.ts"],"names":[],"mappings":"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"}
@@ -1134,11 +1134,13 @@ export class Controller {
1134
1134
  lc.sensitivitySeq = (lc.sensitivitySeq ?? 0) + 1;
1135
1135
  lc.sensitivity = null;
1136
1136
  }
1137
- // Multiconductor cases carry their own bus selection (a string id); clear it
1138
- // so an Escape or empty-map click collapses the expanded terminal detail.
1137
+ // Multiconductor cases carry their own bus/edge selection (string ids);
1138
+ // clear both so an Escape or empty-map click collapses the expanded detail.
1139
1139
  const mc = this.app.activeMulti;
1140
- if (mc)
1140
+ if (mc) {
1141
1141
  mc.selectedBusId = null;
1142
+ mc.selectedEdgeId = null;
1143
+ }
1142
1144
  this.app.selectedBus = null;
1143
1145
  this.app.selectedBranch = null;
1144
1146
  this.app.previewDeltaMw = null;
@@ -1671,8 +1673,22 @@ export class Controller {
1671
1673
  this.app.activeLocalId = null;
1672
1674
  this.app.activeMultiId = caseId;
1673
1675
  this.app.placingMultiId = null;
1676
+ c.selectedEdgeId = null;
1674
1677
  c.selectedBusId = c.selectedBusId === busId ? null : busId;
1675
1678
  };
1679
+ /** Select an edge in a multiconductor case: its conductor pairing expands in
1680
+ * the panel. Mutually exclusive with the bus selection. */
1681
+ selectMultiEdge = (caseId, edgeId) => {
1682
+ const c = this.app.multiCases.find((mc) => mc.id === caseId);
1683
+ if (!c)
1684
+ return;
1685
+ this.app.activeCaseId = null;
1686
+ this.app.activeLocalId = null;
1687
+ this.app.activeMultiId = caseId;
1688
+ this.app.placingMultiId = null;
1689
+ c.selectedBusId = null;
1690
+ c.selectedEdgeId = c.selectedEdgeId === edgeId ? null : edgeId;
1691
+ };
1676
1692
  /** Place a multiconductor case awaiting a center: fit its provided planar
1677
1693
  * coordinates when it carries them, else lay it out synthetically. */
1678
1694
  placeMultiCase = (lon, lat) => {
@@ -1695,8 +1711,10 @@ export class Controller {
1695
1711
  };
1696
1712
  removeMultiCase = async (c, event) => {
1697
1713
  event?.stopPropagation();
1698
- if (this.app.activeMultiId === c.id)
1714
+ if (this.app.activeMultiId === c.id) {
1699
1715
  c.selectedBusId = null;
1716
+ c.selectedEdgeId = null;
1717
+ }
1700
1718
  await this.hydrateFallback(this.app.removeMulti(c.id));
1701
1719
  };
1702
1720
  /** The unified map click-to-place: a pending multiconductor case takes the
@@ -56,6 +56,19 @@ export declare function edgeColor(kind: DistEdgeKind, closed: boolean): RGBA;
56
56
  * feeder reads heavier than a single-phase lateral. Transformers draw a touch
57
57
  * wider to stand out as the equipment they are. */
58
58
  export declare function edgeWidth(kind: DistEdgeKind, nPhases: number): number;
59
+ /** A transformer symbol mark at an edge midpoint, angled along the edge.
60
+ * `angle` is degrees counterclockwise from east in the map plane, with the
61
+ * longitude span compressed by cos(latitude) so the symbol tracks the drawn
62
+ * bearing rather than the coordinate-space one. */
63
+ export interface TransformerMark {
64
+ id: string;
65
+ position: [number, number];
66
+ angle: number;
67
+ }
68
+ /** Midpoint marks for the transformer edges of a placed view. Memoized on the
69
+ * edges array, which is stable until the view is replaced, so the map's layer
70
+ * effect can call this every run without regenerating icon attributes. */
71
+ export declare function transformerMarks(edges: PlacedMultiEdge[]): TransformerMark[];
59
72
  /** Badge color for an attachment kind. */
60
73
  export declare function attachmentColor(kind: DistAttachmentKind): RGBA;
61
74
  /** A short glyph for an attachment kind, for the panel legend and badges. */
@@ -1 +1 @@
1
- {"version":3,"file":"multiconductor.d.ts","sourceRoot":"","sources":["../src/lib/multiconductor.ts"],"names":[],"mappings":"AAAA;;;uDAGuD;AAEvD,OAAO,KAAK,EACX,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,mBAAmB,EAGnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,+EAA+E;IAC/E,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;CAC3D;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3C;AAED,wCAAwC;AACxC,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,eAAe,EAAE,CAAC;CACzB;AAwED;kCACkC;AAClC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAM/D;AAsFD;;6BAE6B;AAC7B,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,SAAS,CAKnF;AAgBD;;iEAEiE;AACjE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAcjD;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;gCAEgC;AAChC,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAInE;AAED;;mDAEmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrE;AAUD,0CAA0C;AAC1C,wBAAgB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAE9D;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAahE"}
1
+ {"version":3,"file":"multiconductor.d.ts","sourceRoot":"","sources":["../src/lib/multiconductor.ts"],"names":[],"mappings":"AAAA;;;uDAGuD;AAEvD,OAAO,KAAK,EACX,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,mBAAmB,EAGnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,+EAA+E;IAC/E,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;CAC3D;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3C;AAED,wCAAwC;AACxC,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,eAAe,EAAE,CAAC;CACzB;AAwED;kCACkC;AAClC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAM/D;AA2FD;;6BAE6B;AAC7B,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,SAAS,CAKnF;AAgBD;;iEAEiE;AACjE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAcjD;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;gCAEgC;AAChC,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAInE;AAED;;mDAEmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED;;;mDAGmD;AACnD,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACd;AAID;;0EAE0E;AAC1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAM5E;AAyBD,0CAA0C;AAC1C,wBAAgB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAE9D;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAahE"}
@@ -101,18 +101,21 @@ function projectPlanar(graph, center) {
101
101
  const ys = placed.map((b) => b.xy[1]);
102
102
  const { min: minX, max: maxX } = extent(xs);
103
103
  const { min: minY, max: maxY } = extent(ys);
104
- const sx = maxX - minX || 1;
105
- const sy = maxY - minY || 1;
104
+ // One uniform scale for both axes, so the drawing keeps its aspect ratio
105
+ // instead of being stretched to fill a square.
106
+ const s = 0.92 / Math.max(maxX - minX || 1, maxY - minY || 1);
107
+ const cx = (minX + maxX) / 2;
108
+ const cy = (minY + maxY) / 2;
106
109
  const span = Math.min(4.5, Math.max(0.32, Math.sqrt(Math.max(placed.length, 1)) * 0.08));
107
110
  const lonScale = Math.max(Math.cos((center.lat * Math.PI) / 180), 0.25);
108
111
  const latSpan = span;
109
112
  const lonSpan = span / lonScale;
110
113
  const coords = new Map();
111
114
  for (const bus of placed) {
112
- // Normalize into [0,1] with a small inset, then into the box at center. Y
113
- // is flipped so larger planar y reads as further north.
114
- const nx = 0.04 + ((bus.xy[0] - minX) / sx) * 0.92;
115
- const ny = 0.04 + ((bus.xy[1] - minY) / sy) * 0.92;
115
+ // Center on [0.5, 0.5], then into the box at center. Larger planar y
116
+ // reads as further north.
117
+ const nx = 0.5 + (bus.xy[0] - cx) * s;
118
+ const ny = 0.5 + (bus.xy[1] - cy) * s;
116
119
  coords.set(bus.id, [
117
120
  center.lon + (nx - 0.5) * lonSpan,
118
121
  center.lat + (ny - 0.5) * latSpan
@@ -154,11 +157,13 @@ function toTopology(graph) {
154
157
  };
155
158
  return { topology, idByIndex };
156
159
  }
157
- /** Lay the graph out with the shared synthetic force layout at `center`, then
158
- * map the numeric-id result back to string bus ids. */
160
+ /** Lay the graph out with the shared synthetic layout at `center`, then map
161
+ * the numeric-id result back to string bus ids. Source buses are passed as
162
+ * root hints so a radial feeder's tree layout starts at its substation. */
159
163
  function layoutSynthetic(graph, center) {
160
164
  const { topology, idByIndex } = toTopology(graph);
161
- const placed = placeSyntheticTopology(topology, center);
165
+ const roots = graph.buses.flatMap((b, i) => (b.has_source ? [i] : []));
166
+ const placed = placeSyntheticTopology(topology, center, { roots });
162
167
  const coords = new Map();
163
168
  for (const bus of placed.buses) {
164
169
  const id = idByIndex[bus.id];
@@ -227,6 +232,31 @@ export function edgeWidth(kind, nPhases) {
227
232
  const base = 1.4 + 0.7 * Math.min(Math.max(nPhases, 1), 4);
228
233
  return kind === 'transformer' ? base + 1 : base;
229
234
  }
235
+ const markCache = new WeakMap();
236
+ /** Midpoint marks for the transformer edges of a placed view. Memoized on the
237
+ * edges array, which is stable until the view is replaced, so the map's layer
238
+ * effect can call this every run without regenerating icon attributes. */
239
+ export function transformerMarks(edges) {
240
+ const cached = markCache.get(edges);
241
+ if (cached)
242
+ return cached;
243
+ const marks = computeTransformerMarks(edges);
244
+ markCache.set(edges, marks);
245
+ return marks;
246
+ }
247
+ function computeTransformerMarks(edges) {
248
+ return edges
249
+ .filter((e) => e.kind === 'transformer')
250
+ .map((e) => {
251
+ const [[x0, y0], [x1, y1]] = e.path;
252
+ const latMid = (y0 + y1) / 2;
253
+ return {
254
+ id: e.id,
255
+ position: [(x0 + x1) / 2, latMid],
256
+ angle: (Math.atan2(y1 - y0, (x1 - x0) * Math.cos((latMid * Math.PI) / 180)) * 180) / Math.PI
257
+ };
258
+ });
259
+ }
230
260
  const ATTACHMENT_COLOR = {
231
261
  source: [63, 111, 187, 255],
232
262
  generator: [74, 143, 95, 255],
@@ -169,6 +169,9 @@ export declare class MulticonductorCase {
169
169
  /** The selected bus id, whose terminal stack and incident conductors expand;
170
170
  * null when nothing is selected. String-keyed: distribution bus ids are names. */
171
171
  selectedBusId: string | null;
172
+ /** The selected edge id, whose conductor pairing expands in the panel;
173
+ * mutually exclusive with selectedBusId. */
174
+ selectedEdgeId: string | null;
172
175
  constructor(init: {
173
176
  id: string;
174
177
  label: string;
@@ -182,6 +185,8 @@ export declare class MulticonductorCase {
182
185
  get placed(): boolean;
183
186
  /** The selected bus's placed detail, or null. */
184
187
  get selectedBus(): import("./multiconductor.js").PlacedMultiBus | null;
188
+ /** The selected edge's placed detail, or null. */
189
+ get selectedEdge(): import("./multiconductor.js").PlacedMultiEdge | null;
185
190
  }
186
191
  export declare class AppState {
187
192
  #private;
@@ -229,6 +234,19 @@ export declare class AppState {
229
234
  placingMultiId: string | null;
230
235
  dragOver: boolean;
231
236
  parsingFile: boolean;
237
+ /** True under `(max-width: 760px)`; the panel renders as a bottom sheet. Set by
238
+ * the shell from one media query so panel and map read the same value. */
239
+ compactLayout: boolean;
240
+ /** Height in px the bottom sheet covers; 0 when `compactLayout` is false.
241
+ * Read by the map's camera padding and by chrome anchored above the sheet. */
242
+ sheetInset: number;
243
+ /** Height in px the header covers at the top of the map, measured by
244
+ * `AppHeader`. Wrapping the case tabs onto their own row roughly doubles it,
245
+ * so callers that need to clear the header read this rather than a constant. */
246
+ headerInset: number;
247
+ /** `window.innerHeight`, tracked by the shell. The sheet's snaps and the map's
248
+ * chrome lift are both fractions of it; the fallback is a desktop window. */
249
+ viewportHeight: number;
232
250
  /** Map framing request: bump seq so repeat targets still fly. `requestFrame`
233
251
  * returns a promise the map resolves when the camera lands (or immediately
234
252
  * when it cannot fly), so a caller can defer heavy work until the animation
@@ -1 +1 @@
1
- {"version":3,"file":"state.svelte.d.ts","sourceRoot":"","sources":["../src/lib/state.svelte.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state.svelte.d.ts","sourceRoot":"","sources":["../src/lib/state.svelte.ts"],"names":[],"mappings":"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"}
@@ -124,6 +124,9 @@ export class MulticonductorCase {
124
124
  /** The selected bus id, whose terminal stack and incident conductors expand;
125
125
  * null when nothing is selected. String-keyed: distribution bus ids are names. */
126
126
  selectedBusId = $state(null);
127
+ /** The selected edge id, whose conductor pairing expands in the panel;
128
+ * mutually exclusive with selectedBusId. */
129
+ selectedEdgeId = $state(null);
127
130
  constructor(init) {
128
131
  this.id = init.id;
129
132
  this.label = init.label;
@@ -143,6 +146,12 @@ export class MulticonductorCase {
143
146
  return null;
144
147
  return this.view?.buses.find((b) => b.id === this.selectedBusId) ?? null;
145
148
  }
149
+ /** The selected edge's placed detail, or null. */
150
+ get selectedEdge() {
151
+ if (this.selectedEdgeId === null)
152
+ return null;
153
+ return this.view?.edges.find((e) => e.id === this.selectedEdgeId) ?? null;
154
+ }
146
155
  }
147
156
  export class AppState {
148
157
  cases = $state.raw([]);
@@ -191,6 +200,19 @@ export class AppState {
191
200
  placingMultiId = $state(null);
192
201
  dragOver = $state(false);
193
202
  parsingFile = $state(false);
203
+ /** True under `(max-width: 760px)`; the panel renders as a bottom sheet. Set by
204
+ * the shell from one media query so panel and map read the same value. */
205
+ compactLayout = $state(false);
206
+ /** Height in px the bottom sheet covers; 0 when `compactLayout` is false.
207
+ * Read by the map's camera padding and by chrome anchored above the sheet. */
208
+ sheetInset = $state(0);
209
+ /** Height in px the header covers at the top of the map, measured by
210
+ * `AppHeader`. Wrapping the case tabs onto their own row roughly doubles it,
211
+ * so callers that need to clear the header read this rather than a constant. */
212
+ headerInset = $state(64);
213
+ /** `window.innerHeight`, tracked by the shell. The sheet's snaps and the map's
214
+ * chrome lift are both fractions of it; the fallback is a desktop window. */
215
+ viewportHeight = $state(800);
194
216
  /** Map framing request: bump seq so repeat targets still fly. `requestFrame`
195
217
  * returns a promise the map resolves when the camera lands (or immediately
196
218
  * when it cannot fly), so a caller can defer heavy work until the animation
package/dist/styles.css CHANGED
@@ -372,11 +372,25 @@ a {
372
372
  /* Coarse pointers: comfortable hit targets for the toggle and reset controls. */
373
373
  @media (hover: none), (pointer: coarse) {
374
374
  .segment button {
375
- min-height: 36px;
375
+ min-height: 44px;
376
376
  }
377
377
 
378
378
  .reset {
379
- min-height: 36px;
379
+ min-height: 44px;
380
+ }
381
+
382
+ /* Keep the chip visually small next to its short siblings; the ::before pads
383
+ the tap target out to 44px, as .case-remove does in AppHeader. */
384
+ .mode > button {
385
+ position: relative;
386
+ min-height: 28px;
387
+ padding-inline: 10px;
388
+ }
389
+
390
+ .mode > button::before {
391
+ content: '';
392
+ position: absolute;
393
+ inset: -8px -4px;
380
394
  }
381
395
  }
382
396
 
@@ -8,5 +8,7 @@ export interface PlacementCenter {
8
8
  lon: number;
9
9
  lat: number;
10
10
  }
11
- export declare function placeSyntheticTopology(topology: Topology, center: PlacementCenter): PlacedNetwork;
11
+ export declare function placeSyntheticTopology(topology: Topology, center: PlacementCenter, opts?: {
12
+ roots?: number[];
13
+ }): PlacedNetwork;
12
14
  //# sourceMappingURL=synthetic-layout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"synthetic-layout.d.ts","sourceRoot":"","sources":["../src/lib/synthetic-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACZ;AAKD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,GAAG,aAAa,CAuCjG"}
1
+ {"version":3,"file":"synthetic-layout.d.ts","sourceRoot":"","sources":["../src/lib/synthetic-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACZ;AAKD,wBAAgB,sBAAsB,CACrC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,eAAe,EACvB,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACzB,aAAa,CA6Cf"}
@@ -1,13 +1,17 @@
1
1
  import { extent } from './format.js';
2
2
  const ALL_PAIRS_LIMIT = 500;
3
- export function placeSyntheticTopology(topology, center) {
3
+ export function placeSyntheticTopology(topology, center, opts) {
4
4
  const buses = [...topology.buses].sort((a, b) => a.id - b.id);
5
5
  const index = new Map(buses.map((bus, i) => [bus.id, i]));
6
6
  const edges = topology.branches
7
7
  .filter((branch) => branch.status !== 0 && index.has(branch.from) && index.has(branch.to))
8
8
  .map((branch) => [index.get(branch.from), index.get(branch.to)])
9
9
  .filter(([from, to]) => from !== to);
10
- const unit = forceLayout(buses.length, edges);
10
+ const roots = new Set((opts?.roots ?? []).flatMap((id) => {
11
+ const i = index.get(id);
12
+ return i === undefined ? [] : [i];
13
+ }));
14
+ const unit = forceLayout(buses.length, edges, roots);
11
15
  const span = Math.min(4.5, Math.max(0.32, Math.sqrt(Math.max(buses.length, 1)) * 0.08));
12
16
  const lonScale = Math.max(Math.cos((center.lat * Math.PI) / 180), 0.25);
13
17
  const latSpan = span;
@@ -38,13 +42,27 @@ export function placeSyntheticTopology(topology, center) {
38
42
  }))
39
43
  };
40
44
  }
41
- function forceLayout(n, edges) {
45
+ function forceLayout(n, edges, roots) {
42
46
  if (n === 0)
43
47
  return [];
44
48
  if (n === 1)
45
49
  return [{ x: 0.5, y: 0.5 }];
50
+ // Distribution feeders are trees (or nearly so once open ties drop out, and
51
+ // those are filtered by status before this point). A force pass turns a
52
+ // deep radial feeder into an illegible tangle; a tidy tree reads like the
53
+ // one-line diagram an engineer expects. Tolerate a couple of closed loops:
54
+ // their chord edges simply draw between the placed endpoints.
55
+ const adjacency = graph(n, edges);
56
+ const components = connectedComponents(adjacency);
57
+ let degreeSum = 0;
58
+ for (const neighbors of adjacency)
59
+ degreeSum += neighbors.length;
60
+ const cycles = degreeSum / 2 - (n - components.length);
61
+ if (cycles <= Math.max(2, Math.ceil(0.02 * n))) {
62
+ return treeLayout(n, adjacency, components, roots ?? new Set());
63
+ }
46
64
  if (n > ALL_PAIRS_LIMIT)
47
- return fastGraphLayout(n, edges);
65
+ return fastGraphLayout(n, adjacency, components);
48
66
  const golden = Math.PI * (3 - Math.sqrt(5));
49
67
  const pos = Array.from({ length: n }, (_, i) => {
50
68
  const r = 0.44 * Math.sqrt((i + 0.5) / n);
@@ -93,9 +111,7 @@ function forceLayout(n, edges) {
93
111
  }
94
112
  return normalize(pos);
95
113
  }
96
- function fastGraphLayout(n, edges) {
97
- const adjacency = graph(n, edges);
98
- const components = connectedComponents(adjacency);
114
+ function fastGraphLayout(n, adjacency, components) {
99
115
  const cols = Math.ceil(Math.sqrt(components.length));
100
116
  const rows = Math.ceil(components.length / cols);
101
117
  const pos = Array.from({ length: n }, () => ({ x: 0.5, y: 0.5 }));
@@ -117,6 +133,105 @@ function fastGraphLayout(n, edges) {
117
133
  }
118
134
  return normalize(pos);
119
135
  }
136
+ /** Tidy tree layout for radial (or near-radial) graphs: depth grows along x
137
+ * from the root, and each subtree occupies its own contiguous band of leaf
138
+ * slots along y, so the drawing is planar by construction. The root is a
139
+ * hinted source bus when one exists, else a BFS diameter endpoint, and a
140
+ * node's slot equals the start of its slot interval, so the deepest chain of
141
+ * first children renders as a straight trunk. Deterministic: every ordering
142
+ * below is total, and there is no RNG. */
143
+ function treeLayout(n, adjacency, components, roots) {
144
+ const pos = Array.from({ length: n }, () => ({ x: 0, y: 0 }));
145
+ let slotCursor = 0;
146
+ for (const comp of components) {
147
+ const hinted = comp.filter((node) => roots.has(node));
148
+ const root = hinted.length > 0 ? Math.min(...hinted) : diameterEndpoint(comp[0], adjacency);
149
+ // BFS spanning tree from the root; chords of a near-tree are simply not
150
+ // tree edges and draw between wherever their endpoints land.
151
+ const parent = new Map();
152
+ const depth = new Map();
153
+ const order = [root];
154
+ parent.set(root, -1);
155
+ depth.set(root, 0);
156
+ for (let head = 0; head < order.length; head++) {
157
+ const node = order[head];
158
+ for (const next of adjacency[node]) {
159
+ if (depth.has(next))
160
+ continue;
161
+ parent.set(next, node);
162
+ depth.set(next, depth.get(node) + 1);
163
+ order.push(next);
164
+ }
165
+ }
166
+ const children = new Map(order.map((node) => [node, []]));
167
+ for (const node of order) {
168
+ const p = parent.get(node);
169
+ if (p >= 0)
170
+ children.get(p).push(node);
171
+ }
172
+ // Subtree metrics, children before parents via the reversed BFS order.
173
+ const leaves = new Map();
174
+ const height = new Map();
175
+ for (let i = order.length - 1; i >= 0; i--) {
176
+ const node = order[i];
177
+ const kids = children.get(node);
178
+ let leafCount = 0;
179
+ let maxHeight = -1;
180
+ for (const kid of kids) {
181
+ leafCount += leaves.get(kid);
182
+ maxHeight = Math.max(maxHeight, height.get(kid));
183
+ }
184
+ leaves.set(node, kids.length === 0 ? 1 : leafCount);
185
+ height.set(node, maxHeight + 1);
186
+ }
187
+ // Tallest subtree first, so the trunk continues straight and laterals
188
+ // hang off it in size order.
189
+ for (const node of order) {
190
+ children
191
+ .get(node)
192
+ .sort((a, b) => height.get(b) - height.get(a) || leaves.get(b) - leaves.get(a) || a - b);
193
+ }
194
+ // Pre-order slot intervals: a node sits at the start of its interval,
195
+ // which its first child inherits, so trunk chains share one slot.
196
+ const stack = [[root, slotCursor]];
197
+ while (stack.length > 0) {
198
+ const [node, lo] = stack.pop();
199
+ pos[node] = { x: depth.get(node), y: lo + 0.5 };
200
+ const kids = children.get(node);
201
+ let start = lo;
202
+ const starts = kids.map((kid) => {
203
+ const s = start;
204
+ start += leaves.get(kid);
205
+ return s;
206
+ });
207
+ for (let i = kids.length - 1; i >= 0; i--)
208
+ stack.push([kids[i], starts[i]]);
209
+ }
210
+ slotCursor += leaves.get(root) + 1;
211
+ }
212
+ return normalize(pos);
213
+ }
214
+ /** The far endpoint of a BFS from `start`: the deepest node, smallest id on
215
+ * ties. One end of (an approximation of) the graph diameter, the natural trunk
216
+ * tip when no source bus is hinted. */
217
+ function diameterEndpoint(start, adjacency) {
218
+ const depth = new Map([[start, 0]]);
219
+ const queue = [start];
220
+ let best = start;
221
+ for (let head = 0; head < queue.length; head++) {
222
+ const node = queue[head];
223
+ const d = depth.get(node);
224
+ if (d > depth.get(best) || (d === depth.get(best) && node < best))
225
+ best = node;
226
+ for (const next of adjacency[node]) {
227
+ if (depth.has(next))
228
+ continue;
229
+ depth.set(next, d + 1);
230
+ queue.push(next);
231
+ }
232
+ }
233
+ return best;
234
+ }
120
235
  function graph(n, edges) {
121
236
  const adjacency = Array.from({ length: n }, () => []);
122
237
  const seen = new Set();
@@ -256,14 +371,18 @@ function relaxEdges(pos, initial, edges) {
256
371
  }
257
372
  }
258
373
  }
374
+ /** Fit into the unit box with one uniform scale, centered, so the layout keeps
375
+ * its aspect ratio: a long feeder stays long instead of being stretched to a
376
+ * square. */
259
377
  function normalize(pos) {
260
378
  const { min: minX, max: maxX } = extent(pos.map((p) => p.x));
261
379
  const { min: minY, max: maxY } = extent(pos.map((p) => p.y));
262
- const sx = maxX - minX || 1;
263
- const sy = maxY - minY || 1;
380
+ const s = 0.92 / Math.max(maxX - minX || 1, maxY - minY || 1);
381
+ const cx = (minX + maxX) / 2;
382
+ const cy = (minY + maxY) / 2;
264
383
  return pos.map((p) => ({
265
- x: 0.04 + ((p.x - minX) / sx) * 0.92,
266
- y: 0.04 + ((p.y - minY) / sy) * 0.92
384
+ x: 0.5 + (p.x - cx) * s,
385
+ y: 0.5 + (p.y - cy) * s
267
386
  }));
268
387
  }
269
388
  function clamp(v) {
@@ -0,0 +1,16 @@
1
+ /** The IEC two-winding transformer symbol as a deck.gl icon: two overlapping
2
+ * circles, rasterized once to a data URL. Drawn white on transparent with
3
+ * `mask: true`, so the layer's getColor tints it. */
4
+ export interface TransformerIcon {
5
+ url: string;
6
+ width: number;
7
+ height: number;
8
+ anchorX: number;
9
+ anchorY: number;
10
+ mask: true;
11
+ }
12
+ /** Rasterize the glyph lazily; layers only build client-side, after the map
13
+ * modules load, so document is always available here. The 128 px backing keeps
14
+ * a ~16 px on-screen symbol crisp on 2x/3x displays. */
15
+ export declare function transformerIcon(): TransformerIcon;
16
+ //# sourceMappingURL=transformer-icon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformer-icon.d.ts","sourceRoot":"","sources":["../src/lib/transformer-icon.ts"],"names":[],"mappings":"AAAA;;qDAEqD;AAErD,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;CACX;AASD;;wDAEwD;AACxD,wBAAgB,eAAe,IAAI,eAAe,CAsBjD"}
@@ -0,0 +1,35 @@
1
+ /** The IEC two-winding transformer symbol as a deck.gl icon: two overlapping
2
+ * circles, rasterized once to a data URL. Drawn white on transparent with
3
+ * `mask: true`, so the layer's getColor tints it. */
4
+ const SIZE = 128;
5
+ const RADIUS = 34;
6
+ const OFFSET = 17;
7
+ const STROKE = 9;
8
+ let cached = null;
9
+ /** Rasterize the glyph lazily; layers only build client-side, after the map
10
+ * modules load, so document is always available here. The 128 px backing keeps
11
+ * a ~16 px on-screen symbol crisp on 2x/3x displays. */
12
+ export function transformerIcon() {
13
+ if (cached)
14
+ return cached;
15
+ const canvas = document.createElement('canvas');
16
+ canvas.width = SIZE;
17
+ canvas.height = SIZE;
18
+ const ctx = canvas.getContext('2d');
19
+ ctx.strokeStyle = '#fff';
20
+ ctx.lineWidth = STROKE;
21
+ for (const dx of [-OFFSET, OFFSET]) {
22
+ ctx.beginPath();
23
+ ctx.arc(SIZE / 2 + dx, SIZE / 2, RADIUS, 0, 2 * Math.PI);
24
+ ctx.stroke();
25
+ }
26
+ cached = {
27
+ url: canvas.toDataURL(),
28
+ width: SIZE,
29
+ height: SIZE,
30
+ anchorX: SIZE / 2,
31
+ anchorY: SIZE / 2,
32
+ mask: true
33
+ };
34
+ return cached;
35
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellegen/svelte",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Svelte components for tellegen power system maps, local case files, and browser solves.",
5
5
  "license": "MIT",
6
6
  "type": "module",