@micheeeeel/yinyangapp 3.0.1 → 3.1.1

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 (117) hide show
  1. package/dist/bundle.css +1 -0
  2. package/dist/bundle.js +1 -2
  3. package/dist/types/adapters/yasuniCauseAdapter.d.ts +13 -2
  4. package/dist/types/adapters/yinYangAdapter.d.ts +7 -0
  5. package/dist/types/animations/AnimationsMngr.d.ts +69 -15
  6. package/dist/types/animations/FrameScheduler.d.ts +99 -0
  7. package/dist/types/animations/rotationMotion.d.ts +43 -0
  8. package/dist/types/api.d.ts +31 -3
  9. package/dist/types/benchmark/runner.d.ts +20 -0
  10. package/dist/types/benchmark/scenarios.d.ts +55 -6
  11. package/dist/types/components/controller/YinYangController.d.ts +109 -14
  12. package/dist/types/components/controller/action-stack/ActionStackController.d.ts +16 -1
  13. package/dist/types/components/controller/action-stack/ActionStackDragHandler.d.ts +4 -0
  14. package/dist/types/components/controller/action-stack/ActionStackManager.d.ts +13 -2
  15. package/dist/types/components/controller/action-stack/ActionStackState.d.ts +8 -5
  16. package/dist/types/components/controller/action-stack/StackFocusController.d.ts +8 -7
  17. package/dist/types/components/controller/action-stack/stackChromePalette.d.ts +20 -0
  18. package/dist/types/components/controller/actions/ActionProjectionService.d.ts +12 -1
  19. package/dist/types/components/controller/actions/ChildActionMenuController.d.ts +74 -32
  20. package/dist/types/components/controller/actions/KeyEventController.d.ts +78 -70
  21. package/dist/types/components/controller/actions/{CoreEventMenuController.d.ts → KeyEventMenuController.d.ts} +28 -33
  22. package/dist/types/components/controller/actions/radialItemMenu.d.ts +43 -5
  23. package/dist/types/components/controller/children/ChildInteractionController.d.ts +4 -0
  24. package/dist/types/components/controller/children/ChildrenBuilder.d.ts +19 -22
  25. package/dist/types/components/controller/children/ComponentSwitchCoordinator.d.ts +3 -1
  26. package/dist/types/components/controller/children/IdleFacettesController.d.ts +205 -0
  27. package/dist/types/components/controller/children/facetModulation.d.ts +49 -0
  28. package/dist/types/components/controller/children/idleTabLayout.d.ts +95 -0
  29. package/dist/types/components/controller/children/idleTabMorph.d.ts +45 -0
  30. package/dist/types/components/controller/children/signatureLook.d.ts +10 -0
  31. package/dist/types/components/controller/force-field/EventFieldLifecycleController.d.ts +14 -0
  32. package/dist/types/components/controller/force-field/EventFieldRenderer.d.ts +3 -3
  33. package/dist/types/components/controller/force-field/ForceFieldCanvasPainter.d.ts +99 -0
  34. package/dist/types/components/controller/force-field/ForceFieldComputationService.d.ts +9 -0
  35. package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +28 -57
  36. package/dist/types/components/controller/force-field/ForceFieldDetailsPresenter.d.ts +4 -1
  37. package/dist/types/components/controller/force-field/ForceFieldLifecycleController.d.ts +16 -1
  38. package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +10 -18
  39. package/dist/types/components/controller/force-field/IncomingForceFieldService.d.ts +2 -2
  40. package/dist/types/components/controller/force-field/PropagationAnimator.d.ts +2 -0
  41. package/dist/types/components/controller/force-field/keyEventPresentation.d.ts +47 -0
  42. package/dist/types/components/controller/force-field/propagation-viz/PropagationCometPlayer.d.ts +4 -0
  43. package/dist/types/components/controller/force-field/propagation-viz/propagationVizLists.d.ts +4 -2
  44. package/dist/types/components/controller/force-field/propagation-viz/propagationVizModel.d.ts +1 -0
  45. package/dist/types/components/controller/force-field/shieldViewModel.d.ts +6 -2
  46. package/dist/types/components/controller/force-field/types.d.ts +2 -1
  47. package/dist/types/components/controller/labels/ChildScoresDeltaRenderer.d.ts +7 -0
  48. package/dist/types/components/controller/labels/ComponentTitlePresenter.d.ts +13 -0
  49. package/dist/types/components/controller/labels/ContextLabelsRenderer.d.ts +16 -0
  50. package/dist/types/components/controller/labels/WeightPreviewRingRenderer.d.ts +33 -0
  51. package/dist/types/components/controller/odd/ChildrenOrbitManager.d.ts +76 -25
  52. package/dist/types/components/controller/odd/OddHighlightEffects.d.ts +2 -0
  53. package/dist/types/components/controller/odd/OddViewManager.d.ts +7 -3
  54. package/dist/types/components/controller/odd/childHighlightStyles.d.ts +45 -3
  55. package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +8 -5
  56. package/dist/types/components/controller/settings/ControllerSettingsApplier.d.ts +4 -4
  57. package/dist/types/components/controller/state/ControllerSession.d.ts +3 -3
  58. package/dist/types/components/controller/state/ControllerUiCallbacks.d.ts +10 -0
  59. package/dist/types/components/controller/state/YinYangControllerState.d.ts +20 -9
  60. package/dist/types/components/controller/types.d.ts +9 -2
  61. package/dist/types/components/controller/utils/actionCatalog.d.ts +1 -1
  62. package/dist/types/components/controller/utils/eventFieldTargets.d.ts +19 -13
  63. package/dist/types/components/controller/utils/keyEventPropagationContext.d.ts +4 -0
  64. package/dist/types/components/controller/utils/keyEventTargetBreakdowns.d.ts +4 -0
  65. package/dist/types/components/controller/utils/svgTransform.d.ts +16 -0
  66. package/dist/types/components/controls/ObstacleDemoControl.d.ts +3 -0
  67. package/dist/types/components/controls/VizControlsPanel.d.ts +3 -1
  68. package/dist/types/components/panel/PanelManager.d.ts +92 -22
  69. package/dist/types/components/search/GlobalSearchController.d.ts +13 -6
  70. package/dist/types/components/view/BorderDrawer.d.ts +40 -14
  71. package/dist/types/components/view/IdleTabGridDrawer.d.ts +15 -0
  72. package/dist/types/components/view/SpikeDrawer.d.ts +18 -0
  73. package/dist/types/components/view/ViewInitializer.d.ts +45 -7
  74. package/dist/types/components/view/YinYangDrawer.d.ts +132 -30
  75. package/dist/types/components/view/borderColorCycle.d.ts +76 -0
  76. package/dist/types/components/workspace/facetWeightRuleSetting.d.ts +10 -0
  77. package/dist/types/components/workspace/workspaceTemplate.d.ts +1 -1
  78. package/dist/types/config/animationConfig.d.ts +10 -1
  79. package/dist/types/data/activeDiagram.d.ts +6 -2
  80. package/dist/types/data/adverse-action-planner.d.ts +3 -3
  81. package/dist/types/data/amplifier-engine.d.ts +6 -6
  82. package/dist/types/data/contacts/demoObstacle.d.ts +3 -0
  83. package/dist/types/data/contacts/index.d.ts +3 -0
  84. package/dist/types/data/contacts/obstacleSignature.d.ts +56 -0
  85. package/dist/types/data/key-event-effects.d.ts +30 -0
  86. package/dist/types/data/key-event-eligibility.d.ts +24 -0
  87. package/dist/types/data/key-event-propagation.d.ts +13 -0
  88. package/dist/types/data/key-event-types.d.ts +48 -0
  89. package/dist/types/data/key-event-validation.d.ts +11 -0
  90. package/dist/types/data/stability-shield.d.ts +14 -0
  91. package/dist/types/data/yasuni_adverse_key_events.d.ts +1 -1
  92. package/dist/types/data/yasuni_cause.d.ts +7 -0
  93. package/dist/types/data/yasuni_key_events.d.ts +4 -60
  94. package/dist/types/interfaces/ICauseModel.d.ts +16 -1
  95. package/dist/types/interfaces/IGraphicsStrategy.d.ts +9 -2
  96. package/dist/types/interfaces/IPropagationGraph.d.ts +14 -0
  97. package/dist/types/interfaces/IViewData.d.ts +19 -3
  98. package/dist/types/interfaces/IYinYangController.d.ts +35 -7
  99. package/dist/types/interfaces/IYinYangInternalModel.d.ts +7 -0
  100. package/dist/types/main.d.ts +1 -1
  101. package/dist/types/utils/actionIconFit.d.ts +23 -0
  102. package/dist/types/utils/actionPropagation.d.ts +6 -4
  103. package/dist/types/utils/causeMetrics.d.ts +29 -11
  104. package/dist/types/utils/chainCardHeight.d.ts +87 -4
  105. package/dist/types/utils/collapseAnimation.d.ts +39 -0
  106. package/dist/types/utils/d3/D3GraphicsStrategy.d.ts +28 -5
  107. package/dist/types/utils/deltaChips.d.ts +0 -4
  108. package/dist/types/utils/exportControls.d.ts +8 -0
  109. package/dist/types/utils/facetWeightLabel.d.ts +6 -4
  110. package/dist/types/utils/facetteImages.d.ts +6 -0
  111. package/dist/types/utils/glowHalo.d.ts +74 -0
  112. package/dist/types/utils/hierBadge.d.ts +1 -1
  113. package/dist/types/utils/keyEventImages.d.ts +1 -1
  114. package/dist/types/utils/menuIconSize.d.ts +17 -0
  115. package/dist/types/utils/spreadAngles.d.ts +17 -0
  116. package/package.json +4 -1
  117. package/dist/bundle.js.LICENSE.txt +0 -1
