@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.
Files changed (121) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +70 -0
  3. package/dist/Sparkline.svelte +100 -0
  4. package/dist/Sparkline.svelte.d.ts +8 -0
  5. package/dist/Sparkline.svelte.d.ts.map +1 -0
  6. package/dist/TellegenMap.svelte +1430 -0
  7. package/dist/TellegenMap.svelte.d.ts +14 -0
  8. package/dist/TellegenMap.svelte.d.ts.map +1 -0
  9. package/dist/TellegenProvider.svelte +38 -0
  10. package/dist/TellegenProvider.svelte.d.ts +9 -0
  11. package/dist/TellegenProvider.svelte.d.ts.map +1 -0
  12. package/dist/TellegenShell.svelte +126 -0
  13. package/dist/TellegenShell.svelte.d.ts +4 -0
  14. package/dist/TellegenShell.svelte.d.ts.map +1 -0
  15. package/dist/TellegenViewer.svelte +19 -0
  16. package/dist/TellegenViewer.svelte.d.ts +4 -0
  17. package/dist/TellegenViewer.svelte.d.ts.map +1 -0
  18. package/dist/api.d.ts +44 -0
  19. package/dist/api.d.ts.map +1 -0
  20. package/dist/api.js +137 -0
  21. package/dist/colors.d.ts +51 -0
  22. package/dist/colors.d.ts.map +1 -0
  23. package/dist/colors.js +140 -0
  24. package/dist/components/AppFooter.svelte +73 -0
  25. package/dist/components/AppFooter.svelte.d.ts +19 -0
  26. package/dist/components/AppFooter.svelte.d.ts.map +1 -0
  27. package/dist/components/AppHeader.svelte +405 -0
  28. package/dist/components/AppHeader.svelte.d.ts +4 -0
  29. package/dist/components/AppHeader.svelte.d.ts.map +1 -0
  30. package/dist/components/BindingLines.svelte +101 -0
  31. package/dist/components/BindingLines.svelte.d.ts +4 -0
  32. package/dist/components/BindingLines.svelte.d.ts.map +1 -0
  33. package/dist/components/BusPicker.svelte +227 -0
  34. package/dist/components/BusPicker.svelte.d.ts +4 -0
  35. package/dist/components/BusPicker.svelte.d.ts.map +1 -0
  36. package/dist/components/ControlPanel.svelte +154 -0
  37. package/dist/components/ControlPanel.svelte.d.ts +19 -0
  38. package/dist/components/ControlPanel.svelte.d.ts.map +1 -0
  39. package/dist/components/DemandSlider.svelte +271 -0
  40. package/dist/components/DemandSlider.svelte.d.ts +4 -0
  41. package/dist/components/DemandSlider.svelte.d.ts.map +1 -0
  42. package/dist/components/DisplayControls.svelte +81 -0
  43. package/dist/components/DisplayControls.svelte.d.ts +19 -0
  44. package/dist/components/DisplayControls.svelte.d.ts.map +1 -0
  45. package/dist/components/DropZone.svelte +46 -0
  46. package/dist/components/DropZone.svelte.d.ts +19 -0
  47. package/dist/components/DropZone.svelte.d.ts.map +1 -0
  48. package/dist/components/FormulationSelector.svelte +82 -0
  49. package/dist/components/FormulationSelector.svelte.d.ts +19 -0
  50. package/dist/components/FormulationSelector.svelte.d.ts.map +1 -0
  51. package/dist/components/LocalCaseDetails.svelte +253 -0
  52. package/dist/components/LocalCaseDetails.svelte.d.ts +4 -0
  53. package/dist/components/LocalCaseDetails.svelte.d.ts.map +1 -0
  54. package/dist/components/MulticonductorDetails.svelte +280 -0
  55. package/dist/components/MulticonductorDetails.svelte.d.ts +19 -0
  56. package/dist/components/MulticonductorDetails.svelte.d.ts.map +1 -0
  57. package/dist/components/NetworkStats.svelte +75 -0
  58. package/dist/components/NetworkStats.svelte.d.ts +19 -0
  59. package/dist/components/NetworkStats.svelte.d.ts.map +1 -0
  60. package/dist/components/PlacementCue.svelte +35 -0
  61. package/dist/components/PlacementCue.svelte.d.ts +19 -0
  62. package/dist/components/PlacementCue.svelte.d.ts.map +1 -0
  63. package/dist/components/RatingSlider.svelte +273 -0
  64. package/dist/components/RatingSlider.svelte.d.ts +4 -0
  65. package/dist/components/RatingSlider.svelte.d.ts.map +1 -0
  66. package/dist/components/RestoreDefaultsButton.svelte +34 -0
  67. package/dist/components/RestoreDefaultsButton.svelte.d.ts +19 -0
  68. package/dist/components/RestoreDefaultsButton.svelte.d.ts.map +1 -0
  69. package/dist/components/SensitivityReadout.svelte +126 -0
  70. package/dist/components/SensitivityReadout.svelte.d.ts +4 -0
  71. package/dist/components/SensitivityReadout.svelte.d.ts.map +1 -0
  72. package/dist/components/SizeLegend.svelte +55 -0
  73. package/dist/components/SizeLegend.svelte.d.ts +19 -0
  74. package/dist/components/SizeLegend.svelte.d.ts.map +1 -0
  75. package/dist/components/SolveCard.svelte +84 -0
  76. package/dist/components/SolveCard.svelte.d.ts +4 -0
  77. package/dist/components/SolveCard.svelte.d.ts.map +1 -0
  78. package/dist/components/TopMovers.svelte +68 -0
  79. package/dist/components/TopMovers.svelte.d.ts +19 -0
  80. package/dist/components/TopMovers.svelte.d.ts.map +1 -0
  81. package/dist/components.d.ts +19 -0
  82. package/dist/components.d.ts.map +1 -0
  83. package/dist/components.js +18 -0
  84. package/dist/context.svelte.d.ts +20 -0
  85. package/dist/context.svelte.d.ts.map +1 -0
  86. package/dist/context.svelte.js +43 -0
  87. package/dist/controller.svelte.d.ts +334 -0
  88. package/dist/controller.svelte.d.ts.map +1 -0
  89. package/dist/controller.svelte.js +2026 -0
  90. package/dist/display.d.ts +31 -0
  91. package/dist/display.d.ts.map +1 -0
  92. package/dist/display.js +63 -0
  93. package/dist/drop-classify.d.ts +48 -0
  94. package/dist/drop-classify.d.ts.map +1 -0
  95. package/dist/drop-classify.js +92 -0
  96. package/dist/format.d.ts +30 -0
  97. package/dist/format.d.ts.map +1 -0
  98. package/dist/format.js +49 -0
  99. package/dist/index.d.ts +21 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +12 -0
  102. package/dist/map.d.ts +9 -0
  103. package/dist/map.d.ts.map +1 -0
  104. package/dist/map.js +4 -0
  105. package/dist/multiconductor.d.ts +63 -0
  106. package/dist/multiconductor.d.ts.map +1 -0
  107. package/dist/multiconductor.js +255 -0
  108. package/dist/state.svelte.d.ts +258 -0
  109. package/dist/state.svelte.d.ts.map +1 -0
  110. package/dist/state.svelte.js +323 -0
  111. package/dist/study-package.d.ts +9 -0
  112. package/dist/study-package.d.ts.map +1 -0
  113. package/dist/study-package.js +17 -0
  114. package/dist/styles.css +393 -0
  115. package/dist/synthetic-layout.d.ts +12 -0
  116. package/dist/synthetic-layout.d.ts.map +1 -0
  117. package/dist/synthetic-layout.js +271 -0
  118. package/dist/types.d.ts +6 -0
  119. package/dist/types.d.ts.map +1 -0
  120. package/dist/types.js +1 -0
  121. package/package.json +67 -0
