@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
@@ -0,0 +1,53 @@
1
+ import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
2
+ import { IYinYangController } from "../../../interfaces/IYinYangController";
3
+ import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
4
+ import { ForceFieldComputationService } from "./ForceFieldComputationService";
5
+ import { ForceFieldRenderer } from "./ForceFieldRenderer";
6
+ import { YinYangControllerState } from "../state/YinYangControllerState";
7
+ type ChildOddMeta = {
8
+ oddId: string;
9
+ score: number;
10
+ cuttingIndex: number;
11
+ };
12
+ type ForceFieldLifecycleControllerDeps = {
13
+ state: YinYangControllerState;
14
+ childOddMap: Map<string, ChildOddMeta>;
15
+ forceFieldComputationService: ForceFieldComputationService;
16
+ forceFieldRenderer: ForceFieldRenderer;
17
+ getCurrentComponent: () => YinYangInternalModel["components"][number] | null;
18
+ getAllComponents: () => YinYangInternalModel["components"] | undefined;
19
+ updateChildActionMenu: (orbitData: ChildrenOrbitEntry[]) => void;
20
+ updateContextLabels: (orbitData: ChildrenOrbitEntry[]) => void;
21
+ clearForceFieldDetails: () => void;
22
+ renderForceFieldDetails: (linkIndex: number) => void;
23
+ renderActionPropagationTable: () => void;
24
+ renderSourceActionDetailsForCurrentSource: () => void;
25
+ clearGhostDetails: () => void;
26
+ clearForceFieldComputationState: () => void;
27
+ buildChildrenOrbitData: () => ChildrenOrbitEntry[];
28
+ setContextLabelsVisibilityOpacity: (opacity: number) => void;
29
+ getGlobalGroupNode: () => SVGGElement | null;
30
+ getChildRenderedCenter: (childController: IYinYangController) => {
31
+ x: number;
32
+ y: number;
33
+ } | null;
34
+ getComponentBorderTargetPoint: (componentId: string) => {
35
+ x: number;
36
+ y: number;
37
+ } | null;
38
+ };
39
+ export declare class ForceFieldLifecycleController {
40
+ private deps;
41
+ private _propCacheKey;
42
+ private _propCacheResult;
43
+ constructor(deps: ForceFieldLifecycleControllerDeps);
44
+ /** Invalide le cache (à appeler après un switch de composante ou clear). */
45
+ invalidatePropagationCache(): void;
46
+ private _buildPropCacheKey;
47
+ renderOppositeChildrenForceField(orbitData?: ChildrenOrbitEntry[]): void;
48
+ removeOppositeChildrenForceField(): void;
49
+ private ensureForceFieldLinks;
50
+ private updateForceFieldVisual;
51
+ private startForceFieldAnimation;
52
+ }
53
+ export {};
@@ -0,0 +1,67 @@
1
+ import { IYinYangController } from "../../../interfaces/IYinYangController";
2
+ import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
3
+ import { ForceFieldSegment } from "./types";
4
+ type Point = {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ export declare class ForceFieldRenderer {
9
+ private forceFieldGroup;
10
+ private forceFieldDefs;
11
+ private forceFieldLayers;
12
+ private readonly gradientPrefix;
13
+ /** Active pulse overrides: linkIndex → { startMs, durationMs }. Cleared on arc end. */
14
+ private readonly _pulsedLinks;
15
+ /** setTimeout id du fondu de sortie en cours, ou null — voir hide(). */
16
+ private _hideTimeoutId;
17
+ /** requestAnimationFrame id de la rétraction géométrique en cours — voir retractGeometry(). */
18
+ private _retractFrameId;
19
+ /**
20
+ * Temporarily boost the visual intensity of a force-field link.
21
+ * Opacity and aura stroke-width are amplified with a sin envelope over `durationMs`.
22
+ * Called by YinYangController while the propagation arc travels the matching segment.
23
+ */
24
+ pulseLink(linkIndex: number, durationMs: number): void;
25
+ hasActiveGroup(): boolean;
26
+ ensureElements(params: {
27
+ globalGroupNode: SVGGElement;
28
+ requiredCount: number;
29
+ }): void;
30
+ updateVisual(params: {
31
+ forceFieldOrbitData: ChildrenOrbitEntry[] | null;
32
+ forceFieldLinks: ForceFieldSegment[];
33
+ forceFieldRevealStartedAt?: number;
34
+ forceFieldPhase: number;
35
+ getChildRenderedCenter: (childController: IYinYangController) => Point | null;
36
+ getComponentBorderTargetPoint: (componentId: string) => Point | null;
37
+ }): void;
38
+ /**
39
+ * Fondu de sortie : au lieu de retirer le groupe instantanément (clear()),
40
+ * ramène son opacité à 0 sur fieldFadeOutDurationMs puis le retire
41
+ * réellement — même grammaire de disparition que EventFieldRenderer.hide().
42
+ * Idempotent : un appel alors qu'un fondu est déjà en cours ne fait rien de
43
+ * plus (le clear() en attente suffit).
44
+ */
45
+ hide(): void;
46
+ /**
47
+ * Rétraction géométrique : anime chaque beam vers son point de départ,
48
+ * inverse exact de la croissance animatedEnd de updateVisual (même
49
+ * fonction d'accélération, lue à l'envers : d3.easeCubicOut(1 - t) au lieu
50
+ * de d3.easeCubicOut(t)). Repart de _prevEndpoint — la géométrie du
51
+ * dernier frame réellement rendu — donc ne dépend d'aucun state externe :
52
+ * elle continue même si les liens qui l'ont produite sont nettoyés entre
53
+ * temps (cas typique : clic sur l'arc de facette, qui déclenche hide()
54
+ * puis, dans la foulée, la destruction des satellites source). Se déroule
55
+ * en parallèle du fondu d'opacité du groupe (même durée, posé par hide()).
56
+ */
57
+ private retractGeometry;
58
+ clear(): void;
59
+ /**
60
+ * Met à jour les coordonnées d'un gradient et, si stopData est fourni (cache miss),
61
+ * les couleurs et opacités des stops.
62
+ * Fix 1 : les offsets ne sont jamais réécrits (initialisés une seule fois dans createStops).
63
+ * Fix 2 : stopData === null signifie que le cache couleur est valide — on n'écrit pas les stops.
64
+ */
65
+ private updateGradient;
66
+ }
67
+ export {};
@@ -0,0 +1,42 @@
1
+ export type ForceFieldLinkDetail = {
2
+ fromComponentId: string;
3
+ toComponentId: string;
4
+ fromOddId: string;
5
+ toOddId: string;
6
+ fromCuttingId?: number;
7
+ toCuttingId?: number;
8
+ baseDelta: number;
9
+ weight: number;
10
+ strategicWeight: number;
11
+ layerType: "inter" | "intra" | "bridge";
12
+ propagationFactor: number;
13
+ absorption: number;
14
+ gap: number;
15
+ fromState: number;
16
+ toState: number;
17
+ deltaTo: number;
18
+ rationale?: string;
19
+ /** Entry cutting in the target ODD's intra chain (from yasuniInterconnectionGraph edge). */
20
+ targetedCutting?: number;
21
+ layersInvolved: string[];
22
+ localLayerWeights: string | null;
23
+ bridgeLayerWeights: string | null;
24
+ };
25
+ export type ForceFieldLink = {
26
+ startIndex?: number;
27
+ sourceComponentId?: string;
28
+ endIndex?: number;
29
+ targetComponentId?: string;
30
+ thickness: number;
31
+ potentialGain: number;
32
+ /** Delay before revealing this link, used for chained intra-ODD propagation. */
33
+ revealDelayMs?: number;
34
+ detail: ForceFieldLinkDetail;
35
+ };
36
+ /**
37
+ * Représentation pure-rendu d'un segment de champ de force.
38
+ * Identique à ForceFieldLink mais sans le champ `detail` (domaine métier).
39
+ * Permet de fusionner des segments qui se superposent visuellement
40
+ * sans impacter la logique de propagation.
41
+ */
42
+ export type ForceFieldSegment = Omit<ForceFieldLink, "detail">;
@@ -0,0 +1,33 @@
1
+ import { IYinYangController } from "../../../interfaces/IYinYangController";
2
+ import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
3
+ import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
4
+ import { ProjectedCuttingState } from "../actions/ActionProjectionService";
5
+ export declare class ChildScoresDeltaRenderer {
6
+ render(params: {
7
+ orbitData: ChildrenOrbitEntry[];
8
+ globalGroupNode: SVGGElement | null;
9
+ parentCenterX: number;
10
+ parentCenterY: number;
11
+ component: YinYangInternalModel["components"][number] | null;
12
+ childOddMap: Map<string, {
13
+ oddId: string;
14
+ score: number;
15
+ cuttingIndex: number;
16
+ }>;
17
+ getChildRenderedCenter: (childController: IYinYangController) => {
18
+ x: number;
19
+ y: number;
20
+ } | null;
21
+ getChildRadius: (childController: IYinYangController) => number;
22
+ projectedGhostCuttingStatesByOddId: Map<string, ProjectedCuttingState[]> | null;
23
+ projectedGhostStateByOddId: Map<string, number> | null;
24
+ weightDeltaByChildKey?: Map<string, number>;
25
+ actionDeltaLabelsVisible: boolean;
26
+ labelsTextShadowEnabled: boolean;
27
+ childStateDeltaFontScale: number;
28
+ childStateDeltaOffset?: number;
29
+ childStateDeltaBoxScale?: number;
30
+ selectedCuttingId?: number;
31
+ selectedOddId?: string;
32
+ }): void;
33
+ }
@@ -0,0 +1,155 @@
1
+ import { YinYangCategoryArcGeometry } from "../../../interfaces/IYinYangGeometry";
2
+ import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
3
+ import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
4
+ import { ProjectedCuttingState } from "../actions/ActionProjectionService";
5
+ type ChildOddMeta = {
6
+ oddId: string;
7
+ score: number;
8
+ cuttingIndex: number;
9
+ };
10
+ /** Satellite (ODD cutting) actuellement actif sous la facette affichée, à
11
+ * afficher comme second niveau du titre — avec, le cas échéant, l'action
12
+ * de ce satellite en troisième niveau. Null en repli sur le seul libellé
13
+ * de facette. */
14
+ export type ComponentTitleSatelliteInfo = {
15
+ label: string;
16
+ oddColor: string;
17
+ actionLabel: string | null;
18
+ } | null;
19
+ type RenderContextLabelsParams = {
20
+ globalGroupNode: SVGGElement | null;
21
+ orbitData: ChildrenOrbitEntry[];
22
+ allComponents: YinYangInternalModel["components"];
23
+ borderSegments: YinYangCategoryArcGeometry[];
24
+ containerTopY: number;
25
+ componentTitleContainer?: HTMLDivElement | null;
26
+ onComponentLegendVisibilityChange?: (isVisible: boolean) => void;
27
+ onComponentLegendSelect?: (componentId: string) => void;
28
+ onComponentTitleClick?: () => void;
29
+ component: YinYangInternalModel["components"][number] | null;
30
+ componentTitle: string;
31
+ satelliteTitle: ComponentTitleSatelliteInfo;
32
+ parentCenterX: number;
33
+ parentCenterY: number;
34
+ childOddMap: Map<string, ChildOddMeta>;
35
+ getChildRenderedCenter: (controller: ChildrenOrbitEntry["controller"]) => {
36
+ x: number;
37
+ y: number;
38
+ } | null;
39
+ getChildRadius: (controller: ChildrenOrbitEntry["controller"]) => number;
40
+ /** Center + radius of a facette's image thumbnail (pre-scale coordinate
41
+ * space), so the component legend can anchor onto the image instead of
42
+ * floating radially around the sphere. Null if the ring isn't built yet. */
43
+ getComponentImagePosition: (componentId: string) => {
44
+ x: number;
45
+ y: number;
46
+ radius: number;
47
+ } | null;
48
+ childrenContextLabelsVisible: boolean;
49
+ labelsFontScale: number;
50
+ componentLabelFontScale: number;
51
+ componentLegendLabelFontScale: number;
52
+ legendLabelsBgEnabled: boolean;
53
+ labelsTextShadowEnabled: boolean;
54
+ childLabelMaxLines: number;
55
+ childLabelShortMaxChars: number;
56
+ actionDeltaLabelsVisible: boolean;
57
+ projectedGhostCuttingStatesByOddId: Map<string, ProjectedCuttingState[]> | null;
58
+ projectedGhostStateByOddId: Map<string, number> | null;
59
+ allLabelsVisible: boolean;
60
+ displayEllipsisForShortLabels: boolean;
61
+ /** True only when no facette is active (Sphère status) — the component
62
+ * legend must only ever show in that state. */
63
+ isSphereStatus: boolean;
64
+ };
65
+ export declare class ContextLabelsRenderer {
66
+ private contextLabelGroup;
67
+ private componentLegendGroup;
68
+ private lastParams;
69
+ private _childLabelCache;
70
+ /** Crossfades du texte du titre (facette / satellite), indépendants pour
71
+ * que le changement de l'un ne fasse pas clignoter l'autre. */
72
+ private _titleCrossfadeTimers;
73
+ /** Timers de révélation "machine à écrire" lettre par lettre, par clé
74
+ * (facette / satellite / action) — annulés et relancés à chaque nouveau
75
+ * texte pour qu'un changement rapide n'empile pas plusieurs cascades. */
76
+ private _typewriterTimers;
77
+ /** Halo sombre multi-direction (au lieu d'un fond plein) qui garde le
78
+ * libellé lisible sur n'importe quel arrière-plan (vignettes, arcs de
79
+ * couleur, etc.) maintenant qu'il n'a plus de cadre. */
80
+ private static readonly TITLE_GLOW;
81
+ /** Ombre sombre pure (sans le halo cyan de TITLE_GLOW) pour les lignes
82
+ * satellite/action : à leur petit corps, le halo lumineux rendait le
83
+ * texte flou — une ombre nette suffit à la lisibilité sur fond mixte. */
84
+ private static readonly SUB_ROW_SHADOW;
85
+ /** Délai entre deux lettres de la révélation "machine à écrire" du titre. */
86
+ private static readonly TITLE_TYPEWRITER_STEP_MS;
87
+ /** Les deux niveaux enfants du titre partagent leur mise en forme entre
88
+ * création et mise à jour via ces specs, seule source de vérité : rampe
89
+ * typographique régulière (15 → 12.5 → 11), indentation en escalier
90
+ * (l'équerre de l'action s'aligne sous le début du texte satellite) et
91
+ * connecteur de l'action légèrement atténué pour reculer d'un plan. */
92
+ private static readonly SATELLITE_ROW_SPEC;
93
+ private static readonly ACTION_ROW_SPEC;
94
+ render(params: RenderContextLabelsParams): void;
95
+ clear(): void;
96
+ setVisibilityOpacity(opacity: number): void;
97
+ /**
98
+ * Updates just the top-left component-title DOM element, independently of
99
+ * the full render() pass (which needs orbit/legend data and is only ever
100
+ * called once the diagram's component-switch animation completes). Lets
101
+ * callers reflect the new active facette in the label the instant the user
102
+ * clicks, instead of waiting ~800ms for the diagram animation.
103
+ */
104
+ updateComponentTitleOnly(container: HTMLDivElement | null | undefined, title: string, satelliteTitle: ComponentTitleSatelliteInfo, fontScale: number, textShadowEnabled: boolean, onTitleClick?: () => void): void;
105
+ private renderComponentTitleInDOM;
106
+ /** Fades the top-left title out whenever a rendered orbit bubble (the
107
+ * tension/force-field badges that fly out around an active facette)
108
+ * physically overlaps its on-screen footprint — the title's fixed corner
109
+ * position means some facettes' badges end up right underneath it.
110
+ * Compares real getBoundingClientRect()s (not the diagram's internal
111
+ * coordinate space) so it stays correct regardless of zoom/resize. */
112
+ private updateTitleObstruction;
113
+ private createTitleElement;
114
+ /** Un niveau (satellite ou action) du titre : un connecteur en ⌐ inversé
115
+ * (SVG, coin arrondi, caps ronds) qui part du bord gauche de la ligne
116
+ * parente et vient pointer sur le libellé, teinté de la couleur ODD du
117
+ * satellite (même convention que le chip STACK du panneau de détails).
118
+ * `indentPx` enfonce l'action un cran de plus que le satellite pour lire
119
+ * la hiérarchie facette → satellite → action d'un coup d'œil. Replié à
120
+ * hauteur nulle plutôt que retiré du DOM quand invisible, pour pouvoir
121
+ * s'animer en douceur à l'apparition/disparition. */
122
+ private createTreeRow;
123
+ /** Toute la mise en forme d'une ligne de l'arbre (géométrie du connecteur
124
+ * comprise), partagée entre le chemin création et le chemin mise à jour
125
+ * pour que les deux restent rigoureusement identiques. Le connecteur est
126
+ * redessiné à chaque passage : son tracé dépend de la hauteur de ligne
127
+ * (fontScale) et de la couleur ODD, tous deux susceptibles de changer. */
128
+ private applyTreeRowStyle;
129
+ /** Révèle `text` dans `el` lettre par lettre, en cascade rapide (effet
130
+ * "machine à écrire" façon interface sci-fi) : chaque caractère est posé
131
+ * dans son propre span, invisible, puis fondu en place avec un léger
132
+ * décalage sur le suivant. `key` isole les cascades concurrentes (facette
133
+ * vs. satellite vs. action) et annule celle déjà en cours pour cette clé
134
+ * afin qu'un changement rapide ne fasse pas se chevaucher deux révélations. */
135
+ private typewriterReveal;
136
+ /** Fades one title line's old text out, then reveals the new text lettre
137
+ * par lettre (typewriterReveal) instead of an abrupt swap, using its own
138
+ * short duration (componentTitleCrossfadeMs) independent of the slower
139
+ * orbit/legend reveal, so the label always reads as a quick, deliberate,
140
+ * sci-fi-flavored change. `key` isolates concurrent crossfades (facette
141
+ * vs. satellite vs. action line) and cancels any one already in flight
142
+ * for that key so rapid re-clicks converge on the latest text instead of
143
+ * racing. */
144
+ private scheduleTextCrossfade;
145
+ private updateTitleElement;
146
+ /** Updates one existing tree row (satellite or action line) in place —
147
+ * the counterpart to createTreeRow for the update path (element already
148
+ * in the DOM). Re-applies the shared style pass (applyTreeRowStyle), then
149
+ * cross-fades the text if it changed. */
150
+ private updateTreeRow;
151
+ private renderComponentLegend;
152
+ private hideComponentLegend;
153
+ private ensureContextLabelGroup;
154
+ }
155
+ export {};
@@ -0,0 +1,61 @@
1
+ import { IYinYangController } from "../../../interfaces/IYinYangController";
2
+ import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
3
+ import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
4
+ /**
5
+ * The satellite equivalent of the facette's score ghost
6
+ * (YinYangDrawer.drawGhostCircle + updateGhostWaveAnimation): the satellite's
7
+ * own circle never changes size — a dashed gold "ghost" circle is drawn at
8
+ * the projected weightDelta radius, and a single wave circle continuously
9
+ * travels between the satellite's real radius and that ghost radius
10
+ * (d3.easeSinInOut, same waveTravelDurationSec-length lap, sin envelope
11
+ * fading it in/out at each end so it loops without a visible pop).
12
+ */
13
+ export declare class WeightPreviewRingRenderer {
14
+ private entries;
15
+ private frameId;
16
+ private groupNode;
17
+ private pulseStates;
18
+ private basePulseEnabled;
19
+ private pulseDurationMs;
20
+ private pulseMorphRatio;
21
+ render(params: {
22
+ orbitData: ChildrenOrbitEntry[];
23
+ globalGroupNode: SVGGElement | null;
24
+ component: YinYangInternalModel["components"][number] | null;
25
+ childOddMap: Map<string, {
26
+ oddId: string;
27
+ score: number;
28
+ cuttingIndex: number;
29
+ }>;
30
+ weightDeltaByChildKey: Map<string, number>;
31
+ getChildRenderedCenter: (childController: IYinYangController) => {
32
+ x: number;
33
+ y: number;
34
+ } | null;
35
+ getChildRadius: (childController: IYinYangController) => number;
36
+ /** Mirrors ViewInitializer.basePulseEnabled/ghostPulseDurationSec/
37
+ * pulseMorphRatio ("Pulsation rayons activée") from the parent facette,
38
+ * so toggling that one control affects both ghosts identically. */
39
+ basePulseEnabled: boolean;
40
+ pulseDurationMs: number;
41
+ pulseMorphRatio: number;
42
+ }): void;
43
+ /** Starts/stops per-satellite pulse state to match the current entry set
44
+ * and basePulseEnabled flag, resetting any satellite's own scale back to
45
+ * identity the moment it stops being targeted or pulsing is turned off —
46
+ * mirrors YinYangDrawer.updateBasePulseAnimationForType's reset path. */
47
+ private syncPulseStates;
48
+ private resetPulseTransforms;
49
+ private resetEntryTransform;
50
+ private drawGhostCircles;
51
+ private ensureLoop;
52
+ private stopLoop;
53
+ /** Breathes each pulsing satellite's own size out to its weightDelta
54
+ * target and back, on a loop with a pause — same morph/reset/pause cycle
55
+ * as YinYangDrawer.applyPulseFrame, scaling the satellite's globalGroup
56
+ * around its own center instead of morphing a single circle's radius, so
57
+ * the whole satellite (arcs, masks, border) breathes together. */
58
+ private updateBasePulse;
59
+ private updateWaves;
60
+ private clear;
61
+ }
@@ -0,0 +1,25 @@
1
+ import { IYinYangView } from "../../../interfaces/IYinYangView";
2
+ import { YinYangControllerState } from "../state/YinYangControllerState";
3
+ import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
4
+ import { IYinYangController } from "../../../interfaces/IYinYangController";
5
+ type ChildrenOrbitManagerDeps = {
6
+ view: IYinYangView;
7
+ getChildControllers: () => IYinYangController[];
8
+ state: YinYangControllerState;
9
+ renderOppositeChildrenForceField: (orbitData: ChildrenOrbitEntry[]) => void;
10
+ };
11
+ export declare class ChildrenOrbitManager {
12
+ private deps;
13
+ private readonly orbitService;
14
+ private cachedOrbitData;
15
+ constructor(deps: ChildrenOrbitManagerDeps);
16
+ invalidateCache(): void;
17
+ buildOrbitData(): ChildrenOrbitEntry[];
18
+ applyTransforms(angleOffset: number, orbitData?: ChildrenOrbitEntry[]): void;
19
+ setEnabled(isEnabled: boolean): void;
20
+ setSpeed(speed: number): void;
21
+ setRadiusScale(scale: number): void;
22
+ start(_durationMs: number): void;
23
+ stop(): void;
24
+ }
25
+ export {};
@@ -0,0 +1,44 @@
1
+ import { IYinYangController } from "../../../interfaces/IYinYangController";
2
+ import { IYinYangView } from "../../../interfaces/IYinYangView";
3
+ import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
4
+ import { ForceFieldDetailsPanel } from "../force-field/ForceFieldDetailsPanel";
5
+ import { ActionStackController } from "../action-stack/ActionStackController";
6
+ import type { CumulativeBlock } from "../YinYangController";
7
+ type ChildOddMeta = {
8
+ oddId: string;
9
+ score: number;
10
+ cuttingIndex: number;
11
+ };
12
+ type OddViewManagerDeps = {
13
+ view: IYinYangView;
14
+ getChildControllers: () => IYinYangController[];
15
+ getChildOddMap: () => Map<string, ChildOddMeta>;
16
+ getActiveChildKey: () => string | null;
17
+ enterOddView: (oddId: string) => void;
18
+ exitOddView: () => void;
19
+ getCurrentComponent: () => YinYangInternalModel["components"][number] | null;
20
+ getAllComponents: () => YinYangInternalModel["components"] | undefined;
21
+ forceFieldDetailsPanel: ForceFieldDetailsPanel;
22
+ actionStackController: ActionStackController;
23
+ hasActiveAction: () => boolean;
24
+ /** Blocs "keyEvent" de la Facette (voir YinYangController.buildKeyEventBlocksForComponent)
25
+ * — affichés par renderComposanteInfo même sans satellite sélectionné. */
26
+ buildKeyEventBlocksForComponent: (component: {
27
+ id: string;
28
+ }) => CumulativeBlock[];
29
+ onNavigateToAction: (actionId: string) => void;
30
+ };
31
+ export declare class OddViewManager {
32
+ private deps;
33
+ constructor(deps: OddViewManagerDeps);
34
+ highlightOddInChildren(oddId: string | null): void;
35
+ highlightOddByStackItemId(stackItemId: string | null): void;
36
+ cancelOddHighlight(): void;
37
+ showOddInfo(oddId: string): void;
38
+ showComposanteInfo(): void;
39
+ applyOddHighlight(oddId: string): void;
40
+ applyEnterOddView(oddId: string): void;
41
+ applyOddStateForCutting(oddId: string): void;
42
+ private applyChildOddHighlight;
43
+ }
44
+ export {};
@@ -0,0 +1,125 @@
1
+ import { IYinYangController } from "../../../interfaces/IYinYangController";
2
+ import { IYinYangView } from "../../../interfaces/IYinYangView";
3
+ import { YinYangControllerState } from "../state/YinYangControllerState";
4
+ import { ActionStackController } from "../action-stack/ActionStackController";
5
+ import { ChildActionMenuController } from "../actions/ChildActionMenuController";
6
+ import type { KeyEventDefinition } from "../../../data/yasuni_key_events";
7
+ import type { Point } from "../actions/radialItemMenu";
8
+ type ChildOddMeta = {
9
+ oddId: string;
10
+ score: number;
11
+ cuttingIndex: number;
12
+ };
13
+ type DiagramCuttingNavEvent = {
14
+ type: "cutting";
15
+ componentIndex: number;
16
+ oddId: string;
17
+ cuttingIndex: number;
18
+ };
19
+ /** Subset of PendingComponentSwitchContext values set by search interactions. */
20
+ type SearchPendingContext = null | {
21
+ type: "searchCutting";
22
+ oddId: string;
23
+ cuttingIndex: number;
24
+ forceOpen?: boolean;
25
+ } | {
26
+ type: "searchOdd";
27
+ oddId: string;
28
+ } | {
29
+ type: "searchOddHighlight";
30
+ oddId: string;
31
+ } | {
32
+ type: "searchAction";
33
+ oddId: string;
34
+ cuttingIndex: number;
35
+ actionId: string;
36
+ } | {
37
+ type: "restoreAction";
38
+ oddId: string;
39
+ cuttingIndex: number;
40
+ actionId: string;
41
+ };
42
+ type SearchPanelSynchronizerDeps = {
43
+ view: IYinYangView;
44
+ getChildControllers: () => IYinYangController[];
45
+ getChildOddMap: () => Map<string, ChildOddMeta>;
46
+ state: YinYangControllerState;
47
+ ACTION_DRAG_THRESHOLD_PX: number;
48
+ setPendingContext: (ctx: SearchPendingContext) => void;
49
+ setPendingOddHighlightAfterSwitch: (oddId: string) => void;
50
+ setPendingCuttingNavigationAfterSwitch: (oddId: string, cuttingIndex: number, forceOpen: boolean) => void;
51
+ setRouteNextDirectActionBlockToPanelB: (val: boolean) => void;
52
+ setSuppressDirectActionBlockRender: (val: boolean) => void;
53
+ prepareForComponentSwitch: (targetComponentId: string) => void;
54
+ animateChildrenHide: () => void;
55
+ setChildrenEnabled: (enabled: boolean) => void;
56
+ onDiagramComposanteClicked: (componentIndex: number) => void;
57
+ onDiagramOddArcClicked: (oddId: string) => void;
58
+ onDiagramNavChange?: (event: DiagramCuttingNavEvent) => void;
59
+ applyEnterOddView: (oddId: string) => void;
60
+ applyOddHighlight: (oddId: string) => void;
61
+ focusChildByOddCutting: (oddId: string, cuttingIndex: number, forceOpen?: boolean) => void;
62
+ focusChildByOddCuttingAndAction: (oddId: string, cuttingIndex: number, actionId: string) => void;
63
+ validateActionSelection: (childController: IYinYangController, actionId: string, label: string, insertAtVisibleIndex?: number | null, entryOrigin?: {
64
+ x: number;
65
+ y: number;
66
+ }) => void;
67
+ validateKeyEventSelection: (keyEvent: KeyEventDefinition, insertAtVisibleIndex?: number | null, entryOrigin?: {
68
+ x: number;
69
+ y: number;
70
+ }) => void;
71
+ restoreKeyEventDiagramState: (keyEventId: string) => void;
72
+ actionStackController: ActionStackController;
73
+ childActionMenuController: ChildActionMenuController;
74
+ renderDragGhost: (clientX: number, clientY: number, iconUrl: string) => void;
75
+ removeDragGhost: () => void;
76
+ clientPointToGlobalGroup: (clientX: number, clientY: number) => {
77
+ x: number;
78
+ y: number;
79
+ } | null;
80
+ };
81
+ /**
82
+ * Coordonne le panneau RECHERCHE avec le diagramme — et héberge aussi le
83
+ * cœur partagé du glisser-déposer vers la pile (startActionDrag), réutilisé
84
+ * par ChildActionMenuController pour le glisser depuis une bulle satellite
85
+ * du diagramme, qui n'a rien de "RECHERCHE" en soi (voir startActionDrag).
86
+ */
87
+ export declare class SearchPanelSynchronizer {
88
+ private deps;
89
+ private searchHoverChildNode;
90
+ constructor(deps: SearchPanelSynchronizerDeps);
91
+ searchHandleComposanteClick(componentIndex: number): void;
92
+ searchNavigateToComponent(componentIndex: number): void;
93
+ searchNavigateToOdd(componentIndex: number, oddId: string): void;
94
+ searchHandleOddArcClick(componentIndex: number, oddId: string): void;
95
+ searchHighlightOdd(componentIndex: number, oddId: string): void;
96
+ searchPreviewHover(target: {
97
+ type: string;
98
+ componentIndex: number;
99
+ oddId?: string;
100
+ cuttingIndex?: number;
101
+ actionId?: string;
102
+ } | null): void;
103
+ searchHandleCuttingClick(componentIndex: number, oddId: string, cuttingIndex: number): void;
104
+ searchNavigateToCutting(componentIndex: number, oddId: string, cuttingIndex: number, forceOpen?: boolean): void;
105
+ searchNavigateToAction(componentIndex: number, oddId: string, cuttingIndex: number, actionId: string): void;
106
+ restoreActionDiagramState(componentIndex: number, oddId: string, cuttingIndex: number, actionId: string): void;
107
+ startSearchActionDrag(componentIndex: number, oddId: string, cuttingIndex: number, actionId: string, label: string, startEvent: PointerEvent, sourceEl: Element, onDragIntentDetected?: () => void): void;
108
+ startSearchKeyEventDrag(componentIndex: number, keyEventId: string, label: string, startEvent: PointerEvent, sourceEl: Element, onDragIntentDetected?: () => void): void;
109
+ /**
110
+ * Cœur partagé du glisser-déposer vers la pile — entièrement générique
111
+ * (ne connaît ni action ni Événement Clé), utilisé par startSearchActionDrag
112
+ * (hiérarchie RECHERCHE), par ChildActionMenuController (bulle satellite du
113
+ * diagramme) et par CoreEventMenuController (bulle Événement Clé du cercle
114
+ * central) : chaque appelant fournit l'icône du fantôme de glisser et un
115
+ * `onDrop` qui sait construire l'item de pile approprié. Retourne `cleanup`
116
+ * comme poignée d'annulation, pour permettre à un appelant de stopper
117
+ * proprement un glisser en cours (ex. fermeture du menu radial en plein
118
+ * glisser — les écouteurs pointermove/pointerup vivent sur `window`, pas
119
+ * sur l'élément source, donc le retirer du DOM ne suffit pas à arrêter
120
+ * le glisser).
121
+ */
122
+ startActionDrag(iconUrl: string, startEvent: PointerEvent, sourceEl: Element, onDrop: (insertAtVisibleIndex: number | null, entryOrigin: Point) => void, onDragIntentDetected?: () => void): () => void;
123
+ private clearSearchHoverChild;
124
+ }
125
+ export {};
@@ -0,0 +1,50 @@
1
+ import { IYinYangView } from "../../../interfaces/IYinYangView";
2
+ import { YinYangControllerState } from "../state/YinYangControllerState";
3
+ import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
4
+ type ControllerSettingsApplierDeps = {
5
+ state: YinYangControllerState;
6
+ view: IYinYangView;
7
+ hasChildrenControllers: () => boolean;
8
+ getOrbitData: () => ChildrenOrbitEntry[];
9
+ updateContextLabels: (orbitData: ChildrenOrbitEntry[]) => void;
10
+ updateChildActionMenu: (orbitData: ChildrenOrbitEntry[]) => void;
11
+ updateCoreEventMenu: () => void;
12
+ applyChildrenFitScale: () => void;
13
+ clearForceFieldComputationState: () => void;
14
+ renderOppositeChildrenForceField: () => void;
15
+ };
16
+ export declare class ControllerSettingsApplier {
17
+ private deps;
18
+ constructor(deps: ControllerSettingsApplierDeps);
19
+ setRandomForceFieldCount(count: number): void;
20
+ setActionDeltaLabelsVisible(isVisible: boolean): void;
21
+ setChildrenContextLabelsVisible(isVisible: boolean): void;
22
+ setLabelsFontScale(scale: number): void;
23
+ setLabelsTextShadowEnabled(isEnabled: boolean): void;
24
+ setChildLabelPlacement(position: "top" | "bottom"): void;
25
+ setComponentLabelFontScale(scale: number): void;
26
+ setChildStateDeltaFontScale(scale: number): void;
27
+ setChildStateDeltaOffset(offset: number): void;
28
+ setChildStateDeltaBoxScale(scale: number): void;
29
+ setOddLabelFontScale(scale: number): void;
30
+ setComponentLegendLabelFontScale(scale: number): void;
31
+ setLegendLabelsBgEnabled(enabled: boolean): void;
32
+ setDisplayEllipsisForShortLabels(enabled: boolean): void;
33
+ setOddContextLabelsVisible(isVisible: boolean): void;
34
+ setAllLabelsVisible(isVisible: boolean): void;
35
+ setOddLabelsCompact(compact: boolean): void;
36
+ setChildActionMenuItemDistance(distance: number): void;
37
+ setChildActionMenuItemScale(scale: number): void;
38
+ setCoreEventMenuDistanceOffset(offset: number): void;
39
+ setCoreEventMenuItemScale(scale: number): void;
40
+ setChildActionIconFontScale(scale: number): void;
41
+ setCoreEventIconFontScale(scale: number): void;
42
+ setChildLabelMaxLines(lines: number): void;
43
+ setOddLabelMaxLines(lines: number): void;
44
+ setFacetteLabelFontScale(scale: number): void;
45
+ setFacetteLabelSuffixVisible(isVisible: boolean): void;
46
+ setLabelShortMaxChars(chars: number): void;
47
+ private clamp;
48
+ private clampInt;
49
+ }
50
+ export {};