@tellegen/svelte 0.2.0 → 0.3.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/README.md +36 -5
- package/dist/TellegenMap.svelte +325 -163
- package/dist/TellegenProvider.svelte +4 -0
- package/dist/TellegenShell.svelte +19 -13
- package/dist/api.d.ts +8 -1
- package/dist/api.js +6 -2
- package/dist/colors.d.ts +7 -7
- package/dist/colors.js +13 -13
- package/dist/components/AppHeader.svelte +23 -11
- package/dist/components/BindingLines.svelte +3 -6
- package/dist/components/BusPicker.svelte +8 -2
- package/dist/components/ControlPanel.svelte +106 -343
- package/dist/components/DemandSlider.svelte +21 -23
- package/dist/components/DiagramCanvas.svelte +486 -0
- package/dist/components/DiagramCanvas.svelte.d.ts +13 -0
- package/dist/components/DisplayControls.svelte +4 -2
- package/dist/components/FormulationSelector.svelte +8 -3
- package/dist/components/LocalCaseDetails.svelte +55 -45
- package/dist/components/McResults.svelte +365 -0
- package/dist/components/McResults.svelte.d.ts +11 -0
- package/dist/components/ModelDetails.svelte +230 -0
- package/dist/components/ModelDetails.svelte.d.ts +7 -0
- package/dist/components/MulticonductorDetails.svelte +227 -78
- package/dist/components/NetworkStats.svelte +20 -18
- package/dist/components/NotificationCenter.svelte +243 -0
- package/dist/components/NotificationCenter.svelte.d.ts +3 -0
- package/dist/components/PanelCard.svelte +319 -0
- package/dist/components/PanelCard.svelte.d.ts +9 -0
- package/dist/components/PanelFrame.svelte +46 -0
- package/dist/components/PanelFrame.svelte.d.ts +16 -0
- package/dist/components/PanelHost.svelte +212 -0
- package/dist/components/PanelHost.svelte.d.ts +3 -0
- package/dist/components/PowerFlowDetails.svelte +99 -0
- package/dist/components/PowerFlowDetails.svelte.d.ts +3 -0
- package/dist/components/RatingSlider.svelte +5 -9
- package/dist/components/SavedNetworkDetails.svelte +214 -0
- package/dist/components/SavedNetworkDetails.svelte.d.ts +3 -0
- package/dist/components/SensitivityReadout.svelte +24 -16
- package/dist/components/SolveCard.svelte +46 -49
- package/dist/components/TopMovers.svelte +8 -3
- package/dist/components/TopMovers.svelte.d.ts +2 -17
- package/dist/components.d.ts +2 -0
- package/dist/components.js +2 -0
- package/dist/controller.svelte.d.ts +54 -33
- package/dist/controller.svelte.js +927 -233
- package/dist/diagram-labels.d.ts +9 -0
- package/dist/diagram-labels.js +40 -0
- package/dist/display.d.ts +3 -7
- package/dist/display.js +31 -27
- package/dist/format.js +5 -4
- package/dist/index.d.ts +10 -4
- package/dist/index.js +7 -2
- package/dist/map.d.ts +1 -1
- package/dist/map.js +1 -1
- package/dist/multiconductor.d.ts +11 -2
- package/dist/multiconductor.js +107 -14
- package/dist/notices.svelte.d.ts +29 -0
- package/dist/notices.svelte.js +82 -0
- package/dist/panels.svelte.d.ts +65 -0
- package/dist/panels.svelte.js +215 -0
- package/dist/state.svelte.d.ts +90 -23
- package/dist/state.svelte.js +94 -20
- package/dist/synthetic-layout.js +1 -0
- package/package.json +22 -9
- package/dist/study-package.d.ts +0 -8
- package/dist/study-package.js +0 -17
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
const KEY = Symbol('tellegen.panel-layout');
|
|
3
|
+
const STORAGE_KEY = 'tellegen.panel-layout.v1';
|
|
4
|
+
export const PANEL_BREAKPOINT = 960;
|
|
5
|
+
export const PANEL_MIN_DOCK_HEIGHT = 500;
|
|
6
|
+
export const PANEL_COMPACT_QUERY = `(max-width: ${PANEL_BREAKPOINT}px), (max-height: ${PANEL_MIN_DOCK_HEIGHT - 1}px)`;
|
|
7
|
+
/** Layout belongs to one provider and stores presentation preferences only. */
|
|
8
|
+
export class PanelLayout {
|
|
9
|
+
panels = $state.raw([]);
|
|
10
|
+
placements = $state({});
|
|
11
|
+
compact = $state(false);
|
|
12
|
+
drawer = $state('network');
|
|
13
|
+
lastActive = $state('network');
|
|
14
|
+
dockActive = $state({ left: 'network', right: 'solver' });
|
|
15
|
+
viewportWidth = $state(1280);
|
|
16
|
+
viewportHeight = $state(800);
|
|
17
|
+
top = $state(100);
|
|
18
|
+
bottom = $state(88);
|
|
19
|
+
storageError = $state(null);
|
|
20
|
+
#storage;
|
|
21
|
+
#gesture = null;
|
|
22
|
+
beginGesture(panel, kind, x, y, bounds) {
|
|
23
|
+
this.#gesture = { panel, kind, x, y, bounds, moved: false };
|
|
24
|
+
}
|
|
25
|
+
moveGesture(x, y) {
|
|
26
|
+
const gesture = this.#gesture;
|
|
27
|
+
if (!gesture)
|
|
28
|
+
return;
|
|
29
|
+
const dx = x - gesture.x, dy = y - gesture.y;
|
|
30
|
+
if (!gesture.moved && Math.hypot(dx, dy) < 4)
|
|
31
|
+
return;
|
|
32
|
+
gesture.moved = true;
|
|
33
|
+
this.float(gesture.panel, gesture.kind === 'move'
|
|
34
|
+
? {
|
|
35
|
+
...gesture.bounds,
|
|
36
|
+
x: gesture.bounds.x + dx,
|
|
37
|
+
y: gesture.bounds.y + dy
|
|
38
|
+
}
|
|
39
|
+
: {
|
|
40
|
+
...gesture.bounds,
|
|
41
|
+
width: gesture.bounds.width + dx,
|
|
42
|
+
height: gesture.bounds.height + dy
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
finishGesture() {
|
|
46
|
+
if (this.#gesture?.moved)
|
|
47
|
+
this.save();
|
|
48
|
+
this.#gesture = null;
|
|
49
|
+
}
|
|
50
|
+
register(panel) {
|
|
51
|
+
this.panels = [...this.panels.filter((p) => p.id !== panel.id), panel];
|
|
52
|
+
return () => {
|
|
53
|
+
this.panels = this.panels.filter((p) => p.id !== panel.id);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
update(id, open, title, width) {
|
|
57
|
+
const previous = this.panels.find((p) => p.id === id);
|
|
58
|
+
if (!previous ||
|
|
59
|
+
(previous.open === open && previous.title === title && previous.width === width))
|
|
60
|
+
return;
|
|
61
|
+
this.panels = this.panels.map((p) => (p.id === id ? { ...p, open, title, width } : p));
|
|
62
|
+
if (open && !previous.open) {
|
|
63
|
+
this.activate(previous);
|
|
64
|
+
if (this.compact)
|
|
65
|
+
this.drawer = id;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
activate(panel) {
|
|
69
|
+
this.lastActive = panel.id;
|
|
70
|
+
const side = this.position(panel);
|
|
71
|
+
if (side !== 'floating')
|
|
72
|
+
this.dockActive[side] = panel.id;
|
|
73
|
+
}
|
|
74
|
+
preferred(panel) {
|
|
75
|
+
const side = this.position(panel);
|
|
76
|
+
if (side === 'floating')
|
|
77
|
+
return false;
|
|
78
|
+
const open = this.ordered(side).filter((candidate) => candidate.open);
|
|
79
|
+
const selected = open.find((candidate) => candidate.id === this.dockActive[side]) ?? open[0];
|
|
80
|
+
return selected?.id === panel.id;
|
|
81
|
+
}
|
|
82
|
+
position(panel) {
|
|
83
|
+
return this.placements[panel.id]?.position ?? panel.side;
|
|
84
|
+
}
|
|
85
|
+
ordered(side) {
|
|
86
|
+
return this.panels
|
|
87
|
+
.filter((p) => side === undefined || this.position(p) === side)
|
|
88
|
+
.sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
|
|
89
|
+
}
|
|
90
|
+
toggle(panel) {
|
|
91
|
+
if (this.compact) {
|
|
92
|
+
this.drawer = this.drawer === panel.id ? null : panel.id;
|
|
93
|
+
if (this.drawer === panel.id) {
|
|
94
|
+
this.activate(panel);
|
|
95
|
+
panel.setOpen(true);
|
|
96
|
+
panel.onopen?.();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
if (!panel.open)
|
|
101
|
+
this.activate(panel);
|
|
102
|
+
panel.setOpen(!panel.open);
|
|
103
|
+
if (!panel.open)
|
|
104
|
+
panel.onopen?.();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
close(panel) {
|
|
108
|
+
panel.setOpen(false);
|
|
109
|
+
if (this.drawer === panel.id)
|
|
110
|
+
this.drawer = null;
|
|
111
|
+
}
|
|
112
|
+
dock(panel, side = panel.side) {
|
|
113
|
+
this.placements[panel.id] = { ...this.bounds(panel), position: side };
|
|
114
|
+
this.activate(panel);
|
|
115
|
+
this.save();
|
|
116
|
+
}
|
|
117
|
+
float(panel, bounds) {
|
|
118
|
+
this.placements[panel.id] = {
|
|
119
|
+
...this.clamp(bounds ?? this.bounds(panel)),
|
|
120
|
+
position: 'floating'
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
bounds(panel) {
|
|
124
|
+
return this.clamp(this.placements[panel.id] ?? {
|
|
125
|
+
x: panel.side === 'left' ? 24 : this.viewportWidth - panel.width - 24,
|
|
126
|
+
y: this.top + 16,
|
|
127
|
+
width: panel.width,
|
|
128
|
+
height: Math.min(520, this.viewportHeight - this.top - this.bottom - 22)
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
clamp(bounds) {
|
|
132
|
+
const availableWidth = Math.max(1, this.viewportWidth - 32);
|
|
133
|
+
const availableHeight = Math.max(1, this.viewportHeight - this.top - this.bottom - 12);
|
|
134
|
+
const width = Math.min(availableWidth, Math.max(240, bounds.width));
|
|
135
|
+
const height = Math.min(availableHeight, Math.max(120, bounds.height));
|
|
136
|
+
return {
|
|
137
|
+
width,
|
|
138
|
+
height,
|
|
139
|
+
x: Math.max(16, Math.min(bounds.x, this.viewportWidth - width - 16)),
|
|
140
|
+
y: Math.max(this.top, Math.min(bounds.y, this.viewportHeight - height - this.bottom))
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
resizeViewport(width, height, top) {
|
|
144
|
+
this.viewportWidth = width;
|
|
145
|
+
this.viewportHeight = height;
|
|
146
|
+
this.top = top;
|
|
147
|
+
const wasCompact = this.compact;
|
|
148
|
+
this.compact = width <= PANEL_BREAKPOINT || height < PANEL_MIN_DOCK_HEIGHT;
|
|
149
|
+
if (this.compact && !wasCompact && this.panels.length > 0) {
|
|
150
|
+
const latest = this.panels.find((panel) => panel.id === this.lastActive && panel.open);
|
|
151
|
+
this.drawer = latest?.id ?? this.panels.find((panel) => panel.open)?.id ?? null;
|
|
152
|
+
}
|
|
153
|
+
for (const [id, panel] of Object.entries(this.placements)) {
|
|
154
|
+
if (panel.position === 'floating')
|
|
155
|
+
this.placements[id] = { ...this.clamp(panel), position: 'floating' };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
dockWidth(side) {
|
|
159
|
+
const panels = this.ordered(side).filter((p) => p.open);
|
|
160
|
+
return panels.length
|
|
161
|
+
? Math.min(Math.max(...panels.map((p) => p.width)), this.viewportWidth * 0.29)
|
|
162
|
+
: 0;
|
|
163
|
+
}
|
|
164
|
+
reset() {
|
|
165
|
+
this.placements = {};
|
|
166
|
+
this.save();
|
|
167
|
+
}
|
|
168
|
+
initialize(storage) {
|
|
169
|
+
this.#storage = storage;
|
|
170
|
+
if (!storage)
|
|
171
|
+
return;
|
|
172
|
+
try {
|
|
173
|
+
const text = storage.getItem(STORAGE_KEY);
|
|
174
|
+
if (!text)
|
|
175
|
+
return;
|
|
176
|
+
const value = JSON.parse(text);
|
|
177
|
+
if (value.version !== 1 || !value.panels || typeof value.panels !== 'object')
|
|
178
|
+
return;
|
|
179
|
+
for (const [id, panel] of Object.entries(value.panels)) {
|
|
180
|
+
if (!panel ||
|
|
181
|
+
!['left', 'right', 'floating'].includes(panel.position) ||
|
|
182
|
+
!['x', 'y', 'width', 'height'].every((key) => Number.isFinite(panel[key])))
|
|
183
|
+
continue;
|
|
184
|
+
this.placements[id] = {
|
|
185
|
+
...this.clamp(panel),
|
|
186
|
+
position: panel.position
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
this.storageError = 'Panel layout could not be restored. Reset layout to use the defaults.';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
save() {
|
|
195
|
+
if (!this.#storage)
|
|
196
|
+
return;
|
|
197
|
+
try {
|
|
198
|
+
this.#storage.setItem(STORAGE_KEY, JSON.stringify({
|
|
199
|
+
version: 1,
|
|
200
|
+
panels: this.placements
|
|
201
|
+
}));
|
|
202
|
+
this.storageError = null;
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
this.storageError = 'Panel layout could not be saved. Changes last for this visit.';
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
export const setPanelLayout = (layout) => setContext(KEY, layout);
|
|
210
|
+
export const getPanelLayout = () => {
|
|
211
|
+
const layout = getContext(KEY);
|
|
212
|
+
if (!layout)
|
|
213
|
+
throw new Error('PanelFrame requires a TellegenProvider');
|
|
214
|
+
return layout;
|
|
215
|
+
};
|
package/dist/state.svelte.d.ts
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
import type { CaseSummary, DemandDeltas, Network, NetworkBranch, NetworkBus, SensitivityColumn, Solution, SolveIteration } from './api.js';
|
|
2
|
-
import { type BranchRatingDeltas, type CaseFileSummary, type DistGraph, type IngestedDistCase, type SensTarget, type Topology } from '@tellegen/engine';
|
|
2
|
+
import { type StudyView, type BranchRatingDeltas, type BrowserMcPfSession, type CaseFileSummary, type DistGraph, type Formulation, type IngestedDistCase, type McPfResult, type McLoadBranchState, type McLoadPowerEdit, type McStudySnapshot, type SensTarget, type Topology } from '@tellegen/engine';
|
|
3
3
|
import type { MultiView } from './multiconductor.js';
|
|
4
4
|
export type SolveBackend = 'clarabel-wasm' | 'clarabel-wasm-server-sensitivity' | 'rust-server';
|
|
5
5
|
/** A map framing request: a case id, 'all', or one branch to center. */
|
|
6
6
|
export type FrameTarget = string | 'all' | {
|
|
7
7
|
caseId: string;
|
|
8
8
|
branchId: number;
|
|
9
|
+
} | {
|
|
10
|
+
caseId: string;
|
|
11
|
+
busId: number;
|
|
9
12
|
};
|
|
13
|
+
export interface CameraSnapshot {
|
|
14
|
+
center: [number, number];
|
|
15
|
+
zoom: number;
|
|
16
|
+
bearing: number;
|
|
17
|
+
pitch: number;
|
|
18
|
+
}
|
|
19
|
+
export interface DiagramCameraSnapshot {
|
|
20
|
+
caseId: string;
|
|
21
|
+
center: [number, number];
|
|
22
|
+
scale: number;
|
|
23
|
+
}
|
|
10
24
|
export type DemandRangeMode = 'local' | 'full';
|
|
11
|
-
export type DisplayMode = '
|
|
25
|
+
export type DisplayMode = 'price' | 'angle' | 'voltage';
|
|
12
26
|
/** The case a removal promoted to active, so the caller can hydrate it: a backend
|
|
13
27
|
* case needs its network/solution loaded, a local needs a browser solve, and
|
|
14
28
|
* `none` means nothing remains (or the removal left the active case untouched). */
|
|
@@ -34,6 +48,7 @@ export interface LocalSubstations {
|
|
|
34
48
|
}
|
|
35
49
|
type CoordsKind = 'file' | 'synthetic_pending' | 'synthetic' | 'manual' | 'geofile';
|
|
36
50
|
type LocalView = {
|
|
51
|
+
coordinate_space?: 'geographic' | 'diagram';
|
|
37
52
|
buses: NetworkBus[];
|
|
38
53
|
branches: NetworkBranch[];
|
|
39
54
|
};
|
|
@@ -42,8 +57,11 @@ export interface LocalCaseInit {
|
|
|
42
57
|
id: string;
|
|
43
58
|
label: string;
|
|
44
59
|
fileName: string;
|
|
60
|
+
formulation?: Formulation;
|
|
61
|
+
declaredFormulation?: Formulation;
|
|
45
62
|
summary?: CaseFileSummary | null;
|
|
46
|
-
|
|
63
|
+
/** Retained PowerIO module used to construct solver studies. */
|
|
64
|
+
studyInputJson?: string;
|
|
47
65
|
topology?: Topology;
|
|
48
66
|
coordsKind?: CoordsKind;
|
|
49
67
|
view?: LocalView | null;
|
|
@@ -59,10 +77,11 @@ export declare class LocalCase {
|
|
|
59
77
|
readonly id: string;
|
|
60
78
|
readonly label: string;
|
|
61
79
|
readonly fileName: string;
|
|
80
|
+
readonly declaredFormulation?: Formulation;
|
|
62
81
|
/** Case stats; null for a .pwd display only entry. */
|
|
63
82
|
summary: CaseFileSummary | null;
|
|
64
|
-
/**
|
|
65
|
-
|
|
83
|
+
/** Generation 2 PowerIO IR used for display edits and solver studies. */
|
|
84
|
+
studyInputJson: string | undefined;
|
|
66
85
|
/** Topology for synthetic placement when the file has no coordinates. */
|
|
67
86
|
topology: Topology | undefined;
|
|
68
87
|
coordsKind: CoordsKind | undefined;
|
|
@@ -72,6 +91,13 @@ export declare class LocalCase {
|
|
|
72
91
|
lon: number;
|
|
73
92
|
lat: number;
|
|
74
93
|
} | undefined;
|
|
94
|
+
diagram: {
|
|
95
|
+
view: LocalView;
|
|
96
|
+
layer: string;
|
|
97
|
+
name: string;
|
|
98
|
+
warnings: string[];
|
|
99
|
+
} | null;
|
|
100
|
+
displayMode: 'geographic' | 'diagram';
|
|
75
101
|
geoSource: string | undefined;
|
|
76
102
|
geoWarnings: string[] | undefined;
|
|
77
103
|
network: Network | null;
|
|
@@ -81,8 +107,7 @@ export declare class LocalCase {
|
|
|
81
107
|
deltas: DemandDeltas;
|
|
82
108
|
/** Committed branch rating deltas (MW from base, keyed by branch). */
|
|
83
109
|
ratings: BranchRatingDeltas;
|
|
84
|
-
/** The
|
|
85
|
-
* full AC OPF, or the SOCWR relaxation. Changing it rebuilds the Study. */
|
|
110
|
+
/** The selected calculation. Changing it rebuilds the numerical Study. */
|
|
86
111
|
formulation: import("@tellegen/engine").BrowserFormulation;
|
|
87
112
|
iterations: SolveIteration[];
|
|
88
113
|
solving: boolean;
|
|
@@ -91,6 +116,8 @@ export declare class LocalCase {
|
|
|
91
116
|
solveFallbackReason: string | null;
|
|
92
117
|
/** Monotone token: only the latest solve may write this case. */
|
|
93
118
|
solveSeq: number;
|
|
119
|
+
/** Monotone generation for external optimistic concurrency. */
|
|
120
|
+
revisionGeneration: number;
|
|
94
121
|
/** Monotone token: only the latest sensitivity request may write this case. */
|
|
95
122
|
sensitivitySeq: number;
|
|
96
123
|
predictedObjective: number | null;
|
|
@@ -104,9 +131,10 @@ export declare class LocalCase {
|
|
|
104
131
|
export declare class CaseState {
|
|
105
132
|
readonly id: string;
|
|
106
133
|
readonly name: string;
|
|
134
|
+
readonly unavailableReason: string | null;
|
|
107
135
|
network: Network | null;
|
|
108
|
-
/**
|
|
109
|
-
|
|
136
|
+
/** Retained PowerIO module for the browser solver; fetched lazily. */
|
|
137
|
+
studyInputJson: string | null;
|
|
110
138
|
/** Boot solution at base demand; never changes. */
|
|
111
139
|
baseSolution: Solution | null;
|
|
112
140
|
/** Exact solution at the current committed perturbation. */
|
|
@@ -126,6 +154,8 @@ export declare class CaseState {
|
|
|
126
154
|
solveFallbackReason: string | null;
|
|
127
155
|
/** Monotone token: only the latest solve may write this case. */
|
|
128
156
|
solveSeq: number;
|
|
157
|
+
/** Monotone generation for external optimistic concurrency. */
|
|
158
|
+
revisionGeneration: number;
|
|
129
159
|
/** Monotone token: only the latest sensitivity request may write this case. */
|
|
130
160
|
sensitivitySeq: number;
|
|
131
161
|
/** Closer for this case's in-flight server solve stream, if any. Owned per
|
|
@@ -140,27 +170,39 @@ export declare class CaseState {
|
|
|
140
170
|
/** A case the solver can run: a server-backed case or a browser-parsed local case. */
|
|
141
171
|
export type SolvableCase = CaseState | LocalCase;
|
|
142
172
|
/** The multiconductor ingest payload without the graph: the summary counts,
|
|
143
|
-
* connected load/generation, coordinate provenance, and
|
|
173
|
+
* connected load/generation, coordinate provenance, and diagnostics. */
|
|
144
174
|
export type MultiCaseSummary = Omit<IngestedDistCase, 'graph'>;
|
|
145
|
-
/**
|
|
146
|
-
* straight on; `planar`/`synthetic` need a map center, so they sit `pending`
|
|
147
|
-
* until the user places them. */
|
|
175
|
+
/** Geographic coordinates use the map; other positions use the diagram canvas. */
|
|
148
176
|
export type MultiCoordsKind = 'geographic' | 'planar' | 'synthetic';
|
|
149
|
-
/** A
|
|
150
|
-
* formulation, no sliders, no Study. It carries the bus/terminal graph, its
|
|
151
|
-
* placed map view, and the selected bus whose terminal detail expands. Fields
|
|
152
|
-
* are reactive like the solvable cases so the panel and map track them. */
|
|
177
|
+
/** A conductor-resolved case with retained electrical inputs and terminal results. */
|
|
153
178
|
export declare class MulticonductorCase {
|
|
154
179
|
readonly id: string;
|
|
155
180
|
readonly label: string;
|
|
156
181
|
readonly fileName: string;
|
|
182
|
+
moduleJson: string | null;
|
|
183
|
+
geoLayer: string | null;
|
|
184
|
+
geoWarnings: string[];
|
|
185
|
+
result: McPfResult | null;
|
|
186
|
+
mcSnapshot: McStudySnapshot | null;
|
|
187
|
+
mcSession: BrowserMcPfSession | null;
|
|
188
|
+
mcLoadBranches: McLoadBranchState[];
|
|
189
|
+
mcLoadEdits: McLoadPowerEdit[];
|
|
190
|
+
mcEditRevision: number;
|
|
191
|
+
mcEditRunning: boolean;
|
|
192
|
+
mcEditTimer: ReturnType<typeof setTimeout> | null;
|
|
193
|
+
mcSavedAt: string | null;
|
|
194
|
+
solving: boolean;
|
|
195
|
+
solveMs: number | null;
|
|
196
|
+
solveSeq: number;
|
|
197
|
+
revisionGeneration: number;
|
|
198
|
+
solveAbort: AbortController | null;
|
|
157
199
|
/** Summary counts and coordinate provenance from the parse. */
|
|
158
200
|
summary: MultiCaseSummary | null;
|
|
159
201
|
/** The render-ready bus/terminal graph. */
|
|
160
202
|
graph: DistGraph | null;
|
|
161
203
|
/** Placement kind resolved at ingest from the case's coordinate space. */
|
|
162
204
|
coordsKind: MultiCoordsKind;
|
|
163
|
-
/** The
|
|
205
|
+
/** The map or diagram positions. */
|
|
164
206
|
view: MultiView | null;
|
|
165
207
|
syntheticCenter: {
|
|
166
208
|
lon: number;
|
|
@@ -181,6 +223,8 @@ export declare class MulticonductorCase {
|
|
|
181
223
|
coordsKind: MultiCoordsKind;
|
|
182
224
|
view?: MultiView | null;
|
|
183
225
|
});
|
|
226
|
+
get mcPfReason(): string | null;
|
|
227
|
+
get mcPfSupported(): boolean;
|
|
184
228
|
/** Whether the case is placed and ready to render. */
|
|
185
229
|
get placed(): boolean;
|
|
186
230
|
/** The selected bus's placed detail, or null. */
|
|
@@ -188,8 +232,30 @@ export declare class MulticonductorCase {
|
|
|
188
232
|
/** The selected edge's placed detail, or null. */
|
|
189
233
|
get selectedEdge(): import("./multiconductor.js").PlacedMultiEdge | null;
|
|
190
234
|
}
|
|
235
|
+
export interface StudyDisplaySnapshot {
|
|
236
|
+
id: string;
|
|
237
|
+
studyId: string;
|
|
238
|
+
caseId: string;
|
|
239
|
+
revision: number;
|
|
240
|
+
label: string;
|
|
241
|
+
formulation: Formulation;
|
|
242
|
+
network: Network;
|
|
243
|
+
solution: StudyView | null;
|
|
244
|
+
inputJson?: string;
|
|
245
|
+
baseDemandMw?: Record<string, number>;
|
|
246
|
+
}
|
|
191
247
|
export declare class AppState {
|
|
192
248
|
#private;
|
|
249
|
+
camera: CameraSnapshot | null;
|
|
250
|
+
cameraRequest: CameraSnapshot | null;
|
|
251
|
+
cameraSeq: number;
|
|
252
|
+
diagramCamera: DiagramCameraSnapshot | null;
|
|
253
|
+
diagramCameraRequest: DiagramCameraSnapshot | null;
|
|
254
|
+
diagramCameraSeq: number;
|
|
255
|
+
requestDiagramCamera(caseId: string, snapshot: Omit<DiagramCameraSnapshot, 'caseId'>): void;
|
|
256
|
+
requestCamera(snapshot: CameraSnapshot): void;
|
|
257
|
+
/** Saved Study inspection is independent of the editable case and its solution. */
|
|
258
|
+
studyView: StudyDisplaySnapshot | null;
|
|
193
259
|
cases: CaseState[];
|
|
194
260
|
activeCaseId: string | null;
|
|
195
261
|
/** Selected bus in the active case. */
|
|
@@ -200,21 +266,22 @@ export declare class AppState {
|
|
|
200
266
|
previewDeltaMw: number | null;
|
|
201
267
|
/** Live rating slider value (MW from base) before commit; null when idle. */
|
|
202
268
|
previewRatingMw: number | null;
|
|
203
|
-
/** True while the demand control should keep the map in
|
|
269
|
+
/** True while the demand control should keep the map in nodal value preview mode. */
|
|
204
270
|
previewActive: boolean;
|
|
205
|
-
/** Engine first
|
|
206
|
-
* ($/MWh) per bus at the previewed edit, scoped to the case and selection
|
|
271
|
+
/** Engine first order nodal value preview for the live drag, scoped to the case and selection
|
|
207
272
|
* target (bus or branch) it was computed for. Set by the Study path; null when
|
|
208
273
|
* no Study preview applies (the map then falls back to the JS
|
|
209
274
|
* sensitivity-times-step preview). Reassigned wholesale, so $state.raw. */
|
|
210
|
-
|
|
275
|
+
previewPrices: {
|
|
211
276
|
caseId: string;
|
|
212
277
|
target: SensTarget;
|
|
213
278
|
delta: Map<number, number>;
|
|
279
|
+
units: string;
|
|
214
280
|
} | null;
|
|
215
281
|
demandRangeMode: DemandRangeMode;
|
|
216
282
|
displayMode: DisplayMode;
|
|
217
283
|
sensitivityLoading: boolean;
|
|
284
|
+
errorRevision: number;
|
|
218
285
|
/** Re-runs the operation behind the current `error`, when one applies. Every
|
|
219
286
|
* write to `error` clears it, so a retry op can never outlive its message. */
|
|
220
287
|
errorRetry: (() => void) | null;
|
|
@@ -225,7 +292,7 @@ export declare class AppState {
|
|
|
225
292
|
/** Local case the panel shows; clicking a bundled case or a bus clears it. */
|
|
226
293
|
activeLocalId: string | null;
|
|
227
294
|
placingLocalId: string | null;
|
|
228
|
-
/** Multiconductor
|
|
295
|
+
/** Multiconductor cases with retained inputs and AC power flow results. */
|
|
229
296
|
multiCases: MulticonductorCase[];
|
|
230
297
|
/** Multiconductor case the panel shows; mutually exclusive with the solvable
|
|
231
298
|
* active ids. */
|