@tellegen/svelte 0.1.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/LICENSE +19 -0
- package/README.md +70 -0
- package/dist/Sparkline.svelte +100 -0
- package/dist/Sparkline.svelte.d.ts +8 -0
- package/dist/Sparkline.svelte.d.ts.map +1 -0
- package/dist/TellegenMap.svelte +1430 -0
- package/dist/TellegenMap.svelte.d.ts +14 -0
- package/dist/TellegenMap.svelte.d.ts.map +1 -0
- package/dist/TellegenProvider.svelte +38 -0
- package/dist/TellegenProvider.svelte.d.ts +9 -0
- package/dist/TellegenProvider.svelte.d.ts.map +1 -0
- package/dist/TellegenShell.svelte +126 -0
- package/dist/TellegenShell.svelte.d.ts +4 -0
- package/dist/TellegenShell.svelte.d.ts.map +1 -0
- package/dist/TellegenViewer.svelte +19 -0
- package/dist/TellegenViewer.svelte.d.ts +4 -0
- package/dist/TellegenViewer.svelte.d.ts.map +1 -0
- package/dist/api.d.ts +44 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +137 -0
- package/dist/colors.d.ts +51 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +140 -0
- package/dist/components/AppFooter.svelte +73 -0
- package/dist/components/AppFooter.svelte.d.ts +19 -0
- package/dist/components/AppFooter.svelte.d.ts.map +1 -0
- package/dist/components/AppHeader.svelte +405 -0
- package/dist/components/AppHeader.svelte.d.ts +4 -0
- package/dist/components/AppHeader.svelte.d.ts.map +1 -0
- package/dist/components/BindingLines.svelte +101 -0
- package/dist/components/BindingLines.svelte.d.ts +4 -0
- package/dist/components/BindingLines.svelte.d.ts.map +1 -0
- package/dist/components/BusPicker.svelte +227 -0
- package/dist/components/BusPicker.svelte.d.ts +4 -0
- package/dist/components/BusPicker.svelte.d.ts.map +1 -0
- package/dist/components/ControlPanel.svelte +154 -0
- package/dist/components/ControlPanel.svelte.d.ts +19 -0
- package/dist/components/ControlPanel.svelte.d.ts.map +1 -0
- package/dist/components/DemandSlider.svelte +271 -0
- package/dist/components/DemandSlider.svelte.d.ts +4 -0
- package/dist/components/DemandSlider.svelte.d.ts.map +1 -0
- package/dist/components/DisplayControls.svelte +81 -0
- package/dist/components/DisplayControls.svelte.d.ts +19 -0
- package/dist/components/DisplayControls.svelte.d.ts.map +1 -0
- package/dist/components/DropZone.svelte +46 -0
- package/dist/components/DropZone.svelte.d.ts +19 -0
- package/dist/components/DropZone.svelte.d.ts.map +1 -0
- package/dist/components/FormulationSelector.svelte +82 -0
- package/dist/components/FormulationSelector.svelte.d.ts +19 -0
- package/dist/components/FormulationSelector.svelte.d.ts.map +1 -0
- package/dist/components/LocalCaseDetails.svelte +253 -0
- package/dist/components/LocalCaseDetails.svelte.d.ts +4 -0
- package/dist/components/LocalCaseDetails.svelte.d.ts.map +1 -0
- package/dist/components/MulticonductorDetails.svelte +280 -0
- package/dist/components/MulticonductorDetails.svelte.d.ts +19 -0
- package/dist/components/MulticonductorDetails.svelte.d.ts.map +1 -0
- package/dist/components/NetworkStats.svelte +75 -0
- package/dist/components/NetworkStats.svelte.d.ts +19 -0
- package/dist/components/NetworkStats.svelte.d.ts.map +1 -0
- package/dist/components/PlacementCue.svelte +35 -0
- package/dist/components/PlacementCue.svelte.d.ts +19 -0
- package/dist/components/PlacementCue.svelte.d.ts.map +1 -0
- package/dist/components/RatingSlider.svelte +273 -0
- package/dist/components/RatingSlider.svelte.d.ts +4 -0
- package/dist/components/RatingSlider.svelte.d.ts.map +1 -0
- package/dist/components/RestoreDefaultsButton.svelte +34 -0
- package/dist/components/RestoreDefaultsButton.svelte.d.ts +19 -0
- package/dist/components/RestoreDefaultsButton.svelte.d.ts.map +1 -0
- package/dist/components/SensitivityReadout.svelte +126 -0
- package/dist/components/SensitivityReadout.svelte.d.ts +4 -0
- package/dist/components/SensitivityReadout.svelte.d.ts.map +1 -0
- package/dist/components/SizeLegend.svelte +55 -0
- package/dist/components/SizeLegend.svelte.d.ts +19 -0
- package/dist/components/SizeLegend.svelte.d.ts.map +1 -0
- package/dist/components/SolveCard.svelte +84 -0
- package/dist/components/SolveCard.svelte.d.ts +4 -0
- package/dist/components/SolveCard.svelte.d.ts.map +1 -0
- package/dist/components/TopMovers.svelte +68 -0
- package/dist/components/TopMovers.svelte.d.ts +19 -0
- package/dist/components/TopMovers.svelte.d.ts.map +1 -0
- package/dist/components.d.ts +19 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +18 -0
- package/dist/context.svelte.d.ts +20 -0
- package/dist/context.svelte.d.ts.map +1 -0
- package/dist/context.svelte.js +43 -0
- package/dist/controller.svelte.d.ts +334 -0
- package/dist/controller.svelte.d.ts.map +1 -0
- package/dist/controller.svelte.js +2026 -0
- package/dist/display.d.ts +31 -0
- package/dist/display.d.ts.map +1 -0
- package/dist/display.js +63 -0
- package/dist/drop-classify.d.ts +48 -0
- package/dist/drop-classify.d.ts.map +1 -0
- package/dist/drop-classify.js +92 -0
- package/dist/format.d.ts +30 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +49 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/map.d.ts +9 -0
- package/dist/map.d.ts.map +1 -0
- package/dist/map.js +4 -0
- package/dist/multiconductor.d.ts +63 -0
- package/dist/multiconductor.d.ts.map +1 -0
- package/dist/multiconductor.js +255 -0
- package/dist/state.svelte.d.ts +258 -0
- package/dist/state.svelte.d.ts.map +1 -0
- package/dist/state.svelte.js +323 -0
- package/dist/study-package.d.ts +9 -0
- package/dist/study-package.d.ts.map +1 -0
- package/dist/study-package.js +17 -0
- package/dist/styles.css +393 -0
- package/dist/synthetic-layout.d.ts +12 -0
- package/dist/synthetic-layout.d.ts.map +1 -0
- package/dist/synthetic-layout.js +271 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getController } from '../context.svelte.js';
|
|
3
|
+
import { fmt, signed } from '../format.js';
|
|
4
|
+
|
|
5
|
+
const ctrl = getController();
|
|
6
|
+
|
|
7
|
+
// Fill from the committed rating to the live thumb. The number line stays
|
|
8
|
+
// stable after release; only the committed tick moves.
|
|
9
|
+
const thumbSizePx = 14;
|
|
10
|
+
const bounds = $derived(ctrl.ratingBounds);
|
|
11
|
+
const sliderSpan = $derived(Math.max(bounds.max - bounds.min, 1e-9));
|
|
12
|
+
const valFrac = $derived(
|
|
13
|
+
Math.max(0, Math.min(1, (ctrl.ratingSliderValue - bounds.min) / sliderSpan))
|
|
14
|
+
);
|
|
15
|
+
const neutralFrac = $derived(
|
|
16
|
+
Math.max(0, Math.min(1, (ctrl.committedRating - bounds.min) / sliderSpan))
|
|
17
|
+
);
|
|
18
|
+
const thumbAlignedPos = (frac: number) =>
|
|
19
|
+
`calc(${frac * 100}% + ${(0.5 - frac) * thumbSizePx}px)`;
|
|
20
|
+
const valPos = $derived(thumbAlignedPos(valFrac));
|
|
21
|
+
const neutralPos = $derived(thumbAlignedPos(neutralFrac));
|
|
22
|
+
const fillLo = $derived(valFrac < neutralFrac ? valPos : neutralPos);
|
|
23
|
+
const fillHi = $derived(valFrac < neutralFrac ? neutralPos : valPos);
|
|
24
|
+
const sliderTip =
|
|
25
|
+
'The black tick marks the last committed rating change. Drag the knob to preview a new thermal rating; release to solve and move the tick to that point.';
|
|
26
|
+
const disabledTip = "this line's rating is synthesized; not adjustable";
|
|
27
|
+
const scoreTip =
|
|
28
|
+
'Gradient is the estimate of total cost change versus base before the solve finishes, from the engine preview at the committed point. Exact is the resolved OPF objective change.';
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
{#if ctrl.activeSolvable}
|
|
32
|
+
{@const c = ctrl.activeSolvable}
|
|
33
|
+
{@const branch = ctrl.selectedBranchData}
|
|
34
|
+
<div class="slider-block">
|
|
35
|
+
<div class="slider-head mono">
|
|
36
|
+
<span>Δ rating</span>
|
|
37
|
+
<span class="val">{signed(ctrl.ratingSliderValue)} MW</span>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="line-row mono">
|
|
40
|
+
{#if branch}
|
|
41
|
+
<span class="dim"
|
|
42
|
+
>line {branch.from} – {branch.to} · {fmt.format(
|
|
43
|
+
branch.rate_mw
|
|
44
|
+
)} MW</span
|
|
45
|
+
>
|
|
46
|
+
{/if}
|
|
47
|
+
<span class="dim">
|
|
48
|
+
{#if bounds.disabled}
|
|
49
|
+
not adjustable
|
|
50
|
+
{:else}
|
|
51
|
+
{fmt.format(bounds.min)} to +{fmt.format(bounds.max)} MW
|
|
52
|
+
{/if}
|
|
53
|
+
</span>
|
|
54
|
+
</div>
|
|
55
|
+
<div
|
|
56
|
+
class="slider-track"
|
|
57
|
+
style="--fill-lo:{fillLo}; --fill-hi:{fillHi}; --neutral-pos:{neutralPos}"
|
|
58
|
+
title={bounds.disabled ? disabledTip : sliderTip}
|
|
59
|
+
>
|
|
60
|
+
<input
|
|
61
|
+
type="range"
|
|
62
|
+
min={bounds.min}
|
|
63
|
+
max={bounds.max}
|
|
64
|
+
step="any"
|
|
65
|
+
disabled={bounds.disabled}
|
|
66
|
+
bind:value={ctrl.ratingSliderCurrent, ctrl.setRatingPreview}
|
|
67
|
+
aria-label="rating delta at selected line"
|
|
68
|
+
onpointerdown={() => ctrl.setRatingPreview(ctrl.ratingSliderValue)}
|
|
69
|
+
onkeydown={() => ctrl.setRatingPreview(ctrl.ratingSliderValue)}
|
|
70
|
+
onpointerup={(e) => ctrl.finishRatingInput(Number(e.currentTarget.value))}
|
|
71
|
+
onkeyup={(e) => ctrl.finishRatingInput(Number(e.currentTarget.value))}
|
|
72
|
+
onchange={(e) => ctrl.finishRatingInput(Number(e.currentTarget.value))}
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="rating-feedback" class:idle={!ctrl.previewing && !ctrl.isPerturbed(c)}>
|
|
76
|
+
<p class="pred mono dim" aria-hidden={!(ctrl.predictedDeltaObj !== null && ctrl.previewing)}>
|
|
77
|
+
{#if ctrl.predictedDeltaObj !== null && ctrl.previewing}
|
|
78
|
+
predicted Δcost {signed(ctrl.predictedDeltaObj)} $/h
|
|
79
|
+
{:else}
|
|
80
|
+
|
|
81
|
+
{/if}
|
|
82
|
+
</p>
|
|
83
|
+
<p class="score mono" aria-hidden={!(ctrl.gradientScore && ctrl.isPerturbed(c))}>
|
|
84
|
+
{#if ctrl.gradientScore && ctrl.isPerturbed(c)}
|
|
85
|
+
<span title={scoreTip}>
|
|
86
|
+
gradient {signed(ctrl.gradientScore.pred)} · exact {signed(
|
|
87
|
+
ctrl.gradientScore.exact
|
|
88
|
+
)}
|
|
89
|
+
$/h
|
|
90
|
+
</span>
|
|
91
|
+
{:else}
|
|
92
|
+
|
|
93
|
+
{/if}
|
|
94
|
+
</p>
|
|
95
|
+
<div class="reset-row">
|
|
96
|
+
{#if ctrl.isPerturbed(c)}
|
|
97
|
+
<button class="reset mono" onclick={() => ctrl.resetCase(c)}>reset rating</button>
|
|
98
|
+
{/if}
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
{/if}
|
|
103
|
+
|
|
104
|
+
<style>
|
|
105
|
+
.slider-block {
|
|
106
|
+
margin-top: 14px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.slider-head {
|
|
110
|
+
display: flex;
|
|
111
|
+
justify-content: space-between;
|
|
112
|
+
font-size: 11.5px;
|
|
113
|
+
color: var(--text-secondary);
|
|
114
|
+
margin-bottom: 4px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.slider-head .val {
|
|
118
|
+
color: var(--ink);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.line-row {
|
|
122
|
+
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
justify-content: space-between;
|
|
125
|
+
gap: 8px;
|
|
126
|
+
margin: 6px 0 7px;
|
|
127
|
+
font-size: 10.5px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.slider-track {
|
|
131
|
+
position: relative;
|
|
132
|
+
margin: 6px 0;
|
|
133
|
+
isolation: isolate;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.slider-track::before {
|
|
137
|
+
content: '';
|
|
138
|
+
position: absolute;
|
|
139
|
+
top: 50%;
|
|
140
|
+
left: var(--neutral-pos, 50%);
|
|
141
|
+
z-index: 0;
|
|
142
|
+
width: 2px;
|
|
143
|
+
height: 16px;
|
|
144
|
+
background: var(--ink);
|
|
145
|
+
border-radius: 1px;
|
|
146
|
+
box-shadow: 0 0 0 1px rgb(var(--paper-rgb) / 0.72);
|
|
147
|
+
transform: translate(-50%, -50%);
|
|
148
|
+
pointer-events: none;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
input[type='range'] {
|
|
152
|
+
-webkit-appearance: none;
|
|
153
|
+
appearance: none;
|
|
154
|
+
position: relative;
|
|
155
|
+
z-index: 1;
|
|
156
|
+
width: 100%;
|
|
157
|
+
height: 4px;
|
|
158
|
+
padding: 7px 0;
|
|
159
|
+
box-sizing: content-box;
|
|
160
|
+
background:
|
|
161
|
+
linear-gradient(
|
|
162
|
+
90deg,
|
|
163
|
+
transparent 0 var(--fill-lo, 0%),
|
|
164
|
+
rgb(var(--accent-rgb) / 0.32) var(--fill-lo, 0%) var(--fill-hi, 0%),
|
|
165
|
+
transparent var(--fill-hi, 0%) 100%
|
|
166
|
+
),
|
|
167
|
+
var(--line);
|
|
168
|
+
background-clip: content-box;
|
|
169
|
+
border-radius: var(--radius-xs);
|
|
170
|
+
outline-offset: 4px;
|
|
171
|
+
margin: 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
input[type='range']:disabled {
|
|
175
|
+
opacity: 0.45;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
input[type='range']::-webkit-slider-thumb {
|
|
179
|
+
-webkit-appearance: none;
|
|
180
|
+
appearance: none;
|
|
181
|
+
width: 14px;
|
|
182
|
+
height: 14px;
|
|
183
|
+
border-radius: 50%;
|
|
184
|
+
background: var(--accent);
|
|
185
|
+
border: 2px solid var(--paper);
|
|
186
|
+
box-shadow: var(--shadow-thumb);
|
|
187
|
+
cursor: ew-resize;
|
|
188
|
+
transition:
|
|
189
|
+
transform var(--dur-fast) var(--ease-out),
|
|
190
|
+
box-shadow var(--dur-fast) var(--ease-out);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
input[type='range']::-moz-range-thumb {
|
|
194
|
+
width: 14px;
|
|
195
|
+
height: 14px;
|
|
196
|
+
border-radius: 50%;
|
|
197
|
+
background: var(--accent);
|
|
198
|
+
border: 2px solid var(--paper);
|
|
199
|
+
box-shadow: var(--shadow-thumb);
|
|
200
|
+
cursor: ew-resize;
|
|
201
|
+
transition:
|
|
202
|
+
transform var(--dur-fast) var(--ease-out),
|
|
203
|
+
box-shadow var(--dur-fast) var(--ease-out);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
input[type='range']:active::-webkit-slider-thumb,
|
|
207
|
+
input[type='range']:focus-visible::-webkit-slider-thumb {
|
|
208
|
+
transform: scale(1.15);
|
|
209
|
+
box-shadow: 0 2px 7px rgb(var(--ink-rgb) / 0.35);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
input[type='range']:active::-moz-range-thumb,
|
|
213
|
+
input[type='range']:focus-visible::-moz-range-thumb {
|
|
214
|
+
transform: scale(1.15);
|
|
215
|
+
box-shadow: 0 2px 7px rgb(var(--ink-rgb) / 0.35);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* Coarse pointers: a larger track and thumb for a comfortable touch target.
|
|
219
|
+
The input's own border box grows to a 44px tap target (padding is symmetric,
|
|
220
|
+
so the thumb -- centered on the input's box by default -- stays centered on
|
|
221
|
+
the thinner painted line); background-clip keeps the visible line itself thin. */
|
|
222
|
+
@media (hover: none), (pointer: coarse) {
|
|
223
|
+
input[type='range'] {
|
|
224
|
+
height: 6px;
|
|
225
|
+
padding: 19px 0;
|
|
226
|
+
box-sizing: content-box;
|
|
227
|
+
background-clip: content-box;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
input[type='range']::-webkit-slider-thumb {
|
|
231
|
+
width: 20px;
|
|
232
|
+
height: 20px;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
input[type='range']::-moz-range-thumb {
|
|
236
|
+
width: 20px;
|
|
237
|
+
height: 20px;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.pred {
|
|
242
|
+
margin: 2px 0 0;
|
|
243
|
+
font-size: 11px;
|
|
244
|
+
min-height: 16px;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.score {
|
|
248
|
+
margin: 8px 0 0;
|
|
249
|
+
font-size: 11px;
|
|
250
|
+
color: var(--ink);
|
|
251
|
+
min-height: 16px;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.rating-feedback {
|
|
255
|
+
min-height: 78px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* On a fresh selection (no preview, no perturbation) the predicted/gradient/
|
|
259
|
+
reset rows are empty; collapse the reserved block so the panel isn't padded
|
|
260
|
+
with whitespace. The reservation returns during interaction to avoid jumps. */
|
|
261
|
+
.rating-feedback.idle {
|
|
262
|
+
min-height: 0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.rating-feedback.idle .pred,
|
|
266
|
+
.rating-feedback.idle .score {
|
|
267
|
+
display: none;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.reset-row {
|
|
271
|
+
min-height: 28px;
|
|
272
|
+
}
|
|
273
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RatingSlider.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/RatingSlider.svelte.ts"],"names":[],"mappings":"AAqFA,QAAA,MAAM,YAAY,2DAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getController, getUiConfig } from '../context.svelte.js';
|
|
3
|
+
|
|
4
|
+
const ctrl = getController();
|
|
5
|
+
const config = getUiConfig();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
{#if config.loadDefaultCases && ctrl.casesLoaded && ctrl.hiddenDefaults.size > 0}
|
|
9
|
+
<button class="restore-defaults mono" onclick={ctrl.restoreDefaultCases}>
|
|
10
|
+
↺ restore default cases
|
|
11
|
+
</button>
|
|
12
|
+
{/if}
|
|
13
|
+
|
|
14
|
+
<style>
|
|
15
|
+
.restore-defaults {
|
|
16
|
+
position: absolute;
|
|
17
|
+
bottom: 34px;
|
|
18
|
+
left: 20px;
|
|
19
|
+
z-index: 10;
|
|
20
|
+
padding: 6px 11px;
|
|
21
|
+
background: var(--panel);
|
|
22
|
+
border: 1px solid var(--line);
|
|
23
|
+
border-radius: 3px;
|
|
24
|
+
color: var(--text-secondary);
|
|
25
|
+
font-size: 11px;
|
|
26
|
+
cursor: pointer;
|
|
27
|
+
box-shadow: 0 2px 10px rgba(32, 36, 43, 0.1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.restore-defaults:hover {
|
|
31
|
+
border-color: var(--accent);
|
|
32
|
+
color: var(--text-accent);
|
|
33
|
+
}
|
|
34
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const RestoreDefaultsButton: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type RestoreDefaultsButton = InstanceType<typeof RestoreDefaultsButton>;
|
|
18
|
+
export default RestoreDefaultsButton;
|
|
19
|
+
//# sourceMappingURL=RestoreDefaultsButton.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RestoreDefaultsButton.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/RestoreDefaultsButton.svelte.ts"],"names":[],"mappings":"AAsBA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,qBAAqB;;kBAA+E,CAAC;AACzF,KAAK,qBAAqB,GAAG,YAAY,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC1E,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { sensGradient } from '../colors.js';
|
|
3
|
+
import { getAppState, getController } from '../context.svelte.js';
|
|
4
|
+
import { signedExp } from '../format.js';
|
|
5
|
+
|
|
6
|
+
const app = getAppState();
|
|
7
|
+
const ctrl = getController();
|
|
8
|
+
const busUnitTitle =
|
|
9
|
+
'LMP is measured in $/MWh and demand is perturbed in MW, so dLMP/dd has units ($/MWh)/MW. ' +
|
|
10
|
+
'DC LMPs move only when a binding constraint changes, so most nudges in this slider range ' +
|
|
11
|
+
'shift prices very little unless the active set changes.';
|
|
12
|
+
const branchUnitTitle =
|
|
13
|
+
'LMP is measured in $/MWh and the rating is perturbed in MVA, so dLMP/dfmax has units ' +
|
|
14
|
+
"($/MWh)/MVA. The column is zero unless the line's limit is binding.";
|
|
15
|
+
|
|
16
|
+
// Branch mode: the selection is a line and the column is ∂LMP/∂rating; the
|
|
17
|
+
// legend and preview pipeline are identical (both columns are bus-keyed).
|
|
18
|
+
const branchMode = $derived(app.selectedBranch !== null);
|
|
19
|
+
const unitTitle = $derived(branchMode ? branchUnitTitle : busUnitTitle);
|
|
20
|
+
const units = $derived(branchMode ? '($/MWh)/MVA' : '($/MWh)/MW');
|
|
21
|
+
|
|
22
|
+
const previewStep = $derived(
|
|
23
|
+
branchMode
|
|
24
|
+
? ctrl.ratingSliderValue - ctrl.committedRating
|
|
25
|
+
: ctrl.sliderValue - ctrl.committedDelta
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Label the selected line by its bus pair, matching BindingLines and
|
|
29
|
+
// RatingSlider; fall back to the raw branch id while the network loads.
|
|
30
|
+
const branchLabel = $derived.by(() => {
|
|
31
|
+
const b = ctrl.selectedBranchData;
|
|
32
|
+
return b ? `${b.from} – ${b.to}` : String(app.selectedBranch);
|
|
33
|
+
});
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<div class="mode">
|
|
37
|
+
<span class="chip">
|
|
38
|
+
{ctrl.previewing ? 'LMP preview' : branchMode ? '∂LMP/∂rating' : '∂LMP/∂d'}
|
|
39
|
+
</span>
|
|
40
|
+
<span class="mono dim">
|
|
41
|
+
{#if branchMode}line {branchLabel}{:else}bus {app.selectedBus}{/if}
|
|
42
|
+
</span>
|
|
43
|
+
<button class="mono" onclick={ctrl.clearSelection}>esc clear</button>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="sensitivity-readout" aria-live="polite">
|
|
46
|
+
{#if ctrl.previewing}
|
|
47
|
+
<p class="dim small">
|
|
48
|
+
{ctrl.activeSolvable?.solving
|
|
49
|
+
? 'Exact solve running; the map keeps the LMP preview.'
|
|
50
|
+
: 'First order LMP preview. Release for the exact solve.'}
|
|
51
|
+
</p>
|
|
52
|
+
{#if ctrl.sensSummary?.flat}
|
|
53
|
+
<div class="legend flat" style:background={ctrl.flatSensBackground}></div>
|
|
54
|
+
<div class="legend-labels mono single">
|
|
55
|
+
<span>uniform {signedExp(ctrl.sensSummary.mean * previewStep)} $/MWh</span>
|
|
56
|
+
</div>
|
|
57
|
+
{:else if ctrl.previewScale}
|
|
58
|
+
<!-- The bounds are fixed for the whole drag (column scale × full slider
|
|
59
|
+
deflection), so the ramp ends label the colors: full green/purple is
|
|
60
|
+
the predicted ΔLMP at full deflection, and intensity grows with the
|
|
61
|
+
step instead of renormalizing every frame. -->
|
|
62
|
+
<div class="legend" style:background={sensGradient}></div>
|
|
63
|
+
<div class="legend-labels mono">
|
|
64
|
+
<span>−{ctrl.previewScale.toExponential(1)}</span>
|
|
65
|
+
<span>ΔLMP $/MWh</span>
|
|
66
|
+
<span>+{ctrl.previewScale.toExponential(1)}</span>
|
|
67
|
+
</div>
|
|
68
|
+
{/if}
|
|
69
|
+
{:else}
|
|
70
|
+
<p class="dim small sensitivity-copy" title={unitTitle}>
|
|
71
|
+
{#if branchMode}
|
|
72
|
+
LMP response per MVA of rating on line {branchLabel}.
|
|
73
|
+
{:else}
|
|
74
|
+
LMP response per MW of demand at bus {app.selectedBus}.
|
|
75
|
+
{/if}
|
|
76
|
+
<span class="hint-dot mono" title={unitTitle} aria-label={unitTitle}>i</span>
|
|
77
|
+
</p>
|
|
78
|
+
{#if ctrl.sensSummary?.flat}
|
|
79
|
+
<div class="legend flat" style:background={ctrl.flatSensBackground}></div>
|
|
80
|
+
<div class="legend-labels mono single">
|
|
81
|
+
<span>uniform {signedExp(ctrl.sensSummary.mean)} {units}</span>
|
|
82
|
+
</div>
|
|
83
|
+
{:else if ctrl.sensSummary}
|
|
84
|
+
<div class="legend" style:background={sensGradient}></div>
|
|
85
|
+
<div class="legend-labels mono">
|
|
86
|
+
<span>−{ctrl.sensSummary.scale.toExponential(1)}</span>
|
|
87
|
+
<span>0</span>
|
|
88
|
+
<span>+{ctrl.sensSummary.scale.toExponential(1)}</span>
|
|
89
|
+
</div>
|
|
90
|
+
{:else if app.sensitivityLoading}
|
|
91
|
+
<div class="legend" style:background="var(--line)" style:opacity="0.4"></div>
|
|
92
|
+
<div class="legend-labels mono single">
|
|
93
|
+
<span class="blink">
|
|
94
|
+
computing {#if branchMode}∂LMP/∂fmax{:else}∂LMP/∂d{/if}…
|
|
95
|
+
</span>
|
|
96
|
+
</div>
|
|
97
|
+
{/if}
|
|
98
|
+
{/if}
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<style>
|
|
102
|
+
.chip {
|
|
103
|
+
font-family: var(--font-mono);
|
|
104
|
+
font-size: 11px;
|
|
105
|
+
padding: 2px 8px;
|
|
106
|
+
border: 1px solid var(--accent);
|
|
107
|
+
color: var(--text-accent);
|
|
108
|
+
background: var(--accent-soft);
|
|
109
|
+
border-radius: 2px;
|
|
110
|
+
white-space: nowrap;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* .mode > button lives in the global .mode block in app.css, not here: scoping
|
|
114
|
+
it would raise its specificity above the global @media (max-width: 760px)
|
|
115
|
+
override and break the mobile layout. See the note by .mode in app.css. */
|
|
116
|
+
|
|
117
|
+
.sensitivity-readout {
|
|
118
|
+
min-height: 58px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.sensitivity-copy {
|
|
122
|
+
font-size: 11.5px;
|
|
123
|
+
line-height: 1.35;
|
|
124
|
+
white-space: nowrap;
|
|
125
|
+
}
|
|
126
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SensitivityReadout.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/SensitivityReadout.svelte.ts"],"names":[],"mappings":"AAwGA,QAAA,MAAM,kBAAkB,2DAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { busRadius } from '../colors.js';
|
|
3
|
+
|
|
4
|
+
const SIZE_SAMPLES = [10, 100, 500];
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="sizes">
|
|
8
|
+
{#each SIZE_SAMPLES as mw (mw)}
|
|
9
|
+
<span class="size mono">
|
|
10
|
+
<i style:width="{2 * busRadius(mw)}px" style:height="{2 * busRadius(mw)}px"></i>
|
|
11
|
+
{mw}
|
|
12
|
+
</span>
|
|
13
|
+
{/each}
|
|
14
|
+
<span class="mono dim caption">MW, max(load, gen)</span>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
.sizes {
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
gap: 12px;
|
|
22
|
+
font-size: 10px;
|
|
23
|
+
color: var(--text-secondary);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.size {
|
|
27
|
+
display: inline-flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
gap: 5px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.size i {
|
|
33
|
+
display: inline-block;
|
|
34
|
+
border-radius: 50%;
|
|
35
|
+
background: rgba(212, 116, 34, 0.55);
|
|
36
|
+
border: 1px solid rgba(46, 42, 34, 0.45);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.caption {
|
|
40
|
+
margin-left: auto;
|
|
41
|
+
font-size: 9.5px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@media (max-width: 760px) {
|
|
45
|
+
.sizes {
|
|
46
|
+
flex-wrap: wrap;
|
|
47
|
+
gap: 8px 12px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.caption {
|
|
51
|
+
margin-left: 0;
|
|
52
|
+
flex-basis: 100%;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const SizeLegend: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type SizeLegend = InstanceType<typeof SizeLegend>;
|
|
18
|
+
export default SizeLegend;
|
|
19
|
+
//# sourceMappingURL=SizeLegend.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SizeLegend.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/SizeLegend.svelte.ts"],"names":[],"mappings":"AAyBA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,UAAU;;kBAA+E,CAAC;AAC9E,KAAK,UAAU,GAAG,YAAY,CAAC,OAAO,UAAU,CAAC,CAAC;AACpD,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getController } from '../context.svelte.js';
|
|
3
|
+
import { formulationLabel, solveMetaLabel } from '../format.js';
|
|
4
|
+
import Sparkline from '../Sparkline.svelte';
|
|
5
|
+
|
|
6
|
+
const ctrl = getController();
|
|
7
|
+
const active = $derived(ctrl.activeSolvable);
|
|
8
|
+
const iterations = $derived(active?.iterations ?? []);
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
{#if active && (active.solving || active.solveMs != null)}
|
|
12
|
+
<div class="solvecard">
|
|
13
|
+
<div class="solvecard-head mono">
|
|
14
|
+
<span><b>OPF solve</b></span>
|
|
15
|
+
</div>
|
|
16
|
+
{#if iterations.length > 1}
|
|
17
|
+
{#key iterations}
|
|
18
|
+
<Sparkline {iterations} />
|
|
19
|
+
{/key}
|
|
20
|
+
{/if}
|
|
21
|
+
<div class="solve-meta mono dim">
|
|
22
|
+
<span class="solve-formulation">{formulationLabel(active.formulation)}</span>
|
|
23
|
+
<span>{solveMetaLabel(active)}</span>
|
|
24
|
+
{#if active.solveMs != null}<span>{active.solveMs} ms</span>{/if}
|
|
25
|
+
</div>
|
|
26
|
+
{#if active.solveBackend === 'rust-server' && active.solveFallbackReason}
|
|
27
|
+
<p class="fallback-reason mono dim" title={active.solveFallbackReason}>
|
|
28
|
+
fallback: {active.solveFallbackReason}
|
|
29
|
+
</p>
|
|
30
|
+
{/if}
|
|
31
|
+
</div>
|
|
32
|
+
{/if}
|
|
33
|
+
|
|
34
|
+
<style>
|
|
35
|
+
.solvecard {
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: 76px;
|
|
38
|
+
right: 20px;
|
|
39
|
+
z-index: 10;
|
|
40
|
+
width: 300px;
|
|
41
|
+
padding: 13px 15px 11px;
|
|
42
|
+
background: var(--panel);
|
|
43
|
+
border: 1px solid var(--line);
|
|
44
|
+
border-radius: 3px;
|
|
45
|
+
backdrop-filter: blur(6px);
|
|
46
|
+
box-shadow: 0 4px 24px rgba(32, 36, 43, 0.08);
|
|
47
|
+
animation: rise 0.3s ease-out both;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.solvecard-head {
|
|
51
|
+
font-size: 10.5px;
|
|
52
|
+
margin-bottom: 6px;
|
|
53
|
+
white-space: nowrap;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.solve-meta {
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
flex-wrap: wrap;
|
|
60
|
+
gap: 10px 14px;
|
|
61
|
+
font-size: 10px;
|
|
62
|
+
margin-top: 6px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.solve-formulation {
|
|
66
|
+
color: var(--text-accent);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.fallback-reason {
|
|
70
|
+
margin: 6px 0 0;
|
|
71
|
+
font-size: 10px;
|
|
72
|
+
line-height: 1.35;
|
|
73
|
+
overflow-wrap: anywhere;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@media (max-width: 760px) {
|
|
77
|
+
.solvecard {
|
|
78
|
+
top: 184px;
|
|
79
|
+
left: auto;
|
|
80
|
+
right: 10px;
|
|
81
|
+
width: min(300px, calc(100% - 20px));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SolveCard.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/SolveCard.svelte.ts"],"names":[],"mappings":"AA4CA,QAAA,MAAM,SAAS,2DAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|