Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions docs/data/charts/sankey/SankeyLinkSorting.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import Typography from '@mui/material/Typography';

const data = {
links: [
{ source: 'C', target: 'Y', value: 10 },
{ source: 'A', target: 'X', value: 25 },
{ source: 'B', target: 'X', value: 10 },
{ source: 'X', target: 'Z', value: 25 },
{ source: 'Y', target: 'Z', value: 8 },
{ source: 'B', target: 'Y', value: 5 },
{ source: 'Y', target: 'Z', value: 8 },
{ source: 'X', target: 'Z', value: 25 },
{ source: 'B', target: 'X', value: 10 },
{ source: 'A', target: 'X', value: 25 },
{ source: 'C', target: 'Y', value: 10 },
],
};

Expand All @@ -28,14 +28,37 @@ export default function SankeyLinkSorting() {
>
<div>
<Typography variant="h6" gutterBottom>
Default Link Order
auto (default)
</Typography>
<SankeyChart height={300} series={{ data }} />
<SankeyChart
height={300}
series={{
data,
linkOptions: {
sort: 'auto',
},
}}
/>
</div>

<div>
<Typography variant="h6" gutterBottom>
fixed
</Typography>
<SankeyChart
height={300}
series={{
data,
linkOptions: {
sort: 'fixed',
},
}}
/>
</div>

<div>
<Typography variant="h6" gutterBottom>
Links Sorted by Value
Custom Function
</Typography>
<SankeyChart
height={300}
Expand Down
39 changes: 31 additions & 8 deletions docs/data/charts/sankey/SankeyLinkSorting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import Typography from '@mui/material/Typography';

const data = {
links: [
{ source: 'C', target: 'Y', value: 10 },
{ source: 'A', target: 'X', value: 25 },
{ source: 'B', target: 'X', value: 10 },
{ source: 'X', target: 'Z', value: 25 },
{ source: 'Y', target: 'Z', value: 8 },
{ source: 'B', target: 'Y', value: 5 },
{ source: 'Y', target: 'Z', value: 8 },
{ source: 'X', target: 'Z', value: 25 },
{ source: 'B', target: 'X', value: 10 },
{ source: 'A', target: 'X', value: 25 },
{ source: 'C', target: 'Y', value: 10 },
],
};

Expand All @@ -28,14 +28,37 @@ export default function SankeyLinkSorting() {
>
<div>
<Typography variant="h6" gutterBottom>
Default Link Order
auto (default)
</Typography>
<SankeyChart height={300} series={{ data }} />
<SankeyChart
height={300}
series={{
data,
linkOptions: {
sort: 'auto',
},
}}
/>
</div>

<div>
<Typography variant="h6" gutterBottom>
fixed
</Typography>
<SankeyChart
height={300}
series={{
data,
linkOptions: {
sort: 'fixed',
},
}}
/>
</div>

<div>
<Typography variant="h6" gutterBottom>
Links Sorted by Value
Custom Function
</Typography>
<SankeyChart
height={300}
Expand Down
39 changes: 35 additions & 4 deletions docs/data/charts/sankey/SankeyNodeSorting.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import { Unstable_SankeyChart as SankeyChart } from '@mui/x-charts-pro/SankeyCha
import Typography from '@mui/material/Typography';

const data = {
nodes: [
{ id: 'C' },
{ id: 'B' },
{ id: 'A' },
{ id: 'X' },
{ id: 'Y' },
{ id: 'Z' },
],
links: [
{ source: 'C', target: 'Y', value: 10 },
{ source: 'A', target: 'X', value: 25 },
Expand All @@ -16,7 +24,7 @@ const data = {
const nodeSortFunction = (a, b) => {
const labelA = a.label || a.id;
const labelB = b.label || b.id;
return labelA.localeCompare(labelB);
return labelB.localeCompare(labelA);
};

export default function SankeyNodeSorting() {
Expand All @@ -32,14 +40,37 @@ export default function SankeyNodeSorting() {
>
<div>
<Typography variant="h6" gutterBottom>
Default Node Order
auto (default)
</Typography>
<SankeyChart
height={300}
series={{
data,
nodeOptions: {
sort: 'auto',
},
}}
/>
</div>

<div>
<Typography variant="h6" gutterBottom>
fixed
</Typography>
<SankeyChart height={300} series={{ data }} />
<SankeyChart
height={300}
series={{
data,
nodeOptions: {
sort: 'fixed',
},
}}
/>
</div>

<div>
<Typography variant="h6" gutterBottom>
Nodes Sorted Alphabetically
Custom Function
</Typography>
<SankeyChart
height={300}
Expand Down
39 changes: 35 additions & 4 deletions docs/data/charts/sankey/SankeyNodeSorting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import { Unstable_SankeyChart as SankeyChart } from '@mui/x-charts-pro/SankeyCha
import Typography from '@mui/material/Typography';

const data = {
nodes: [
{ id: 'C' },
{ id: 'B' },
{ id: 'A' },
{ id: 'X' },
{ id: 'Y' },
{ id: 'Z' },
],
links: [
{ source: 'C', target: 'Y', value: 10 },
{ source: 'A', target: 'X', value: 25 },
Expand All @@ -16,7 +24,7 @@ const data = {
const nodeSortFunction = (a: any, b: any) => {
const labelA = a.label || a.id;
const labelB = b.label || b.id;
return labelA.localeCompare(labelB);
return labelB.localeCompare(labelA);
};

export default function SankeyNodeSorting() {
Expand All @@ -32,14 +40,37 @@ export default function SankeyNodeSorting() {
>
<div>
<Typography variant="h6" gutterBottom>
Default Node Order
auto (default)
</Typography>
<SankeyChart
height={300}
series={{
data,
nodeOptions: {
sort: 'auto',
},
}}
/>
</div>

<div>
<Typography variant="h6" gutterBottom>
fixed
</Typography>
<SankeyChart height={300} series={{ data }} />
<SankeyChart
height={300}
series={{
data,
nodeOptions: {
sort: 'fixed',
},
}}
/>
</div>

<div>
<Typography variant="h6" gutterBottom>
Nodes Sorted Alphabetically
Custom Function
</Typography>
<SankeyChart
height={300}
Expand Down
18 changes: 14 additions & 4 deletions docs/data/charts/sankey/sankey.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,25 @@ To dynamically customize the order, use the sorting functions for the element th

### Node sorting

The `nodeOptions.sort` function allows control of the vertical order of nodes within each column.
It receives two `SankeyLayoutNode` objects and should return a number (similar to [`Array.sort()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#comparefn)).
The `nodeOptions.sort` property controls the vertical order of nodes within each column.

It accepts three types of values:

- A **function** that receives two `SankeyLayoutNode` objects and returns a number (similar to [`Array.sort()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#comparefn))
- `'auto'` (default): Uses the automatic sorting behavior
- `'fixed'`: Preserves the order from the `nodes` array, disabling automatic sorting

{{"demo": "SankeyNodeSorting.js"}}

### Link sorting

The `linkOptions.sort` function allows control of the order of links emanating from each node.
It receives two `SankeyLayoutLink` objects and should return a number.
The `linkOptions.sort` property controls the order of links emanating from each node.

It accepts the same three types of values:

- A **function** that receives two `SankeyLayoutLink` objects and returns a number
- `'auto'` (default): Uses the automatic sorting behavior
- `'fixed'`: Preserves the order from the `links` array, disabling automatic sorting

{{"demo": "SankeyLinkSorting.js"}}

Expand Down
25 changes: 14 additions & 11 deletions packages/x-charts-pro/src/SankeyChart/calculateSankeyLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,10 @@ export function calculateSankeyLayout(
width: nodeWidth = 15,
padding: nodePadding = 10,
align: nodeAlign = 'justify',
sort: nodeSort = null,
sort: nodeSort,
} = nodeOptions ?? {};

const {
color: linkColor = 'source',
sort: linkSort = null,
curveCorrection = 10,
} = linkOptions ?? {};
const { color: linkColor = 'source', sort: linkSort, curveCorrection = 10 } = linkOptions ?? {};

const { width, height, left, top, bottom, right } = drawingArea;
if (!data || !data.links) {
Expand All @@ -56,7 +52,7 @@ export function calculateSankeyLayout(
};

// Create the sankey layout generator
let sankeyGenerator = sankey<typeof graph, SankeyLayoutNode, SankeyLayoutLink>()
const sankeyGenerator = sankey<typeof graph, SankeyLayoutNode, SankeyLayoutLink>()
.nodeWidth(nodeWidth)
.nodePadding(nodePadding)
.nodeAlign(getNodeAlignFunction(nodeAlign))
Expand All @@ -67,11 +63,18 @@ export function calculateSankeyLayout(
.nodeId((d) => d.id)
.iterations(iterations);

if (nodeSort) {
sankeyGenerator = sankeyGenerator.nodeSort(nodeSort);
// For 'auto' or undefined, don't set anything (use d3-sankey default behavior)
if (typeof nodeSort === 'function') {
sankeyGenerator.nodeSort(nodeSort);
} else if (nodeSort === 'fixed') {
// Null is not accepted by the types.
sankeyGenerator.nodeSort(null as any);
}
if (linkSort) {
sankeyGenerator = sankeyGenerator.linkSort(linkSort);
if (typeof linkSort === 'function') {
sankeyGenerator.linkSort(linkSort);
} else if (linkSort === 'fixed') {
// Null is not accepted by the types.
sankeyGenerator.linkSort(null as any);
}

// Generate the layout
Expand Down
22 changes: 18 additions & 4 deletions packages/x-charts-pro/src/SankeyChart/sankey.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,19 @@ export type SankeyNodeOptions = {
*/
showLabels?: boolean;
/**
* Custom sort function for nodes
* Custom sort mode for nodes
*
* - 'auto': Automatic sorting behavior (default)
* - 'fixed': Preserve the order from the nodes array (disables automatic sorting)
* - or a custom function
*
* @param {SankeyLayoutNode} a - First node to compare
* @param {SankeyLayoutNode} b - Second node to compare
* @returns {number} Comparison result
*
* @default 'auto'
*/
sort?: (a: SankeyLayoutNode, b: SankeyLayoutNode) => number | null;
sort?: 'auto' | 'fixed' | ((a: SankeyLayoutNode, b: SankeyLayoutNode) => number);
} & SankeyNodeHighlightScope;

export type SankeyLinkOptions = {
Expand All @@ -116,12 +123,19 @@ export type SankeyLinkOptions = {
*/
showValues?: boolean;
/**
* Custom sort function for links
* Custom sort mode for links
*
* - 'auto': Automatic sorting behavior (default)
* - 'fixed': Preserve the order from the links array (disables automatic sorting)
* - or a custom function
*
* @param {SankeyLayoutLink} a - First link to compare
* @param {SankeyLayoutLink} b - Second link to compare
* @returns {number} Comparison result
* @default 'auto'
*/
sort?: (a: SankeyLayoutLink, b: SankeyLayoutLink) => number | null;
sort?: 'auto' | 'fixed' | ((a: SankeyLayoutLink, b: SankeyLayoutLink) => number);
/**
* Applies the given number to the X dimension of the control points of the link's curve function.
* This can create better looking links between nodes, but is dependent on the graph layout.
Expand Down
Loading