@micheeeeel/yinyangapp 2.5.0 → 2.6.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/dist/bundle.js +1 -1
- package/dist/types/adapters/yasuniCauseAdapter.d.ts +31 -5
- package/dist/types/api.d.ts +5 -1
- package/dist/types/components/controller/YinYangController.d.ts +63 -679
- package/dist/types/components/controller/action-stack/ActionStackController.d.ts +35 -0
- package/dist/types/components/controller/action-stack/ActionStackManager.d.ts +9 -0
- package/dist/types/components/controller/action-stack/StackFocusController.d.ts +105 -0
- package/dist/types/components/controller/actions/ActionProjectionService.d.ts +32 -3
- package/dist/types/components/controller/actions/ChildActionMenuController.d.ts +8 -4
- package/dist/types/components/controller/actions/CoreEventMenuController.d.ts +13 -13
- package/dist/types/components/controller/actions/KeyEventController.d.ts +192 -0
- package/dist/types/components/controller/actions/radialItemMenu.d.ts +0 -9
- package/dist/types/components/controller/children/ChildrenBuilder.d.ts +95 -0
- package/dist/types/components/controller/children/ComponentSwitchCoordinator.d.ts +80 -0
- package/dist/types/components/controller/debug/ControllerDebugTools.d.ts +81 -0
- package/dist/types/components/controller/force-field/ForceFieldComputationService.d.ts +3 -15
- package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +120 -66
- package/dist/types/components/controller/force-field/ForceFieldDetailsPresenter.d.ts +139 -0
- package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +0 -8
- package/dist/types/components/controller/force-field/IncomingForceFieldService.d.ts +53 -0
- package/dist/types/components/controller/force-field/PropagationAnimator.d.ts +56 -0
- package/dist/types/components/controller/force-field/edgeIdentity.d.ts +28 -0
- package/dist/types/components/controller/force-field/incomingContinuation.d.ts +22 -0
- package/dist/types/components/controller/force-field/propagation-viz/PropagationCometPlayer.d.ts +60 -0
- package/dist/types/components/controller/force-field/propagation-viz/propagationVizLists.d.ts +51 -0
- package/dist/types/components/controller/force-field/propagation-viz/propagationVizModel.d.ts +60 -0
- package/dist/types/components/controller/force-field/propagationTree.d.ts +32 -0
- package/dist/types/components/controller/force-field/shieldViewModel.d.ts +79 -0
- package/dist/types/components/controller/force-field/types.d.ts +37 -10
- package/dist/types/components/controller/labels/ComponentTitlePresenter.d.ts +99 -0
- package/dist/types/components/controller/navigation/DiagramNavigator.d.ts +64 -0
- package/dist/types/components/controller/odd/OddViewManager.d.ts +1 -1
- package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +9 -0
- package/dist/types/components/controller/state/ControllerSession.d.ts +107 -0
- package/dist/types/components/controller/state/ControllerUiCallbacks.d.ts +60 -0
- package/dist/types/components/controller/state/YinYangControllerState.d.ts +4 -5
- package/dist/types/components/controller/types.d.ts +103 -0
- package/dist/types/components/controller/utils/actionCatalog.d.ts +15 -0
- package/dist/types/components/controller/utils/forceFieldPresentation.d.ts +14 -8
- package/dist/types/components/search/GlobalSearchController.d.ts +68 -9
- package/dist/types/components/view/BorderDrawer.d.ts +5 -0
- package/dist/types/components/workspace/workspaceTemplate.d.ts +1 -1
- package/dist/types/config/propagationCometConfig.d.ts +9 -36
- package/dist/types/config/propagationCometVizConfig.d.ts +34 -0
- package/dist/types/data/activeDiagram.d.ts +4 -6
- package/dist/types/data/adverse-action-planner.d.ts +22 -0
- package/dist/types/data/catalogue-coverage.d.ts +26 -0
- package/dist/types/data/combo-engine.d.ts +76 -21
- package/dist/types/data/contacts/buildContactSphere.d.ts +23 -4
- package/dist/types/data/contacts/index.d.ts +6 -3
- package/dist/types/data/propagation-graph.d.ts +16 -0
- package/dist/types/data/stability-shield.d.ts +21 -0
- package/dist/types/data/yasuni_actions.d.ts +38 -5
- package/dist/types/data/yasuni_cause.d.ts +7 -0
- package/dist/types/data/yasuni_key_events.d.ts +3 -2
- package/dist/types/interfaces/IPropagationGraph.d.ts +39 -0
- package/dist/types/interfaces/IYinYangController.d.ts +2 -2
- package/dist/types/utils/actionPropagation.d.ts +104 -32
- package/dist/types/utils/adverseMode.d.ts +14 -0
- package/package.json +4 -2
- package/dist/types/components/controller/utils/forceFieldMetadata.d.ts +0 -4
- package/dist/types/data/yasuni_graph.d.ts +0 -22
- package/dist/types/data/yasuni_propagation_layers.d.ts +0 -3
- package/dist/types/interfaces/ICauseGraph.d.ts +0 -9
- package/dist/types/interfaces/IPropagationLayers.d.ts +0 -27
- package/dist/types/utils/causeGraph.d.ts +0 -6
|
@@ -1,26 +1,43 @@
|
|
|
1
|
+
import type { PropagationScope } from "../../../interfaces/IPropagationGraph";
|
|
2
|
+
/**
|
|
3
|
+
* Une arrivée de propagation prête pour l'affichage : un saut du graphe
|
|
4
|
+
* unifié, d'un satellite à un autre, issu d'une résolution précise.
|
|
5
|
+
*
|
|
6
|
+
* Identité (PROP-GRAPH-04) : `edgeId` est unique dans tout ensemble de
|
|
7
|
+
* lignes affichées, même après filtrage, transformation ou fusion de
|
|
8
|
+
* plusieurs actions de la pile ; `parentEdgeId` désigne l'arrivée qui a
|
|
9
|
+
* porté le budget de ce saut. Ensemble, ils forment l'arbre des arrivées
|
|
10
|
+
* (voir propagationTree.ts) : embranchements, convergences et retours
|
|
11
|
+
* cycliques s'y lisent sans cas particulier. Deux actions qui produisent la
|
|
12
|
+
* même relation gardent des identités distinctes (`resolutionId`).
|
|
13
|
+
*/
|
|
1
14
|
export type ForceFieldLinkDetail = {
|
|
15
|
+
/** Résolution d'origine : un bloc de pile, ou le satellite source d'un
|
|
16
|
+
* champ de force. Toutes les arêtes d'une résolution le partagent. */
|
|
17
|
+
resolutionId: string;
|
|
18
|
+
edgeId: string;
|
|
19
|
+
/** Absent pour une sortie du point de départ de la résolution. Peut
|
|
20
|
+
* désigner une arrivée absente des lignes affichées (sautée dans une autre
|
|
21
|
+
* facette) : la ligne est alors une racine pour cet affichage. */
|
|
22
|
+
parentEdgeId?: string;
|
|
23
|
+
scope: PropagationScope;
|
|
2
24
|
fromComponentId: string;
|
|
3
25
|
toComponentId: string;
|
|
4
26
|
fromOddId: string;
|
|
5
27
|
toOddId: string;
|
|
6
|
-
fromCuttingId
|
|
7
|
-
toCuttingId
|
|
28
|
+
fromCuttingId: number;
|
|
29
|
+
toCuttingId: number;
|
|
8
30
|
baseDelta: number;
|
|
9
31
|
weight: number;
|
|
10
32
|
strategicWeight: number;
|
|
11
|
-
layerType: "inter" | "intra" | "bridge";
|
|
12
|
-
propagationFactor: number;
|
|
13
33
|
absorption: number;
|
|
14
34
|
gap: number;
|
|
15
35
|
fromState: number;
|
|
16
36
|
toState: number;
|
|
17
37
|
deltaTo: number;
|
|
18
38
|
rationale?: string;
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
layersInvolved: string[];
|
|
22
|
-
localLayerWeights: string | null;
|
|
23
|
-
bridgeLayerWeights: string | null;
|
|
39
|
+
/** Chemin causal de l'arrivée (PropagatedActionEdge.path). */
|
|
40
|
+
path?: readonly string[];
|
|
24
41
|
};
|
|
25
42
|
export type ForceFieldLink = {
|
|
26
43
|
startIndex?: number;
|
|
@@ -29,7 +46,8 @@ export type ForceFieldLink = {
|
|
|
29
46
|
targetComponentId?: string;
|
|
30
47
|
thickness: number;
|
|
31
48
|
potentialGain: number;
|
|
32
|
-
/** Delay before revealing this link
|
|
49
|
+
/** Delay before revealing this link: its depth in the arrival tree times the
|
|
50
|
+
* reveal step, whatever its scope. */
|
|
33
51
|
revealDelayMs?: number;
|
|
34
52
|
/** Index orbital du satellite source racine ayant produit ce lien (posé par
|
|
35
53
|
* ForceFieldComputationService.build, un appel par source). Pour un segment
|
|
@@ -56,3 +74,12 @@ export declare function buildSourceOriginKey(componentId: string, oddId: string,
|
|
|
56
74
|
* sans impacter la logique de propagation.
|
|
57
75
|
*/
|
|
58
76
|
export type ForceFieldSegment = Omit<ForceFieldLink, "detail">;
|
|
77
|
+
/**
|
|
78
|
+
* Clé d'une entrée de liens entrants (contexte "incoming" d'un changement de
|
|
79
|
+
* facette) : l'identité de l'arrivée elle-même (PROP-GRAPH-04). Deux
|
|
80
|
+
* arrivées distinctes — autre action, autre satellite de départ, autre
|
|
81
|
+
* satellite cible, autre chemin — restent deux entrées, sans qu'aucune ne
|
|
82
|
+
* soit écartée au profit de la plus forte ; une même arrivée vue deux fois
|
|
83
|
+
* (état courant et recalcul) n'en fait qu'une.
|
|
84
|
+
*/
|
|
85
|
+
export declare function buildIncomingLinkKey(detail: Pick<ForceFieldLinkDetail, "edgeId">): string;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { IYinYangView } from "../../../interfaces/IYinYangView";
|
|
2
|
+
import { IYinYangController } from "../../../interfaces/IYinYangController";
|
|
3
|
+
import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
|
|
4
|
+
import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
|
|
5
|
+
import { ForceFieldDetailsPanel } from "../force-field/ForceFieldDetailsPanel";
|
|
6
|
+
import { YinYangControllerState } from "../state/YinYangControllerState";
|
|
7
|
+
import { ControllerSession } from "../state/ControllerSession";
|
|
8
|
+
import { ChildScoresDeltaRenderer } from "./ChildScoresDeltaRenderer";
|
|
9
|
+
import { WeightPreviewRingRenderer } from "./WeightPreviewRingRenderer";
|
|
10
|
+
import { ContextLabelsRenderer } from "./ContextLabelsRenderer";
|
|
11
|
+
import { ActionStackManager } from "../action-stack/ActionStackManager";
|
|
12
|
+
import type { CumulativeBlock } from "../types";
|
|
13
|
+
export type ComponentTitlePresenterDeps = {
|
|
14
|
+
actionStackManager: ActionStackManager;
|
|
15
|
+
buildChildrenOrbitData: () => ChildrenOrbitEntry[];
|
|
16
|
+
buildKeyEventBlocksForComponent: (component: {
|
|
17
|
+
id: string;
|
|
18
|
+
}) => CumulativeBlock[];
|
|
19
|
+
childOddMap: Map<string, {
|
|
20
|
+
oddId: string;
|
|
21
|
+
score: number;
|
|
22
|
+
cuttingIndex: number;
|
|
23
|
+
}>;
|
|
24
|
+
childScoresDeltaRenderer: ChildScoresDeltaRenderer;
|
|
25
|
+
contextLabelsRenderer: ContextLabelsRenderer;
|
|
26
|
+
forceFieldDetailsPanel: ForceFieldDetailsPanel;
|
|
27
|
+
getActiveChildMeta: () => {
|
|
28
|
+
oddId: string;
|
|
29
|
+
cuttingIndex: number;
|
|
30
|
+
componentId: string;
|
|
31
|
+
} | null;
|
|
32
|
+
getAllComponents: () => YinYangInternalModel["components"];
|
|
33
|
+
getChildRenderedCenter: (childController: IYinYangController) => {
|
|
34
|
+
x: number;
|
|
35
|
+
y: number;
|
|
36
|
+
} | null;
|
|
37
|
+
getCurrentComponent: () => YinYangInternalModel["components"][number] | null;
|
|
38
|
+
getInternalModel: () => YinYangInternalModel;
|
|
39
|
+
navigateToPrereqAction: (actionId: string) => void;
|
|
40
|
+
session: ControllerSession;
|
|
41
|
+
showComposanteInfo: () => void;
|
|
42
|
+
state: YinYangControllerState;
|
|
43
|
+
view: IYinYangView;
|
|
44
|
+
weightPreviewRingRenderer: WeightPreviewRingRenderer;
|
|
45
|
+
};
|
|
46
|
+
/** Titre de composante (facette / satellite / action), étiquettes de
|
|
47
|
+
* contexte, deltas de score des satellites et anneau d'aperçu de poids. */
|
|
48
|
+
export declare class ComponentTitlePresenter {
|
|
49
|
+
private deps;
|
|
50
|
+
constructor(deps: ComponentTitlePresenterDeps);
|
|
51
|
+
private getCurrentComponentTitle;
|
|
52
|
+
/** Second (et, le cas échéant, troisième) niveau du titre : libellé + couleur
|
|
53
|
+
* ODD du satellite actif sous la facette courante (menu ouvert, ou
|
|
54
|
+
* sélection en lecture seule — voir getActiveChildMeta), avec le libellé
|
|
55
|
+
* de son action active le cas échéant. Un Événement Clé actif (frère du
|
|
56
|
+
* Satellite, jamais les deux à la fois côté menu — voir activeKeyEventId)
|
|
57
|
+
* prend la priorité et occupe cette même ligne, sans action associée
|
|
58
|
+
* (targetedActionIds sont des renvois, pas une Action propre). Null hors
|
|
59
|
+
* facette / sans satellite ni Événement Clé actif. */
|
|
60
|
+
private getCurrentSatelliteTitle;
|
|
61
|
+
/** Troisième niveau du titre : libellé de l'action actuellement active,
|
|
62
|
+
* seulement si elle appartient bien au satellite affiché (oddId,
|
|
63
|
+
* cuttingIndex) — actionSourceChildKey peut différer du satellite affiché
|
|
64
|
+
* quand l'utilisateur navigue vers un autre satellite en lecture seule
|
|
65
|
+
* (recherche/STACK) pendant qu'une action reste techniquement active sur
|
|
66
|
+
* le précédent (voir le commentaire sur actionSourceChildKey). Sans ce
|
|
67
|
+
* contrôle, le titre affichait le libellé de l'ancienne action sous le
|
|
68
|
+
* nouveau satellite. */
|
|
69
|
+
private getCurrentActionTitle;
|
|
70
|
+
/** Refreshes just the top-left title's satellite line against the current
|
|
71
|
+
* state — cheap, idempotent DOM diffing — from every code path that can
|
|
72
|
+
* change which satellite is active (menu open/close, force-field link
|
|
73
|
+
* click, hierarchy/search navigation, cumulative view). */
|
|
74
|
+
refreshComponentTitle(): void;
|
|
75
|
+
/** Cross-fades the top-left component-title label to `componentIndex`'s
|
|
76
|
+
* name immediately, without waiting for the full updateContextLabels()
|
|
77
|
+
* pass (orbit data, legend, etc.) that only runs once the diagram's
|
|
78
|
+
* component-switch animation completes. A facette switch always starts
|
|
79
|
+
* with no active satellite (createYinYangChildren() resets it), so the
|
|
80
|
+
* satellite line is cleared here rather than read from state mid-switch. */
|
|
81
|
+
updateComponentTitleLabelImmediate(componentIndex: number): void;
|
|
82
|
+
updateContextLabels(orbitData: ChildrenOrbitEntry[]): void;
|
|
83
|
+
renderChildScoresDeltas(orbitData: ChildrenOrbitEntry[]): void;
|
|
84
|
+
/** Re-syncs the weightDelta ghost/wave/pulse against the current
|
|
85
|
+
* ViewInitializer settings (basePulseEnabled, ghostPulseDurationSec,
|
|
86
|
+
* pulseMorphRatio) without waiting for the next natural preview change.
|
|
87
|
+
* Needed because toggling "Pulsation rayons activée" only calls
|
|
88
|
+
* redrawBothGhosts() (VizControlsPanel), which refreshes the facette's own
|
|
89
|
+
* score ghost but has no reason to know about the weightDelta preview. */
|
|
90
|
+
refreshWeightPreviewPulse(): void;
|
|
91
|
+
/** Draws the weightDelta ghost + traveling wave for every satellite
|
|
92
|
+
* targeted by a currently-previewed action — see
|
|
93
|
+
* ActionStackManager.getWeightDeltaByChildKey. The satellite's own circle
|
|
94
|
+
* never resizes, same as the facette ghost never resizes the real
|
|
95
|
+
* yin-yang circle; WeightPreviewRingRenderer resyncs every child each
|
|
96
|
+
* call (no delta = no ghost/wave), same "recompute the full desired
|
|
97
|
+
* state" pattern as highlightOddInChildren. */
|
|
98
|
+
applyWeightPreview(orbitData: ChildrenOrbitEntry[], globalGroupNode: SVGGElement | null): void;
|
|
99
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { IYinYangView } from "../../../interfaces/IYinYangView";
|
|
2
|
+
import { IYinYangController } from "../../../interfaces/IYinYangController";
|
|
3
|
+
import { YinYangComponentNode, YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
|
|
4
|
+
import { type ComboResult } from "../../../data/combo-engine";
|
|
5
|
+
import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
|
|
6
|
+
import { ForceFieldDetailsPanel } from "../force-field/ForceFieldDetailsPanel";
|
|
7
|
+
import { YinYangControllerState } from "../state/YinYangControllerState";
|
|
8
|
+
import { ComponentTitlePresenter } from "../labels/ComponentTitlePresenter";
|
|
9
|
+
import { ControllerSession } from "../state/ControllerSession";
|
|
10
|
+
import type { ControllerUiCallbacks } from "../state/ControllerUiCallbacks";
|
|
11
|
+
import { ForceFieldComputationService } from "../force-field/ForceFieldComputationService";
|
|
12
|
+
export type DiagramNavigatorDeps = {
|
|
13
|
+
computeComboResultsForAction: (actionId: string) => ComboResult[] | undefined;
|
|
14
|
+
animateChildrenHide: () => void;
|
|
15
|
+
buildChildrenOrbitData: () => ChildrenOrbitEntry[];
|
|
16
|
+
getChildControllers: () => IYinYangController[];
|
|
17
|
+
childOddMap: Map<string, {
|
|
18
|
+
oddId: string;
|
|
19
|
+
score: number;
|
|
20
|
+
cuttingIndex: number;
|
|
21
|
+
}>;
|
|
22
|
+
forceFieldComputationService: ForceFieldComputationService;
|
|
23
|
+
forceFieldDetailsPanel: ForceFieldDetailsPanel;
|
|
24
|
+
getAllComponents: () => YinYangInternalModel["components"];
|
|
25
|
+
getCurrentComponent: () => YinYangInternalModel["components"][number] | null;
|
|
26
|
+
getCurrentComponentOrUndefined: () => YinYangInternalModel["components"][number] | undefined;
|
|
27
|
+
renderCumulativeDetailsForCutting: (oddId: string, cuttingId: number | undefined) => boolean;
|
|
28
|
+
renderForceFieldDetails: (linkIndex: number) => void;
|
|
29
|
+
renderSourceActionDetailsForCurrentSource: (opts?: {
|
|
30
|
+
deltaOverride?: number;
|
|
31
|
+
comboResults?: ComboResult[];
|
|
32
|
+
}) => void;
|
|
33
|
+
session: ControllerSession;
|
|
34
|
+
state: YinYangControllerState;
|
|
35
|
+
titlePresenter: ComponentTitlePresenter;
|
|
36
|
+
ui: ControllerUiCallbacks;
|
|
37
|
+
view: IYinYangView;
|
|
38
|
+
};
|
|
39
|
+
/** Navigation dans le diagramme depuis les panneaux (source d'une action,
|
|
40
|
+
* prérequis, découpe ciblée, clic sur une étiquette de découpe) et fantôme
|
|
41
|
+
* HTML affiché pendant un glisser d'action. */
|
|
42
|
+
export declare class DiagramNavigator {
|
|
43
|
+
private deps;
|
|
44
|
+
constructor(deps: DiagramNavigatorDeps);
|
|
45
|
+
private htmlDragGhost;
|
|
46
|
+
navigateToSource(fromOddId: string, fromCuttingId: number | undefined, fromComponentId: string | undefined): void;
|
|
47
|
+
navigateToPrereqAction(actionId: string): void;
|
|
48
|
+
navigateToCutting(toOddId: string, toCuttingId: number | undefined, toComponentId: string | undefined): void;
|
|
49
|
+
/** Index (position dans l'ODD) d'un cutting à partir de son id — inverse
|
|
50
|
+
* de resolveOddCuttingId ; undefined si l'ODD ou l'id est inconnu. */
|
|
51
|
+
resolveCuttingIndex(component: YinYangInternalModel["components"][number], oddId: string, cuttingId: number): number | undefined;
|
|
52
|
+
notifyCuttingNavigated(oddId: string, cuttingId: number | undefined): void;
|
|
53
|
+
clientPointToGlobalGroup(clientX: number, clientY: number): {
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
} | null;
|
|
57
|
+
renderDragGhost(clientX: number, clientY: number, iconUrl: string): void;
|
|
58
|
+
removeDragGhost(): void;
|
|
59
|
+
onCuttingLabelClick(oddId: string, cuttingId: number | undefined): void;
|
|
60
|
+
resolveActionSource(component: YinYangComponentNode | undefined): {
|
|
61
|
+
oddId: string;
|
|
62
|
+
cuttingId: number | undefined;
|
|
63
|
+
} | undefined;
|
|
64
|
+
}
|
|
@@ -4,7 +4,7 @@ import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel"
|
|
|
4
4
|
import { ForceFieldDetailsPanel } from "../force-field/ForceFieldDetailsPanel";
|
|
5
5
|
import { ActionStackController } from "../action-stack/ActionStackController";
|
|
6
6
|
import { OddHighlightIntensity, ChildHighlightState } from "./childHighlightStyles";
|
|
7
|
-
import type { CumulativeBlock } from "../
|
|
7
|
+
import type { CumulativeBlock } from "../types";
|
|
8
8
|
type ChildOddMeta = {
|
|
9
9
|
oddId: string;
|
|
10
10
|
score: number;
|
|
@@ -83,6 +83,15 @@ type SearchPanelSynchronizerDeps = {
|
|
|
83
83
|
x: number;
|
|
84
84
|
y: number;
|
|
85
85
|
} | null;
|
|
86
|
+
/** Glisser guidé d'un prérequis : réaffiche dans le panneau STACK les
|
|
87
|
+
* blocs de l'item de pile portant le combo. */
|
|
88
|
+
showStackItemBlocksForDrag: (stackItemId: string) => void;
|
|
89
|
+
/** Glisser guidé : aperçu en direct des cartes combo selon l'emplacement
|
|
90
|
+
* survolé (restaure le contenu d'origine hors glisser guidé). */
|
|
91
|
+
refreshGuidedComboPreview: () => void;
|
|
92
|
+
/** Sélectionne le satellite d'un item de pile et centre son bloc — même
|
|
93
|
+
* chemin qu'un clic sur le libellé de l'item dans la pile. */
|
|
94
|
+
focusStackItemSatellite: (stackItemId: string) => void;
|
|
86
95
|
};
|
|
87
96
|
/**
|
|
88
97
|
* Coordonne le panneau RECHERCHE avec le diagramme — et héberge aussi le
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ForceFieldLink, ForceFieldLinkDetail } from "../force-field/types";
|
|
2
|
+
/** Contexte "incoming" préparé avant un changement de facette (voir
|
|
3
|
+
* ComponentSwitchContext). */
|
|
4
|
+
export type IncomingLinksByOddId = Map<string, {
|
|
5
|
+
toOddId: string;
|
|
6
|
+
thickness: number;
|
|
7
|
+
potentialGain: number;
|
|
8
|
+
detail: ForceFieldLinkDetail;
|
|
9
|
+
sourceOriginKey?: string;
|
|
10
|
+
}>;
|
|
11
|
+
/**
|
|
12
|
+
* Prepared by prepareForComponentSwitch() before children are hidden.
|
|
13
|
+
* undefined = not yet prepared (fallback path)
|
|
14
|
+
* null = prepared but no action applies to target component
|
|
15
|
+
* { type: 'incoming', ... } = show incoming force fields on arrival
|
|
16
|
+
* { type: 'reactivate' } = re-activate the source action on arrival
|
|
17
|
+
*/
|
|
18
|
+
export type ComponentSwitchContext = undefined | null | {
|
|
19
|
+
type: "incoming";
|
|
20
|
+
sourceComponentId: string;
|
|
21
|
+
/** Keyed by the arrival's own identity (edgeId) — voir
|
|
22
|
+
* buildIncomingLinkKey — so that every arrival is preserved as a
|
|
23
|
+
* separate entry. `toOddId` is also stored in the value since the key
|
|
24
|
+
* is not the plain ODD id. */
|
|
25
|
+
linksByOddId: IncomingLinksByOddId;
|
|
26
|
+
} | {
|
|
27
|
+
type: "reactivate";
|
|
28
|
+
} | {
|
|
29
|
+
type: "searchCutting";
|
|
30
|
+
oddId: string;
|
|
31
|
+
cuttingIndex: number;
|
|
32
|
+
forceOpen?: boolean;
|
|
33
|
+
} | {
|
|
34
|
+
type: "searchOdd";
|
|
35
|
+
oddId: string;
|
|
36
|
+
} | {
|
|
37
|
+
type: "searchOddHighlight";
|
|
38
|
+
oddId: string;
|
|
39
|
+
} | {
|
|
40
|
+
type: "searchAction";
|
|
41
|
+
oddId: string;
|
|
42
|
+
cuttingIndex: number;
|
|
43
|
+
actionId: string;
|
|
44
|
+
} | {
|
|
45
|
+
type: "restoreAction";
|
|
46
|
+
oddId: string;
|
|
47
|
+
cuttingIndex: number;
|
|
48
|
+
actionId: string;
|
|
49
|
+
};
|
|
50
|
+
export type PersistentActionContext = {
|
|
51
|
+
sourceComponentId: string;
|
|
52
|
+
sourceOddId: string;
|
|
53
|
+
sourceCuttingIndex: number;
|
|
54
|
+
actionId: string;
|
|
55
|
+
actionLabel?: string;
|
|
56
|
+
links: ForceFieldLink[];
|
|
57
|
+
};
|
|
58
|
+
export type SourceFocus = {
|
|
59
|
+
oddId: string;
|
|
60
|
+
cuttingId: number | undefined;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* État de navigation mutable partagé entre YinYangController et ses
|
|
64
|
+
* collaborateurs (bascule de facette, navigation, panneau de détails,
|
|
65
|
+
* Événements Clés). Regroupé ici pour que chacun lise et écrive la même
|
|
66
|
+
* instance plutôt que de passer par des getters/setters du contrôleur.
|
|
67
|
+
*/
|
|
68
|
+
export declare class ControllerSession {
|
|
69
|
+
/**
|
|
70
|
+
* Persists the active action across component switches.
|
|
71
|
+
* Cleared only when the user explicitly deselects the action.
|
|
72
|
+
*/
|
|
73
|
+
persistentActionContext: PersistentActionContext | null;
|
|
74
|
+
pendingComponentSwitchContext: ComponentSwitchContext;
|
|
75
|
+
selectedSourceFocus: SourceFocus | null;
|
|
76
|
+
/** Focus saved just before switching away from the source component, so returning
|
|
77
|
+
* to the source component restores the same highlighted cutting (multi-action). */
|
|
78
|
+
focusBeforeComponentSwitch: SourceFocus | null;
|
|
79
|
+
/** Cross-component force-field links from the source component, saved when
|
|
80
|
+
* switching away to a target component. Used to recompute the incoming view
|
|
81
|
+
* when a checkbox toggle fires while already on the target component. */
|
|
82
|
+
savedSourceComponentLinks: ForceFieldLink[];
|
|
83
|
+
/** Set by navigateToCutting for cross-component nav: after the switch the
|
|
84
|
+
* incoming force field context is established, then onCuttingLabelClick is
|
|
85
|
+
* called for this cutting to show its propagated card. */
|
|
86
|
+
pendingCuttingFocusAfterSwitch: SourceFocus | null;
|
|
87
|
+
pendingOddHighlightAfterSwitch: string | null;
|
|
88
|
+
/** Set by SearchPanelSynchronizer.searchNavigateToCutting when a stack-item
|
|
89
|
+
* click switches facette while an action is active: prepareForComponentSwitch
|
|
90
|
+
* owns pendingComponentSwitchContext for the incoming force field, so this
|
|
91
|
+
* navigation is applied separately once the switch completes. */
|
|
92
|
+
pendingCuttingNavigationAfterSwitch: {
|
|
93
|
+
oddId: string;
|
|
94
|
+
cuttingIndex: number;
|
|
95
|
+
forceOpen: boolean;
|
|
96
|
+
} | null;
|
|
97
|
+
/** Menu cœur à déployer à l'arrivée sur la facette (voir searchSetKeyEventMenuOpen). */
|
|
98
|
+
pendingKeyEventMenuAfterSwitch: boolean;
|
|
99
|
+
isCoreEventMenuOpen: boolean;
|
|
100
|
+
/** Id de l'Événement Clé actuellement en aperçu (carte affichée), ou null. */
|
|
101
|
+
activeKeyEventId: string | null;
|
|
102
|
+
/** Quand vrai, le prochain appel à onShowDirectActionBlock est routé vers le panneau B. */
|
|
103
|
+
routeNextDirectActionBlockToPanelB: boolean;
|
|
104
|
+
/** Quand vrai, renderSourceActionDetailsForCurrentSource ne re-rend pas le bloc Panel A.
|
|
105
|
+
* Utilisé pendant reactivatePersistentAction pour préserver l'état des <details> ouverts. */
|
|
106
|
+
suppressDirectActionBlockRender: boolean;
|
|
107
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { DiagramNavEvent } from "../types";
|
|
2
|
+
type DirectActionBlockCallback = (compId: string, oddId: string, cutIdx: number, actionId: string, cardsHtml: string, attachHandlers: (container: HTMLElement) => void) => void;
|
|
3
|
+
/**
|
|
4
|
+
* Callbacks UI branchés depuis l'extérieur (main.ts, PanelManager,
|
|
5
|
+
* DiagramPanelBridge…) via les setOn* de YinYangController. Partagé tel quel
|
|
6
|
+
* avec les collaborateurs qui doivent notifier les panneaux.
|
|
7
|
+
*/
|
|
8
|
+
export type ControllerUiCallbacks = {
|
|
9
|
+
/** Callback to open the search tab and set a query — wired from main.ts. */
|
|
10
|
+
openSearchWithQuery?: (query: string) => void;
|
|
11
|
+
/** Injecte le bloc d'impact d'action directe dans l'onglet Recherche. */
|
|
12
|
+
onShowDirectActionBlock?: DirectActionBlockCallback;
|
|
13
|
+
/** Affiche le bloc d'action directe d'un prérequis dans le panneau B. */
|
|
14
|
+
onShowDirectActionBlockPanelB?: DirectActionBlockCallback;
|
|
15
|
+
/** Efface le bloc d'impact d'action directe de l'onglet Recherche. */
|
|
16
|
+
onClearDirectActionBlock?: () => void;
|
|
17
|
+
/** Injecte la carte descriptive d'un Événement Clé dans l'onglet Recherche. */
|
|
18
|
+
onShowKeyEventBlock?: (compId: string, keyEventId: string, cardsHtml: string, attachHandlers: (container: HTMLElement) => void) => void;
|
|
19
|
+
/** Efface la carte d'Événement Clé de l'onglet Recherche. */
|
|
20
|
+
onClearKeyEventBlock?: () => void;
|
|
21
|
+
/** Notifie la hiérarchie RECHERCHE de l'état du menu radial des Événements
|
|
22
|
+
* Clés (diagramme → arbre), pour que le groupe "Événements Clés" reste le
|
|
23
|
+
* reflet exact des bulles réellement déployées. */
|
|
24
|
+
onKeyEventMenuStateChange?: (componentIndex: number, open: boolean) => void;
|
|
25
|
+
/** Injecte le bloc d'action propagée dans l'onglet Recherche. */
|
|
26
|
+
onShowPropagationBlock?: (compId: string, oddId: string, cutIdx: number, html: string, attachHandlers: (container: HTMLElement) => void, sourceDesc: {
|
|
27
|
+
breadcrumb: string;
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
}, rationale?: string) => void;
|
|
31
|
+
/** Efface le bloc d'action propagée de l'onglet Recherche. */
|
|
32
|
+
onClearPropagationBlock?: () => void;
|
|
33
|
+
onDiagramActionDragIntent?: () => void;
|
|
34
|
+
onActiveChildChange?: () => void;
|
|
35
|
+
onOuterSparkAutoToggle?: (enabled: boolean) => void;
|
|
36
|
+
/** Fired unconditionally at the end of onCuttingLabelClick (both the cumulative and
|
|
37
|
+
* the normal branch), regardless of which internal path handled the click, so that
|
|
38
|
+
* DiagramPanelBridge can keep the STACK hierarchy (chip + history) in sync even when
|
|
39
|
+
* the cumulative view intercepts the click before renderForceFieldDetails /
|
|
40
|
+
* onShowPropagationBlock is reached. Signature mirrors setOnPropagationBlock's
|
|
41
|
+
* (compId, oddId, cuttingIndex) shape so the same STACK-sync handler can be reused. */
|
|
42
|
+
onCuttingNavigated?: (compId: string, oddId: string, cuttingIndex: number) => void;
|
|
43
|
+
onDiagramOddChange?: (componentIndex: number, oddId: string, mode: "highlight") => void;
|
|
44
|
+
onDiagramNavChange?: (event: DiagramNavEvent) => void;
|
|
45
|
+
/** Fired when the user re-clicks the active satellite in the diagram (toggle-to-close),
|
|
46
|
+
* or when an ODD-level interaction deselects it — componentIndex lets the listener
|
|
47
|
+
* restore its detail panel to the facette view rather than clearing it entirely. */
|
|
48
|
+
onDiagramSatelliteDeselect?: (componentIndex: number) => void;
|
|
49
|
+
/** Fired when the user clicks the current composante's border arc to hide its satellites. */
|
|
50
|
+
onDiagramComposanteDeselect?: () => void;
|
|
51
|
+
/** Vers le panneau Recherche quand la souris entre/sort d'un satellite dans le diagramme. */
|
|
52
|
+
onDiagramChildHover?: ((componentIndex: number | null, oddId: string | null, cuttingIndex?: number) => void) | null;
|
|
53
|
+
/** Vers le panneau Recherche quand la souris entre/sort d'un arc de bordure (composante). */
|
|
54
|
+
onDiagramComposanteHover?: ((componentIndex: number | null) => void) | null;
|
|
55
|
+
/** Vers le panneau Recherche quand la souris entre/sort d'un cercle d'action dans le menu radial. */
|
|
56
|
+
onDiagramActionHover?: ((componentIndex: number | null, oddId: string | null, cuttingIndex: number | null, actionId: string | null) => void) | null;
|
|
57
|
+
/** Panneau RECHERCHE : la souris entre/sort d'un arc ODD dans le diagramme. */
|
|
58
|
+
onDiagramOddArcHover?: ((oddId: string | null) => void) | null;
|
|
59
|
+
};
|
|
60
|
+
export {};
|
|
@@ -47,7 +47,6 @@ export declare class YinYangControllerState {
|
|
|
47
47
|
coreEventIconFontScale: number;
|
|
48
48
|
};
|
|
49
49
|
action: {
|
|
50
|
-
propagationFactor: number;
|
|
51
50
|
delta: number;
|
|
52
51
|
};
|
|
53
52
|
visibility: {
|
|
@@ -59,14 +58,14 @@ export declare class YinYangControllerState {
|
|
|
59
58
|
* chaque plafond levé. Bornés (false) par défaut : comportement actuel. */
|
|
60
59
|
combos: {
|
|
61
60
|
/** Lève le plafond à 1 sur le ratio de performance des prérequis
|
|
62
|
-
* DÉCLENCHEURS (
|
|
61
|
+
* DÉCLENCHEURS (exploitations éligibles), ce qui autorise une cascade de
|
|
63
62
|
* combos à dépasser ×2. N'affecte pas les prérequis PROTECTEURS d'un
|
|
64
|
-
*
|
|
63
|
+
* sécurisation (voir dangerousComboCanBecomeBonus). */
|
|
65
64
|
uncappedChainedPerformance: boolean;
|
|
66
65
|
/** Lève le plafond à 1 sur le ratio de performance des prérequis
|
|
67
|
-
* PROTECTEURS d'
|
|
66
|
+
* PROTECTEURS d'une sécurisation, ce qui permet à m = avgRatio de
|
|
68
67
|
* dépasser ×1 (le risque devient un bonus net). N'affecte pas les
|
|
69
|
-
*
|
|
68
|
+
* exploitations éligibles (voir uncappedChainedPerformance). */
|
|
70
69
|
dangerousComboCanBecomeBonus: boolean;
|
|
71
70
|
};
|
|
72
71
|
labels: {
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { ForceFieldLinkDetail } from "./force-field/types";
|
|
2
|
+
import type { ComboResult } from "../../data/combo-engine";
|
|
3
|
+
import type { AmplifierResult, AmplifierTargetBreakdown } from "../../data/amplifier-engine";
|
|
4
|
+
import type { AbsorptionBreakdown, ActiveShield } from "./force-field/shieldViewModel";
|
|
5
|
+
/**
|
|
6
|
+
* Bloc "action" de la vue cumulative (mode STACK) : "source" = action jouée
|
|
7
|
+
* sur le satellite ciblé, "propagation" = effet indirect qui l'atteint depuis
|
|
8
|
+
* un autre satellite.
|
|
9
|
+
*/
|
|
10
|
+
export type ActionCumulativeBlock = {
|
|
11
|
+
type: "source" | "propagation";
|
|
12
|
+
actionId?: string;
|
|
13
|
+
actionName: string;
|
|
14
|
+
actionDescription: string;
|
|
15
|
+
sourceComponentName?: string;
|
|
16
|
+
sourceOddName?: string;
|
|
17
|
+
/** Facette du satellite qui porte l'action (peut différer de la facette
|
|
18
|
+
* affichée pour un bloc de propagation). */
|
|
19
|
+
sourceComponentId?: string;
|
|
20
|
+
sourceOddId: string;
|
|
21
|
+
sourceCuttingId: number | undefined;
|
|
22
|
+
totalDelta: number;
|
|
23
|
+
rawDelta?: number;
|
|
24
|
+
baseDelta?: number;
|
|
25
|
+
weightDelta?: number;
|
|
26
|
+
weightDeltaBase?: number;
|
|
27
|
+
detailRows: ForceFieldLinkDetail[];
|
|
28
|
+
comboResults?: ComboResult[];
|
|
29
|
+
amplifierResults?: AmplifierResult[];
|
|
30
|
+
stackItemId?: string;
|
|
31
|
+
color?: string;
|
|
32
|
+
/** This item's own propagation edges from the real sequential
|
|
33
|
+
* simulation (see computeSequentialStackContributionsAtFocus) — lets
|
|
34
|
+
* the panel build this block's descriptive breakdown (cascade,
|
|
35
|
+
* absorption/gap badges, "satellites touchés" list) from data that
|
|
36
|
+
* exactly matches totalDelta, instead of the shared isolated pool. */
|
|
37
|
+
sequentialDetailPool?: ForceFieldLinkDetail[];
|
|
38
|
+
/** Arrivées de la seule résolution de ce bloc : pool séquentiel quand il
|
|
39
|
+
* existe, sinon les lignes de la résolution de cet item. Lues par les
|
|
40
|
+
* listes Source / Bilan et la comète (PROP-VIZ-01). */
|
|
41
|
+
resolutionPool?: ForceFieldLinkDetail[];
|
|
42
|
+
/** Position dans la pile (ActionStackItem.slotIndex) — permet de fusionner
|
|
43
|
+
* et trier les blocs "keyEvent" avec les blocs action dans leur ordre
|
|
44
|
+
* naturel de pile (voir renderCumulativeDetailsForCutting). */
|
|
45
|
+
slotIndex?: number;
|
|
46
|
+
/** Bouclier de stabilité déjà actif sur le satellite en focus quand ce
|
|
47
|
+
* bloc s'est résolu (bloc "source" uniquement). */
|
|
48
|
+
activeShield?: ActiveShield;
|
|
49
|
+
/** Bouclier créé par cette action (slots de stabilisation déclenchés). */
|
|
50
|
+
createdShield?: number;
|
|
51
|
+
/** Réduction appliquée par le bouclier du satellite en focus à la
|
|
52
|
+
* contribution négative de ce bloc — journal de résolution. */
|
|
53
|
+
shieldAbsorption?: AbsorptionBreakdown;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Bloc "keyEvent" de la vue cumulative : un Événement Clé joué (kind="keyEvent"
|
|
57
|
+
* dans la pile), toujours affiché dès que sa Facette d'origine correspond à
|
|
58
|
+
* celle affichée — voir buildKeyEventBlocksForComponent. `active` distingue
|
|
59
|
+
* visuellement "amplifie actuellement une action ciblée" de "présent mais
|
|
60
|
+
* rien ne l'active encore" (voir isKeyEventCurrentlyActive) ; l'existence du
|
|
61
|
+
* bloc, elle, ne dépend jamais de cette condition.
|
|
62
|
+
*/
|
|
63
|
+
export type KeyEventCumulativeBlock = {
|
|
64
|
+
type: "keyEvent";
|
|
65
|
+
keyEventId: string;
|
|
66
|
+
active: boolean;
|
|
67
|
+
totalDelta: number;
|
|
68
|
+
slotIndex?: number;
|
|
69
|
+
stackItemId?: string;
|
|
70
|
+
color?: string;
|
|
71
|
+
targetedActions: Array<{
|
|
72
|
+
id: string;
|
|
73
|
+
name: string;
|
|
74
|
+
}>;
|
|
75
|
+
breakdowns?: AmplifierTargetBreakdown[];
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Un bloc de la vue cumulative (mode STACK). Hissé au niveau module (au lieu
|
|
79
|
+
* d'un type local à renderCumulativeDetailsForCutting) pour être partagé avec
|
|
80
|
+
* buildKeyEventBlocksForComponent, réutilisé aussi par renderComposanteInfo
|
|
81
|
+
* quand aucun satellite n'est sélectionné.
|
|
82
|
+
*/
|
|
83
|
+
export type CumulativeBlock = ActionCumulativeBlock | KeyEventCumulativeBlock;
|
|
84
|
+
/** Navigation diagramme → panneau RECHERCHE (voir setOnDiagramNavChange). */
|
|
85
|
+
export type DiagramNavEvent = {
|
|
86
|
+
type: "composante";
|
|
87
|
+
componentIndex: number;
|
|
88
|
+
} | {
|
|
89
|
+
type: "cutting";
|
|
90
|
+
componentIndex: number;
|
|
91
|
+
oddId: string;
|
|
92
|
+
cuttingIndex: number;
|
|
93
|
+
} | {
|
|
94
|
+
type: "action";
|
|
95
|
+
componentIndex: number;
|
|
96
|
+
oddId: string;
|
|
97
|
+
cuttingIndex: number;
|
|
98
|
+
actionId: string;
|
|
99
|
+
} | {
|
|
100
|
+
type: "keyEvent";
|
|
101
|
+
componentIndex: number;
|
|
102
|
+
keyEventId: string;
|
|
103
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ActionDefinition } from "../../../data/yasuni_actions";
|
|
2
|
+
import type { KeyEventDefinition } from "../../../data/yasuni_key_events";
|
|
3
|
+
/** Catalogue indexé par ID — instancié une seule fois au chargement du module. */
|
|
4
|
+
export declare const actionMap: Map<string, ActionDefinition>;
|
|
5
|
+
/**
|
|
6
|
+
* Cibles d'un Événement Clé prêtes pour buildKeyEventCardHtml : id + nom,
|
|
7
|
+
* la carte affichant pour chacune le seul bonus ajouté par l'effet (pas de
|
|
8
|
+
* deltas du catalogue à charrier jusque-là). Les deux points d'appel (clic
|
|
9
|
+
* sur le cercle central, cartes cumulées du panneau) passent par ici — une
|
|
10
|
+
* seule définition de la forme attendue.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildKeyEventTargets(keyEvent: KeyEventDefinition): Array<{
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}>;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { PropagationScope } from "../../../interfaces/IPropagationGraph";
|
|
2
|
+
/** Libellé de la portée réelle d'une arête du graphe unifié (PROP-GRAPH-04) :
|
|
3
|
+
* la même mécanique, seule la destination change. */
|
|
4
|
+
export declare function getScopeDisplayName(scope: PropagationScope): string;
|
|
5
|
+
/** Classe CSS d'une ligne selon sa portée (voir details-panel.css). */
|
|
6
|
+
export declare function getScopeCssClass(scope: PropagationScope): string;
|
|
7
|
+
/**
|
|
8
|
+
* Delta affiché sur un lien du champ de force qui regroupe plusieurs
|
|
9
|
+
* arrivées le long du même trajet (même satellite de départ, même cible) :
|
|
10
|
+
* leur somme, c'est-à-dire tout ce que ce trajet apporte réellement à la
|
|
11
|
+
* cible dans la résolution.
|
|
12
|
+
*/
|
|
13
|
+
export declare function calculateDisplayedDelta(details: readonly {
|
|
4
14
|
deltaTo: number;
|
|
5
|
-
};
|
|
6
|
-
export declare function getForceFieldWeightLabel(layerType: ForceFieldLayerType): string;
|
|
7
|
-
export declare function getLayerDisplayName(layerType: ForceFieldLayerType): string;
|
|
8
|
-
export declare function getPropagationCardTitle(layerType: ForceFieldLayerType): string;
|
|
9
|
-
export declare function calculateDisplayedDelta(details: ForceFieldDeltaDetail[]): number;
|
|
15
|
+
}[]): number;
|