@micheeeeel/yinyangapp 1.0.6 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,149 @@
|
|
|
1
|
+
import { type ActionStackItem } from "./ActionStackState";
|
|
2
|
+
export type { ActionStackItem };
|
|
3
|
+
type Point = {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
};
|
|
7
|
+
export declare class ActionStackController {
|
|
8
|
+
private readonly state;
|
|
9
|
+
private readonly drag;
|
|
10
|
+
private actionStackGroup;
|
|
11
|
+
private stackLayoutMetrics;
|
|
12
|
+
private actionStackLabelFontScale;
|
|
13
|
+
private historyButtonScale;
|
|
14
|
+
private fallingStackItemIds;
|
|
15
|
+
private keyboardListenersBound;
|
|
16
|
+
private _linkedHoverId;
|
|
17
|
+
private _onBlockHighlightCb?;
|
|
18
|
+
private _onSatelliteHighlightCb?;
|
|
19
|
+
private activeComboHighlight;
|
|
20
|
+
/** Highlight temporaire (tag click) — remplacé par activeComboHighlight si actif. */
|
|
21
|
+
private flashComboHighlight;
|
|
22
|
+
private flashComboTimeout;
|
|
23
|
+
private resizeObserver;
|
|
24
|
+
private _cachedNumVisibleSlots;
|
|
25
|
+
private onLocateInSearch?;
|
|
26
|
+
private onSelectSatellite?;
|
|
27
|
+
setOnLocateInSearch(cb: (componentId: string, oddId: string, cuttingIndex: number, actionId: string, kind: "action" | "keyEvent") => void): void;
|
|
28
|
+
setOnSelectSatellite(cb: (componentId: string, oddId: string, cuttingIndex: number, stackItemId: string) => void): void;
|
|
29
|
+
constructor(onActiveItemsChange: (activeItems: ActionStackItem[]) => void, onClear?: () => void);
|
|
30
|
+
setLabelFontScale(scale: number): void;
|
|
31
|
+
setHistoryButtonScale(scale: number): void;
|
|
32
|
+
/**
|
|
33
|
+
* Surligne dans le stack les actions impliquées dans le combo actuellement affiché.
|
|
34
|
+
* Affiche un crochet coloré sur la droite qui délimite la fenêtre temporelle,
|
|
35
|
+
* met en valeur les actions requises (glow) et estompe les autres dans la fenêtre.
|
|
36
|
+
*/
|
|
37
|
+
highlightComboContext(params: {
|
|
38
|
+
requires: string[];
|
|
39
|
+
withinLastN?: number;
|
|
40
|
+
type: string;
|
|
41
|
+
comboName?: string;
|
|
42
|
+
sourceItemId?: string;
|
|
43
|
+
deltaMultiplier?: number;
|
|
44
|
+
maxDeltaMultiplier?: number;
|
|
45
|
+
direction?: "forward" | "backward";
|
|
46
|
+
}): void;
|
|
47
|
+
/** Efface le surlignage combo et restaure l'apparence normale du stack. */
|
|
48
|
+
clearComboHighlight(): void;
|
|
49
|
+
setBlockHighlightCallback(cb: (id: string | null) => void): void;
|
|
50
|
+
setSatelliteHighlightCallback(cb: (id: string | null) => void): void;
|
|
51
|
+
getItemById(id: string): ActionStackItem | undefined;
|
|
52
|
+
highlightByStackItemId(id: string | null): void;
|
|
53
|
+
/**
|
|
54
|
+
* Affiche temporairement le highlight combo (cercles de fenêtre) pendant ~1.8 s.
|
|
55
|
+
* Sans effet si un highlight permanent est déjà actif.
|
|
56
|
+
*/
|
|
57
|
+
flashComboContext(params: {
|
|
58
|
+
requires: string[];
|
|
59
|
+
withinLastN?: number;
|
|
60
|
+
type: string;
|
|
61
|
+
comboName?: string;
|
|
62
|
+
sourceItemId?: string;
|
|
63
|
+
deltaMultiplier?: number;
|
|
64
|
+
maxDeltaMultiplier?: number;
|
|
65
|
+
direction?: "forward" | "backward";
|
|
66
|
+
}): void;
|
|
67
|
+
/**
|
|
68
|
+
* Brève mise en valeur (flash) d'une action dans le stack par son actionId.
|
|
69
|
+
* Anime l'intégralité de l'élément (icôn + checkbox + libellé) via un glow
|
|
70
|
+
* drop-shadow, sans toucher au mécanisme de combo highlight.
|
|
71
|
+
*/
|
|
72
|
+
flashActionById(actionId: string): void;
|
|
73
|
+
canUndo(): boolean;
|
|
74
|
+
canRedo(): boolean;
|
|
75
|
+
undo(): void;
|
|
76
|
+
redo(): void;
|
|
77
|
+
clearAll(): void;
|
|
78
|
+
clearToolRange(): void;
|
|
79
|
+
/**
|
|
80
|
+
* Clears the active selection in the stack without emitting a change event
|
|
81
|
+
* and without recording history. Called when the diagram state is cleared
|
|
82
|
+
* externally (e.g. the user clicks a different child or closes an action menu)
|
|
83
|
+
* so the stack visual stays in sync. Because the deselection is a side-effect
|
|
84
|
+
* of a diagram action — not a direct user action on the stack — it is not
|
|
85
|
+
* added to the undo history.
|
|
86
|
+
*/
|
|
87
|
+
deselectAllItems(): void;
|
|
88
|
+
getActionLabel(actionId: string): string | null;
|
|
89
|
+
clickBookmark(index: number): void;
|
|
90
|
+
addItem(item: Omit<ActionStackItem, "id" | "validatedAt" | "slotIndex">, insertAtVisibleIndex?: number | null, entryOrigin?: Point): void;
|
|
91
|
+
/** Insertion à un slot absolu avec décalage systématique — voir
|
|
92
|
+
* ActionStackState.addItemAtSlot. Même remise à zéro de l'aperçu de
|
|
93
|
+
* glisser qu'addItem, pour la même raison (rendu synchrone dans
|
|
94
|
+
* state.addItemAtSlot). */
|
|
95
|
+
addItemAtSlot(item: Omit<ActionStackItem, "id" | "validatedAt" | "slotIndex">, slotIndex: number): ActionStackItem;
|
|
96
|
+
syncActiveAction(sourceChildKey: string | null, actionId: string | null): void;
|
|
97
|
+
setExternalDragActive(active: boolean): void;
|
|
98
|
+
clearDropPreview(): void;
|
|
99
|
+
updateDropPreview(clientX: number, clientY: number, _localY: number): boolean;
|
|
100
|
+
isDropZoneHit(clientX: number, clientY: number): boolean;
|
|
101
|
+
getInsertionPreviewIndex(): number | null;
|
|
102
|
+
/** True while the user is actively dragging a stack item. */
|
|
103
|
+
get isDragging(): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Returns all action IDs currently in the stack, in visual stack order
|
|
106
|
+
* (bottom-first, i.e. earliest-played first). This is the authoritative
|
|
107
|
+
* "played history" for combo evaluation: items[0] is the oldest/bottom card,
|
|
108
|
+
* items[last] is the newest/top card. Drag-and-drop reordering is reflected
|
|
109
|
+
* immediately because reorderStackItemsByVisibleIndex mutates this.state.items.
|
|
110
|
+
*/
|
|
111
|
+
getOrderedActionIds(): string[];
|
|
112
|
+
getSlotPaddedActionIds(anchorSlot: number, activeItemIds?: Set<string>): string[];
|
|
113
|
+
getNextTopSlot(): number;
|
|
114
|
+
getItemsInStackOrder(): ActionStackItem[];
|
|
115
|
+
getEffectiveDeltaByActionId(): Map<string, number>;
|
|
116
|
+
updateVisual(): void;
|
|
117
|
+
/**
|
|
118
|
+
* Garantit, dans le <defs> du SVG de la pile, le gradient de cœur propre au
|
|
119
|
+
* type de highlight courant, ainsi que le gradient d'impulsion et le filtre
|
|
120
|
+
* de flou partagés par toutes les jauges de fenêtre. Idempotent.
|
|
121
|
+
*/
|
|
122
|
+
private _ensureWindowIndicatorDefs;
|
|
123
|
+
private _buildRenderContext;
|
|
124
|
+
/**
|
|
125
|
+
* Pendant un glisser du corps du bracket (voir draggingRangeBlock), calcule une
|
|
126
|
+
* projection en direct des positions — mêmes formules que ActionStackState.
|
|
127
|
+
* moveRangeTo, mais purement pour l'affichage : this.state.items n'est modifié
|
|
128
|
+
* qu'au relâchement (commitRangeMove). Hors glisser, retourne les items tels quels.
|
|
129
|
+
*/
|
|
130
|
+
private _computePreviewItems;
|
|
131
|
+
private _computeLayout;
|
|
132
|
+
private _renderPanel;
|
|
133
|
+
private _renderFooterButtons;
|
|
134
|
+
private _renderConfigBookmarks;
|
|
135
|
+
private _renderGhostSlots;
|
|
136
|
+
private _renderTimeline;
|
|
137
|
+
private _renderItems;
|
|
138
|
+
private _renderComboHighlight;
|
|
139
|
+
private _renderUnifiedControl;
|
|
140
|
+
private _renderDragGhost;
|
|
141
|
+
private _bindItemInteractions;
|
|
142
|
+
private ensureActionStackGroup;
|
|
143
|
+
private ensureResizeObserver;
|
|
144
|
+
/** Copies the current tool range to the internal clipboard. */
|
|
145
|
+
copyRangeToClipboard(): void;
|
|
146
|
+
/** Pastes the clipboard at the top of the currently active stack. */
|
|
147
|
+
pasteClipboard(): void;
|
|
148
|
+
private ensureKeyboardListeners;
|
|
149
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as d3 from "d3";
|
|
2
|
+
import type { ActionStackState, ActionStackItem } from "./ActionStackState";
|
|
3
|
+
export interface DragHandlerHost {
|
|
4
|
+
updateVisual(): void;
|
|
5
|
+
removeItem(id: string): void;
|
|
6
|
+
toggleItemSelection(id: string, emitChange: boolean): void;
|
|
7
|
+
toggleRangeActivation(): void;
|
|
8
|
+
setToolRange(minSlot: number, maxSlot: number): void;
|
|
9
|
+
/** Tap (sans glisser) sur la poignée basse : étend la plage jusqu'au slot 0. */
|
|
10
|
+
expandRangeToBottom(): void;
|
|
11
|
+
/** Tap (sans glisser) sur la poignée haute : étend la plage jusqu'au dernier item. */
|
|
12
|
+
expandRangeToTop(): void;
|
|
13
|
+
/** Double-clic sur la gouttière, n'importe où : sélectionne toute la pile d'un coup. */
|
|
14
|
+
selectAllRange(): void;
|
|
15
|
+
/** Déplace effectivement le bloc [originalMinSlot..originalMaxSlot] jusqu'à ce
|
|
16
|
+
* que son début arrive à targetMinSlot — appelé au relâchement d'un glisser sur
|
|
17
|
+
* le corps du bracket, une fois le geste confirmé (pas un simple tap). */
|
|
18
|
+
commitRangeMove(originalMinSlot: number, originalMaxSlot: number, targetMinSlot: number): void;
|
|
19
|
+
highlightByStackItemId(id: string | null): void;
|
|
20
|
+
triggerBlockHighlight(id: string | null): void;
|
|
21
|
+
triggerSatelliteHighlight(id: string | null): void;
|
|
22
|
+
locateInSearch(compId: string, oddId: string, cutIdx: number, actionId: string, kind: "action" | "keyEvent"): void;
|
|
23
|
+
/** Clic sur le libellé d'un item : sélectionne automatiquement son
|
|
24
|
+
* satellite porteur dans le diagramme (action) — ou sa Facette d'origine
|
|
25
|
+
* (Événement Clé, sentinel oddId="" / cutIdx=-1, cf. ActionStackState) —
|
|
26
|
+
* sans changer d'onglet, contrairement à locateInSearch. stackItemId
|
|
27
|
+
* permet ensuite de centrer automatiquement le bloc correspondant dans la
|
|
28
|
+
* liste "Effets cumulés" une fois celle-ci (re)rendue. */
|
|
29
|
+
selectSatelliteForItem(compId: string, oddId: string, cutIdx: number, stackItemId: string): void;
|
|
30
|
+
}
|
|
31
|
+
type Point = {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
};
|
|
35
|
+
type RenderableItem = ActionStackItem & {
|
|
36
|
+
isPlaceholder?: boolean;
|
|
37
|
+
/** Aperçu d'échange lors d'un réordonnancement interne uniquement — voir
|
|
38
|
+
* ActionStackController._computeLayout. */
|
|
39
|
+
isDisplacedPreview?: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare class ActionStackDragHandler {
|
|
42
|
+
private readonly state;
|
|
43
|
+
private readonly host;
|
|
44
|
+
static readonly ACTION_DRAG_THRESHOLD_PX = 12;
|
|
45
|
+
static readonly DOUBLE_CLICK_MS = 300;
|
|
46
|
+
draggingStackItemId: string | null;
|
|
47
|
+
draggingStackItemPosition: Point | null;
|
|
48
|
+
draggingStackItemGhostWithLabel: boolean;
|
|
49
|
+
stackInsertionPreviewIndex: number | null;
|
|
50
|
+
pendingStackItemEntryOrigins: Map<string, Point>;
|
|
51
|
+
pendingSwapDropY: Map<string, number>;
|
|
52
|
+
stackControlDragInProgress: boolean;
|
|
53
|
+
/** Bloc en cours de glissement via le corps du bracket — permet au rendu de
|
|
54
|
+
* prévisualiser en direct la translation des items concernés, sans encore
|
|
55
|
+
* toucher à l'état persistant (le vrai déplacement n'a lieu qu'au relâchement,
|
|
56
|
+
* voir commitRangeMove). */
|
|
57
|
+
draggingRangeBlock: {
|
|
58
|
+
ids: Set<string>;
|
|
59
|
+
originalMinSlot: number;
|
|
60
|
+
originalMaxSlot: number;
|
|
61
|
+
} | null;
|
|
62
|
+
externalActionDragActive: boolean;
|
|
63
|
+
dropZoneClient: {
|
|
64
|
+
left: number;
|
|
65
|
+
top: number;
|
|
66
|
+
right: number;
|
|
67
|
+
bottom: number;
|
|
68
|
+
} | null;
|
|
69
|
+
dropZoneIsHot: boolean;
|
|
70
|
+
private lastGutterClickTime;
|
|
71
|
+
private layoutMetrics;
|
|
72
|
+
constructor(state: ActionStackState, host: DragHandlerHost);
|
|
73
|
+
get isDragging(): boolean;
|
|
74
|
+
setExternalDragActive(active: boolean): void;
|
|
75
|
+
setRenderGeometry(dropZoneClient: {
|
|
76
|
+
left: number;
|
|
77
|
+
top: number;
|
|
78
|
+
right: number;
|
|
79
|
+
bottom: number;
|
|
80
|
+
}, layoutMetrics: {
|
|
81
|
+
firstSlotCenterY: number;
|
|
82
|
+
slotSpacing: number;
|
|
83
|
+
compactLength: number;
|
|
84
|
+
}): void;
|
|
85
|
+
clearDropPreview(): void;
|
|
86
|
+
updateDropPreview(clientX: number, clientY: number, _localY: number): boolean;
|
|
87
|
+
isDropZoneHit(clientX: number, clientY: number): boolean;
|
|
88
|
+
getInsertionPreviewIndex(): number | null;
|
|
89
|
+
private emitDragPreviewChange;
|
|
90
|
+
syncPosition(actionStackGroup: SVGGElement | null): void;
|
|
91
|
+
bindItemInteractions(mergedItems: d3.Selection<SVGGElement, RenderableItem, SVGGElement, unknown>, bindCtx: {
|
|
92
|
+
x: number;
|
|
93
|
+
leftPad: number;
|
|
94
|
+
labelXOffset: number;
|
|
95
|
+
bottomY: number;
|
|
96
|
+
}, actionStackGroup: SVGGElement | null, _actionStackLabelFontScale: number): void;
|
|
97
|
+
bindUnifiedControlInteractions(ctrlMerged: d3.Selection<SVGGElement, number, SVGGElement, unknown>, ctrlBounds: {
|
|
98
|
+
minSlot: number;
|
|
99
|
+
maxSlot: number;
|
|
100
|
+
}, slotSpacing: number, numVisibleSlots: number): void;
|
|
101
|
+
/**
|
|
102
|
+
* Glisser dans la gouttière temporelle (graduation à gauche de la pile) définit
|
|
103
|
+
* une plage libre — plus d'ancrage forcé au slot 0. Un simple tap sélectionne le
|
|
104
|
+
* slot visé seul (plage de taille 1) ; un glissement l'étend jusqu'au slot courant.
|
|
105
|
+
* Réutilise le même calcul slot↔Y que l'aperçu de dépôt (updateDropPreview) pour
|
|
106
|
+
* rester cohérent avec la conversion clientY → slot déjà éprouvée ailleurs.
|
|
107
|
+
*/
|
|
108
|
+
bindGutterSelectInteraction(hitStrip: d3.Selection<SVGRectElement, number, SVGGElement, unknown>): void;
|
|
109
|
+
private _svgLocalPoint;
|
|
110
|
+
}
|
|
111
|
+
export {};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { IYinYangController } from "../../../interfaces/IYinYangController";
|
|
2
|
+
import { IYinYangView } from "../../../interfaces/IYinYangView";
|
|
3
|
+
import { YinYangControllerState } from "../state/YinYangControllerState";
|
|
4
|
+
import { ActionStackController, ActionStackItem } from "./ActionStackController";
|
|
5
|
+
import { ChildrenOrbitEntry } from "../utils/childrenOrbit";
|
|
6
|
+
import { SequentialActionProjectionInput } from "../actions/ActionProjectionService";
|
|
7
|
+
import { type ComboResult } from "../../../data/combo-engine";
|
|
8
|
+
import { ForceFieldLink } from "../force-field/types";
|
|
9
|
+
import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
|
|
10
|
+
type ChildOddMeta = {
|
|
11
|
+
oddId: string;
|
|
12
|
+
score: number;
|
|
13
|
+
cuttingIndex: number;
|
|
14
|
+
};
|
|
15
|
+
type SelectedSourceFocus = {
|
|
16
|
+
oddId: string;
|
|
17
|
+
cuttingId: number | undefined;
|
|
18
|
+
} | null;
|
|
19
|
+
type PersistentActionContext = {
|
|
20
|
+
sourceComponentId: string;
|
|
21
|
+
sourceOddId: string;
|
|
22
|
+
sourceCuttingIndex: number;
|
|
23
|
+
actionId: string;
|
|
24
|
+
actionLabel?: string;
|
|
25
|
+
links: ForceFieldLink[];
|
|
26
|
+
} | null;
|
|
27
|
+
type ActionStackManagerDeps = {
|
|
28
|
+
view: IYinYangView;
|
|
29
|
+
state: YinYangControllerState;
|
|
30
|
+
actionStackController: ActionStackController;
|
|
31
|
+
getChildControllers: () => IYinYangController[];
|
|
32
|
+
getChildOddMap: () => Map<string, ChildOddMeta>;
|
|
33
|
+
getSelectedSourceFocus: () => SelectedSourceFocus;
|
|
34
|
+
setSelectedSourceFocus: (focus: SelectedSourceFocus) => void;
|
|
35
|
+
getPersistentActionContext: () => PersistentActionContext;
|
|
36
|
+
setPersistentActionContext: (ctx: PersistentActionContext) => void;
|
|
37
|
+
getInternalModel: () => YinYangInternalModel;
|
|
38
|
+
getCurrentComponent: () => YinYangInternalModel["components"][number] | null;
|
|
39
|
+
getCurrentComponentOrUndefined: () => YinYangInternalModel["components"][number] | undefined;
|
|
40
|
+
getAllComponents: () => YinYangInternalModel["components"] | undefined;
|
|
41
|
+
prepareForComponentSwitch: (targetComponentId: string) => void;
|
|
42
|
+
animateChildrenHide: () => void;
|
|
43
|
+
recomputeIncomingForceFieldForItems: (items: ActionStackItem[], sourceComponentId: string, currentComponentId: string) => boolean;
|
|
44
|
+
buildProjectionActionsFromStackItems: (items: ActionStackItem[]) => SequentialActionProjectionInput[];
|
|
45
|
+
buildForceFieldSourceIndicesFromStackItems: (items: ActionStackItem[]) => number[];
|
|
46
|
+
clearProjectedActionState: (options?: {
|
|
47
|
+
deselect?: boolean;
|
|
48
|
+
}) => void;
|
|
49
|
+
clearActiveChild: () => void;
|
|
50
|
+
clearForceFieldComputationState: () => void;
|
|
51
|
+
renderOppositeChildrenForceField: () => void;
|
|
52
|
+
renderForceFieldDetails: (linkIndex: number) => void;
|
|
53
|
+
buildChildrenOrbitData: () => ChildrenOrbitEntry[];
|
|
54
|
+
renderChildScoresDeltas: (orbitData: ChildrenOrbitEntry[]) => void;
|
|
55
|
+
syncGhostTensionFromAction: () => void;
|
|
56
|
+
renderGhostDetailsForActiveAction: () => void;
|
|
57
|
+
renderCumulativeDetailsForCutting: (oddId: string, cuttingId: number | undefined) => boolean | undefined;
|
|
58
|
+
renderSourceActionDetailsForCurrentSource: () => void;
|
|
59
|
+
renderActionPropagationTable: () => void;
|
|
60
|
+
clearGhostDetails: () => void;
|
|
61
|
+
/** Réaffiche le descriptif de la Facette courante (avec ses blocs Événement
|
|
62
|
+
* Clé) — utilisé quand la pile ne contient plus que des items sans
|
|
63
|
+
* satellite (Événement Clé) après clearProjectedActionState, qui sinon
|
|
64
|
+
* retombe seul sur la carte Sphère. */
|
|
65
|
+
showComposanteInfo: () => void;
|
|
66
|
+
refreshChildActionMenu: () => void;
|
|
67
|
+
};
|
|
68
|
+
export declare class ActionStackManager {
|
|
69
|
+
private readonly deps;
|
|
70
|
+
private activeStackItemsSnapshot;
|
|
71
|
+
private lastComboResults;
|
|
72
|
+
private lastFocusBeforeAllUnchecked;
|
|
73
|
+
/** weightDelta of the action(s) currently previewed, summed per targeted
|
|
74
|
+
* satellite (a satellite is always its own single target, never
|
|
75
|
+
* propagated) — read by YinYangController to animate/ring each satellite. */
|
|
76
|
+
private currentWeightDeltaByChildKey;
|
|
77
|
+
constructor(deps: ActionStackManagerDeps);
|
|
78
|
+
getActiveItems(): ActionStackItem[];
|
|
79
|
+
getWeightDeltaByChildKey(): Map<string, number>;
|
|
80
|
+
/**
|
|
81
|
+
* Same weightDelta computation as getWeightDeltaByChildKey (baseDelta ×
|
|
82
|
+
* amplificateurs, écrêté aux bornes [WEIGHT_MIN, WEIGHT_MAX] du poids
|
|
83
|
+
* actuel), mais agrégée sur TOUTE la pile active — pas seulement les items
|
|
84
|
+
* de la facette actuellement affichée. La bordure du cercle central montre
|
|
85
|
+
* toutes les facettes à la fois (voir buildBorderSegments), donc son ghost
|
|
86
|
+
* a besoin du poids projeté de chaque facette ayant des items empilés,
|
|
87
|
+
* même celles qu'on ne regarde pas en ce moment. Clé :
|
|
88
|
+
* `${sourceComponentId}::${sourceOddId}::${sourceCuttingIndex}` — un
|
|
89
|
+
* satellite d'une facette non affichée n'a pas de sourceChildKey exploitable
|
|
90
|
+
* ici (childOddMap ne connaît que la facette courante).
|
|
91
|
+
*/
|
|
92
|
+
getWeightDeltaByComponentOddCutting(): Map<string, number>;
|
|
93
|
+
clearWeightPreview(): void;
|
|
94
|
+
resetLastComboResults(): void;
|
|
95
|
+
computeComboResultsForAction(actionId: string): ComboResult[] | undefined;
|
|
96
|
+
validateActionSelection(childController: IYinYangController, actionId: string, label: string, insertAtVisibleIndex?: number | null, entryOrigin?: {
|
|
97
|
+
x: number;
|
|
98
|
+
y: number;
|
|
99
|
+
}): void;
|
|
100
|
+
/**
|
|
101
|
+
* Insertion directe à un slot absolu, sans passer par la sélection
|
|
102
|
+
* d'action du satellite (pas de menu, pas de champ de force) : c'est le
|
|
103
|
+
* chemin du placement automatique des actions adverses par le système.
|
|
104
|
+
* Le delta effectif est évalué à la position réelle d'insertion ; il
|
|
105
|
+
* sera de toute façon recalculé pour toute la pile par
|
|
106
|
+
* onStackItemVisibilityToggle à l'émission qui suit.
|
|
107
|
+
*/
|
|
108
|
+
insertActionAtSlot(childController: IYinYangController, actionId: string, label: string, slotIndex: number): void;
|
|
109
|
+
/** Item de pile d'une action jouée depuis un satellite — couleur de son
|
|
110
|
+
* ODD, métadonnées de son cutting. Null si le satellite est inconnu. */
|
|
111
|
+
private buildActionStackItem;
|
|
112
|
+
activateActionFromChild(childController: IYinYangController, actionId?: string, label?: string, clearStack?: boolean): void;
|
|
113
|
+
applyProjectedGhostFromStackItems(items: ActionStackItem[]): void;
|
|
114
|
+
onStackItemVisibilityToggle(activeItems: ActionStackItem[]): void;
|
|
115
|
+
private updateProjectedGhostTensions;
|
|
116
|
+
private applyEmptyGhostProjectionState;
|
|
117
|
+
}
|
|
118
|
+
export {};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
export type ActionStackItem = {
|
|
2
|
+
id: string;
|
|
3
|
+
/**
|
|
4
|
+
* Nature de l'item — "action" (par défaut) pour une action satellite
|
|
5
|
+
* classique, "keyEvent" pour un Événement Clé joué depuis le cercle
|
|
6
|
+
* central d'une facette. Un keyEvent n'a pas de satellite cible (les
|
|
7
|
+
* champs source* ci-dessous sont des sentinels dans ce cas) ni de delta
|
|
8
|
+
* propre (effectiveDelta reste 0) — son seul effet est d'amplifier les
|
|
9
|
+
* actions listées dans sa définition, si elles sont jouées après lui
|
|
10
|
+
* dans la pile (voir amplifier-engine.ts).
|
|
11
|
+
*/
|
|
12
|
+
kind: "action" | "keyEvent";
|
|
13
|
+
/** actionId pour kind="action" ; KeyEventDefinition.id pour kind="keyEvent"
|
|
14
|
+
* (préfixe "key_" garantit l'absence de collision avec un actionId). */
|
|
15
|
+
actionId: string;
|
|
16
|
+
label: string;
|
|
17
|
+
/** Sentinel "" pour kind="keyEvent" — non rattaché à un satellite précis. */
|
|
18
|
+
sourceChildKey: string;
|
|
19
|
+
/** Sentinel "" pour kind="keyEvent". */
|
|
20
|
+
sourceOddId: string;
|
|
21
|
+
/** Sentinel -1 pour kind="keyEvent". */
|
|
22
|
+
sourceCuttingIndex: number;
|
|
23
|
+
/** Facette d'origine — pour un keyEvent, c'est la facette de déclenchement. */
|
|
24
|
+
sourceComponentId: string;
|
|
25
|
+
color: string;
|
|
26
|
+
validatedAt: number;
|
|
27
|
+
/** Delta effectif après évaluation du combo (= baseDelta × multiplicateur).
|
|
28
|
+
* Toujours 0 pour kind="keyEvent" (pas d'effet propre). */
|
|
29
|
+
effectiveDelta: number;
|
|
30
|
+
/** Résultats des combos évalués au moment du jeu — un par slot déclenché. */
|
|
31
|
+
comboResults?: import("../../../data/combo-engine").ComboResult[];
|
|
32
|
+
/** Index du slot occupé dans la pile (0 = en bas, croissant vers le haut). */
|
|
33
|
+
slotIndex: number;
|
|
34
|
+
};
|
|
35
|
+
/** Champs persistants d'un item copié — sans id/validatedAt/slotIndex, qui sont
|
|
36
|
+
* réattribués à l'insertion (dans la même pile ou une autre, via un bookmark). */
|
|
37
|
+
export type StackClipboardEntry = Omit<ActionStackItem, "id" | "validatedAt" | "slotIndex">;
|
|
38
|
+
export type BookmarkState = "empty" | "unlocked" | "locked";
|
|
39
|
+
export type ConfigBookmark = {
|
|
40
|
+
state: BookmarkState;
|
|
41
|
+
lockedSnapshot: StackState | null;
|
|
42
|
+
dominantColor: string;
|
|
43
|
+
};
|
|
44
|
+
export type StackState = {
|
|
45
|
+
items: ActionStackItem[];
|
|
46
|
+
activeItemIds: string[];
|
|
47
|
+
};
|
|
48
|
+
export type ActionStackSnapshot = StackState & {
|
|
49
|
+
activeBookmarkIndex: number | null;
|
|
50
|
+
bookmarks: Array<{
|
|
51
|
+
state: BookmarkState;
|
|
52
|
+
lockedSnapshot: StackState | null;
|
|
53
|
+
dominantColor: string;
|
|
54
|
+
}>;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Pure state class for the action stack — no DOM, no D3.
|
|
58
|
+
* Manages items, selection, history, config bookmarks and tool range.
|
|
59
|
+
* The controller wraps mutations with a visual update after each call.
|
|
60
|
+
*/
|
|
61
|
+
export declare class ActionStackState {
|
|
62
|
+
private readonly onActiveItemsChange;
|
|
63
|
+
private readonly onClear?;
|
|
64
|
+
readonly ACTION_STACK_MAX_ITEMS = 30;
|
|
65
|
+
readonly HISTORY_LIMIT = 120;
|
|
66
|
+
readonly CONFIG_BOOKMARKS_MAX = 4;
|
|
67
|
+
items: ActionStackItem[];
|
|
68
|
+
activeItemIds: Set<string>;
|
|
69
|
+
historyPast: ActionStackSnapshot[];
|
|
70
|
+
historyFuture: ActionStackSnapshot[];
|
|
71
|
+
isApplyingHistory: boolean;
|
|
72
|
+
toolRangeMin: number;
|
|
73
|
+
toolRangeMax: number | null;
|
|
74
|
+
/** Presse-papiers de plage — survit volontairement au changement de bookmark
|
|
75
|
+
* (copier sur une pile, basculer de bookmark, coller sur une autre). */
|
|
76
|
+
stackClipboard: StackClipboardEntry[] | null;
|
|
77
|
+
configBookmarks: ConfigBookmark[];
|
|
78
|
+
activeBookmarkIndex: number;
|
|
79
|
+
constructor(onActiveItemsChange: (activeItems: ActionStackItem[]) => void, onClear?: (() => void) | undefined);
|
|
80
|
+
canUndo(): boolean;
|
|
81
|
+
canRedo(): boolean;
|
|
82
|
+
getItemById(id: string): ActionStackItem | undefined;
|
|
83
|
+
getActionLabel(actionId: string): string | null;
|
|
84
|
+
getOrderedActionIds(): string[];
|
|
85
|
+
getSlotPaddedActionIds(anchorSlot: number, activeItemIds?: Set<string>): string[];
|
|
86
|
+
getNextTopSlot(): number;
|
|
87
|
+
getItemsInStackOrder(): ActionStackItem[];
|
|
88
|
+
getEffectiveDeltaByActionId(): Map<string, number>;
|
|
89
|
+
/** Bornes de la plage d'outil, qu'elle contienne des items ou non — pour l'affichage
|
|
90
|
+
* du bracket, qui doit rester visible même sur une plage dessinée à vide (voir
|
|
91
|
+
* getToolBlock ci-dessous, qui lui exige au moins un item pour les mutations). */
|
|
92
|
+
getToolRangeBounds(): {
|
|
93
|
+
minSlot: number;
|
|
94
|
+
maxSlot: number;
|
|
95
|
+
} | null;
|
|
96
|
+
getToolBlock(): {
|
|
97
|
+
items: ActionStackItem[];
|
|
98
|
+
minSlot: number;
|
|
99
|
+
maxSlot: number;
|
|
100
|
+
} | null;
|
|
101
|
+
hasClipboard(): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Adds a new item to the stack and returns the created ActionStackItem so
|
|
104
|
+
* the controller can register animation origins if needed.
|
|
105
|
+
*
|
|
106
|
+
* @param compactLength Current number of visible slots (from render context).
|
|
107
|
+
* Null when called without a specific insertion index.
|
|
108
|
+
*/
|
|
109
|
+
addItem(item: Omit<ActionStackItem, "id" | "validatedAt" | "slotIndex">, insertAtVisibleIndex: number | null, compactLength: number | null): ActionStackItem;
|
|
110
|
+
/**
|
|
111
|
+
* Insère à un slot ABSOLU (0 = bas de pile), en décalant d'un cran tout
|
|
112
|
+
* item situé à ce slot ou au-dessus — inconditionnellement, même si le
|
|
113
|
+
* slot est un trou : c'est ce qui rend l'arithmétique d'un plan
|
|
114
|
+
* d'insertions (adverse-action-planner.ts) exacte, insertion après
|
|
115
|
+
* insertion. addItem, lui, n'a pas cette garantie (il ne décale qu'en
|
|
116
|
+
* présence d'un occupant, et raisonne en index visible).
|
|
117
|
+
*/
|
|
118
|
+
addItemAtSlot(item: Omit<ActionStackItem, "id" | "validatedAt" | "slotIndex">, slotIndex: number): ActionStackItem;
|
|
119
|
+
private pushItemAtSlot;
|
|
120
|
+
removeItem(itemId: string): void;
|
|
121
|
+
clearAll(): void;
|
|
122
|
+
deselectAllItems(): void;
|
|
123
|
+
syncActiveAction(sourceChildKey: string | null, actionId: string | null): boolean;
|
|
124
|
+
toggleItemSelection(itemId: string, emitChange: boolean): void;
|
|
125
|
+
/** Définit la plage d'outil librement (glisser dans la gouttière temporelle) — plus d'ancrage forcé au slot 0. */
|
|
126
|
+
setToolRange(minSlot: number, maxSlot: number): void;
|
|
127
|
+
/** Fait disparaître le bracket sans toucher aux items — clic sur un emplacement
|
|
128
|
+
* vide de la pile, en dehors de la gouttière et du bracket lui-même. */
|
|
129
|
+
clearToolRange(): void;
|
|
130
|
+
/** Étend la borne basse de la plage jusqu'au tout début de la pile (slot 0) —
|
|
131
|
+
* tap sur la poignée basse du bracket, sans glisser. */
|
|
132
|
+
expandRangeToBottom(): void;
|
|
133
|
+
/** Étend la borne haute de la plage jusqu'au dernier item de la pile — tap sur
|
|
134
|
+
* la poignée haute du bracket, sans glisser. */
|
|
135
|
+
expandRangeToTop(): void;
|
|
136
|
+
/** Sélectionne d'un coup l'ensemble de la pile — double-clic sur la gouttière
|
|
137
|
+
* temporelle, n'importe où. */
|
|
138
|
+
selectAllRange(): void;
|
|
139
|
+
clickBookmark(index: number): void;
|
|
140
|
+
undo(): void;
|
|
141
|
+
redo(): void;
|
|
142
|
+
/**
|
|
143
|
+
* Translate le bloc [originalMinSlot..originalMaxSlot] pour que son début arrive
|
|
144
|
+
* à targetMinSlot — décalage pur des numéros de slot, pas une réinsertion relative
|
|
145
|
+
* aux autres items. Les items "traversés" par le déplacement (ceux qui occupaient
|
|
146
|
+
* l'espace entre l'ancienne et la nouvelle position du bloc) sont repoussés de la
|
|
147
|
+
* taille du bloc pour combler l'espace laissé vacant ; tout le reste ne bouge pas.
|
|
148
|
+
* Généralise l'ancien couple moveRangeUp/moveRangeDown (un cran à la fois, swap
|
|
149
|
+
* avec le seul item adjacent) à un déplacement de plusieurs crans en un glisser.
|
|
150
|
+
*/
|
|
151
|
+
moveRangeTo(originalMinSlot: number, originalMaxSlot: number, targetMinSlot: number): void;
|
|
152
|
+
toggleRangeActivation(): void;
|
|
153
|
+
/** Copie la plage sélectionnée dans le presse-papiers interne — n'affecte pas la pile,
|
|
154
|
+
* donc pas d'entrée d'historique. */
|
|
155
|
+
copyRangeToClipboard(): void;
|
|
156
|
+
/** Colle le contenu du presse-papiers au sommet de la pile courante (celle du
|
|
157
|
+
* bookmark actif) et sélectionne la plage collée. */
|
|
158
|
+
pasteClipboard(): void;
|
|
159
|
+
createSnapshot(): ActionStackSnapshot;
|
|
160
|
+
recordHistoryBeforeMutation(): void;
|
|
161
|
+
recordHistoryBeforeMutationAndReturnItems(): ActionStackItem[];
|
|
162
|
+
markActiveBookmarkDirty(): void;
|
|
163
|
+
ensureItemSlotIndices(): void;
|
|
164
|
+
emitActiveItemsChange(): void;
|
|
165
|
+
private createStackState;
|
|
166
|
+
private pushHistory;
|
|
167
|
+
private applyStackState;
|
|
168
|
+
private applySnapshot;
|
|
169
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
|
|
2
|
+
import { type PropagatedActionEdge } from "../../../utils/actionPropagation";
|
|
3
|
+
import { ForceFieldLink } from "../force-field/types";
|
|
4
|
+
export type ProjectedCuttingState = {
|
|
5
|
+
cuttingId: number;
|
|
6
|
+
originalTension: number;
|
|
7
|
+
projectedTension: number;
|
|
8
|
+
originalState: number;
|
|
9
|
+
projectedState: number;
|
|
10
|
+
};
|
|
11
|
+
export type GhostProjectionResult = {
|
|
12
|
+
projectedGhostTensionByOddId: Map<string, number>;
|
|
13
|
+
projectedGhostStateByOddId: Map<string, number>;
|
|
14
|
+
projectedGhostComponentTension: number;
|
|
15
|
+
projectedGhostCuttingStatesByOddId: Map<string, ProjectedCuttingState[]>;
|
|
16
|
+
};
|
|
17
|
+
export type SequentialActionProjectionInput = {
|
|
18
|
+
sourceOddId: string;
|
|
19
|
+
sourceCuttingIndex: number;
|
|
20
|
+
};
|
|
21
|
+
export type EmptyGhostProjectionState = {
|
|
22
|
+
projectedGhostTensionByOddId: null;
|
|
23
|
+
projectedGhostStateByOddId: null;
|
|
24
|
+
projectedGhostComponentTension: null;
|
|
25
|
+
projectedGhostCuttingStatesByOddId: null;
|
|
26
|
+
};
|
|
27
|
+
export declare function getEmptyGhostProjectionState(): EmptyGhostProjectionState;
|
|
28
|
+
export declare function projectGhostStateForIncomingLinks(params: {
|
|
29
|
+
component: YinYangInternalModel["components"][number] | undefined;
|
|
30
|
+
incomingLinks: ForceFieldLink[];
|
|
31
|
+
}): GhostProjectionResult | null;
|
|
32
|
+
export type ActionSequenceStateSnapshot = Map<string, Map<number, number>>;
|
|
33
|
+
export type ActionSequenceStepInfo = {
|
|
34
|
+
actionIndex: number;
|
|
35
|
+
action: SequentialActionProjectionInput;
|
|
36
|
+
effectiveDelta: number;
|
|
37
|
+
/** Clone of the fractional accumulator just before this step is applied. */
|
|
38
|
+
statesBefore: ActionSequenceStateSnapshot;
|
|
39
|
+
/** Clone of the fractional accumulator just after this step is applied. */
|
|
40
|
+
statesAfter: ActionSequenceStateSnapshot;
|
|
41
|
+
/** This step's own propagation edges — the exact same computation (single
|
|
42
|
+
* pass, computeActionPropagationDetails) that produced statesBefore →
|
|
43
|
+
* statesAfter, against the real rolled-forward state this step saw. Lets
|
|
44
|
+
* callers build a descriptive breakdown (e.g. UI badges) that's guaranteed
|
|
45
|
+
* consistent with the state diff, without re-running propagation. */
|
|
46
|
+
edges: PropagatedActionEdge[];
|
|
47
|
+
};
|
|
48
|
+
export declare function projectGhostStateForActionSequence(params: {
|
|
49
|
+
component: YinYangInternalModel["components"][number] | undefined;
|
|
50
|
+
allComponents: YinYangInternalModel["components"] | undefined;
|
|
51
|
+
actions: SequentialActionProjectionInput[];
|
|
52
|
+
actionDelta: number;
|
|
53
|
+
actionPropagationFactor: number;
|
|
54
|
+
/** Delta effectif par action (index-aligné sur `actions`). Quand fourni,
|
|
55
|
+
* remplace `actionDelta` pour chaque action individuellement. */
|
|
56
|
+
actionDeltas?: number[];
|
|
57
|
+
/** Called once per action, exposing the fractional accumulator state right
|
|
58
|
+
* before and right after that step — lets callers read the exact marginal
|
|
59
|
+
* contribution of a single stacked action within the real sequential
|
|
60
|
+
* simulation (e.g. the STACK panel's per-block delta). No effect on the
|
|
61
|
+
* returned projection. */
|
|
62
|
+
onStep?: (info: ActionSequenceStepInfo) => void;
|
|
63
|
+
}): GhostProjectionResult | null;
|
|
64
|
+
export declare function projectGhostStateForComponent(params: {
|
|
65
|
+
component: YinYangInternalModel["components"][number] | undefined;
|
|
66
|
+
allComponents: YinYangInternalModel["components"] | undefined;
|
|
67
|
+
sourceOddId: string | undefined;
|
|
68
|
+
sourceCuttingIndex: number;
|
|
69
|
+
actionDelta: number;
|
|
70
|
+
actionPropagationFactor: number;
|
|
71
|
+
}): GhostProjectionResult | null;
|
|
72
|
+
export declare function getOriginalComponentTension(component: YinYangInternalModel["components"][number] | undefined): number | null;
|
|
73
|
+
export declare function getOriginalOddTension(component: YinYangInternalModel["components"][number] | undefined, oddId: string): number | null;
|