@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.
Files changed (66) hide show
  1. package/dist/bundle.js +1 -1
  2. package/dist/types/adapters/yasuniCauseAdapter.d.ts +31 -5
  3. package/dist/types/api.d.ts +5 -1
  4. package/dist/types/components/controller/YinYangController.d.ts +63 -679
  5. package/dist/types/components/controller/action-stack/ActionStackController.d.ts +35 -0
  6. package/dist/types/components/controller/action-stack/ActionStackManager.d.ts +9 -0
  7. package/dist/types/components/controller/action-stack/StackFocusController.d.ts +105 -0
  8. package/dist/types/components/controller/actions/ActionProjectionService.d.ts +32 -3
  9. package/dist/types/components/controller/actions/ChildActionMenuController.d.ts +8 -4
  10. package/dist/types/components/controller/actions/CoreEventMenuController.d.ts +13 -13
  11. package/dist/types/components/controller/actions/KeyEventController.d.ts +192 -0
  12. package/dist/types/components/controller/actions/radialItemMenu.d.ts +0 -9
  13. package/dist/types/components/controller/children/ChildrenBuilder.d.ts +95 -0
  14. package/dist/types/components/controller/children/ComponentSwitchCoordinator.d.ts +80 -0
  15. package/dist/types/components/controller/debug/ControllerDebugTools.d.ts +81 -0
  16. package/dist/types/components/controller/force-field/ForceFieldComputationService.d.ts +3 -15
  17. package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +120 -66
  18. package/dist/types/components/controller/force-field/ForceFieldDetailsPresenter.d.ts +139 -0
  19. package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +0 -8
  20. package/dist/types/components/controller/force-field/IncomingForceFieldService.d.ts +53 -0
  21. package/dist/types/components/controller/force-field/PropagationAnimator.d.ts +56 -0
  22. package/dist/types/components/controller/force-field/edgeIdentity.d.ts +28 -0
  23. package/dist/types/components/controller/force-field/incomingContinuation.d.ts +22 -0
  24. package/dist/types/components/controller/force-field/propagation-viz/PropagationCometPlayer.d.ts +60 -0
  25. package/dist/types/components/controller/force-field/propagation-viz/propagationVizLists.d.ts +51 -0
  26. package/dist/types/components/controller/force-field/propagation-viz/propagationVizModel.d.ts +60 -0
  27. package/dist/types/components/controller/force-field/propagationTree.d.ts +32 -0
  28. package/dist/types/components/controller/force-field/shieldViewModel.d.ts +79 -0
  29. package/dist/types/components/controller/force-field/types.d.ts +37 -10
  30. package/dist/types/components/controller/labels/ComponentTitlePresenter.d.ts +99 -0
  31. package/dist/types/components/controller/navigation/DiagramNavigator.d.ts +64 -0
  32. package/dist/types/components/controller/odd/OddViewManager.d.ts +1 -1
  33. package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +9 -0
  34. package/dist/types/components/controller/state/ControllerSession.d.ts +107 -0
  35. package/dist/types/components/controller/state/ControllerUiCallbacks.d.ts +60 -0
  36. package/dist/types/components/controller/state/YinYangControllerState.d.ts +4 -5
  37. package/dist/types/components/controller/types.d.ts +103 -0
  38. package/dist/types/components/controller/utils/actionCatalog.d.ts +15 -0
  39. package/dist/types/components/controller/utils/forceFieldPresentation.d.ts +14 -8
  40. package/dist/types/components/search/GlobalSearchController.d.ts +68 -9
  41. package/dist/types/components/view/BorderDrawer.d.ts +5 -0
  42. package/dist/types/components/workspace/workspaceTemplate.d.ts +1 -1
  43. package/dist/types/config/propagationCometConfig.d.ts +9 -36
  44. package/dist/types/config/propagationCometVizConfig.d.ts +34 -0
  45. package/dist/types/data/activeDiagram.d.ts +4 -6
  46. package/dist/types/data/adverse-action-planner.d.ts +22 -0
  47. package/dist/types/data/catalogue-coverage.d.ts +26 -0
  48. package/dist/types/data/combo-engine.d.ts +76 -21
  49. package/dist/types/data/contacts/buildContactSphere.d.ts +23 -4
  50. package/dist/types/data/contacts/index.d.ts +6 -3
  51. package/dist/types/data/propagation-graph.d.ts +16 -0
  52. package/dist/types/data/stability-shield.d.ts +21 -0
  53. package/dist/types/data/yasuni_actions.d.ts +38 -5
  54. package/dist/types/data/yasuni_cause.d.ts +7 -0
  55. package/dist/types/data/yasuni_key_events.d.ts +3 -2
  56. package/dist/types/interfaces/IPropagationGraph.d.ts +39 -0
  57. package/dist/types/interfaces/IYinYangController.d.ts +2 -2
  58. package/dist/types/utils/actionPropagation.d.ts +104 -32
  59. package/dist/types/utils/adverseMode.d.ts +14 -0
  60. package/package.json +4 -2
  61. package/dist/types/components/controller/utils/forceFieldMetadata.d.ts +0 -4
  62. package/dist/types/data/yasuni_graph.d.ts +0 -22
  63. package/dist/types/data/yasuni_propagation_layers.d.ts +0 -3
  64. package/dist/types/interfaces/ICauseGraph.d.ts +0 -9
  65. package/dist/types/interfaces/IPropagationLayers.d.ts +0 -27
  66. package/dist/types/utils/causeGraph.d.ts +0 -6
