@micheeeeel/yinyangapp 2.5.1 → 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
@@ -4,92 +4,8 @@ import { IYinYangController } from "../../interfaces/IYinYangController";
4
4
  import { IYinYangAppFactory } from "../../interfaces/IYinYangAppFactory";
5
5
  import { IAnimator } from "../../interfaces/IAnimator";
6
6
  import { YinYangInternalModel } from "../../interfaces/IYinYangInternalModel";
7
- import { type ComboResult } from "../../data/combo-engine";
8
- import { type AmplifierResult, type AmplifierTargetBreakdown } from "../../data/amplifier-engine";
9
7
  import { ForceFieldLinkDetail } from "./force-field/types";
10
- /**
11
- * Bloc "action" de la vue cumulative (mode STACK) : "source" = action jouée
12
- * sur le satellite ciblé, "propagation" = effet indirect qui l'atteint depuis
13
- * un autre satellite.
14
- */
15
- type ActionCumulativeBlock = {
16
- type: "source" | "propagation";
17
- actionId?: string;
18
- actionName: string;
19
- actionDescription: string;
20
- sourceComponentName?: string;
21
- sourceOddName?: string;
22
- sourceOddId: string;
23
- sourceCuttingId: number | undefined;
24
- totalDelta: number;
25
- rawDelta?: number;
26
- baseDelta?: number;
27
- weightDelta?: number;
28
- weightDeltaBase?: number;
29
- detailRows: ForceFieldLinkDetail[];
30
- comboResults?: ComboResult[];
31
- amplifierResults?: AmplifierResult[];
32
- stackItemId?: string;
33
- color?: string;
34
- /** This item's own propagation edges from the real sequential
35
- * simulation (see computeSequentialStackContributionsAtFocus) — lets
36
- * the panel build this block's descriptive breakdown (cascade,
37
- * absorption/gap badges, "satellites touchés" list) from data that
38
- * exactly matches totalDelta, instead of the shared isolated pool. */
39
- sequentialDetailPool?: ForceFieldLinkDetail[];
40
- /** Position dans la pile (ActionStackItem.slotIndex) — permet de fusionner
41
- * et trier les blocs "keyEvent" avec les blocs action dans leur ordre
42
- * naturel de pile (voir renderCumulativeDetailsForCutting). */
43
- slotIndex?: number;
44
- };
45
- /**
46
- * Bloc "keyEvent" de la vue cumulative : un Événement Clé joué (kind="keyEvent"
47
- * dans la pile), toujours affiché dès que sa Facette d'origine correspond à
48
- * celle affichée — voir buildKeyEventBlocksForComponent. `active` distingue
49
- * visuellement "amplifie actuellement une action ciblée" de "présent mais
50
- * rien ne l'active encore" (voir isKeyEventCurrentlyActive) ; l'existence du
51
- * bloc, elle, ne dépend jamais de cette condition.
52
- */
53
- type KeyEventCumulativeBlock = {
54
- type: "keyEvent";
55
- keyEventId: string;
56
- active: boolean;
57
- totalDelta: number;
58
- slotIndex?: number;
59
- stackItemId?: string;
60
- color?: string;
61
- targetedActions: Array<{
62
- id: string;
63
- name: string;
64
- }>;
65
- breakdowns?: AmplifierTargetBreakdown[];
66
- };
67
- /**
68
- * Un bloc de la vue cumulative (mode STACK). Hissé au niveau module (au lieu
69
- * d'un type local à renderCumulativeDetailsForCutting) pour être partagé avec
70
- * buildKeyEventBlocksForComponent, réutilisé aussi par renderComposanteInfo
71
- * quand aucun satellite n'est sélectionné.
72
- */
73
- export type CumulativeBlock = ActionCumulativeBlock | KeyEventCumulativeBlock;
74
- type DiagramNavEvent = {
75
- type: "composante";
76
- componentIndex: number;
77
- } | {
78
- type: "cutting";
79
- componentIndex: number;
80
- oddId: string;
81
- cuttingIndex: number;
82
- } | {
83
- type: "action";
84
- componentIndex: number;
85
- oddId: string;
86
- cuttingIndex: number;
87
- actionId: string;
88
- } | {
89
- type: "keyEvent";
90
- componentIndex: number;
91
- keyEventId: string;
92
- };
8
+ import type { DiagramNavEvent } from "./types";
93
9
  export declare class YinYangController implements IYinYangController {
94
10
  model: IYinYangModel;
95
11
  view: IYinYangView;
@@ -103,48 +19,10 @@ export declare class YinYangController implements IYinYangController {
103
19
  private rotationState;
104
20
  private childrenOrbitManager;
105
21
  private childOddMap;
106
- /**
107
- * Persists the active action across component switches.
108
- * Cleared only when the user explicitly deselects the action.
109
- */
110
- private persistentActionContext;
111
- /**
112
- * Prepared by prepareForComponentSwitch() before children are hidden.
113
- * undefined = not yet prepared (fallback path)
114
- * null = prepared but no action applies to target component
115
- * { type: 'incoming', ... } = show incoming force fields on arrival
116
- * { type: 'reactivate' } = re-activate the source action on arrival
117
- */
118
- private pendingComponentSwitchContext;
119
- private readonly CHILD_LABEL_SHORT_MAX_CHARS;
120
22
  private readonly ACTION_DRAG_THRESHOLD_PX;
121
- private htmlDragGhost;
122
- private selectedSourceFocus;
123
- /** Focus saved just before switching away from the source component, so returning
124
- * to the source component restores the same highlighted cutting (multi-action). */
125
- private focusBeforeComponentSwitch;
126
- /** Cross-component force-field links from the source component, saved when
127
- * switching away to a target component. Used to recompute the incoming view
128
- * when a checkbox toggle fires while already on the target component. */
129
- private savedSourceComponentLinks;
130
- /** Set by navigateToCutting for cross-component nav: after the switch the
131
- * incoming force field context is established, then onCuttingLabelClick is
132
- * called for this cutting to show its propagated card. */
133
- private _pendingCuttingFocusAfterSwitch;
134
- private _pendingOddHighlightAfterSwitch;
135
- /** Set by SearchPanelSynchronizer.searchNavigateToCutting when a stack-item
136
- * click switches facette while an action is active: prepareForComponentSwitch
137
- * owns pendingComponentSwitchContext for the incoming force field, so this
138
- * navigation is applied separately once the switch completes. */
139
- private _pendingCuttingNavigationAfterSwitch;
140
- /** Menu cœur à déployer à l'arrivée sur la facette (voir searchSetKeyEventMenuOpen). */
141
- private _pendingKeyEventMenuAfterSwitch;
142
23
  private actionStackController;
143
24
  private childActionMenuController;
144
25
  private coreEventMenuController;
145
- private isCoreEventMenuOpen;
146
- /** Id de l'Événement Clé actuellement en aperçu (carte affichée), ou null. */
147
- private activeKeyEventId;
148
26
  private forceFieldDetailsPanel;
149
27
  private forceFieldRenderer;
150
28
  /** Champ d'événement — liens cœur → satellites amplifiés par l'Événement
@@ -162,31 +40,18 @@ export declare class YinYangController implements IYinYangController {
162
40
  private searchPanelSynchronizer;
163
41
  private actionStackManager;
164
42
  private state;
165
- /** Callback to open the search tab and set a query — wired from main.ts. */
166
- private openSearchWithQuery?;
167
- /** Callback: injecte le bloc d'impact d'action directe dans l'onglet Recherche. */
168
- private _onShowDirectActionBlock?;
169
- /** Callback: affiche le bloc d'action directe d'un prérequis dans le panneau B. */
170
- private _onShowDirectActionBlockPanelB?;
171
- /** Quand vrai, le prochain appel à _onShowDirectActionBlock est routé vers le panneau B. */
172
- private _routeNextDirectActionBlockToPanelB;
173
- /** Quand vrai, renderSourceActionDetailsForCurrentSource ne re-rend pas le bloc Panel A.
174
- * Utilisé pendant reactivatePersistentAction pour préserver l'état des <details> ouverts. */
175
- private _suppressDirectActionBlockRender;
176
- /** Callback: efface le bloc d'impact d'action directe de l'onglet Recherche. */
177
- private _onClearDirectActionBlock?;
178
- /** Callback: injecte la carte descriptive d'un Événement Clé dans l'onglet Recherche. */
179
- private _onShowKeyEventBlock?;
180
- /** Callback: efface la carte d'Événement Clé de l'onglet Recherche. */
181
- private _onClearKeyEventBlock?;
182
- /** Notifie la hiérarchie RECHERCHE de l'état du menu radial des Événements
183
- * Clés (diagramme → arbre), pour que le groupe "Événements Clés" reste le
184
- * reflet exact des bulles réellement déployées. */
185
- private _onKeyEventMenuStateChange?;
186
- /** Callback: injecte le bloc d'action propagée dans l'onglet Recherche. */
187
- private _onShowPropagationBlock?;
188
- /** Callback: efface le bloc d'action propagée de l'onglet Recherche. */
189
- private _onClearPropagationBlock?;
43
+ private childrenBuilder;
44
+ private componentSwitch;
45
+ private incomingForceField;
46
+ private detailsPresenter;
47
+ private navigator;
48
+ private keyEvents;
49
+ private stackFocus;
50
+ private titlePresenter;
51
+ private propagationAnimator;
52
+ private debugTools;
53
+ private session;
54
+ private ui;
190
55
  /**
191
56
  * Constructor to initialize the controller with its model, view, and factory.
192
57
  */
@@ -210,39 +75,10 @@ export declare class YinYangController implements IYinYangController {
210
75
  * Generates a unique child key for sub-instances.
211
76
  */
212
77
  generateChildKey(): string;
213
- /**
214
- * Creates child instances of the YinYang pattern using the model's data.
215
- * Each child is generated based on the small circle data.
216
- */
217
78
  createYinYangChildren(): void;
218
- /** Both distance and size are fixed relative to the facette's uniform
219
- * baseline radius, independent of any satellite's own weight-scaled
220
- * radius — mirrors ChildActionMenuController's action cluster geometry. */
221
- private getChildActionClusterReach;
222
- /** Décalage constant appliqué au poids ET à sa moyenne avant de calculer le
223
- * ratio de taille d'un satellite (voir weightToSizeRatio) : resserre la
224
- * fourchette de tailles (poids min moins minuscule, poids max un peu
225
- * moins dominant) sans changer la taille d'un satellite au poids moyen
226
- * exact (ratio toujours 1 dans ce cas), et sans dépendre du poids moyen
227
- * de la fratrie pour l'ampleur du resserrement. */
228
- private static readonly WEIGHT_SIZE_FLOOR_OFFSET;
229
- /** Ratio de taille d'un satellite (rayon relatif à la baseline uniforme de
230
- * sa facette) à partir de son poids et du poids moyen de sa fratrie —
231
- * voir WEIGHT_SIZE_FLOOR_OFFSET pour le resserrement. */
232
- private static weightToSizeRatio;
233
- /** Ratio of a component's heaviest satellite radius to its own uniform
234
- * baseline radius. Mirrors the per-cutting weight-based scaling applied
235
- * in createYinYangChildren(). */
236
- private getMaxWeightRatio;
237
- /** The container-fit shrink ratio only depends on borderOuterRadius/
238
- * smallCircleRadius/distanceFromChild, which are fixed for the whole
239
- * session once this top-level view is first initialized (they don't get
240
- * recomputed on facette switch) — so this is computed once (on the worst
241
- * case weight ratio across every facette) and cached. That's what keeps
242
- * the whole diagram's size from visibly changing every time the user
243
- * switches facette. */
244
- private cachedGlobalFitShrinkRatio?;
245
- private computeGlobalFitShrinkRatio;
79
+ /** Nom de l'objet racine : celui de la Cause montée quand elle en porte un
80
+ * (sphère de contact), sinon la sphère active de la page. */
81
+ private rootName;
246
82
  /** Mode PRÉSENTATION (voir `IViewData.presentation`) : le diagramme se lit,
247
83
  * il ne se manœuvre pas. Lu sur la vue, donc hérité par les satellites —
248
84
  * chacun porte la même `viewData.presentation`. */
@@ -260,13 +96,6 @@ export declare class YinYangController implements IYinYangController {
260
96
  * a plain redraw would not pick the new values up. */
261
97
  rebuildBorderSegments(): void;
262
98
  setChildrenEnabled(isEnabled: boolean): void;
263
- /**
264
- * Dev-only helper: vide la pile d'actions et la remplit avec des actions
265
- * choisies au hasard parmi les enfants visibles, en réutilisant le pipeline
266
- * normal de validation (`validateActionSelection`) afin d'exercer le même
267
- * calcul de projection ghost que dans l'usage réel. Sert à tester
268
- * rapidement l'affichage des yin-yang ghost sans clics manuels répétés.
269
- */
270
99
  debugFillActionStackWithRandomActions(count?: number): void;
271
100
  /**
272
101
  * Immediately starts hiding children animation without waiting.
@@ -286,18 +115,6 @@ export declare class YinYangController implements IYinYangController {
286
115
  refreshGhostVisualState(): void;
287
116
  prepareForComponentSwitch(targetComponentId: string): void;
288
117
  handleComponentSwitchChildren(): void;
289
- private refreshChildrenForComponentSwitch;
290
- private restoreIncomingForceFieldContext;
291
- /**
292
- * Recomputes the incoming force-field view for `currentComponentId` based on
293
- * the subset of source actions provided by `items`, using the source links saved
294
- * when the user originally switched away from the source component.
295
- * Returns true if matching cross-component links were found and the view was
296
- * updated; returns false if no links target the current component (caller should
297
- * fall back to switching to the source component instead).
298
- */
299
- private recomputeIncomingForceFieldForItems;
300
- private reactivatePersistentAction;
301
118
  private setChildrenHiddenState;
302
119
  private attachChildToggleHandler;
303
120
  /**
@@ -351,10 +168,16 @@ export declare class YinYangController implements IYinYangController {
351
168
  cuttingIndex: number;
352
169
  }>): void;
353
170
  startSearchActionDrag(componentIndex: number, oddId: string, cuttingIndex: number, actionId: string, label: string, startEvent: PointerEvent, sourceEl: Element, onDragIntentDetected?: () => void): void;
171
+ /**
172
+ * Glisser d'un libellé d'action (prérequis d'une carte combo, tag de règle)
173
+ * vers la pile. Le libellé ne porte que l'id de l'action : on résout ici
174
+ * son emplacement (ODD/découpage de la composante courante) puis on passe
175
+ * la main à `onDragStart` — le même gestionnaire que le glisser depuis
176
+ * l'arbre RECHERCHE (cf. PanelManager.wireSearchDrag), donc même
177
+ * comportement, bascule automatique vers STACK comprise.
178
+ */
179
+ setOnActionTagDragStart(onDragStart: (componentIndex: number, oddId: string, cuttingIndex: number, actionId: string, label: string, event: PointerEvent, el: Element) => void): void;
354
180
  startSearchKeyEventDrag(componentIndex: number, keyEventId: string, label: string, startEvent: PointerEvent, sourceEl: Element, onDragIntentDetected?: () => void): void;
355
- private navigateToSource;
356
- private navigateToPrereqAction;
357
- private navigateToCutting;
358
181
  private buildProjectionActionsFromStackItems;
359
182
  private buildForceFieldSourceIndicesFromStackItems;
360
183
  private applyProjectedGhostFromStackItems;
@@ -429,15 +252,12 @@ export declare class YinYangController implements IYinYangController {
429
252
  setDisplayEllipsisForShortLabels(enabled: boolean): void;
430
253
  /** Wire from main.ts so rule-tag clicks with absent actions open the search tab. */
431
254
  setOpenSearchWithQuery(cb: (query: string) => void): void;
432
- private _onDiagramActionDragIntentCb?;
433
255
  /** Déclenché une fois, au franchissement du seuil de glisser d'une bulle
434
256
  * d'action satellite (voir la dépendance startActionDrag câblée au
435
257
  * constructeur de ChildActionMenuController) — DiagramPanelBridge s'en
436
258
  * sert pour basculer sur l'onglet STACK, comme pour le glisser RECHERCHE. */
437
259
  setOnDiagramActionDragIntent(cb: () => void): void;
438
- private _onActiveChildChange?;
439
260
  setOnActiveChildChange(cb: () => void): void;
440
- private _onOuterSparkAutoToggle?;
441
261
  /** Notified whenever the Sphère/Facette status auto-toggles the perimeter
442
262
  * spark, so the "Étincelle périmètre" checkbox can mirror it. */
443
263
  setOnOuterSparkAutoToggle(cb: (enabled: boolean) => void): void;
@@ -463,27 +283,7 @@ export declare class YinYangController implements IYinYangController {
463
283
  * currentAnimation slot with its own pseudo-switch, and silently swallow
464
284
  * the real switch's finalization (which is what used to turn the spark off). */
465
285
  cancelOuterSparkForActivation(): void;
466
- /** Dev-only: toggles the perimeter spark sweep from the "Étincelle"
467
- * button — a second click restores whatever it was before the first
468
- * (off, in every normal case, since the spark otherwise never turns on
469
- * by itself). The spark stays purely opt-in — this button and the
470
- * "Étincelle périmètre" checkbox are the only ways to start it. */
471
286
  triggerOuterSparkDev(): void;
472
- /** Dev-only: (re)lance l'étincelle d'équilibre sur la facette active.
473
- * L'orientation passée est celle de la facette, c'est-à-dire son lobe
474
- * dominant (getRadiiForScore le dessine à 0.5 + score/2, donc toujours
475
- * le plus grand des deux) : c'est la seule qui satisfasse le contrat de
476
- * triggerBalanceSpark, qui calibre la croissance de queue et le taux de
477
- * combustion partagé sur l'étincelle primaire. Elle était codée en dur
478
- * sur "yang", ce qui inversait les rôles sur une facette yin-dominante
479
- * — la survivante se faisait alors tuer par la limite de durée de vie à
480
- * l'instant même où sa jumelle s'éteignait, sans pondre un seul têtard.
481
- * Contrairement à l'étincelle du périmètre, c'est une animation
482
- * ponctuelle (elle s'arrête d'elle-même une fois le sous-cercle
483
- * parcouru à moitié) : chaque clic la relance depuis le début plutôt
484
- * que de la toggle. `onComplete`, transmis tel quel à triggerBalanceSpark,
485
- * permet à l'appelant (le bouton dev, une fois basculé en mode actif) de
486
- * la relancer en boucle sans dupliquer sa logique de durée. */
487
287
  triggerBalanceSparkDev(onComplete?: () => void): void;
488
288
  /** Satellite dont le menu d'action est ouvert, sinon (repli) le satellite
489
289
  * "sélectionné en lecture seule" — même surbrillance que la bordure du
@@ -564,6 +364,33 @@ export declare class YinYangController implements IYinYangController {
564
364
  /** Centre automatiquement (scroll animé) le bloc "Effets cumulés" correspondant
565
365
  * à cet item de pile, dès qu'il apparaît dans le panneau — voir
566
366
  * ForceFieldDetailsPanel.requestScrollToStackItemBlock. */
367
+ /**
368
+ * Glisser guidé d'un prérequis depuis RECHERCHE : la bascule vers STACK
369
+ * faite par le glisser (switchToTab direct, sans le clic d'onglet qui
370
+ * appelle syncForceFieldToStackMode) laissait le panneau sur le satellite
371
+ * de l'action glissée — encore absente de la pile, donc sans aucun bloc.
372
+ * On resynchronise les champs de la pile comme un vrai passage en STACK,
373
+ * puis on affiche les blocs du satellite de l'action portant le combo,
374
+ * sans déplacer la sélection du diagramme (le dépôt s'en charge).
375
+ */
376
+ private showStackItemBlocksForDrag;
377
+ /**
378
+ * Sélectionne le satellite porteur d'un item de pile (diagramme + panneau)
379
+ * et centre son bloc — même effet qu'un clic sur le libellé de l'item
380
+ * (voir setOnSelectStackItemSatellite dans DiagramPanelBridge).
381
+ */
382
+ private focusStackItemSatellite;
383
+ /** Item dont les cartes combo sont actuellement en aperçu de dépôt. */
384
+ private _guidedComboPreviewItemId;
385
+ /**
386
+ * Pendant le glisser guidé d'un prérequis, met à jour en direct les cartes
387
+ * combo de l'action qui le requiert, comme si le prérequis était déposé à
388
+ * l'emplacement survolé — le pendant, pour un glisser venu de RECHERCHE, de
389
+ * la projection que fait déjà le glisser d'un item interne à la pile
390
+ * (ActionStackDragHandler.emitDragPreviewChange). Hors zone de dépôt ou
391
+ * glisser terminé : contenu d'origine restauré.
392
+ */
393
+ private refreshGuidedComboPreview;
567
394
  requestScrollToStackItemBlock(stackItemId: string): void;
568
395
  /**
569
396
  * Wire from main.ts — injecte le bloc d'impact d'action directe dans l'onglet Recherche
@@ -576,17 +403,6 @@ export declare class YinYangController implements IYinYangController {
576
403
  setOnKeyEventMenuStateChange(cb: (componentIndex: number, open: boolean) => void): void;
577
404
  /** Wire from main.ts — affiche le bloc d'action directe d'un prérequis dans le panneau B. */
578
405
  setOnDirectActionBlockPanelB(show: (compId: string, oddId: string, cutIdx: number, actionId: string, cardsHtml: string, attachHandlers: (container: HTMLElement) => void) => void): void;
579
- /**
580
- * Construit le bloc d'action directe pour un emplacement connu (compId/oddId/cutIdx/actionId)
581
- * sans naviguer le diagramme, et fire le callback avec (compId, oddId, cutIdx, actionId, html, attachHandlers).
582
- * Utilisé par les panneaux contextuels pour afficher le bloc d'une action cliquée dans leur arbre.
583
- */
584
- /**
585
- * Déclenche l'affichage du bloc de propagation dans un panneau contextuel lorsque
586
- * l'utilisateur clique sur un cutting dans l'arbre de ce panneau.
587
- * Retourne true si le cutting est effectivement impacté par l'action active (bloc affiché),
588
- * false sinon (aucun changement).
589
- */
590
406
  showPropagationForContextCutting(componentId: string, oddId: string, cuttingIndex: number): boolean;
591
407
  buildDirectActionBlockForContext(compId: string, oddId: string, cutIdx: number, actionId: string, onReady: (compId: string, oddId: string, cutIdx: number, actionId: string, html: string, attachHandlers: (container: HTMLElement) => void) => void): void;
592
408
  /**
@@ -604,40 +420,16 @@ export declare class YinYangController implements IYinYangController {
604
420
  label: string;
605
421
  cssClass: string;
606
422
  } | undefined, name: string | undefined) => void): void;
607
- /** Fired unconditionally at the end of onCuttingLabelClick (both the cumulative and
608
- * the normal branch), regardless of which internal path handled the click, so that
609
- * DiagramPanelBridge can keep the STACK hierarchy (chip + history) in sync even when
610
- * the cumulative view intercepts the click before renderForceFieldDetails /
611
- * _onShowPropagationBlock is reached. Signature mirrors setOnPropagationBlock's
612
- * (compId, oddId, cuttingIndex) shape so the same STACK-sync handler can be reused. */
613
- private _onCuttingNavigated?;
614
423
  setOnCuttingNavigated(cb: (compId: string, oddId: string, cuttingIndex: number) => void): void;
615
- private notifyCuttingNavigated;
616
- private onDiagramOddChangeCb?;
617
424
  /** Wire from main.ts to sync the search panel when the user clicks an ODD arc. */
618
425
  setOnDiagramOddChange(cb: (componentIndex: number, oddId: string, mode: "highlight") => void): void;
619
- private onDiagramNavChangeCb?;
620
426
  /** Wire from main.ts to sync the search panel on composante / cutting / action clicks. */
621
427
  setOnDiagramNavChange(cb: (event: DiagramNavEvent) => void): void;
622
- /** Fired when the user re-clicks the active satellite in the diagram (toggle-to-close),
623
- * or when an ODD-level interaction deselects it — componentIndex lets the listener
624
- * restore its detail panel to the facette view rather than clearing it entirely. */
625
- private _onDiagramSatelliteDeselect?;
626
428
  setOnDiagramSatelliteDeselect(cb: (componentIndex: number) => void): void;
627
- /** Fired when the user clicks the current composante's border arc to hide its satellites. */
628
- private _onDiagramComposanteDeselect?;
629
429
  setOnDiagramComposanteDeselect(cb: () => void): void;
630
- /** Callback vers le panneau Recherche quand la souris entre/sort d'un satellite dans le diagramme. */
631
- private _onDiagramChildHoverCb;
632
430
  setOnDiagramChildHover(cb: (componentIndex: number | null, oddId: string | null, cuttingIndex?: number) => void): void;
633
- /** Callback vers le panneau Recherche quand la souris entre/sort d'un arc de bordure (composante). */
634
- private _onDiagramComposanteHoverCb;
635
431
  setOnDiagramComposanteHover(cb: (componentIndex: number | null) => void): void;
636
- /** Callback vers le panneau Recherche quand la souris entre/sort d'un cercle d'action dans le menu radial. */
637
- private _onDiagramActionHoverCb;
638
432
  setOnDiagramActionHover(cb: (componentIndex: number | null, oddId: string | null, cuttingIndex: number | null, actionId: string | null) => void): void;
639
- /** Callback externe (panneau RECHERCHE) quand la souris entre/sort d'un arc ODD dans le diagramme. */
640
- private _onDiagramOddArcHoverCb;
641
433
  setOnDiagramOddArcHover(cb: (oddId: string | null) => void): void;
642
434
  /** Called by BorderDrawer when the user clicks a composante border arc. */
643
435
  onDiagramComposanteClicked(componentIndex: number): void;
@@ -687,312 +479,25 @@ export declare class YinYangController implements IYinYangController {
687
479
  private clearForceFieldVisualState;
688
480
  private clearForceFieldVisualOnly;
689
481
  private renderOppositeChildrenForceField;
690
- private clearGhostDetails;
691
- private renderGhostDetailsForActiveAction;
692
482
  clearForceFieldDetails(): void;
693
- private renderActionPropagationTable;
694
- /**
695
- * Calcule les ComboResult pour une action donnée.
696
- * Priorité : résultats pré-calculés du stack item → évaluation à la volée.
697
- * Utilisé par le panneau principal et tous les panneaux contextuels.
698
- */
699
- private _computeComboResultsForAction;
700
- private renderSourceActionDetailsForCurrentSource;
701
- private _mergeAllComponentLinkDetails;
702
- /**
703
- * For each cross-component inter row in the source's allLinkDetails, compute the
704
- * cascade intra rows that would appear in the target component's ODD.
705
- * These rows live in the target controller's state (only populated after the user
706
- * switches to that component), so we recompute them eagerly here, mirroring the
707
- * logic of restoreIncomingForceFieldContext exactly.
708
- *
709
- * Three sub-cases, matching restoreIncomingForceFieldContext:
710
- * A) intraEdges.length === 0 → distributeToAllChildren (equal split)
711
- * B) targetedCutting undefined → global mode: each flat intra edge gets the full budget
712
- * C) targetedCutting set → targeted DFS with cascading budget from entry node
713
- * C') entry node not found → distributeToAllChildren fallback (non-bridge only)
714
- */
715
- private _computeCrossComponentCascadeRows;
716
- private renderForceFieldDetails;
717
- private flashChildCuttings;
718
- /** Waypoint d'un satellite de la facette courante (par index orbital). Le
719
- * contrôleur peut être passé quand l'appelant l'a déjà sous la main. */
720
- private _resolveOrbitWaypoint;
721
- /** Waypoint sur l'arc de bordure d'une autre facette (cible inter-facettes). */
722
- private _resolveBorderWaypoint;
723
- /** `color` avec l'opacité `alpha` (chaîne CSS). */
724
- private static _withAlpha;
725
- /**
726
- * Couleur de la comète : celle de l'action portant l'emphase (aperçu ??
727
- * focus) quand le réglage le demande et qu'elle est identifiable, sinon la
728
- * couleur fixe du réglage.
729
- */
730
- private _resolvePropagationColor;
731
- /** Anneau doux (couleur de la comète) autour d'un satellite atteint :
732
- * un cercle qui s'élargit en s'éteignant, plus une brève lueur pleine.
733
- * Intensité réglable (ringOpacity, 0 = rien). */
734
- private _drawFlashRings;
735
- /**
736
- * Joue une passe de propagation sur des waypoints déjà résolus : lueur sur
737
- * la source, comète parcourant tout le chemin d'un seul mouvement (en
738
- * pulsant chaque lien de champ de force à son entrée), anneau à chaque
739
- * arrivée. Partagée par le clic sur une ligne du panneau
740
- * (flashChildCuttings) et par la boucle de l'action en focus
741
- * (flashSourcePropagationTree). Retourne la durée totale de la passe en ms
742
- * (comète éteinte et dernier anneau fondu), pour cadencer la boucle.
743
- */
744
- private _animateResolvedPropagation;
745
- /**
746
- * Comète parcourant `waypoints` (polyligne) d'un seul mouvement : vitesse
747
- * de croisière réglable, départ et arrivée adoucis (easeSinInOut sur tout
748
- * le trajet), fondu d'apparition/extinction, halo flouté, et queue fondue
749
- * reconstituée à partir des positions récentes (elle épouse donc les
750
- * virages aux étapes au lieu de se couper à chaque segment). Tout est
751
- * déterministe en fonction du temps écoulé : la queue se calcule sans
752
- * historique, en rééchantillonnant la position à t − Δ.
753
- * `onWaypointArrival(wp)` à chaque étape atteinte (sauf la source),
754
- * `onSegmentStart(i)` à l'entrée dans chaque segment. `isCancelled` lu à
755
- * chaque frame : vrai → la comète disparaît net. Retourne la durée du
756
- * trajet (ms), fondu de sortie non compris.
757
- */
758
- private _animateComet;
759
483
  private getCurrentComponent;
760
484
  private getCurrentComponentOrUndefined;
761
- /** Nom de l'objet racine : celui de la Cause montée quand elle en porte un
762
- * (sphère de contact), sinon la sphère active de la page. */
763
- private rootName;
764
- private getCurrentComponentTitle;
765
- /** Second (et, le cas échéant, troisième) niveau du titre : libellé + couleur
766
- * ODD du satellite actif sous la facette courante (menu ouvert, ou
767
- * sélection en lecture seule — voir getActiveChildMeta), avec le libellé
768
- * de son action active le cas échéant. Un Événement Clé actif (frère du
769
- * Satellite, jamais les deux à la fois côté menu — voir activeKeyEventId)
770
- * prend la priorité et occupe cette même ligne, sans action associée
771
- * (targetedActionIds sont des renvois, pas une Action propre). Null hors
772
- * facette / sans satellite ni Événement Clé actif. */
773
- private getCurrentSatelliteTitle;
774
- /** Troisième niveau du titre : libellé de l'action actuellement active,
775
- * seulement si elle appartient bien au satellite affiché (oddId,
776
- * cuttingIndex) — actionSourceChildKey peut différer du satellite affiché
777
- * quand l'utilisateur navigue vers un autre satellite en lecture seule
778
- * (recherche/STACK) pendant qu'une action reste techniquement active sur
779
- * le précédent (voir le commentaire sur actionSourceChildKey). Sans ce
780
- * contrôle, le titre affichait le libellé de l'ancienne action sous le
781
- * nouveau satellite. */
782
- private getCurrentActionTitle;
783
- /** Refreshes just the top-left title's satellite line against the current
784
- * state — cheap, idempotent DOM diffing — from every code path that can
785
- * change which satellite is active (menu open/close, force-field link
786
- * click, hierarchy/search navigation, cumulative view). */
787
- private refreshComponentTitle;
788
- /** Cross-fades the top-left component-title label to `componentIndex`'s
789
- * name immediately, without waiting for the full updateContextLabels()
790
- * pass (orbit data, legend, etc.) that only runs once the diagram's
791
- * component-switch animation completes. A facette switch always starts
792
- * with no active satellite (createYinYangChildren() resets it), so the
793
- * satellite line is cleared here rather than read from state mid-switch. */
794
- private updateComponentTitleLabelImmediate;
795
- private updateContextLabels;
796
- private renderChildScoresDeltas;
797
- /** Re-syncs the weightDelta ghost/wave/pulse against the current
798
- * ViewInitializer settings (basePulseEnabled, ghostPulseDurationSec,
799
- * pulseMorphRatio) without waiting for the next natural preview change.
800
- * Needed because toggling "Pulsation rayons activée" only calls
801
- * redrawBothGhosts() (VizControlsPanel), which refreshes the facette's own
802
- * score ghost but has no reason to know about the weightDelta preview. */
803
485
  refreshWeightPreviewPulse(): void;
804
- /** Draws the weightDelta ghost + traveling wave for every satellite
805
- * targeted by a currently-previewed action — see
806
- * ActionStackManager.getWeightDeltaByChildKey. The satellite's own circle
807
- * never resizes, same as the facette ghost never resizes the real
808
- * yin-yang circle; WeightPreviewRingRenderer resyncs every child each
809
- * call (no delta = no ghost/wave), same "recompute the full desired
810
- * state" pattern as highlightOddInChildren. */
811
- private applyWeightPreview;
812
486
  private clearChildActionMenu;
813
487
  private clearProjectedActionState;
814
488
  private applyEmptyGhostProjectionState;
815
489
  private updateChildActionMenu;
490
+ /** Clic sur le libellé de l'item en focus dans la pile, rejoué depuis une
491
+ * bulle du diagramme — null hors STACK ou sans focus. */
492
+ private focusedStackItemLabelClick;
816
493
  /** Sélectionne (ouvre) le satellite `childKey` de la facette courante,
817
494
  * comme un clic dessus — sans toggle-close s'il est déjà actif. */
818
495
  private selectSatelliteByKey;
819
- /**
820
- * Appelé par YinYangDrawer quand le petit cercle "œil" du lobe dominant
821
- * (yin ou yang, selon Composante.orientation) est cliqué — jamais l'autre
822
- * lobe, jamais un satellite (garde déjà appliquée côté YinYangDrawer, même
823
- * principe que onDiagramOddArcClicked pour les arcs ODD). Ouvre/ferme le
824
- * menu radial des Événements Clés de la facette active.
825
- */
826
496
  onCoreEventNucleusClicked(): void;
827
- private notifyKeyEventMenuState;
828
- private toggleCoreEventMenu;
829
- /**
830
- * Fermeture du Champ d'événement : l'Événement Clé en aperçu et les bulles
831
- * du menu cœur — chemin unique partagé par la fermeture de facette
832
- * (closeCurrentComposante) et par l'exclusivité action/événement
833
- * (openActionMenuFromChild). No-op si rien n'est ouvert.
834
- *
835
- * hide() d'abord pour la rétraction immédiate du souffle (le geste
836
- * d'ouverture joué à l'envers — cf. prepareForComponentSwitch),
837
- * updateCoreEventMenu() ensuite pour replier les bulles et laisser
838
- * refreshTargets constater qu'il n'y a plus rien à dessiner. La carte du
839
- * panneau RECHERCHE part avec : elle décrit l'Événement Clé qu'on vient de
840
- * retirer du diagramme, et rien ne garantit qu'un autre bloc prenne sa
841
- * place (ouvrir un satellite n'affiche qu'un descriptif, pas un bloc).
842
- */
843
- private closeKeyEventField;
844
- private updateCoreEventMenu;
845
- /**
846
- * Événements Clés qui pilotent le Champ d'événement en ce moment — source
847
- * unique de vérité pour EventFieldLifecycleController (cibles) comme pour
848
- * getEventFieldSource (point d'émission).
849
- *
850
- * Deux régimes, mêmes règles de priorité que le champ de force d'action :
851
- * un APERÇU (clic sur une bulle du menu cœur ou sur l'entrée de l'arbre
852
- * RECHERCHE) prend toujours la main — c'est le geste que l'utilisateur
853
- * vient de faire, quel que soit l'onglet ; sinon, en mode STACK, ce sont
854
- * les Événements Clés COCHÉS de la pile qui décident, exactement comme les
855
- * actions cochées y décident des champs de force. En mode RECHERCHE sans
856
- * aperçu, rien : la pile n'a pas voix au chapitre.
857
- *
858
- * Le renderer n'a qu'une source (le souffle part d'UN point, voir
859
- * EventFieldRenderer), donc on ne renvoie jamais qu'un jeu d'événements
860
- * partageant la même : ceux nés de la facette courante partent tous de son
861
- * cœur et se cumulent ; à défaut, on retombe sur le plus récent des
862
- * événements distants qui atteignent cette facette (mode entrant, source =
863
- * l'arc de sa facette d'origine).
864
- */
865
- private getEventFieldKeyEvents;
866
- /**
867
- * Point d'émission du Champ d'événement : le CŒUR du yin/yang, c'est-à-dire
868
- * le disque central du lobe correspondant à l'orientation de la facette
869
- * courante — le cœur noir du yang sur une facette Yang, le cœur blanc du
870
- * yin sur une facette Yin. Ce n'est PAS le centre géométrique du symbole :
871
- * les deux lobes ont des rayons qui varient avec le score, donc le cœur se
872
- * déplace le long de l'axe vertical au fil de la partie, d'où la
873
- * relecture de la géométrie à chaque frame. Injecté dans
874
- * EventFieldLifecycleController (getEventFieldSource), rappelé à chaque
875
- * frame de son animation.
876
- *
877
- * `geometry.yin/yang.centerY` est la position CANONIQUE (pré-rotation) :
878
- * pendant une rotation Yin/Yang (AnimationsMngr), le cœur visible se
879
- * déplace via un `transform` écrit à même `graphElementGroup` à chaque
880
- * frame, sans jamais toucher `geometry`. On lit donc la position réelle
881
- * via getLiveLobeCoreCenter plutôt que la géométrie statique, pour que les
882
- * anneaux du champ d'événement suivent le cœur qui tourne au lieu de
883
- * naître à une origine figée.
884
- */
885
- private getEventFieldSource;
886
- /**
887
- * Résout un point porté par `lobeGroup` (coordonnées locales, ici le
888
- * centre canonique du cœur) dans le repère de globalGroup — celui où
889
- * EventFieldRenderer dessine (voir EventFieldLifecycleController,
890
- * getGlobalGroupNode). Passe par les CTM SVG plutôt que de reparser
891
- * l'attribut `transform` (comme getChildRenderedCenter le fait pour une
892
- * simple translation) : le transform posé sur graphElementGroup pendant
893
- * une rotation combine rotate ET translate, et cette composition suit
894
- * fidèlement AnimationsMngr sans dépendre de sa formule exacte — un
895
- * changement futur de celle-ci n'a pas besoin d'être répercuté ici.
896
- */
897
- private getLiveLobeCoreCenter;
898
- /**
899
- * Rejoue l'aperçu d'un Événement Clé depuis une navigation Recherche
900
- * (historique précédent/suivant) — pendant minimal de searchNavigateToAction,
901
- * sans mise au point du diagramme (pas de satellite/facette à recentrer,
902
- * l'entrée d'arbre dédiée est hors scope pour l'instant).
903
- */
904
497
  searchNavigateToKeyEvent(keyEventId: string): void;
905
- /**
906
- * Rétablit le Champ d'événement d'un Événement Clé DÉJÀ affiché à droite —
907
- * pendant de restoreActionDiagramState pour les événements, utilisé au
908
- * retour en mode RECHERCHE (voir PanelManager.resyncDiagramToMasterPanel).
909
- *
910
- * Volontairement plus étroit que previewKeyEvent : ni carte redessinée, ni
911
- * notification de navigation (donc pas d'entrée d'historique en double) —
912
- * le panneau montre déjà cet événement, c'est le diagramme qui le rattrape.
913
- * On garde en revanche l'exclusivité action/événement : les deux champs ne
914
- * cohabitent jamais.
915
- *
916
- * Si la facette courante n'est plus celle de l'événement (l'utilisateur a
917
- * navigué ailleurs pendant le mode STACK), on revient d'abord sur sa facette
918
- * d'origine — mêmes gestes que searchSetKeyEventMenuOpen : l'aperçu survit
919
- * au switch (prepareForComponentSwitch le garde vivant, destination =
920
- * origine) et le menu cœur se redéploie à l'arrivée avec sa bulle active.
921
- */
922
498
  restoreKeyEventDiagramState(keyEventId: string): void;
923
- /**
924
- * Dépli/repli du groupe "Événements Clés" depuis la hiérarchie RECHERCHE —
925
- * pendant exact du clic sur le cœur du yin/yang (onCoreEventNucleusClicked),
926
- * pour que l'arbre et le diagramme montrent le même menu déployé : ouvrir le
927
- * groupe déploie les bulles de la facette, le refermer les rétracte (même
928
- * règle que le dépli d'un Satellite, qui déploie ses boutons d'Action).
929
- *
930
- * Le repli passe par closeKeyEventField plutôt que par le toggle : il doit
931
- * aussi emporter l'Événement Clé en aperçu (et sa carte), sinon une bulle
932
- * validée resterait allumée sous un groupe replié.
933
- */
934
499
  searchSetKeyEventMenuOpen(componentIndex: number, open: boolean): void;
935
- /** Ouverture idempotente du menu cœur — no-op s'il est déjà déployé (le
936
- * toggle le refermerait). */
937
- private openCoreEventMenu;
938
- /** Seul point de mutation de activeKeyEventId — resynchronise la ligne
939
- * Événement Clé du titre (voir getCurrentSatelliteTitle) à chaque
940
- * changement, exactement comme setActiveChildKey le fait pour le
941
- * satellite. */
942
- private setActiveKeyEventId;
943
- /** Aperçu — 1er clic sur un Événement Clé : affiche sa carte descriptive
944
- * dans le panneau Recherche, ne joue rien (même principe que
945
- * activateActionFromChild côté satellite). */
946
- private previewKeyEvent;
947
- /** Validation — 2e clic sur l'Événement Clé déjà en aperçu, ou glisser une
948
- * bulle jusqu'à une position précise de la pile (voir startKeyEventDrag,
949
- * même mécanisme que validateActionSelection côté satellite). Sans
950
- * insertAtVisibleIndex, l'item est ajouté au sommet — le menu radial
951
- * reste ouvert dans les deux cas, pour enchaîner d'autres choix. */
952
- private validateKeyEventSelection;
953
500
  private validateActionSelection;
954
- private clientPointToGlobalGroup;
955
- private renderDragGhost;
956
- private removeDragGhost;
957
- private onCuttingLabelClick;
958
- private resolveActionSource;
959
- private getActiveActionMeta;
960
- /**
961
- * Per active stack item sourced from the CURRENT component: its marginal
962
- * contribution (state units, 0..100) to (oddId, cuttingId), and its own
963
- * detailed propagation edges — both produced by the real sequential
964
- * simulation (projectGhostStateForActionSequence), the same one that
965
- * drives the diagram's displayed Δ.
966
- *
967
- * - marginalDeltaAtFocus: summing this across items equals the diagram's Δ
968
- * exactly, by construction (telescoping sum over the fractional
969
- * accumulator). Used as the authoritative block total.
970
- * - detailPool: this item's OWN propagation edges (absorption/gap/cascade),
971
- * from the exact same single-pass computation (computeActionPropagationDetails,
972
- * via onStep) that produced marginalDeltaAtFocus — not a second, separately
973
- * re-run propagation — against the exact rolled-forward state this item
974
- * saw at its point in the stack, not the pristine base state. Used so the
975
- * panel's descriptive breakdown badges match the authoritative total
976
- * instead of an isolated estimate.
977
- *
978
- * Items sourced from a DIFFERENT component are absent from the map: they
979
- * don't participate in this component's rolling simulation (their effect
980
- * is merged separately via the cross-component bridge/incoming-links path).
981
- * Callers must fall back to the isolated per-source estimate for those.
982
- */
983
- private computeSequentialStackContributionsAtFocus;
984
- /**
985
- * Blocs "keyEvent" pour la vue cumulative : un Événement Clé actif (coché
986
- * dans la pile) dont la Facette d'origine (originComposanteId) correspond à
987
- * `component` — indépendamment du satellite précis sélectionné, et même si
988
- * aucune de ses actions ciblées n'est jouée (voir isKeyEventCurrentlyActive
989
- * pour le seul état visuel actif/inactif). Réutilisé par
990
- * renderCumulativeDetailsForCutting (satellite sélectionné) et par les
991
- * appelants de renderComposanteInfo (Facette sélectionnée, aucun satellite).
992
- */
993
- private buildKeyEventBlocksForComponent;
994
- private renderCumulativeDetailsForCutting;
995
- private collectDetailRowsForSourceTarget;
996
501
  private getChildRenderedCenter;
997
502
  private getComponentBorderTargetPoint;
998
503
  private clearForceFieldComputationState;
@@ -1042,139 +547,18 @@ export declare class YinYangController implements IYinYangController {
1042
547
  * que YinYangDrawer applique déjà à l'arc lui-même.
1043
548
  */
1044
549
  previewOddHighlight(oddId: string | null): void;
1045
- /** Focus persistant — null pour l'effacer. */
1046
- private setFocusedStackItem;
1047
- /**
1048
- * Clic sur le libellé d'un item déjà en focus, alors que son bloc est
1049
- * visible dans le panneau (satellite porteur sélectionné) : désactive le
1050
- * focus et retourne true — l'appelant n'a alors ni navigation ni scroll à
1051
- * faire. Si le bloc n'est pas visible (l'utilisateur a navigué ailleurs
1052
- * entre-temps), le clic redevient une sélection normale : false.
1053
- */
1054
550
  toggleStackItemFocusFromStack(stackItemId: string): boolean;
1055
- /** Aperçu par survol — null à la sortie, qui retombe sur le focus. */
1056
- private setStackItemEmphasisPreview;
1057
- /**
1058
- * Point d'accroche unique de la mise en valeur du satellite source de
1059
- * l'action portant l'emphase (aperçu ?? focus). Réutilise pour l'instant
1060
- * le glow de highlightOddByStackItemId (ou le segment de bordure si la
1061
- * source est dans une autre facette) — l'anneau animé viendra ici.
1062
- * `clearIfNone` : sans emphase, efface la mise en valeur (sorties de
1063
- * survol, défocus) ; false pour les simples re-applications (satellites
1064
- * recréés, fin d'un survol de satellite) afin de ne pas écraser d'autres
1065
- * highlights en cours.
1066
- */
1067
- private applyFocusedSourceHighlight;
1068
- /** Memo à une entrée de resolveEmphasisSourceChildIndex (lu chaque frame). */
1069
- private _emphasisSourceMemo;
1070
- /**
1071
- * Index orbital du satellite source de l'action portant l'emphase, ou null
1072
- * si rien ne doit être atténué : hors mode STACK (un aperçu RECHERCHE ne
1073
- * doit pas hériter d'un focus STACK résiduel), item absent, Événement Clé
1074
- * (pas de champ de force), ou source dans une autre facette (tout reste
1075
- * plein, la bordure source est surlignée par highlightOddByStackItemId).
1076
- * Résolution par oddId + cuttingIndex (buildForceFieldSourceIndicesFromStackItems),
1077
- * robuste au rebuild de childOddMap ; la clé du memo suit la convention de
1078
- * ForceFieldLifecycleController._buildPropCacheKey.
1079
- */
1080
- private resolveEmphasisSourceChildIndex;
1081
- /** Identité stable (sourceOriginKey) du satellite source d'un item de la
1082
- * pile — null pour un Événement Clé ou une facette introuvable. */
1083
- private _stackItemSourceOriginKey;
1084
- private _emphasisKeyMemo;
1085
- /** Clé de la source de l'action portant l'emphase (aperçu ?? focus), quelle
1086
- * que soit sa facette ; null hors STACK ou sans emphase. Lue à chaque frame. */
1087
- private resolveEmphasisSourceOriginKey;
1088
- /** Memo à une entrée de resolveFocusedActionSource (lu à chaque update du menu). */
1089
- private _focusSourceMemo;
1090
- /**
1091
- * Action en focus (focus persistant seulement, pas l'aperçu par survol —
1092
- * une bulle qui apparaît/disparaît au survol serait du bruit), résolue en
1093
- * (actionId, clé et index orbital du satellite source) dans la facette
1094
- * courante. null hors mode STACK, sans focus, pour un Événement Clé, ou si
1095
- * la source vit dans une autre facette.
1096
- */
1097
- private resolveFocusedActionSource;
1098
- /**
1099
- * Point de départ « bulle » du champ de force de l'action en focus : la
1100
- * bulle de son action dans le menu radial si le satellite source est celui
1101
- * sélectionné, sinon la bulle détachée posée sur la source. null si
1102
- * aucune bulle n'est visible (le champ démarre alors au satellite).
1103
- */
1104
- private resolveFocusBubbleStub;
1105
- private _focusLoopTimer;
1106
- /** Jeton d'annulation : incrémenté à chaque (re)départ/arrêt, les passes en
1107
- * vol comparent leur jeton à chaque frame et s'effacent si dépassées. */
1108
- private _focusLoopRun;
1109
- /** Pause entre deux passes (propagationCometConfig.loopGapMs, panneau
1110
- * Debug). Un timer en attente est reposé avec la nouvelle valeur pour que
1111
- * le réglage se sente tout de suite. */
1112
551
  setFocusPropagationLoopGapMs(ms: number): void;
1113
- private restartFocusPropagationLoop;
1114
- private stopFocusPropagationLoop;
1115
- private _runFocusPropagationLoopPass;
1116
- /** Liens sortants par index orbital de départ (segments chaînés inclus),
1117
- * restreints à ceux qui mènent quelque part (satellite ou autre facette). */
1118
- private _buildOutgoingLinkMap;
1119
- /** Tous les chemins `prefix` + descente depuis `node` jusqu'aux feuilles
1120
- * (satellite sans lien sortant, ou arc d'une autre facette), sans cycle. */
1121
- private _walkPropagationPaths;
1122
- /** Anime simultanément chaque chemin (waypoints `head` puis la cible de
1123
- * chaque lien) ; retourne la durée de la passe la plus longue. */
1124
- private _animatePropagationPaths;
1125
- /**
1126
- * Joue une passe de propagation sur l'arbre complet des champs de force
1127
- * d'une source de la facette courante : chaque chemin racine → feuille est
1128
- * animé simultanément, comme le clic sur l'en-tête d'un bloc source.
1129
- * L'arbre est lu dans state.forceField.links via le tag sourceChildIndex
1130
- * (segments chaînés inclus : startIndex = cible précédente). La comète part
1131
- * de la bulle d'action quand elle est visible. Retourne la durée de la
1132
- * passe (0 si rien à animer).
1133
- */
1134
- private flashSourcePropagationTree;
1135
- /**
1136
- * Même passe pour une action dont la source vit dans une autre facette :
1137
- * ses liens entrants ici (tagués sourceOriginKey, recopié par
1138
- * restoreIncomingForceFieldContext) partent de l'arc de la facette source ;
1139
- * chaque entrée est prolongée par sa cascade intra-facette. Retourne la
1140
- * durée de la passe (0 si cette action n'a aucun lien entrant ici).
1141
- */
1142
- private flashIncomingPropagationTree;
1143
552
  highlightOddByStackItemId(stackItemId: string | null): void;
553
+ debugInsertAdverseActions(count: number): void;
1144
554
  /**
1145
- * Retourne les actions applicables au cutting associé à `childKey`,
1146
- * en consultant `activeComposantes` via `actionMap` (lookup O(1)).
1147
- *
1148
- * Les actions adverses vivent sous le même satellite (l'invariant "une
1149
- * action vit sous un satellite" tient) mais ne sont jamais proposées au
1150
- * joueur ici : le système se chargera de les placer lui-même dans la
1151
- * pile, pas un clic sur le satellite.
1152
- */
1153
- private getActionsForChild;
1154
- /**
1155
- * Dev-only : le système place lui-même `count` items adverses — actions
1156
- * ET Événements adverses (yasuni_adverse_key_events.ts) — dans la pile
1157
- * active, piochés dans tout le catalogue (toutes les facettes, pas
1158
- * seulement celle affichée à l'écran), aux slots choisis par
1159
- * adverse-action-planner.ts (chaînes de combos complètes, ordre narratif,
1160
- * fenêtres d'effet respectées — un combo d'action adverse peut avoir un
1161
- * Événement adverse pour prérequis). Les adverses déjà présents dans la
1162
- * pile ne sont pas rejoués.
555
+ * Mode adverse (outil de debug, voir adverseMode.ts) : les actions et
556
+ * Événements adverses remplacent les ordinaires sur le diagramme (bulles
557
+ * des satellites, menu cœur) et dans l'arbre RECHERCHE — qui se
558
+ * reconstruit seul à la bascule. La pile n'est jamais filtrée.
1163
559
  *
1164
- * Une action d'une facette non affichée n'a pas de childController vivant
1165
- * (childControllers/childOddMap ne connaissent que la facette courante,
1166
- * voir createYinYangChildren) : l'item de pile est donc construit à la
1167
- * main plutôt que via ActionStackManager.insertActionAtSlot, qui exige un
1168
- * childController réel. sourceChildKey reste au sentinel "" — le reste du
1169
- * code résout toujours l'origine d'un item via sourceComponentId /
1170
- * sourceOddId / sourceCuttingIndex, jamais via sourceChildKey une fois en
1171
- * pile (childOddMap est reconstruit avec de nouvelles clés à chaque
1172
- * changement de facette). Un Événement adverse porte les sentinelles d'un
1173
- * item keyEvent (sourceOddId "" / sourceCuttingIndex −1, voir
1174
- * validateKeyEventSelection) et sa Facette d'origine en sourceComponentId
1175
- * — indispensable au scoping Facette de son bloc dans l'ANALYSE (voir
1176
- * buildKeyEventBlocksForComponent).
560
+ * Hors STACK, l'action ou l'Événement en aperçu de l'autre bord perdrait
561
+ * sa bulle : on le referme plutôt que de laisser un champ sans émetteur.
1177
562
  */
1178
- debugInsertAdverseActions(count: number): void;
563
+ setAdverseMode(isEnabled: boolean): void;
1179
564
  }
1180
- export {};