@@ -1,9 +1,11 @@
1
+ import type { KeyEventActionEffects } from "../../../data/key-event-effects";
2
+ import { type EventTargetBreakdown } from "./keyEventPresentation";
1
3
  import { type CometPlayFn } from "./propagation-viz/propagationVizLists";
2
4
  import { YinYangComponentNode, YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
3
5
  import { ForceFieldLink, ForceFieldLinkDetail } from "./types";
4
- import type { ComboResult } from "../../../data/combo-engine";
6
+ import { type ComboResult } from "../../../data/combo-engine";
5
7
  import { type AbsorptionBreakdown, type ActiveShield } from "./shieldViewModel";
6
- import type { AmplifierResult, AmplifierTargetBreakdown } from "../../../data/amplifier-engine";
8
+ import type { AmplifierResult } from "../../../data/amplifier-engine";
7
9
  import { type KeyEventDefinition } from "../../../data/yasuni_key_events";
8
10
  import type { Composante, ODD } from "../../../data/yasuni_cause";
9
11
  /** Contexte combo (backward) ou amplificateur (forward) transmis au clic
@@ -45,6 +47,7 @@ type ActionCumulativeBlockViewModel = {
45
47
  detailRows: ForceFieldLinkDetail[];
46
48
  comboResults?: ComboResult[];
47
49
  amplifierResults?: AmplifierResult[];
50
+ eventEffects?: KeyEventActionEffects;
48
51
  stackItemId?: string;
49
52
  color?: string;
50
53
  sequentialDetailPool?: ForceFieldLinkDetail[];
@@ -65,6 +68,10 @@ type ActionCumulativeBlockViewModel = {
65
68
  * contribution négative de ce bloc — direct, propagé, agrégé, absorbé,
66
69
  * appliqué (journal de résolution). */
67
70
  shieldAbsorption?: AbsorptionBreakdown;
71
+ directionalAbsorptions?: Array<{
72
+ active?: ActiveShield;
73
+ breakdown: AbsorptionBreakdown;
74
+ }>;
68
75
  };
