@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.
- package/README.md +105 -0
- package/dist/bundle.js +2 -1
- package/dist/bundle.js.LICENSE.txt +1 -0
- package/dist/types/adapters/yinYangAdapter.d.ts +10 -0
- package/dist/types/animations/AnimationsMngr.d.ts +7 -19
- package/dist/types/api-film.d.ts +22 -0
- package/dist/types/api.d.ts +48 -0
- package/dist/types/benchmark/runner.d.ts +5 -0
- package/dist/types/benchmark/scenarios.d.ts +118 -0
- package/dist/types/components/action-image/ActionImageModal.d.ts +42 -0
- package/dist/types/components/controller/YinYangController.d.ts +946 -18
- package/dist/types/components/controller/action-stack/ActionStackController.d.ts +149 -0
- package/dist/types/components/controller/action-stack/ActionStackDragHandler.d.ts +111 -0
- package/dist/types/components/controller/action-stack/ActionStackManager.d.ts +118 -0
- package/dist/types/components/controller/action-stack/ActionStackState.d.ts +169 -0
- package/dist/types/components/controller/actions/ActionProjectionService.d.ts +73 -0
- package/dist/types/components/controller/actions/ChildActionMenuController.d.ts +83 -0
- package/dist/types/components/controller/actions/CoreEventMenuController.d.ts +90 -0
- package/dist/types/components/controller/actions/radialItemMenu.d.ts +117 -0
- package/dist/types/components/controller/children/ChildInteractionController.d.ts +38 -0
- package/dist/types/components/controller/children/ChildrenOrbitService.d.ts +14 -0
- package/dist/types/components/controller/force-field/EventFieldLifecycleController.d.ts +104 -0
- package/dist/types/components/controller/force-field/EventFieldRenderer.d.ts +86 -0
- package/dist/types/components/controller/force-field/ForceFieldComputationService.d.ts +50 -0
- package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +639 -0
- package/dist/types/components/controller/force-field/ForceFieldLifecycleController.d.ts +53 -0
- package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +67 -0
- package/dist/types/components/controller/force-field/types.d.ts +42 -0
- package/dist/types/components/controller/labels/ChildScoresDeltaRenderer.d.ts +33 -0
- package/dist/types/components/controller/labels/ContextLabelsRenderer.d.ts +155 -0
- package/dist/types/components/controller/labels/WeightPreviewRingRenderer.d.ts +61 -0
- package/dist/types/components/controller/odd/ChildrenOrbitManager.d.ts +25 -0
- package/dist/types/components/controller/odd/OddViewManager.d.ts +44 -0
- package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +125 -0
- package/dist/types/components/controller/settings/ControllerSettingsApplier.d.ts +50 -0
- package/dist/types/components/controller/state/BlockingAnimationTracker.d.ts +17 -0
- package/dist/types/components/controller/state/YinYangControllerState.d.ts +176 -0
- package/dist/types/components/controller/utils/actionStackMath.d.ts +13 -0
- package/dist/types/components/controller/utils/actionStackReorder.d.ts +7 -0
- package/dist/types/components/controller/utils/childrenOrbit.d.ts +18 -0
- package/dist/types/components/controller/utils/cuttingLabels.d.ts +9 -0
- package/dist/types/components/controller/utils/eventFieldStyle.d.ts +13 -0
- package/dist/types/components/controller/utils/eventFieldTargets.d.ts +47 -0
- package/dist/types/components/controller/utils/forceFieldMetadata.d.ts +4 -0
- package/dist/types/components/controller/utils/forceFieldPresentation.d.ts +9 -0
- package/dist/types/components/controller/utils/forceFieldStyle.d.ts +10 -0
- package/dist/types/components/controller/utils/labelGeometry.d.ts +5 -0
- package/dist/types/components/controller/utils/oddCutting.d.ts +2 -0
- package/dist/types/components/controller/utils/svgCoordinates.d.ts +9 -0
- package/dist/types/components/controller/utils/svgTransform.d.ts +5 -0
- package/dist/types/components/controller/utils/textLayout.d.ts +2 -0
- package/dist/types/components/controls/VizControlsPanel.d.ts +14 -0
- package/dist/types/components/factory/YinYangAppFactory.d.ts +4 -6
- package/dist/types/components/model/YinYangModel.d.ts +4 -30
- package/dist/types/components/panel/DiagramPanelBridge.d.ts +34 -0
- package/dist/types/components/panel/PanelManager.d.ts +150 -0
- package/dist/types/components/search/GlobalSearchController.d.ts +396 -0
- package/dist/types/components/stack-nav/StackNavOverlay.d.ts +82 -0
- package/dist/types/components/view/BorderDrawer.d.ts +203 -13
- package/dist/types/components/view/SpikeDrawer.d.ts +37 -31
- package/dist/types/components/view/ViewInitializer.d.ts +438 -2
- package/dist/types/components/view/YinYangDrawer.d.ts +414 -11
- package/dist/types/config/animationConfig.d.ts +37 -0
- package/dist/types/config/deltaColors.d.ts +64 -0
- package/dist/types/config/labelStyleConfig.d.ts +50 -0
- package/dist/types/data/OddCategoryColors.d.ts +12 -2
- package/dist/types/data/adverse-action-planner.d.ts +51 -0
- package/dist/types/data/adverse-action-planner.test.d.ts +1 -0
- package/dist/types/data/amplifier-engine.d.ts +107 -0
- package/dist/types/data/amplifier-engine.test.d.ts +1 -0
- package/dist/types/data/combo-engine.d.ts +94 -0
- package/dist/types/data/combo-engine.test.d.ts +1 -0
- package/dist/types/data/odd_generic_descriptions.d.ts +4 -0
- package/dist/types/data/odd_labels.d.ts +5 -0
- package/dist/types/data/yasuni_actions.d.ts +47 -0
- package/dist/types/data/yasuni_adverse_actions.d.ts +2 -0
- package/dist/types/data/yasuni_adverse_key_events.d.ts +2 -0
- package/dist/types/data/yasuni_cause.d.ts +33 -0
- package/dist/types/data/yasuni_graph.d.ts +22 -0
- package/dist/types/data/yasuni_key_events.d.ts +61 -0
- package/dist/types/data/yasuni_propagation_layers.d.ts +3 -0
- package/dist/types/interfaces/IActions.d.ts +1 -0
- package/dist/types/interfaces/ICauseGraph.d.ts +9 -0
- package/dist/types/interfaces/ICauseModel.d.ts +33 -0
- package/dist/types/interfaces/IGraphicsStrategy.d.ts +9 -5
- package/dist/types/interfaces/IPropagationLayers.d.ts +27 -0
- package/dist/types/interfaces/IViewData.d.ts +12 -0
- package/dist/types/interfaces/IYinYangAppFactory.d.ts +3 -3
- package/dist/types/interfaces/IYinYangController.d.ts +301 -6
- package/dist/types/interfaces/IYinYangGeometry.d.ts +43 -0
- package/dist/types/interfaces/IYinYangInternalModel.d.ts +34 -0
- package/dist/types/interfaces/IYinYangModel.d.ts +3 -11
- package/dist/types/main.d.ts +9 -0
- package/dist/types/utils/actionImages.d.ts +14 -0
- package/dist/types/utils/actionPropagation.d.ts +74 -0
- package/dist/types/utils/appMode.d.ts +5 -0
- package/dist/types/utils/causeGraph.d.ts +6 -0
- package/dist/types/utils/causeMetrics.d.ts +26 -0
- package/dist/types/utils/chainCardHeight.d.ts +27 -0
- package/dist/types/utils/d3/D3Element.d.ts +2 -2
- package/dist/types/utils/d3/D3GraphicsStrategy.d.ts +21 -4
- package/dist/types/utils/deltaChips.d.ts +15 -0
- package/dist/types/utils/deltaLabels.d.ts +54 -0
- package/dist/types/utils/facetteImages.d.ts +1 -0
- package/dist/types/utils/geometryUtils.d.ts +0 -1
- package/dist/types/utils/hierBadge.d.ts +44 -0
- package/dist/types/utils/idleSphereImage.d.ts +8 -0
- package/dist/types/utils/keyEventImages.d.ts +41 -0
- package/dist/types/utils/oddLegend.d.ts +30 -0
- package/dist/types/utils/positionalEfficiency.d.ts +16 -0
- package/dist/types/utils/yinYangWatermark.d.ts +29 -0
- package/package.json +27 -12
- package/dist/index.html +0 -1
- package/dist/types/data/coupe_rase_Orangs-outans/data_Kalimantan.d.ts +0 -3
- package/dist/types/data/coupe_rase_Orangs-outans/data_PT_Mayawana_Persada.d.ts +0 -3
- package/dist/types/data/data_institu_bancaire.d.ts +0 -3
- package/dist/types/interfaces/IOddItem.d.ts +0 -6
- package/dist/types/script.d.ts +0 -13
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { IYinYangController } from "../../../interfaces/IYinYangController";
|
|
2
|
+
import { IYinYangView } from "../../../interfaces/IYinYangView";
|
|
3
|
+
import { type ActionDefinition } from "../../../data/yasuni_actions";
|
|
4
|
+
import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
|
|
5
|
+
import { type Point } from "./radialItemMenu";
|
|
6
|
+
type ChildActionMenuContext = {
|
|
7
|
+
orbitData: ChildrenOrbitEntry[];
|
|
8
|
+
activeActionMenuChildKey: string | null;
|
|
9
|
+
activeActionMenuActionId: string | null;
|
|
10
|
+
childActionMenuItemDistance: number;
|
|
11
|
+
childActionMenuItemScale: number;
|
|
12
|
+
childActionIconFontScale: number;
|
|
13
|
+
/** Actions filtrées pour le cutting actif (depuis yasuniCause + actionMap). */
|
|
14
|
+
actionsForActiveChild: ActionDefinition[];
|
|
15
|
+
};
|
|
16
|
+
export declare class ChildActionMenuController {
|
|
17
|
+
private readonly view;
|
|
18
|
+
private readonly getChildRenderedCenter;
|
|
19
|
+
private readonly refreshActionStackVisual;
|
|
20
|
+
/** Aperçu — 1er clic sur une action : affiche sa carte, ne joue rien. */
|
|
21
|
+
private readonly activateActionFromChild;
|
|
22
|
+
/** Validation — 2e clic sur l'action déjà en aperçu : l'ajoute à la pile. */
|
|
23
|
+
private readonly validateActionSelection;
|
|
24
|
+
/** Glisser une bulle vers une position précise de la pile — cœur partagé
|
|
25
|
+
* avec le glisser-déposer depuis la hiérarchie RECHERCHE et depuis le
|
|
26
|
+
* menu des Événements Clés (voir SearchPanelSynchronizer.startActionDrag,
|
|
27
|
+
* entièrement générique). Retourne une poignée d'annulation, conservée
|
|
28
|
+
* dans activeDragCancel. */
|
|
29
|
+
private readonly startActionDrag;
|
|
30
|
+
private childActionMenuGroup;
|
|
31
|
+
/** Groupe séparé pour les traits satellite → bulle, repositionné à chaque
|
|
32
|
+
* update() juste devant children-group (voir ensureLineLayer) pour
|
|
33
|
+
* qu'ils s'affichent derrière les satellites plutôt que par-dessus —
|
|
34
|
+
* même technique que CoreEventMenuController.coreEventLineLayer. */
|
|
35
|
+
private childActionLineLayer;
|
|
36
|
+
private lastChildActionMenuSourceCenter;
|
|
37
|
+
/** Poignée d'annulation du glisser-déposer en cours (voir startActionDrag),
|
|
38
|
+
* ou null si aucun glisser n'est en cours. */
|
|
39
|
+
private activeDragCancel;
|
|
40
|
+
/** Bulle survolée — sert uniquement à allumer l'impulsion de son lien
|
|
41
|
+
* (voir linkStyleGetter) ; l'aperçu reste porté par le contexte. */
|
|
42
|
+
private hoveredActionId;
|
|
43
|
+
/** Résolveur de style des liens, reconstruit à chaque update() (il capture
|
|
44
|
+
* le contexte courant) et rejoué au survol : rallumer une impulsion ne
|
|
45
|
+
* doit pas relancer la chorégraphie d'ouverture. */
|
|
46
|
+
private linkStyleGetter;
|
|
47
|
+
constructor(view: IYinYangView, getChildRenderedCenter: (childController: IYinYangController) => Point | null, refreshActionStackVisual: () => void,
|
|
48
|
+
/** Aperçu — 1er clic sur une action : affiche sa carte, ne joue rien. */
|
|
49
|
+
activateActionFromChild: (childController: IYinYangController, actionId: string, label?: string) => void,
|
|
50
|
+
/** Validation — 2e clic sur l'action déjà en aperçu : l'ajoute à la pile. */
|
|
51
|
+
validateActionSelection: (childController: IYinYangController, actionId: string, label: string, insertAtVisibleIndex?: number | null, entryOrigin?: Point) => void,
|
|
52
|
+
/** Glisser une bulle vers une position précise de la pile — cœur partagé
|
|
53
|
+
* avec le glisser-déposer depuis la hiérarchie RECHERCHE et depuis le
|
|
54
|
+
* menu des Événements Clés (voir SearchPanelSynchronizer.startActionDrag,
|
|
55
|
+
* entièrement générique). Retourne une poignée d'annulation, conservée
|
|
56
|
+
* dans activeDragCancel. */
|
|
57
|
+
startActionDrag: (iconUrl: string, startEvent: PointerEvent, sourceEl: Element, onDrop: (insertAtVisibleIndex: number | null, entryOrigin: Point) => void) => () => void);
|
|
58
|
+
/** Callback déclenché quand la souris entre/sort d'un cercle d'action dans le menu radial. */
|
|
59
|
+
private _onActionHoverCb?;
|
|
60
|
+
setOnActionHover(cb: (actionId: string | null, activeChildKey: string) => void): void;
|
|
61
|
+
/**
|
|
62
|
+
* Applique un highlight de survol sur le cercle d'action identifié, ou le retire si null.
|
|
63
|
+
* Le highlight est posé sur le <g> wrapper (pas sur le <circle>) pour éviter le conflit
|
|
64
|
+
* avec le filtre inline déjà présent sur le cercle.
|
|
65
|
+
*/
|
|
66
|
+
highlightActionById(actionId: string | null): void;
|
|
67
|
+
/** Restyle les seuls liens (impulsion allumée/éteinte), sans toucher à leur
|
|
68
|
+
* géométrie : le survol ne doit rien réanimer. */
|
|
69
|
+
private setHoveredAction;
|
|
70
|
+
retractAndDispose(): void;
|
|
71
|
+
clearImmediately(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Starts the fold-out animation on the visible action buttons, then removes
|
|
74
|
+
* the group once every item has finished animating. Nulls the group
|
|
75
|
+
* reference immediately so that any synchronous clearImmediately() call
|
|
76
|
+
* that follows is a no-op and won't cancel the in-flight transition.
|
|
77
|
+
*/
|
|
78
|
+
animateClose(): void;
|
|
79
|
+
update(context: ChildActionMenuContext): void;
|
|
80
|
+
private ensureChildActionMenuGroup;
|
|
81
|
+
private ensureLineLayer;
|
|
82
|
+
}
|
|
83
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { IYinYangView } from "../../../interfaces/IYinYangView";
|
|
2
|
+
import type { KeyEventDefinition } from "../../../data/yasuni_key_events";
|
|
3
|
+
import { type Point } from "./radialItemMenu";
|
|
4
|
+
type CoreEventMenuContext = {
|
|
5
|
+
/** null/false ferme le menu (même logique que activeActionMenuChildKey côté satellite). */
|
|
6
|
+
isOpen: boolean;
|
|
7
|
+
keyEventsForActiveFacette: KeyEventDefinition[];
|
|
8
|
+
/** Id de l'événement actuellement en aperçu (carte affichée), ou null. */
|
|
9
|
+
activeKeyEventId: string | null;
|
|
10
|
+
/** Même valeur que le contrôle "Distance boutons" du groupe "Grappe Actions"
|
|
11
|
+
* (state.menu.itemDistance) — pas de contrôle dédié : voir le calcul de
|
|
12
|
+
* offsetDistance plus bas, qui la réutilise telle quelle. */
|
|
13
|
+
childActionMenuItemDistance: number;
|
|
14
|
+
/** Distance centre du cercle central → satellites de la facette active
|
|
15
|
+
* (moyenne des rayons d'orbite réels, cf. buildChildrenOrbitData) — le
|
|
16
|
+
* "connu" dont dérive offsetDistance plus bas. */
|
|
17
|
+
childrenOrbitRadius: number;
|
|
18
|
+
/** Taille des bulles — contrôle dédié "Taille boutons" du groupe
|
|
19
|
+
* "Événements clés" (state.menu.coreEventMenuItemScale) : les Événements
|
|
20
|
+
* Clés se dimensionnent indépendamment des boutons d'action des
|
|
21
|
+
* satellites. */
|
|
22
|
+
coreEventMenuItemScale: number;
|
|
23
|
+
coreEventIconFontScale: number;
|
|
24
|
+
/** Ajustement fin (px) de la distance des boutons, de part et d'autre de
|
|
25
|
+
* la longueur auto-calculée — contrôle "Distance boutons" du groupe
|
|
26
|
+
* "Événements clés", voir state.menu.coreEventMenuDistanceOffset. */
|
|
27
|
+
coreEventMenuDistanceOffset: number;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Menu radial des Événements Clés, déclenché par un clic sur le cercle
|
|
31
|
+
* central (yin-yang) de la facette active — même langage visuel et même
|
|
32
|
+
* sémantique de clic que ChildActionMenuController (bulles + icône,
|
|
33
|
+
* chorégraphie D3 en éventail, 1er clic = aperçu / 2e clic sur l'item déjà
|
|
34
|
+
* actif = validation — factorisées dans radialItemMenu.ts), mais ancré sur
|
|
35
|
+
* le centre fixe de la facette plutôt que sur un satellite, et déployé à
|
|
36
|
+
* angle égal sur 360° plutôt que sur un axe source.
|
|
37
|
+
*/
|
|
38
|
+
export declare class CoreEventMenuController {
|
|
39
|
+
private readonly view;
|
|
40
|
+
/** Aperçu — 1er clic sur un événement : affiche sa carte, ne joue rien. */
|
|
41
|
+
private readonly previewKeyEvent;
|
|
42
|
+
/** Validation — 2e clic sur l'événement déjà en aperçu : l'ajoute à la pile
|
|
43
|
+
* (au sommet par défaut, ou à insertAtVisibleIndex si fourni par un
|
|
44
|
+
* glisser-déposer — voir startKeyEventDrag). */
|
|
45
|
+
private readonly validateKeyEventSelection;
|
|
46
|
+
/** Glisser une bulle vers une position précise de la pile — même cœur
|
|
47
|
+
* partagé que ChildActionMenuController.startActionDrag (voir
|
|
48
|
+
* SearchPanelSynchronizer.startActionDrag, entièrement générique).
|
|
49
|
+
* Retourne une poignée d'annulation, conservée dans activeDragCancel. */
|
|
50
|
+
private readonly startKeyEventDrag;
|
|
51
|
+
private coreEventMenuGroup;
|
|
52
|
+
/** Groupe séparé pour les traits centre → bulle, abaissé au fond du
|
|
53
|
+
* z-order (voir ensureLineLayer) pour qu'ils s'affichent derrière le
|
|
54
|
+
* disque central et les satellites plutôt que par-dessus. */
|
|
55
|
+
private coreEventLineLayer;
|
|
56
|
+
/** Poignée d'annulation du glisser-déposer en cours (voir startKeyEventDrag),
|
|
57
|
+
* ou null si aucun glisser n'est en cours — même rôle que
|
|
58
|
+
* ChildActionMenuController.activeDragCancel. */
|
|
59
|
+
private activeDragCancel;
|
|
60
|
+
/** Bulle actuellement survolée — sert uniquement à allumer l'impulsion de
|
|
61
|
+
* son lien (voir linkStyleGetter) ; l'état d'aperçu, lui, reste porté par
|
|
62
|
+
* context.activeKeyEventId. */
|
|
63
|
+
private hoveredKeyEventId;
|
|
64
|
+
/** Résolveur de style des liens, reconstruit à chaque update() (il capture
|
|
65
|
+
* le contexte courant) et rejoué tel quel au survol : rallumer une
|
|
66
|
+
* impulsion ne doit pas relancer toute la chorégraphie. */
|
|
67
|
+
private linkStyleGetter;
|
|
68
|
+
constructor(view: IYinYangView,
|
|
69
|
+
/** Aperçu — 1er clic sur un événement : affiche sa carte, ne joue rien. */
|
|
70
|
+
previewKeyEvent: (keyEvent: KeyEventDefinition) => void,
|
|
71
|
+
/** Validation — 2e clic sur l'événement déjà en aperçu : l'ajoute à la pile
|
|
72
|
+
* (au sommet par défaut, ou à insertAtVisibleIndex si fourni par un
|
|
73
|
+
* glisser-déposer — voir startKeyEventDrag). */
|
|
74
|
+
validateKeyEventSelection: (keyEvent: KeyEventDefinition, insertAtVisibleIndex?: number | null, entryOrigin?: Point) => void,
|
|
75
|
+
/** Glisser une bulle vers une position précise de la pile — même cœur
|
|
76
|
+
* partagé que ChildActionMenuController.startActionDrag (voir
|
|
77
|
+
* SearchPanelSynchronizer.startActionDrag, entièrement générique).
|
|
78
|
+
* Retourne une poignée d'annulation, conservée dans activeDragCancel. */
|
|
79
|
+
startKeyEventDrag: (iconUrl: string, startEvent: PointerEvent, sourceEl: Element, onDrop: (insertAtVisibleIndex: number | null, entryOrigin: Point) => void) => () => void);
|
|
80
|
+
private _onHoverCb?;
|
|
81
|
+
setOnHover(cb: (keyEventId: string | null) => void): void;
|
|
82
|
+
clearImmediately(): void;
|
|
83
|
+
update(context: CoreEventMenuContext): void;
|
|
84
|
+
/** Restyle les seuls liens (impulsion allumée/éteinte) sans toucher à leur
|
|
85
|
+
* géométrie : le survol ne doit rien réanimer. */
|
|
86
|
+
private setHoveredKeyEvent;
|
|
87
|
+
private ensureGroup;
|
|
88
|
+
private ensureLineLayer;
|
|
89
|
+
}
|
|
90
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as d3 from "d3";
|
|
2
|
+
export type Point = {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
};
|
|
6
|
+
export type FanLayoutMode = "arc" | "full-circle";
|
|
7
|
+
export type RadialMenuItemPosition<T> = {
|
|
8
|
+
uniqueKey: string;
|
|
9
|
+
id: string;
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
r: number;
|
|
13
|
+
item: T;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Calcule la position en éventail de chaque item autour d'un centre.
|
|
17
|
+
* - mode "arc" : réparti sur ±maxAngularOffset autour de `axis` (menu
|
|
18
|
+
* satellite — doit respecter un axe "depuis la source").
|
|
19
|
+
* - mode "full-circle" : réparti à angle égal sur les 360° (menu du
|
|
20
|
+
* cercle central — pas d'axe source à respecter, maximise l'écart
|
|
21
|
+
* angulaire entre bulles).
|
|
22
|
+
*/
|
|
23
|
+
export declare function computeFanPositions<T extends {
|
|
24
|
+
id: string;
|
|
25
|
+
}>(items: T[], opts: {
|
|
26
|
+
mode: FanLayoutMode;
|
|
27
|
+
center: Point;
|
|
28
|
+
axis: number;
|
|
29
|
+
maxAngularOffset?: number;
|
|
30
|
+
offsetDistance: number;
|
|
31
|
+
itemRadius: number;
|
|
32
|
+
keyPrefix: string;
|
|
33
|
+
}): RadialMenuItemPosition<T>[];
|
|
34
|
+
/**
|
|
35
|
+
* Referme et retire toutes les bulles d'un menu radial (repli en
|
|
36
|
+
* éventail), utilisé à la fois quand update() ne reçoit plus de
|
|
37
|
+
* contexte actif et par les fermetures explicites (animateClose).
|
|
38
|
+
*/
|
|
39
|
+
export declare function closeAllRadialItems(groupNode: SVGGElement, dataRole: string, onAllClosed?: () => void): void;
|
|
40
|
+
/**
|
|
41
|
+
* Chorégraphie D3 commune (data join, transition de sortie, création
|
|
42
|
+
* ligne+cercle+image à l'entrée, transition d'ouverture) — le style
|
|
43
|
+
* visuel par item (couleurs, tailles selon état actif) reste à la
|
|
44
|
+
* charge de l'appelant via un `.each()` sur la sélection retournée,
|
|
45
|
+
* les deux menus ayant des palettes distinctes.
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderRadialItemsChoreography<T>(params: {
|
|
48
|
+
groupNode: SVGGElement;
|
|
49
|
+
dataRole: string;
|
|
50
|
+
positions: RadialMenuItemPosition<T>[];
|
|
51
|
+
exitAnimationCenter: Point;
|
|
52
|
+
enterCenter: Point;
|
|
53
|
+
getIconUrl: (id: string) => string;
|
|
54
|
+
/** Décor optionnel inséré entre la plaque (cercle) et le pictogramme, sur
|
|
55
|
+
* la seule sélection enter() — c'est par là que le menu des Événements
|
|
56
|
+
* Clés glisse son filigrane Yin/Yang, que le menu des actions n'a pas.
|
|
57
|
+
* Appelé à cet endroit précis pour que le z-order (plaque → décor →
|
|
58
|
+
* icône) tombe juste sans réordonnancement. */
|
|
59
|
+
decorateItemEnter?: (enter: d3.Selection<SVGGElement, RadialMenuItemPosition<T>, SVGGElement, unknown>) => void;
|
|
60
|
+
onItemClick: (item: T) => void;
|
|
61
|
+
onItemHoverEnter?: (item: T) => void;
|
|
62
|
+
onItemHoverLeave?: (item: T) => void;
|
|
63
|
+
}): d3.Selection<SVGGElement, RadialMenuItemPosition<T>, SVGGElement, unknown>;
|
|
64
|
+
/** Style d'un lien, résolu par l'appelant depuis son propre état (les deux
|
|
65
|
+
* menus ont des palettes distinctes — ambre pour les Événements Clés,
|
|
66
|
+
* vert/cyan pour les actions — mais la même mise en scène). */
|
|
67
|
+
export type RadialItemLinkStyle = {
|
|
68
|
+
/** Teinte du faisceau. L'alpha du rgba est celui de l'extrémité BULLE :
|
|
69
|
+
* le dégradé se charge de le ramener à zéro côté parent. */
|
|
70
|
+
color: string;
|
|
71
|
+
/** Item en aperçu : faisceau plus large et plus net. */
|
|
72
|
+
isActive?: boolean;
|
|
73
|
+
/** Cœur en pointillés (Événement Clé verrouillé). */
|
|
74
|
+
dashed?: boolean;
|
|
75
|
+
/** Impulsion qui remonte le lien — actif ou survolé uniquement. */
|
|
76
|
+
pulse?: boolean;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Applique le style (teinte, épaisseur, pointillés, impulsion) sur les liens
|
|
80
|
+
* déjà en place, SANS toucher à leur géométrie ni relancer d'animation
|
|
81
|
+
* d'ouverture. Séparé du rendu pour que le survol d'une bulle puisse
|
|
82
|
+
* rallumer l'impulsion de son seul lien à coût nul.
|
|
83
|
+
*/
|
|
84
|
+
export declare function styleRadialItemLinks<T extends {
|
|
85
|
+
id: string;
|
|
86
|
+
}>(groupNode: SVGGElement | null, dataRole: string, getStyle: (d: RadialMenuItemPosition<T>) => RadialItemLinkStyle): void;
|
|
87
|
+
/**
|
|
88
|
+
* Chorégraphie D3 des liens parent → item, rendus dans un groupe SÉPARÉ de
|
|
89
|
+
* celui des bulles (voir CoreEventMenuController : ce groupe est glissé plus
|
|
90
|
+
* tôt dans le z-order pour passer derrière les satellites et le disque
|
|
91
|
+
* central, alors que les bulles restent devant dans leur propre groupe).
|
|
92
|
+
* Anime directement x2/y2 des lignes : un lien entrant grandit depuis le bord
|
|
93
|
+
* du parent vers l'item, un lien sortant s'y rétracte puis disparaît — même
|
|
94
|
+
* easing/cascade que renderRadialItemsChoreography pour rester visuellement
|
|
95
|
+
* synchronisé avec les bulles. `positions: []` ferme tous les liens existants
|
|
96
|
+
* (repli complet), sans qu'un appelant ait besoin d'une fonction dédiée.
|
|
97
|
+
*/
|
|
98
|
+
export declare function renderRadialItemLinks<T extends {
|
|
99
|
+
id: string;
|
|
100
|
+
}>(params: {
|
|
101
|
+
groupNode: SVGGElement;
|
|
102
|
+
dataRole: string;
|
|
103
|
+
positions: RadialMenuItemPosition<T>[];
|
|
104
|
+
center: Point;
|
|
105
|
+
/** Rayon du disque parent : le faisceau démarre à son bord. 0 = au centre. */
|
|
106
|
+
startRadius?: number;
|
|
107
|
+
getStyle?: (d: RadialMenuItemPosition<T>) => RadialItemLinkStyle;
|
|
108
|
+
}): void;
|
|
109
|
+
/**
|
|
110
|
+
* Sémantique de clic partagée par les deux menus radiaux : un premier
|
|
111
|
+
* clic sur un item prévisualise (affiche sa carte, ne joue rien) ; un
|
|
112
|
+
* second clic sur ce même item déjà actif valide (l'ajoute à la
|
|
113
|
+
* pile). Cliquer un autre item pendant qu'un aperçu est actif bascule
|
|
114
|
+
* l'aperçu sans valider — c'est simplement le cas "isAlreadyActive
|
|
115
|
+
* === false" pour ce nouvel item.
|
|
116
|
+
*/
|
|
117
|
+
export declare function handleRadialItemClick(isAlreadyActive: boolean, onPreview: () => void, onValidate: () => void): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { IYinYangController } from "../../../interfaces/IYinYangController";
|
|
2
|
+
import { IYinYangView } from "../../../interfaces/IYinYangView";
|
|
3
|
+
import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
|
|
4
|
+
type ChildOddMeta = {
|
|
5
|
+
oddId: string;
|
|
6
|
+
score: number;
|
|
7
|
+
cuttingIndex: number;
|
|
8
|
+
};
|
|
9
|
+
type ChildInteractionControllerDeps = {
|
|
10
|
+
view: IYinYangView;
|
|
11
|
+
getCurrentComponent: () => YinYangInternalModel["components"][number] | null;
|
|
12
|
+
getActiveChildKey: () => string | null;
|
|
13
|
+
setActiveChildKey: (childKey: string | null) => void;
|
|
14
|
+
openActionMenuFromChild: (childController: IYinYangController) => void;
|
|
15
|
+
highlightOddInChildren: (oddId: string | null) => void;
|
|
16
|
+
cancelOddHighlight: () => void;
|
|
17
|
+
syncGhostTensionFromAction: () => void;
|
|
18
|
+
renderGhostDetailsForActiveAction: () => void;
|
|
19
|
+
onUserCuttingClicked?: (childController: IYinYangController) => void;
|
|
20
|
+
/** Appelé quand la souris entre/sort d'un satellite (null = sortie). */
|
|
21
|
+
onChildHover?: (oddId: string | null, cuttingIndex?: number) => void;
|
|
22
|
+
};
|
|
23
|
+
export declare class ChildInteractionController {
|
|
24
|
+
private deps;
|
|
25
|
+
constructor(deps: ChildInteractionControllerDeps);
|
|
26
|
+
setChildrenHiddenState(childControllers: IYinYangController[], hidden: boolean): void;
|
|
27
|
+
attachChildToggleHandler(childController: IYinYangController, childOddMap: Map<string, ChildOddMeta>): void;
|
|
28
|
+
attachChildHoverHandler(childController: IYinYangController, childOddMap: Map<string, ChildOddMeta>): void;
|
|
29
|
+
attachBackgroundClickHandler(): void;
|
|
30
|
+
enterOddView(oddId: string): void;
|
|
31
|
+
exitOddView(): void;
|
|
32
|
+
setActiveChild(childControllers: IYinYangController[], childKey: string): void;
|
|
33
|
+
clearActiveChild(childControllers: IYinYangController[]): void;
|
|
34
|
+
animateChildren(childControllers: IYinYangController[], show: boolean, onBeforeShow?: () => void, onBeforeHide?: () => void): Promise<void>;
|
|
35
|
+
private applyChildActiveStyle;
|
|
36
|
+
private getChildOffset;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IYinYangController } from "../../../interfaces/IYinYangController";
|
|
2
|
+
import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
|
|
3
|
+
export declare class ChildrenOrbitService {
|
|
4
|
+
buildOrbitData(params: {
|
|
5
|
+
parentX: number;
|
|
6
|
+
parentY: number;
|
|
7
|
+
childControllers: IYinYangController[];
|
|
8
|
+
radiusScale: number;
|
|
9
|
+
}): ChildrenOrbitEntry[];
|
|
10
|
+
computeTranslation(orbitEntry: ChildrenOrbitEntry, angleOffset: number): {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
|
|
2
|
+
import { IYinYangController } from "../../../interfaces/IYinYangController";
|
|
3
|
+
import { ActionStackItem } from "../action-stack/ActionStackController";
|
|
4
|
+
import { KeyEventDefinition } from "../../../data/yasuni_key_events";
|
|
5
|
+
import { EventFieldRenderer, Point } from "./EventFieldRenderer";
|
|
6
|
+
import { YinYangControllerState } from "../state/YinYangControllerState";
|
|
7
|
+
type ChildOddMeta = {
|
|
8
|
+
oddId: string;
|
|
9
|
+
score: number;
|
|
10
|
+
cuttingIndex: number;
|
|
11
|
+
};
|
|
12
|
+
type EventFieldLifecycleControllerDeps = {
|
|
13
|
+
state: YinYangControllerState;
|
|
14
|
+
childOddMap: Map<string, ChildOddMeta>;
|
|
15
|
+
eventFieldRenderer: EventFieldRenderer;
|
|
16
|
+
/** Événements Clés qui pilotent le champ pour la frame courante — aperçu
|
|
17
|
+
* RECHERCHE (un seul) ou items cochés de la pile en mode STACK (plusieurs
|
|
18
|
+
* possibles), déjà réduits par l'appelant à un jeu qui partage UNE source
|
|
19
|
+
* (voir YinYangController.getEventFieldKeyEvents). */
|
|
20
|
+
getActiveKeyEvents: () => KeyEventDefinition[];
|
|
21
|
+
getCurrentComponentOrUndefined: () => YinYangInternalModel["components"][number] | undefined;
|
|
22
|
+
getActiveItems: () => ActionStackItem[];
|
|
23
|
+
getChildControllers: () => IYinYangController[];
|
|
24
|
+
getGlobalGroupNode: () => SVGGElement | null;
|
|
25
|
+
getChildRenderedCenter: (childController: IYinYangController) => Point | null;
|
|
26
|
+
getComponentBorderTargetPoint: (componentId: string) => Point | null;
|
|
27
|
+
getEventFieldSource: () => {
|
|
28
|
+
center: Point | null;
|
|
29
|
+
radius: number;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Cycle de vie du "Champ d'événement" (souffle cœur → satellites de
|
|
34
|
+
* l'Événement Clé en aperçu ou validé) : calcul des cibles, boucle rAF,
|
|
35
|
+
* délégation au dessin. Miroir de ForceFieldLifecycleController pour le
|
|
36
|
+
* champ de force d'action — même découpage état (YinYangControllerState) /
|
|
37
|
+
* orchestration (ici) / dessin (EventFieldRenderer).
|
|
38
|
+
*/
|
|
39
|
+
export declare class EventFieldLifecycleController {
|
|
40
|
+
private deps;
|
|
41
|
+
private _targetsCacheKey;
|
|
42
|
+
private _targetsCacheResult;
|
|
43
|
+
constructor(deps: EventFieldLifecycleControllerDeps);
|
|
44
|
+
/**
|
|
45
|
+
* Recalcule les cibles du Champ d'événement et démarre/arrête son animation
|
|
46
|
+
* en conséquence. À appeler à chaque aperçu/validation/ouverture-fermeture
|
|
47
|
+
* du menu radial, à chaque toggle de visibilité de la pile ET à chaque
|
|
48
|
+
* bascule d'onglet RECHERCHE/STACK : la portée elle-même ne dépend pas de la
|
|
49
|
+
* pile, mais l'épaisseur du souffle distingue les satellites réellement
|
|
50
|
+
* amplifiés, qui en dépendent — et en mode STACK ce sont les événements
|
|
51
|
+
* cochés de la pile qui décident du champ tout entier.
|
|
52
|
+
*/
|
|
53
|
+
updateEventField(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Recalcule state.eventField.targets pour la frame courante (cache-key
|
|
56
|
+
* gated via getTargets — quasi gratuit quand rien n'a changé) et, s'il n'y
|
|
57
|
+
* a plus rien à montrer, cache le champ. Retourne false dans ce cas (rien
|
|
58
|
+
* à rendre cette frame), true sinon.
|
|
59
|
+
*
|
|
60
|
+
* Appelée aussi bien par updateEventField (points d'entrée explicites :
|
|
61
|
+
* aperçu, toggle pile, fin de switch) que par la boucle rAF de
|
|
62
|
+
* startEventFieldAnimation. Cette dernière en a besoin car
|
|
63
|
+
* currentComponentId peut changer de façon SYNCHRONE bien avant que
|
|
64
|
+
* updateEventField() ne soit rappelé : un clic sur l'arc de facette flippe
|
|
65
|
+
* ViewInitializer.currentComponentIndex dès animateToComponent(), alors
|
|
66
|
+
* que refreshChildrenForComponentSwitch() (qui, lui, rappelle
|
|
67
|
+
* updateEventField pour de vrai) n'arrive qu'~componentSwitchDurationMs
|
|
68
|
+
* plus tard, une fois les satellites de la nouvelle facette créés.
|
|
69
|
+
* getEventFieldSource() (le point de départ) réagit à ce flip dès la frame
|
|
70
|
+
* suivante puisqu'il est relu à chaque frame — sans ce recalcul ici, les
|
|
71
|
+
* CIBLES (donc les points d'arrivée) restaient l'ancien tableau pendant
|
|
72
|
+
* tout le switch : un cordon arc-à-arc incohérent (source déjà "entrant",
|
|
73
|
+
* cible encore l'ancien point distant) jusqu'à la correction tardive.
|
|
74
|
+
*/
|
|
75
|
+
private refreshTargets;
|
|
76
|
+
/** Mémoïse buildEventFieldTargets : coûteux à parcourir (yasuniCause en
|
|
77
|
+
* entier) mais dont les entrées pertinentes ne changent qu'avec la
|
|
78
|
+
* facette, les Événements Clés actifs, ou les items de pile qui les
|
|
79
|
+
* concernent — voir buildTargetsCacheKey, concaténée sur tout le jeu. */
|
|
80
|
+
private getTargets;
|
|
81
|
+
/**
|
|
82
|
+
* Union des portées de plusieurs Événements Clés actifs (pile STACK avec
|
|
83
|
+
* plusieurs événements cochés) : un satellite touché par deux d'entre eux
|
|
84
|
+
* ne reçoit qu'UN cordon — le renderer n'a qu'une source, deux cordons
|
|
85
|
+
* superposés se liraient comme un seul, en plus lumineux. On garde le
|
|
86
|
+
* coefficient le plus fort, celui qui décrit l'amplification réellement
|
|
87
|
+
* subie par ce satellite.
|
|
88
|
+
*/
|
|
89
|
+
private mergeTargets;
|
|
90
|
+
/** Ne dépend que de ce qui peut réellement changer le résultat : la
|
|
91
|
+
* facette courante, la taille du mapping ODD (proxy de changement de
|
|
92
|
+
* facette, même convention que ForceFieldLifecycleController), et — parmi
|
|
93
|
+
* les items de la pile — seulement ceux liés à CET Événement Clé (son
|
|
94
|
+
* propre item, pour la règle de slotIndex, et les actions qu'il cible).
|
|
95
|
+
* Les autres items de la pile n'influencent pas le champ d'événement. */
|
|
96
|
+
private buildTargetsCacheKey;
|
|
97
|
+
/** Résout les cibles courantes en points écran et pousse la frame au
|
|
98
|
+
* renderer — appelé une fois par updateEventField (état) et à chaque
|
|
99
|
+
* frame par startEventFieldAnimation (orbite + pulsation). */
|
|
100
|
+
private updateEventFieldVisual;
|
|
101
|
+
private startEventFieldAnimation;
|
|
102
|
+
private stopEventFieldAnimation;
|
|
103
|
+
}
|
|
104
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export type Point = {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
};
|
|
5
|
+
/** Segment cœur → cible déjà résolu en points écran — la résolution
|
|
6
|
+
* logique (quel satellite, quelle facette) vit dans eventFieldTargets.ts,
|
|
7
|
+
* ce renderer ne fait que dessiner. */
|
|
8
|
+
export type EventFieldRenderSegment = {
|
|
9
|
+
end: Point;
|
|
10
|
+
/** Bonus de score de l'Événement Clé — pilote l'épaisseur du souffle. */
|
|
11
|
+
scoreBonus: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Chorégraphie du "Champ d'événement" : un souffle annulaire. Le cœur du
|
|
15
|
+
* yin/yang (le disque central du lobe de l'orientation courante, pas le
|
|
16
|
+
* centre géométrique du symbole) émet des anneaux concentriques ; chaque
|
|
17
|
+
* anneau allume au passage le segment de cordon qu'il traverse, puis éclate
|
|
18
|
+
* en onde de choc en atteignant le satellite amplifié.
|
|
19
|
+
*
|
|
20
|
+
* Les anneaux sont partagés par toutes les cibles — un seul souffle,
|
|
21
|
+
* plusieurs impacts — ce qui dit visuellement ce que fait un Événement Clé :
|
|
22
|
+
* quelque chose se produit au niveau de la facette et irradie vers les
|
|
23
|
+
* satellites concernés.
|
|
24
|
+
*
|
|
25
|
+
* Volontairement distinct du beam laser rectiligne et continu des champs de
|
|
26
|
+
* force d'action (ForceFieldRenderer) : la distinction porte sur la
|
|
27
|
+
* grammaire temporelle (émission rythmée vs flux continu) autant que sur la
|
|
28
|
+
* teinte, elle survit donc à un changement de palette.
|
|
29
|
+
*/
|
|
30
|
+
export declare class EventFieldRenderer {
|
|
31
|
+
private group;
|
|
32
|
+
private rings;
|
|
33
|
+
private layers;
|
|
34
|
+
private coreHalo;
|
|
35
|
+
/** setTimeout id du fondu de sortie en cours, ou null — voir hide(). */
|
|
36
|
+
private _hideTimeoutId;
|
|
37
|
+
/** requestAnimationFrame id de la rétraction géométrique en cours — voir retractGeometry(). */
|
|
38
|
+
private _retractFrameId;
|
|
39
|
+
hasActiveGroup(): boolean;
|
|
40
|
+
ensureElements(params: {
|
|
41
|
+
globalGroupNode: SVGGElement;
|
|
42
|
+
requiredCount: number;
|
|
43
|
+
}): void;
|
|
44
|
+
/**
|
|
45
|
+
* Fondu de sortie : au lieu de retirer le groupe instantanément (clear()),
|
|
46
|
+
* ramène son opacité à 0 sur fieldFadeOutDurationMs puis le retire
|
|
47
|
+
* réellement — même grammaire de disparition que ForceFieldRenderer.hide().
|
|
48
|
+
* Idempotent : un appel alors qu'un fondu est déjà en cours ne fait rien de
|
|
49
|
+
* plus (le clear() en attente suffit).
|
|
50
|
+
*/
|
|
51
|
+
hide(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Rétraction géométrique : ramène chaque cordon vers le cœur (ou l'arc de
|
|
54
|
+
* bordure en mode entrant), inverse exact de la croissance animatedEnd de
|
|
55
|
+
* updateVisual (même courbe lue à l'envers : d3.easeCubicOut(1 - t)).
|
|
56
|
+
* Repart de _prevCord — la géométrie du dernier frame réellement rendu —
|
|
57
|
+
* donc indépendante de tout state externe : continue même si la cible
|
|
58
|
+
* (satellite, Événement Clé actif) a déjà disparu entre temps. headAura/
|
|
59
|
+
* headCore suivent la pointe rétractée : leur opacité a un plancher non
|
|
60
|
+
* nul (0.3 / 0.6 × revealEase dans updateVisual, visibles même hors flash
|
|
61
|
+
* d'impact) — les laisser figés à l'ancienne cible les détacherait
|
|
62
|
+
* visiblement du cordon en train de se rétracter sous eux. Seuls les
|
|
63
|
+
* anneaux / capsules / onde de choc restent figés sur leur dernière pose
|
|
64
|
+
* et s'effacent avec le fondu d'opacité du groupe posé par hide().
|
|
65
|
+
*/
|
|
66
|
+
private retractGeometry;
|
|
67
|
+
clear(): void;
|
|
68
|
+
updateVisual(params: {
|
|
69
|
+
/** Centre du cœur — disque central du lobe yin OU yang selon
|
|
70
|
+
* l'orientation de la facette courante, jamais le centre du symbole. */
|
|
71
|
+
sourceCenter: Point | null;
|
|
72
|
+
/** Rayon de ce disque : les cordons partent de son bord et les anneaux
|
|
73
|
+
* naissent à sa circonférence, pas d'un point. */
|
|
74
|
+
sourceRadius: number;
|
|
75
|
+
segments: EventFieldRenderSegment[];
|
|
76
|
+
/** Temps écoulé en secondes depuis le début de l'animation. */
|
|
77
|
+
phase: number;
|
|
78
|
+
/** performance.now() du dernier souffle qui a (ré)apparu — undefined ou
|
|
79
|
+
* déjà écoulé = plein régime immédiat. Pilote la croissance cœur → cible
|
|
80
|
+
* à l'apparition, même convention que ForceFieldRenderer (revealStartedAt
|
|
81
|
+
* / revealEase) : sans elle le cordon surgissait déjà à pleine longueur
|
|
82
|
+
* et pleine opacité, contrastant avec le beam d'action qui se dessine
|
|
83
|
+
* progressivement. */
|
|
84
|
+
revealStartedAt?: number;
|
|
85
|
+
}): void;
|
|
86
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type PropagatedActionEdge } from "../../../utils/actionPropagation";
|
|
2
|
+
import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
|
|
3
|
+
import { CauseGraph } from "../../../interfaces/ICauseGraph";
|
|
4
|
+
import { PropagationLayersConfig } from "../../../interfaces/IPropagationLayers";
|
|
5
|
+
import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
|
|
6
|
+
import { ForceFieldLink, ForceFieldLinkDetail } from "./types";
|
|
7
|
+
/** Single source of truth for turning a raw propagation edge into the
|
|
8
|
+
* enriched ForceFieldLinkDetail the UI consumes (rationale, layer
|
|
9
|
+
* summaries…) — shared by build(), buildFromSource(), and any other caller
|
|
10
|
+
* that needs to map edges from computeActionPropagationDetails/
|
|
11
|
+
* propagateForceFieldActionInComponent without re-deriving this metadata. */
|
|
12
|
+
export declare function mapPropagatedEdgeToDetail(edge: PropagatedActionEdge, componentId: string): ForceFieldLinkDetail;
|
|
13
|
+
export declare class ForceFieldComputationService {
|
|
14
|
+
build(params: {
|
|
15
|
+
orbitData: ChildrenOrbitEntry[];
|
|
16
|
+
sourceChildIndex: number;
|
|
17
|
+
childOddMap: Map<string, {
|
|
18
|
+
oddId: string;
|
|
19
|
+
score: number;
|
|
20
|
+
cuttingIndex: number;
|
|
21
|
+
}>;
|
|
22
|
+
component: YinYangInternalModel["components"][number] | null;
|
|
23
|
+
allComponents: YinYangInternalModel["components"] | undefined;
|
|
24
|
+
actionDelta: number;
|
|
25
|
+
actionPropagationFactor: number;
|
|
26
|
+
interconnectionGraph: CauseGraph;
|
|
27
|
+
propagationLayers: PropagationLayersConfig;
|
|
28
|
+
}): {
|
|
29
|
+
links: ForceFieldLink[];
|
|
30
|
+
allLinkDetails: ForceFieldLinkDetail[];
|
|
31
|
+
} | null;
|
|
32
|
+
/**
|
|
33
|
+
* Variante de build() qui accepte directement sourceOddId + sourceCuttingId,
|
|
34
|
+
* sans avoir besoin de orbitData/childOddMap. Utilisée pour les actions
|
|
35
|
+
* cross-composantes où ces structures ne sont pas disponibles.
|
|
36
|
+
*/
|
|
37
|
+
buildFromSource(params: {
|
|
38
|
+
sourceOddId: string;
|
|
39
|
+
sourceCuttingId: number | undefined;
|
|
40
|
+
component: YinYangInternalModel["components"][number];
|
|
41
|
+
allComponents: YinYangInternalModel["components"] | undefined;
|
|
42
|
+
actionDelta: number;
|
|
43
|
+
actionPropagationFactor: number;
|
|
44
|
+
interconnectionGraph: CauseGraph;
|
|
45
|
+
propagationLayers: PropagationLayersConfig;
|
|
46
|
+
}): {
|
|
47
|
+
links: ForceFieldLink[];
|
|
48
|
+
allLinkDetails: ForceFieldLinkDetail[];
|
|
49
|
+
} | null;
|
|
50
|
+
}
|