@micheeeeel/yinyangapp 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/bundle.css +1 -0
  2. package/dist/bundle.js +1 -2
  3. package/dist/types/adapters/yasuniCauseAdapter.d.ts +3 -0
  4. package/dist/types/adapters/yinYangAdapter.d.ts +7 -0
  5. package/dist/types/animations/AnimationsMngr.d.ts +69 -15
  6. package/dist/types/animations/FrameScheduler.d.ts +99 -0
  7. package/dist/types/animations/rotationMotion.d.ts +43 -0
  8. package/dist/types/api.d.ts +17 -2
  9. package/dist/types/benchmark/runner.d.ts +20 -0
  10. package/dist/types/benchmark/scenarios.d.ts +55 -6
  11. package/dist/types/components/controller/YinYangController.d.ts +104 -14
  12. package/dist/types/components/controller/action-stack/ActionStackController.d.ts +16 -1
  13. package/dist/types/components/controller/action-stack/ActionStackDragHandler.d.ts +4 -0
  14. package/dist/types/components/controller/action-stack/ActionStackManager.d.ts +13 -2
  15. package/dist/types/components/controller/action-stack/ActionStackState.d.ts +8 -5
  16. package/dist/types/components/controller/action-stack/StackFocusController.d.ts +8 -7
  17. package/dist/types/components/controller/action-stack/stackChromePalette.d.ts +20 -0
  18. package/dist/types/components/controller/actions/ActionProjectionService.d.ts +16 -1
  19. package/dist/types/components/controller/actions/ChildActionMenuController.d.ts +74 -32
  20. package/dist/types/components/controller/actions/KeyEventController.d.ts +78 -70
  21. package/dist/types/components/controller/actions/{CoreEventMenuController.d.ts → KeyEventMenuController.d.ts} +28 -33
  22. package/dist/types/components/controller/actions/radialItemMenu.d.ts +43 -5
  23. package/dist/types/components/controller/children/ChildInteractionController.d.ts +4 -0
  24. package/dist/types/components/controller/children/ChildrenBuilder.d.ts +3 -1
  25. package/dist/types/components/controller/children/ComponentSwitchCoordinator.d.ts +3 -1
  26. package/dist/types/components/controller/children/IdleFacettesController.d.ts +151 -0
  27. package/dist/types/components/controller/children/idleTabLayout.d.ts +95 -0
  28. package/dist/types/components/controller/children/idleTabMorph.d.ts +45 -0
  29. package/dist/types/components/controller/force-field/EventFieldLifecycleController.d.ts +14 -0
  30. package/dist/types/components/controller/force-field/EventFieldRenderer.d.ts +3 -3
  31. package/dist/types/components/controller/force-field/ForceFieldCanvasPainter.d.ts +99 -0
  32. package/dist/types/components/controller/force-field/ForceFieldComputationService.d.ts +9 -0
  33. package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +28 -57
  34. package/dist/types/components/controller/force-field/ForceFieldDetailsPresenter.d.ts +4 -1
  35. package/dist/types/components/controller/force-field/ForceFieldLifecycleController.d.ts +16 -1
  36. package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +10 -18
  37. package/dist/types/components/controller/force-field/IncomingForceFieldService.d.ts +2 -2
  38. package/dist/types/components/controller/force-field/PropagationAnimator.d.ts +2 -0
  39. package/dist/types/components/controller/force-field/keyEventPresentation.d.ts +47 -0
  40. package/dist/types/components/controller/force-field/propagation-viz/PropagationCometPlayer.d.ts +4 -0
  41. package/dist/types/components/controller/force-field/propagation-viz/propagationVizLists.d.ts +4 -2
  42. package/dist/types/components/controller/force-field/propagation-viz/propagationVizModel.d.ts +1 -0
  43. package/dist/types/components/controller/force-field/shieldViewModel.d.ts +6 -2
  44. package/dist/types/components/controller/force-field/types.d.ts +2 -1
  45. package/dist/types/components/controller/labels/ChildScoresDeltaRenderer.d.ts +7 -0
  46. package/dist/types/components/controller/labels/ComponentTitlePresenter.d.ts +13 -0
  47. package/dist/types/components/controller/labels/ContextLabelsRenderer.d.ts +16 -0
  48. package/dist/types/components/controller/labels/WeightPreviewRingRenderer.d.ts +6 -0
  49. package/dist/types/components/controller/odd/ChildrenOrbitManager.d.ts +76 -25
  50. package/dist/types/components/controller/odd/OddHighlightEffects.d.ts +2 -0
  51. package/dist/types/components/controller/odd/OddViewManager.d.ts +7 -3
  52. package/dist/types/components/controller/odd/childHighlightStyles.d.ts +45 -3
  53. package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +8 -5
  54. package/dist/types/components/controller/settings/ControllerSettingsApplier.d.ts +4 -4
  55. package/dist/types/components/controller/state/ControllerSession.d.ts +3 -3
  56. package/dist/types/components/controller/state/ControllerUiCallbacks.d.ts +10 -0
  57. package/dist/types/components/controller/state/YinYangControllerState.d.ts +20 -9
  58. package/dist/types/components/controller/types.d.ts +9 -2
  59. package/dist/types/components/controller/utils/actionCatalog.d.ts +1 -1
  60. package/dist/types/components/controller/utils/eventFieldTargets.d.ts +19 -13
  61. package/dist/types/components/controller/utils/keyEventPropagationContext.d.ts +4 -0
  62. package/dist/types/components/controller/utils/keyEventTargetBreakdowns.d.ts +4 -0
  63. package/dist/types/components/controller/utils/svgTransform.d.ts +16 -0
  64. package/dist/types/components/controls/VizControlsPanel.d.ts +3 -1
  65. package/dist/types/components/panel/PanelManager.d.ts +92 -22
  66. package/dist/types/components/search/GlobalSearchController.d.ts +13 -6
  67. package/dist/types/components/view/BorderDrawer.d.ts +40 -14
  68. package/dist/types/components/view/IdleTabGridDrawer.d.ts +15 -0
  69. package/dist/types/components/view/SpikeDrawer.d.ts +18 -0
  70. package/dist/types/components/view/ViewInitializer.d.ts +53 -13
  71. package/dist/types/components/view/YinYangDrawer.d.ts +139 -40
  72. package/dist/types/components/view/borderColorCycle.d.ts +76 -0
  73. package/dist/types/components/workspace/facetWeightRuleSetting.d.ts +10 -0
  74. package/dist/types/components/workspace/workspaceTemplate.d.ts +1 -1
  75. package/dist/types/config/animationConfig.d.ts +10 -1
  76. package/dist/types/data/adverse-action-planner.d.ts +3 -3
  77. package/dist/types/data/amplifier-engine.d.ts +6 -6
  78. package/dist/types/data/key-event-effects.d.ts +30 -0
  79. package/dist/types/data/key-event-eligibility.d.ts +24 -0
  80. package/dist/types/data/key-event-propagation.d.ts +13 -0
  81. package/dist/types/data/key-event-types.d.ts +48 -0
  82. package/dist/types/data/key-event-validation.d.ts +11 -0
  83. package/dist/types/data/stability-shield.d.ts +14 -0
  84. package/dist/types/data/yasuni_adverse_key_events.d.ts +1 -1
  85. package/dist/types/data/yasuni_cause.d.ts +7 -0
  86. package/dist/types/data/yasuni_key_events.d.ts +4 -60
  87. package/dist/types/interfaces/ICauseModel.d.ts +12 -1
  88. package/dist/types/interfaces/IGraphicsStrategy.d.ts +9 -2
  89. package/dist/types/interfaces/IPropagationGraph.d.ts +14 -0
  90. package/dist/types/interfaces/IViewData.d.ts +10 -0
  91. package/dist/types/interfaces/IYinYangController.d.ts +25 -7
  92. package/dist/types/interfaces/IYinYangInternalModel.d.ts +5 -0
  93. package/dist/types/main.d.ts +0 -1
  94. package/dist/types/utils/actionIconFit.d.ts +23 -0
  95. package/dist/types/utils/actionPropagation.d.ts +6 -4
  96. package/dist/types/utils/causeMetrics.d.ts +50 -0
  97. package/dist/types/utils/chainCardHeight.d.ts +87 -4
  98. package/dist/types/utils/collapseAnimation.d.ts +39 -0
  99. package/dist/types/utils/d3/D3GraphicsStrategy.d.ts +28 -5
  100. package/dist/types/utils/deltaChips.d.ts +0 -4
  101. package/dist/types/utils/exportControls.d.ts +8 -0
  102. package/dist/types/utils/facetWeightLabel.d.ts +13 -0
  103. package/dist/types/utils/facetteImages.d.ts +6 -0
  104. package/dist/types/utils/glowHalo.d.ts +74 -0
  105. package/dist/types/utils/hierBadge.d.ts +1 -1
  106. package/dist/types/utils/keyEventImages.d.ts +1 -1
  107. package/dist/types/utils/menuIconSize.d.ts +17 -0
  108. package/dist/types/utils/spreadAngles.d.ts +8 -0
  109. package/package.json +4 -1
  110. package/dist/bundle.js.LICENSE.txt +0 -1
