@micheeeeel/yinyangapp 3.0.1 → 3.1.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 (110) hide show
  1. package/dist/bundle.css +1 -0
  2. package/dist/bundle.js +1 -2
  3. package/dist/types/adapters/yasuniCauseAdapter.d.ts +1 -1
  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 +17 -2
  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 +104 -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 +3 -1
  25. package/dist/types/components/controller/children/ComponentSwitchCoordinator.d.ts +3 -1
  26. package/dist/types/components/controller/children/IdleFacettesController.d.ts +151 -0
  27. package/dist/types/components/controller/children/idleTabLayout.d.ts +95 -0
  28. package/dist/types/components/controller/children/idleTabMorph.d.ts +45 -0
  29. package/dist/types/components/controller/force-field/EventFieldLifecycleController.d.ts +14 -0
  30. package/dist/types/components/controller/force-field/EventFieldRenderer.d.ts +3 -3
  31. package/dist/types/components/controller/force-field/ForceFieldCanvasPainter.d.ts +99 -0
  32. package/dist/types/components/controller/force-field/ForceFieldComputationService.d.ts +9 -0
  33. package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +28 -57
  34. package/dist/types/components/controller/force-field/ForceFieldDetailsPresenter.d.ts +4 -1
  35. package/dist/types/components/controller/force-field/ForceFieldLifecycleController.d.ts +16 -1
  36. package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +10 -18
  37. package/dist/types/components/controller/force-field/IncomingForceFieldService.d.ts +2 -2
  38. package/dist/types/components/controller/force-field/PropagationAnimator.d.ts +2 -0
  39. package/dist/types/components/controller/force-field/keyEventPresentation.d.ts +47 -0
  40. package/dist/types/components/controller/force-field/propagation-viz/PropagationCometPlayer.d.ts +4 -0
  41. package/dist/types/components/controller/force-field/propagation-viz/propagationVizLists.d.ts +4 -2
  42. package/dist/types/components/controller/force-field/propagation-viz/propagationVizModel.d.ts +1 -0
  43. package/dist/types/components/controller/force-field/shieldViewModel.d.ts +6 -2
  44. package/dist/types/components/controller/force-field/types.d.ts +2 -1
  45. package/dist/types/components/controller/labels/ChildScoresDeltaRenderer.d.ts +7 -0
  46. package/dist/types/components/controller/labels/ComponentTitlePresenter.d.ts +13 -0
  47. package/dist/types/components/controller/labels/ContextLabelsRenderer.d.ts +16 -0
  48. package/dist/types/components/controller/labels/WeightPreviewRingRenderer.d.ts +6 -0
  49. package/dist/types/components/controller/odd/ChildrenOrbitManager.d.ts +76 -25
  50. package/dist/types/components/controller/odd/OddHighlightEffects.d.ts +2 -0
  51. package/dist/types/components/controller/odd/OddViewManager.d.ts +7 -3
  52. package/dist/types/components/controller/odd/childHighlightStyles.d.ts +45 -3
  53. package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +8 -5
  54. package/dist/types/components/controller/settings/ControllerSettingsApplier.d.ts +4 -4
  55. package/dist/types/components/controller/state/ControllerSession.d.ts +3 -3
  56. package/dist/types/components/controller/state/ControllerUiCallbacks.d.ts +10 -0
  57. package/dist/types/components/controller/state/YinYangControllerState.d.ts +20 -9
  58. package/dist/types/components/controller/types.d.ts +9 -2
  59. package/dist/types/components/controller/utils/actionCatalog.d.ts +1 -1
  60. package/dist/types/components/controller/utils/eventFieldTargets.d.ts +19 -13
  61. package/dist/types/components/controller/utils/keyEventPropagationContext.d.ts +4 -0
  62. package/dist/types/components/controller/utils/keyEventTargetBreakdowns.d.ts +4 -0
  63. package/dist/types/components/controller/utils/svgTransform.d.ts +16 -0
  64. package/dist/types/components/controls/VizControlsPanel.d.ts +3 -1
  65. package/dist/types/components/panel/PanelManager.d.ts +92 -22
  66. package/dist/types/components/search/GlobalSearchController.d.ts +13 -6
  67. package/dist/types/components/view/BorderDrawer.d.ts +40 -14
  68. package/dist/types/components/view/IdleTabGridDrawer.d.ts +15 -0
  69. package/dist/types/components/view/SpikeDrawer.d.ts +18 -0
  70. package/dist/types/components/view/ViewInitializer.d.ts +45 -7
  71. package/dist/types/components/view/YinYangDrawer.d.ts +132 -30
  72. package/dist/types/components/view/borderColorCycle.d.ts +76 -0
  73. package/dist/types/components/workspace/facetWeightRuleSetting.d.ts +10 -0
  74. package/dist/types/components/workspace/workspaceTemplate.d.ts +1 -1
  75. package/dist/types/config/animationConfig.d.ts +10 -1
  76. package/dist/types/data/adverse-action-planner.d.ts +3 -3
  77. package/dist/types/data/amplifier-engine.d.ts +6 -6
  78. package/dist/types/data/key-event-effects.d.ts +30 -0
  79. package/dist/types/data/key-event-eligibility.d.ts +24 -0
  80. package/dist/types/data/key-event-propagation.d.ts +13 -0
  81. package/dist/types/data/key-event-types.d.ts +48 -0
  82. package/dist/types/data/key-event-validation.d.ts +11 -0
  83. package/dist/types/data/stability-shield.d.ts +14 -0
  84. package/dist/types/data/yasuni_adverse_key_events.d.ts +1 -1
  85. package/dist/types/data/yasuni_cause.d.ts +7 -0
  86. package/dist/types/data/yasuni_key_events.d.ts +4 -60
  87. package/dist/types/interfaces/ICauseModel.d.ts +10 -1
  88. package/dist/types/interfaces/IGraphicsStrategy.d.ts +9 -2
  89. package/dist/types/interfaces/IPropagationGraph.d.ts +14 -0
  90. package/dist/types/interfaces/IViewData.d.ts +10 -0
  91. package/dist/types/interfaces/IYinYangController.d.ts +25 -7
  92. package/dist/types/interfaces/IYinYangInternalModel.d.ts +5 -0
  93. package/dist/types/main.d.ts +0 -1
  94. package/dist/types/utils/actionIconFit.d.ts +23 -0
  95. package/dist/types/utils/actionPropagation.d.ts +6 -4
  96. package/dist/types/utils/causeMetrics.d.ts +29 -11
  97. package/dist/types/utils/chainCardHeight.d.ts +87 -4
  98. package/dist/types/utils/collapseAnimation.d.ts +39 -0
  99. package/dist/types/utils/d3/D3GraphicsStrategy.d.ts +28 -5
  100. package/dist/types/utils/deltaChips.d.ts +0 -4
  101. package/dist/types/utils/exportControls.d.ts +8 -0
  102. package/dist/types/utils/facetWeightLabel.d.ts +6 -4
  103. package/dist/types/utils/facetteImages.d.ts +6 -0
  104. package/dist/types/utils/glowHalo.d.ts +74 -0
  105. package/dist/types/utils/hierBadge.d.ts +1 -1
  106. package/dist/types/utils/keyEventImages.d.ts +1 -1
  107. package/dist/types/utils/menuIconSize.d.ts +17 -0
  108. package/dist/types/utils/spreadAngles.d.ts +8 -0
  109. package/package.json +4 -1
  110. package/dist/bundle.js.LICENSE.txt +0 -1
