Co-Study4Grid / frontend /src /types.ts
github-actions[bot]
Deploy 7688ef1
13d4e44
Raw
History Blame Contribute Delete
29 kB
// Copyright (c) 2025-2026, RTE (https://www.rte-france.com)
// This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
// If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0
// This file is part of Co-Study4Grid a Power Grid Study tool Assistant Interface to help solve contigencies for a grid state under study.
export interface ConfigRequest {
network_path: string;
action_file_path: string;
min_line_reconnections: number;
min_close_coupling: number;
min_open_coupling: number;
min_line_disconnections: number;
min_pst?: number;
min_load_shedding?: number;
min_renewable_curtailment_actions?: number;
min_redispatch?: number;
allowed_action_types?: string[];
n_prioritized_actions: number;
lines_monitoring_path?: string;
monitoring_factor: number;
pre_existing_overload_threshold?: number;
ignore_reconnections?: boolean;
pypowsybl_fast_mode?: boolean;
layout_path?: string;
// Pluggable recommender selection. ``model`` is the registry key
// (e.g. "expert", "random", "random_overflow" or a third-party
// plugin name); ``compute_overflow_graph`` toggles the (expensive)
// step-2 graph build for models that don't strictly require it.
model?: string;
compute_overflow_graph?: boolean;
}
export interface AnalysisRequest {
/**
* Ordered list of element IDs to disconnect simultaneously. A
* single-item list is the legacy N-1 case; longer lists drive
* N-K (multi-element) contingency studies.
*/
disconnected_elements: string[];
}
export interface ActionTopology {
lines_ex_bus: Record<string, number>;
lines_or_bus: Record<string, number>;
gens_bus: Record<string, number>;
loads_bus: Record<string, number>;
pst_tap?: Record<string, number>;
substations?: Record<string, unknown>;
switches?: Record<string, unknown>;
loads_p?: Record<string, number>;
gens_p?: Record<string, number>;
// Backend-supplied VoltageLevelId hint surfaced from the
// dict_action entry for pypowsybl switch-based / coupling
// actions. Highest-priority signal for the Action Overview pin
// anchor and the ActionCard VL chip.
voltage_level_id?: string;
}
export interface LoadSheddingDetail {
load_name: string;
voltage_level_id: string | null;
shedded_mw: number;
}
export interface CurtailmentDetail {
gen_name: string;
voltage_level_id: string | null;
curtailed_mw: number;
}
export interface PstDetail {
pst_name: string;
tap_position: number;
low_tap: number | null;
high_tap: number | null;
}
export interface RedispatchDetail {
gen_name: string;
voltage_level_id: string | null;
// Signed MW change applied to the generator: > 0 raises production,
// < 0 lowers it.
delta_mw: number;
// Resulting production magnitude (MW) after the redispatch.
target_mw: number;
direction: 'up' | 'down';
// Current production (MW) before the redispatch.
current_mw?: number;
// Maximum further raise / lower (MW) bounded by the generator's
// [min_p, max_p] active-power limits. Null when unknown.
max_raise_mw?: number | null;
max_lower_mw?: number | null;
}
export interface ActionDetail {
description_unitaire: string;
rho_before: number[] | null;
rho_after: number[] | null;
max_rho: number | null;
max_rho_line: string;
is_rho_reduction: boolean;
estimated_max_rho?: number | null;
estimated_max_rho_line?: string;
is_manual?: boolean;
is_estimated?: boolean;
is_islanded?: boolean;
n_components?: number;
disconnected_mw?: number;
non_convergence?: string | null;
action_topology?: ActionTopology;
lines_overloaded_after?: string[];
/**
* ``{line_name: live_end_reactive_mvar}`` for still-"overloaded" lines the
* action leaves open at ONE end with a loading above ~1 %. Such a line is
* out of service for active power (the SLD / NAD show p = 0) but its
* capacitance draws reactive charging current from the live end, so its
* current-based loading stays non-zero (the reported ~33 %). The ActionCard
* annotates the loading with the reactive amount so it reads as charging
* current, not a residual overload. Backend: ``half_open_branch_reactive_from_obs``.
*/
half_open_overloads?: Record<string, number>;
load_shedding_details?: LoadSheddingDetail[];
curtailment_details?: CurtailmentDetail[];
redispatch_details?: RedispatchDetail[];
pst_details?: PstDetail[];
/**
* Provenance of the action card — distinct from `is_manual`, which
* is an overloaded UI-state flag (it's also stamped `true` when the
* operator stars a recommender suggestion). `origin` records where
* the action *came from* and never changes after creation:
* - `"user"` — the operator simulated it themselves (manual
* search dropdown, "Make a first guess").
* - `<model id>` — produced / scored by a recommender model
* (e.g. `"expert"`, `"random_overflow"`); this
* is the `active_model` echoed by the step-2
* `result` event, and also covers an
* unsimulated pin the operator materialised
* (it was scored by that model).
* Optional for backward compat: legacy sessions that predate the
* field get an `origin` derived from their saved status flags on
* reload (see `useSession.handleRestoreSession`).
*/
origin?: string;
}
export interface CombinedAction {
action1_id: string;
action2_id: string;
betas: number[];
p_or_combined: number[];
max_rho: number;
max_rho_line: string;
is_rho_reduction: boolean;
description: string;
rho_after: number[];
rho_before: number[];
is_islanded?: boolean;
disconnected_mw?: number;
estimated_max_rho?: number | null;
estimated_max_rho_line?: string;
target_max_rho?: number | null;
target_max_rho_line?: string;
error?: string;
}
export interface AnalysisResult {
pdf_path: string | null;
pdf_url: string | null;
actions: Record<string, ActionDetail>;
action_scores?: Record<string, { scores: Record<string, number>; mw_start?: Record<string, number | null>; tap_start?: Record<string, { pst_name: string; tap: number; low_tap: number | null; high_tap: number | null } | null> }>;
lines_overloaded: string[];
combined_actions?: Record<string, CombinedAction>;
message: string;
dc_fallback: boolean;
lines_we_care_about?: string[];
computed_pairs?: Record<string, unknown>;
// Identifier of the recommender model that produced the
// suggestions in this result (e.g. "expert", "random",
// "random_overflow", or a third-party plugin name). Echoed by
// the backend in every `result` SSE event from
// `/api/run-analysis-step2`; persisted in the saved session so
// a reload shows which model was active for the run.
active_model?: string;
// Whether the step-2 overflow-graph build actually ran for this
// analysis. True when the chosen model declares
// `requires_overflow_graph=true` OR the operator opted in via
// the Compute Overflow Graph toggle.
compute_overflow_graph?: boolean;
// Per-stage execution times (seconds), reported by the backend.
// `overflow_graph_time` is null when the active model does not
// consume the overflow graph (no time was spent building it); it is
// 0.0 on a cached re-run, so a model swap can be distinguished from
// a fresh run. Used by the ActionFeed reminder and the iframe's
// header to show the operator how long each stage took.
overflow_graph_time?: number | null;
action_prediction_time?: number;
assessment_time?: number;
// Step 1 (contingency simulation + overload detection) ran in a
// separate HTTP call before step 2. The backend echoes its
// wall-clock here so the breakdown can show the full pipeline.
step1_time?: number | null;
// Co-Study4Grid post-processing after assessment (action enrichment
// + combined-pair target_max_rho augmentation + MW-start scoring).
enrichment_time?: number;
// Frontend wall-clock from the "Analyze & Suggest" click until the
// result event arrives ("Display N prioritized actions" appears).
// Captures backend stages + network round-trip + NDJSON streaming
// overhead. Difference vs. the sum of the per-stage timings above
// is the "transit" overhead.
wall_clock_time?: number;
// Present only when the contingency islands a radial ("antenne")
// pocket: the overflow graph is a synthetic downstream graph of the
// disconnected zone and recommendations are injection-only (load
// shedding / curtailment / redispatch). Null/absent otherwise.
antenna_meta?: AntennaMeta | null;
}
// Describes the disconnected radial pocket of an islanded-contingency
// ("antenne") analysis. Mirrors the recommender's antenna_meta dict.
export interface AntennaMeta {
constraint_line_name: string;
root_sub_name: string;
antenna_sub_names: string[];
n_subs: number;
total_prod_mw: number;
total_load_mw: number;
net_mw: number;
// "producer" (net export → curtailment / redispatch-down) or
// "consumer" (net import → load shedding / redispatch-up).
direction: 'producer' | 'consumer';
}
export interface BranchResponse {
branches: string[];
/** Optional mapping from element ID to human-readable display name. */
name_map?: Record<string, string>;
}
/**
* Mapping from element/VL ID to a human-readable display name.
* Used throughout the UI to show real substation/circuit names.
*/
export type NameMap = Record<string, string>;
export interface DiagramData {
svg: string | SVGSVGElement;
metadata: unknown;
lf_converged?: boolean;
lf_status?: string;
action_id?: string;
flow_deltas?: Record<string, FlowDelta>;
reactive_flow_deltas?: Record<string, FlowDelta>;
asset_deltas?: Record<string, AssetDelta>;
originalViewBox?: ViewBox | null;
lines_overloaded?: string[];
lines_overloaded_rho?: number[];
}
export interface FlowDelta {
delta: number;
category: 'positive' | 'negative' | 'grey';
flip_arrow?: boolean;
}
export interface AssetDelta {
delta_p: number;
delta_q: number;
category: 'positive' | 'negative' | 'grey';
category_p?: 'positive' | 'negative' | 'grey';
category_q?: 'positive' | 'negative' | 'grey';
}
export interface ViewBox {
x: number;
y: number;
w: number;
h: number;
}
export interface NodeMeta {
equipmentId: string;
svgId: string;
x: number;
y: number;
legendSvgId?: string;
legendEdgeSvgId?: string;
[key: string]: unknown;
}
export interface EdgeInfoMeta {
svgId: string;
infoType?: string;
direction?: string;
externalLabel?: string;
}
export interface EdgeMeta {
equipmentId: string;
svgId: string;
node1: string;
node2: string;
edgeInfo1?: EdgeInfoMeta;
edgeInfo2?: EdgeInfoMeta;
[key: string]: unknown;
}
export interface MetadataIndex {
nodesByEquipmentId: Map<string, NodeMeta>;
nodesBySvgId: Map<string, NodeMeta>;
edgesByEquipmentId: Map<string, EdgeMeta>;
edgesByNode: Map<string, EdgeMeta[]>;
/** VL text-label (name box) svgId → its VL NodeMeta, so the label box can
* be interactive (open the SLD) exactly like the VL disk. Optional because
* the many hand-built MetadataIndex test fixtures omit it. */
textNodesBySvgId?: Map<string, NodeMeta>;
}
export interface DiagramPatch {
patchable: boolean;
reason?: string;
contingency_id?: string;
action_id?: string;
lf_converged: boolean;
lf_status: string;
non_convergence?: string | null;
disconnected_edges?: string[];
absolute_flows?: {
p1: Record<string, number>;
p2: Record<string, number>;
q1: Record<string, number>;
q2: Record<string, number>;
vl1: Record<string, string>;
vl2: Record<string, string>;
};
lines_overloaded?: string[];
lines_overloaded_rho?: number[];
flow_deltas?: Record<string, FlowDelta>;
reactive_flow_deltas?: Record<string, FlowDelta>;
asset_deltas?: Record<string, AssetDelta>;
vl_subtrees?: Record<string, {
node_svg: string;
node_sub_svg_id: string;
edge_fragments?: Record<string, { svg: string; sub_svg_id: string }>;
}>;
meta?: {
base_state?: 'N' | 'contingency';
elapsed_ms?: number;
};
}
export type TabId = 'n' | 'contingency' | 'action' | 'overflow';
export interface SettingsBackup {
networkPath?: string;
actionPath?: string;
outputFolderPath?: string;
minLineReconnections: number;
minCloseCoupling: number;
minOpenCoupling: number;
minLineDisconnections: number;
minLoadShedding: number;
minRenewableCurtailmentActions: number;
minRedispatch: number;
allowedActionTypes: string[];
nPrioritizedActions: number;
linesMonitoringPath: string;
monitoringFactor: number;
preExistingOverloadThreshold: number;
ignoreReconnections?: boolean;
pypowsyblFastMode?: boolean;
layoutPath?: string;
}
export interface RecommenderDisplayConfig {
minLineReconnections: number;
minCloseCoupling: number;
minOpenCoupling: number;
minLineDisconnections: number;
minPst: number;
minLoadShedding: number;
minRenewableCurtailmentActions: number;
minRedispatch: number;
nPrioritizedActions: number;
ignoreReconnections: boolean;
}
export interface AvailableAction {
id: string;
description: string;
type?: string;
}
export type SldTab = 'n' | 'contingency' | 'action';
export interface SldFeederNode {
id: string;
equipmentId: string;
componentType?: string;
direction?: string;
}
/**
* Baseline descriptor for one editable active-power injection (a load or
* generator) on the displayed SLD. Drives the interactive injection-edit
* bubble in ``useSldTopologyEdit`` / ``SldInjectionPopover``: the operator
* retunes ``p`` and the user-built action sends back the absolute setpoint
* as ``{loads_p|gens_p: {id: MW}}``. Backend populates this on every SLD
* endpoint via ``extract_vl_injections``.
*/
export interface VlInjection {
kind: 'generator' | 'load';
/** Current active-power setpoint (MW): ``target_p`` (gen) / ``p0`` (load). */
p: number | null;
/** Generator active-power capability bounds (MW); absent for loads. */
min_p?: number | null;
max_p?: number | null;
/** Generator energy source (e.g. ``WIND`` / ``NUCLEAR``); absent for loads. */
energy_source?: string;
}
/**
* Identity + display label for one branch feeder on the displayed SLD.
* Backend populates this on every SLD endpoint via ``build_feeder_labels``.
*
* ``label`` is the **name of the voltage level at the OTHER end** of the
* branch (+ a parallel-circuit index when several branches of this VL reach
* the same far-end VL) — far more interpretable than pypowsybl's default raw
* IIDM branch id. ``name`` carries the branch's friendly / operator name
* (e.g. ``MARSIL61PRAGN``) so an overloaded line reported by friendly name
* can be mapped back to its IIDM-id-keyed SLD cell for the overload halo.
*/
export interface FeederLabel {
/** Branch friendly (operator / grid2op) name; ``null`` when none. */
name: string | null;
/** Voltage-level id at the far end of the branch; ``null`` when unknown. */
other_vl: string | null;
/** Display label (far-end VL name + index); ``null`` → keep the default id. */
label: string | null;
}
export interface VlOverlay {
vlName: string;
actionId: string | null;
svg: string | null;
sldMetadata: string | null;
loading: boolean;
error: string | null;
tab: SldTab;
flow_deltas?: Record<string, FlowDelta>;
reactive_flow_deltas?: Record<string, FlowDelta>;
asset_deltas?: Record<string, AssetDelta>;
changed_switches?: Record<string, { from_open: boolean; to_open: boolean }>;
/**
* Branch feeder identities + relabel targets for the displayed VL, keyed
* by IIDM equipment id. Drives the feeder relabelling (other-end VL name)
* and the friendly-name → IIDM-id resolution that lets the overload halo
* land on the right cell. Backend populates via ``build_feeder_labels``.
*/
feeder_labels?: Record<string, FeederLabel>;
/**
* Baseline switch states for the displayed VL (``{switch_id:
* is_open}``). Drives the interactive SLD-edit feature in
* ``useSldTopologyEdit``: only switches present in this map are
* editable, and a toggle is computed as ``user_state !== baseline``.
* Backend populates this on every SLD endpoint via
* ``extract_vl_switch_states``.
*/
switch_states?: Record<string, boolean>;
/**
* Baseline active-power injections (loads + generators) for the
* displayed VL, keyed by equipment id. Drives the interactive
* injection-edit bubble: only equipment present here is editable, and
* a staged change is computed as ``user_setpoint !== baseline.p``.
* Backend populates this on every SLD endpoint via
* ``extract_vl_injections``.
*/
injections?: Record<string, VlInjection>;
}
// ===== Session Save =====
export interface SavedActionStatus {
is_selected: boolean;
is_suggested: boolean;
is_rejected: boolean;
is_manually_simulated: boolean;
}
export interface SavedActionEntry {
description_unitaire: string;
rho_before: number[] | null;
rho_after: number[] | null;
max_rho: number | null;
max_rho_line: string;
is_rho_reduction: boolean;
is_estimated?: boolean;
estimated_max_rho?: number | null;
estimated_max_rho_line?: string;
is_islanded?: boolean;
n_components?: number;
disconnected_mw?: number;
non_convergence?: string | null;
action_topology?: ActionTopology;
lines_overloaded_after?: string[];
/**
* ``{line_name: live_end_reactive_mvar}`` for still-"overloaded" lines the
* action leaves open at ONE end with a loading above ~1 %. Such a line is
* out of service for active power (the SLD / NAD show p = 0) but its
* capacitance draws reactive charging current from the live end, so its
* current-based loading stays non-zero (the reported ~33 %). The ActionCard
* annotates the loading with the reactive amount so it reads as charging
* current, not a residual overload. Backend: ``half_open_branch_reactive_from_obs``.
*/
half_open_overloads?: Record<string, number>;
load_shedding_details?: LoadSheddingDetail[];
curtailment_details?: CurtailmentDetail[];
redispatch_details?: RedispatchDetail[];
pst_details?: PstDetail[];
/**
* Provenance of the action — `"user"` or a recommender model id.
* Mirrors `ActionDetail.origin`. Optional: legacy session dumps
* that predate the field get an `origin` derived from the saved
* status flags + `analysis.active_model` on reload.
*/
origin?: string;
status: SavedActionStatus;
}
export interface SavedCombinedAction {
action1_id: string;
action2_id: string;
betas: number[];
max_rho: number;
max_rho_line: string;
is_rho_reduction: boolean;
description: string;
estimated_max_rho?: number | null;
estimated_max_rho_line?: string;
is_islanded?: boolean;
disconnected_mw?: number;
simulated_max_rho?: number | null;
simulated_max_rho_line?: string;
is_simulated: boolean;
}
export interface SessionResult {
saved_at: string;
configuration: {
network_path: string;
action_file_path: string;
layout_path: string;
min_line_reconnections: number;
min_close_coupling: number;
min_open_coupling: number;
min_line_disconnections: number;
min_pst: number;
min_load_shedding: number;
min_renewable_curtailment_actions?: number;
min_redispatch?: number;
allowed_action_types?: string[];
n_prioritized_actions: number;
lines_monitoring_path: string;
monitoring_factor: number;
pre_existing_overload_threshold: number;
ignore_reconnections: boolean;
pypowsybl_fast_mode: boolean;
// Registry key of the recommender model selected at the time
// the session was saved (e.g. "expert", "random",
// "random_overflow"). Persisted so a reload shows which model
// produced the suggestions.
model?: string;
// Whether the operator had the Compute Overflow Graph toggle
// on at save time. For models with
// `requires_overflow_graph=true` this is always effectively
// true; for opt-in models it captures the user choice.
compute_overflow_graph?: boolean;
};
contingency: {
disconnected_elements: string[];
disconnected_element?: string;
selected_overloads: string[];
monitor_deselected: boolean;
additional_lines_to_cut?: string[];
};
overloads: {
n_overloads: string[];
n1_overloads: string[];
resolved_overloads: string[];
n_overloads_rho?: number[];
n1_overloads_rho?: number[];
};
overflow_graph: {
pdf_url: string | null;
pdf_path: string | null;
} | null;
analysis: {
message: string;
dc_fallback: boolean;
action_scores: Record<string, Record<string, unknown>> | undefined;
actions: Record<string, SavedActionEntry>;
combined_actions: Record<string, SavedCombinedAction>;
lines_we_care_about?: string[] | null;
computed_pairs?: Record<string, unknown> | null;
// Model that produced this analysis result. Mirrors
// `configuration.model` but captured from the result event
// (= the model the backend actually executed, which may
// differ from the configured one when an unknown name
// silently falls back to the default).
active_model?: string | null;
// Whether step-2 overflow graph was actually computed for
// this run. Useful when reloading a session to know whether
// the Overflow Analysis tab will have content.
compute_overflow_graph?: boolean | null;
// Per-stage execution times (seconds), captured at run time.
// Optional for backward compatibility with sessions saved before
// the breakdown was added.
overflow_graph_time?: number | null;
action_prediction_time?: number | null;
assessment_time?: number | null;
step1_time?: number | null;
enrichment_time?: number | null;
wall_clock_time?: number | null;
} | null;
interaction_log?: InteractionLogEntry[];
}
// ===== Interaction Logging =====
export type InteractionType =
| 'config_loaded'
| 'settings_opened'
| 'settings_tab_changed'
| 'settings_applied'
| 'settings_cancelled'
| 'path_picked'
| 'contingency_selected'
| 'contingency_confirmed'
| 'contingency_element_added'
| 'contingency_element_removed'
| 'contingency_applied'
| 'analysis_step1_started'
| 'analysis_step1_completed'
| 'overload_toggled'
| 'additional_line_to_cut_toggled'
| 'recommender_model_changed'
| 'suggested_actions_cleared'
| 'analysis_step2_started'
| 'analysis_step2_completed'
| 'prioritized_actions_displayed'
| 'action_selected'
| 'action_deselected'
| 'action_favorited'
| 'action_unfavorited'
| 'action_rejected'
| 'action_unrejected'
| 'manual_action_simulated'
| 'action_mw_resimulated'
| 'pst_tap_resimulated'
| 'combine_modal_opened'
| 'combine_modal_closed'
| 'combine_pair_toggled'
| 'combine_pair_estimated'
| 'combine_pair_simulated'
| 'diagram_tab_changed'
| 'tab_detached'
| 'tab_reattached'
| 'tab_tied'
| 'tab_untied'
| 'view_mode_changed'
| 'overflow_layout_mode_toggled'
| 'overflow_pins_toggled'
| 'overflow_pin_clicked'
| 'overflow_pin_double_clicked'
| 'overflow_layer_toggled'
| 'overflow_select_all_layers'
| 'overflow_node_double_clicked'
| 'voltage_range_changed'
| 'asset_clicked'
| 'zoom_in'
| 'zoom_out'
| 'zoom_reset'
| 'inspect_query_changed'
| 'vl_names_toggled'
| 'sld_overlay_opened'
| 'sld_overlay_tab_changed'
| 'sld_overlay_closed'
| 'sld_edit_mode_toggled'
| 'sld_switch_toggled'
| 'sld_maneuver_removed'
| 'sld_maneuver_focused'
| 'sld_edit_reset'
| 'sld_injection_staged'
| 'sld_injection_removed'
| 'sld_topology_simulated'
| 'overview_shown'
| 'overview_hidden'
| 'overview_pin_clicked'
| 'overview_pin_double_clicked'
| 'overview_popover_closed'
| 'overview_zoom_in'
| 'overview_zoom_out'
| 'overview_zoom_fit'
| 'overview_inspect_changed'
| 'overview_filter_changed'
| 'overview_unsimulated_toggled'
| 'overview_unsimulated_pin_simulated'
| 'session_saved'
| 'session_reload_modal_opened'
| 'session_reloaded'
| 'sidebar_collapsed_toggled'
| 'contingency_clear_requested'
| 'theme_toggled'
| 'smooth_pan_zoom_toggled';
export interface InteractionLogEntry {
seq: number;
timestamp: string;
type: InteractionType;
details: Record<string, unknown>;
correlation_id?: string;
duration_ms?: number;
}
// ===== Action Overview Filters =====
export type ActionSeverityCategory = 'green' | 'orange' | 'red' | 'grey';
export type ActionTypeFilterToken = 'all' | 'disco' | 'reco' | 'ls' | 'rc' | 'redispatch' | 'open' | 'close' | 'pst';
export interface ActionOverviewFilters {
categories: Record<ActionSeverityCategory, boolean>;
threshold: number;
showUnsimulated: boolean;
actionType: ActionTypeFilterToken;
showCombinedOnly: boolean;
}
export interface UnsimulatedActionScoreInfo {
type: string;
score: number;
mwStart?: number | null;
tapStart?: {
pst_name: string;
tap: number;
low_tap: number | null;
high_tap: number | null;
} | null;
rankInType: number;
countInType: number;
maxScoreInType: number;
}
// =====================================================================
// Overflow-iframe postMessage envelope
// =====================================================================
export interface OverflowIframeScreenRect {
left: number;
top: number;
width: number;
height: number;
}
export type IframeToParentMessage =
| { type: 'cs4g:overlay-ready' }
| {
type: 'cs4g:pin-clicked';
actionId: string;
screenRect?: OverflowIframeScreenRect;
}
| {
type: 'cs4g:pin-double-clicked';
actionId: string;
substation: string;
}
| {
type: 'cs4g:overflow-unsimulated-pin-double-clicked';
actionId: string;
}
| {
type: 'cs4g:overflow-filter-changed';
filters: ActionOverviewFilters;
}
| {
type: 'cs4g:overflow-layer-toggled';
key: string;
label: string;
visible: boolean;
}
| {
type: 'cs4g:overflow-select-all-layers';
visible: boolean;
}
| {
type: 'cs4g:overflow-node-double-clicked';
name: string;
}
| {
type: 'cs4g:overflow-pins-toggled';
enabled: boolean;
};
export type IframeToParentMessageType = IframeToParentMessage['type'];
export type ParentToIframeMessage =
| {
type: 'cs4g:pins';
visible: boolean;
pins: ReadonlyArray<unknown>;
}
| {
type: 'cs4g:filters';
filters: ActionOverviewFilters;
}
| {
// Total execution time (seconds) for creating + generating the
// overflow analysis graph. Posted by the React parent once the
// step-2 ``result`` event arrives — the overlay JS renders it
// as a subtitle just below the sidebar ``<h1>`` so the operator
// can see how long the graph took to produce.
type: 'cs4g:overflow-meta';
overflowGraphTime: number | null;
}
| {
// Light/dark theme of the host app. Posted on overlay-ready and
// whenever the parent's `<html data-theme>` flips, so the
// embedded overflow viewer can match the surrounding chrome.
type: 'cs4g:theme';
theme: 'light' | 'dark';
};