Skip to content

Commit

Permalink
[d3-sankey] Update to Minor 0.7 (DefinitelyTyped#17166)
Browse files Browse the repository at this point in the history
* [d3-sankey] Update to Minor 0.7
* [FEATURE] `nodeId(...)` Add ability to configure node id accessor function
* [FEATURE] `nodeAlign(...)` Add ability to configure horizontal alignment of layout
* [FEATURE] Add pre-build layout alignment functions
* [CHORE] Bump minor version number.

* [d3-sankey] [FIX] Add `height` property to node.
  • Loading branch information
tomwanzek authored and Andy committed Jun 14, 2017
1 parent 9772a48 commit 232926f
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 28 deletions.
150 changes: 130 additions & 20 deletions types/d3-sankey/d3-sankey-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import * as d3Sankey from 'd3-sankey';
import {select, Selection} from 'd3-selection';
import { select, Selection } from 'd3-selection';
import { Link } from 'd3-shape';

// ---------------------------------------------------------------------------
Expand All @@ -18,38 +18,44 @@ import { Link } from 'd3-shape';
// the Sankey layout generator. The latter are reflected in the SankeyNode and SankeyLink interfaces provided
// by the definitions file
interface SNodeExtra {
nodeId: number;
name: string;
name: string;
}

interface SNodeExtraCustomId {
nodeId: string;
name: string;
}

interface SLinkExtra {
uom: string;
uom: string;
}

// For convenience
type SNode = d3Sankey.SankeyNode<SNodeExtra, SLinkExtra>;
type SNodeCustomId = d3Sankey.SankeyNode<SNodeExtraCustomId, SLinkExtra>;
type SLink = d3Sankey.SankeyLink<SNodeExtra, SLinkExtra>;
type SLinkCustomId = d3Sankey.SankeyLink<SNodeExtraCustomId, SLinkExtra>;

interface DAG {
customNodes: SNode[];
customLinks: SLink[];
customNodes: SNode[];
customLinks: SLink[];
}

interface DAGCustomId {
customNodes: SNodeCustomId[];
customLinks: SLinkCustomId[];
}

const graph: DAG = {
const graphDefault: DAG = {
customNodes: [{
nodeId: 0,
name: "node0"
}, {
nodeId: 1,
name: "node1"
}, {
nodeId: 2,
name: "node2"
}, {
nodeId: 3,
name: "node3"
}, {
nodeId: 4,
name: "node4"
}],
customLinks: [{
Expand Down Expand Up @@ -90,6 +96,61 @@ const graph: DAG = {
}]
};

const graphCustomId: DAGCustomId = {
customNodes: [{
nodeId: "n0",
name: "node0"
}, {
nodeId: "n1",
name: "node1"
}, {
nodeId: "n2",
name: "node2"
}, {
nodeId: "n3",
name: "node3"
}, {
nodeId: "n4",
name: "node4"
}],
customLinks: [{
source: "n0",
target: "n2",
value: 2,
uom: 'Widget(s)'
}, {
source: "n1",
target: "n2",
value: 2,
uom: 'Widget(s)'
}, {
source: "n1",
target: "n3",
value: 2,
uom: 'Widget(s)'
}, {
source: "n0",
target: "n4",
value: 2,
uom: 'Widget(s)'
}, {
source: "n2",
target: "n3",
value: 2,
uom: 'Widget(s)'
}, {
source: "n2",
target: "n4",
value: 2,
uom: 'Widget(s)'
}, {
source: "n3",
target: "n4",
value: 4,
uom: 'Widget(s)'
}]
};

let sNodes: SNode[];
let sLinks: SLink[];

Expand All @@ -109,6 +170,7 @@ let sGraph: d3Sankey.SankeyGraph<SNodeExtra, SLinkExtra>;

let slgDefault: d3Sankey.SankeyLayout<d3Sankey.SankeyGraph<{}, {}>, {}, {}> = d3Sankey.sankey();
let slgDAG: d3Sankey.SankeyLayout<DAG, SNodeExtra, SLinkExtra> = d3Sankey.sankey<DAG, SNodeExtra, SLinkExtra>();
let slgDAGCustomId: d3Sankey.SankeyLayout<DAGCustomId, SNodeExtraCustomId, SLinkExtra> = d3Sankey.sankey<DAGCustomId, SNodeExtraCustomId, SLinkExtra>();

// ---------------------------------------------------------------------------
// NodeWidth
Expand Down Expand Up @@ -175,14 +237,62 @@ slgDAG = slgDAG.iterations(40);

num = slgDAG.iterations();

// ---------------------------------------------------------------------------
// Node Id
// ---------------------------------------------------------------------------

// Set -----------------------------------------------------------------------

slgDAGCustomId = slgDAGCustomId.nodeId((d) => {
const node: SNodeCustomId = d;
return d.nodeId;
});

// Get -----------------------------------------------------------------------

let nodeIdAccessor: (d: SNodeCustomId) => string | number;

nodeIdAccessor = slgDAGCustomId.nodeId();

// ---------------------------------------------------------------------------
// Node Alignment
// ---------------------------------------------------------------------------

// Set -----------------------------------------------------------------------

declare const testNode: SNode;

// Test pre-defined alignment functions
slgDAG = slgDAG.nodeAlign(d3Sankey.sankeyLeft);
num = d3Sankey.sankeyLeft(testNode, 10);
slgDAG = slgDAG.nodeAlign(d3Sankey.sankeyRight);
num = d3Sankey.sankeyRight(testNode, 10);
slgDAG = slgDAG.nodeAlign(d3Sankey.sankeyCenter);
num = d3Sankey.sankeyCenter(testNode, 10);
slgDAG = slgDAG.nodeAlign(d3Sankey.sankeyJustify);
num = d3Sankey.sankeyJustify(testNode, 10);

// Test custom
slgDAG = slgDAG.nodeAlign((node, maxN) => {
const n: SNode = node;
const mN: number = maxN;
return node.depth || 0;
});

// Get -----------------------------------------------------------------------

let nodeAlignmentFn: (d: SNode, n: number) => number;

nodeAlignmentFn = slgDAG.nodeAlign();

// ---------------------------------------------------------------------------
// Nodes
// ---------------------------------------------------------------------------

// Set -----------------------------------------------------------------------

// Use array and test return type for chainability
slgDAG = slgDAG.nodes(graph.customNodes);
slgDAG = slgDAG.nodes(graphDefault.customNodes);

// Use accessor function and test return type for chainability
slgDAG = slgDAG.nodes(d => d.customNodes);
Expand All @@ -198,7 +308,7 @@ let nodesAccessor: (d: DAG) => SNode[] = slgDAG.nodes();
// Set -----------------------------------------------------------------------

// test return type for chainability
slgDAG = slgDAG.links(graph.customLinks);
slgDAG = slgDAG.links(graphDefault.customLinks);

// Use accessor function and test return type for chainability
slgDAG = slgDAG.links(d => d.customLinks);
Expand All @@ -211,9 +321,9 @@ let linksAccessor: (d: DAG) => SLink[] = slgDAG.links();
// Compute Initial Layout
// ---------------------------------------------------------------------------

sGraph = slgDAG(graph);
sGraph = slgDAG(graphDefault);
// With additional arguments, although here unused.
sGraph = slgDAG(graph, "foo", 50);
sGraph = slgDAG(graphDefault, "foo", 50);

// ---------------------------------------------------------------------------
// Update Layout
Expand Down Expand Up @@ -255,7 +365,6 @@ let sNode = sNodes[0];

// User-specified extra properties:

num = sNode.nodeId;
str = sNode.name;

// Sankey Layout calculated (if layout has been run, otherwise undefined):
Expand All @@ -267,6 +376,7 @@ numMaybe = sNode.y1;
numMaybe = sNode.value;
numMaybe = sNode.index;
numMaybe = sNode.depth;
numMaybe = sNode.height;

let linksArrMaybe: SLink[] | undefined;

Expand All @@ -290,10 +400,10 @@ num = sLink.value;
// layout(...) was invoked, the source and target nodes may be numbers
// objects without the Sankey layout coordinates, or objects with calculated
// information
let numOrSankeyNode: number | SNode;
let numStringOrSankeyNode: number | string | SNode;

numOrSankeyNode = sLink.source;
numOrSankeyNode = sLink.target;
numStringOrSankeyNode = sLink.source;
numStringOrSankeyNode = sLink.target;

// Sankey Layout calculated (if layout has been run, otherwise undefined):

Expand Down
88 changes: 80 additions & 8 deletions types/d3-sankey/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Type definitions for D3JS d3-sankey module 0.6
// Type definitions for D3JS d3-sankey module 0.7
// Project: https://github.com/d3/d3-sankey/
// Definitions by: Tom Wanzek <https://github.com/tomwanzek>, Alex Ford <https://github.com/gustavderdrache>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped

// Last module patch version validated against: 0.6
// Last module patch version validated against: 0.7

import { Link } from 'd3-shape';

Expand Down Expand Up @@ -50,6 +50,10 @@ export interface SankeyNodeMinimal<N extends SankeyExtraProperties, L extends Sa
* Node’s zero-based graph depth, derived from the graph topology calculated by Sankey layout generator.
*/
depth?: number;
/**
* Node’s zero-based graph height, derived from the graph topology calculated by Sankey layout generator.
*/
height?: number;
/**
* Node's minimum horizontal position (derived from the node.depth) calculated by Sankey layout generator.
*/
Expand Down Expand Up @@ -96,23 +100,25 @@ export type SankeyNode<N extends SankeyExtraProperties, L extends SankeyExtraPro
*/
export interface SankeyLinkMinimal<N extends SankeyExtraProperties, L extends SankeyExtraProperties> {
/**
* Link's source node. For convenience, when initializing a Sankey layout,
* Link's source node. For convenience, when initializing a Sankey layout using the default node id accessor,
* 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.
* returned by the nodes accessor of the Sankey layout generator rather than object references. Alternatively,
* the Sankey layout can be configured with a custom node ID accessor to resolve the source node of the link upon initialization.
*
* 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<N, L>;
source: number | string | SankeyNode<N, L>;
/**
* Link's target node. For convenience, when initializing a Sankey layout,
* Link's target node. For convenience, when initializing a Sankey layout using the default node id accessor,
* 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.
* returned by the nodes accessor of the Sankey layout generator rather than object references. Alternatively,
* the Sankey layout can be configured with a custom node ID accessor to resolve the target node of the link upon initialization.
*
* 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<N, L>;
target: number | string | SankeyNode<N, L>;
/**
* Link's numeric value
*/
Expand Down Expand Up @@ -244,6 +250,34 @@ export interface SankeyLayout<Data, N extends SankeyExtraProperties, L extends S
*/
links(links: (data: Data, ...args: any[]) => Array<SankeyLink<N, L>>): this;

/**
* Return the current node id accessor.
* The default accessor is a function being passed in a Sankey layout node and returning its numeric node.index.
*/
nodeId(): (node: SankeyNode<N, L>) => string | number;
/**
* Set the node id accessor to the specified function and return this Sankey layout generator.
*
* The default accessor is a function being passed in a Sankey layout node and returning its numeric node.index.
* The default id accessor allows each link’s source and target to be specified as a zero-based index into the nodes array.
*
* @param nodeId A node id accessor function being passed a node in the Sankey graph and returning its id.
*/
nodeId(nodeId: (node: SankeyNode<N, L>) => string | number): this;

/**
* Return the current node alignment method, which defaults to d3.sankeyLeft.
*/
nodeAlign(): (node: SankeyNode<N, L>, n: number) => number;
/**
* Set the node alignment method the specified function and return this Sankey layout generator.
*
* @param nodeAlign A node alignment function which is evaluated for each input node in order,
* being passed the current node and the total depth n of the graph (one plus the maximum node.depth),
* and must return an integer between 0 and n - 1 that indicates the desired horizontal position of the node in the generated Sankey diagram.
*/
nodeAlign(nodeAlign: (node: SankeyNode<N, L>, n: number) => number): this;

/**
* Return the current node width, which defaults to 24.
*/
Expand Down Expand Up @@ -346,6 +380,44 @@ export function sankey<N extends SankeyExtraProperties, L extends SankeyExtraPro
*/
export function sankey<Data, N extends SankeyExtraProperties, L extends SankeyExtraProperties>(): SankeyLayout<Data, N, L>;

/**
* Compute the horizontal node position of a node in a Sankey layout with left alignment.
* Returns (node.depth) to indicate the desired horizontal position of the node in the generated Sankey diagram.
*
* @param node Sankey node for which to calculate the horizontal node position.
* @param n Total depth n of the graph (one plus the maximum node.depth)
*/
export function sankeyLeft(node: SankeyNode<{}, {}>, n: number): number;

/**
* Compute the horizontal node position of a node in a Sankey layout with right alignment.
* Returns (n - 1 - node.height) to indicate the desired horizontal position of the node in the generated Sankey diagram.
*
* @param node Sankey node for which to calculate the horizontal node position.
* @param n Total depth n of the graph (one plus the maximum node.depth)
*/
export function sankeyRight(node: SankeyNode<{}, {}>, n: number): number;

/**
* Compute the horizontal node position of a node in a Sankey layout with center alignment.
* Like d3.sankeyLeft, except that nodes without any incoming links are moved as right as possible.
* Returns an integer between 0 and n - 1 that indicates the desired horizontal position of the node in the generated Sankey diagram.
*
* @param node Sankey node for which to calculate the horizontal node position.
* @param n Total depth n of the graph (one plus the maximum node.depth)
*/
export function sankeyCenter(node: SankeyNode<{}, {}>, n: number): number;

/**
* Compute the horizontal node position of a node in a Sankey layout with justified alignment.
* Like d3.sankeyLeft, except that nodes without any outgoing links are moved to the far right.
* Returns an integer between 0 and n - 1 that indicates the desired horizontal position of the node in the generated Sankey diagram.
*
* @param node Sankey node for which to calculate the horizontal node position.
* @param n Total depth n of the graph (one plus the maximum node.depth)
*/
export function sankeyJustify(node: SankeyNode<{}, {}>, n: number): number;

/**
* Get a horizontal link shape suitable for a Sankey diagram.
* Source and target accessors are pre-configured and work with the
Expand Down

0 comments on commit 232926f

Please sign in to comment.