import { Class_DrawingArea } from './DrawingArea'; import { ElementStyleConfigsDict, ElementStyleKey } from '../Elements/ElementStyle'; import { Class_LinkElement } from '../Elements/Link'; import { Class_NodeElement } from '../Elements/Node'; import type { Class_NodeBase } from '../Elements/NodeBase'; import { Class_NodeDimension } from '../Elements/NodeDimension'; import { Class_DataTag } from '../types/Tag'; import { Class_NodeTagGroup, Class_FluxTagGroup, Class_DataTagGroup, Class_LevelTagGroup, Class_ViewTagGroup } from './TagGroup'; import { Class_Theme } from './Theme'; import { Class_UnitsRegistry } from './Units'; import type { Type_DeterminationCatalog } from './Determination'; import { Type_MacroTagGroup } from '../types/Utils'; import { ALL_ATTRIBUTES_CONFIG } from '../Elements/ElementsAttributesConfig'; import { Class_ElementStyle, Class_ProtoElement } from '../Elements/Element'; import { Class_ContainerElement } from '../Elements/TextZone'; import type { Type_UnitaryProcess } from './UnitaryProcess'; export type Type_RatioFluxConstraint = { origin: string; destination: string; origin_ref: string; destination_ref: string; coef: number | null; min: number | null; max: number | null; data_tag: string | null; data_tag_ref: string | null; traduction: string | null; }; export type Type_RatioStockFluxConstraint = { origin: string; destination: string; coef: number | null; min: number | null; max: number | null; stock: string; data_tag: string | null; data_tag_ref: string | null; traduction: string | null; }; export type Type_StockChainingConstraint = { stock: string; coef: number | null; delta_stock: string; data_tag: string | null; data_tag_ref: string | null; traduction: string | null; }; export type Type_SpreadsheetState = { active_sheet?: string; sheet_overrides?: { [sheetId: string]: boolean; }; col_overrides?: { [sheetId: string]: { [col: number]: boolean; }; }; }; export declare class Class_Sankey { drawing_area: Class_DrawingArea; private _id; name: string; protected _is_visible: boolean; protected _nodes: { [_: string]: Class_NodeElement; }; private _links; protected _containers: { [_: string]: Class_ContainerElement; }; protected _container_activated: boolean; _styles: { [_: string]: Class_ElementStyle; }; _node_taggs: { [_: string]: Class_NodeTagGroup; }; _flux_taggs: { [_: string]: Class_FluxTagGroup; }; _data_taggs: { [_: string]: Class_DataTagGroup; }; _level_taggs: { [_: string]: Class_LevelTagGroup; }; _view_taggs: { [_: string]: Class_ViewTagGroup; }; private _taggs_order; protected _nodes_dimensions: { [_: string]: Class_NodeDimension; }; protected _node_tags_fingerprint: string; protected _flux_tags_fingerprint: string; protected _data_tags_fingerprint: string; private _icon_catalog; private _ratio_flux_constraints; private _ratio_stock_flux_constraints; private _stock_chaining_constraints; private _spreadsheet_state; private _units; private _determination; private _unitary_process; private _theme; /** Table nœud -> teinte de palette, mémoïsée. `null` = à reconstruire. */ private _theme_node_colors; normalised_link?: Class_LinkElement; constructor(drawing_area: Class_DrawingArea, id?: string); get dimensions_list(): Class_NodeDimension[]; get ratio_flux_constraints(): Type_RatioFluxConstraint[]; set ratio_flux_constraints(_: Type_RatioFluxConstraint[]); get ratio_stock_flux_constraints(): Type_RatioStockFluxConstraint[]; set ratio_stock_flux_constraints(_: Type_RatioStockFluxConstraint[]); get stock_chaining_constraints(): Type_StockChainingConstraint[]; set stock_chaining_constraints(_: Type_StockChainingConstraint[]); get spreadsheet_state(): Type_SpreadsheetState; set spreadsheet_state(_: Type_SpreadsheetState); /** OS#1286 — registre d'unités (grandeurs/unités/défauts) du diagramme. */ get units(): Class_UnitsRegistry; /** #426 — catalogues « d'où vient ta valeur » produits par la réconciliation. */ get determination(): Type_DeterminationCatalog | undefined; set determination(_: Type_DeterminationCatalog | undefined); /** os#1378 — section `process` : `null` quand le diagramme n'est pas une brique. */ get unitary_process(): Type_UnitaryProcess | null; set unitary_process(_: Type_UnitaryProcess | null); delete(): void; setVisible(): void; setInvisible(): void; toggleVisibility(): void; get is_visible(): boolean; delete_all_nodes_and_links(): void; update(): void; copyFrom(sankey_to_copy: Class_Sankey): void; get container_activated(): boolean; set container_activated(_: boolean); isMouseOverAnExistingContainer(): boolean; /** * #285 — bascule dimension→annotation SANS PERTE (NOTE-FUSION-TAGS.md §3.3) : * le groupe de dataTags devient un groupe d'étiquettes libres (mêmes tags, * mêmes couleurs), et sur chaque lien le niveau d'arbre correspondant est * replié — chaque tranche devient des sous-valeurs coordonnées, la feuille * fusionnée porte la somme des données. Les résultats de résolution des * tranches sont abandonnés. Le sens inverse (annotation→dimension) attend * l'arbitrage §6.2. */ convertDataTagGroupToFluxTagGroup(data_tagg: Class_DataTagGroup): Class_FluxTagGroup; /** * #285 (§3.3/§6.2) — bascule annotation→DIMENSION : un groupe libre porteur * devient un groupe de dataTags. Chaque valeur coordonnée par un tag du * groupe devient la valeur de la tranche correspondante (ses autres * coordonnées restent des valeurs coordonnées dans la tranche) ; la * quantité SANS tag du groupe (scalaire hérité ou valeur non coordonnée) * va sur un tag « Non affecté » créé automatiquement (totaux préservés, * réversible). Un groupe à échelles distinctes devient un groupe unité * (échelles transférées). * * Piège structurel : addDataTagGroup étend l'arbre de valeurs de chaque * lien en DÉTRUISANT les feuilles (expand copie puis delete) — on * snapshotte donc tout AVANT, puis on réécrit dans les tranches. */ convertFluxTagGroupToDataTagGroup(flux_tagg: Class_FluxTagGroup): Class_DataTagGroup | null; /** * #285 — fusionne des flux PARALLÈLES (même source, même cible — l'ancien * contournement « n flux pour n étiquettes », cf. NOTE-FUSION-TAGS.md §2.1) * en UN flux à n valeurs coordonnées : la valeur de chaque lien devient une * valeur du flux conservé, coordonnée par ses étiquettes ; la valeur * principale porte le total (partition assumée par l'utilisateur qui * déclenche la fusion) ; le premier lien garde sa géométrie et son style, * les autres sont supprimés. * * V1 : liens sans dimensions (pas d'arbre de valeurs) — le cas des fichiers * construits avec le contournement. Retourne null si la fusion est refusée. */ /** * #285 — migration au chargement : fusionne TOUS les groupes de flux * parallèles (même source, même cible — même direction) dont au moins un * membre porte des étiquettes de flux, en un flux à n valeurs coordonnées. * Idempotent ; sans effet si le fichier a des dimensions (V1 de * mergeParallelLinks) ou si les parallèles ne sont pas tagués (choix de * dessin respecté). */ migrateParallelTaggedLinks(): void; mergeParallelLinks(links: Class_LinkElement[]): Class_LinkElement | null; create_internal_style(id: ElementStyleKey, configs: ElementStyleConfigsDict): void; /** * Réinitialise le style par défaut et les styles de base aux valeurs usine, en * mutant les instances existantes (les éléments les référencent en index 0, on ne * peut donc pas les remplacer). Utilisé par le board unitaire (OS+) : il amorce une * DrawingArea isolée par copie JSON du diagramme source, ce qui ramène les * customisations de styles du source (valeur affichée sur les nœuds, cadres de * label, couleurs...). Le board unitaire doit repartir « from scratch » ; on remet * donc le socle de styles à neuf avant d'appliquer les styles unitaires. * Ne touche ni la topologie, ni les styles custom (retirés par removeAllStyles). */ resetBaseStylesToFactory(): void; draw(): void; /** * OS#1246 — join keyé des zones de texte (`gg_labels`). Même forme que les * nœuds : Class_ContainerElement hérite de Class_NodeBase (donc même parent * `g_elements_sankey`, `datum(this)` posé dans _initDraw) et la boucle de * dessin est INCONDITIONNELLE — le join peut donc posséder le cycle de vie du * racine (enter/update/exit), contrairement aux flux. */ private _drawContainersJoin; /** * OS#1246 — join keyé LITTÉRAL des flux. Le join possède le cycle de vie du * racine (enter/update/exit), comme pour les nœuds et les ZDT. * * Le contenu, lui, reste posé par le nœud source/cible (node._drawLinks → * updateLinksPositions), qui ne redessine un flux que si sa position a bougé * ≥1px OU si isRelatedD3SelectionPresentAndSynced() est faux. C'est pour ça * que ce join ne pouvait pas pré-créer les tant que cette sync se résumait * à « l'id existe-t-il ? » : un vide passait pour synchronisé et le flux * n'était jamais tracé. La sync vérifie désormais un marqueur de CONTENU * (Link._hasDrawnContent : .link_shape / .link_path), donc un pré-créé * vide est bien vu comme « à dessiner ». */ private _drawLinksJoin; /** * OS#1246 — premier vrai data-join keyé de la lib. Le join possède le cycle * de vie du racine des nœuds : enter l'append, exit le retire, update le * conserve. Le CONTENU reste dessiné par node.draw() (qui réutilise ce * via Element._initDraw idempotent) — migration « groupe par groupe » sans * casser l'architecture par classes. Les existants * portent leur datum(this) (posé dans NodeBase._initDraw), donc le join les * reconnaît par id (update) au lieu de les recréer. Prérequis des transitions * animées : enter/update/exit sont désormais des sélections nommées. */ private _drawNodesJoin; linkValueHasReconciliedData: () => boolean; get id(): string; set id(_: string); elementFromId(id: string): Class_LinkElement | Class_NodeElement | Class_ContainerElement | { name: string; is_selected: boolean; is_visible: boolean; }; get elements_list(): (Class_LinkElement | Class_NodeElement | Class_ContainerElement)[]; get visible_elements_list(): (Class_LinkElement | Class_NodeElement | Class_ContainerElement)[]; get nodes_dict(): { [_: string]: Class_NodeElement; }; get nodes_list(): Class_NodeElement[]; get nodes_list_sorted(): Class_NodeElement[]; get visible_nodes_list(): Class_NodeElement[]; get visible_nodes_list_sorted(): Class_NodeElement[]; get links_dict(): { [_: string]: Class_LinkElement; }; get links_list(): Class_LinkElement[]; get links_list_sorted(): Class_LinkElement[]; get visible_links_list(): Class_LinkElement[]; get visible_links_list_sorted(): Class_LinkElement[]; get containers_dict(): { [_: string]: Class_ContainerElement; }; get containers_list(): Class_ContainerElement[]; get containers_list_sorted(): Class_ContainerElement[]; get visible_containers_list(): Class_ContainerElement[]; private _addLabel; private _addNode; private _addLink; protected createNewNode(id: string, name: string): Class_NodeElement; protected createNewLink(id: string, source: Class_NodeElement, target: Class_NodeElement): Class_LinkElement; private _scheduleAutoFitAfterAdd; addNewNode(id: string, name: string): Class_NodeElement; addNewLink(source: Class_NodeElement, target: Class_NodeElement): Class_LinkElement; addNewContainer(id: string, name: string): Class_ContainerElement; /** * os#1344/os#1347 — hook de VALIDATION de connexion : le MODÈLE décide si un flux * source → target est constructible ; les handlers de geste (création connectée, * outil flux) l'interrogent au lieu de porter la règle. Règles de base : deux vrais * nœuds distincts de CE sankey. Les flux parallèles (2e flux entre les deux mêmes * nœuds) restent permis, comme via addNewLink (id suffixé). */ isValidConnection(source: Class_NodeElement, target: Class_NodeElement): boolean; addNewDefaultNode(): Class_NodeElement; addNewDefaultLink(): Class_LinkElement; addNewDefaultContainer(): Class_ContainerElement; /** * Retourne la zone de texte marquée comme titre du diagramme (ou undefined). */ getTitleContainer(): Class_ContainerElement | undefined; /** * Retourne le container titre, en le créant s'il n'existe pas. À la création : * gras, plus gros, centré, sans cadre, positionné en haut et centré sur le * contenu. C'est une zone de texte normale, éditable via l'interface ZDT. */ getOrCreateTitleContainer(): Class_ContainerElement; /** * Position par défaut du titre : centré horizontalement sur la bbox logique * des nœuds visibles, juste au-dessus. */ private _computeTitleTopCenter; addNewNodeWithName(name: string): Class_NodeElement; addNewLinkWithId(id: string, source: Class_NodeElement, target: Class_NodeElement): Class_LinkElement; deleteNode(node: Class_NodeElement): void; deleteLink(link: Class_LinkElement): void; deleteContainer(container: Class_ContainerElement): void; deleteLocalAttrSelectedElements(k: keyof typeof ALL_ATTRIBUTES_CONFIG, selected_elements_list: Class_ProtoElement[]): void; createNewElementStyle(id: string, name: string, is_deletable?: boolean): Class_ElementStyle; get default_style(): Class_ElementStyle; get theme(): Class_Theme; /** Bascule de thème : pose aussi ses globaux sur la zone de dessin. */ set theme(_: Class_Theme); /** * Pose le thème SANS appliquer ses globaux ni son patch de styles. * * C'est le chemin du CHARGEMENT : le fichier porte déjà les styles et le fond que * le thème avait produits, et ils font autorité (l'utilisateur a pu les retoucher * après coup). Seule la palette est reprise du thème, puisqu'elle n'est plus cuite. */ loadTheme(theme: Class_Theme): void; /** * Bascule de thème depuis l'interface : ramène les styles pilotés par le thème à * leur AMORCE, y écrit le patch du nouveau thème, et pose ses globaux. * * Le point délicat est la valeur de repli. Vider ces styles ne restitue PAS * l'apparence OpenSankey, contrairement à ce qu'on pourrait croire : ils sont * amorcés à la création depuis `elementStyleConfigs` (`create_internal_style`), et * c'est cette amorce — pas les défauts usine — qui porte l'identité d'OpenSankey. * Exemple vécu : `value_label_is_visible` vaut `false` en défaut usine, et les * valeurs de flux ne s'affichent que parce que `elementStyleConfigs[LinkStyle]` le * remet à `true`. Vider aurait donc fait disparaître les valeurs de flux en * repassant à `opensankey`. On repart donc de l'amorce, jamais du vide. * * La remise à l'amorce est ce qui rend la bascule RÉVERSIBLE : sans elle, revenir * de `sankeymatic` laisserait en place son opacité 0.45, ses polices et ses labels * masqués. * * Contrepartie assumée (cf. NOTE-THEMES.md) : une personnalisation que * l'utilisateur aurait posée sur `NodeStyle` ou `LinkStyle` eux-mêmes est perdue. * Ce qu'il a posé sur un ÉLÉMENT, en revanche, est intact — c'est là que vit le * « choix de l'utilisateur bat le thème ». */ applyTheme(theme: Class_Theme): void; /** * L'ordre d'attribution des teintes dépend de l'ordre des demandes : toute * modification de la population de nœuds (ou de leurs noms) périme la table. */ invalidateThemePalette(): void; /** * Renommage d'un nœud : la table de palette est indexée par `id` mais calculée * depuis les NOMS. Un renommage peut donc changer le regroupement par premier mot, * et c'est toute la table qui est périmée, pas la seule entrée du nœud renommé. * * Le paramètre n'est pas décoratif : `Class_ContainerElement` hérite de * `Class_NodeBase` et passe donc par le même setter, alors qu'il ne participe pas * à la palette. On filtre sur l'appartenance à `_nodes`. * * Le redraw n'a lieu que si la palette dépend réellement des noms — sous * `opensankey` (`by-tag`) ou `stan` (`none`), renommer ne change aucune couleur. * Il est aussi sauté sous `bypass_redraws` : le chargement et les opérations en * masse redessinent à la fin, et `fromJSON` pose le thème AVANT les nœuds. * Les flux sont du lot : sous `shape_color_rule: 'source'` leur couleur suit * celle de leur nœud source. */ onNodeRenamed(node: Class_NodeBase): void; /** * Couleur que la palette du thème attribue à ce nœud, ou `undefined` si le thème * ne se prononce pas — l'appelant poursuit alors sa propre cascade. * * La table est construite en une fois, dans l'ordre d'insertion des nœuds (donc * l'ordre du fichier source), et non paresseusement au fil du rendu : appelée * depuis `getShapeColorToUse`, une attribution dans l'ordre des appels de dessin * donnerait des couleurs qui changent d'un rendu à l'autre. * * Un nœud portant une couleur explicite est ignoré et ne consomme donc pas de * teinte, exactement comme dans SankeyMATIC. */ themeNodeColor(node: Class_NodeElement): string | undefined; addNewDefaultElementStyle(): Class_ElementStyle; addNewElementStyle(id: string, name: string): Class_ElementStyle; deleteElementStyle(style: Class_ElementStyle): void; getStyleOfSelectedElements(): string; switchElementStyle(n_style: Class_ElementStyle, add: boolean): void; resetAttrSelectedElements(): void; /** * Enlève toutes les surcharges d'un style par rapport au style par défaut * (équivalent de resetAttrSelectedElements, mais pour un style édité). */ resetAttrStyle(style: Class_ElementStyle): void; /** Enlève une surcharge précise d'un style (équivalent deleteLocalAttrSelectedElements). */ deleteLocalAttrStyle(style: Class_ElementStyle, k: keyof typeof ALL_ATTRIBUTES_CONFIG): void; get styles_dict(): { [_: string]: Class_ElementStyle; }; get element_default_style(): Class_ElementStyle; get styles_list(): Class_ElementStyle[]; get styles_list_sorted(): Class_ElementStyle[]; addNodeDimension(dim: Class_NodeDimension): void; removeNodeDimension(dim: Class_NodeDimension): void; showAccordingToLevelTags(): void; addLevelTagGroup(id: string, name: string): Class_LevelTagGroup; addViewTagGroup(id: string, name: string): Class_ViewTagGroup; addNodeTagGroup(id: string, name: string, with_a_tag?: boolean): Class_NodeTagGroup; addFluxTagGroup(id: string, name: string, with_a_tag?: boolean): Class_FluxTagGroup; addDataTagGroup(id: string, name: string, with_a_tag?: boolean): Class_DataTagGroup; createTagGroup(type_group: Type_MacroTagGroup, with_a_tag?: boolean): Class_LevelTagGroup | Class_NodeTagGroup | Class_ViewTagGroup | Class_DataTagGroup | Class_FluxTagGroup; removeTagGroupWithId(type_group: Type_MacroTagGroup, id: string): void; removeTagGroup(type_group: Type_MacroTagGroup, tagg: Class_NodeTagGroup | Class_FluxTagGroup | Class_LevelTagGroup | Class_DataTagGroup): void; getTagGroupsAsList(type_group: Type_MacroTagGroup): any[]; getTagGroupsAsDict(type_group: Type_MacroTagGroup): { [_: string]: Class_LevelTagGroup; } | { [_: string]: Class_NodeTagGroup; } | { [_: string]: Class_ViewTagGroup; } | { [_: string]: Class_DataTagGroup; } | { [_: string]: Class_FluxTagGroup; }; moveTagGroupUp(type_group: Type_MacroTagGroup, id: string): void; moveTagGroupDown(type_group: Type_MacroTagGroup, id: string): void; getTagGroupsOrder(type_group: Type_MacroTagGroup): string[]; setTagGroupsOrder(type_group: Type_MacroTagGroup, order: string[]): void; nodeTagsUpdated(): void; fluxTagsUpdated(): void; dataTagsUpdated(): void; get selected_node_tags_links_list(): Class_LinkElement[]; get selected_tags_nodes_list(): Class_NodeElement[]; get node_taggs_dict(): { [_: string]: Class_NodeTagGroup; }; get node_taggs_list(): Class_NodeTagGroup[]; get node_tags_fingerprint(): string; get flux_taggs_dict(): { [_: string]: Class_FluxTagGroup; }; get flux_taggs_list(): Class_FluxTagGroup[]; get flux_tags_fingerprint(): string; get data_taggs_dict(): { [_: string]: Class_DataTagGroup; }; get data_taggs_list(): Class_DataTagGroup[]; get data_taggs_entries(): [string, Class_DataTagGroup][]; get data_tags_fingerprint(): string; get selected_data_tags_list(): Class_DataTag[]; get selected_data_tags_entries(): { [x: string]: Class_DataTag; }; /** * Return an array of possible path to link value, * it use the combinitation of all tags from different data_taggs * * Exemple : * [ * * [grp1_key1,grp2_key1], * * [grp1_key1,grp2_key2], * * [grp1_key2,grp2_key1], * * [grp1_key2,grp2_key2], * ... * ] * * * @readonly * @memberof Class_Sankey */ get list_combinatorial_data_taggs_path(): string[][]; get level_taggs_dict(): { [_: string]: Class_LevelTagGroup; }; get level_taggs_list(): Class_LevelTagGroup[]; get view_taggs_dict(): { [_: string]: Class_ViewTagGroup; }; get view_taggs_list(): Class_ViewTagGroup[]; /** * Groupes de view tags en « mode filtre » (activés + view_mode). Sélectionner une * étiquette d'un tel groupe filtre la visibilité en court-circuitant les level tags * (cf. Node.viewTagVisibility). Visibilité seulement — pas de remontée vers les * ancêtres. * * os#1382 : les groupes unitaires câblés (unitary/product_unitary/sector_unitary) * ne sont plus créés et n'ont plus d'exclusion ici. Un ancien fichier qui en porte * les décrit avec view_mode=false (jamais posé par l'ex-createUnitaryView) : ils ne * sont donc pas retenus de toute façon. */ get view_mode_groups(): Class_ViewTagGroup[]; /** True dès qu'au moins un groupe de view tags est en mode filtre. */ get view_mode_active(): boolean; /** * Étiquette view tag courante servant de clé aux références d'échelle par view tag * (cf. DrawingArea.applyViewTagScaleReference). C'est l'étiquette sélectionnée du * premier groupe de view tags en mode filtre. undefined en « vue complète » (aucun * groupe en mode filtre, ou aucune étiquette sélectionnée) → pas de référence d'échelle. */ get current_scale_reference_viewtag_id(): string | undefined; get icon_catalog(): { [x: string]: string; }; set icon_catalog(value: { [x: string]: string; }); getIconFromCatalog(id_icon: string): string; /** * Sorts nodes from lower v coordinates to higher v * @memberof Class_Sankey */ sortNodes(): void; tradeOption(): "none" | "close" | "above_below" | undefined; setTrade: (close: boolean) => void; }