@micheeeeel/yinyangapp 1.0.6 → 2.0.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 (118) hide show
  1. package/README.md +105 -0
  2. package/dist/bundle.js +2 -1
  3. package/dist/bundle.js.LICENSE.txt +1 -0
  4. package/dist/types/adapters/yinYangAdapter.d.ts +10 -0
  5. package/dist/types/animations/AnimationsMngr.d.ts +7 -19
  6. package/dist/types/api-film.d.ts +22 -0
  7. package/dist/types/api.d.ts +48 -0
  8. package/dist/types/benchmark/runner.d.ts +5 -0
  9. package/dist/types/benchmark/scenarios.d.ts +118 -0
  10. package/dist/types/components/action-image/ActionImageModal.d.ts +42 -0
  11. package/dist/types/components/controller/YinYangController.d.ts +946 -18
  12. package/dist/types/components/controller/action-stack/ActionStackController.d.ts +149 -0
  13. package/dist/types/components/controller/action-stack/ActionStackDragHandler.d.ts +111 -0
  14. package/dist/types/components/controller/action-stack/ActionStackManager.d.ts +118 -0
  15. package/dist/types/components/controller/action-stack/ActionStackState.d.ts +169 -0
  16. package/dist/types/components/controller/actions/ActionProjectionService.d.ts +73 -0
  17. package/dist/types/components/controller/actions/ChildActionMenuController.d.ts +83 -0
  18. package/dist/types/components/controller/actions/CoreEventMenuController.d.ts +90 -0
  19. package/dist/types/components/controller/actions/radialItemMenu.d.ts +117 -0
  20. package/dist/types/components/controller/children/ChildInteractionController.d.ts +38 -0
  21. package/dist/types/components/controller/children/ChildrenOrbitService.d.ts +14 -0
  22. package/dist/types/components/controller/force-field/EventFieldLifecycleController.d.ts +104 -0
  23. package/dist/types/components/controller/force-field/EventFieldRenderer.d.ts +86 -0
  24. package/dist/types/components/controller/force-field/ForceFieldComputationService.d.ts +50 -0
  25. package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +639 -0
  26. package/dist/types/components/controller/force-field/ForceFieldLifecycleController.d.ts +53 -0
  27. package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +67 -0
  28. package/dist/types/components/controller/force-field/types.d.ts +42 -0
  29. package/dist/types/components/controller/labels/ChildScoresDeltaRenderer.d.ts +33 -0
  30. package/dist/types/components/controller/labels/ContextLabelsRenderer.d.ts +155 -0
  31. package/dist/types/components/controller/labels/WeightPreviewRingRenderer.d.ts +61 -0
  32. package/dist/types/components/controller/odd/ChildrenOrbitManager.d.ts +25 -0
  33. package/dist/types/components/controller/odd/OddViewManager.d.ts +44 -0
  34. package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +125 -0
  35. package/dist/types/components/controller/settings/ControllerSettingsApplier.d.ts +50 -0
  36. package/dist/types/components/controller/state/BlockingAnimationTracker.d.ts +17 -0
  37. package/dist/types/components/controller/state/YinYangControllerState.d.ts +176 -0
  38. package/dist/types/components/controller/utils/actionStackMath.d.ts +13 -0
  39. package/dist/types/components/controller/utils/actionStackReorder.d.ts +7 -0
  40. package/dist/types/components/controller/utils/childrenOrbit.d.ts +18 -0
  41. package/dist/types/components/controller/utils/cuttingLabels.d.ts +9 -0
  42. package/dist/types/components/controller/utils/eventFieldStyle.d.ts +13 -0
  43. package/dist/types/components/controller/utils/eventFieldTargets.d.ts +47 -0
  44. package/dist/types/components/controller/utils/forceFieldMetadata.d.ts +4 -0
  45. package/dist/types/components/controller/utils/forceFieldPresentation.d.ts +9 -0
  46. package/dist/types/components/controller/utils/forceFieldStyle.d.ts +10 -0
  47. package/dist/types/components/controller/utils/labelGeometry.d.ts +5 -0
  48. package/dist/types/components/controller/utils/oddCutting.d.ts +2 -0
  49. package/dist/types/components/controller/utils/svgCoordinates.d.ts +9 -0
  50. package/dist/types/components/controller/utils/svgTransform.d.ts +5 -0
  51. package/dist/types/components/controller/utils/textLayout.d.ts +2 -0
  52. package/dist/types/components/controls/VizControlsPanel.d.ts +14 -0
  53. package/dist/types/components/factory/YinYangAppFactory.d.ts +4 -6
  54. package/dist/types/components/model/YinYangModel.d.ts +4 -30
  55. package/dist/types/components/panel/DiagramPanelBridge.d.ts +34 -0
  56. package/dist/types/components/panel/PanelManager.d.ts +150 -0
  57. package/dist/types/components/search/GlobalSearchController.d.ts +396 -0
  58. package/dist/types/components/stack-nav/StackNavOverlay.d.ts +82 -0
  59. package/dist/types/components/view/BorderDrawer.d.ts +203 -13
  60. package/dist/types/components/view/SpikeDrawer.d.ts +37 -31
  61. package/dist/types/components/view/ViewInitializer.d.ts +438 -2
  62. package/dist/types/components/view/YinYangDrawer.d.ts +414 -11
  63. package/dist/types/config/animationConfig.d.ts +37 -0
  64. package/dist/types/config/deltaColors.d.ts +64 -0
  65. package/dist/types/config/labelStyleConfig.d.ts +50 -0
  66. package/dist/types/data/OddCategoryColors.d.ts +12 -2
  67. package/dist/types/data/adverse-action-planner.d.ts +51 -0
  68. package/dist/types/data/adverse-action-planner.test.d.ts +1 -0
  69. package/dist/types/data/amplifier-engine.d.ts +107 -0
  70. package/dist/types/data/amplifier-engine.test.d.ts +1 -0
  71. package/dist/types/data/combo-engine.d.ts +94 -0
  72. package/dist/types/data/combo-engine.test.d.ts +1 -0
  73. package/dist/types/data/odd_generic_descriptions.d.ts +4 -0
  74. package/dist/types/data/odd_labels.d.ts +5 -0
  75. package/dist/types/data/yasuni_actions.d.ts +47 -0
  76. package/dist/types/data/yasuni_adverse_actions.d.ts +2 -0
  77. package/dist/types/data/yasuni_adverse_key_events.d.ts +2 -0
  78. package/dist/types/data/yasuni_cause.d.ts +33 -0
  79. package/dist/types/data/yasuni_graph.d.ts +22 -0
  80. package/dist/types/data/yasuni_key_events.d.ts +61 -0
  81. package/dist/types/data/yasuni_propagation_layers.d.ts +3 -0
  82. package/dist/types/interfaces/IActions.d.ts +1 -0
  83. package/dist/types/interfaces/ICauseGraph.d.ts +9 -0
  84. package/dist/types/interfaces/ICauseModel.d.ts +33 -0
  85. package/dist/types/interfaces/IGraphicsStrategy.d.ts +9 -5
  86. package/dist/types/interfaces/IPropagationLayers.d.ts +27 -0
  87. package/dist/types/interfaces/IViewData.d.ts +12 -0
  88. package/dist/types/interfaces/IYinYangAppFactory.d.ts +3 -3
  89. package/dist/types/interfaces/IYinYangController.d.ts +301 -6
  90. package/dist/types/interfaces/IYinYangGeometry.d.ts +43 -0
  91. package/dist/types/interfaces/IYinYangInternalModel.d.ts +34 -0
  92. package/dist/types/interfaces/IYinYangModel.d.ts +3 -11
  93. package/dist/types/main.d.ts +9 -0
  94. package/dist/types/utils/actionImages.d.ts +14 -0
  95. package/dist/types/utils/actionPropagation.d.ts +74 -0
  96. package/dist/types/utils/appMode.d.ts +5 -0
  97. package/dist/types/utils/causeGraph.d.ts +6 -0
  98. package/dist/types/utils/causeMetrics.d.ts +26 -0
  99. package/dist/types/utils/chainCardHeight.d.ts +27 -0
  100. package/dist/types/utils/d3/D3Element.d.ts +2 -2
  101. package/dist/types/utils/d3/D3GraphicsStrategy.d.ts +21 -4
  102. package/dist/types/utils/deltaChips.d.ts +15 -0
  103. package/dist/types/utils/deltaLabels.d.ts +54 -0
  104. package/dist/types/utils/facetteImages.d.ts +1 -0
  105. package/dist/types/utils/geometryUtils.d.ts +0 -1
  106. package/dist/types/utils/hierBadge.d.ts +44 -0
  107. package/dist/types/utils/idleSphereImage.d.ts +8 -0
  108. package/dist/types/utils/keyEventImages.d.ts +41 -0
  109. package/dist/types/utils/oddLegend.d.ts +30 -0
  110. package/dist/types/utils/positionalEfficiency.d.ts +16 -0
  111. package/dist/types/utils/yinYangWatermark.d.ts +29 -0
  112. package/package.json +27 -12
  113. package/dist/index.html +0 -1
  114. package/dist/types/data/coupe_rase_Orangs-outans/data_Kalimantan.d.ts +0 -3
  115. package/dist/types/data/coupe_rase_Orangs-outans/data_PT_Mayawana_Persada.d.ts +0 -3
  116. package/dist/types/data/data_institu_bancaire.d.ts +0 -3
  117. package/dist/types/interfaces/IOddItem.d.ts +0 -6
  118. package/dist/types/script.d.ts +0 -13