@@ -0,0 +1,80 @@
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 { ActionStackItem } from "../action-stack/ActionStackController";
6
+ import { ForceFieldDetailsPanel } from "../force-field/ForceFieldDetailsPanel";
7
+ import { ForceFieldRenderer } from "../force-field/ForceFieldRenderer";
8
+ import { EventFieldRenderer } from "../force-field/EventFieldRenderer";
9
+ import { ForceFieldLinkDetail } from "../force-field/types";
10
+ import { YinYangControllerState } from "../state/YinYangControllerState";
11
+ import { IncomingForceFieldService } from "../force-field/IncomingForceFieldService";
12
+ import { ForceFieldDetailsPresenter } from "../force-field/ForceFieldDetailsPresenter";
13
+ import { DiagramNavigator } from "../navigation/DiagramNavigator";
14
+ import { KeyEventController } from "../actions/KeyEventController";
15
+ import { ComponentTitlePresenter } from "../labels/ComponentTitlePresenter";
16
+ import { PropagationAnimator } from "../force-field/PropagationAnimator";
17
+ import { ControllerSession } from "../state/ControllerSession";
18
+ import { EventFieldLifecycleController } from "../force-field/EventFieldLifecycleController";
19
+ import { ActionStackManager } from "../action-stack/ActionStackManager";
20
+ export type ComponentSwitchCoordinatorDeps = {
21
+ actionStackManager: ActionStackManager;
22
+ activateActionFromChild: (childController: IYinYangController, actionId?: string, label?: string, clearStack?: boolean) => void;
23
+ applyEmptyGhostProjectionState: () => void;
24
+ applyEnterOddView: (oddId: string) => void;
25
+ applyOddHighlight: (oddId: string) => void;
26
+ applyProjectedGhostFromStackItems: (items: ActionStackItem[]) => void;
27
+ buildChildrenOrbitData: () => ChildrenOrbitEntry[];
28
+ getChildControllers: () => IYinYangController[];
29
+ childOddMap: Map<string, {
30
+ oddId: string;
31
+ score: number;
32
+ cuttingIndex: number;
33
+ }>;
34
+ clearActiveChild: () => void;
35
+ clearChildren: () => void;
36
+ createYinYangChildren: () => void;
37
+ detailsPresenter: ForceFieldDetailsPresenter;
38
+ disableOuterSpark: () => void;
39
+ eventFieldLifecycleController: EventFieldLifecycleController;
40
+ eventFieldRenderer: EventFieldRenderer;
41
+ focusChildByOddCutting: (oddId: string, cuttingIndex: number, forceOpen?: boolean) => void;
42
+ focusChildByOddCuttingAndAction: (oddId: string, cuttingIndex: number, actionId: string) => void;
43
+ forceFieldDetailsPanel: ForceFieldDetailsPanel;
44
+ forceFieldRenderer: ForceFieldRenderer;
45
+ getAllComponents: () => YinYangInternalModel["components"];
46
+ getCurrentComponent: () => YinYangInternalModel["components"][number] | null;
47
+ getCurrentComponentOrUndefined: () => YinYangInternalModel["components"][number] | undefined;
48
+ incomingForceField: IncomingForceFieldService;
49
+ keyEvents: KeyEventController;
50
+ navigator: DiagramNavigator;
51
+ propagationAnimator: PropagationAnimator;
52
+ renderOppositeChildrenForceField: (orbitData?: ChildrenOrbitEntry[], angleOffset?: number) => void;
53
+ session: ControllerSession;
54
+ state: YinYangControllerState;
55
+ syncGhostTensionFromAction: () => void;
56
+ titlePresenter: ComponentTitlePresenter;
57
+ view: IYinYangView;
58
+ };
59
+ /** Changement de facette : prépare le contexte (action à réactiver, champ
60
+ * entrant, navigation en attente) avant de masquer les satellites, puis le
61
+ * rejoue à l'arrivée une fois les nouveaux satellites créés. */
62
+ export declare class ComponentSwitchCoordinator {
63
+ private deps;
64
+ constructor(deps: ComponentSwitchCoordinatorDeps);
65
+ prepareForComponentSwitch(targetComponentId: string): void;
66
+ handleComponentSwitchChildren(): void;
67
+ refreshChildrenForComponentSwitch(): Promise<void>;
68
+ restoreIncomingForceFieldContext(context: {
69
+ type: "incoming";
70
+ sourceComponentId: string;
71
+ linksByOddId: Map<string, {
72
+ toOddId: string;
73
+ thickness: number;
74
+ potentialGain: number;
75
+ detail: ForceFieldLinkDetail;
76
+ sourceOriginKey?: string;
77
+ }>;
78
+ }): void;
79
+ private reactivatePersistentAction;
80
+ }
@@ -0,0 +1,81 @@
1
+ import { IYinYangView } from "../../../interfaces/IYinYangView";
2
+ import { IYinYangController } from "../../../interfaces/IYinYangController";
3
+ import { type ActionDefinition } from "../../../data/yasuni_actions";
4
+ import { ActionStackController } from "../action-stack/ActionStackController";
5
+ import { YinYangControllerState } from "../state/YinYangControllerState";
6
+ import type { ControllerUiCallbacks } from "../state/ControllerUiCallbacks";
7
+ export type ControllerDebugToolsDeps = {
8
+ actionStackController: ActionStackController;
9
+ getChildControllers: () => IYinYangController[];
10
+ disableOuterSpark: () => void;
11
+ getActionsForChild: (childKey: string, filter?: "mode" | "playable" | "adverse" | "all") => ActionDefinition[];
12
+ setChildrenEnabled: (isEnabled: boolean) => void;
13
+ state: YinYangControllerState;
14
+ ui: ControllerUiCallbacks;
15
+ validateActionSelection: (childController: IYinYangController, actionId: string, label: string, insertAtVisibleIndex?: number | null, entryOrigin?: {
16
+ x: number;
17
+ y: number;
18
+ }) => void;
19
+ view: IYinYangView;
20
+ };
21
+ /** Outils de développement (boutons dev du panneau de contrôle) : remplissage
22
+ * aléatoire de la pile, insertion d'actions adverses, étincelles. */
23
+ export declare class ControllerDebugTools {
24
+ private deps;
25
+ constructor(deps: ControllerDebugToolsDeps);
26
+ /**
27
+ * Dev-only helper: vide la pile d'actions et la remplit avec des actions
28
+ * choisies au hasard parmi les enfants visibles, en réutilisant le pipeline
29
+ * normal de validation (`validateActionSelection`) afin d'exercer le même
30
+ * calcul de projection ghost que dans l'usage réel. Sert à tester
31
+ * rapidement l'affichage des yin-yang ghost sans clics manuels répétés.
32
+ */
33
+ debugFillActionStackWithRandomActions(count?: number): void;
34
+ /** Dev-only: toggles the perimeter spark sweep from the "Étincelle"
35
+ * button — a second click restores whatever it was before the first
36
+ * (off, in every normal case, since the spark otherwise never turns on
37
+ * by itself). The spark stays purely opt-in — this button and the
38
+ * "Étincelle périmètre" checkbox are the only ways to start it. */
39
+ triggerOuterSparkDev(): void;
40
+ /** Dev-only: (re)lance l'étincelle d'équilibre sur la facette active.
41
+ * L'orientation passée est celle de la facette, c'est-à-dire son lobe
42
+ * dominant (getRadiiForScore le dessine à 0.5 + score/2, donc toujours
43
+ * le plus grand des deux) : c'est la seule qui satisfasse le contrat de
44
+ * triggerBalanceSpark, qui calibre la croissance de queue et le taux de
45
+ * combustion partagé sur l'étincelle primaire. Elle était codée en dur
46
+ * sur "yang", ce qui inversait les rôles sur une facette yin-dominante
47
+ * — la survivante se faisait alors tuer par la limite de durée de vie à
48
+ * l'instant même où sa jumelle s'éteignait, sans pondre un seul têtard.
49
+ * Contrairement à l'étincelle du périmètre, c'est une animation
50
+ * ponctuelle (elle s'arrête d'elle-même une fois le sous-cercle
51
+ * parcouru à moitié) : chaque clic la relance depuis le début plutôt
52
+ * que de la toggle. `onComplete`, transmis tel quel à triggerBalanceSpark,
53
+ * permet à l'appelant (le bouton dev, une fois basculé en mode actif) de
54
+ * la relancer en boucle sans dupliquer sa logique de durée. */
55
+ triggerBalanceSparkDev(onComplete?: () => void): void;
56
+ /**
57
+ * Dev-only : le système place lui-même `count` items adverses — actions
58
+ * ET Événements adverses (yasuni_adverse_key_events.ts) — dans la pile
59
+ * active, piochés dans tout le catalogue (toutes les facettes, pas
60
+ * seulement celle affichée à l'écran), aux slots choisis par
61
+ * adverse-action-planner.ts (chaînes de combos complètes, ordre narratif,
62
+ * fenêtres d'effet respectées — un combo d'action adverse peut avoir un
63
+ * Événement adverse pour prérequis). Les adverses déjà présents dans la
64
+ * pile ne sont pas rejoués.
65
+ *
66
+ * Une action d'une facette non affichée n'a pas de childController vivant
67
+ * (childControllers/childOddMap ne connaissent que la facette courante,
68
+ * voir createYinYangChildren) : l'item de pile est donc construit à la
69
+ * main plutôt que via ActionStackManager.insertActionAtSlot, qui exige un
70
+ * childController réel. sourceChildKey reste au sentinel "" — le reste du
71
+ * code résout toujours l'origine d'un item via sourceComponentId /
72
+ * sourceOddId / sourceCuttingIndex, jamais via sourceChildKey une fois en
73
+ * pile (childOddMap est reconstruit avec de nouvelles clés à chaque
74
+ * changement de facette). Un Événement adverse porte les sentinelles d'un
75
+ * item keyEvent (sourceOddId "" / sourceCuttingIndex −1, voir
76
+ * validateKeyEventSelection) et sa Facette d'origine en sourceComponentId
77
+ * — indispensable au scoping Facette de son bloc dans l'ANALYSE (voir
78
+ * buildKeyEventBlocksForComponent).
79
+ */
80
+ debugInsertAdverseActions(count: number): void;
81
+ }
@@ -1,15 +1,7 @@
1
- import { type PropagatedActionEdge } from "../../../utils/actionPropagation";
2
1
  import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
