diff --git a/types/d3-sankey/d3-sankey-tests.ts b/types/d3-sankey/d3-sankey-tests.ts index 246755a900..4ed508f267 100644 --- a/types/d3-sankey/d3-sankey-tests.ts +++ b/types/d3-sankey/d3-sankey-tests.ts @@ -8,6 +8,7 @@ import * as d3Sankey from 'd3-sankey'; import {select, Selection} from 'd3-selection'; +import { Link } from 'd3-shape'; // --------------------------------------------------------------------------- // Preparatory Steps @@ -30,12 +31,12 @@ type SNode = d3Sankey.SankeyNode; type SLink = d3Sankey.SankeyLink; interface DAG { - nodes: SNode[]; - links: SLink[]; + customNodes: SNode[]; + customLinks: SLink[]; } const graph: DAG = { - nodes: [{ + customNodes: [{ nodeId: 0, name: "node0" }, { @@ -51,7 +52,7 @@ const graph: DAG = { nodeId: 4, name: "node4" }], - links: [{ + customLinks: [{ source: 0, target: 2, value: 2, @@ -96,15 +97,18 @@ let num: number; let numMaybe: number | undefined; let str: string; let size: [number, number]; +let extent: [[number, number], [number, number]]; const svgLinkPaths = select('svg').selectAll('.linkPath'); // assume mock DOM +let sGraph: d3Sankey.SankeyGraph; + // --------------------------------------------------------------------------- // Obtain SankeyLayout Generator // --------------------------------------------------------------------------- -let slgDefault: d3Sankey.SankeyLayout<{}, {}> = d3Sankey.sankey(); -let slgDAG: d3Sankey.SankeyLayout = d3Sankey.sankey(); +let slgDefault: d3Sankey.SankeyLayout, {}, {}> = d3Sankey.sankey(); +let slgDAG: d3Sankey.SankeyLayout = d3Sankey.sankey(); // --------------------------------------------------------------------------- // NodeWidth @@ -132,6 +136,19 @@ slgDAG = slgDAG.nodePadding(8); num = slgDAG.nodePadding(); +// --------------------------------------------------------------------------- +// Extent +// --------------------------------------------------------------------------- + +// Set ----------------------------------------------------------------------- + +// test return type for chainability +slgDAG = slgDAG.extent([[0, 0], [1200, 800]]); + +// Get ----------------------------------------------------------------------- + +extent = slgDAG.extent(); + // --------------------------------------------------------------------------- // Size // --------------------------------------------------------------------------- @@ -151,12 +168,15 @@ size = slgDAG.size(); // Set ----------------------------------------------------------------------- -// test return type for chainability -slgDAG = slgDAG.nodes(graph.nodes); +// Use array and test return type for chainability +slgDAG = slgDAG.nodes(graph.customNodes); + +// Use accessor function and test return type for chainability +slgDAG = slgDAG.nodes(d => d.customNodes); // Get ----------------------------------------------------------------------- -sNodes = slgDAG.nodes(); +let nodesAccessor: (d: DAG) => SNode[] = slgDAG.nodes(); // --------------------------------------------------------------------------- // Links @@ -165,51 +185,59 @@ sNodes = slgDAG.nodes(); // Set ----------------------------------------------------------------------- // test return type for chainability -slgDAG = slgDAG.links(graph.links); +slgDAG = slgDAG.links(graph.customLinks); + +// Use accessor function and test return type for chainability +slgDAG = slgDAG.links(d => d.customLinks); // Get ----------------------------------------------------------------------- -sLinks = slgDAG.links(); +let linksAccessor: (d: DAG) => SLink[] = slgDAG.links(); // --------------------------------------------------------------------------- -// Compute Layout +// Compute Initial Layout // --------------------------------------------------------------------------- -// test return type for chainability -slgDAG = slgDAG.layout(22); +sGraph = slgDAG(graph); +// With additional arguments, although here unused. +sGraph = slgDAG(graph, "foo", 50); // --------------------------------------------------------------------------- -// Relayout +// Update Layout // --------------------------------------------------------------------------- -// test return type for chainability -slgDAG = slgDAG.relayout(); +sGraph = slgDAG.update(sGraph); // --------------------------------------------------------------------------- -// Obtain and Use Link SVG Path Generator +// Obtain and Use Horizontal Link Path Generator // --------------------------------------------------------------------------- -let pathGen: d3Sankey.SankeyLinkPathGenerator; +let defaultPathGen: Link, [number, number]>; +let pathGen: Link; -pathGen = slgDAG.link(); +defaultPathGen = d3Sankey.sankeyLinkHorizontal(); -// Adjust Link SVG Path Generator curvature ---------------------------------- +pathGen = d3Sankey.sankeyLinkHorizontal(); -// test return type -pathGen = pathGen.curvature(0.6); -num = pathGen.curvature(); +// Render to svg path -// uses - -let svgPathString: string = pathGen(slgDAG.links()[0]); +let svgPathString: string | null = pathGen(sGraph.links[0]); svgLinkPaths.attr('d', pathGen); +// Render to canvas + +declare const ctx: CanvasRenderingContext2D; + +pathGen.context(ctx); +pathGen(sGraph.links[0]); + // --------------------------------------------------------------------------- // Shape test Node/Link related interfaces and types // --------------------------------------------------------------------------- // Sankey Node -------------------------------------------------------------- +sNodes = sGraph.nodes; let sNode = sNodes[0]; // User-specified extra properties: @@ -232,6 +260,7 @@ linksArrMaybe = sNode.targetLinks; // Sankey Link -------------------------------------------------------------- +sLinks = sGraph.links; let sLink = sLinks[0]; // User-specified extra properties: diff --git a/types/d3-sankey/index.d.ts b/types/d3-sankey/index.d.ts index 1446bc917f..e4fcd139ef 100644 --- a/types/d3-sankey/index.d.ts +++ b/types/d3-sankey/index.d.ts @@ -1,14 +1,16 @@ -// Type definitions for D3JS d3-sankey module 0.4 +// Type definitions for D3JS d3-sankey module 0.5 // Project: https://github.com/d3/d3-sankey/ // Definitions by: Tom Wanzek , Alex Ford // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// Last module patch version validated against: 0.4.2 +// Last module patch version validated against: 0.5 + +import { Link } from 'd3-shape'; /** * A helper interface as an extension reference for user-provided properties of * nodes and links in the graph, which are not required or calculated by - * the Sankey Layout Generator + * the Sankey layout Generator */ export interface SankeyExtraProperties { [key: string]: any; } @@ -26,33 +28,34 @@ export interface SankeyExtraProperties { [key: string]: any; } */ export interface SankeyNodeMinimal { /** - * Array of links which have this node as their source. + * Array of outgoing links which have this node as their source. * This property is calculated internally by the Sankey layout generator. */ sourceLinks?: Array>; /** - * Array of links which have this node as their target. + * Array of incoming links which have this node as their target. * This property is calculated internally by the Sankey layout generator. */ targetLinks?: Array>; /** - * Node value calculated by Sankey Layout Generator based on values of incoming and outgoing links + * Node's value calculated by Sankey layout Generator; + * the sum of link.value for the node’s incoming links. */ value?: number; /** - * Node horizontal position calculated by Sankey layout generator + * Node's horizontal position (derived from the graph topology) calculated by Sankey layout generator. */ x?: number; /** - * Node width calculated by Sankey layout generator + * Node's node width calculated by Sankey layout generator. */ dx?: number; /** - * Node vertical position (depth) calculated by Sankey layout generator + * Node's vertical position calculated by Sankey layout generator. */ y?: number; /** - * Node height (vertical extent based on node value) calculated by Sankey layout generator + * Node's height (proportional to its value) calculated by Sankey layout generator. */ dy?: number; } @@ -85,31 +88,37 @@ export type SankeyNode { /** - * Source node of the link. For convenience, when initializing a Sankey layout, source may be the index of the source node in the nodes array - * passed into the Sankey layout generator. Once the layout(...) method is invoked, the numeric index will be replaced with the corresponding - * source node object. + * Link's source node. For convenience, when initializing a Sankey layout, + * source may be the zero-based index of the corresponding node in the nodes array + * returned by the nodes accessor of the Sankey layout generator rather than object references. + * + * Once the Sankey generator is invoked to return the Sankey graph object, + * the numeric index will be replaced with the corresponding source node object. */ source: number | SankeyNode; /** - * Target node of the link. For convenience, when initializing a Sankey layout, target may be the index of the target node in the nodes array - * passed into the Sankey layout generator. Once the layout(...) method is invoked, the numeric index will be replaced with the corresponding - * target node object. + * Link's target node. For convenience, when initializing a Sankey layout, + * target may be the zero-based index of the corresponding node in the nodes array + * returned by the nodes accessor of the Sankey layout generator rather than object references. + * + * Once the Sankey generator is invoked to return the Sankey graph object, + * the numeric index will be replaced with the corresponding target node object. */ target: number | SankeyNode; /** - * Value of the link + * Link's numeric value */ value: number; /** - * Link breadth calculated by Sankey layout generator based on the link value + * Link breadth (proportional to its value) calculated by Sankey layout generator. */ dy?: number; /** - * Vertical starting position of the link (at source node) calculated by Sankey layout generator + * Link's vertical starting position (at source node) calculated by Sankey layout generator. */ sy?: number; /** - * Vertical end position of the link (at target node) calculated by Sankey layout generator + * Link's vertical end position (at target node) calculated by Sankey layout generator. */ ty?: number; } @@ -129,32 +138,7 @@ export interface SankeyLinkMinimal = L & SankeyLinkMinimal; /** - * An svg path generator factory for the link paths in a calculated Sankey Layout. - */ -export interface SankeyLinkPathGenerator { - /** - * Return svg path string for a given link. - * - * IMPORTANT: Only invoke for link data with Sankey Layout information previously calculated. - * - * @param link A Sankey diagram link, for which the layout has already been calculated. - */ - (link: SankeyLink): string; - /** - * Returns the current curvature used to calculate svg paths for links. - * The default curvature is 0.5. - */ - curvature(): number; - /** - * Set the curvature used to calculate svg paths for links and return the updated link path generator. - * - * @param curvature Curvature to be used when calculating svg paths for links. The default curvature is 0.5. - */ - curvature(curvature: number): this; -} - -/** - * A Sankey layout generator. + * A Sankey Graph Object which contains the computed layout information for nodes and links. * * The first generic N refers to user-defined properties contained in the node data passed into * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the @@ -164,7 +148,90 @@ export interface SankeyLinkPathGenerator { +export interface SankeyGraph { + /** + * Array of Sankey diagram nodes + */ + nodes: Array>; + /** + * Array of Sankey diagram links + */ + links: Array>; +} + +/** + * A Sankey layout generator. + * + * The first generic Data refers to the data type of the first argument passed in when invoking the + * Sankey layout generator and internally the configured nodes/links accessor functions. + * + * The second generic N refers to user-defined properties contained in the node data passed into + * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the + * SankeyNodeMinimal interface. + * + * The third generic L refers to user-defined properties contained in the link data passed into + * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the + * SankeyLinkMinimal interface. + */ +export interface SankeyLayout { + /** + * Computes the node and link positions for the given arguments, returning a graph representing the Sankey layout. + * + * @param data Data object being passed as the first argument to the nodes and links accessor functions. Additional arguments will also be passed + * to the accessor functions. + */ + (data: Data, ...args: any[]): SankeyGraph; + + /** + * Recomputes the specified graph’s links’ positions, updating the following properties of each link: + * + * - link.sy: the link’s vertical starting position (at source node) + * - link.ty: the link’s vertical end position (at target node) + * + * This method is intended to be called after computing the initial Sankey layout, for example when the diagram is repositioned interactively. + * + * @param graph + */ + update(graph: SankeyGraph): SankeyGraph; + + /** + * Return the current nodes accessor function, which defaults to a function returning the "nodes" property of the + * first argument it is invoked with. + */ + nodes(): (data: Data, ...args: any[]) => Array>; + /** + * Set the Sankey generator's nodes accessor to a function returning the specified array of objects and returns this Sankey layout generator. + * + * @param nodes Array of nodes. + */ + nodes(nodes: Array>): this; + /** + * Set the Sankey generator's nodes accessor to the specified function and returns this Sankey layout generator. + * + * @param nodes A nodes accessor function. The function is invoked when the Sankey layout is generated, being passed any arguments passed to the Sankey generator. + * This function must return an array of nodes. + */ + nodes(nodes: (data: Data, ...args: any[]) => Array>): this; + + /** + * Return the current links accessor function, which defaults to a function returning the "links" property of the + * first argument it is invoked with. + */ + links(): (data: Data, ...args: any[]) => Array>; + /** + * Set the Sankey generator's links accessor to a function returning the specified array of objects and returns this Sankey layout generator. + * + * @param links Array of links. + */ + links(links: Array>): this; + /** + * Set the Sankey generator's links accessor to the specified function and returns this Sankey layout generator. + * + * @param links A links accessor function. The function is invoked when the Sankey layout is generated, being passed any arguments passed to the Sankey generator. + * This function must return an array of links. + */ + links(links: (data: Data, ...args: any[]) => Array>): this; + /** * Return the current node width, which defaults to 24. */ @@ -183,48 +250,23 @@ export interface SankeyLayout>; + extent(): [[number, number], [number, number]]; /** - * Set the sankey generator's nodes to the specified array of objects and returns this sankey layout generator. + * Set the extent of the Sankey layout to the specified bounds and returns this Sankey layout generator. * - * @param nodes Array of nodes. + * @param extent Extent bounds for the layout. The extent bounds are specified as an array [[x0, y0], [x1, y1]], + * where x0 is the left side of the extent, y0 is the top, x1 is the right and y1 is the bottom. The default is [[0, 0], [1, 1]]. */ - nodes(nodes: Array>): this; - - /** - * Return the current array of links, which defaults to []. - */ - links(): Array>; - /** - * Set the sankey generator's links to the specified array of objects and returns this sankey layout generator. - * - * @param links Array of links. - */ - links(links: Array>): this; - - /** - * Runs the sankey layout algorithm updating the nodes and links with their respective layout information and returns this sankey generator. - * - * @param iterations Number of passes to be used in the iterative relaxation algorithm for node placement. - */ - layout(iterations: number): this; - - /** - * Recalculate the depth of links and return this Sankey layout generator. - * This methods is primarily used when a node is moved vertically, e.g. using d3-drag. - */ - relayout(): this; + extent(extent: [[number, number], [number, number]]): this; /** * Return the current layout size in pixels. The size is a two element array of [width, height] which defaults to [1, 1]. @@ -232,18 +274,11 @@ export interface SankeyLayout path string for the link. - * By default the link path generator uses a curvature of 0.5. - */ - link(): SankeyLinkPathGenerator; } /** @@ -251,11 +286,15 @@ export interface SankeyLayout; +export function sankey(): SankeyLayout, {}, {}>; /** * Get a Sankey layout generator. * + * Default nodes/links accessors are assumed. + * * The first generic N refers to user-defined properties contained in the node data passed into * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the * SankeyNodeMinimal interface. @@ -264,4 +303,43 @@ export function sankey(): SankeyLayout<{}, {}>; * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the * SankeyLinkMinimal interface. */ -export function sankey(): SankeyLayout; +export function sankey(): SankeyLayout, N, L>; +/** + * Get a Sankey layout generator. + * + * The nodes/links accessors need to be configured to work with the data type of the first argument passed + * in when invoking the Sankey lyout generator. + * + * The first generic corresponds to the data type of the first argument passed in when invoking the Sankey layout generator, + * and its nodes/links accessors. + * + * The second generic N refers to user-defined properties contained in the node data passed into + * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the + * SankeyNodeMinimal interface. + * + * The third generic L refers to user-defined properties contained in the link data passed into + * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the + * SankeyLinkMinimal interface. + */ +export function sankey(): SankeyLayout; + +/** + * Get a horizontal link shape suitable for a Sankey diagram. + * Source and target accessors are pre-configured and work with the + * default x- and y- accessors of the link shape generator. + */ +export function sankeyLinkHorizontal(): Link, [number, number]>; +/** + * Get a horizontal link shape suitable for a Sankey diagram. + * Source and target accessors are pre-configured and work with the + * default x- and y- accessors of the link shape generator. + * + * The first generic N refers to user-defined properties contained in the node data passed into + * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the + * SankeyNodeMinimal interface. + * + * The second generic L refers to user-defined properties contained in the link data passed into + * Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the + * SankeyLinkMinimal interface. + */ +export function sankeyLinkHorizontal(): Link, [number, number]>;