@@ -0,0 +1,31 @@
1
+ import type { BranchRatingDeltas, DemandDeltas } from './api.js';
2
+ import { type DisplayMode, type SolvableCase } from './state.svelte.js';
3
+ /** One bus-color variable the panel and map can show, without its per-bus values.
4
+ * The values for the active mode are fetched separately via `displaySeriesFor`, so
5
+ * inactive modes never build an array nobody reads. */
6
+ export type DisplayOption = {
7
+ mode: DisplayMode;
8
+ label: string;
9
+ unit: string;
10
+ copy: string;
11
+ gradient: string;
12
+ };
13
+ /** The display variables available for a case's current solution and formulation:
14
+ * LMP always, the DC phase angle under DC OPF, the relaxed |V| under SOCWR. Metadata
15
+ * only; call `displaySeriesFor` for one mode's per-bus values. Empty when unsolved. */
16
+ export declare function displayMetaFor(c: SolvableCase | null): DisplayOption[];
17
+ /** Per-bus values for one display mode: LMP in $/MWh, the DC phase angle in rad, or
18
+ * the SOCWR voltage magnitude (sqrt of the squared-voltage variable w, clamped at 0).
19
+ * Empty when the case is unsolved. Single source for both the panel legend stats and
20
+ * the map node coloring, so the |V| transform stays in one place. */
21
+ export declare function displaySeriesFor(c: SolvableCase | null, mode: DisplayMode): {
22
+ bus: number;
23
+ value: number;
24
+ }[];
25
+ /** The committed demand deltas for a case (MW from base, keyed by bus). A backend
26
+ * case always carries a deltas map; a local case defaults to an empty one. */
27
+ export declare function caseDeltas(c: SolvableCase): DemandDeltas;
28
+ /** The committed branch rating deltas for a case (MW from base, keyed by branch).
29
+ * The rating counterpart of `caseDeltas`. */
30
+ export declare function caseRatings(c: SolvableCase): BranchRatingDeltas;
31
+ //# sourceMappingURL=display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/lib/display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGjE,OAAO,EAAa,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEnF;;uDAEuD;AACvD,MAAM,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;uFAEuF;AACvF,wBAAgB,cAAc,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,aAAa,EAAE,CA8BtE;AAED;;;qEAGqE;AACrE,wBAAgB,gBAAgB,CAC/B,CAAC,EAAE,YAAY,GAAG,IAAI,EACtB,IAAI,EAAE,WAAW,GACf;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAQlC;AAED;8EAC8E;AAC9E,wBAAgB,UAAU,CAAC,CAAC,EAAE,YAAY,GAAG,YAAY,CAExD;AAED;6CAC6C;AAC7C,wBAAgB,WAAW,CAAC,CAAC,EAAE,YAAY,GAAG,kBAAkB,CAE/D"}
@@ -0,0 +1,63 @@
1
+ import { lmpGradient } from './colors.js';
2
+ import { priceCopy } from './format.js';
3
+ import { CaseState } from './state.svelte.js';
4
+ /** The display variables available for a case's current solution and formulation:
5
+ * LMP always, the DC phase angle under DC OPF, the relaxed |V| under SOCWR. Metadata
6
+ * only; call `displaySeriesFor` for one mode's per-bus values. Empty when unsolved. */
7
+ export function displayMetaFor(c) {
8
+ if (!c?.solution)
9
+ return [];
10
+ const options = [
11
+ {
12
+ mode: 'lmp',
13
+ label: 'LMP',
14
+ unit: '$/MWh',
15
+ copy: priceCopy(c.formulation),
16
+ gradient: lmpGradient
17
+ }
18
+ ];
19
+ if (c.formulation === 'dcopf' && c.solution.va.length > 0) {
20
+ options.push({
21
+ mode: 'angle',
22
+ label: 'angle',
23
+ unit: 'rad',
24
+ copy: 'DC bus voltage phase angle from the current OPF solution.',
25
+ gradient: lmpGradient
26
+ });
27
+ }
28
+ if (c.formulation === 'socwr' && c.solution.w.length > 0) {
29
+ options.push({
30
+ mode: 'voltage',
31
+ label: '|V|',
32
+ unit: 'pu',
33
+ copy: 'SOCWR voltage magnitude from the current relaxed solution.',
34
+ gradient: lmpGradient
35
+ });
36
+ }
37
+ return options;
38
+ }
39
+ /** Per-bus values for one display mode: LMP in $/MWh, the DC phase angle in rad, or
40
+ * the SOCWR voltage magnitude (sqrt of the squared-voltage variable w, clamped at 0).
41
+ * Empty when the case is unsolved. Single source for both the panel legend stats and
42
+ * the map node coloring, so the |V| transform stays in one place. */
43
+ export function displaySeriesFor(c, mode) {
44
+ const sol = c?.solution;
45
+ if (!sol)
46
+ return [];
47
+ if (mode === 'angle')
48
+ return sol.va;
49
+ if (mode === 'voltage') {
50
+ return sol.w.map((s) => ({ bus: s.bus, value: Math.sqrt(Math.max(0, s.value)) }));
51
+ }
52
+ return sol.lmp.map((s) => ({ bus: s.bus, value: s.usd_per_mwh }));
53
+ }
54
+ /** The committed demand deltas for a case (MW from base, keyed by bus). A backend
55
+ * case always carries a deltas map; a local case defaults to an empty one. */
56
+ export function caseDeltas(c) {
57
+ return c instanceof CaseState ? c.deltas : (c.deltas ?? {});
58
+ }
59
+ /** The committed branch rating deltas for a case (MW from base, keyed by branch).
60
+ * The rating counterpart of `caseDeltas`. */
61
+ export function caseRatings(c) {
62
+ return c instanceof CaseState ? c.ratings : (c.ratings ?? {});
63
+ }
@@ -0,0 +1,48 @@
1
+ /** The single owner of drop-file classification: given a file name or its JSON
2
+ * content, decide which ingest path handles it. Extension routing (`.dss`, and
3
+ * the balanced `.m`/`.raw`/`.aux` via `formatOf` in the engine) is name-based;
4
+ * everything under `.json` is content-sniffed here so there is one place that
5
+ * decides package-vs-case and balanced-vs-multiconductor.
6
+ *
7
+ * The rules mirror the readers they feed:
8
+ * - a `.pio.json` package is recognized by its `schema` envelope field, then
9
+ * split by the authoritative `model_kind` (balanced restores a study;
10
+ * multiconductor is viewed);
11
+ * - a non-package document is distribution JSON, PMD when it carries the
12
+ * `data_model` marker and BMOPF otherwise (the same split
13
+ * `powerio_dist` uses for `.json`), except a GeoJSON FeatureCollection,
14
+ * which stays unrouted so the geo sidecar path keeps accepting it.
15
+ *
16
+ * Every function is total: malformed, truncated, or non-JSON input classifies
17
+ * as `not-json` rather than throwing. */
18
+ /** The schema URL prefix every `.pio.json` package envelope carries. */
19
+ export declare const PIO_PACKAGE_SCHEMA_PREFIX = "https://powerio.dev/schema/pio-package";
20
+ /** How a dropped JSON file should be ingested. */
21
+ export type JsonDropKind =
22
+ /** A saved balanced study package: restore the case, edits, and formulation. */
23
+ 'balanced-package'
24
+ /** A package carrying a multiconductor payload: view it (no solve). */
25
+ | 'multiconductor-package'
26
+ /** A BMOPF JSON distribution case. */
27
+ | 'bmopf'
28
+ /** A PowerModelsDistribution ENGINEERING JSON case. */
29
+ | 'pmd'
30
+ /** Not JSON, or JSON we do not route (left to the generic error path). */
31
+ | 'not-json';
32
+ /** The distribution format for a file recognized by extension, or null. Only
33
+ * `.dss` is name-routed; PMD and BMOPF share the `.json` extension and are
34
+ * content-sniffed by {@link classifyJson}. */
35
+ export declare function distExtensionFormat(name: string): 'dss' | null;
36
+ /** True for geographic sidecar files by extension (`.csv`, `.json`,
37
+ * `.geojson`). Routable `.json` content (packages, distribution documents) is
38
+ * consumed by {@link classifyJson} before this applies; what remains parses
39
+ * through the engine's tolerant geo reader. */
40
+ export declare function isGeoFileName(name: string): boolean;
41
+ /** Whether `text` is a `.pio.json` package envelope, by its `schema` field. */
42
+ export declare function isPackageEnvelope(obj: Record<string, unknown> | null): boolean;
43
+ /** Classify a dropped JSON document into its ingest path. */
44
+ export declare function classifyJson(text: string): JsonDropKind;
45
+ /** Whether `text` is a saved study package (a balanced `.pio.json`). Kept for
46
+ * the study-restore path; multiconductor packages are viewed, not restored. */
47
+ export declare function isStudyPackageText(text: string): boolean;
48
+ //# sourceMappingURL=drop-classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drop-classify.d.ts","sourceRoot":"","sources":["../src/lib/drop-classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;yCAgByC;AAEzC,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,2CAA2C,CAAC;AAElF,kDAAkD;AAClD,MAAM,MAAM,YAAY;AACvB,gFAAgF;AAC9E,kBAAkB;AACpB,uEAAuE;GACrE,wBAAwB;AAC1B,sCAAsC;GACpC,OAAO;AACT,uDAAuD;GACrD,KAAK;AACP,0EAA0E;GACxE,UAAU,CAAC;AAEd;;8CAE8C;AAC9C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAE9D;AAED;;;+CAG+C;AAC/C,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKnD;AAeD,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO,CAE9E;AAaD,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAkBvD;AAED;+EAC+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD"}
@@ -0,0 +1,92 @@
1
+ /** The single owner of drop-file classification: given a file name or its JSON
2
+ * content, decide which ingest path handles it. Extension routing (`.dss`, and
3
+ * the balanced `.m`/`.raw`/`.aux` via `formatOf` in the engine) is name-based;
4
+ * everything under `.json` is content-sniffed here so there is one place that
5
+ * decides package-vs-case and balanced-vs-multiconductor.
6
+ *
7
+ * The rules mirror the readers they feed:
8
+ * - a `.pio.json` package is recognized by its `schema` envelope field, then
9
+ * split by the authoritative `model_kind` (balanced restores a study;
10
+ * multiconductor is viewed);
11
+ * - a non-package document is distribution JSON, PMD when it carries the
12
+ * `data_model` marker and BMOPF otherwise (the same split
13
+ * `powerio_dist` uses for `.json`), except a GeoJSON FeatureCollection,
14
+ * which stays unrouted so the geo sidecar path keeps accepting it.
15
+ *
16
+ * Every function is total: malformed, truncated, or non-JSON input classifies
17
+ * as `not-json` rather than throwing. */
18
+ /** The schema URL prefix every `.pio.json` package envelope carries. */
19
+ export const PIO_PACKAGE_SCHEMA_PREFIX = 'https://powerio.dev/schema/pio-package';
20
+ /** The distribution format for a file recognized by extension, or null. Only
21
+ * `.dss` is name-routed; PMD and BMOPF share the `.json` extension and are
22
+ * content-sniffed by {@link classifyJson}. */
23
+ export function distExtensionFormat(name) {
24
+ return name.split('.').pop()?.toLowerCase() === 'dss' ? 'dss' : null;
25
+ }
26
+ /** True for geographic sidecar files by extension (`.csv`, `.json`,
27
+ * `.geojson`). Routable `.json` content (packages, distribution documents) is
28
+ * consumed by {@link classifyJson} before this applies; what remains parses
29
+ * through the engine's tolerant geo reader. */
30
+ export function isGeoFileName(name) {
31
+ const dot = name.lastIndexOf('.');
32
+ if (dot <= 0)
33
+ return false;
34
+ const ext = name.slice(dot + 1).toLowerCase();
35
+ return ext === 'csv' || ext === 'json' || ext === 'geojson';
36
+ }
37
+ /** Parse `text` as JSON, returning the top-level object or null. */
38
+ function topLevelObject(text) {
39
+ let value;
40
+ try {
41
+ value = JSON.parse(text);
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
47
+ ? value
48
+ : null;
49
+ }
50
+ /** Whether `text` is a `.pio.json` package envelope, by its `schema` field. */
51
+ export function isPackageEnvelope(obj) {
52
+ return typeof obj?.schema === 'string' && obj.schema.startsWith(PIO_PACKAGE_SCHEMA_PREFIX);
53
+ }
54
+ /** The package's model family. `model_kind` is authoritative and stored
55
+ * explicitly; fall back to the payload's own `model.kind` tag for a package
56
+ * written before the field existed. */
57
+ function packageModelKind(obj) {
58
+ const explicit = obj.model_kind;
59
+ if (explicit === 'balanced' || explicit === 'multiconductor')
60
+ return explicit;
61
+ const payloadKind = obj.model?.kind;
62
+ if (payloadKind === 'balanced' || payloadKind === 'multiconductor')
63
+ return payloadKind;
64
+ return null;
65
+ }
66
+ /** Classify a dropped JSON document into its ingest path. */
67
+ export function classifyJson(text) {
68
+ const obj = topLevelObject(text);
69
+ if (!obj)
70
+ return 'not-json';
71
+ if (isPackageEnvelope(obj)) {
72
+ const kind = packageModelKind(obj);
73
+ // A package with no readable kind is treated as balanced: that is the
74
+ // historical payload and the study-restore path fails closed on a
75
+ // non-balanced document anyway.
76
+ return kind === 'multiconductor' ? 'multiconductor-package' : 'balanced-package';
77
+ }
78
+ // A GeoJSON FeatureCollection saved as `.json` is coordinate data for the
79
+ // geo sidecar path, which accepted it before this classifier existed; leave
80
+ // it unrouted so it falls through.
81
+ if (Array.isArray(obj.features))
82
+ return 'not-json';
83
+ // Non-package JSON is a distribution document: PMD declares `data_model`,
84
+ // everything else is routed to BMOPF (which gives the precise parse error
85
+ // when it is neither).
86
+ return 'data_model' in obj ? 'pmd' : 'bmopf';
87
+ }
88
+ /** Whether `text` is a saved study package (a balanced `.pio.json`). Kept for
89
+ * the study-restore path; multiconductor packages are viewed, not restored. */
90
+ export function isStudyPackageText(text) {
91
+ return classifyJson(text) === 'balanced-package';
92
+ }
@@ -0,0 +1,30 @@
1
+ import type { SolveIteration } from './api.js';
2
+ import type { RGBA } from './colors.js';
3
+ import type { DisplayMode, SolveBackend } from './state.svelte.js';
4
+ import { type Formulation } from '@tellegen/engine';
5
+ export { errorText } from '@tellegen/engine';
6
+ /** The short menu label for a formulation tag (e.g. `acopf` -> `AC OPF`). */
7
+ export declare function formulationLabel(id: Formulation): string;
8
+ export declare function formulationHint(id: Formulation): string;
9
+ export declare function priceCopy(id: Formulation): string;
10
+ export declare function splitName(name: string): [string, string];
11
+ /** Structural shape `solveMetaLabel` needs, satisfied by `CaseState` and `LocalCase`. */
12
+ type SolveMeta = {
13
+ iterations?: SolveIteration[];
14
+ solveBackend: SolveBackend | null;
15
+ };
16
+ export declare function solveMetaLabel(c: SolveMeta): string;
17
+ export declare function rgbaCss([r, g, b, a]: RGBA): string;
18
+ /** Min and max of a numeric array in one pass. Used instead of
19
+ * `Math.min(...values)` / `Math.max(...values)`, which throw a RangeError once the
20
+ * argument count exceeds the engine limit (~65k on JavaScriptCore) — reachable on a
21
+ * dropped case with tens of thousands of buses. */
22
+ export declare function extent(values: number[]): {
23
+ min: number;
24
+ max: number;
25
+ };
26
+ export declare const fmt: Intl.NumberFormat;
27
+ export declare const signed: (v: number) => string;
28
+ export declare const signedExp: (v: number) => string;
29
+ export declare const displayFmt: (mode: DisplayMode, value: number) => string;
30
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/lib/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIlE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAExD;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAEvD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAIjD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAGxD;AAED,yFAAyF;AACzF,KAAK,SAAS,GAAG;IAAE,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAA;CAAE,CAAC;AAEtF,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAInD;AAED,wBAAgB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAElD;AAED;;;mDAGmD;AACnD,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAQrE;AAED,eAAO,MAAM,GAAG,mBAA+D,CAAC;AAChF,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,WAAqD,CAAC;AACtF,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,WAA0D,CAAC;AAC9F,eAAO,MAAM,UAAU,GAAI,MAAM,WAAW,EAAE,OAAO,MAAM,WACL,CAAC"}
package/dist/format.js ADDED
@@ -0,0 +1,49 @@
1
+ import { FORMULATIONS } from '@tellegen/engine';
2
+ // errorText is defined once in wasm.ts (its first consumer) and surfaced here so UI
3
+ // code can import it alongside the other formatting helpers.
4
+ export { errorText } from '@tellegen/engine';
5
+ /** The short menu label for a formulation tag (e.g. `acopf` -> `AC OPF`). */
6
+ export function formulationLabel(id) {
7
+ return FORMULATIONS.find((f) => f.id === id)?.label ?? id;
8
+ }
9
+ export function formulationHint(id) {
10
+ return FORMULATIONS.find((f) => f.id === id)?.hint ?? id;
11
+ }
12
+ export function priceCopy(id) {
13
+ return id === 'socwr'
14
+ ? 'Select a bus to see how relaxed prices change.'
15
+ : 'Select a bus to see how prices change.';
16
+ }
17
+ export function splitName(name) {
18
+ const m = name.match(/^(.*?)\s*\((.*)\)$/);
19
+ return m ? [m[1], m[2]] : [name, ''];
20
+ }
21
+ export function solveMetaLabel(c) {
22
+ if ((c.iterations ?? []).length > 1)
23
+ return `${c.iterations?.length} iterations`;
24
+ if (c.solveBackend === 'clarabel-wasm-server-sensitivity')
25
+ return 'server dLMP/dd';
26
+ return c.solveBackend === 'rust-server' ? 'server solve' : 'browser solve';
27
+ }
28
+ export function rgbaCss([r, g, b, a]) {
29
+ return `rgba(${r}, ${g}, ${b}, ${(a / 255).toFixed(3)})`;
30
+ }
31
+ /** Min and max of a numeric array in one pass. Used instead of
32
+ * `Math.min(...values)` / `Math.max(...values)`, which throw a RangeError once the
33
+ * argument count exceeds the engine limit (~65k on JavaScriptCore) — reachable on a
34
+ * dropped case with tens of thousands of buses. */
35
+ export function extent(values) {
36
+ let min = Infinity;
37
+ let max = -Infinity;
38
+ for (const v of values) {
39
+ if (v < min)
40
+ min = v;
41
+ if (v > max)
42
+ max = v;
43
+ }
44
+ return { min, max };
45
+ }
46
+ export const fmt = new Intl.NumberFormat('en-US', { maximumFractionDigits: 1 });
47
+ export const signed = (v) => `${v < 0 ? '−' : '+'}${fmt.format(Math.abs(v))}`;
48
+ export const signedExp = (v) => `${v < 0 ? '−' : '+'}${Math.abs(v).toExponential(2)}`;
49
+ export const displayFmt = (mode, value) => mode === 'lmp' ? fmt.format(value) : value.toFixed(3);
@@ -0,0 +1,21 @@
1
+ export { default as TellegenProvider } from './TellegenProvider.svelte';
2
+ export { default as TellegenShell } from './TellegenShell.svelte';
3
+ export { default as TellegenViewer } from './TellegenViewer.svelte';
4
+ export { default as TellegenMap } from './TellegenMap.svelte';
5
+ export { DEFAULT_TELLEGEN_UI_CONFIG, getAppState, getController, getUiConfig, resolveTellegenUiConfig, setAppState, setController, setUiConfig } from './context.svelte.js';
6
+ export { ApiError, createApiClient } from './api.js';
7
+ export { Controller, createController } from './controller.svelte.js';
8
+ export { AppState, CaseState, LocalCase, MulticonductorCase, createAppState } from './state.svelte.js';
9
+ export { attachmentColor, attachmentGlyph, edgeColor, edgeWidth, phaseColor, placeMultiView, buildGeographicView } from './multiconductor.js';
10
+ export { classifyJson, distExtensionFormat, isStudyPackageText } from './drop-classify.js';
11
+ export { caseDeltas, caseRatings, displayMetaFor, displaySeriesFor } from './display.js';
12
+ export { DEFAULT_FORMULATION, FORMULATIONS, BrowserStudy, Study, capabilities, createStudy, errorText, formatOf, ingestCase, isDisplayFile, isPermanentEngineFailure, parseDisplay, solveJson } from '@tellegen/engine';
13
+ export type { BranchRatingDeltas, CaseSummary, DemandDeltas, Network, NetworkBranch, NetworkBus, SensitivityColumn, Solution, SolveIteration, SolveStreamHandlers, TellegenApiClient, TellegenApiClientOptions } from './api.js';
14
+ export type { TellegenUiConfig, TellegenUiOptions } from './context.svelte.js';
15
+ export type { ControllerOptions } from './controller.svelte.js';
16
+ export type { DisplayOption } from './display.js';
17
+ export type { DemandRangeMode, DisplayMode, FallbackTarget, LocalCaseInit, LocalSubstations, MultiCaseSummary, MultiCoordsKind, SolvableCase, SolveBackend } from './state.svelte.js';
18
+ export type { JsonDropKind } from './drop-classify.js';
19
+ export type { MultiView, PlacedMultiBus, PlacedMultiEdge } from './multiconductor.js';
20
+ export type { CaseFileSummary, DistAttachmentKind, DistEdgeKind, DistGraph, DistGraphAttachment, DistGraphBus, DistGraphEdge, DisplayPreview, Formulation, IngestedCase, IngestedDistCase, SensTarget, Topology, TopologyBranch, TopologyBus } from '@tellegen/engine';
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EACN,0BAA0B,EAC1B,WAAW,EACX,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,WAAW,EACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACN,QAAQ,EACR,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,cAAc,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,eAAe,EACf,eAAe,EACf,SAAS,EACT,SAAS,EACT,UAAU,EACV,cAAc,EACd,mBAAmB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE3F,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzF,OAAO,EACN,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,KAAK,EACL,YAAY,EACZ,WAAW,EACX,SAAS,EACT,QAAQ,EACR,UAAU,EACV,aAAa,EACb,wBAAwB,EACxB,YAAY,EACZ,SAAS,EACT,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACX,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,OAAO,EACP,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,QAAQ,EACR,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,EACxB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EACX,SAAS,EACT,cAAc,EACd,eAAe,EACf,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACX,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,QAAQ,EACR,cAAc,EACd,WAAW,EACX,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ export { default as TellegenProvider } from './TellegenProvider.svelte';
2
+ export { default as TellegenShell } from './TellegenShell.svelte';
3
+ export { default as TellegenViewer } from './TellegenViewer.svelte';
4
+ export { default as TellegenMap } from './TellegenMap.svelte';
5
+ export { DEFAULT_TELLEGEN_UI_CONFIG, getAppState, getController, getUiConfig, resolveTellegenUiConfig, setAppState, setController, setUiConfig } from './context.svelte.js';
6
+ export { ApiError, createApiClient } from './api.js';
7
+ export { Controller, createController } from './controller.svelte.js';
8
+ export { AppState, CaseState, LocalCase, MulticonductorCase, createAppState } from './state.svelte.js';
9
+ export { attachmentColor, attachmentGlyph, edgeColor, edgeWidth, phaseColor, placeMultiView, buildGeographicView } from './multiconductor.js';
10
+ export { classifyJson, distExtensionFormat, isStudyPackageText } from './drop-classify.js';
11
+ export { caseDeltas, caseRatings, displayMetaFor, displaySeriesFor } from './display.js';
12
+ export { DEFAULT_FORMULATION, FORMULATIONS, BrowserStudy, Study, capabilities, createStudy, errorText, formatOf, ingestCase, isDisplayFile, isPermanentEngineFailure, parseDisplay, solveJson } from '@tellegen/engine';
package/dist/map.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { ComponentProps } from 'svelte';
2
+ import TellegenMap from './TellegenMap.svelte';
3
+ export { default as TellegenMap } from './TellegenMap.svelte';
4
+ export { branchColor, branchWidth, busNeutral, busRadius, lmpColor, lmpDomain, lmpGradient, scalarDomain, sensColor, sensFlatColor, sensGradient, sensNeutral, sensitivityDomain } from './colors.js';
5
+ export { caseDeltas, displayMetaFor, displaySeriesFor } from './display.js';
6
+ export type { RGBA, SensitivityDomain } from './colors.js';
7
+ export type { DisplayOption } from './display.js';
8
+ export type TellegenMapProps = ComponentProps<typeof TellegenMap>;
9
+ //# sourceMappingURL=map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/lib/map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EACN,WAAW,EACX,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,SAAS,EACT,aAAa,EACb,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC5E,YAAY,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,WAAW,CAAC,CAAC"}
package/dist/map.js ADDED
@@ -0,0 +1,4 @@
1
+ import TellegenMap from './TellegenMap.svelte';
2
+ export { default as TellegenMap } from './TellegenMap.svelte';
3
+ export { branchColor, branchWidth, busNeutral, busRadius, lmpColor, lmpDomain, lmpGradient, scalarDomain, sensColor, sensFlatColor, sensGradient, sensNeutral, sensitivityDomain } from './colors.js';
4
+ export { caseDeltas, displayMetaFor, displaySeriesFor } from './display.js';
@@ -0,0 +1,63 @@
1
+ /** Pure helpers for the multiconductor viewing path: place a distribution
2
+ * bus/terminal graph onto the map, and the phase/edge/attachment palette the
3
+ * layers and the terminal detail share. No solve, no reactive state here — the
4
+ * `MulticonductorCase` state and the map own those. */
5
+ import type { DistAttachmentKind, DistEdgeKind, DistGraph, DistGraphAttachment } from '@tellegen/engine';
6
+ import { type PlacementCenter } from './synthetic-layout.js';
7
+ import type { RGBA } from './colors.js';
8
+ /** A bus positioned on the map, carrying its terminal-level detail. */
9
+ export interface PlacedMultiBus {
10
+ id: string;
11
+ lon: number;
12
+ lat: number;
13
+ terminals: string[];
14
+ grounded: string[];
15
+ load_kw: number;
16
+ gen_kw: number;
17
+ has_source: boolean;
18
+ /** Distinct attachment kinds on the bus, in a stable order, for the badges. */
19
+ attachmentKinds: DistAttachmentKind[];
20
+ terminalAttachments: Record<string, DistGraphAttachment[]>;
21
+ }
22
+ /** An edge positioned on the map: a two-point path plus its typed detail. */
23
+ export interface PlacedMultiEdge {
24
+ id: string;
25
+ kind: DistEdgeKind;
26
+ from: string;
27
+ to: string;
28
+ conductors: [string, string][];
29
+ closed: boolean;
30
+ n_phases: number;
31
+ path: [[number, number], [number, number]];
32
+ }
33
+ /** The placed graph the map renders. */
34
+ export interface MultiView {
35
+ buses: PlacedMultiBus[];
36
+ edges: PlacedMultiEdge[];
37
+ }
38
+ /** Place a geographic graph: each bus's `xy` is `[longitude, latitude]` and
39
+ * drops straight onto the map. */
40
+ export declare function buildGeographicView(graph: DistGraph): MultiView;
41
+ /** Place a non-geographic graph at a map `center`: fit the provided planar
42
+ * coordinates when the case carries them, otherwise fall back to the shared
43
+ * synthetic force layout. */
44
+ export declare function placeMultiView(graph: DistGraph, center: PlacementCenter): MultiView;
45
+ /** Color a conductor by its terminal name. OpenDSS node numbers map 1/2/3 to
46
+ * the three phases; a named phase (`a`/`b`/`c`) maps the same way; anything else
47
+ * (neutral `n`, ground, the fourth wire) is the neutral gray. */
48
+ export declare function phaseColor(terminal: string): RGBA;
49
+ /** True when a terminal is a phase conductor (not a neutral/ground return). */
50
+ export declare function isPhaseTerminal(terminal: string): boolean;
51
+ /** Base color for an edge by kind and state. Lines are the warm gray of the
52
+ * single-phase branches; transformers are steel; a switch is amber when closed
53
+ * and a faded red when open. */
54
+ export declare function edgeColor(kind: DistEdgeKind, closed: boolean): RGBA;
55
+ /** Edge stroke width in pixels, growing with conductor count so a three-phase
56
+ * feeder reads heavier than a single-phase lateral. Transformers draw a touch
57
+ * wider to stand out as the equipment they are. */
58
+ export declare function edgeWidth(kind: DistEdgeKind, nPhases: number): number;
59
+ /** Badge color for an attachment kind. */
60
+ export declare function attachmentColor(kind: DistAttachmentKind): RGBA;
61
+ /** A short glyph for an attachment kind, for the panel legend and badges. */
62
+ export declare function attachmentGlyph(kind: DistAttachmentKind): string;
63
+ //# sourceMappingURL=multiconductor.d.ts.map
@@ -0,0 +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"}