3
- import { CauseGraph } from "../../../interfaces/ICauseGraph";
4
- import { PropagationLayersConfig } from "../../../interfaces/IPropagationLayers";
2
+ import type { CompiledPropagationGraph } from "../../../interfaces/IPropagationGraph";
5
3
  import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
6
4
  import { ForceFieldLink, ForceFieldLinkDetail } from "./types";
7
- /** Single source of truth for turning a raw propagation edge into the
8
- * enriched ForceFieldLinkDetail the UI consumes (rationale, layer
9
- * summaries…) — shared by build(), buildFromSource(), and any other caller
10
- * that needs to map edges from computeActionPropagationDetails/
11
- * propagateForceFieldActionInComponent without re-deriving this metadata. */
12
- export declare function mapPropagatedEdgeToDetail(edge: PropagatedActionEdge, componentId: string): ForceFieldLinkDetail;
13
5
  export declare class ForceFieldComputationService {
14
6
  build(params: {
15
7
  orbitData: ChildrenOrbitEntry[];
@@ -22,9 +14,7 @@ export declare class ForceFieldComputationService {
22
14
  component: YinYangInternalModel["components"][number] | null;
23
15
  allComponents: YinYangInternalModel["components"] | undefined;
24
16
  actionDelta: number;
25
- actionPropagationFactor: number;
26
- interconnectionGraph: CauseGraph;
27
- propagationLayers: PropagationLayersConfig;
17
+ propagationGraph: CompiledPropagationGraph;
28
18
  }): {
29
19
  links: ForceFieldLink[];
30
20
  allLinkDetails: ForceFieldLinkDetail[];
@@ -40,9 +30,7 @@ export declare class ForceFieldComputationService {
40
30
  component: YinYangInternalModel["components"][number];
41
31
  allComponents: YinYangInternalModel["components"] | undefined;
42
32
  actionDelta: number;
43
- actionPropagationFactor: number;
44
- interconnectionGraph: CauseGraph;
45
- propagationLayers: PropagationLayersConfig;
33
+ propagationGraph: CompiledPropagationGraph;
46
34
  }): {
47
35
  links: ForceFieldLink[];
48
36
  allLinkDetails: ForceFieldLinkDetail[];
@@ -1,6 +1,8 @@
1
+ import { type CometPlayFn } from "./propagation-viz/propagationVizLists";
1
2
  import { YinYangComponentNode, YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
2
3
  import { ForceFieldLink, ForceFieldLinkDetail } from "./types";
3
4
  import type { ComboResult } from "../../../data/combo-engine";
5
+ import { type AbsorptionBreakdown, type ActiveShield } from "./shieldViewModel";
4
6
  import type { AmplifierResult, AmplifierTargetBreakdown } from "../../../data/amplifier-engine";
5
7
  import { type KeyEventDefinition } from "../../../data/yasuni_key_events";
6
8
  import type { Composante, ODD } from "../../../data/yasuni_cause";
@@ -23,6 +25,9 @@ type ActionCumulativeBlockViewModel = {
23
25
  actionDescription: string;
24
26
  sourceComponentName?: string;
25
27
  sourceOddName?: string;
28
+ /** Facette du satellite qui porte l'action (peut différer de la facette
29
+ * affichée pour un bloc de propagation). */
30
+ sourceComponentId?: string;
26
31
  sourceOddId: string;
27
32
  sourceCuttingId: number | undefined;
28
33
  totalDelta: number;
@@ -43,10 +48,23 @@ type ActionCumulativeBlockViewModel = {
43
48
  stackItemId?: string;
44
49
  color?: string;
45
50
  sequentialDetailPool?: ForceFieldLinkDetail[];
51
+ /** Arrivées de la seule résolution de ce bloc (PROP-VIZ-01). */
52
+ resolutionPool?: ForceFieldLinkDetail[];
46
53
  /** Position dans la pile (ActionStackItem.slotIndex) — permet de fusionner
47
54
  * et trier les blocs "keyEvent" (voir ci-dessous) avec les blocs action
48
55
  * dans leur ordre naturel de pile. */
49
56
  slotIndex?: number;
57
+ /** Bouclier de stabilité déjà actif sur le satellite en focus au moment
58
+ * où ce bloc s'est résolu (type "source" uniquement — l'action vise ce
59
+ * satellite). Voir shieldViewModel.ts. */
60
+ activeShield?: ActiveShield;
61
+ /** Bouclier que cette action crée elle-même (slots de stabilisation
62
+ * déclenchés), à confronter à activeShield. */
63
+ createdShield?: number;
64
+ /** Réduction appliquée par le bouclier du satellite en focus à la
65
+ * contribution négative de ce bloc — direct, propagé, agrégé, absorbé,
66
+ * appliqué (journal de résolution). */
67
+ shieldAbsorption?: AbsorptionBreakdown;
50
68
  };
51
69
  /** Bloc "keyEvent" : un Événement Clé joué, toujours affiché dès que sa
52
70
  * Facette d'origine correspond à celle affichée (voir YinYangController.
@@ -68,15 +86,24 @@ type KeyEventCumulativeBlockViewModel = {
68
86
  };
69
87
  type CumulativeBlockViewModel = ActionCumulativeBlockViewModel | KeyEventCumulativeBlockViewModel;
70
88
  export declare class ForceFieldDetailsPanel {
89
+ /** Même seuil que le glisser vers la pile (YinYangController). */
90
+ private static readonly TAG_DRAG_THRESHOLD_PX;
71
91
  private onComboHighlight?;
72
92
  private onComboClear?;
73
93
  /** Key of the currently active (clicked) combo card — persists across re-renders. */
74
94
  private activeComboCardKey;
95
+ /** Item de pile passé en focus alors que les barres d'une carte combo
96
+ * étaient affichées : son bloc reprend les barres dès que sa carte
97
+ * équivalente est rendue (voir _reanchorActiveComboCard). */
98
+ private _pendingComboReanchorItemId;
75
99
  /** Resolves an action ID to its display name for combo rules. Defaults to identity. */
76
100
  private resolveActionName;
77
101
  /** Called when the user clicks an action rule tag.
78
102
  * Second argument is the combo context of the card containing the tag (if any). */
79
103
  private onActionTagClick?;
104
+ /** Called on pointerdown on an action rule tag / prereq name: lets the
105
+ * controller start a drag of that action toward the stack. */
106
+ private onActionTagDragStart?;
80
107
  /** Cached propagation index, invalidated when force-field data changes. */
81
108
  private _cachedPropagationIndex;
82
109
  /** When non-null, clearForceFieldDetails is a no-op (panel frozen during component switch). */
@@ -125,6 +152,7 @@ export declare class ForceFieldDetailsPanel {
125
152
  private _onStackItemHighlightCb?;
126
153
  /** Clic sur l'en-tête d'un bloc → action en focus (YinYangController). */
127
154
  private _onStackItemFocusCb?;
155
+ private _onShieldOriginClickCb?;
128
156
  /** Miroir de state.forceField.focusedStackItemId — sert uniquement à
129
157
  * ré-appliquer .ff-block--focused après chaque innerHTML. */
130
158
  private _focusedStackItemId;
@@ -154,6 +182,7 @@ export declare class ForceFieldDetailsPanel {
154
182
  setSphereInfo(name: string, description: string): void;
155
183
  setActionNameResolver(resolver: (id: string) => string): void;
156
184
  setActionTagClickCallback(cb: (actionId: string, comboContext?: ActionTagComboContext) => void): void;
185
+ setActionTagDragStartCallback(cb: (actionId: string, comboContext: ActionTagComboContext | undefined, event: PointerEvent, el: HTMLElement) => void): void;
157
186
  /**
158
187
  * Enregistre les callbacks de surlignage combo.
159
188
  * Doit être appelé une seule fois depuis YinYangController après instanciation.
@@ -169,6 +198,14 @@ export declare class ForceFieldDetailsPanel {
169
198
  * même clé via data-keyevent-item-id : deux éléments DOM, un seul bloc
170
199
  * logique). */
171
200
  private _getCardKey;
201
+ /** Clé de la carte dont les barres sont affichées : _getCardKey plus
202
+ * l'item de pile porteur, car la même action présente deux fois dans la
203
+ * pile a deux cartes combo de même contenu mais d'ancres différentes. */
204
+ private _getHighlightCardKey;
205
+ /** Titre de carte, gabarit commun à toutes les cartes du rail : étiquette
206
+ * de type facultative (couleur --card-accent de la carte) puis nom
207
+ * lisible — l'information principale à lire. */
208
+ private _cardTitleHtml;
172
209
  /** True pour une carte dont l'état déplié/replié doit être suivi via
173
210
  * _getCardKey (contenu) plutôt que via sa position dans la grid — combo,
174
211
  * ou Événement Clé/action adverse (.ff-chain-keyevent-detail,
@@ -342,6 +379,47 @@ export declare class ForceFieldDetailsPanel {
342
379
  * _attachComboHighlightHandlers) couvrent déjà les attributs data-keyevent-*.
343
380
  */
344
381
  private _buildKeyEventBlockHtml;
382
+ /** Contenu d'origine des cartes combo mises en aperçu par
383
+ * previewComboCardsForItem — restauré tel quel (nœuds et gestionnaires
384
+ * compris) quand l'aperçu s'arrête. */
385
+ private _comboPreviewOriginals;
386
+ /**
387
+ * Aperçu en direct, pendant le glisser guidé d'un prérequis, des cartes
388
+ * combo de l'item `stackItemId` : `comboResults` est le résultat que
389
+ * donnerait le dépôt à l'emplacement survolé. Seul le contenu sous la
390
+ * description (héro, note bouclier, tableau, conseil) est remplacé ; null
391
+ * restaure le contenu d'origine (hors zone de dépôt, fin du glisser).
392
+ */
393
+ previewComboCardsForItem(stackItemId: string, comboResults: ComboResult[] | null): void;
394
+ /**
395
+ * Carte combo d'une action qui n'est pas encore dans la pile (mode
396
+ * Recherche) : l'activation dépend de la position de l'action et de l'ordre
397
+ * de ses prérequis, inconnus tant qu'elle n'est pas placée. On n'affiche
398
+ * donc pas de résultat (bouclier créé, bonus effectif) — seulement le
399
+ * potentiel du combo, le tableau des prérequis (présents ou non dans la
400
+ * pile, Perf./Pos./Score projetés pour un dépôt en haut de pile) et un
401
+ * renvoi vers le mode Stack.
402
+ *
403
+ * Une sécurisation y est évaluée protecteurs supposés joués (×1, voir
404
+ * ActionStackManager.computeComboResultsForAction) pour laisser voir la
405
+ * propagation : la carte le dit, et prévient que la pile, elle, ne le
406
+ * supposera pas.
407
+ */
408
+ private _buildComboOutsideStackHtml;
409
+ /** Sécurisation hors pile, protecteurs supposés joués : risque neutralisé
410
+ * (±0 %) et tableau des protecteurs marqués « supposé joué ».
411
+ * L'avertissement vit sous le bloc (_buildAssumedProtectionNoteHtml). */
412
+ private _buildAssumedProtectionHtml;
413
+ /** Avertissement placé sous le bloc de l'action (après le rail de cartes)
414
+ * quand une sécurisation y est évaluée protecteurs supposés joués : la
415
+ * pile, elle, ne le supposera pas. Vide sinon. */
416
+ private _buildAssumedProtectionNoteHtml;
417
+ /**
418
+ * Tableau de répartition par prérequis/protecteur (Perf., Pos., Score avec
419
+ * mini-barre) — partagé par la carte combo en pile et hors pile (RECHERCHE,
420
+ * où les valeurs projettent un dépôt de l'action en haut de la pile).
421
+ */
422
+ private _buildPrereqTableHtml;
345
423
  /**
346
424
  * Construit le bloc de détail d'un combo : valeur héro (multiplicateur
347
425
  * effectif), tableau de répartition par prérequis/protecteur (avec
@@ -362,6 +440,14 @@ export declare class ForceFieldDetailsPanel {
362
440
  * blocs source (combos vs baseDelta) ET propagation (Abs/Gap vs rawDelta) —
363
441
  * même sémantique des deux côtés, juste un nominal différent. */
364
442
  private _computeBlockOptimizationRatio;
443
+ /** Note « bouclier » de la carte bilan : bouclier actif sur le satellite
444
+ * et, dans le journal de résolution, la réduction réellement appliquée
445
+ * (direct, propagé, agrégé, absorbé, appliqué). Vide sans bouclier. */
446
+ private _buildShieldNoteHtml;
447
+ /** Carte « Bouclier » : maillon additif entre les modificateurs et le
448
+ * Bilan — badge = points absorbés, donc delta avant bouclier + badge =
449
+ * Bilan. Vide quand le bouclier n'a rien réduit dans ce bloc. */
450
+ private _buildShieldCardHtml;
365
451
  private _buildTotalCardHtml;
366
452
  /** Delta "brut" d'une ligne de propagation, avant application d'Absorption
367
453
  * et Gap — sert à la fois à décomposer leur contribution (cartes Abs/Gap)
@@ -386,19 +472,6 @@ export declare class ForceFieldDetailsPanel {
386
472
  * carrying the given nav data attributes. This is the sole navigation trigger for a
387
473
  * listed element — clicking the label itself now animates instead of navigating. */
388
474
  private _buildNavTargetIconHtml;
389
- /** Steps HTML for the propagation source card: one line per sortedDirect row,
390
- * each clickable to navigate back to the source satellite. */
391
- private _buildPropSourceStepsHtml;
392
- /** Flat list of cascade targets (satellites X sends to) for the bilan card. */
393
- /** Reconstructs the forward path origin → ... → (toOddId, toCuttingId) by walking
394
- * cascadeRows backward via fromCuttingId (picking one contributing row per hop when
395
- * several exist, same simplification as _getBranchLabel's "first cascade" pick).
396
- * Used to give each cascade-list entry its own isolated flash sequence. */
397
- private _buildCascadeFlashPath;
398
- private _buildCascadeListHtml;
399
- /** Simple chain-steps HTML from TargetChainData — used in the collapsible section
400
- * when no flash-target context is available (cumulative panel). */
401
- private _buildPropChainStepsHtml;
402
475
  private _buildDetailDisclosureHtml;
403
476
  private _snapshotCardExpansion;
404
477
  /**
@@ -416,52 +489,30 @@ export declare class ForceFieldDetailsPanel {
416
489
  private _initCardRailState;
417
490
  private _handleCardRailClick;
418
491
  private _triggerHighlightFromCard;
419
- /** Maps every row within a target chain's chainCards (trigger + steps) to that card's
420
- * own flash sequence — the diagram nodes lit up when isolating just that one
421
- * propagation path (a bridge hop, an inter-ODD hop, or a pure-intra chain). Shared by
422
- * every panel that offers a "flash all paths combined" header plus a per-path,
423
- * badge-isolated flash (buildPropagatedActionHtml and renderCumulativeActionDetails). */
424
- private _computeChainCardFlashes;
425
- /** Builds a chain-card's final flash sequence: `source` first, then `cardFlash` in its
426
- * own (causally correct) order, deduped by node so the same satellite never flashes
427
- * twice. `target` (the currently focused satellite) is only force-inserted right after
428
- * `source` when `cardFlash` wouldn't otherwise reach it at all — e.g. an inter trigger
429
- * whose own BFS didn't resolve to this exact cutting. When `cardFlash` DOES naturally
430
- * include `target` (the common case), it's left at its true causal position instead of
431
- * being jumped to the front: for a chainCard like "Maladies de peau → Populations
432
- * exposées", forcing the focused satellite (Populations exposées) to position 2 would
433
- * make it flash *before* the intermediate ancestor that actually causes it. Shared by
434
- * every panel presenting a propagation-path flash (buildPropagatedActionHtml,
435
- * renderCumulativeActionDetails) so their animations never diverge. */
436
- private _finalizeFlashSequence;
437
- private _buildBranchFlashSequence;
438
- private _getBranchLabel;
492
+ /** Nom d'un satellite résolu dans sa facette (`componentId`), à défaut
493
+ * dans la facette affichée. */
494
+ /** Lecteur de la comète des listes Source / Bilan (PROP-VIZ-01). */
495
+ private _cometPlay;
496
+ /** Arrivées de la résolution de chaque item de pile dont un bloc est
497
+ * affiché (celles que lisent ses listes Source / Bilan) : la boucle de
498
+ * l'action en focus y lit ses trajets, pour suivre exactement les mêmes. */
499
+ private _stackItemResolutionPools;
500
+ getStackItemResolutionPool(stackItemId: string): readonly ForceFieldLinkDetail[] | undefined;
501
+ setPropagationCometPlayer(play: CometPlayFn): void;
502
+ /** Constructeur des listes Source / Bilan d'un rendu : noms des
503
+ * satellites, réticules de navigation et lecteur de comète. */
504
+ private _createVizLists;
505
+ private _satelliteName;
439
506
  private _handleCardRailClickPrelude;
440
507
  private _resolveDetailPool;
441
508
  private _ensurePropagationIndex;
442
509
  invalidatePropagationIndex(): void;
443
510
  private static _buildTargetChainKey;
444
- private static _buildSourceChainKey;
445
- /** Whether this chain's own satellite is the direct target of a bridge (cross-component)
446
- * edge — an intrinsic property of the chain, independent of which upstream source is
447
- * asking. Chains only reached *indirectly* through an intermediate node that itself
448
- * received a bridge (e.g. one more intra hop downstream) don't qualify: the bridge
449
- * badge should mark the satellite the bridge actually lands on, not everything
450
- * downstream of it. */
451
- private static _chainHasDirectBridgeEdge;
452
511
  private _buildTargetChainData;
453
- /** Builds one TargetChainData per distinct cutting reached within a
454
- * self-contained, single-source pool (e.g. one stack item's own
455
- * sequential-step edges) — the per-item equivalent of
456
- * propagationIndex.sourceToTargetChains, without needing the shared
457
- * cross-item index since the pool already belongs to exactly one action. */
458
- private _buildBranchesFromPool;
459
- private _buildDetailRowKey;
460
512
  private _buildTargetGroupKey;
461
513
  private _renderChainCardHtml;
462
514
  private _selectPropagationTableViewModel;
463
515
  private _selectCumulativeViewModel;
464
- private _selectTargetChainCards;
465
516
  renderCumulativeActionDetails(params: {
466
517
  focusOddId: string;
467
518
  focusCuttingId: number | undefined;
@@ -470,11 +521,6 @@ export declare class ForceFieldDetailsPanel {
470
521
  allComponents?: YinYangComponentNode[];
471
522
  forceFieldLinks: ForceFieldLink[];
472
523
  allForceFieldLinkDetails: ForceFieldLinkDetail[];
473
- onCardElementFlash?: (targets: Array<{
474
- oddId: string;
475
- cuttingId: number | undefined;
476
- componentId?: string;
477
- }>) => void;
478
524
  onNavigateToCutting?: (toOddId: string, toCuttingId: number | undefined, toComponentId: string | undefined) => void;
479
525
  onNavigateToAction?: (actionId: string) => void;
480
526
  blocks: CumulativeBlockViewModel[];
@@ -486,8 +532,18 @@ export declare class ForceFieldDetailsPanel {
486
532
  * item de pile (le satellite/la facette porteuse est sélectionné). */
487
533
  hasBlockForStackItem(stackItemId: string): boolean;
488
534
  setStackItemFocusCallback(cb: (id: string | null) => void): void;
535
+ /** Clic sur le nom de l'action d'origine dans une carte Bouclier. */
536
+ setShieldOriginClickCallback(cb: (stackItemId: string) => void): void;
489
537
  /** Miroir du focus (source de vérité : YinYangController / state). */
490
538
  setFocusedStackItemId(id: string | null): void;
539
+ /**
540
+ * Si les barres affichées sont celles d'une carte combo d'un autre item,
541
+ * active à sa place la carte de même combo portée par `stackItemId` (même
542
+ * _getCardKey, ancre différente) et rejoue les barres. Retourne true si la
543
+ * demande est réglée (carte basculée, ou rien à faire), false si la carte
544
+ * équivalente n'est pas (encore) dans le DOM.
545
+ */
546
+ private _reanchorActiveComboCard;
491
547
  /**
492
548
  * Ré-applique .ff-block--focused sur le bloc en focus — à appeler après
493
549
  * chaque rendu de blocs (innerHTML), comme _consumePendingBlockScroll.
@@ -637,11 +693,10 @@ export declare class ForceFieldDetailsPanel {
637
693
  comboResults?: ComboResult[];
638
694
  amplifierResults?: AmplifierResult[];
639
695
  stackItemId?: string;
640
- onCardElementFlash?: (targets: Array<{
641
- oddId: string;
642
- cuttingId: number | undefined;
643
- componentId?: string;
644
- }>) => void;
696
+ /** Bouclier de stabilité déjà actif sur le satellite ciblé (posé par
697
+ * une action antérieure de la pile) — affiché sur la carte bilan et
698
+ * confronté au bouclier qu'une stabilisation prévisualisée créerait. */
699
+ activeShield?: ActiveShield;
645
700
  onNavigateToCutting?: (toOddId: string, toCuttingId: number | undefined, toComponentId: string | undefined) => void;
646
701
  onNavigateToAction?: (actionId: string) => void;
647
702
  }): {
@@ -658,11 +713,6 @@ export declare class ForceFieldDetailsPanel {
658
713
  linkIndex: number;
659
714
  forceFieldLinks: ForceFieldLink[];
660
715
  allForceFieldLinkDetails: ForceFieldLinkDetail[];
661
- onCardElementFlash?: (targets: Array<{
662
- oddId: string;
663
- cuttingId: number | undefined;
664
- componentId?: string;
665
- }>) => void;
666
716
  onNavigateToCutting?: (toOddId: string, toCuttingId: number | undefined, toComponentId: string | undefined) => void;
667
717
  actionSource?: {
668
718
  oddId: string;
@@ -671,6 +721,9 @@ export declare class ForceFieldDetailsPanel {
671
721
  incomingMode?: boolean;
672
722
  incomingSourceName?: string;
673
723
  currentComponent?: YinYangComponentNode;
724
+ /** Toutes les composantes : nomme les satellites atteints dans une autre
725
+ * facette que celle affichée. */
726
+ allComponents?: YinYangComponentNode[];
674
727
  actionId?: string;
675
728
  actionName?: string;
676
729
  actionDescription?: string;
@@ -680,10 +733,11 @@ export declare class ForceFieldDetailsPanel {
680
733
  html: string;
681
734
  attachHandlers: (container: HTMLElement) => void;
682
735
  } | null;
683
- /** Attaches the standard card↔table click handler used by detail panels with a disclosure table. */
736
+ /** Clics des panneaux à tableau de détail : repli des cartes, lien
737
+ * « pourquoi » vers le tableau et mise en évidence d'une ligne du tableau.
738
+ * La comète des listes est câblée à part (PropagationVizLists.attach). */
684
739
  private _attachDetailPanelClickHandler;
685
740
  private _installClickHandler;
686
- private _buildMultiFlashClickHandler;
687
741
  private _attachNavBtnHandlers;
688
742
  private _attachPrereqNavHandlers;
689
743
  }