@@ -7,7 +7,7 @@ import { type ContactProfileData } from "../data/contacts";
7
7
  * Les scores initiaux sont neutres (0.5 = 50 % de tension), les poids valent 1
8
8
  * par satellite tant qu'aucune valeur n'est renseignée dans les données.
9
9
  * Poids d'une facette (taille de son arc) : C_f, moyenne des poids de TOUS
10
- * ses satellites, catégories confondues, zéros inclus (`meanWeight`) — même
10
+ * ses satellites, catégories confondues, zéros inclus (`facetWeight`) — même
11
11
  * règle pour une cause et pour un contact (POC-05A4).
12
12
  */
13
13
  export declare function composantesToCause(composantes: Composante[], id?: string, name?: string): Cause;
@@ -1,6 +1,13 @@
1
1
  import { YinYangComponentNode, YinYangInternalModel, YinYangOddNode } from "../interfaces/IYinYangInternalModel";
2
2
  import { Cause } from "../interfaces/ICauseModel";
3
3
  export declare function mapCauseToInternalModel(cause: Cause): YinYangInternalModel;
4
+ /**
5
+ * Builds the internal model of a facette satellite (Idle « facettes »
6
+ * sub-state): the whole facette — every ODD and cutting — as the single
7
+ * component of its own model. The satellite thus derives its yin/yang from
8
+ * facetTensionFromOdds exactly as the main circle does for that facette.
9
+ */
10
+ export declare function buildChildFacetteInternalModel(component: YinYangComponentNode): YinYangInternalModel;
4
11
  /**
5
12
  * Builds a single-component, single-odd, single-cutting internal model for a
6
13
  * satellite child, preserving the parent odd's orientation/labels so the
@@ -1,8 +1,22 @@
1
1
  import { IYinYangController } from "../interfaces/IYinYangController";
2
+ /**
3
+ * Rotation Yin/Yang du composant central et de ses satellites, composée par
4
+ * le navigateur : chaque mouvement (rampe, croisière, freinage) est décrit
5
+ * analytiquement (rotationMotion.ts) et joué par des Web Animations sur
6
+ * `transform`. Le contenu des lobes (arcs masqués, dégradés, images) n'est
7
+ * alors plus redessiné à chaque image : seule leur position change, sur le
8
+ * GPU, et le thread principal n'a plus rien à faire à chaque image. Les
9
+ * animations ne sont refaites que sur signal (ViewInitializer.
10
+ * onRotationTargetsChanged : géométrie des lobes, libellés redessinés), et
11
+ * la fin d'un freinage est programmée par une minuterie.
12
+ */
2
13
  export declare class AnimationsMngr {
3
14
  private subscriberMap;
4
15
  subscribe(component: IYinYangController, clockWise?: boolean, time?: number): void;
5
16
  startAll(): void;
17
+ /** Change la durée d'un tour. Une rotation en cours (hors freinage) y
18
+ * converge au rythme de sa rampe — progressivement plutôt que d'un coup
19
+ * si `rampMs > 0`. */
6
20
  setRotationDuration(durationMs: number): void;
7
21
  revertRotation(component: IYinYangController): void;
8
22
  /**
@@ -15,13 +29,13 @@ export declare class AnimationsMngr {
15
29
  */
16
30
  stopRotation(component: IYinYangController, rampMs?: number): void;
17
31
  /**
18
- * Désabonne un composant en fin de vie : coupe sa boucle rAF et libère son
19
- * verrou d'animation, SANS toucher au DOM. À utiliser (et non stopRotation)
20
- * quand les éléments vont être détruits : finalizeStop remettrait les
21
- * transforms des lobes yin/yang à la position de base (resetRotationFrame)
22
- * or ces groupes vivent dans globalGroup, pas dans le yinYangGroup que
23
- * clearChildren retire — le reset ressusciterait donc à l'écran des
24
- * satellites pourtant retirés.
32
+ * Désabonne un composant en fin de vie : annule ses animations et libère
33
+ * son verrou d'animation, SANS écrire dans le DOM. À utiliser (et non
34
+ * stopRotation) quand les éléments vont être détruits : finalizeStop
35
+ * remettrait les transforms des lobes yin/yang à la position de base
36
+ * (resetRotationFrame) or ces groupes vivent dans globalGroup, pas dans le
37
+ * yinYangGroup que clearChildren retire — le reset ressusciterait donc à
38
+ * l'écran des satellites pourtant retirés.
25
39
  */
26
40
  unsubscribe(component: IYinYangController): void;
27
41
  /**
@@ -54,18 +68,58 @@ export declare class AnimationsMngr {
54
68
  * choisie par l'utilisateur — voir `computeFastStopProfile`.
55
69
  */
56
70
  private beginFastHomingStop;
71
+ private beginBrake;
57
72
  private finalizeStop;
73
+ /** Fin de rotation sans toucher au DOM : animations annulées, veilles
74
+ * débranchées, verrou d'animation rendu. */
75
+ private release;
58
76
  private resetRotationFrame;
59
77
  /**
60
78
  * Démarre (ou modifie en vol) la rotation. Avec `rampMs > 0`, la vitesse
61
- * angulaire part de sa valeur courante (0 si à l'arrêt) et chasse
62
- * progressivement la vitesse cible déduite de `time`/`clockWise` — un appel
63
- * pendant qu'un arrêt progressif est en cours ré-accélère en douceur depuis
64
- * la vitesse déjà atteinte, sans à-coup. `rampMs` omis (0) → vitesse cible
65
- * appliquée instantanément, comportement historique.
79
+ * angulaire part de sa valeur courante (0 si à l'arrêt) et rejoint la
80
+ * vitesse cible déduite de `time`/`clockWise` à accélération constante — un
81
+ * appel pendant qu'un arrêt progressif est en cours ré-accélère en douceur
82
+ * depuis la vitesse déjà atteinte, sans à-coup. `rampMs` omis (0) → vitesse
83
+ * cible appliquée instantanément, comportement historique.
66
84
  */
67
85
  animate(component: IYinYangController, clockWise: boolean, time?: number, rampMs?: number): void;
68
- private startRotationLoop;
69
- private applyRotationFrame;
70
- private applyRotationToYinYangGroup;
86
+ /** Mouvement vers la vitesse cible depuis l'état courant (angle et
87
+ * vitesse à cet instant, qu'il y ait rotation, freinage ou arrêt). */
88
+ private startMotion;
89
+ private play;
90
+ /** Géométrie des lobes changée, ghost rempli ou libellés redessinés
91
+ * pendant la rotation : seules les pistes concernées sont refaites. */
92
+ private resync;
93
+ /**
94
+ * Cœur et lobes (base et ghost). Le cœur tourne de θ autour du centre du
95
+ * symbole ; chaque lobe orbite de θ autour de ce même centre puis tourne
96
+ * de ∓2θ sur lui-même — même cinématique que le film (api-film.ts). Les
97
+ * lobes ne sont pas dans le yinYangGroup : chacun porte l'orbite et sa
98
+ * rotation propre dans une seule liste de transformations, interpolée
99
+ * fonction par fonction (angles linéaires en θ).
100
+ */
101
+ private syncLobes;
102
+ /** Libellés contre-tournés : orientation opposée à celle de leur lobe. */
103
+ private syncLabels;
104
+ /**
105
+ * (Re)pose les animations des cibles dont la piste est absente ou
106
+ * périmée ; oublie celles des nœuds sortis du document. Une cible qui ne
107
+ * peint rien (ghost vide, libellé masqué) n'est pas animée : le navigateur
108
+ * refuse de composer une animation sans effet visible et la joue alors
109
+ * sur le thread principal, qui repeindrait tout à chaque image.
110
+ */
111
+ private syncTargets;
112
+ private dropTrack;
113
+ /**
114
+ * Une animation par tronçon, calée sur `document.timeline` : les tronçons
115
+ * s'enchaînent d'eux-mêmes, sans attendre le JS. Un tronçon fini garde sa
116
+ * pose finale (fill forwards) sous le suivant, créé après lui donc
117
+ * prioritaire dès qu'il démarre : pas d'image vide à la jonction. La
118
+ * croisière boucle sur un tour (θ → θ ± 360°), pose identique aux bornes
119
+ * pour chaque cible (multiples entiers de θ).
120
+ */
121
+ private animateTarget;
122
+ private cancelTracks;
123
+ /** Horloge des animations (temps de l'image courante). */
124
+ private now;
71
125
  }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Horloge d'animation commune : UNE seule requestAnimationFrame native par