@@ -0,0 +1,24 @@
1
+ import type { ActionStackItem } from "../components/controller/action-stack/ActionStackState";
2
+ import type { KeyEventDefinition } from "./key-event-types";
3
+ /** EVT-08: an occupied event slot keeps half its nominal effect, including
4
+ * the first action. The shared Beta peak stays unchanged; combos keep their
5
+ * own 15% floor. See documentation/events-balance.md for measured arbitration. */
6
+ export declare const EVENT_MIN_POSITIONAL_STRENGTH = 0.5;
7
+ export declare function eventPositionStrength(slotDistance: number, withinNextN: number): number;
8
+ export interface EligibleKeyEvent {
9
+ eventId: string;
10
+ sourceItemId: string;
11
+ targetItemId: string;
12
+ /** Absolute slot distance, including unoccupied slots. */
13
+ slotDistance: number;
14
+ strength: number;
15
+ }
16
+ /** Shared eligibility for all five signatures. An event remains available on
17
+ * every slot of its window: no charge, consumption, or trigger counter. */
18
+ export declare function evaluateKeyEventEligibility(params: {
19
+ event: KeyEventDefinition;
20
+ sourceItem: ActionStackItem;
21
+ targetItem: ActionStackItem;
22
+ activeItemIds: ReadonlySet<string>;
23
+ actionDelta: number;
24
+ }): EligibleKeyEvent | null;
@@ -0,0 +1,13 @@
1
+ import { type CompiledEdge, type CompiledPropagationGraph, type SatelliteRef } from "../interfaces/IPropagationGraph";
2
+ import type { ResolvedKeyEvent } from "./key-event-effects";
3
+ export type KeyEventPropagationContext = {
4
+ actionId: string;
5
+ source: SatelliteRef;
6
+ /** Actual source satellite's action catalogue, not the event's target list. */
7
+ applicableActionIds: readonly string[];
8
+ eligibleEvents: readonly ResolvedKeyEvent[];
9
+ };
10
+ /** Resolution-local first hops. No writes to graph, catalogue or event data.
11
+ * RAYONNEMENT adds weighted boosts before one clamp. PORTÉE contributions
12
+ * remain separate (including equal endpoints), in stable event/bridge order. */
13
+ export declare function resolveKeyEventPropagationEdges(graph: CompiledPropagationGraph, source: SatelliteRef, context: KeyEventPropagationContext | undefined, exists: (ref: SatelliteRef) => boolean): readonly CompiledEdge[];
@@ -0,0 +1,48 @@
1
+ import type { SatelliteRef } from "../interfaces/IPropagationGraph";
2
+ export type AmplifierSignature = {
3
+ type: "amplifier";
4
+ deltaBonus: number;
5
+ weightBonus?: number;
6
+ };
7
+ export type RayonnementSignature = {
8
+ type: "rayonnement";
9
+ propagationBoost: number;
10
+ };
11
+ export type StabiliteSignature = {
12
+ type: "stabilite";
13
+ shield: number;
14
+ };
15
+ export type GarantieSignature = {
16
+ type: "garantie";
17
+ minBaseDeltaRatio: number;
18
+ };
19
+ export type PorteeSignature = {
20
+ type: "portee";
21
+ bridges: EventPropagationBridge[];
22
+ };
23
+ /** Temporary causal edge; resolved only for an eligible action (EVT-04). */
24
+ export interface EventPropagationBridge {
25
+ from: SatelliteRef;
26
+ to: SatelliteRef;
27
+ w: number;
28
+ rationale: string;
29
+ triggerActionIds?: string[];
30
+ }
31
+ export type KeyEventSignature = AmplifierSignature | RayonnementSignature | StabiliteSignature | GarantieSignature | PorteeSignature;
32
+ export interface KeyEventDefinition {
33
+ id: string;
34
+ alignment: "ally" | "adverse";
35
+ name: string;
36
+ shortDescription: string;
37
+ description: string;
38
+ origin: {
39
+ kind: "facet";
40
+ componentId: string;
41
+ };
42
+ /** Attribution of an adverse event, separate from its facet origin. */
43
+ originLabel?: string;
44
+ targetedActionIds: string[];
45
+ withinNextN: number;
46
+ signature: KeyEventSignature;
47
+ }
48
+ export declare function isAdverseKeyEvent(event: KeyEventDefinition): boolean;
@@ -0,0 +1,11 @@
1
+ import type { KeyEventDefinition } from "./key-event-types";
2
+ import type { ActionDefinition } from "./yasuni_actions";
3
+ import type { Composante } from "./yasuni_cause";
4
+ export interface KeyEventDiagnostic {
5
+ eventId: string;
6
+ path: string;
7
+ message: string;
8
+ }
9
+ /** Read-only catalogue validation. No edge is ever added to the cause graph. */
10
+ export declare function validateKeyEvents(events: readonly KeyEventDefinition[], actions: readonly ActionDefinition[], cause: readonly Composante[]): KeyEventDiagnostic[];
11
+ export declare function formatKeyEventDiagnostics(diagnostics: readonly KeyEventDiagnostic[]): string;
@@ -19,3 +19,17 @@ export declare function applyStabilityShield(aggregatedDelta: number, shield: nu
19
19
  * bouclier plus faible ne dégrade jamais celui déjà en place.
20
20
  */
21
21
  export declare function mergeStabilityShield(current: number | undefined, incoming: number): number;
22
+ /** Persisted scalar shields are always allied, irrespective of the last action. */
23
+ export type ProtectedSign = 1 | -1;
24
+ export type DirectionalShield = {
25
+ magnitude: number;
26
+ protectedSign: ProtectedSign;
27
+ };
28
+ export type StabilityProtection = number | DirectionalShield[];
29
+ export declare function normalizeStabilityProtection(value: StabilityProtection | undefined): DirectionalShield[];
30
+ export declare function mergeDirectionalShield(current: StabilityProtection | undefined, incoming: DirectionalShield): DirectionalShield[];
31
+ /** Filter each signed aggregate once. No consumption and no cross-direction cancellation. */
32
+ export declare function filterDirectionalContributions(positive: number, negative: number, protection: StabilityProtection): {
33
+ positive: number;
34
+ negative: number;
35
+ };
@@ -1,2 +1,2 @@
1
- import type { KeyEventDefinition } from "./yasuni_key_events";
1
+ import type { KeyEventDefinition } from "./key-event-types";
2
2
  export declare const yasuniAdverseKeyEvents: KeyEventDefinition[];
@@ -26,6 +26,13 @@ export interface Composante {
26
26
  id: string;
27
27
  name: string;
28
28
  orientation?: "yin" | "yang";
29
+ /** Notion parente commune à des facettes d'orientations opposées (ex. la
30
+ * Gouvernance, déclinée en une facette yin et une facette yang). Les
31
+ * facettes qui la partagent sont regroupées dans la vue Idle « tab ». */
32
+ notion?: {
33
+ id: string;
34
+ name: string;
35
+ };
29
36
  /** Vue d'ensemble des enjeux et des dynamiques propres à cette composante. */
30
37
  description?: string;
31
38
  odds: ODD[];
@@ -1,62 +1,6 @@
1
- export interface KeyEventEffect {
2
- /**
3
- * Bonus additif nominal au pic de la fenêtre. Pour un slot occupé éligible,
4
- * pondération positionnelle avec plancher 0,15 ; aucun effet si la cible est
5
- * absente ou hors fenêtre. Voir positionalBonus (amplifier-engine.ts).
6
- * Appliqué dans la direction du delta effectif de l'action (après combos),
7
- * jamais sur une action au delta nul. Additif et non multiplicatif : un
8
- * ratio réduit par la position devenait fractionnaire et se faisait
9
- * absorber par l'arrondi du poids ; un montant en points permet aussi à
10
- * un futur malus (bonus négatif) de s'annuler exactement avec lui.
11
- */
12
- scoreBonus: number;
13
- /**
14
- * Bonus ADDITIF de poids (en points entiers), au pic de la fenêtre.
15
- * Renforce le weightDelta de l'action ciblée dans sa propre direction
16
- * (alléger ou alourdir) — sans effet sur une action sans weightDelta.
17
- * L'arrondi à l'entier se fait par événement à l'évaluation, jamais sur
18
- * un total fractionnaire : ce que la carte affiche est ce qui s'applique.
19
- */
20
- weightBonus: number;
21
- }
22
- export interface KeyEventDefinition {
23
- id: string;
24
- name: string;
25
- shortDescription: string;
26
- description: string;
27
- /** Facette (Composante.id) depuis laquelle l'événement se déclenche. */
28
- originComposanteId: string;
29
- /**
30
- * Actions amplifiées (par id), même logique que ComboCondition.requires.
31
- * Cohérence thématique obligatoire avec la facette d'origine.
32
- */
33
- targetedActionIds: string[];
34
- /**
35
- * Fenêtre temporelle AVANT laquelle l'amplification s'arrête — pendant
36
- * inverse de ComboCondition.withinLastN : une action ciblée jouée plus de
37
- * withinNextN slots après l'événement n'est plus amplifiée. Oblige le
38
- * joueur à réserver des emplacements libres après l'événement plutôt que
39
- * de le placer systématiquement tout en bas de la pile.
40
- */
41
- withinNextN?: number;
42
- effect: KeyEventEffect;
43
- /** Acteur à l'origine d'un Événement adverse (pouvoir politique,
44
- * industrie…), affiché en note de provenance sur son bloc — les
45
- * Événements Clés positifs n'en ont pas (ils émanent de la cause). */
46
- origin?: string;
47
- }
48
- /**
49
- * Un Événement adverse est une KeyEventDefinition ordinaire dont l'effet est
50
- * un MALUS (bonus négatifs) — même critère de signe qu'isAdverseAction, pas
51
- * un drapeau. Catalogue séparé (yasuni_adverse_key_events.ts), jamais listé
52
- * dans yasuniKeyEvents : le menu radial du cercle central et l'arbre
53
- * RECHERCHE, qui itèrent ce tableau, l'ignorent donc structurellement — seul
54
- * yasuniKeyEventMap (moteur, rendu de la pile) fusionne les deux catalogues.
55
- */
56
- export declare function isAdverseKeyEvent(keyEvent: KeyEventDefinition): boolean;
1
+ import type { KeyEventDefinition } from "./key-event-types";
2
+ export type * from "./key-event-types";
3
+ export { isAdverseKeyEvent } from "./key-event-types";
57
4
  export declare const yasuniKeyEvents: KeyEventDefinition[];
58
- /** Lookup O(1) par id, même convention que les autres catalogues — fusionne
59
- * Événements Clés ET Événements adverses : le moteur et le rendu de la pile
60
- * résolvent les deux ici, tandis que les surfaces utilisateur (menu radial,
61
- * arbre RECHERCHE) itèrent yasuniKeyEvents, sans les adverses. */
62
5
  export declare const yasuniKeyEventMap: Map<string, KeyEventDefinition>;
6
+ export declare const yasuniKeyEventDiagnostics: import("./key-event-validation").KeyEventDiagnostic[];
@@ -16,14 +16,25 @@ export interface CauseOddCutting {
16
16
  score: number;
17
17
  weight: number;
18
18
  }
19
+ /** Notion parente d'une facette : des facettes d'orientations opposées qui
20
+ * la partagent en sont les déclinaisons yin et yang (regroupées dans la vue
21
+ * Idle « tab »). */
22
+ export interface FacetNotion {
23
+ id: string;
24
+ name: string;
25
+ }
19
26
  export interface CauseComponent {
20
27
  id: string;
21
28
  name?: string;
22
29
  shortName?: string;
23
30
  description?: string;
24
31
  orientation: YinYangOrientation;
32
+ /** Notion parente (absente : la facette est seule de sa notion). */
33
+ notion?: FacetNotion;
25
34
  odds: CauseOdd[];
26
- /** Somme brute des poids de tous les satellites de la facette. */
35
+ /** Poids de la facette (taille relative de son arc) : C_f, moyenne des
36
+ * poids de TOUS ses satellites, zéros inclus, de 0 à 10 — même règle pour
37
+ * une cause et pour un contact (`facetWeight`, POC-05A4). */
27
38
  perimeterWeight: number;
28
39
  }
29
40
  export interface Cause {
@@ -18,10 +18,17 @@ export interface IGraphicsStrategy {
18
18
  color: string;
19
19
  opacity: number;
20
20
  }[], gradientUnits: string): IGraphicElement;
21
+ /** Retire du <defs> les éléments (masques, dégradés…) portant ces ids. */
22
+ removeDefsByIds(ids: Iterable<string>): void;
21
23
  createYinOrYangArcMask(id: string, cx: number, cy: number, innerRadius: number, outerRadius: number, startAngle: number, endAngle: number, type: "yin" | "yang", blendOpacity?: number): string;
24
+ /** Met à jour en place un masque de createYinOrYangArcMask (frame de
25
+ * transition) ; false s'il manque, l'appelant refait alors un rendu complet. */
26
+ updateYinOrYangArcMask(id: string, cx: number, cy: number, innerRadius: number, outerRadius: number, startAngle: number, endAngle: number, type: "yin" | "yang", blendOpacity?: number): boolean;
22
27
  createBorderMask(id: string, cx: number, cy: number, innerRadius: number, outerRadius: number): void;
23
- changeBorderColors(gradient: any, duration: number, colors: string[]): void;
24
28
  drawLineWithGradient(parent: IGraphicElement, x1: number, y1: number, x2: number, y2: number, gradientId: string): void;
25
29
  createUnderlyingCircleGradient(id: string, color: string, spread?: number, intensity?: number): string;
26
- createUnderlyingCircleWithArcMask(maskId: string | undefined, gradientId: string, parent: IGraphicElement, cx: number, cy: number, radius: number): void;
30
+ /** Repeint en place un dégradé de createUnderlyingCircleGradient ; false
31
+ * s'il manque. */
32
+ updateUnderlyingCircleGradientColor(id: string, color: string, spread?: number, intensity?: number): boolean;
33
+ createUnderlyingCircleWithArcMask(maskId: string | undefined, gradientId: string, parent: IGraphicElement, cx: number, cy: number, radius: number): IGraphicElement;
27
34
  }
@@ -22,6 +22,20 @@ export type PropagationScope = "local" | "inter-odd" | "inter-facette";
22
22
  export type CompiledEdge = PropagationTarget & {
23
23
  from: SatelliteRef;
24
24
  scope: PropagationScope;
25
+ eventPropagation?: EventPropagationMetadata;
26
+ };
27
+ /** Explanatory provenance, preserved on applied hops and Bilan details. */
28
+ export type EventPropagationMetadata = {
29
+ kind: "rayonnement" | "portee";
30
+ originalWeight: number;
31
+ sources: readonly {
32
+ eventId: string;
33
+ eventName: string;
34
+ sourceItemId: string;
35
+ strength: number;
36
+ parameter: number;
37
+ bridgeIndex?: number;
38
+ }[];
25
39
  };
26
40
  export type PropagationGraphRule = "V1" | "V2" | "V3" | "V4" | "V5" | "V6" | "V7";
27
41
  export type PropagationGraphDiagnostic = {
@@ -23,4 +23,14 @@ export interface IViewData {
23
23
  * (voir YinYangDrawer.renderChildWeightGauge). Absent pour les patterns
24
24
  * qui ne sont pas des satellites. */
25
25
  weight?: number;
26
+ /** Libellé de poids déjà formaté, affiché tel quel dans la pastille du
27
+ * satellite au lieu de l'entier arrondi de `weight`. Posé pour les
28
+ * satellites-facettes : c'est celui de l'arc de leur facette
29
+ * (facetWeightLabel — « 5,5 » en règle `mean`, « 61 » en règle `sum`). */
30
+ weightLabel?: string;
31
+ /** Angle imposé (radians, repère SVG : 0 = 3 h, sens horaire) auquel ce
32
+ * satellite se place autour de son parent, au lieu de la répartition
33
+ * uniforme par index. Posé pour les satellites-facettes du sous-état
34
+ * Idle « facettes », alignés sur le milieu de l'arc de leur facette. */
35
+ angleOverride?: number;
26
36
  }
@@ -10,6 +10,12 @@ export interface IYinYangController {
10
10
  factory: IYinYangAppFactory;
11
11
  animator: IAnimator;
12
12
  createYinYangChildren(): void;
13
+ /** Fin de vie : arrête toutes les boucles d'animation du contrôleur et de
14
+ * ses satellites (champ de force, orbite, rotation, ghost, étincelles,
15
+ * comètes…), déconnecte ses observers et libère ses defs. Le contrôleur
16
+ * n'est plus utilisable ensuite. Idempotent. Le DOM du diagramme est
17
+ * vidé par l'appelant (voir mountYinYang). */
18
+ destroy(): void;
13
19
  clearForceFieldDetails(): void;
14
20
  applyChildrenFitScale(): void;
15
21
  setChildrenEnabled(isEnabled: boolean): void;
@@ -122,9 +128,9 @@ export interface IYinYangController {
122
128
  * Fine (px) adjustment of the Key Event radial menu buttons' distance,
123
129
  * layered on top of the auto-computed base distance.
124
130
  */
125
- setCoreEventMenuDistanceOffset(offset: number): void;
126
- setCoreEventMenuItemScale(scale: number): void;
127
- setCoreEventIconFontScale(scale: number): void;
131
+ setKeyEventMenuDistanceOffset(offset: number): void;
132
+ setKeyEventMenuItemScale(scale: number): void;
133
+ setKeyEventIconFontScale(scale: number): void;
128
134
  /**
129
135
  * Sets maximum number of lines for child labels (1-3).
130
136
  */
@@ -136,6 +142,18 @@ export interface IYinYangController {
136
142
  setLabelShortMaxChars(chars: number): void;
137
143
  isChildrenEnabled(): boolean;
138
144
  isActionActive(): boolean;
145
+ /** Sous-état d'Idle : arcs pondérés ou un satellite yin/yang par facette. */
146
+ getIdleView(): "arcs" | "facettes" | "tab";
147
+ setIdleView(view: "arcs" | "facettes" | "tab"): Promise<void>;
148
+ /** Crochets de l'hôte autour du sous-état Idle « tab » (voir
149
+ * YinYangController.setIdleTabHooks). */
150
+ setIdleTabHooks(hooks: {
151
+ beforeEnter?: () => Promise<void> | void;
152
+ afterLeave?: () => Promise<void> | void;
153
+ } | null): void;
154
+ setOnIdleViewChange(callback: ((view: "arcs" | "facettes" | "tab") => void) | null): void;
155
+ toggleIdleView(): Promise<void>;
156
+ isIdleFacettesActive(): boolean;
139
157
  /**
140
158
  * Sets font scale for action stack item labels.
141
159
  */
@@ -269,10 +287,10 @@ export interface IYinYangController {
269
287
  /** Called by YinYangDrawer when the user clicks an ODD arc: toggles that
270
288
  * ODD's legend chip in the panel, mirroring a direct chip click. */
271
289
  onDiagramOddArcClicked(oddId: string): void;
272
- /** Called by YinYangDrawer when the user clicks the small "eye" circle of
273
- * the facette's dominant lobe (yin or yang, per Composante.orientation) —
274
- * opens/closes the radial menu of Événements Clés for the active facette. */
275
- onCoreEventNucleusClicked(): void;
290
+ /** Called by YinYangDrawer when the user clicks the core of the facette's
291
+ * dominant lobe (yin or yang, per Composante.orientation) while a Facette
292
+ * is open — closes it and shows the cause in Idle « facettes ». */
293
+ onFacetteCoreClicked(): void;
276
294
  /** Wires a callback fired when the user clicks a composante border, cutting, or action in the diagram. */
277
295
  setOnDiagramNavChange(cb: (event: {
278
296
  type: "composante";
@@ -26,6 +26,11 @@ export interface YinYangComponentNode {
26
26
  label?: string;
27
27
  shortLabel?: string;
28
28
  orientation: YinYangOrientation;
29
+ /** Notion parente — voir `FacetNotion` (ICauseModel). */
30
+ notion?: {
31
+ id: string;
32
+ name: string;
33
+ };
29
34
  odds: YinYangOddNode[];
30
35
  }
31
36
  export interface YinYangInternalModel {
@@ -6,4 +6,3 @@ import "./styles/search.css";
6
6
  import "./styles/delta-chips.css";
7
7
  import "./styles/action-image.css";
8
8
  export * from "./api";
9
- import "./benchmark/runner";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Facteur de taille maximal des icônes d'action pour qu'elles tiennent dans
3
+ * leur bulle (groupe debug "Grappe actions" › "Taille icônes").
4
+ *
5
+ * Les SVG partagent un viewBox 64×64 mais leur dessin n'occupe pas tous la
6
+ * même surface : certains (satellite, barrières flottantes…) remplissent les
7
+ * coins et débordaient du cercle de la bulle. On rastérise chaque icône une
8
+ * fois pour mesurer son rayon réel (trait compris), puis on en déduit le
9
+ * facteur au-delà duquel le dessin franchirait l'anneau.
10
+ */
11
+ /** Taille de l'icône rapportée au rayon de la bulle, pour l'action active —
12
+ * la plus grande des deux variantes rendues par ChildActionMenuController. */
13
+ export declare const ACTIVE_ACTION_ICON_SIZE_RATIO = 1.85;
14
+ export declare function scaleFittingExtent(extent: number): number;
15
+ /** Plus grand facteur qui fait tenir toutes les icônes mesurées jusqu'ici
16
+ * (Infinity tant qu'aucune ne l'a été). */
17
+ export declare function getActionIconFitScale(): number;
18
+ export declare function onActionIconFitScaleChange(listener: (fitScale: number) => void): () => void;
19
+ /** Lance la mesure des icônes pas encore vues ; les abonnés sont prévenus
20
+ * chaque fois que le facteur admissible baisse. La promesse se résout quand
21
+ * toutes les icônes demandées sont mesurées, pour retoucher celles déjà
22
+ * affichées. */
23
+ export declare function measureActionIcons(urls: readonly string[]): Promise<void>;
@@ -1,4 +1,5 @@
1
- import { type CompiledPropagationGraph, type PropagationScope, type SatelliteKey } from "../interfaces/IPropagationGraph";
1
+ import { type KeyEventPropagationContext } from "../data/key-event-propagation";
2
+ import { type EventPropagationMetadata, type CompiledPropagationGraph, type PropagationScope, type SatelliteKey } from "../interfaces/IPropagationGraph";
2
3
  import { YinYangComponentNode } from "../interfaces/IYinYangInternalModel";
3
4
  export type Action = {
4
5
  id: string;
@@ -14,6 +15,7 @@ export type Action = {
14
15
  * ODD, autre facette — sont produites par le même parcours.
15
16
  */
16
17
  export type PropagatedActionEdge = {
18
+ eventPropagation?: EventPropagationMetadata;
17
19
  scope: PropagationScope;
18
20
  fromComponentId: string;
19
21
  toComponentId: string;
@@ -112,7 +114,7 @@ export type ActionPropagationDetails = ProjectedActionStateDetails & {
112
114
  * `allComponents` fournit l'état de base des autres facettes ; sans lui, les
113
115
  * sauts qui sortent de `component` sont ignorés.
114
116
  */
115
- export declare function computeActionPropagationDetails(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[]): ActionPropagationDetails;
117
+ export declare function computeActionPropagationDetails(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[], eventPropagation?: KeyEventPropagationContext): ActionPropagationDetails;
116
118
  /**
117
119
  * Arrivée dans `component` d'une arête venue d'une autre composante, déjà
118
120
  * calculée par la résolution de l'action (voir computeActionPropagationDetails).
@@ -141,6 +143,6 @@ export type IncomingLocalContinuation = {
141
143
  * autre ODD de la même composante est poursuivie comme une arête locale.
142
144
  */
143
145
  export declare function computeIncomingLocalContinuation(component: YinYangComponentNode, entry: IncomingPropagationEntry, graph: CompiledPropagationGraph): IncomingLocalContinuation;
144
- export declare function propagateForceFieldActionInComponent(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[]): PropagatedActionEdge[];
145
- export declare function projectActionStateDetailsInComponent(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[]): ProjectedActionStateDetails;
146
+ export declare function propagateForceFieldActionInComponent(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[], eventPropagation?: KeyEventPropagationContext): PropagatedActionEdge[];
147
+ export declare function projectActionStateDetailsInComponent(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[], eventPropagation?: KeyEventPropagationContext): ProjectedActionStateDetails;
146
148
  export {};
@@ -5,9 +5,58 @@ export declare function clampScore(value: number): number;
5
5
  * Canonical domain metric in [0, 1]. Weighted by each satellite's `weight`
6
6
  * when provided, so a heavier satellite pulls the tension further toward
7
7
  * its own score; falls back to a simple average otherwise.
8
+ *
9
+ * ⚠️ FACETTES D'UN CONTACT : cette règle est reproduite à l'identique par
10
+ * yvy-backend (`src/contacts/contact-facets.ts`), qui fait autorité pour le
11
+ * jeu. Deux implémentations à maintenir identiques : toute évolution met à
12
+ * jour les deux, ainsi que le fichier de cas commun
13
+ * `src/data/contacts/contact-facets.reference.json` (POC-05A2).
8
14
  */
9
15
  export declare function tensionFromCuttings(cuttingScores: number[], cuttingWeights?: number[]): number;
10
16
  export declare const oddTensionFromCuttings: typeof tensionFromCuttings;
17
+ /**
18
+ * RÈGLE DES POIDS DE FACETTE, commutable pour comparaison (debug de la page
19
+ * standalone, clé localStorage `spheres.facetWeightRule`) :
20
+ * - `mean` (défaut, POC-05A4) : C_f = moyenne des poids de tous les
21
+ * satellites ; Q_f = moyenne pondérée sur tous les satellites, repli sur
22
+ * leur moyenne simple ;
23
+ * - `sum` (ancienne règle) : poids = somme des poids ; Q_f = tension de
24
+ * chaque catégorie pondérée par la somme de ses poids, repli par
25
+ * catégorie sur son nombre de satellites.
26
+ * La lib npm reste en `mean` : seule la page standalone la change.
27
+ */
28
+ export type FacetWeightRule = "mean" | "sum";
29
+ export declare function getFacetWeightRule(): FacetWeightRule;
30
+ export declare function setFacetWeightRule(rule: FacetWeightRule): void;
31
+ /** Satellites d'une catégorie (ODD) d'une facette : tensions et poids. */
32
+ interface FacetOddCuttings {
33
+ cuttingScores: readonly number[];
34
+ cuttingWeights: readonly number[];
35
+ }
36
+ /**
37
+ * Tension d'une FACETTE (cause ou contact). Règle `mean` (POC-05A4) :
38
+ * `tensionFromCuttings` sur TOUS ses satellites, catégories confondues —
39
+ * moyenne pondérée par les poids, ou moyenne simple de la facette si tous
40
+ * ses poids sont nuls. Règle `sum` : voir `FacetWeightRule`.
41
+ * Q_f = (1 − T) × 100. `cuttingTensions` remplace les tensions de la
42
+ * catégorie d'indice donné (projection d'une action) ; une catégorie dont
43
+ * les poids ne sont pas alignés sur les scores compte ses satellites à 1.
44
+ * Facette sans satellite : 0,5.
45
+ */
46
+ export declare function facetTensionFromOdds(odds: readonly FacetOddCuttings[], cuttingTensions?: (oddIndex: number) => readonly number[] | undefined): number;
47
+ /**
48
+ * POIDS d'une facette — ou d'une catégorie, pour sa pastille. Règle `mean`
49
+ * (défaut, POC-05A4) : C_f, moyenne arithmétique des poids (bornés à 0) de
50
+ * TOUS ses satellites, zéros inclus, de 0 à 10, indépendante de leur nombre.
51
+ * Règle `sum` : leur somme. Fixe la taille des arcs de facette et la valeur
52
+ * des pastilles. Facettes d'un contact, règle `mean` : reproduite à
53
+ * l'identique par yvy-backend (`contactFacetWeights`), cas communs dans
54
+ * `src/data/contacts/contact-facets.reference.json`.
55
+ */
56
+ export declare function facetWeight(weights: readonly number[]): number;
57
+ /** Plafond de `facetWeight` pour `count` satellites : 10 (`mean`) ou
58
+ * `count × 10` (`sum`). */
59
+ export declare function facetWeightMax(count: number): number;
11
60
  export declare function stateFromTension(tension: number): number;
12
61
  /** Bornes du poids d'un satellite (importance dans sa facette). Un satellite
13
62
  * vaut 1 par défaut ; les actions le font varier par pas entiers, mais ne
@@ -24,3 +73,4 @@ export declare function clampWeight(value: number): number;
24
73
  * signe — ex: +1 sur un satellite déjà à WEIGHT_MAX ne change rien.
25
74
  */
26
75
  export declare function effectiveWeightDelta(currentWeight: number, delta: number): number;
76
+ export {};
@@ -1,3 +1,80 @@
1
+ export type DetailDensity = "full" | "reduced" | "compact";
2
+ export interface DetailDensityInput {
3
+ /** Hauteur visible du conteneur (clientHeight). */
4
+ available: number;
5
+ /** Hauteur de la description dépliée (0 si aucune). */
6
+ descFullH: number;
7
+ /** Hauteur de la description repliée (= descFullH si l'utilisateur l'a dépliée). */
8
+ descFoldedH: number;
9
+ /** Habillage d'un bloc hors carte (marges, en-têtes du bloc). */
10
+ chrome: number;
11
+ /** Nombre de blocs de cartes affichés. */
12
+ blockCount: number;
13
+ /** Hauteur occupée par le reste du contenu (ni description ni bloc). */
14
+ other?: number;
15
+ /** Palier précédent, pour l'hystérésis. */
16
+ previous?: DetailDensity | null;
17
+ }
18
+ export interface DetailDensityResult {
19
+ density: DetailDensity;
20
+ /** null = hauteur de carte par défaut (pas de variable posée). */
21
+ cardHeight: number | null;
22
+ foldDesc: boolean;
23
+ }
24
+ /**
25
+ * Choisit la densité d'une colonne de détail d'après la hauteur réellement
26
+ * libre — pas d'après le nombre de panneaux ouverts :
27
+ * - full : description entière et cartes au format nominal (352px) ;
28
+ * - reduced : description repliée sur une ligne, cartes réduites
29
+ * (≥ REDUCED_MIN_CARD_HEIGHT), haut de l'illustration visible ;
30
+ * - compact : description repliée, cartes au plus court, haut de
31
+ * l'illustration visible.
32
+ * Au-delà de deux blocs, on vise deux blocs visibles et le scroll prend le
33
+ * relais (même règle que l'ancien comportement multi-blocs).
34
+ */
35
+ export declare function computeDetailDensity(input: DetailDensityInput): DetailDensityResult;
36
+ export interface StackCardHeightInput {
37
+ /** Hauteur utile du conteneur (clientHeight moins ses paddings). */
38
+ available: number;
39
+ /** Habillage (en-tête, description, marges) de chaque bloc déplié, dans
40
+ * l'ordre d'affichage. */
41
+ expandedChromes: number[];
42
+ /** Hauteur de tout le reste : blocs repliés, bandeau Σ. */
43
+ other: number;
44
+ previous?: DetailDensity | null;
45
+ }
46
+ /**
47
+ * STACK : hauteur des cartes pour que les blocs dépliés remplissent la place
48
+ * libre. Jusqu'à deux blocs dépliés, tout le panneau (blocs repliés et
49
+ * bandeau Σ compris) doit tenir ; au-delà, on vise les deux premiers blocs
50
+ * et le scroll prend le relais. La carte ne dépasse jamais le format nominal
51
+ * (image entière) : au-delà, il ne resterait que du vide autour de l'image.
52
+ */
53
+ export declare function computeStackCardHeight(input: StackCardHeightInput): {
54
+ density: DetailDensity;
55
+ cardHeight: number | null;
56
+ };
57
+ export interface ChainCardHeightOptions {
58
+ blockSelector?: string;
59
+ /**
60
+ * RECHERCHE : ajuste les cartes à la hauteur libre du conteneur même avec un
61
+ * seul bloc (description comprise) et pose data-density. Sans cette option
62
+ * (STACK), seul le cas « 2 blocs ou plus » réduit les cartes.
63
+ */
64
+ fitToContainer?: boolean;
65
+ /**
66
+ * STACK : ajuste les cartes à la place libre en tenant compte des blocs
67
+ * repliés et du bandeau Σ (voir computeStackCardHeight), et pose
68
+ * data-density.
69
+ */
70
+ fitBlocks?: boolean;
71
+ }
72
+ /**
73
+ * Synchro immédiate d'un conteneur surveillé (watchChainCardHeight), avec ses
74
+ * options : à appeler au sein d'une bascule animée, pour que la hauteur
75
+ * finale mesurée tienne compte des cartes recalées. Sans effet sinon.
76
+ */
77
+ export declare function resyncChainCardHeightNow(container: HTMLElement): void;
1
78
  /**
2
79
  * Un seul bloc affiché : les cartes gardent leur hauteur par défaut, calée sur
3
80
  * le format des illustrations pour qu'elles s'affichent entières (cf.
@@ -6,7 +83,9 @@
6
83
  * tiennent dans la hauteur visible du conteneur sans scroll — au-delà, le
7
84
  * scroll prend le relais. L'image reste alors visible en entier mais plus
8
85
  * petite, avec une bande vide en haut et en bas (object-fit: contain, cf.
9
- * action-image.css) : c'est la hauteur qui cède, jamais le cadrage.
86
+ * action-image.css) : c'est la hauteur qui cède, jamais le cadrage — sauf
87
+ * avec `fitToContainer`, où la carte réduite garde le haut de l'image.
88
+ * Avec `fitToContainer` (RECHERCHE), voir computeDetailDensity.
10
89
  *
11
90
  * La variable CSS est posée à la fois sur le conteneur ET directement sur
12
91
  * chaque `.ff-chain-card` : quand un bloc est ajouté après coup (RECHERCHE,
@@ -15,13 +94,17 @@
15
94
  * `height` déjà calculé des cartes existantes — le poser directement sur
16
95
  * chaque carte contourne ce cas.
17
96
  */
18
- export declare function syncChainCardHeight(container: HTMLElement, blockSelector?: string): void;
97
+ export declare function syncChainCardHeight(container: HTMLElement, options?: ChainCardHeightOptions): void;
19
98
  /**
20
99
  * Recalcule immédiatement puis surveille le conteneur pour garder la hauteur
21
100
  * des cartes synchronisée : redimensionnement du panneau (ResizeObserver) et
22
101
  * ajout/retrait de blocs (MutationObserver — un bloc peut être ajouté/retiré
23
102
  * sans que la taille du conteneur lui-même ne change, ex. panneau RECHERCHE
24
- * où le bloc secondaire propagé apparaît/disparaît). Idempotent : un seul
103
+ * où le bloc secondaire propagé apparaît/disparaît). Avec `fitToContainer`,
104
+ * le sous-arbre est aussi observé : une description remplacée ou des cartes
105
+ * re-rendues changent la place disponible. Seules les insertions/retraits de
106
+ * nœuds sont observés (pas les attributs) : les classes et styles posés par
107
+ * la synchro elle-même ne la redéclenchent donc pas. Idempotent : un seul
25
108
  * couple d'observers est installé par conteneur.
26
109
  */
27
- export declare function watchChainCardHeight(container: HTMLElement, blockSelector?: string): void;
110
+ export declare function watchChainCardHeight(container: HTMLElement, options?: ChainCardHeightOptions): void;