69
76
  /** Bloc "keyEvent" : un Événement Clé joué, toujours affiché dès que sa
70
77
  * Facette d'origine correspond à celle affichée (voir YinYangController.
@@ -82,7 +89,7 @@ type KeyEventCumulativeBlockViewModel = {
82
89
  id: string;
83
90
  name: string;
84
91
  }>;
85
- breakdowns?: AmplifierTargetBreakdown[];
92
+ breakdowns?: EventTargetBreakdown[];
86
93
  };
87
94
  type CumulativeBlockViewModel = ActionCumulativeBlockViewModel | KeyEventCumulativeBlockViewModel;
88
95
  export declare class ForceFieldDetailsPanel {
@@ -134,6 +141,10 @@ export declare class ForceFieldDetailsPanel {
134
141
  /** Timer set during a user card interaction — prevents ResizeObserver from
135
142
  * running _applyAutoFitToGrids while a card is animating. */
136
143
  private _userInteractingTimer;
144
+ /** Observers posés sur les conteneurs de rails, et rappel de la montée des
145
+ * badges en cours : coupés par destroy(). */
146
+ private readonly _resizeObservers;
147
+ private _countUpFrameId;
137
148
  /** Set during a live-update _initCardRailState call. _applyAutoFitToGrids skips
138
149
  * this container until the timer fires (covering both the initial DOM-insertion
139
150
  * resize and the gs-block-open animation resize that follows). */