3
+ * frame, quel que soit le nombre de boucles actives (rotation, orbite,
4
+ * transition de facette, ghost, champ de force, étincelles…).
5
+ *
6
+ * L'API reprend celle de requestAnimationFrame / cancelAnimationFrame pour
7
+ * que les boucles existantes migrent sans changer de forme : un rappel
8
+ * demandé pendant une frame s'exécute à la frame suivante, avec l'horodatage
9
+ * de la frame ; il ne tourne qu'une fois, la boucle se ré-abonne si elle veut
10
+ * continuer. Quand plus aucun rappel n'est en attente, plus aucune rAF native
11
+ * n'est demandée : l'arrêt est automatique.
12
+ *
13
+ * En plus de rAF :
14
+ * - phases : tous les rappels `read` (mesures DOM : getBBox,
15
+ * getBoundingClientRect…) passent avant tous les rappels `write` de la même
16
+ * frame, ce qui évite d'alterner lecture et écriture (layout forcé) ;
17
+ * - `fps` : cadence maximale d'un effet décoratif. Le rappel est simplement
18
+ * reporté aux frames suivantes tant que l'intervalle n'est pas écoulé ; la
19
+ * boucle étant pilotée par l'horodatage, l'animation garde sa vitesse, elle
20
+ * est seulement échantillonnée moins souvent ;
21
+ * - `pauseWhenHidden` : rappel suspendu tant que le diagramme est hors écran
22
+ * (voir observeVisibility). L'onglet caché, lui, est déjà géré par le
23
+ * navigateur, qui n'appelle plus rAF ;
24
+ * - activité (`isActive`, `onActivityChange`) : vrai tant qu'une boucle tourne
25
+ * à chaque frame depuis un moment, c.-à-d. que le diagramme est de toute
26
+ * façon repeint sur le thread principal. Un effet peut alors préférer
27
+ * s'y joindre plutôt que d'ajouter des calques composés (voir
28
+ * borderColorCycle). Les rappels `passive` n'en comptent pas.
29
+ */
30
+ export type FramePhase = "read" | "write";
31
+ export interface FrameRequestOptions {
32
+ /** Défaut "write". */
33
+ phase?: FramePhase;
34
+ /** Cadence maximale (images/s) — pour les effets décoratifs. */
35
+ fps?: number;
36
+ /** Suspendu tant que le diagramme est hors écran. */
37
+ pauseWhenHidden?: boolean;
38
+ /** Ne compte pas comme activité (voir isActive) : un effet qui ne tourne
39
+ * que parce que le diagramme est actif ne doit pas l'entretenir. */
40
+ passive?: boolean;
41
+ }
42
+ /** Ce que les appelants utilisent de d3.Timer. */
43
+ export interface FrameTimer {
44
+ stop(): void;
45
+ }
46
+ export declare class FrameScheduler {
47
+ private nextId;
48
+ private queue;
49
+ /** Frame en cours d'exécution : un cancel() doit aussi pouvoir y retirer
50
+ * un rappel pas encore exécuté, comme cancelAnimationFrame. */
51
+ private running;
52
+ private nativeFrameId;
53
+ /** Dernière exécution de chaque boucle bridée, indexée par son rappel :
54
+ * une boucle se ré-abonne avec la même fonction à chaque frame. */
55
+ private lastRunByCallback;
56
+ private observer;
57
+ private visibility;
58
+ private active;
59
+ /** Début de la suite de frames actives en cours, null hors d'une suite. */
60
+ private activeStreakStart;
61
+ private lastActiveAt;
62
+ private activityListeners;
63
+ request(callback: FrameRequestCallback, options?: FrameRequestOptions): number;
64
+ cancel(id: number | null | undefined): void;
65
+ /** Équivalent de d3.timer : `callback(elapsedMs)` à chaque frame jusqu'à
66
+ * stop(). */
67
+ timer(callback: (elapsedMs: number) => void, options?: FrameRequestOptions): FrameTimer;
68
+ /**
69
+ * Déclare un élément racine du diagramme : tant qu'aucun des éléments
70
+ * déclarés n'est à l'écran, les rappels `pauseWhenHidden` sont suspendus.
71
+ */
72
+ observeVisibility(element: Element): void;
73
+ /** Inverse d'observeVisibility : le diagramme est démonté. */
74
+ unobserveVisibility(element: Element): void;
75
+ isDiagramVisible(): boolean;
76
+ /** Vrai quand une boucle non passive tourne depuis ACTIVITY_ENTER_MS : le
77
+ * diagramme est alors repeint à chaque frame sur le thread principal. */
78
+ get isActive(): boolean;
79
+ /** Prévient à chaque bascule actif/repos ; renvoie le désabonnement. Le
80
+ * retour au repos n'est constaté que par une frame : un écouteur qui veut
81
+ * le voir garde une boucle `passive` tant qu'il est actif. */
82
+ onActivityChange(listener: (active: boolean) => void): () => void;
83
+ /** Nombre de rappels en attente (diagnostic, tests). */
84
+ get pendingCount(): number;
85
+ /** Tests : oublie tout, y compris la rAF native en attente (les tests
86
+ * remplacent requestAnimationFrame entre deux cas). */
87
+ reset(): void;
88
+ private ensureNativeFrame;
89
+ private hasRunnableEntry;
90
+ private flush;
91
+ private trackActivity;
92
+ }
93
+ export declare const frameScheduler: FrameScheduler;
94
+ /** Effets permanents sans valeur hors écran (étincelle du pourtour,
95
+ * surbrillance d'ODD) : suspendus quand le diagramme n'est pas visible. */
96
+ export declare const AMBIENT_FRAME: FrameRequestOptions;
97
+ /** Effets décoratifs en boucle (vagues et pulsation du ghost) : bridés à
98
+ * animationConfig.decorativeFps et suspendus hors écran. */
99
+ export declare const DECORATIVE_FRAME: FrameRequestOptions;
@@ -0,0 +1,43 @@
1
+ import { FastStopProfile } from "./fastHomingStop";
2
+ /**
3
+ * Mouvement angulaire décrit analytiquement, tronçon par tronçon, pour être
4
+ * joué par le navigateur (Web Animations) plutôt qu'écrit image par image :
5
+ * chaque tronçon est à accélération constante, donc sa position est un
6
+ * polynôme du second degré en temps, qu'une courbe `cubic-bezier` reproduit
7
+ * exactement (voir `segmentEasing`).
8
+ *
9
+ * Les temps sont ceux de `document.timeline` (ms), les angles en degrés, les
10
+ * vitesses en °/ms et les accélérations en °/ms², tous signés (+ = horaire).
11
+ * Les calculs ne dépendent pas de l'unité d'angle : l'orbite des satellites
12
+ * (ChildrenOrbitManager) les fait en radians.
13
+ */
14
+ export interface MotionSegment {
15
+ startTime: number;
16
+ /** Infinity = croisière à vitesse constante, sans fin. */
17
+ duration: number;
18
+ angle0: number;
19
+ omega0: number;
20
+ accel: number;
21
+ }
22
+ export declare function angleAfter(segment: MotionSegment, elapsedMs: number): number;
23
+ export declare function motionEndTime(segments: MotionSegment[]): number;
24
+ /** Angle et vitesse du mouvement à l'instant `time` (0 sans mouvement). */
25
+ export declare function evaluateMotion(segments: MotionSegment[], time: number): {
26
+ angle: number;
27
+ omega: number;
28
+ };
29
+ /**
30
+ * Démarrage ou changement de vitesse : rampe à accélération constante
31
+ * (`accelMag`, °/ms²) de `omega` vers `targetOmega`, puis croisière.
32
+ * `accelMag` ≤ 0 → vitesse cible appliquée d'emblée.
33
+ */
34
+ export declare function rampSegments(startTime: number, angle: number, omega: number, targetOmega: number, accelMag: number): MotionSegment[];
35
+ /** Freinage vers la position de base selon un profil de `fastHomingStop`. */
36
+ export declare function brakeSegments(startTime: number, angle: number, direction: number, profile: FastStopProfile): MotionSegment[];
37
+ /**
38
+ * Courbe d'accélération d'un tronçon fini. Avec x1 = 1/3 et x2 = 2/3, le
39
+ * temps est linéaire dans le paramètre de la courbe ; la progression est
40
+ * alors le polynôme cubique de mêmes pentes aux bornes que la position, qui
41
+ * est du second degré : c'est donc elle, exactement.
42
+ */
43
+ export declare function segmentEasing(segment: MotionSegment): string;
@@ -4,9 +4,12 @@ import type { YinYangInternalModel } from "./interfaces/IYinYangInternalModel";
4
4
  import type { Cause } from "./interfaces/ICauseModel";
