diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index bfa7a35..dbebafa 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -31,6 +31,7 @@ export default defineConfig({
{ text: 'Tree with Labels', link: '/examples/label' },
{ text: 'Directed Tree', link: '/examples/directed' },
{ text: 'Tree Orientations', link: '/examples/orientation' },
+ { text: 'Fully Linked', link: '/examples/linked' },
],
},
{
diff --git a/docs/examples/linked.md b/docs/examples/linked.md
new file mode 100644
index 0000000..1ba82bc
--- /dev/null
+++ b/docs/examples/linked.md
@@ -0,0 +1,24 @@
+---
+title: Linked
+---
+
+# Linked
+
+
+
+
+
+### Code
+
+:::code-group
+
+<<< ./linked.ts#config [config]
+
+<<< ./linked.ts#data [data]
+
+:::
diff --git a/docs/examples/linked.ts b/docs/examples/linked.ts
new file mode 100644
index 0000000..9c52572
--- /dev/null
+++ b/docs/examples/linked.ts
@@ -0,0 +1,55 @@
+import type { ChartConfiguration } from 'chart.js';
+import type {} from '../../src';
+import 'chartjs-plugin-datalabels';
+
+// #region data
+
+const edges = [
+ { source: 1, target: 0 },
+ { source: 2, target: 0 },
+ { source: 2, target: 1 },
+ { source: 3, target: 1 },
+ { source: 3, target: 0 },
+ { source: 3, target: 2 },
+];
+
+const widths = [2, 5, 10, 15, 20, 25];
+const dashes = [
+ [2, 2],
+ [5, 5],
+ [10, 10],
+ [15, 15],
+ [20, 20],
+ [25, 25],
+];
+const colors = ['blue', 'red', 'green', 'purple', 'pink', 'yellow'];
+const nodeColors = ['yellow', 'pink', 'teal', 'violet'];
+
+export const data: ChartConfiguration<'tree'>['data'] = {
+ labels: ['A', 'B', 'C', 'D'],
+ datasets: [
+ {
+ data: [{}, {}, {}, {}],
+ edges: edges,
+ pointRadius: 20,
+ pointBackgroundColor: (ctx) => nodeColors[ctx.index],
+ edgeLineBorderWidth: (ctx) => widths[ctx.index],
+ edgeLineBorderDash: (ctx) => dashes[ctx.index],
+ edgeLineBorderColor: (ctx) => colors[ctx.index],
+ },
+ ],
+};
+// #endregion data
+// #region config
+export const config: ChartConfiguration<'tree'> = {
+ type: 'forceDirectedGraph',
+ data,
+ options: {
+ scales: {
+ x: { min: -1.5, max: 1.5 },
+ y: { min: -1.5, max: 1.5 },
+ },
+ plugins: { legend: { display: false } },
+ },
+};
+// #endregion config
diff --git a/package.json b/package.json
index a65c2ab..2bcd3f5 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "chartjs-chart-graph",
"description": "Chart.js module for charting graphs",
- "version": "4.2.4",
+ "version": "4.2.5",
"author": {
"name": "Samuel Gratzl",
"email": "sam@sgratzl.com",
diff --git a/src/controllers/GraphController.ts b/src/controllers/GraphController.ts
index f454886..fbce1d0 100644
--- a/src/controllers/GraphController.ts
+++ b/src/controllers/GraphController.ts
@@ -207,6 +207,8 @@ export class GraphController extends ScatterController {
this.stopLayout();
}
+ declare getContext: (index: number, active: boolean, mode: UpdateMode) => unknown;
+
/**
* @hidden
*/
@@ -215,14 +217,33 @@ export class GraphController extends ScatterController {
_cachedDataOpts: this._cachedDataOpts,
dataElementType: this.dataElementType,
_sharedOptions: this._sharedOptions,
+ // getDataset: this.getDataset,
+ // getParsed: this.getParsed,
};
this._cachedDataOpts = {};
this.dataElementType = this.edgeElementType;
this._sharedOptions = this._edgeSharedOptions;
+
+ const dataset = this.getDataset();
const meta = this._cachedMeta;
- const nodes = meta.data;
+ const nodeElements = meta.data;
const data = (this._cachedMeta as unknown as IExtendedChartMeta)._parsedEdges;
+ // get generic context to prefill cache
+ this.getContext(-1, false, mode);
+ this.getDataset = () => {
+ return new Proxy(dataset, {
+ get(obj: any, prop: string) {
+ return prop === 'data' ? obj.edges ?? [] : obj[prop];
+ },
+ });
+ };
+ this.getParsed = (index: number) => {
+ return data[index] as any;
+ };
+ // patch meta to store edges
+ meta.data = (meta as any).edges;
+
const reset = mode === 'reset';
const firstOpts = this.resolveDataElementOptions(start, mode);
@@ -253,11 +274,11 @@ export class GraphController extends ScatterController {
const parsed = data[index];
const properties: any = {
- source: nodes[parsed.source],
- target: nodes[parsed.target],
+ source: nodeElements[parsed.source],
+ target: nodeElements[parsed.target],
points: Array.isArray(parsed.points) ? parsed.points.map((p) => copyPoint(p)) : [],
};
- properties.points._source = nodes[parsed.source];
+ properties.points._source = nodeElements[parsed.source];
if (includeOptions) {
if (sharedOptions !== dummyShared) {
properties.options = sharedOptions;
@@ -271,6 +292,10 @@ export class GraphController extends ScatterController {
this._edgeSharedOptions = this._sharedOptions;
Object.assign(this, bak);
+ delete (this as any).getDataset;
+ delete (this as any).getParsed;
+ // patch meta to store edges
+ meta.data = nodeElements;
}
/**