@tellegen/svelte 0.3.0 → 0.4.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 +233 -0
- package/dist/Sparkline.svelte +2 -2
- package/dist/TellegenMap.svelte +201 -47
- package/dist/TellegenMap.svelte.d.ts +45 -0
- package/dist/TellegenProvider.svelte +36 -4
- package/dist/TellegenShell.svelte +14 -42
- package/dist/TellegenViewer.svelte +12 -2
- package/dist/api.d.ts +10 -2
- package/dist/api.js +2 -0
- package/dist/basemap.d.ts +192 -0
- package/dist/basemap.js +259 -0
- package/dist/colors.d.ts +18 -0
- package/dist/colors.js +26 -0
- package/dist/components/AppFooter.svelte +3 -2
- package/dist/components/AppHeader.svelte +21 -8
- package/dist/components/BindingLines.svelte +1 -1
- package/dist/components/BusPicker.svelte +3 -3
- package/dist/components/DemandSlider.svelte +16 -7
- package/dist/components/DiagramCanvas.svelte +1 -1
- package/dist/components/DisplayControls.svelte +5 -1
- package/dist/components/DropZone.svelte +1 -1
- package/dist/components/FormulationSelector.svelte +1 -1
- package/dist/components/LocalCaseDetails.svelte +6 -3
- package/dist/components/McResults.svelte +98 -35
- package/dist/components/McResults.svelte.d.ts +8 -2
- package/dist/components/ModelDetails.svelte +5 -5
- package/dist/components/MulticonductorDetails.svelte +9 -9
- package/dist/components/NotificationCenter.svelte +4 -2
- package/dist/components/PanelCard.svelte +72 -7
- package/dist/components/PanelHost.svelte +59 -34
- package/dist/components/PanelHost.svelte.d.ts +4 -1
- package/dist/components/PlacementCue.svelte +1 -1
- package/dist/components/PowerFlowDetails.svelte +1 -1
- package/dist/components/RatingSlider.svelte +14 -5
- package/dist/components/RestoreDefaultsButton.svelte +1 -1
- package/dist/components/SavedNetworkDetails.svelte +3 -3
- package/dist/components/SensitivityReadout.svelte +2 -2
- package/dist/components/ShellEnvironment.svelte +51 -0
- package/dist/components/ShellEnvironment.svelte.d.ts +18 -0
- package/dist/components/SizeLegend.svelte +2 -2
- package/dist/components/SolveCard.svelte +3 -3
- package/dist/components/TopMovers.svelte +1 -1
- package/dist/components.d.ts +3 -0
- package/dist/components.js +3 -0
- package/dist/context.svelte.d.ts +8 -1
- package/dist/context.svelte.js +8 -3
- package/dist/controller.svelte.d.ts +65 -5
- package/dist/controller.svelte.js +262 -76
- package/dist/format.d.ts +9 -0
- package/dist/format.js +12 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +2 -0
- package/dist/map.d.ts +4 -2
- package/dist/map.js +2 -1
- package/dist/maplibre-worker.d.ts +5 -0
- package/dist/maplibre-worker.dev.d.ts +11 -0
- package/dist/maplibre-worker.dev.js +15 -0
- package/dist/maplibre-worker.js +8 -0
- package/dist/notices.svelte.js +5 -1
- package/dist/panels.svelte.d.ts +6 -0
- package/dist/panels.svelte.js +31 -1
- package/dist/slider.d.ts +12 -0
- package/dist/slider.js +31 -0
- package/dist/state.svelte.d.ts +19 -2
- package/dist/state.svelte.js +12 -0
- package/dist/styles.css +59 -6
- package/package.json +13 -8
package/dist/map.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import TellegenMap from './TellegenMap.svelte';
|
|
2
2
|
export { default as TellegenMap } from './TellegenMap.svelte';
|
|
3
|
-
export {
|
|
3
|
+
export { CARTO_STYLES, OPENFREEMAP_STYLES, attachBasemapFallback, cartoStyleUrl, defaultBasemap, isOpenFreeMapStyle, openFreeMapEdits, resolveBasemap } from './basemap.js';
|
|
4
|
+
export { MAP_PALETTE, branchColor, branchWidth, busNeutral, busRadius, priceColor, priceDomain, priceGradient, scalarDomain, sensColor, sensFlatColor, sensGradient, sensNeutral, sensitivityDomain } from './colors.js';
|
|
4
5
|
export { caseDeltas, displayMetaFor, displaySeriesFor } from './display.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The URL of MapLibre's worker, which the host's Vite build bundles with its
|
|
2
|
+
* shared chunk. `TellegenMap` hands it to `setWorkerUrl` before it creates a
|
|
3
|
+
* map. Reached through the `@tellegen/svelte/maplibre-worker` export; see
|
|
4
|
+
* `maplibre-worker.dev.ts` for the dev server. */
|
|
5
|
+
export declare function maplibreWorkerUrl(): Promise<string>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The dev server's `@tellegen/svelte/maplibre-worker`, chosen by the
|
|
2
|
+
* `development` export condition.
|
|
3
|
+
*
|
|
4
|
+
* Vite's dev server pre-bundles this package with Rolldown, which cannot load
|
|
5
|
+
* the `?worker&url` import in `maplibre-worker.ts`, so a static import of that
|
|
6
|
+
* module would stop the dev server at startup. Here it is imported at run time
|
|
7
|
+
* by URL instead, outside the pre-bundle, and the dev server resolves the
|
|
8
|
+
* query itself. Vite rewrites the `new URL` in a pre-bundled file to point at
|
|
9
|
+
* the original. A production build takes the default condition and imports
|
|
10
|
+
* `maplibre-worker.ts` directly. */
|
|
11
|
+
export declare function maplibreWorkerUrl(): Promise<string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** The dev server's `@tellegen/svelte/maplibre-worker`, chosen by the
|
|
2
|
+
* `development` export condition.
|
|
3
|
+
*
|
|
4
|
+
* Vite's dev server pre-bundles this package with Rolldown, which cannot load
|
|
5
|
+
* the `?worker&url` import in `maplibre-worker.ts`, so a static import of that
|
|
6
|
+
* module would stop the dev server at startup. Here it is imported at run time
|
|
7
|
+
* by URL instead, outside the pre-bundle, and the dev server resolves the
|
|
8
|
+
* query itself. Vite rewrites the `new URL` in a pre-bundled file to point at
|
|
9
|
+
* the original. A production build takes the default condition and imports
|
|
10
|
+
* `maplibre-worker.ts` directly. */
|
|
11
|
+
export async function maplibreWorkerUrl() {
|
|
12
|
+
const url = new URL('./maplibre-worker.js', import.meta.url).href;
|
|
13
|
+
const module = await import(/* @vite-ignore */ url);
|
|
14
|
+
return module.maplibreWorkerUrl();
|
|
15
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import workerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url';
|
|
2
|
+
/** The URL of MapLibre's worker, which the host's Vite build bundles with its
|
|
3
|
+
* shared chunk. `TellegenMap` hands it to `setWorkerUrl` before it creates a
|
|
4
|
+
* map. Reached through the `@tellegen/svelte/maplibre-worker` export; see
|
|
5
|
+
* `maplibre-worker.dev.ts` for the dev server. */
|
|
6
|
+
export async function maplibreWorkerUrl() {
|
|
7
|
+
return workerUrl;
|
|
8
|
+
}
|
package/dist/notices.svelte.js
CHANGED
|
@@ -70,11 +70,15 @@ export function getNoticeCenter() {
|
|
|
70
70
|
export function errorNoticeTitle(details) {
|
|
71
71
|
if (/rate limit/i.test(details))
|
|
72
72
|
return 'Too many requests';
|
|
73
|
+
// MapLibre's WebGL failure includes "Read more"; classify our map errors
|
|
74
|
+
// before the generic file/read fallback so it does not blame a case file.
|
|
75
|
+
if (/^map failed to load:|^the map lost its graphics context/i.test(details))
|
|
76
|
+
return 'Map unavailable';
|
|
73
77
|
if (/storage|quota|space|indexeddb/i.test(details))
|
|
74
78
|
return 'Could not save locally';
|
|
75
79
|
if (/sensitivity|derivative|singular/i.test(details))
|
|
76
80
|
return 'Sensitivity unavailable';
|
|
77
|
-
if (/infeasib|converg|solver|solving|calculation|compute|webassembly/i.test(details))
|
|
81
|
+
if (/infeasib|converg|solver|solving|calculation|compute|webassembly|power flow/i.test(details))
|
|
78
82
|
return 'Calculation did not complete';
|
|
79
83
|
if (/parse|read|file|format/i.test(details))
|
|
80
84
|
return 'Could not read this file';
|
package/dist/panels.svelte.d.ts
CHANGED
|
@@ -49,6 +49,9 @@ export declare class PanelLayout {
|
|
|
49
49
|
position(panel: PanelRegistration): PanelPosition;
|
|
50
50
|
ordered(side?: PanelSide): PanelRegistration[];
|
|
51
51
|
toggle(panel: PanelRegistration): void;
|
|
52
|
+
/** The control that had focus when the panel last opened, while it is still
|
|
53
|
+
* in the document: where focus returns when the panel closes. */
|
|
54
|
+
opener(panel: PanelRegistration): HTMLElement | SVGElement | null;
|
|
52
55
|
close(panel: PanelRegistration): void;
|
|
53
56
|
dock(panel: PanelRegistration, side?: PanelSide): void;
|
|
54
57
|
float(panel: PanelRegistration, bounds?: PanelBounds): void;
|
|
@@ -60,6 +63,9 @@ export declare class PanelLayout {
|
|
|
60
63
|
initialize(storage?: Storage): void;
|
|
61
64
|
save(): void;
|
|
62
65
|
}
|
|
66
|
+
/** Focus the first candidate that takes focus. A detached or hidden element
|
|
67
|
+
* does not, so the next one gets its turn. */
|
|
68
|
+
export declare function focusFirst(candidates: Array<HTMLElement | SVGElement | null | undefined>): HTMLElement | SVGElement | null;
|
|
63
69
|
export declare const setPanelLayout: (layout: PanelLayout) => PanelLayout;
|
|
64
70
|
export declare const getPanelLayout: () => PanelLayout;
|
|
65
71
|
export {};
|
package/dist/panels.svelte.js
CHANGED
|
@@ -18,6 +18,7 @@ export class PanelLayout {
|
|
|
18
18
|
bottom = $state(88);
|
|
19
19
|
storageError = $state(null);
|
|
20
20
|
#storage;
|
|
21
|
+
#openers = new Map();
|
|
21
22
|
#gesture = null;
|
|
22
23
|
beginGesture(panel, kind, x, y, bounds) {
|
|
23
24
|
this.#gesture = { panel, kind, x, y, bounds, moved: false };
|
|
@@ -60,6 +61,7 @@ export class PanelLayout {
|
|
|
60
61
|
return;
|
|
61
62
|
this.panels = this.panels.map((p) => (p.id === id ? { ...p, open, title, width } : p));
|
|
62
63
|
if (open && !previous.open) {
|
|
64
|
+
this.#rememberOpener(id);
|
|
63
65
|
this.activate(previous);
|
|
64
66
|
if (this.compact)
|
|
65
67
|
this.drawer = id;
|
|
@@ -91,19 +93,35 @@ export class PanelLayout {
|
|
|
91
93
|
if (this.compact) {
|
|
92
94
|
this.drawer = this.drawer === panel.id ? null : panel.id;
|
|
93
95
|
if (this.drawer === panel.id) {
|
|
96
|
+
this.#rememberOpener(panel.id);
|
|
94
97
|
this.activate(panel);
|
|
95
98
|
panel.setOpen(true);
|
|
96
99
|
panel.onopen?.();
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
102
|
else {
|
|
100
|
-
if (!panel.open)
|
|
103
|
+
if (!panel.open) {
|
|
104
|
+
this.#rememberOpener(panel.id);
|
|
101
105
|
this.activate(panel);
|
|
106
|
+
}
|
|
102
107
|
panel.setOpen(!panel.open);
|
|
103
108
|
if (!panel.open)
|
|
104
109
|
panel.onopen?.();
|
|
105
110
|
}
|
|
106
111
|
}
|
|
112
|
+
/** The control that had focus when the panel last opened, while it is still
|
|
113
|
+
* in the document: where focus returns when the panel closes. */
|
|
114
|
+
opener(panel) {
|
|
115
|
+
const element = this.#openers.get(panel.id);
|
|
116
|
+
return element?.isConnected ? element : null;
|
|
117
|
+
}
|
|
118
|
+
#rememberOpener(id) {
|
|
119
|
+
const active = typeof document === 'undefined' ? null : document.activeElement;
|
|
120
|
+
if ((active instanceof HTMLElement || active instanceof SVGElement) && active !== document.body)
|
|
121
|
+
this.#openers.set(id, active);
|
|
122
|
+
else
|
|
123
|
+
this.#openers.delete(id);
|
|
124
|
+
}
|
|
107
125
|
close(panel) {
|
|
108
126
|
panel.setOpen(false);
|
|
109
127
|
if (this.drawer === panel.id)
|
|
@@ -206,6 +224,18 @@ export class PanelLayout {
|
|
|
206
224
|
}
|
|
207
225
|
}
|
|
208
226
|
}
|
|
227
|
+
/** Focus the first candidate that takes focus. A detached or hidden element
|
|
228
|
+
* does not, so the next one gets its turn. */
|
|
229
|
+
export function focusFirst(candidates) {
|
|
230
|
+
for (const candidate of candidates) {
|
|
231
|
+
if (!candidate?.isConnected)
|
|
232
|
+
continue;
|
|
233
|
+
candidate.focus();
|
|
234
|
+
if (candidate.ownerDocument.activeElement === candidate)
|
|
235
|
+
return candidate;
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
209
239
|
export const setPanelLayout = (layout) => setContext(KEY, layout);
|
|
210
240
|
export const getPanelLayout = () => {
|
|
211
241
|
const layout = getContext(KEY);
|
package/dist/slider.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Smallest demand or rating edit that counts: a slider released closer than
|
|
2
|
+
* this to the committed value commits nothing and starts no solve. */
|
|
3
|
+
export declare const DEAD_ZONE_MW = 0.25;
|
|
4
|
+
/** Arrow-key step of a demand or rating slider spanning `span` MW: about 1%
|
|
5
|
+
* of the span, rounded up to 1, 2 or 5 times a power of ten. It is at least
|
|
6
|
+
* twice the dead zone, so one press always leaves it, rounding error
|
|
7
|
+
* included. The native step of a `step="any"` range is 1% of the span, which
|
|
8
|
+
* on a small bus never leaves the dead zone. */
|
|
9
|
+
export declare function sliderKeyStep(span: number): number;
|
|
10
|
+
/** The value an arrow key moves a slider to, kept within [min, max], or null
|
|
11
|
+
* for any other key. Right and up raise it. */
|
|
12
|
+
export declare function sliderKeyValue(key: string, value: number, min: number, max: number): number | null;
|
package/dist/slider.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Smallest demand or rating edit that counts: a slider released closer than
|
|
2
|
+
* this to the committed value commits nothing and starts no solve. */
|
|
3
|
+
export const DEAD_ZONE_MW = 0.25;
|
|
4
|
+
const KEY_DIRECTIONS = {
|
|
5
|
+
ArrowRight: 1,
|
|
6
|
+
ArrowUp: 1,
|
|
7
|
+
ArrowLeft: -1,
|
|
8
|
+
ArrowDown: -1
|
|
9
|
+
};
|
|
10
|
+
/** Arrow-key step of a demand or rating slider spanning `span` MW: about 1%
|
|
11
|
+
* of the span, rounded up to 1, 2 or 5 times a power of ten. It is at least
|
|
12
|
+
* twice the dead zone, so one press always leaves it, rounding error
|
|
13
|
+
* included. The native step of a `step="any"` range is 1% of the span, which
|
|
14
|
+
* on a small bus never leaves the dead zone. */
|
|
15
|
+
export function sliderKeyStep(span) {
|
|
16
|
+
const target = Math.max(span / 100, 2 * DEAD_ZONE_MW);
|
|
17
|
+
const power = 10 ** Math.floor(Math.log10(target));
|
|
18
|
+
for (const factor of [1, 2, 5]) {
|
|
19
|
+
if (factor * power >= target)
|
|
20
|
+
return factor * power;
|
|
21
|
+
}
|
|
22
|
+
return 10 * power;
|
|
23
|
+
}
|
|
24
|
+
/** The value an arrow key moves a slider to, kept within [min, max], or null
|
|
25
|
+
* for any other key. Right and up raise it. */
|
|
26
|
+
export function sliderKeyValue(key, value, min, max) {
|
|
27
|
+
const direction = KEY_DIRECTIONS[key];
|
|
28
|
+
if (direction === undefined)
|
|
29
|
+
return null;
|
|
30
|
+
return Math.min(max, Math.max(min, value + direction * sliderKeyStep(max - min)));
|
|
31
|
+
}
|
package/dist/state.svelte.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CaseSummary, DemandDeltas, Network, NetworkBranch, NetworkBus, SensitivityColumn, Solution, SolveIteration } from './api.js';
|
|
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';
|
|
2
|
+
import { type StudyView, type BranchRatingDeltas, type BrowserMcPfSession, type CaseFileSummary, type DistGraph, type Formulation, type IngestedDistCase, type McPfCallTiming, type McPfResult, type McPfSummary, 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. */
|
|
@@ -174,6 +174,12 @@ export type SolvableCase = CaseState | LocalCase;
|
|
|
174
174
|
export type MultiCaseSummary = Omit<IngestedDistCase, 'graph'>;
|
|
175
175
|
/** Geographic coordinates use the map; other positions use the diagram canvas. */
|
|
176
176
|
export type MultiCoordsKind = 'geographic' | 'planar' | 'synthetic';
|
|
177
|
+
/** Where one interactive load edit spent its time, in milliseconds: engine
|
|
178
|
+
* (solve and summary), transfer, and parsing as recorded by the session, and
|
|
179
|
+
* the total from the start of the solve until the result state is updated. */
|
|
180
|
+
export interface McEditTiming extends McPfCallTiming {
|
|
181
|
+
total_ms: number;
|
|
182
|
+
}
|
|
177
183
|
/** A conductor-resolved case with retained electrical inputs and terminal results. */
|
|
178
184
|
export declare class MulticonductorCase {
|
|
179
185
|
readonly id: string;
|
|
@@ -182,7 +188,14 @@ export declare class MulticonductorCase {
|
|
|
182
188
|
moduleJson: string | null;
|
|
183
189
|
geoLayer: string | null;
|
|
184
190
|
geoWarnings: string[];
|
|
185
|
-
|
|
191
|
+
/** Summary of the displayed operating point: from the live session after
|
|
192
|
+
* each solve or load edit, or derived from a stored full result. */
|
|
193
|
+
result: McPfSummary | null;
|
|
194
|
+
/** The complete result when no live session holds the operating point: a
|
|
195
|
+
* saved Study, a solve without sessions, or after coordinates are attached. */
|
|
196
|
+
mcFullResult: McPfResult | null;
|
|
197
|
+
/** Latency breakdown of the latest load-edit solve. */
|
|
198
|
+
mcTiming: McEditTiming | null;
|
|
186
199
|
mcSnapshot: McStudySnapshot | null;
|
|
187
200
|
mcSession: BrowserMcPfSession | null;
|
|
188
201
|
mcLoadBranches: McLoadBranchState[];
|
|
@@ -285,6 +298,10 @@ export declare class AppState {
|
|
|
285
298
|
/** Re-runs the operation behind the current `error`, when one applies. Every
|
|
286
299
|
* write to `error` clears it, so a retry op can never outlive its message. */
|
|
287
300
|
errorRetry: (() => void) | null;
|
|
301
|
+
/** Technical detail behind the current `error`, when the message itself is
|
|
302
|
+
* written for people; notices keep it in their disclosure. Every write to
|
|
303
|
+
* `error` clears it, as it clears `errorRetry`. */
|
|
304
|
+
errorDetail: string | null;
|
|
288
305
|
get error(): string | null;
|
|
289
306
|
set error(message: string | null);
|
|
290
307
|
/** Case files parsed in the browser via the powerio wasm module. */
|
package/dist/state.svelte.js
CHANGED
|
@@ -122,7 +122,14 @@ export class MulticonductorCase {
|
|
|
122
122
|
moduleJson = $state.raw(null);
|
|
123
123
|
geoLayer = $state.raw(null);
|
|
124
124
|
geoWarnings = $state.raw([]);
|
|
125
|
+
/** Summary of the displayed operating point: from the live session after
|
|
126
|
+
* each solve or load edit, or derived from a stored full result. */
|
|
125
127
|
result = $state.raw(null);
|
|
128
|
+
/** The complete result when no live session holds the operating point: a
|
|
129
|
+
* saved Study, a solve without sessions, or after coordinates are attached. */
|
|
130
|
+
mcFullResult = $state.raw(null);
|
|
131
|
+
/** Latency breakdown of the latest load-edit solve. */
|
|
132
|
+
mcTiming = $state.raw(null);
|
|
126
133
|
mcSnapshot = $state.raw(null);
|
|
127
134
|
mcSession = $state.raw(null);
|
|
128
135
|
mcLoadBranches = $state.raw([]);
|
|
@@ -251,6 +258,10 @@ export class AppState {
|
|
|
251
258
|
/** Re-runs the operation behind the current `error`, when one applies. Every
|
|
252
259
|
* write to `error` clears it, so a retry op can never outlive its message. */
|
|
253
260
|
errorRetry = $state.raw(null);
|
|
261
|
+
/** Technical detail behind the current `error`, when the message itself is
|
|
262
|
+
* written for people; notices keep it in their disclosure. Every write to
|
|
263
|
+
* `error` clears it, as it clears `errorRetry`. */
|
|
264
|
+
errorDetail = $state(null);
|
|
254
265
|
get error() {
|
|
255
266
|
return this.#error;
|
|
256
267
|
}
|
|
@@ -259,6 +270,7 @@ export class AppState {
|
|
|
259
270
|
if (message)
|
|
260
271
|
this.errorRevision++;
|
|
261
272
|
this.errorRetry = null;
|
|
273
|
+
this.errorDetail = null;
|
|
262
274
|
}
|
|
263
275
|
/** Case files parsed in the browser via the powerio wasm module. */
|
|
264
276
|
localCases = $state.raw([]);
|
package/dist/styles.css
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
--surface-panel: var(--panel);
|
|
33
33
|
--surface-chip: rgb(var(--paper-rgb) / 0.65);
|
|
34
34
|
--surface-control: rgb(var(--paper-rgb) / 0.55);
|
|
35
|
+
--surface-menu: #fff;
|
|
35
36
|
--border-default: var(--line);
|
|
36
37
|
--border-strong: var(--accent);
|
|
37
38
|
--text-primary: var(--ink);
|
|
@@ -47,6 +48,10 @@
|
|
|
47
48
|
--data-pos: var(--pos);
|
|
48
49
|
--data-neg: var(--neg);
|
|
49
50
|
--focus-ring: var(--accent);
|
|
51
|
+
/* unselected bus outline in the plain diagram view */
|
|
52
|
+
--diagram-bus-stroke: #756a5b;
|
|
53
|
+
/* ground symbol in the multiconductor bus detail */
|
|
54
|
+
--mc-ground-stroke: #3a3a3a;
|
|
50
55
|
|
|
51
56
|
/* type scale, anchored at the 15px body */
|
|
52
57
|
--fs-display-lg: 33px;
|
|
@@ -81,6 +86,11 @@
|
|
|
81
86
|
--radius-full: 50%;
|
|
82
87
|
--elev-1: 0 2px 10px rgb(var(--ink-rgb) / 0.1);
|
|
83
88
|
--elev-2: 0 4px 24px rgb(var(--ink-rgb) / 0.08);
|
|
89
|
+
/* floating controls that keep their own light shadows; the dark theme maps
|
|
90
|
+
them onto the two steps above */
|
|
91
|
+
--elev-cue: 0 4px 18px rgb(var(--ink-rgb) / 0.1);
|
|
92
|
+
--elev-menu: 0 4px 18px rgb(var(--ink-rgb) / 0.14);
|
|
93
|
+
--elev-tooltip: 0 2px 10px rgb(var(--ink-rgb) / 0.12);
|
|
84
94
|
--shadow-thumb: 0 1px 4px rgb(var(--ink-rgb) / 0.3);
|
|
85
95
|
--inset-active: inset 0 -2px 0 var(--accent);
|
|
86
96
|
|
|
@@ -103,6 +113,49 @@
|
|
|
103
113
|
--z-grain: 9999;
|
|
104
114
|
}
|
|
105
115
|
|
|
116
|
+
/* Dark theme: `TellegenProvider theme="dark"` sets the attribute (a host may
|
|
117
|
+
also put it in its template). Contrast ratios are measured against the panel
|
|
118
|
+
composited over #4a4a4a, the darkest grey a dark basemap paints under it:
|
|
119
|
+
every text token clears 7:1. --border-strong marks a panel's edge over the
|
|
120
|
+
map, so it clears the 3:1 non-text minimum against that panel and against
|
|
121
|
+
bare #4a4a4a. The same markup passes WCAG AA on either ground. */
|
|
122
|
+
:root[data-theme='dark'] {
|
|
123
|
+
--bg: #0b1420;
|
|
124
|
+
--paper: #0f1a27;
|
|
125
|
+
--panel: rgba(10, 20, 31, 0.92);
|
|
126
|
+
--line: #34465a; /* decorative separators only */
|
|
127
|
+
--border-strong: #859cb4; /* 6.30:1 against the panel, 3.13:1 against bare #4a4a4a */
|
|
128
|
+
--ink: #e8eef4; /* 15.3:1 */
|
|
129
|
+
--ink-dim: #b4c1cd; /* 9.7:1 */
|
|
130
|
+
--ink-faint: #95a6b6; /* 7.14:1, and 7.02:1 on the opaque --paper of a panel card */
|
|
131
|
+
--accent: #ffb24d;
|
|
132
|
+
--accent-bright: #ffc46e; /* 11.4:1 */
|
|
133
|
+
--accent-soft: rgba(255, 178, 77, 0.14);
|
|
134
|
+
--red: #ff9f8b; /* 9.0:1 */
|
|
135
|
+
--pos: #c9a7e0;
|
|
136
|
+
--neg: #8fd0a4;
|
|
137
|
+
--bg-rgb: 11 20 32;
|
|
138
|
+
--ink-rgb: 232 238 244;
|
|
139
|
+
--accent-rgb: 255 178 77;
|
|
140
|
+
--paper-rgb: 15 26 39;
|
|
141
|
+
--text-primary: var(--ink);
|
|
142
|
+
--text-secondary: var(--ink-dim);
|
|
143
|
+
--text-tertiary: var(--ink-faint);
|
|
144
|
+
--text-accent: var(--accent-bright);
|
|
145
|
+
--text-danger: var(--red);
|
|
146
|
+
--focus-ring: #8de7f7; /* 12.7:1 */
|
|
147
|
+
--surface-menu: var(--paper);
|
|
148
|
+
--diagram-bus-stroke: var(--ink-faint);
|
|
149
|
+
--mc-ground-stroke: var(--ink-dim);
|
|
150
|
+
--elev-1: 0 2px 10px rgb(0 0 0 / 0.45);
|
|
151
|
+
--elev-2: 0 4px 24px rgb(0 0 0 / 0.4);
|
|
152
|
+
--elev-cue: var(--elev-2);
|
|
153
|
+
--elev-menu: var(--elev-2);
|
|
154
|
+
--elev-tooltip: var(--elev-1);
|
|
155
|
+
/* the light form derives from --ink-rgb, which would glow here */
|
|
156
|
+
--shadow-thumb: 0 1px 4px rgb(0 0 0 / 0.5);
|
|
157
|
+
}
|
|
158
|
+
|
|
106
159
|
* {
|
|
107
160
|
box-sizing: border-box;
|
|
108
161
|
}
|
|
@@ -225,7 +278,7 @@ a {
|
|
|
225
278
|
ControlPanel.svelte; the .mode / .display-mode / @media source order is
|
|
226
279
|
preserved so the cascade resolves exactly as before. */
|
|
227
280
|
.region {
|
|
228
|
-
font-size:
|
|
281
|
+
font-size: 12px;
|
|
229
282
|
font-weight: 400;
|
|
230
283
|
color: var(--text-secondary);
|
|
231
284
|
text-transform: uppercase;
|
|
@@ -245,7 +298,7 @@ a {
|
|
|
245
298
|
before the component split. Scoping this would raise its specificity past that rule. */
|
|
246
299
|
.mode > button {
|
|
247
300
|
margin-left: auto;
|
|
248
|
-
font-size:
|
|
301
|
+
font-size: 12.5px;
|
|
249
302
|
padding: 2px 7px;
|
|
250
303
|
background: none;
|
|
251
304
|
border: 1px solid var(--line);
|
|
@@ -264,7 +317,7 @@ a {
|
|
|
264
317
|
}
|
|
265
318
|
|
|
266
319
|
.display-mode .segment button {
|
|
267
|
-
font-size:
|
|
320
|
+
font-size: 13px;
|
|
268
321
|
padding: 2px 9px;
|
|
269
322
|
}
|
|
270
323
|
|
|
@@ -282,7 +335,7 @@ a {
|
|
|
282
335
|
.legend-labels {
|
|
283
336
|
display: flex;
|
|
284
337
|
justify-content: space-between;
|
|
285
|
-
font-size:
|
|
338
|
+
font-size: 12.5px;
|
|
286
339
|
color: var(--text-tertiary);
|
|
287
340
|
margin-top: 4px;
|
|
288
341
|
}
|
|
@@ -301,7 +354,7 @@ a {
|
|
|
301
354
|
border-radius: 999px;
|
|
302
355
|
color: var(--text-secondary);
|
|
303
356
|
background: var(--surface-control);
|
|
304
|
-
font-size:
|
|
357
|
+
font-size: 12px;
|
|
305
358
|
line-height: 1;
|
|
306
359
|
cursor: help;
|
|
307
360
|
}
|
|
@@ -334,7 +387,7 @@ a {
|
|
|
334
387
|
|
|
335
388
|
.reset {
|
|
336
389
|
margin-top: 10px;
|
|
337
|
-
font-size:
|
|
390
|
+
font-size: 12.5px;
|
|
338
391
|
padding: 3px 10px;
|
|
339
392
|
background: none;
|
|
340
393
|
border: 1px solid var(--line);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tellegen/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Svelte components for tellegen power system maps, local case files, and browser solves.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|
|
@@ -53,6 +53,11 @@
|
|
|
53
53
|
"svelte": "./dist/map.js",
|
|
54
54
|
"default": "./dist/map.js"
|
|
55
55
|
},
|
|
56
|
+
"./maplibre-worker": {
|
|
57
|
+
"types": "./dist/maplibre-worker.d.ts",
|
|
58
|
+
"development": "./dist/maplibre-worker.dev.js",
|
|
59
|
+
"default": "./dist/maplibre-worker.js"
|
|
60
|
+
},
|
|
56
61
|
"./styles.css": "./dist/styles.css"
|
|
57
62
|
},
|
|
58
63
|
"scripts": {
|
|
@@ -65,19 +70,19 @@
|
|
|
65
70
|
"@deck.gl/core": "^9.4.0",
|
|
66
71
|
"@deck.gl/layers": "^9.4.0",
|
|
67
72
|
"@deck.gl/maplibre": "^9.4.0",
|
|
68
|
-
"@tellegen/engine": "^0.
|
|
69
|
-
"maplibre-gl": "^6.
|
|
73
|
+
"@tellegen/engine": "^0.4.0",
|
|
74
|
+
"maplibre-gl": "^6.15.0"
|
|
70
75
|
},
|
|
71
76
|
"peerDependencies": {
|
|
72
77
|
"svelte": ">=5.30 <6"
|
|
73
78
|
},
|
|
74
79
|
"devDependencies": {
|
|
75
80
|
"@sveltejs/package": "^2.3.0",
|
|
76
|
-
"@sveltejs/vite-plugin-svelte": "^7.3.
|
|
77
|
-
"svelte": "^5.57.
|
|
78
|
-
"svelte-check": "^4.7.
|
|
81
|
+
"@sveltejs/vite-plugin-svelte": "^7.3.1",
|
|
82
|
+
"svelte": "^5.57.2",
|
|
83
|
+
"svelte-check": "^4.7.7",
|
|
79
84
|
"typescript": "^6.0.3",
|
|
80
|
-
"vite": "^8.
|
|
81
|
-
"vitest": "^5.0.
|
|
85
|
+
"vite": "^8.3.1",
|
|
86
|
+
"vitest": "^5.0.2"
|
|
82
87
|
}
|
|
83
88
|
}
|