5
5
  export type { IViewData } from "./interfaces/IViewData";
6
6
  export type { IYinYangController } from "./interfaces/IYinYangController";
7
- export type { Cause, CauseComponent, CauseOdd, CauseOddCutting, } from "./interfaces/ICauseModel";
7
+ export type { Cause, CauseComponent, CauseOdd, CauseOddCutting, FacetNotion, } from "./interfaces/ICauseModel";
8
8
  export type { YinYangInternalModel, YinYangComponentNode, YinYangOddNode, YinYangCuttingNode, YinYangCategorySlice, YinYangOrientation, } from "./interfaces/IYinYangInternalModel";
9
9
  export { mapCauseToInternalModel } from "./adapters/yinYangAdapter";
10
+ /** Sous-état Idle du diagramme (aucune facette ouverte) — voir
11
+ * `YinYangMountConfig.idleView`. */
12
+ export type YinYangIdleView = "arcs" | "facettes" | "tab";
10
13
  /** Données acceptées : soit une `Cause` (format métier), soit le modèle interne déjà adapté. */
11
14
  export type YinYangData = Cause | YinYangInternalModel;
12
15
  export interface YinYangSvgConfig {
@@ -29,10 +32,22 @@ export interface YinYangMountConfig {
29
32
  /** Mode PRÉSENTATION : le diagramme se lit, il ne se manœuvre pas — voir
30
33
  * `IViewData.presentation`. Défaut : false (l'atelier complet). */
31
34
  presentation?: boolean;
35
+ /** Sous-état Idle affiché au montage : `"arcs"` (arcs pondérés des
36
+ * facettes autour de l'illustration) ou `"facettes"` (un satellite
37
+ * yin/yang par facette, à l'angle de son arc) ou `"tab"` (ces mêmes
38
+ * satellites rangés dans une grille régulière autour d'une illustration
39
+ * réduite — les facettes d'une même notion parente, `CauseComponent.notion`,
40
+ * y sont regroupées). L'utilisateur passe ensuite d'un sous-état au
41
+ * suivant en cliquant l'illustration centrale. Défaut : `"arcs"`. */
42
+ idleView?: YinYangIdleView;
32
43
  }
33
44
  export interface YinYangMountHandle {
34
45
  controller: IYinYangController;
35
- /** Vide le conteneur. */
46
+ /** Bascule (animée) du sous-état Idle — voir `YinYangMountConfig.idleView`.
47
+ * Facette ouverte : le choix s'applique à sa fermeture. */
48
+ setIdleView(view: YinYangIdleView): Promise<void>;
49
+ /** Arrête toutes les boucles d'animation du diagramme (champ de force,
50
+ * orbite, rotation, ghost, étincelles…) puis vide le conteneur. */
36
51
  destroy(): void;
37
52
  }
38
53
  /**
@@ -1,5 +1,25 @@
1
1
  declare global {
2
2
  var runBenchmark: () => Promise<void>;
3
3
  var runBenchmarkAvg: (n: number) => Promise<void>;
4
+ var runBenchmarkReport: (only?: string[]) => Promise<BenchmarkReport>;
5
+ }
6
+ import { type DomCounts } from "./scenarios";
7
+ interface ScenarioResult {
8
+ name: string;
9
+ description: string;
10
+ duration: number;
11
+ setupMs?: number;
12
+ avgFrameMs: number;
13
+ p95FrameMs: number;
14
+ longTasksCount: number;
15
+ domCounts?: DomCounts;
16
+ }
17
+ interface BenchmarkReport {
18
+ commit: string;
19
+ timestamp: string;
20
+ runsCount?: number;
21
+ longTaskObserverOk?: boolean;
22
+ scenarios: ScenarioResult[];
23
+ analysis?: Record<string, unknown>;
4
24
  }
5
25
  export {};
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Compteurs DOM d'un scénario (détection de fuites : nœuds SVG, `<animate>` SMIL,
3
+ * enfants de `<defs>`). Relevés par le scénario juste avant de retirer son
4
+ * conteneur, puis lus une seule fois par le runner via takeDomCounts().
5
+ */
6
+ export interface DomCounts {
7
+ svgNodes: number;
8
+ animateNodes: number;
9
+ defsChildren: number;
10
+ }
11
+ export declare function takeDomCounts(): DomCounts | undefined;
1
12
  /**
2
13
  * Scenario 1 — Large dataset initialization.
3
14
  *
@@ -35,10 +46,9 @@ export declare function runComponentSwitchScenario(hooks?: ComponentSwitchHooks)
35
46
  /**
36
47
  * Scenario 3 — Rotation animation.
37
48
  *
38
- * Starts the continuous rotation animation (AnimationsMngr RAF loop) on a
39
- * full Yasuni instance including orbit children, and lets it run for
40
- * TRANSITION_DURATION_MS. Measures per-frame cost: Yin/Yang orbital math,
41
- * SVG transform updates for parent + all children.
49
+ * Starts the continuous rotation animation (AnimationsMngr, Web Animations
50
+ * composed by the browser) on a full Yasuni instance including orbit
51
+ * children, and lets it run for TRANSITION_DURATION_MS.
42
52
  *
43
53
  * Performance measure name: "bm-transition"
44
54
  */
@@ -50,8 +60,8 @@ export interface BaselineHooks {
50
60
  /**
51
61
  * Scenario — Baseline (pivot).
52
62
  *
53
- * Controller + satellites en état idle : aucune action activée, aucune rotation,
54
- * aucun champ de force. Seuls les RAF loops systèmes tournent en arrière-plan
63
+ * Facette 0 ouverte (donc satellites présents), sans action, rotation ni champ de force :
64
+ * seuls les RAF loops systèmes tournent en arrière-plan
55
65
  * (ghost pulse, outer spark, cycle couleurs de bordure).
56
66
  *
57
67
  * Sert de référence directe pour quantifier le surcoût de chaque autre scénario :
@@ -116,3 +126,42 @@ export declare function runForceFieldDirectScenario(hooks?: ForceFieldHooks): Pr
116
126
  * Performance measure names: "bm-forcefield-merged-setup", "bm-forcefield-merged"
117
127
  */
118
128
  export declare function runForceFieldMergedScenario(hooks?: ForceFieldHooks): Promise<void>;
129
+ /**
130
+ * Scenario 8 — ghostProjection : action projetée en mode Pile, 3 s.
131
+ *
132
+ * Mode Pile forcé + activation d'une action (ODD_15 / cut0) : le ghost (badge
133
+ * de deltas, vagues, arc / bordure / spikes ghost) tourne en boucle sans fin.
134
+ * Mesure le régime établi pendant 3 s, une fois la projection affichée.
135
+ *
136
+ * Performance measure names: "bm-ghost-setup", "bm-ghost"
137
+ */
138
+ export declare function runGhostProjectionScenario(hooks?: ForceFieldHooks): Promise<void>;
139
+ /**
140
+ * Scenario 9 — orbit : orbite des satellites SANS action active (3 s).
141
+ *
142
+ * setChildrenOrbitEnabled(true) : chaque frame, ChildrenOrbitManager.applyTransforms
143
+ * déclenche renderOppositeChildrenForceField (labels de contexte, panneau de
144
+ * détails…). Cible : la cascade applicative à 60 fps hors champ de force.
145
+ *
146
+ * Performance measure name: "bm-orbit"
147
+ */
148
+ export declare function runOrbitScenario(hooks?: ForceFieldHooks): Promise<void>;
149
+ /**
150
+ * Scenario 10 — orbitAction : orbite des satellites AVEC une action active (3 s).
151
+ *
152
+ * Même chose qu'orbit, mais après searchNavigateToAction : le champ de force
153
+ * est alors dessiné par l'orbite ET par sa propre boucle.
154
+ *
155
+ * Performance measure names: "bm-orbit-action-setup", "bm-orbit-action"
156
+ */
157
+ export declare function runOrbitActionScenario(hooks?: ForceFieldHooks): Promise<void>;
158
+ /**
159
+ * Scenario 11 — idleTabMorph : Idle « facettes » → « tab » → « facettes ».
160
+ *
161
+ * La fenêtre de mesure couvre les deux morphs et un maintien de 1 s sur la
162
+ * grille « tab » (transform sur le globalGroup racine à chaque tick, fondus
163
+ * d'images clip-pathées).
164
+ *
165
+ * Performance measure name: "bm-idle-tab"
166
+ */
167
+ export declare function runIdleTabMorphScenario(hooks?: ForceFieldHooks): Promise<void>;
@@ -5,6 +5,8 @@ import { IYinYangAppFactory } from "../../interfaces/IYinYangAppFactory";
5
5
  import { IAnimator } from "../../interfaces/IAnimator";
6
6
  import { YinYangInternalModel } from "../../interfaces/IYinYangInternalModel";
7
7
  import { ForceFieldLinkDetail } from "./force-field/types";
8
+ import { type IdleTabHooks } from "./children/IdleFacettesController";
9
+ import type { IdleView } from "./state/YinYangControllerState";
8
10
  import type { DiagramNavEvent } from "./types";
9
11
  export declare class YinYangController implements IYinYangController {
10
12
  model: IYinYangModel;
@@ -12,6 +14,9 @@ export declare class YinYangController implements IYinYangController {
12
14
  factory: IYinYangAppFactory;
13
15
  animator: IAnimator;
14
16
  private childControllers;
17
+ /** Vrai pendant la création des satellites (ChildrenBuilder) : les rendus
18
+ * intermédiaires du champ de force y sont ignorés, un seul suit. */
19
+ private forceFieldRenderSuppressed;
15
20
  /** État de la rotation spin (voir startRotation/stopRotationAll) — non nul
16
21
  * tant que la rotation est active, pour que les enfants recréés en cours
17
22
  * de route (createYinYangChildren) démarrent immédiatement avec les mêmes
@@ -22,7 +27,7 @@ export declare class YinYangController implements IYinYangController {
22
27
  private readonly ACTION_DRAG_THRESHOLD_PX;
23
28
  private actionStackController;
24
29
  private childActionMenuController;
25
- private coreEventMenuController;
30
+ private keyEventMenuController;
26
31
  private forceFieldDetailsPanel;
27
32
  private forceFieldRenderer;
28
33
  /** Champ d'événement — liens cœur → satellites amplifiés par l'Événement
@@ -41,6 +46,8 @@ export declare class YinYangController implements IYinYangController {
41
46
  private actionStackManager;
42
47
  private state;
43
48
  private childrenBuilder;
49
+ private idleFacettes;
50
+ private onIdleViewChange;
44
51
  private componentSwitch;
45
52
  private incomingForceField;
46
53
  private detailsPresenter;
@@ -56,6 +63,35 @@ export declare class YinYangController implements IYinYangController {
56
63
  * Constructor to initialize the controller with its model, view, and factory.
57
64
  */
58
65
  constructor(model: IYinYangModel, view: IYinYangView, factory: IYinYangAppFactory);
66
+ /** Sous-état d'Idle affiché quand aucune Facette n'est ouverte : arcs
67
+ * pondérés (« arcs ») ou un satellite yin/yang par facette (« facettes »). */
68
+ getIdleView(): IdleView;
69
+ /** Crochets de l'hôte autour du sous-état Idle « tab » : `beforeEnter`
70
+ * (attendu avant le calcul de la grille — ex. replier des panneaux pour
71
+ * agrandir le conteneur du diagramme) et `afterLeave` (satellites revenus
72
+ * à leur place radiale — ex. rétablir ces panneaux). */
73
+ setIdleTabHooks(hooks: IdleTabHooks | null): void;
74
+ /** Rappel de l'hôte à chaque changement de sous-état Idle (ex. refléter
75
+ * l'état d'un bouton « Arcs »). */
76
+ setOnIdleViewChange(callback: ((view: IdleView) => void) | null): void;
77
+ /** Bascule vers un sous-état d'Idle. Hors Idle (Facette ouverte), le choix
78
+ * est seulement mémorisé : il s'appliquera à la fermeture de la Facette. */
79
+ setIdleView(view: IdleView): Promise<void>;
80
+ private isEventFieldInIdleFacettes;
81
+ /** Amène le diagramme en Idle « facettes » — en refermant la Facette
82
+ * ouverte s'il le faut. Résolu une fois les satellites-facettes sortis. */
83
+ private showIdleFacettes;
84
+ /** Clic sur le cœur du lobe dominant en Facette : referme la Facette et
85
+ * revient à la cause en Idle « facettes », quel que soit le sous-état
86
+ * Idle mémorisé. */
87
+ onFacetteCoreClicked(): void;
88
+ /** Clic sur l'illustration centrale : facettes ↔ tab (sans effet hors Idle
89
+ * et en « arcs »). */
90
+ toggleIdleView(): Promise<void>;
91
+ /** Vrai quand le sous-état Idle « facettes » est visé (arcs repliés). */
92
+ isIdleFacettesActive(): boolean;
93
+ /** Réaligne le sous-état Idle après une entrée/sortie d'Idle. */
94
+ syncIdleView(): void;
59
95
  /**
60
96
  * Retrieves the number of borders for the YinYang view.
61
97
  */
@@ -211,6 +247,8 @@ export declare class YinYangController implements IYinYangController {
211
247
  private setActiveChild;
212
248
  private clearActiveChild;
213
249
  private animateChildren;
250
+ private destroyed;
251
+ destroy(): void;
214
252
  private clearChildren;
215
253
  setChildrenOrbitEnabled(isEnabled: boolean, rampMs?: number): void;
216
254
  /** Arrête l'orbite des satellites en rejoignant leur position de base dans
@@ -307,10 +345,37 @@ export declare class YinYangController implements IYinYangController {
307
345
  * Fermeture du menu radial d'un satellite et de l'action qu'il projetait
308
346
  * (champ de force, ghosts, bloc d'action du panneau) — chemin unique partagé
309
347
  * par la hiérarchie (deactivateChildMenuFromHierarchy) et par l'exclusivité
310
- * action/événement (toggleCoreEventMenu, previewKeyEvent). No-op si aucun
348
+ * action/événement (toggleKeyEventMenu, previewKeyEvent). No-op si aucun
311
349
  * satellite n'est actif.
312
350
  */
313
351
  private closeChildActionMenu;
352
+ /**
353
+ * Sélection courante du diagramme — satellite, sinon ODD mis en valeur,
354
+ * sinon facette ; null en vue Sphère (aucune facette ouverte). Sert à
355
+ * mémoriser la sélection propre à un mode au moment de le quitter (voir
356
+ * PanelManager.rememberStackSelection).
357
+ */
358
+ getDiagramSelection(): {
359
+ type: "composante";
360
+ componentIndex: number;
361
+ } | {
362
+ type: "odd";
363
+ componentIndex: number;
364
+ oddId: string;
365
+ } | {
366
+ type: "cutting";
367
+ componentIndex: number;
368
+ oddId: string;
369
+ cuttingIndex: number;
370
+ } | null;
371
+ /**
372
+ * Remet le diagramme à blanc sous la facette courante — satellite
373
+ * désélectionné (menu et action projetée compris), ODD éteint — avant d'y
374
+ * rejouer la sélection mémorisée d'un mode. La facette elle-même reste
375
+ * ouverte (vue ODD quittée) : c'est la sélection rejouée qui décide de la
376
+ * garder, d'en changer ou de la fermer.
377
+ */
378
+ clearDiagramSelection(): void;
314
379
  deactivateComposanteFromHierarchy(): void;
315
380
  /**
316
381
  * Fermeture de la facette courante — chemin unique partagé par l'arc de
@@ -335,7 +400,7 @@ export declare class YinYangController implements IYinYangController {
335
400
  */
336
401
  syncForceFieldToStackMode(): void;
337
402
  /**
338
- * Recalcule le Champ d'événement pour le mode courant — à appeler APRÈS que
403
+ * Recalcule les bulles et le Champ d'événement pour le mode courant — APRÈS que
339
404
  * l'onglet a réellement basculé (les gardes RECHERCHE/STACK, elles, tournent
340
405
  * en phase de capture, avant le toggle de `ff-tab-active`, et liraient donc
341
406
  * encore l'ancien mode via isStackModeActive).
@@ -364,18 +429,20 @@ export declare class YinYangController implements IYinYangController {
364
429
  /** Centre automatiquement (scroll animé) le bloc "Effets cumulés" correspondant
365
430
  * à cet item de pile, dès qu'il apparaît dans le panneau — voir
366
431
  * ForceFieldDetailsPanel.requestScrollToStackItemBlock. */
432
+ private _guidedEventPreviewItem;
367
433
  /**
368
434
  * Glisser guidé d'un prérequis depuis RECHERCHE : la bascule vers STACK
369
435
  * faite par le glisser (switchToTab direct, sans le clic d'onglet qui
370
436
  * appelle syncForceFieldToStackMode) laissait le panneau sur le satellite
371
437
  * de l'action glissée — encore absente de la pile, donc sans aucun bloc.
372
438
  * 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,
439
+ * puis on affiche les blocs du satellite de l'action portant le combo
440
+ * ou l'aperçu de l'action ciblée par l'événement,
374
441
  * sans déplacer la sélection du diagramme (le dépôt s'en charge).
375
442
  */
376
443
  private showStackItemBlocksForDrag;
377
444
  /**
378
- * Sélectionne le satellite porteur d'un item de pile (diagramme + panneau)
445
+ * Sélectionne le satellite porteur ou la Facette d'origine d'un item de pile (diagramme + panneau)
379
446
  * et centre son bloc — même effet qu'un clic sur le libellé de l'item
380
447
  * (voir setOnSelectStackItemSatellite dans DiagramPanelBridge).
381
448
  */
@@ -399,7 +466,8 @@ export declare class YinYangController implements IYinYangController {
399
466
  setOnDirectActionBlock(show: (compId: string, oddId: string, cutIdx: number, actionId: string, cardsHtml: string, attachHandlers: (container: HTMLElement) => void) => void, clear: () => void): void;
400
467
  /** Wire from main.ts — injecte la carte descriptive d'un Événement Clé dans l'onglet Recherche. */
401
468
  setOnShowKeyEventBlock(show: (compId: string, keyEventId: string, cardsHtml: string, attachHandlers: (container: HTMLElement) => void) => void, clear: () => void): void;
402
- /** Enregistre le miroir "menu cœur déployé ?" vers la hiérarchie RECHERCHE. */
469
+ /** Enregistre le miroir "bulles d'Événements Clés déployées sur quel
470
+ * satellite-facette ?" vers la hiérarchie RECHERCHE. */
403
471
  setOnKeyEventMenuStateChange(cb: (componentIndex: number, open: boolean) => void): void;
404
472
  /** Wire from main.ts — affiche le bloc d'action directe d'un prérequis dans le panneau B. */
405
473
  setOnDirectActionBlockPanelB(show: (compId: string, oddId: string, cutIdx: number, actionId: string, cardsHtml: string, attachHandlers: (container: HTMLElement) => void) => void): void;
@@ -425,6 +493,19 @@ export declare class YinYangController implements IYinYangController {
425
493
  setOnDiagramOddChange(cb: (componentIndex: number, oddId: string, mode: "highlight") => void): void;
426
494
  /** Wire from main.ts to sync the search panel on composante / cutting / action clicks. */
427
495
  setOnDiagramNavChange(cb: (event: DiagramNavEvent) => void): void;
496
+ /** Consulter un autre satellite garde l'action active (et son champ de
497
+ * force) : toujours en STACK, en RECHERCHE seulement avec un panneau
498
+ * verrouillé — voir openActionMenuFromChild. */
499
+ private keepsActiveActionOnSatelliteSwitch;
500
+ setIsAnyRecherchePanelLocked(cb: () => boolean): void;
501
+ /** Multi-blocs : un panneau RECHERCHE verrouillé sur une action la fige
502
+ * comme action source — les boutons d'action s'estompent et un clic
503
+ * dessus est refusé (voir onActionSelectionBlocked). */
504
+ setActionSelectionLock(isLocked: () => boolean, onBlocked: (retry: () => void) => void): void;
505
+ private isActionSelectionLocked;
506
+ /** Redessine le menu d'actions du satellite sélectionné — après un
507
+ * (dé)verrouillage de panneau, qui change l'estompage des boutons. */
508
+ refreshChildActionMenu(): void;
428
509
  setOnDiagramSatelliteDeselect(cb: (componentIndex: number) => void): void;
429
510
  setOnDiagramComposanteDeselect(cb: () => void): void;
430
511
  setOnDiagramChildHover(cb: (componentIndex: number | null, oddId: string | null, cuttingIndex?: number) => void): void;
@@ -466,9 +547,9 @@ export declare class YinYangController implements IYinYangController {
466
547
  setChildActionMenuItemDistance(distance: number): void;
467
548
  setChildActionMenuItemScale(scale: number): void;
468
549
  setChildActionIconFontScale(scale: number): void;
469
- setCoreEventMenuDistanceOffset(offset: number): void;
470
- setCoreEventMenuItemScale(scale: number): void;
471
- setCoreEventIconFontScale(scale: number): void;
550
+ setKeyEventMenuDistanceOffset(offset: number): void;
551
+ setKeyEventMenuItemScale(scale: number): void;
552
+ setKeyEventIconFontScale(scale: number): void;
472
553
  setChildLabelMaxLines(lines: number): void;
473
554
  setLabelShortMaxChars(chars: number): void;
474
555
  setOddLabelMaxLines(lines: number): void;
@@ -487,13 +568,22 @@ export declare class YinYangController implements IYinYangController {
487
568
  private clearProjectedActionState;
488
569
  private applyEmptyGhostProjectionState;
489
570
  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;
571
+ /**
572
+ * STACK : une bulle par action activée de la pile dont la source est sur
573
+ * la facette affichée, sur son satellite source. Comme les champs de
574
+ * force : l'action en focus ressort, les autres s'estompent, et toutes
575
+ * sont pleines quand aucune n'est en focus.
576
+ */
577
+ private buildStackDetachedBubbles;
578
+ /**
579
+ * RECHERCHE multi-blocs (panneau verrouillé) : l'action active garde ses
580
+ * champs de force pendant qu'on consulte un autre satellite — sa bulle
581
+ * reste donc visible sur la source, que le menu radial ne montre plus.
582
+ */
583
+ private buildRechercheDetachedBubbles;
493
584
  /** Sélectionne (ouvre) le satellite `childKey` de la facette courante,
494
585
  * comme un clic dessus — sans toggle-close s'il est déjà actif. */
495
586
  private selectSatelliteByKey;
496
- onCoreEventNucleusClicked(): void;
497
587
  searchNavigateToKeyEvent(keyEventId: string): void;
498
588
  restoreKeyEventDiagramState(keyEventId: string): void;
499
589
  searchSetKeyEventMenuOpen(componentIndex: number, open: boolean): void;
@@ -554,7 +644,7 @@ export declare class YinYangController implements IYinYangController {
554
644
  /**
555
645
  * Mode adverse (outil de debug, voir adverseMode.ts) : les actions et
556
646
  * Événements adverses remplacent les ordinaires sur le diagramme (bulles
557
- * des satellites, menu cœur) et dans l'arbre RECHERCHE — qui se
647
+ * des satellites et des satellites-facettes) et dans l'arbre RECHERCHE — qui se
558
648
  * reconstruit seul à la bascule. La pile n'est jamais filtrée.
559
649
  *
560
650
  * Hors STACK, l'action ou l'Événement en aperçu de l'autre bord perdrait