@@ -150,8 +161,6 @@ export declare class ForceFieldDetailsPanel {
150
161
  private _onDiagramElementHover?;
151
162
  /** Called when hovering a cumulative block — notifies the stack to highlight the matching item. */
152
163
  private _onStackItemHighlightCb?;
153
- /** Clic sur l'en-tête d'un bloc → action en focus (YinYangController). */
154
- private _onStackItemFocusCb?;
155
164
  private _onShieldOriginClickCb?;
156
165
  /** Miroir de state.forceField.focusedStackItemId — sert uniquement à
157
166
  * ré-appliquer .ff-block--focused après chaque innerHTML. */
@@ -202,6 +211,9 @@ export declare class ForceFieldDetailsPanel {
202
211
  * l'item de pile porteur, car la même action présente deux fois dans la
203
212
  * pile a deux cartes combo de même contenu mais d'ancres différentes. */
204
213
  private _getHighlightCardKey;
214
+ /** Repère d'une ligne Source : le satellite où l'action est jouée porte
215
+ * la petite icône de l'action (son nom en infobulle). */
216
+ private _actionSourceMarkHtml;
205
217
  /** Titre de carte, gabarit commun à toutes les cartes du rail : étiquette
206
218
  * de type facultative (couleur --card-accent de la carte) puis nom
207
219
  * lisible — l'information principale à lire. */
@@ -258,7 +270,7 @@ export declare class ForceFieldDetailsPanel {
258
270
  /**
259
271
  * Carte descriptive autonome d'un Événement Clé — affichée dans le
260
272
  * panneau Recherche quand l'utilisateur prévisualise l'événement lui-même
261
- * (1er clic sur une bulle du menu radial du cercle central), pas quand il
273
+ * (1er clic sur une bulle du menu radial du satellite-facette), pas quand il
262
274
  * amplifie une action (voir _buildAmplifierSectionHtml pour cette carte-là).
263
275
  * Reprend délibérément le langage visuel de la carte action "source" (voir
264
276
  * _renderChainCardHtml/isSourceCard) — illustration plein cadre — mais SANS
@@ -289,13 +301,12 @@ export declare class ForceFieldDetailsPanel {
289
301
  name: string;
290
302
  }>;
291
303
  /** Répartition par action ciblée (position dans la fenêtre, bonus
292
- * effectif déjà réduit) — absente en aperçu avant validation, où
293
- * l'événement n'a pas encore de slot depuis lequel compter une position.
294
- * Une entrée par targetedActions quand présente (voir
295
- * getAmplifierTargetBreakdown). */
296
- breakdowns?: AmplifierTargetBreakdown[];
297
- /** Id de l'item "keyEvent" actif dans la pile (absent en aperçu avant
298
- * validation) — active le clic "barres de gain par slot" sur la carte
304
+ * effectif déjà réduit) — bloc STACK seulement : absente en aperçu
305
+ * (RECHERCHE), où aucune position n'existe hors de la pile. En STACK,
306
+ * réduite aux actions cochées et amplifiées, comme targetedActions
307
+ * (voir buildKeyEventBlocksForComponent). */
308
+ breakdowns?: EventTargetBreakdown[];
309
+ /** Id de l'item "keyEvent" actif dans la pile (absent en aperçu) — active le clic "barres de gain par slot" sur la carte
299
310
  * et sa section d'actions ciblées (voir _attachComboHighlightHandlers),
300
311
  * même mécanisme que le clic sur une carte combo. */
301
312
  sourceItemId?: string;
@@ -304,49 +315,6 @@ export declare class ForceFieldDetailsPanel {
304
315
  html: string;
305
316
  attachHandlers: (container: HTMLElement) => void;
306
317
  };
307
- /**
308
- * Carte "actions ciblées" d'une source d'effet différé — la liste des
309
- * actions qu'un Événement Clé amplifie ("Actions amplifiées") ou qu'une
310
- * action adverse entrave ("Actions entravées"), avec pour chacune le seul
311
- * delta AJOUTÉ (ou retiré) par l'effet — pas le résultat final combiné au
312
- * delta de base de l'action, qui deviendrait faux dès qu'un combo entre
313
- * en jeu ailleurs sur la même action. Même grammaire que la chip de bonus
314
- * de la carte Événement Clé sœur (buildKeyEventChipsHtml) : rester simple
315
- * et lisible plutôt que reconstituer un calcul complet ici.
316
- *
317
- * Le bonus du catalogue est le PLAFOND — atteint seulement quand l'action
318
- * est jouée au pic de la fenêtre. Une fois la source placée (breakdowns
319
- * disponibles), chaque ligne affiche le bonus EFFECTIF (réduit selon la
320
- * position) plutôt que ce plafond nominal — sinon la chip mentirait sur ce
321
- * que l'action rapporte réellement. Sans breakdowns, le plafond reste la
322
- * meilleure estimation disponible.
323
- *
324
- * Porte le même jeu d'attributs data-keyevent-* que la carte source
325
- * (Événement Clé ou action adverse) pour que _attachComboHighlightHandlers
326
- * et _extractTagComboContext y lisent la fenêtre "en avant" : un clic
327
- * affiche les barres de gain par slot pour toute la fenêtre withinNextN.
328
- *
329
- * Badge et tableau repris à l'identique du gabarit carte combo (voir
330
- * _buildComboSectionHtml/_buildPrereqBreakdownHtml) plutôt qu'un format ad
331
- * hoc : le badge affiche le bonus/malus plafond du catalogue, accompagné
332
- * d'un chip de poids (même paire badge+chip que portait la carte source
333
- * avant que ces deltas n'emménagent ici, voir buildKeyEventCardHtml —
334
- * absent si l'effet ne touche pas le poids), et le tableau réutilise les
335
- * colonnes ff-pt-name/ff-pt-val de
336
- * .ff-combo-prereq-table (les noms passent à la ligne plutôt que d'exiger
337
- * une largeur de carte dérogatoire). Repliable comme n'importe quelle autre
338
- * carte de la famille (le garde-fou qui la forçait dépliée a été retiré de
339
- * _handleCardRailClick/_applyAutoFitToGrids) et précédée d'un séparateur
340
- * .ff-chain-separator — même traitement que la carte source vis-à-vis d'un
341
- * bloc combo/amplificateur, pour que ce bloc-ci ne fasse pas exception.
342
- */
343
- private _buildDelayedTargetsCardHtml;
344
- /** Badge et note de provenance d'un bloc action de la vue cumulative.
345
- * Seule une action propagée porte une note dans l'en-tête (le satellite
346
- * dont elle provient) : pour une action directe — adverse comprise — on
347
- * est déjà sur le satellite porteur, l'information serait redondante.
348
- * L'acteur d'origine d'une action adverse est rendu à part (`origin`),
349
- * dans le corps du bloc, pour ne pas concurrencer le nom. */
350
318
  private _pickActionBlockBadge;
351
319
  /** Ligne « Acteur : … » placée en tête du corps d'un bloc adverse (action
352
320
  * ou Événement) — remplace l'ancienne note d'en-tête. */
@@ -486,6 +454,9 @@ export declare class ForceFieldDetailsPanel {
486
454
  * re-runs the auto-fit measurement whenever the container changes size.
487
455
  */
488
456
  private _ensureResizeObserver;
457
+ /** Fin de vie : observers déconnectés, minuteries et montée des badges
458
+ * coupées. Le DOM du panneau appartient à l'hôte : non touché. */
459
+ destroy(): void;
489
460
  private _initCardRailState;
490
461
  private _handleCardRailClick;
491
462
  private _triggerHighlightFromCard;
@@ -531,7 +502,6 @@ export declare class ForceFieldDetailsPanel {
531
502
  /** Vrai si le panneau affiche actuellement le bloc « Effets cumulés » de cet
532
503
  * item de pile (le satellite/la facette porteuse est sélectionné). */
533
504
  hasBlockForStackItem(stackItemId: string): boolean;
534
- setStackItemFocusCallback(cb: (id: string | null) => void): void;
535
505
  /** Clic sur le nom de l'action d'origine dans une carte Bouclier. */
536
506
  setShieldOriginClickCallback(cb: (stackItemId: string) => void): void;
537
507
  /** Miroir du focus (source de vérité : YinYangController / state). */
@@ -692,6 +662,7 @@ export declare class ForceFieldDetailsPanel {
692
662
  allComponents?: YinYangComponentNode[];
693
663
  comboResults?: ComboResult[];
694
664
  amplifierResults?: AmplifierResult[];
665
+ eventEffects?: KeyEventActionEffects;
695
666
  stackItemId?: string;
696
667
  /** Bouclier de stabilité déjà actif sur le satellite ciblé (posé par
697
668
  * une action antérieure de la pile) — affiché sur la carte bilan et
@@ -20,7 +20,7 @@ export type ForceFieldDetailsPresenterDeps = {
20
20
  actionStackManager: ActionStackManager;
21
21
  applyOddStateForCutting: (oddId: string) => void;
22
22
  buildChildrenOrbitData: () => ChildrenOrbitEntry[];
23
- buildProjectionActionsFromStackItems: (items: ActionStackItem[]) => SequentialActionProjectionInput[];
23
+ buildProjectionActionsFromStackItems: (items: ActionStackItem[], eventContextItems?: ActionStackItem[]) => SequentialActionProjectionInput[];
24
24
  getChildControllers: () => IYinYangController[];
25
25
  childOddMap: Map<string, {
26
26
  oddId: string;
@@ -47,6 +47,9 @@ export type ForceFieldDetailsPresenterDeps = {
47
47
  export declare class ForceFieldDetailsPresenter {
48
48
  private deps;
49
49
  constructor(deps: ForceFieldDetailsPresenterDeps);
50
+ /** Action ciblée par un événement pendant son insertion depuis RECHERCHE.
51
+ * Les positions projetées servent au même moteur d'effets que le dépôt. */
52
+ renderGuidedActionPreview(preview: ActionStackItem, projected: ActionStackItem[] | null): void;
50
53
  /**
51
54
  * Construit le bloc d'action directe pour un emplacement connu (compId/oddId/cutIdx/actionId)
52
55
  * sans naviguer le diagramme, et fire le callback avec (compId, oddId, cutIdx, actionId, html, attachHandlers).
@@ -18,6 +18,12 @@ type ForceFieldLifecycleControllerDeps = {
18
18
  getAllComponents: () => YinYangInternalModel["components"] | undefined;
19
19
  updateChildActionMenu: (orbitData: ChildrenOrbitEntry[]) => void;
20
20
  updateContextLabels: (orbitData: ChildrenOrbitEntry[]) => void;
21
+ /** Frame d'orbite : bulles du menu radial et bulles détachées recalées
22
+ * sur leur satellite, sans data join ni transitions. */
23
+ followOrbitChildActionMenu: (orbitData: ChildrenOrbitEntry[]) => void;
24
+ /** Frame d'orbite : libellés, deltas et anneau de poids recalés, sans
25
+ * réécrire le titre, la légende ni les panneaux. */
26
+ followOrbitContextLabels: (orbitData: ChildrenOrbitEntry[]) => void;
21
27
  clearForceFieldDetails: () => void;
22
28
  renderForceFieldDetails: (linkIndex: number) => void;
23
29
  renderActionPropagationTable: () => void;
@@ -62,7 +68,16 @@ export declare class ForceFieldLifecycleController {
62
68
  invalidatePropagationCache(): void;
63
69
  private _buildPropCacheKey;
64
70
  renderOppositeChildrenForceField(orbitData?: ChildrenOrbitEntry[]): void;
65
- removeOppositeChildrenForceField(): void;
71
+ /**
72
+ * Frame d'orbite en vol (ChildrenOrbitManager) : les satellites viennent
73
+ * de bouger, rien d'autre n'a changé. Seule la géométrie qui dépend de
74
+ * leur position est recalée ; le champ de force est dessiné ici une seule
75
+ * fois, sa propre boucle se contentant alors d'avancer la phase.
76
+ */
77
+ updateOrbitFrame(orbitData: ChildrenOrbitEntry[]): void;
78
+ /** Fin de vie : coupe la boucle du champ de force. */
79
+ destroy(): void;
80
+ removeOppositeChildrenForceField(orbitData?: ChildrenOrbitEntry[]): void;
66
81
  private ensureForceFieldLinks;
67
82
  private updateForceFieldVisual;
68
83
  private startForceFieldAnimation;
@@ -6,13 +6,12 @@ type Point = {
6
6
  y: number;
7
7
  };
8
8
  export declare class ForceFieldRenderer {
9
- private forceFieldGroup;
10
- private forceFieldDefs;
9
+ /** Surface du champ de force ; null = aucun champ affiché. */
10
+ private painter;
11
11
  private forceFieldLayers;
12
- private readonly gradientPrefix;
13
12
  /** setTimeout id du fondu de sortie en cours, ou null — voir hide(). */
14
13
  private _hideTimeoutId;
15
- /** requestAnimationFrame id de la rétraction géométrique en cours — voir retractGeometry(). */
14
+ /** Id frameScheduler de la rétraction géométrique en cours — voir retractGeometry(). */
16
15
  private _retractFrameId;
17
16
  /** Horodatage du dernier updateVisual — updateVisual ne reçoit pas de Δt,
18
17
  * on le dérive ici pour le lissage de l'emphase. */
@@ -53,32 +52,25 @@ export declare class ForceFieldRenderer {
53
52
  getComponentBorderTargetPoint: (componentId: string) => Point | null;
54
53
  }): void;
55
54
  /**
56
- * Fondu de sortie : au lieu de retirer le groupe instantanément (clear()),
57
- * ramène son opacité à 0 sur fieldFadeOutDurationMs puis le retire
55
+ * Fondu de sortie : au lieu de retirer la surface instantanément (clear()),
56
+ * ramène son opacité à 0 sur fieldFadeOutDurationMs puis la retire
58
57
  * réellement — même grammaire de disparition que EventFieldRenderer.hide().
59
58
  * Idempotent : un appel alors qu'un fondu est déjà en cours ne fait rien de
60
59
  * plus (le clear() en attente suffit).
61
60
  */
62
61
  hide(): void;
63
62
  /**
64
- * Rétraction géométrique : anime chaque beam vers son point de départ,
63
+ * Rétraction géométrique : ramène chaque faisceau vers son point de départ,
65
64
  * inverse exact de la croissance animatedEnd de updateVisual (même
66
65
  * fonction d'accélération, lue à l'envers : d3.easeCubicOut(1 - t) au lieu
67
- * de d3.easeCubicOut(t)). Repart de _prevEndpoint — la géométrie du
68
- * dernier frame réellement rendu — donc ne dépend d'aucun state externe :
69
- * elle continue même si les liens qui l'ont produite sont nettoyés entre
66
+ * de d3.easeCubicOut(t)). Repart du dernier faisceau réellement peint, figé
67
+ * (respiration et comètes arrêtées), donc ne dépend d'aucun state externe :
68
+ * elle continue même si les liens qui l'ont produit sont nettoyés entre
70
69
  * temps (cas typique : clic sur l'arc de facette, qui déclenche hide()
71
70
  * puis, dans la foulée, la destruction des satellites source). Se déroule
72
- * en parallèle du fondu d'opacité du groupe (même durée, posé par hide()).
71
+ * en parallèle du fondu d'opacité (même durée, posé par hide()).
73
72
  */
74
73
  private retractGeometry;
75
74
  clear(): void;
76
- /**
77
- * Met à jour les coordonnées d'un gradient et, si stopData est fourni (cache miss),
78
- * les couleurs et opacités des stops.
79
- * Fix 1 : les offsets ne sont jamais réécrits (initialisés une seule fois dans createStops).
80
- * Fix 2 : stopData === null signifie que le cache couleur est valide — on n'écrit pas les stops.
81
- */
82
- private updateGradient;
83
75
  }
84
76
  export {};
@@ -8,10 +8,10 @@ import { ComponentTitlePresenter } from "../labels/ComponentTitlePresenter";
8
8
  import { ControllerSession } from "../state/ControllerSession";
9
9
  import { ForceFieldComputationService } from "./ForceFieldComputationService";
10
10
  export type IncomingForceFieldServiceDeps = {
11
- applyProjectedGhostFromStackItems: (items: ActionStackItem[]) => void;
11
+ applyProjectedGhostFromStackItems: (items: ActionStackItem[], eventContextItems?: ActionStackItem[]) => void;
12
12
  buildChildrenOrbitData: () => ChildrenOrbitEntry[];
13
13
  buildForceFieldSourceIndicesFromStackItems: (items: ActionStackItem[]) => number[];
14
- buildProjectionActionsFromStackItems: (items: ActionStackItem[]) => SequentialActionProjectionInput[];
14
+ buildProjectionActionsFromStackItems: (items: ActionStackItem[], eventContextItems?: ActionStackItem[]) => SequentialActionProjectionInput[];
15
15
  childOddMap: Map<string, {
16
16
  oddId: string;
17
17
  score: number;
@@ -44,6 +44,8 @@ export declare class PropagationAnimator {
44
44
  * le réglage se sente tout de suite. */
45
45
  setFocusPropagationLoopGapMs(ms: number): void;
46
46
  restartFocusPropagationLoop(): void;
47
+ /** Fin de vie : coupe la boucle de l'action en focus et la comète. */
48
+ destroy(): void;
47
49
  private stopFocusPropagationLoop;
48
50
  private _runFocusPropagationLoopPass;
49
51
  /** Joue une passe pour l'item ; retourne sa durée (0 si rien à jouer). */
@@ -0,0 +1,47 @@
1
+ import type { KeyEventDefinition } from "../../../data/key-event-types";
2
+ import type { KeyEventActionEffects } from "../../../data/key-event-effects";
3
+ import type { ForceFieldLinkDetail } from "./types";
4
+ export declare const escapeEventHtml: (text: string) => string;
5
+ export type EventTargetBreakdown = {
6
+ id: string;
7
+ positional: number;
8
+ played: boolean;
9
+ effectText: string;
10
+ slotIndex?: number;
11
+ };
12
+ export declare const eventSignatureName: (event: KeyEventDefinition) => string;
13
+ /** Catalogue potential, or the parameter at the exact shared eligibility strength.
14
+ * These are labelled parameters, never fabricated additive deltas. */
15
+ export declare function eventSignatureDescription(event: KeyEventDefinition, strength?: number): string;
16
+ export declare function eventSignatureChipHtml(event: KeyEventDefinition): string;
17
+ export declare function eventEffectRows(effects: KeyEventActionEffects | undefined): {
18
+ event: KeyEventDefinition;
19
+ text: string;
20
+ strength: number;
21
+ }[];
22
+ export type EventEffectCardContext = {
23
+ baseDelta?: number;
24
+ comboDelta?: number;
25
+ stackItemId?: string;
26
+ detailRows?: ForceFieldLinkDetail[];
27
+ activeShield?: number;
28
+ activeShieldProtectedSign?: 1 | -1;
29
+ };
30
+ /** Cartes de modification dans le rail de l'action : même grammaire que
31
+ * les combos, avec les unités propres à chaque signature. Les badges de
32
+ * propagation/bouclier ne prétendent jamais être des deltas additionnables. */
33
+ export declare function eventEffectsCardsHtml(effects: KeyEventActionEffects | undefined, context?: EventEffectCardContext): string;
34
+ export declare function eventPropagationLabel(row: ForceFieldLinkDetail): string;
35
+ export declare function eventTargetsCardHtml(params: {
36
+ keyEvent: KeyEventDefinition;
37
+ targetedActions: Array<{
38
+ id: string;
39
+ name: string;
40
+ }>;
41
+ breakdowns?: EventTargetBreakdown[];
42
+ requiresAttr: string;
43
+ withinNextNAttr: string;
44
+ nameAttr: string;
45
+ itemIdAttr: string;
46
+ adverse: boolean;
47
+ }): string;
@@ -37,6 +37,10 @@ export type CometPlayOptions = {
37
37
  export declare class PropagationCometPlayer {
38
38
  private deps;
39
39
  private run;
40
+ /** Rappel de frame en attente et couche de la lecture en cours : `stop()`
41
+ * les retire tout de suite au lieu d'attendre la frame suivante. */
42
+ private pendingFrameId;
43
+ private pendingLayer;
40
44
  constructor(deps: PropagationCometPlayerDeps);
41
45
  private get cfg();
42
46
  /** Joue un ou plusieurs arbres (rafale). Retourne la durée de la lecture
@@ -38,8 +38,10 @@ export declare class PropagationVizLists {
38
38
  pool: readonly ForceFieldLinkDetail[];
39
39
  satellite: VizSatellite;
40
40
  blockColor?: string;
41
- /** Libellé d'une provenance (ex. nom de l'action pour son satellite). */
42
- labelOf?: (satellite: VizSatellite) => string | undefined;
41
+ /** Repère HTML ajouté après le nom d'un satellite (ex. icône de l'action
42
+ * sur le satellite où elle est jouée) — le nom, lui, reste celui du
43
+ * satellite : une ligne de liste désigne toujours un satellite. */
44
+ markOf?: (satellite: VizSatellite) => string | undefined;
43
45
  }): {
44
46
  html: string;
45
47
  count: number;
@@ -15,6 +15,7 @@ export type VizListEntry = {
15
15
  delta: number;
16
16
  edgeIds: string[];
17
17
  rationales: string[];
18
+ provenance: string[];
18
19
  };
19
20
  /** Arbre de trajet d'une comète : le satellite de départ, puis chaque
20
21
  * satellite atteint, embranchements compris. */
@@ -5,6 +5,7 @@ export interface ShieldGrant {
5
5
  oddId: string;
6
6
  cuttingIndex: number;
7
7
  shield: number;
8
+ protectedSign?: 1 | -1;
8
9
  /** Nom de l'action qui l'a créé — l'origine affichée au joueur. */
9
10
  label?: string;
10
11
  /** Item de pile qui l'a créé — cible du lien de la carte Bouclier. */
@@ -12,6 +13,7 @@ export interface ShieldGrant {
12
13
  }
13
14
  export interface ActiveShield {
14
15
  value: number;
16
+ protectedSign?: 1 | -1;
15
17
  originLabel?: string;
16
18
  originStackItemId?: string;
17
19
  }
@@ -25,7 +27,7 @@ export interface ShieldTargetRef {
25
27
  * un seul par satellite, le plus fort ; à valeur égale, le premier posé
26
28
  * reste l'origine (un bouclier plus faible ou égal ne remplace jamais).
27
29
  */
28
- export declare function resolveActiveShield(grants: ShieldGrant[], target: ShieldTargetRef): ActiveShield | undefined;
30
+ export declare function resolveActiveShield(grants: ShieldGrant[], target: ShieldTargetRef, protectedSign?: 1 | -1): ActiveShield | undefined;
29
31
  export type ShieldVerdict = "creates" | "replaces" | "ignored" | "unchanged";
30
32
  /**
31
33
  * Ce que ferait un bouclier `created` face au bouclier `active` déjà en
@@ -52,13 +54,14 @@ export interface AbsorptionBreakdown {
52
54
  applied: number;
53
55
  /** true si le bouclier a tout absorbé : le delta appliqué est 0, pas un gain. */
54
56
  boundedToZero: boolean;
57
+ protectedSign?: 1 | -1;
55
58
  }
56
59
  /**
57
60
  * @param absorption réduction rapportée par la projection pour ce satellite
58
61
  * @param directDelta delta effectif de l'action si elle vise ce satellite,
59
62
  * 0 sinon — permet de séparer direct et propagé.
60
63
  */
61
- export declare function buildAbsorptionBreakdown(absorption: Pick<ShieldAbsorption, "shield" | "aggregated" | "applied">, directDelta: number): AbsorptionBreakdown;
64
+ export declare function buildAbsorptionBreakdown(absorption: Pick<ShieldAbsorption, "shield" | "aggregated" | "applied" | "protectedSign">, directDelta: number): AbsorptionBreakdown;
62
65
  /** Lignes courtes du journal de résolution, dans l'ordre du pipeline. */
63
66
  export declare function absorptionSentences(b: AbsorptionBreakdown): string[];
64
67
  /** Carte « Bouclier » d'un bloc de l'ANALYSE : maillon additif entre les
@@ -73,6 +76,7 @@ export interface ShieldCardViewModel {
73
76
  /** Lignes de calcul, dans l'ordre du pipeline. */
74
77
  lines: string[];
75
78
  boundedToZero: boolean;
79
+ protectedSign?: 1 | -1;
76
80
  }
77
81
  /** undefined quand le bouclier n'a rien réduit dans ce bloc (contribution
78
82
  * positive, ou pas de bouclier) : pas de carte, la note du Bilan suffit. */
@@ -1,4 +1,4 @@
1
- import type { PropagationScope } from "../../../interfaces/IPropagationGraph";
1
+ import type { EventPropagationMetadata, PropagationScope } from "../../../interfaces/IPropagationGraph";
2
2
  /**
3
3
  * Une arrivée de propagation prête pour l'affichage : un saut du graphe
4
4
  * unifié, d'un satellite à un autre, issu d'une résolution précise.
@@ -20,6 +20,7 @@ export type ForceFieldLinkDetail = {
20
20
  * désigner une arrivée absente des lignes affichées (sautée dans une autre
21
21
  * facette) : la ligne est alors une racine pour cet affichage. */
22
22
  parentEdgeId?: string;
23
+ eventPropagation?: EventPropagationMetadata;
23
24
  scope: PropagationScope;
24
25
  fromComponentId: string;
25
26
  toComponentId: string;
@@ -3,6 +3,13 @@ import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel"
3
3
  import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
4
4
  import { ProjectedCuttingState } from "../actions/ActionProjectionService";
5
5
  export declare class ChildScoresDeltaRenderer {
6
+ private lastParams;
7
+ /**
8
+ * Frame d'orbite : chaque bloc de deltas déjà rendu glisse vers son
9
+ * nouvel ancrage par un simple `transform` sur son groupe (décalage par
10
+ * rapport à l'ancrage du dernier render), sans recréer textes ni voile.
11
+ */
12
+ followOrbit(): void;
6
13
  render(params: {
7
14
  orbitData: ChildrenOrbitEntry[];
8
15
  globalGroupNode: SVGGElement | null;
@@ -49,6 +49,15 @@ export declare class ComponentTitlePresenter {
49
49
  private deps;
50
50
  constructor(deps: ComponentTitlePresenterDeps);
51
51
  private getCurrentComponentTitle;
52
+ /** L'Événement Clé actif, s'il est issu de `component` — partagé par le
53
+ * titre en Facette et au repos. */
54
+ private getActiveKeyEventOf;
55
+ /** Au repos (Idle « facettes » / « tab ») : la hiérarchie du titre remonte
56
+ * d'un cran — l'objet racine en tête, le satellite-facette sélectionné
57
+ * (celui dont les bulles sont déployées) sur la ligne enfant, son
58
+ * Événement Clé actif au niveau suivant. Même rendu qu'une Facette
59
+ * ouverte (facette › satellite › action). */
60
+ private getIdleFacetteTitle;
52
61
  /** Second (et, le cas échéant, troisième) niveau du titre : libellé + couleur
53
62
  * ODD du satellite actif sous la facette courante (menu ouvert, ou
54
63
  * sélection en lecture seule — voir getActiveChildMeta), avec le libellé
@@ -80,6 +89,10 @@ export declare class ComponentTitlePresenter {
80
89
  * satellite line is cleared here rather than read from state mid-switch. */
81
90
  updateComponentTitleLabelImmediate(componentIndex: number): void;
82
91
  updateContextLabels(orbitData: ChildrenOrbitEntry[]): void;
92
+ /** Frame d'orbite (ForceFieldLifecycleController.updateOrbitFrame) :
93
+ * libellés, deltas et anneau de poids suivent les satellites. Le titre,
94
+ * la légende et les ghosts de bordure ne dépendent pas de l'angle. */
95
+ followOrbit(orbitData: ChildrenOrbitEntry[]): void;
83
96
  renderChildScoresDeltas(orbitData: ChildrenOrbitEntry[]): void;
84
97
  /** Re-syncs the weightDelta ghost/wave/pulse against the current
85
98
  * ViewInitializer settings (basePulseEnabled, ghostPulseDurationSec,
@@ -67,6 +67,12 @@ export declare class ContextLabelsRenderer {
67
67
  private componentLegendGroup;
68
68
  private lastParams;
69
69
  private _childLabelCache;
70
+ /** Rects écran du SVG et du titre pour updateTitleObstruction, relus au
71
+ * plus toutes les OBSTRUCTION_RECTS_TTL_MS pendant l'orbite : les lire à
72
+ * chaque frame, juste après les transforms des satellites, forçait un
73
+ * layout complet. */
74
+ private _obstructionRects;
75
+ private static readonly OBSTRUCTION_RECTS_TTL_MS;
70
76
  /** Crossfades du texte du titre (facette / satellite), indépendants pour
71
77
  * que le changement de l'un ne fasse pas clignoter l'autre. */
72
78
  private _titleCrossfadeTimers;
@@ -92,6 +98,16 @@ export declare class ContextLabelsRenderer {
92
98
  private static readonly SATELLITE_ROW_SPEC;
93
99
  private static readonly ACTION_ROW_SPEC;
94
100
  render(params: RenderContextLabelsParams): void;
101
+ /** Place le libellé court d'un satellite au meilleur endroit autour de
102
+ * son centre ; ne réécrit rien si rien n'a bougé depuis `cache`. */
103
+ private layoutChildLabel;
104
+ /**
105
+ * Frame d'orbite : les satellites ont bougé, rien d'autre. Recale chaque
106
+ * libellé déjà rendu (groupe + position du texte) et l'occultation du
107
+ * titre, sans data join ni réécriture du titre HTML, de la légende ou du
108
+ * contenu des libellés — tout cela ne change que par render().
109
+ */
110
+ followOrbit(orbitData: ChildrenOrbitEntry[]): void;
95
111
  clear(): void;
96
112
  setVisibilityOpacity(opacity: number): void;
97
113
  /**
@@ -18,6 +18,12 @@ export declare class WeightPreviewRingRenderer {
18
18
  private basePulseEnabled;
19
19
  private pulseDurationMs;
20
20
  private pulseMorphRatio;
21
+ /** Fantôme en contour seul (signature, voir renderFixed) plutôt qu'en
22
+ * lavis quand il est plus grand que le satellite. */
23
+ private outlineOnly;
24
+ /** Vague entre le satellite et son fantôme (coupée en mouvement réduit). */
25
+ private wavesEnabled;
26
+ private getChildRenderedCenter;
21
27
  render(params: {
22
28
  orbitData: ChildrenOrbitEntry[];
23
29
  globalGroupNode: SVGGElement | null;
@@ -40,6 +46,31 @@ export declare class WeightPreviewRingRenderer {
40
46
  pulseDurationMs: number;
41
47
  pulseMorphRatio: number;
42
48
  }): void;
49
+ /**
50
+ * Fantôme de SIGNATURE (OBS-UI-01, satellites-facettes d'une signature
51
+ * d'obstacle modulée par un contact) : le même cercle d'or et la même
52
+ * vague que l'aperçu de poids, mais sur des rayons fournis par l'appelant
53
+ * — le satellite a déjà sa taille modulée (`baseRadius`), le fantôme garde
54
+ * celle de la signature (`targetRadius`). Contour seul (une trace de
55
+ * l'exigence, pas un gain), sans pulsation du satellite : sa taille est
56
+ * celle de la modulation, l'animer la rendrait fausse. `waves: false`
57
+ * (mouvement réduit) laisse le fantôme immobile, même information.
58
+ */
59
+ renderFixed(params: {
60
+ groupNode: SVGGElement | null;
61
+ entries: Array<{
62
+ id: string;
63
+ controller: IYinYangController;
64
+ centerX: number;
65
+ centerY: number;
66
+ baseRadius: number;
67
+ targetRadius: number;
68
+ }>;
69
+ waves: boolean;
70
+ }): void;
71
+ /** Frame d'orbite : recentre fantômes et vagues sur leur satellite (les
72
+ * entrées sont les données liées aux cercles), sans data join. */
73
+ followOrbit(): void;
43
74
  /** Starts/stops per-satellite pulse state to match the current entry set
44
75
  * and basePulseEnabled flag, resetting any satellite's own scale back to
45
76
  * identity the moment it stops being targeted or pulsing is turned off —
@@ -49,6 +80,8 @@ export declare class WeightPreviewRingRenderer {
49
80
  private resetEntryTransform;
50
81
  private drawGhostCircles;
51
82
  private ensureLoop;
83
+ /** Fin de vie : coupe la boucle de pulsation. */
84
+ destroy(): void;
52
85
  private stopLoop;
53
86
  /** Breathes each pulsing satellite's own size out to its weightDelta
54
87
  * target and back, on a loop with a pause — same morph/reset/pause cycle