@@ -5,6 +5,7 @@ import { ICategory } from "../../interfaces/ICategory";
5
5
  import { IYinYangView } from "../../interfaces/IYinYangView";
6
6
  import { IYinOrYangPattern } from "../../interfaces/IYinOrYangPattern";
7
7
  import { IViewData } from "../../interfaces/IViewData";
8
+ import { IYinYangGeometry, YinYangCategoryArcGeometry, YinYangSpikeGeometry } from "../../interfaces/IYinYangGeometry";
8
9
  export declare class ViewInitializer {
9
10
  graphicContainer: IGraphicElement;
10
11
  graphicStrategy: IGraphicsStrategy;
@@ -13,13 +14,66 @@ export declare class ViewInitializer {
13
14
  yin: IYinOrYangPattern;
14
15
  yang: IYinOrYangPattern;
15
16
  };
17
+ yinOrYangGroupGhost: {
18
+ yin: IYinOrYangPattern;
19
+ yang: IYinOrYangPattern;
20
+ };
16
21
  yinYangGroup: IGraphicElement;
22
+ childrenGroup: IGraphicElement;
23
+ facetteImageBackgroundGroup: IGraphicElement;
24
+ borderArcsGroup: IGraphicElement;
17
25
  smallCircleRadius: number;
18
26
  distanceFromChild: number;
19
27
  controller: IYinYangController;
20
28
  viewData: IViewData;
21
- averageScore: number;
29
+ averageTension: number;
30
+ averageTensionGhost: number;
31
+ /** Somme des deltas de poids projetés sur CETTE facette (0 s'il n'y a
32
+ * aucun aperçu en cours) — le pendant "poids" d'averageTensionGhost, que
33
+ * le badge du ghost affiche à côté du delta de score. Écrit par
34
+ * YinYangController.applyWeightPreview, qui est seul à connaître la pile
35
+ * d'actions ; reste à 0 sur un satellite, dont les deltas sont déjà
36
+ * affichés à côté de lui (ChildScoresDeltaRenderer). */
37
+ weightDeltaGhostTotal: number;
38
+ ghostVisible: boolean;
39
+ yinOpacity: number;
40
+ yangOpacity: number;
41
+ perimeterWaveOpacity: number;
42
+ numberOfWaves: number;
43
+ waveSpacing: number;
44
+ waveStrokeWidth: number;
45
+ ghostPerimeterStrokeWidth: number;
46
+ ghostPerimeterColor: string;
47
+ waveColorIncrease: string;
48
+ waveColorDecrease: string;
49
+ ghostPerimeterSolid: boolean;
50
+ basePulseEnabled: boolean;
51
+ ghostPulseDurationSec: number;
52
+ pulseMorphRatio: number;
53
+ waveTravelDurationSec: number;
54
+ /** Multiplicateur de taille du badge de deltas posé dans le noyau du lobe
55
+ * dominant (score/poids projetés) — voir
56
+ * YinYangDrawer.updateGhostDeltaBadge. Au-delà de 1, le texte déborde
57
+ * volontairement du disque du noyau : il n'y a plus de plaque de fond à
58
+ * respecter depuis que le noyau lui-même en tient lieu. */
59
+ ghostDeltaBadgeSizeBoost: number;
22
60
  categories: ICategory[];
61
+ /** Projection ghost des arcs de bordure (une par facette) — recalculée par
62
+ * updateBorderSegmentGhost à partir des weightDelta actifs sur toute la
63
+ * pile ; null quand aucun weightDelta n'est prévisualisé. */
64
+ borderSegmentsGhost: YinYangCategoryArcGeometry[] | null;
65
+ /** Projection ghost des arcs ODD (categories) de la facette actuellement
66
+ * affichée — recalculée par updateCategoryGhost à partir des weightDelta
67
+ * actifs sur les satellites de cette facette ; null quand aucun n'est
68
+ * prévisualisé. Se recalcule naturellement pour la nouvelle facette après
69
+ * un changement de composante (voir YinYangController.applyWeightPreview). */
70
+ categoriesGhost: ICategory[] | null;
71
+ /** Projection ghost des spikes (satellites de la facette/ODD affichée)
72
+ * ayant un weightDelta actif — recalculée par updateSpikeGhost ; null
73
+ * quand aucun n'est prévisualisé. Contrairement aux arcs, chaque spike
74
+ * est indépendant (pas de renormalisation entre siblings), donc seuls
75
+ * les spikes ciblés par un delta sont présents dans ce tableau. */
76
+ spikesGhost: YinYangSpikeGeometry[] | null;
23
77
  containerId: string;
24
78
  key: string;
25
79
  isChild: boolean;
@@ -29,9 +83,157 @@ export declare class ViewInitializer {
29
83
  borderThickness: number;
30
84
  borderInnerRadius: number;
31
85
  borderOuterRadius: number;
86
+ /** Poids de ce satellite relatif à la moyenne de sa fratrie (1 = moyenne),
87
+ * voir IViewData.weightRatio. */
88
+ weightRatio: number;
89
+ /** Poids brut (échelle absolue), voir IViewData.weight. */
90
+ weight: number;
32
91
  offsetfromBorder: number;
33
- isEnemy: boolean;
92
+ childrenScale: number;
93
+ oddGradientSpread: number;
94
+ oddGradientIntensity: number;
95
+ borderGlowIntensity: number;
96
+ borderSegmentWidthExpansion: number;
97
+ /** Arrondi des extrémités des arcs de bordure, exprimé en fraction de la
98
+ * demi-épaisseur de la couronne : 0 = angles vifs (portion de camembert),
99
+ * 1 = capsule parfaite. Voir BorderDrawer.getSegmentCornerRadius. */
100
+ borderSegmentCornerRadius: number;
101
+ /** Intensité du biseau posé sur chaque arc (ombre au bord interne, crête
102
+ * lumineuse au bord externe) qui remplace le relief que donnaient
103
+ * autrefois les cercles concentriques tracés. 0 = arc plat. */
104
+ borderSegmentBevelIntensity: number;
105
+ /** Amplitude du soulèvement radial d'un arc survolé, en fraction de
106
+ * l'épaisseur totale de la couronne. 0 = pas de soulèvement. */
107
+ borderSegmentHoverLift: number;
108
+ outerSparkIntensity: number;
109
+ outerSparkEnabled: boolean;
110
+ outerSparkLength: number;
111
+ outerSparkStrokeWidth: number;
112
+ outerSparkAngleRad: number;
113
+ outerSparkRotationDurationMs: number;
114
+ outerSparkGlowColor: string;
115
+ balanceSparkIntensity: number;
116
+ /** Tail length reached at the end of the primary spark's own path — it
117
+ * starts at 0.1 and grows linearly with distance traveled (see
118
+ * YinYangDrawer.startBalanceSparkAnimation). */
119
+ balanceSparkMaxLength: number;
120
+ balanceSparkStrokeWidth: number;
121
+ balanceSparkDurationMs: number;
122
+ /** Balance spark colors, keyed by the POLE each spark belongs to, not by
123
+ * its primary/inverse role: the primary spark is always the dominant
124
+ * lobe (see triggerBalanceSpark), so keying by role meant the dominant
125
+ * pole kept the same color whether it was yin or yang. */
126
+ balanceSparkYangColor: string;
127
+ balanceSparkYinColor: string;
128
+ /** How far (px) the ember particles fly from the contact point during
129
+ * the consume phase — see YinYangDrawer's ember shower. */
130
+ balanceSparkEmberDistance: number;
131
+ /** Multiplier applied to the embers' base radius. */
132
+ balanceSparkEmberSize: number;
133
+ /** Duration (ms) of one ember's pop-out-and-fade cycle — smaller is a
134
+ * faster crackle. */
135
+ balanceSparkEmberSpeedMs: number;
136
+ balanceSparkEmberColor: string;
137
+ /** How concentrated the tadpole's swelling is toward the head: the
138
+ * width at a point t (0=tail tip, 1=head) is maxWidth·t^power. Higher
139
+ * = a longer thin tail with the bulk of the width packed near the
140
+ * head; lower (near 1) = a more even, cone-like taper. */
141
+ balanceSparkTaperPower: number;
142
+ /** Fraction of the final max width the spark already has the instant
143
+ * it's born (0 = a true point, growing entirely from nothing). */
144
+ balanceSparkBirthWidthRatio: number;
145
+ /** How many swimming tadpole fragments the lone survivor shatters into
146
+ * — see the fragment block in YinYangDrawer.startBalanceSparkAnimation.
147
+ * Clamped there to the fragment pool size (10). They split the remnant
148
+ * (see balanceSparkDriftRemnantScale) evenly, so raising the count
149
+ * shortens each of them. */
150
+ balanceSparkDriftFragmentCount: number;
151
+ /** Total length the lone survivor sheds when it shatters, as a fraction
152
+ * of the disc radius at a FULL imbalance (score 1) — the actual remnant
153
+ * is this scaled by the current facette's imbalance, then split evenly
154
+ * between the fragments. A perfectly balanced facette sheds nothing. */
155
+ balanceSparkDriftRemnantScale: number;
156
+ /** Outward ("centrifugal") push, in px/ms, blended with the spark's own
157
+ * tangential speed to set the shattered fragments' shared launch
158
+ * direction — see the launch-vector block in
159
+ * YinYangDrawer.startBalanceSparkAnimation. 0 launches them straight
160
+ * along the tangent; higher values bend the launch further outward. */
161
+ balanceSparkDriftCentrifugalForce: number;
162
+ /** Gap (pre-scale px) between the border ring and the facette image ring,
163
+ * and between that ring and the container edge. */
164
+ facetteImageMargin: number;
165
+ /** Percent of the thumbnail radius that stays fully opaque before the
166
+ * vaporous fade to the edge begins. */
167
+ facetteImageFadeStart: number;
168
+ /** Opacity remaining at the very edge of the thumbnail (0 = fully invisible). */
169
+ facetteImageFadeEndOpacity: number;
170
+ /** Fraction (0.1-2) of the max available diameter actually used by the
171
+ * heaviest facette's thumbnail. The thumbnail's inner edge stays fixed at
172
+ * a constant distance from the border arc regardless of this value, so it
173
+ * shrinks/grows toward the container edge only — values above 1
174
+ * deliberately overshoot the reserved gap. */
175
+ facetteImageDiameterScale: number;
176
+ /** Exponent (0-1) applied to each facette's weight ratio (its weight over
177
+ * the heaviest facette's weight) before it scales the thumbnail radius:
178
+ * radius = baseRadius * weightRatio^curve. 1 = linear (proportional to
179
+ * weight, the default, and the strongest shrinkage). Below 1 attenuates
180
+ * the falloff — lighter facettes stay closer to full size — down to 0,
181
+ * where every facette renders at the same full size regardless of weight. */
182
+ facetteImageWeightCurve: number;
183
+ /** Extra pre-scale px added to the thumbnail's distance from the diagram
184
+ * center, on top of the fixed mid-gap position — moves it closer to
185
+ * (negative) or further from (positive) the sphere, independent of margin
186
+ * and diameter. */
187
+ facetteImageOffset: number;
188
+ oddContextLabelsVisible: boolean;
189
+ oddContextLabelsSuppressed: boolean;
190
+ oddLabelsCompact: boolean;
191
+ legendLabelsBgEnabled: boolean;
192
+ labelsFontAutoScale: number;
193
+ labelsFontScale: number;
194
+ componentLabelFontScale: number;
195
+ childStateDeltaFontScale: number;
196
+ oddLabelFontScale: number;
197
+ /** Score/poids de la facette affichés au centre du cercle principal (voir
198
+ * YinYangDrawer.renderFacetteStateLabel/WeightLabel). */
199
+ facetteLabelFontScale: number;
200
+ /** Suffixe "/max" du score et du poids — mutualisé entre le libellé de
201
+ * facette (renderFacetteStateLabel/WeightLabel) et celui de l'ODD
202
+ * sélectionné (buildOddArcLabelLines) : un seul réglage pour les deux,
203
+ * puisqu'ils occupent le même cercle et ne s'affichent jamais ensemble. */
204
+ facetteLabelSuffixVisible: boolean;
205
+ labelsTextShadowEnabled: boolean;
206
+ childLabelMaxLines: number;
207
+ oddLabelMaxLines: number;
208
+ oddLabelShortMaxChars: number;
209
+ geometry: IYinYangGeometry;
210
+ yinOrYangGroupCache?: {
211
+ yin: IYinOrYangPattern;
212
+ yang: IYinOrYangPattern;
213
+ };
34
214
  private areChildren;
215
+ private currentComponentIndex;
216
+ private animationSequence;
217
+ private isAnimationRunning;
218
+ private isDisplayingOddMode;
219
+ /**
220
+ * Returns whether the view is currently in ODD display mode.
221
+ */
222
+ isInOddMode(): boolean;
223
+ private displayingOddId;
224
+ /**
225
+ * Returns the currently displayed ODD id in ODD view mode, or null otherwise.
226
+ */
227
+ getDisplayingOddId(): string | null;
228
+ private animationRadii?;
229
+ private currentAnimation?;
230
+ private lastGhostDisplayKey;
231
+ private lastGhostOrderKey;
232
+ private lastGhostOrderParent;
233
+ private sliderElement;
234
+ private sliderValueElement;
235
+ private categoryFadeOpacities;
236
+ private readonly borderSegmentGapAngle;
35
237
  constructor(graphicStrategy: IGraphicsStrategy);
36
238
  /**
37
239
  * Initializes the graphical elements for the YinYang visualization.
@@ -43,7 +245,208 @@ export declare class ViewInitializer {
43
245
  * @param parent - The parent controller (optional), used to calculate child positions.
44
246
  */
45
247
  initializeGraphicElements(controller: IYinYangController, viewData: IViewData, parent?: IYinYangController): void;
248
+ /** Current absolute scale applied to globalGroup by the last resizeWholePattern()
249
+ * call (e.g. the shrink reserving room for satellites). Lets code positioning
250
+ * elements in the pre-scale coordinate space (like the facette image ring)
251
+ * compute how much of that space maps to the container's actual edge. */
252
+ patternScale: number;
46
253
  resizeWholePattern(shrinkRatio: number): void;
254
+ setChildrenScale(scale: number): void;
255
+ private applyChildrenScale;
256
+ /**
257
+ * Updates the average tension and redraws the visualization.
258
+ *
259
+ * @param newTension - The new tension value (0 to 1).
260
+ */
261
+ updateTension(newTension: number): void;
262
+ /**
263
+ * Updates the ghost tension and redraws the ghost geometry only.
264
+ *
265
+ * @param newTension - The new ghost tension value (0 to 1).
266
+ */
267
+ updateGhostTension(newTension: number): void;
268
+ setGhostVisible(isVisible: boolean): void;
269
+ refreshGhostDisplay(): void;
270
+ /**
271
+ * Single source of truth for whether the ghost yin/yang should be visible:
272
+ * only on the central diagram (never on satellite children), only while the
273
+ * STACK tab is active, only when the user hasn't manually hidden it, and
274
+ * never while a blocking animation (rotation, facette/ODD switch, ...) is
275
+ * running on this controller — see YinYangController.beginBlockingAnimation.
276
+ */
277
+ isGhostDisplayAllowed(): boolean;
278
+ /**
279
+ * Redraws the YinYang geometry based on the current average tension.
280
+ * Keeps yinYangGroup intact while refreshing symbol groups and spikes.
281
+ */
282
+ private redrawYinYangGeometry;
283
+ /**
284
+ * Redraws the ghost Yin/Yang geometry without touching borders or spikes.
285
+ */
286
+ private redrawGhostGeometry;
287
+ /**
288
+ * Redraws the borders with the current relief intensity setting
289
+ */
290
+ redrawBorders(): void;
291
+ /**
292
+ * Refreshes the spikes visualization based on current visibility settings.
293
+ * This includes clearing old spikes and redrawing them.
294
+ */
295
+ refreshSpikes(): void;
296
+ /**
297
+ * Gets the current average tension.
298
+ *
299
+ * @returns The current average tension value.
300
+ */
301
+ getAverageTension(): number;
302
+ getAverageState(): number;
303
+ /** Poids agrégé de la facette courante : somme des poids de tous ses ODD
304
+ * (même formule que getOddWeight, celle qui fixe la taille de chaque
305
+ * arc — le chiffre affiché au centre du cercle explique donc la somme
306
+ * des arcs qui l'entourent). */
307
+ getFacetteWeight(): number;
308
+ /** Plafond du poids agrégé : WEIGHT_MAX par satellite, tous ODD confondus
309
+ * (même règle que le plafond par-ODD affiché sur les arcs, voir
310
+ * buildOddArcLabelLines dans YinYangDrawer). */
311
+ getFacetteWeightMax(): number;
312
+ getCurrentComponentIndex(): number;
313
+ getCurrentComponentName(): string;
314
+ getCurrentComponentOrientation(): "yin" | "yang";
315
+ /**
316
+ * Centre courant (écran, repère de `globalGroup`) du sous-cercle yin ou
317
+ * yang, en tenant compte d'une éventuelle rotation Yin/Yang en cours
318
+ * (AnimationsMngr écrit un `transform` orbite+spin directement sur
319
+ * `yinOrYangGroup[orientation].graphElementGroup` à chaque frame, sans
320
+ * jamais toucher `geometry`). Résolu via le CTM plutôt qu'en rejouant la
321
+ * formule d'orbite d'AnimationsMngr : le point transformé est le centre
322
+ * CANONIQUE du lobe, qui est aussi le pivot de sa rotation locale — une
323
+ * rotation autour de son propre point fixe n'a par construction aucun
324
+ * effet sur lui, donc seule la translation d'orbite se répercute ici,
325
+ * jamais le spin. Même principe que
326
+ * YinYangController.getLiveLobeCoreCenter (dupliqué plutôt que partagé
327
+ * pour ne rien risquer sur ce chemin déjà en prod), utilisé ici pour que
328
+ * l'étincelle d'équilibre trace le bon cercle — orbitant mais non
329
+ * spinnant — pendant la rotation.
330
+ */
331
+ getLiveOrbitCenter(orientation: "yin" | "yang"): {
332
+ x: number;
333
+ y: number;
334
+ };
335
+ private getComponentOrientation;
336
+ private getRadiiForScore;
337
+ categoryBlendOpacity: number;
338
+ getOddColor(oddId: string): string;
339
+ /**
340
+ * Converts a string to a safe identifier for SVG/CSS (removes special characters, replaces with underscores)
341
+ * @param id - The original identifier
342
+ * @returns A sanitized identifier safe for SVG/CSS usage
343
+ */
344
+ getSafeIdPart(id: string): string;
345
+ /**
346
+ * Gets the category blend opacity (transparency level for category layering).
347
+ * During animation, fading-out categories have their blend opacity
348
+ * progressively reduced in sync with the arc's own disappearance.
349
+ * @param category - The category identifier
350
+ * @returns The opacity value (0-1)
351
+ */
352
+ getCategoryBlendOpacity(category: string): number;
353
+ /**
354
+ * Computes per-category blend mask opacities during animation.
355
+ * Categories fading out (present in start but not in target) get
356
+ * their opacity progressively reduced from 1.0 to the configured minimum.
357
+ * Categories fading in (present in target but not in start) get
358
+ * their opacity progressively increased from the configured minimum to 1.0.
359
+ * Categories present in both maintain full opacity.
360
+ *
361
+ * @param startCategories - The categories at animation start.
362
+ * @param targetCategories - The categories at animation end.
363
+ * @param easeProgress - The eased animation progress (0 to 1).
364
+ */
365
+ private updateCategoryFadeOpacities;
366
+ /** Returns true while a "real" (user/search-driven) component-switch
367
+ * animation is in progress. Pseudo-activations (notifyChildren = false,
368
+ * e.g. the perimeter spark sweeping across a border arc) are decorative
369
+ * and must never block a genuine click/search/nav switch from firing. */
370
+ isComponentSwitching(): boolean;
371
+ /**
372
+ * Animates a smooth transition to a different component.
373
+ * Smoothly interpolates the score and animates category/color changes.
374
+ *
375
+ * @param componentIndex - The index of the component to animate to.
376
+ * @param duration - Animation duration in milliseconds (default: 800ms).
377
+ */
378
+ animateToComponent(componentIndex: number, duration?: number, notifyChildren?: boolean): void;
379
+ /**
380
+ * Rend synchroniquement une image de la bascule fromIndex → toIndex au
381
+ * progrès donné (0..1), sans boucle rAF : même interpolation que
382
+ * startComponentAnimationLoop (easing cubique, rayons, catégories, fondu),
383
+ * suivie d'un redraw complet. Sert à la cuisson des "films" (voir api-film.ts).
384
+ * Laisse l'instance dans l'état stable de toIndex quand progress >= 1.
385
+ */
386
+ renderSwitchFrame(fromIndex: number, toIndex: number, progress: number): void;
387
+ animateToComponentView(duration?: number): void;
388
+ animateToOdd(oddId: string, oddScore: number, duration?: number): void;
389
+ /**
390
+ * Converts categories hex colors to RGB for efficient interpolation.
391
+ * This is done once before animation starts, not per frame.
392
+ */
393
+ private convertCategoriesToRGB;
394
+ /**
395
+ * Interpolates between two sets of categories using pre-computed RGB colors.
396
+ * No hex conversion happens during animation - only arithmetic operations.
397
+ *
398
+ * Critical: Angles are RECALCULATED from percentages after interpolation,
399
+ * not interpolated directly. This ensures valid geometry when slice counts differ.
400
+ */
401
+ private interpolateCategoriesRGB;
402
+ private startCategoryAnimation;
403
+ private startComponentAnimationLoop;
404
+ private getAnimationCurrentState;
405
+ private getComponentAnimationState;
406
+ private buildOddCategories;
407
+ private getOddWeight;
408
+ private buildCategoriesFromComponent;
409
+ /**
410
+ * Recomputes the ghost (projected) ODD categories from a per-(oddId,
411
+ * cuttingIndex) weightDelta map, then asks YinYangDrawer to redraw just
412
+ * the ghost overlay — the ODD-arc equivalent of updateBorderSegmentGhost.
413
+ * Scoped to the currently displayed facette only (getCurrentComponent):
414
+ * unlike the border ring, the ODD arcs belong to a single facette, so
415
+ * switching facette naturally makes this recompute against the new one's
416
+ * odds the next time a weightDelta is previewed there.
417
+ */
418
+ updateCategoryGhost(weightDeltaByOddCutting: Map<string, number> | null): void;
419
+ private buildGhostCategories;
420
+ /**
421
+ * Recomputes the ghost (projected) spikes from the same per-(oddId,
422
+ * cuttingIndex) weightDelta map used for the ODD-arc ghost, then asks
423
+ * SpikeDrawer to redraw just the ghost overlay. Unlike arcs/border
424
+ * segments, a spike's length depends only on its own weight (no
425
+ * renormalization against siblings), so only the targeted spikes need a
426
+ * ghost entry — same "only what's targeted" scope as
427
+ * WeightPreviewRingRenderer's satellite ghosts.
428
+ */
429
+ updateSpikeGhost(weightDeltaByOddCutting: Map<string, number> | null): void;
430
+ private buildGhostSpikes;
431
+ private projectSpikeWeight;
432
+ private buildGhostOddSpikes;
433
+ private buildGhostComponentSpikes;
434
+ private areCategoriesEqual;
435
+ private clearGroupChildren;
436
+ /**
437
+ * Converts hex color to RGB object.
438
+ * @param hex Hex color (e.g., "#FF0000")
439
+ * @returns {r, g, b} object or null if invalid
440
+ */
441
+ private hexToRgb;
442
+ /**
443
+ * Converts RGB values to hex color.
444
+ * @param r Red value (0-255)
445
+ * @param g Green value (0-255)
446
+ * @param b Blue value (0-255)
447
+ * @returns Hex color string (e.g., "#FF0000")
448
+ */
449
+ private rgbToHex;
47
450
  /**
48
451
  * Creates the main graphic container where the YinYang visualization will be rendered .
49
452
  *
@@ -59,6 +462,37 @@ export declare class ViewInitializer {
59
462
  * @returns Object containing the Yin and Yang group elements and properties.
60
463
  */
61
464
  private createYinOrYangGroups;
465
+ private updateYinOrYangGroup;
466
+ private applyGhostOverlapRules;
467
+ private buildGeometry;
468
+ private buildSpikes;
469
+ /**
470
+ * Builds spikes for the ODD view (single ODD displayed).
471
+ * Each spike represents one oddCutting, distributed evenly across 360°.
472
+ */
473
+ private buildOddSpikes;
474
+ private buildComponentSpikes;
475
+ private buildSpike;
476
+ private calculateAverageTension;
477
+ private getCurrentComponent;
478
+ handleSparkAngleUpdate(currentAngle: number, previousAngle: number | null): void;
479
+ private normalizeAngle;
480
+ private hasCrossedAngle;
481
+ private getTotalBorderColors;
482
+ private getCategoryColor;
483
+ private getComponentColor;
484
+ private buildBorderSegments;
485
+ /**
486
+ * Recomputes the ghost (projected) border segments from a per-facette
487
+ * weightDelta map, then asks BorderDrawer to redraw just the ghost overlay
488
+ * — the border-ring equivalent of updateGhostTension. Segment angles are
489
+ * normalized against the projected total weight of every facette (see
490
+ * buildBorderSegments), so a single facette's weightDelta shifts every
491
+ * segment's boundary, not just its own — the full ring is recomputed.
492
+ */
493
+ updateBorderSegmentGhost(weightDeltaByComponentOddCutting: Map<string, number> | null): void;
494
+ private buildGhostBorderSegments;
495
+ private setupCategories;
62
496
  /**
63
497
  * Determines the position of the pattern.
64
498
  * If the view is a child, its position is calculated relative to the parent;
@@ -79,6 +513,8 @@ export declare class ViewInitializer {
79
513
  positionX: number;
80
514
  positionY: number;
81
515
  };
516
+ private getParentChildCount;
517
+ private getChildCount;
82
518
  /**
83
519
  * Centers the current motif in the graphic container.
84
520
  *