force-graph 1.42.13 → 1.42.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,27 +15,15 @@ var indexBy = require('index-array-by');
15
15
  var d3Scale = require('d3-scale');
16
16
  var d3ScaleChromatic = require('d3-scale-chromatic');
17
17
 
18
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
19
-
20
- var throttle__default = /*#__PURE__*/_interopDefaultLegacy(throttle);
21
- var TWEEN__default = /*#__PURE__*/_interopDefaultLegacy(TWEEN);
22
- var Kapsule__default = /*#__PURE__*/_interopDefaultLegacy(Kapsule);
23
- var accessorFn__default = /*#__PURE__*/_interopDefaultLegacy(accessorFn);
24
- var ColorTracker__default = /*#__PURE__*/_interopDefaultLegacy(ColorTracker);
25
- var indexBy__default = /*#__PURE__*/_interopDefaultLegacy(indexBy);
26
-
27
18
  function styleInject(css, ref) {
28
19
  if (ref === void 0) ref = {};
29
20
  var insertAt = ref.insertAt;
30
-
31
21
  if (!css || typeof document === 'undefined') {
32
22
  return;
33
23
  }
34
-
35
24
  var head = document.head || document.getElementsByTagName('head')[0];
36
25
  var style = document.createElement('style');
37
26
  style.type = 'text/css';
38
-
39
27
  if (insertAt === 'top') {
40
28
  if (head.firstChild) {
41
29
  head.insertBefore(style, head.firstChild);
@@ -45,7 +33,6 @@ function styleInject(css, ref) {
45
33
  } else {
46
34
  head.appendChild(style);
47
35
  }
48
-
49
36
  if (style.styleSheet) {
50
37
  style.styleSheet.cssText = css;
51
38
  } else {
@@ -53,22 +40,19 @@ function styleInject(css, ref) {
53
40
  }
54
41
  }
55
42
 
56
- var css_248z = ".force-graph-container canvas {\n display: block;\n user-select: none;\n outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n\n.force-graph-container .graph-tooltip {\n position: absolute;\n top: 0;\n transform: translate(-50%, 25px);\n font-family: sans-serif;\n font-size: 16px;\n padding: 4px;\n border-radius: 3px;\n color: #eee;\n background: rgba(0,0,0,0.65);\n visibility: hidden; /* by default */\n}\n\n.force-graph-container .clickable {\n cursor: pointer;\n}\n\n.force-graph-container .grabbable {\n cursor: move;\n cursor: grab;\n cursor: -moz-grab;\n cursor: -webkit-grab;\n}\n\n.force-graph-container .grabbable:active {\n cursor: grabbing;\n cursor: -moz-grabbing;\n cursor: -webkit-grabbing;\n}\n";
43
+ var css_248z = ".force-graph-container canvas {\n display: block;\n user-select: none;\n outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n\n.force-graph-container .graph-tooltip {\n position: absolute;\n top: 0;\n font-family: sans-serif;\n font-size: 16px;\n padding: 4px;\n border-radius: 3px;\n color: #eee;\n background: rgba(0,0,0,0.65);\n visibility: hidden; /* by default */\n}\n\n.force-graph-container .clickable {\n cursor: pointer;\n}\n\n.force-graph-container .grabbable {\n cursor: move;\n cursor: grab;\n cursor: -moz-grab;\n cursor: -webkit-grab;\n}\n\n.force-graph-container .grabbable:active {\n cursor: grabbing;\n cursor: -moz-grabbing;\n cursor: -webkit-grabbing;\n}\n";
57
44
  styleInject(css_248z);
58
45
 
59
46
  function ownKeys(object, enumerableOnly) {
60
47
  var keys = Object.keys(object);
61
-
62
48
  if (Object.getOwnPropertySymbols) {
63
49
  var symbols = Object.getOwnPropertySymbols(object);
64
50
  enumerableOnly && (symbols = symbols.filter(function (sym) {
65
51
  return Object.getOwnPropertyDescriptor(object, sym).enumerable;
66
52
  })), keys.push.apply(keys, symbols);
67
53
  }
68
-
69
54
  return keys;
70
55
  }
71
-
72
56
  function _objectSpread2(target) {
73
57
  for (var i = 1; i < arguments.length; i++) {
74
58
  var source = null != arguments[i] ? arguments[i] : {};
@@ -78,10 +62,8 @@ function _objectSpread2(target) {
78
62
  Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
79
63
  });
80
64
  }
81
-
82
65
  return target;
83
66
  }
84
-
85
67
  function _typeof(obj) {
86
68
  "@babel/helpers - typeof";
87
69
 
@@ -91,7 +73,6 @@ function _typeof(obj) {
91
73
  return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
92
74
  }, _typeof(obj);
93
75
  }
94
-
95
76
  function _defineProperty(obj, key, value) {
96
77
  if (key in obj) {
97
78
  Object.defineProperty(obj, key, {
@@ -103,10 +84,8 @@ function _defineProperty(obj, key, value) {
103
84
  } else {
104
85
  obj[key] = value;
105
86
  }
106
-
107
87
  return obj;
108
88
  }
109
-
110
89
  function _setPrototypeOf(o, p) {
111
90
  _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
112
91
  o.__proto__ = p;
@@ -114,12 +93,10 @@ function _setPrototypeOf(o, p) {
114
93
  };
115
94
  return _setPrototypeOf(o, p);
116
95
  }
117
-
118
96
  function _isNativeReflectConstruct() {
119
97
  if (typeof Reflect === "undefined" || !Reflect.construct) return false;
120
98
  if (Reflect.construct.sham) return false;
121
99
  if (typeof Proxy === "function") return true;
122
-
123
100
  try {
124
101
  Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
125
102
  return true;
@@ -127,7 +104,6 @@ function _isNativeReflectConstruct() {
127
104
  return false;
128
105
  }
129
106
  }
130
-
131
107
  function _construct(Parent, args, Class) {
132
108
  if (_isNativeReflectConstruct()) {
133
109
  _construct = Reflect.construct.bind();
@@ -141,44 +117,33 @@ function _construct(Parent, args, Class) {
141
117
  return instance;
142
118
  };
143
119
  }
144
-
145
120
  return _construct.apply(null, arguments);
146
121
  }
147
-
148
122
  function _slicedToArray(arr, i) {
149
123
  return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
150
124
  }
151
-
152
125
  function _toConsumableArray(arr) {
153
126
  return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
154
127
  }
155
-
156
128
  function _arrayWithoutHoles(arr) {
157
129
  if (Array.isArray(arr)) return _arrayLikeToArray(arr);
158
130
  }
159
-
160
131
  function _arrayWithHoles(arr) {
161
132
  if (Array.isArray(arr)) return arr;
162
133
  }
163
-
164
134
  function _iterableToArray(iter) {
165
135
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
166
136
  }
167
-
168
137
  function _iterableToArrayLimit(arr, i) {
169
138
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
170
-
171
139
  if (_i == null) return;
172
140
  var _arr = [];
173
141
  var _n = true;
174
142
  var _d = false;
175
-
176
143
  var _s, _e;
177
-
178
144
  try {
179
145
  for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
180
146
  _arr.push(_s.value);
181
-
182
147
  if (i && _arr.length === i) break;
183
148
  }
184
149
  } catch (err) {
@@ -191,10 +156,8 @@ function _iterableToArrayLimit(arr, i) {
191
156
  if (_d) throw _e;
192
157
  }
193
158
  }
194
-
195
159
  return _arr;
196
160
  }
197
-
198
161
  function _unsupportedIterableToArray(o, minLen) {
199
162
  if (!o) return;
200
163
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
@@ -203,27 +166,23 @@ function _unsupportedIterableToArray(o, minLen) {
203
166
  if (n === "Map" || n === "Set") return Array.from(o);
204
167
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
205
168
  }
206
-
207
169
  function _arrayLikeToArray(arr, len) {
208
170
  if (len == null || len > arr.length) len = arr.length;
209
-
210
171
  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
211
-
212
172
  return arr2;
213
173
  }
214
-
215
174
  function _nonIterableSpread() {
216
175
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
217
176
  }
218
-
219
177
  function _nonIterableRest() {
220
178
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
221
179
  }
222
180
 
223
- var autoColorScale = d3Scale.scaleOrdinal(d3ScaleChromatic.schemePaired); // Autoset attribute colorField by colorByAccessor property
181
+ var autoColorScale = d3Scale.scaleOrdinal(d3ScaleChromatic.schemePaired);
182
+
183
+ // Autoset attribute colorField by colorByAccessor property
224
184
  // If an object has already a color, don't set it
225
185
  // Objects can be nodes or links
226
-
227
186
  function autoColorObjects(objects, colorByAccessor, colorField) {
228
187
  if (!colorByAccessor || typeof colorField !== 'string') return;
229
188
  objects.filter(function (obj) {
@@ -235,18 +194,16 @@ function autoColorObjects(objects, colorByAccessor, colorField) {
235
194
 
236
195
  function getDagDepths (_ref, idAccessor) {
237
196
  var nodes = _ref.nodes,
238
- links = _ref.links;
239
-
197
+ links = _ref.links;
240
198
  var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
241
- _ref2$nodeFilter = _ref2.nodeFilter,
242
- nodeFilter = _ref2$nodeFilter === void 0 ? function () {
243
- return true;
244
- } : _ref2$nodeFilter,
245
- _ref2$onLoopError = _ref2.onLoopError,
246
- onLoopError = _ref2$onLoopError === void 0 ? function (loopIds) {
247
- throw "Invalid DAG structure! Found cycle in node path: ".concat(loopIds.join(' -> '), ".");
248
- } : _ref2$onLoopError;
249
-
199
+ _ref2$nodeFilter = _ref2.nodeFilter,
200
+ nodeFilter = _ref2$nodeFilter === void 0 ? function () {
201
+ return true;
202
+ } : _ref2$nodeFilter,
203
+ _ref2$onLoopError = _ref2.onLoopError,
204
+ onLoopError = _ref2$onLoopError === void 0 ? function (loopIds) {
205
+ throw "Invalid DAG structure! Found cycle in node path: ".concat(loopIds.join(' -> '), ".");
206
+ } : _ref2$onLoopError;
250
207
  // linked graph
251
208
  var graph = {};
252
209
  nodes.forEach(function (node) {
@@ -259,7 +216,7 @@ function getDagDepths (_ref, idAccessor) {
259
216
  });
260
217
  links.forEach(function (_ref3) {
261
218
  var source = _ref3.source,
262
- target = _ref3.target;
219
+ target = _ref3.target;
263
220
  var sourceId = getNodeId(source);
264
221
  var targetId = getNodeId(target);
265
222
  if (!graph.hasOwnProperty(sourceId)) throw "Missing source node with id: ".concat(sourceId);
@@ -267,7 +224,6 @@ function getDagDepths (_ref, idAccessor) {
267
224
  var sourceNode = graph[sourceId];
268
225
  var targetNode = graph[targetId];
269
226
  sourceNode.out.push(targetNode);
270
-
271
227
  function getNodeId(node) {
272
228
  return _typeof(node) === 'object' ? idAccessor(node) : node;
273
229
  }
@@ -276,31 +232,25 @@ function getDagDepths (_ref, idAccessor) {
276
232
  traverse(Object.values(graph));
277
233
  var nodeDepths = Object.assign.apply(Object, [{}].concat(_toConsumableArray(Object.entries(graph).filter(function (_ref4) {
278
234
  var _ref5 = _slicedToArray(_ref4, 2),
279
- node = _ref5[1];
280
-
235
+ node = _ref5[1];
281
236
  return !node.skip;
282
237
  }).map(function (_ref6) {
283
238
  var _ref7 = _slicedToArray(_ref6, 2),
284
- id = _ref7[0],
285
- node = _ref7[1];
286
-
239
+ id = _ref7[0],
240
+ node = _ref7[1];
287
241
  return _defineProperty({}, id, node.depth);
288
242
  }))));
289
243
  return nodeDepths;
290
-
291
244
  function traverse(nodes) {
292
245
  var nodeStack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
293
246
  var currentDepth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
294
-
295
247
  for (var i = 0, l = nodes.length; i < l; i++) {
296
248
  var node = nodes[i];
297
-
298
249
  if (nodeStack.indexOf(node) !== -1) {
299
250
  var _ret = function () {
300
251
  var loop = [].concat(_toConsumableArray(nodeStack.slice(nodeStack.indexOf(node))), [node]).map(function (d) {
301
252
  return idAccessor(d.data);
302
253
  });
303
-
304
254
  if (!foundLoops.some(function (foundLoop) {
305
255
  return foundLoop.length === loop.length && foundLoop.every(function (id, idx) {
306
256
  return id === loop[idx];
@@ -309,13 +259,10 @@ function getDagDepths (_ref, idAccessor) {
309
259
  foundLoops.push(loop);
310
260
  onLoopError(loop);
311
261
  }
312
-
313
262
  return "continue";
314
263
  }();
315
-
316
264
  if (_ret === "continue") continue;
317
265
  }
318
-
319
266
  if (currentDepth > node.depth) {
320
267
  // Don't unnecessarily revisit chunks of the graph
321
268
  node.depth = currentDepth;
@@ -325,13 +272,15 @@ function getDagDepths (_ref, idAccessor) {
325
272
  }
326
273
  }
327
274
 
328
- var DAG_LEVEL_NODE_RATIO = 2; // whenever styling props are changed that require a canvas redraw
275
+ //
329
276
 
277
+ var DAG_LEVEL_NODE_RATIO = 2;
278
+
279
+ // whenever styling props are changed that require a canvas redraw
330
280
  var notifyRedraw = function notifyRedraw(_, state) {
331
281
  return state.onNeedsRedraw && state.onNeedsRedraw();
332
282
  };
333
-
334
- var CanvasForceGraph = Kapsule__default["default"]({
283
+ var CanvasForceGraph = Kapsule({
335
284
  props: {
336
285
  graphData: {
337
286
  "default": {
@@ -341,7 +290,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
341
290
  onChange: function onChange(_, state) {
342
291
  state.engineRunning = false;
343
292
  } // Pause simulation
344
-
345
293
  },
346
294
  dagMode: {
347
295
  onChange: function onChange(dagMode, state) {
@@ -351,6 +299,7 @@ var CanvasForceGraph = Kapsule__default["default"]({
351
299
  }); // unfix nodes when disabling dag mode
352
300
  }
353
301
  },
302
+
354
303
  dagLevelDistance: {},
355
304
  dagNodeFilter: {
356
305
  "default": function _default(node) {
@@ -544,7 +493,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
544
493
  }
545
494
 
546
495
  state.forceLayout.force(forceName, forceFn); // Force setter
547
-
548
496
  return this;
549
497
  },
550
498
  d3ReheatSimulation: function d3ReheatSimulation(state) {
@@ -568,52 +516,49 @@ var CanvasForceGraph = Kapsule__default["default"]({
568
516
  !state.isShadow && paintArrows();
569
517
  !state.isShadow && paintPhotons();
570
518
  paintNodes();
571
- return this; //
519
+ return this;
520
+
521
+ //
572
522
 
573
523
  function layoutTick() {
574
524
  if (state.engineRunning) {
575
525
  if (++state.cntTicks > state.cooldownTicks || new Date() - state.startTickTime > state.cooldownTime || state.d3AlphaMin > 0 && state.forceLayout.alpha() < state.d3AlphaMin) {
576
526
  state.engineRunning = false; // Stop ticking graph
577
-
578
527
  state.onEngineStop();
579
528
  } else {
580
529
  state.forceLayout.tick(); // Tick it
581
-
582
530
  state.onEngineTick();
583
531
  }
584
532
  }
585
533
  }
586
-
587
534
  function paintNodes() {
588
- var getVisibility = accessorFn__default["default"](state.nodeVisibility);
589
- var getVal = accessorFn__default["default"](state.nodeVal);
590
- var getColor = accessorFn__default["default"](state.nodeColor);
591
- var getNodeCanvasObjectMode = accessorFn__default["default"](state.nodeCanvasObjectMode);
592
- var ctx = state.ctx; // Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
535
+ var getVisibility = accessorFn(state.nodeVisibility);
536
+ var getVal = accessorFn(state.nodeVal);
537
+ var getColor = accessorFn(state.nodeColor);
538
+ var getNodeCanvasObjectMode = accessorFn(state.nodeCanvasObjectMode);
539
+ var ctx = state.ctx;
593
540
 
541
+ // Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
594
542
  var padAmount = state.isShadow / state.globalScale;
595
543
  var visibleNodes = state.graphData.nodes.filter(getVisibility);
596
544
  ctx.save();
597
545
  visibleNodes.forEach(function (node) {
598
546
  var nodeCanvasObjectMode = getNodeCanvasObjectMode(node);
599
-
600
547
  if (state.nodeCanvasObject && (nodeCanvasObjectMode === 'before' || nodeCanvasObjectMode === 'replace')) {
601
548
  // Custom node before/replace paint
602
549
  state.nodeCanvasObject(node, ctx, state.globalScale);
603
-
604
550
  if (nodeCanvasObjectMode === 'replace') {
605
551
  ctx.restore();
606
552
  return;
607
553
  }
608
- } // Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
609
-
554
+ }
610
555
 
556
+ // Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
611
557
  var r = Math.sqrt(Math.max(0, getVal(node) || 1)) * state.nodeRelSize + padAmount;
612
558
  ctx.beginPath();
613
559
  ctx.arc(node.x, node.y, r, 0, 2 * Math.PI, false);
614
560
  ctx.fillStyle = getColor(node) || 'rgba(31, 120, 180, 0.92)';
615
561
  ctx.fill();
616
-
617
562
  if (state.nodeCanvasObject && nodeCanvasObjectMode === 'after') {
618
563
  // Custom node after paint
619
564
  state.nodeCanvasObject(node, state.ctx, state.globalScale);
@@ -621,27 +566,26 @@ var CanvasForceGraph = Kapsule__default["default"]({
621
566
  });
622
567
  ctx.restore();
623
568
  }
624
-
625
569
  function paintLinks() {
626
- var getVisibility = accessorFn__default["default"](state.linkVisibility);
627
- var getColor = accessorFn__default["default"](state.linkColor);
628
- var getWidth = accessorFn__default["default"](state.linkWidth);
629
- var getLineDash = accessorFn__default["default"](state.linkLineDash);
630
- var getCurvature = accessorFn__default["default"](state.linkCurvature);
631
- var getLinkCanvasObjectMode = accessorFn__default["default"](state.linkCanvasObjectMode);
632
- var ctx = state.ctx; // Draw wider lines by 2px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
570
+ var getVisibility = accessorFn(state.linkVisibility);
571
+ var getColor = accessorFn(state.linkColor);
572
+ var getWidth = accessorFn(state.linkWidth);
573
+ var getLineDash = accessorFn(state.linkLineDash);
574
+ var getCurvature = accessorFn(state.linkCurvature);
575
+ var getLinkCanvasObjectMode = accessorFn(state.linkCanvasObjectMode);
576
+ var ctx = state.ctx;
633
577
 
578
+ // Draw wider lines by 2px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
634
579
  var padAmount = state.isShadow * 2;
635
580
  var visibleLinks = state.graphData.links.filter(getVisibility);
636
581
  visibleLinks.forEach(calcLinkControlPoints); // calculate curvature control points for all visible links
637
582
 
638
583
  var beforeCustomLinks = [],
639
- afterCustomLinks = [],
640
- defaultPaintLinks = visibleLinks;
641
-
584
+ afterCustomLinks = [],
585
+ defaultPaintLinks = visibleLinks;
642
586
  if (state.linkCanvasObject) {
643
587
  var replaceCustomLinks = [],
644
- otherCustomLinks = [];
588
+ otherCustomLinks = [];
645
589
  visibleLinks.forEach(function (d) {
646
590
  return ({
647
591
  before: beforeCustomLinks,
@@ -651,34 +595,32 @@ var CanvasForceGraph = Kapsule__default["default"]({
651
595
  });
652
596
  defaultPaintLinks = [].concat(_toConsumableArray(beforeCustomLinks), afterCustomLinks, otherCustomLinks);
653
597
  beforeCustomLinks = beforeCustomLinks.concat(replaceCustomLinks);
654
- } // Custom link before paints
655
-
598
+ }
656
599
 
600
+ // Custom link before paints
657
601
  ctx.save();
658
602
  beforeCustomLinks.forEach(function (link) {
659
603
  return state.linkCanvasObject(link, ctx, state.globalScale);
660
604
  });
661
- ctx.restore(); // Bundle strokes per unique color/width/dash for performance optimization
605
+ ctx.restore();
662
606
 
663
- var linksPerColor = indexBy__default["default"](defaultPaintLinks, [getColor, getWidth, getLineDash]);
607
+ // Bundle strokes per unique color/width/dash for performance optimization
608
+ var linksPerColor = indexBy(defaultPaintLinks, [getColor, getWidth, getLineDash]);
664
609
  ctx.save();
665
610
  Object.entries(linksPerColor).forEach(function (_ref) {
666
611
  var _ref2 = _slicedToArray(_ref, 2),
667
- color = _ref2[0],
668
- linksPerWidth = _ref2[1];
669
-
612
+ color = _ref2[0],
613
+ linksPerWidth = _ref2[1];
670
614
  var lineColor = !color || color === 'undefined' ? 'rgba(0,0,0,0.15)' : color;
671
615
  Object.entries(linksPerWidth).forEach(function (_ref3) {
672
616
  var _ref4 = _slicedToArray(_ref3, 2),
673
- width = _ref4[0],
674
- linesPerLineDash = _ref4[1];
675
-
617
+ width = _ref4[0],
618
+ linesPerLineDash = _ref4[1];
676
619
  var lineWidth = (width || 1) / state.globalScale + padAmount;
677
620
  Object.entries(linesPerLineDash).forEach(function (_ref5) {
678
621
  var _ref6 = _slicedToArray(_ref5, 2);
679
- _ref6[0];
680
- var links = _ref6[1];
681
-
622
+ _ref6[0];
623
+ var links = _ref6[1];
682
624
  var lineDashSegments = getLineDash(links[0]);
683
625
  ctx.beginPath();
684
626
  links.forEach(function (link) {
@@ -688,7 +630,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
688
630
 
689
631
  ctx.moveTo(start.x, start.y);
690
632
  var controlPoints = link.__controlPoints;
691
-
692
633
  if (!controlPoints) {
693
634
  // Straight line
694
635
  ctx.lineTo(end.x, end.y);
@@ -704,23 +645,24 @@ var CanvasForceGraph = Kapsule__default["default"]({
704
645
  });
705
646
  });
706
647
  });
707
- ctx.restore(); // Custom link after paints
648
+ ctx.restore();
708
649
 
650
+ // Custom link after paints
709
651
  ctx.save();
710
652
  afterCustomLinks.forEach(function (link) {
711
653
  return state.linkCanvasObject(link, ctx, state.globalScale);
712
654
  });
713
- ctx.restore(); //
655
+ ctx.restore();
656
+
657
+ //
714
658
 
715
659
  function calcLinkControlPoints(link) {
716
660
  var curvature = getCurvature(link);
717
-
718
661
  if (!curvature) {
719
662
  // straight line
720
663
  link.__controlPoints = null;
721
664
  return;
722
665
  }
723
-
724
666
  var start = link.source;
725
667
  var end = link.target;
726
668
  if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link
@@ -729,7 +671,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
729
671
 
730
672
  if (l > 0) {
731
673
  var a = Math.atan2(end.y - start.y, end.x - start.x); // line angle
732
-
733
674
  var d = l * curvature; // control point distance
734
675
 
735
676
  var cp = {
@@ -741,20 +682,18 @@ var CanvasForceGraph = Kapsule__default["default"]({
741
682
  } else {
742
683
  // Same point, draw a loop
743
684
  var _d = curvature * 70;
744
-
745
685
  link.__controlPoints = [end.x, end.y - _d, end.x + _d, end.y];
746
686
  }
747
687
  }
748
688
  }
749
-
750
689
  function paintArrows() {
751
690
  var ARROW_WH_RATIO = 1.6;
752
691
  var ARROW_VLEN_RATIO = 0.2;
753
- var getLength = accessorFn__default["default"](state.linkDirectionalArrowLength);
754
- var getRelPos = accessorFn__default["default"](state.linkDirectionalArrowRelPos);
755
- var getVisibility = accessorFn__default["default"](state.linkVisibility);
756
- var getColor = accessorFn__default["default"](state.linkDirectionalArrowColor || state.linkColor);
757
- var getNodeVal = accessorFn__default["default"](state.nodeVal);
692
+ var getLength = accessorFn(state.linkDirectionalArrowLength);
693
+ var getRelPos = accessorFn(state.linkDirectionalArrowRelPos);
694
+ var getVisibility = accessorFn(state.linkVisibility);
695
+ var getColor = accessorFn(state.linkDirectionalArrowColor || state.linkColor);
696
+ var getNodeVal = accessorFn(state.nodeVal);
758
697
  var ctx = state.ctx;
759
698
  ctx.save();
760
699
  state.graphData.links.filter(getVisibility).forEach(function (link) {
@@ -768,10 +707,10 @@ var CanvasForceGraph = Kapsule__default["default"]({
768
707
  var endR = Math.sqrt(Math.max(0, getNodeVal(end) || 1)) * state.nodeRelSize;
769
708
  var arrowRelPos = Math.min(1, Math.max(0, getRelPos(link)));
770
709
  var arrowColor = getColor(link) || 'rgba(0,0,0,0.28)';
771
- var arrowHalfWidth = arrowLength / ARROW_WH_RATIO / 2; // Construct bezier for curved lines
710
+ var arrowHalfWidth = arrowLength / ARROW_WH_RATIO / 2;
772
711
 
712
+ // Construct bezier for curved lines
773
713
  var bzLine = link.__controlPoints && _construct(bezierJs.Bezier, [start.x, start.y].concat(_toConsumableArray(link.__controlPoints), [end.x, end.y]));
774
-
775
714
  var getCoordsAlongLine = bzLine ? function (t) {
776
715
  return bzLine.get(t);
777
716
  } // get position along bezier line
@@ -798,13 +737,12 @@ var CanvasForceGraph = Kapsule__default["default"]({
798
737
  });
799
738
  ctx.restore();
800
739
  }
801
-
802
740
  function paintPhotons() {
803
- var getNumPhotons = accessorFn__default["default"](state.linkDirectionalParticles);
804
- var getSpeed = accessorFn__default["default"](state.linkDirectionalParticleSpeed);
805
- var getDiameter = accessorFn__default["default"](state.linkDirectionalParticleWidth);
806
- var getVisibility = accessorFn__default["default"](state.linkVisibility);
807
- var getColor = accessorFn__default["default"](state.linkDirectionalParticleColor || state.linkColor);
741
+ var getNumPhotons = accessorFn(state.linkDirectionalParticles);
742
+ var getSpeed = accessorFn(state.linkDirectionalParticleSpeed);
743
+ var getDiameter = accessorFn(state.linkDirectionalParticleWidth);
744
+ var getVisibility = accessorFn(state.linkVisibility);
745
+ var getColor = accessorFn(state.linkDirectionalParticleColor || state.linkColor);
808
746
  var ctx = state.ctx;
809
747
  ctx.save();
810
748
  state.graphData.links.filter(getVisibility).forEach(function (link) {
@@ -818,23 +756,20 @@ var CanvasForceGraph = Kapsule__default["default"]({
818
756
  var photons = link.__photons || [];
819
757
  var photonR = Math.max(0, getDiameter(link) / 2) / Math.sqrt(state.globalScale);
820
758
  var photonColor = getColor(link) || 'rgba(0,0,0,0.28)';
821
- ctx.fillStyle = photonColor; // Construct bezier for curved lines
759
+ ctx.fillStyle = photonColor;
822
760
 
761
+ // Construct bezier for curved lines
823
762
  var bzLine = link.__controlPoints ? _construct(bezierJs.Bezier, [start.x, start.y].concat(_toConsumableArray(link.__controlPoints), [end.x, end.y])) : null;
824
763
  var cyclePhotonIdx = 0;
825
764
  var needsCleanup = false; // whether some photons need to be removed from list
826
-
827
765
  photons.forEach(function (photon) {
828
766
  var singleHop = !!photon.__singleHop;
829
-
830
767
  if (!photon.hasOwnProperty('__progressRatio')) {
831
768
  photon.__progressRatio = singleHop ? 0 : cyclePhotonIdx / numCyclePhotons;
832
769
  }
833
-
834
770
  !singleHop && cyclePhotonIdx++; // increase regular photon index
835
771
 
836
772
  photon.__progressRatio += particleSpeed;
837
-
838
773
  if (photon.__progressRatio >= 1) {
839
774
  if (!singleHop) {
840
775
  photon.__progressRatio = photon.__progressRatio % 1;
@@ -843,7 +778,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
843
778
  return;
844
779
  }
845
780
  }
846
-
847
781
  var photonPosRatio = photon.__progressRatio;
848
782
  var coords = bzLine ? bzLine.get(photonPosRatio) // get position along bezier line
849
783
  : {
@@ -855,7 +789,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
855
789
  ctx.arc(coords.x, coords.y, photonR, 0, 2 * Math.PI, false);
856
790
  ctx.fill();
857
791
  });
858
-
859
792
  if (needsCleanup) {
860
793
  // remove expired single hop photons
861
794
  link.__photons = link.__photons.filter(function (photon) {
@@ -869,11 +802,9 @@ var CanvasForceGraph = Kapsule__default["default"]({
869
802
  emitParticle: function emitParticle(state, link) {
870
803
  if (link) {
871
804
  !link.__photons && (link.__photons = []);
872
-
873
805
  link.__photons.push({
874
806
  __singleHop: true
875
807
  }); // add a single hop particle
876
-
877
808
  }
878
809
 
879
810
  return this;
@@ -891,31 +822,26 @@ var CanvasForceGraph = Kapsule__default["default"]({
891
822
  },
892
823
  update: function update(state) {
893
824
  state.engineRunning = false; // Pause simulation
894
-
895
825
  state.onUpdate();
896
-
897
826
  if (state.nodeAutoColorBy !== null) {
898
827
  // Auto add color to uncolored nodes
899
- autoColorObjects(state.graphData.nodes, accessorFn__default["default"](state.nodeAutoColorBy), state.nodeColor);
828
+ autoColorObjects(state.graphData.nodes, accessorFn(state.nodeAutoColorBy), state.nodeColor);
900
829
  }
901
-
902
830
  if (state.linkAutoColorBy !== null) {
903
831
  // Auto add color to uncolored links
904
- autoColorObjects(state.graphData.links, accessorFn__default["default"](state.linkAutoColorBy), state.linkColor);
905
- } // parse links
906
-
832
+ autoColorObjects(state.graphData.links, accessorFn(state.linkAutoColorBy), state.linkColor);
833
+ }
907
834
 
835
+ // parse links
908
836
  state.graphData.links.forEach(function (link) {
909
837
  link.source = link[state.linkSource];
910
838
  link.target = link[state.linkTarget];
911
839
  });
912
-
913
840
  if (!state.isShadow) {
914
841
  // Add photon particles
915
- var linkParticlesAccessor = accessorFn__default["default"](state.linkDirectionalParticles);
842
+ var linkParticlesAccessor = accessorFn(state.linkDirectionalParticles);
916
843
  state.graphData.links.forEach(function (link) {
917
844
  var numPhotons = Math.round(Math.abs(linkParticlesAccessor(link)));
918
-
919
845
  if (numPhotons) {
920
846
  link.__photons = _toConsumableArray(Array(numPhotons)).map(function () {
921
847
  return {};
@@ -924,21 +850,21 @@ var CanvasForceGraph = Kapsule__default["default"]({
924
850
  delete link.__photons;
925
851
  }
926
852
  });
927
- } // Feed data to force-directed layout
928
-
853
+ }
929
854
 
855
+ // Feed data to force-directed layout
930
856
  state.forceLayout.stop().alpha(1) // re-heat the simulation
931
- .nodes(state.graphData.nodes); // add links (if link force is still active)
857
+ .nodes(state.graphData.nodes);
932
858
 
859
+ // add links (if link force is still active)
933
860
  var linkForce = state.forceLayout.force('link');
934
-
935
861
  if (linkForce) {
936
862
  linkForce.id(function (d) {
937
863
  return d[state.nodeId];
938
864
  }).links(state.graphData.links);
939
- } // setup dag force constraints
940
-
865
+ }
941
866
 
867
+ // setup dag force constraints
942
868
  var nodeDepths = state.dagMode && getDagDepths(state.graphData, function (node) {
943
869
  return node[state.nodeId];
944
870
  }, {
@@ -946,36 +872,34 @@ var CanvasForceGraph = Kapsule__default["default"]({
946
872
  onLoopError: state.onDagError || undefined
947
873
  });
948
874
  var maxDepth = Math.max.apply(Math, _toConsumableArray(Object.values(nodeDepths || [])));
949
- var dagLevelDistance = state.dagLevelDistance || state.graphData.nodes.length / (maxDepth || 1) * DAG_LEVEL_NODE_RATIO * (['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? 0.7 : 1); // Fix nodes to x,y for dag mode
875
+ var dagLevelDistance = state.dagLevelDistance || state.graphData.nodes.length / (maxDepth || 1) * DAG_LEVEL_NODE_RATIO * (['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? 0.7 : 1);
950
876
 
877
+ // Fix nodes to x,y for dag mode
951
878
  if (state.dagMode) {
952
879
  var getFFn = function getFFn(fix, invert) {
953
880
  return function (node) {
954
881
  return !fix ? undefined : (nodeDepths[node[state.nodeId]] - maxDepth / 2) * dagLevelDistance * (invert ? -1 : 1);
955
882
  };
956
883
  };
957
-
958
884
  var fxFn = getFFn(['lr', 'rl'].indexOf(state.dagMode) !== -1, state.dagMode === 'rl');
959
885
  var fyFn = getFFn(['td', 'bu'].indexOf(state.dagMode) !== -1, state.dagMode === 'bu');
960
886
  state.graphData.nodes.filter(state.dagNodeFilter).forEach(function (node) {
961
887
  node.fx = fxFn(node);
962
888
  node.fy = fyFn(node);
963
889
  });
964
- } // Use radial force for radial dags
965
-
890
+ }
966
891
 
892
+ // Use radial force for radial dags
967
893
  state.forceLayout.force('dagRadial', ['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? d3Force3d.forceRadial(function (node) {
968
894
  var nodeDepth = nodeDepths[node[state.nodeId]] || -1;
969
895
  return (state.dagMode === 'radialin' ? maxDepth - nodeDepth : nodeDepth) * dagLevelDistance;
970
896
  }).strength(function (node) {
971
897
  return state.dagNodeFilter(node) ? 1 : 0;
972
898
  }) : null);
973
-
974
899
  for (var i = 0; i < state.warmupTicks && !(state.d3AlphaMin > 0 && state.forceLayout.alpha() < state.d3AlphaMin); i++) {
975
900
  state.forceLayout.tick();
976
901
  } // Initial ticks before starting to render
977
902
 
978
-
979
903
  this.resetCountdown();
980
904
  state.onFinishUpdate();
981
905
  }
@@ -1004,12 +928,10 @@ function linkKapsule (kapsulePropNames, kapsuleType) {
1004
928
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1005
929
  args[_key - 1] = arguments[_key];
1006
930
  }
1007
-
1008
931
  var returnVals = [];
1009
932
  propNames.forEach(function (propName) {
1010
933
  var kapsuleInstance = state[propName];
1011
934
  var returnVal = kapsuleInstance[method].apply(kapsuleInstance, args);
1012
-
1013
935
  if (returnVal !== kapsuleInstance) {
1014
936
  returnVals.push(returnVal);
1015
937
  }
@@ -1021,9 +943,9 @@ function linkKapsule (kapsulePropNames, kapsuleType) {
1021
943
  }
1022
944
 
1023
945
  var HOVER_CANVAS_THROTTLE_DELAY = 800; // ms to throttle shadow canvas updates for perf improvement
946
+ var ZOOM2NODES_FACTOR = 4;
1024
947
 
1025
- var ZOOM2NODES_FACTOR = 4; // Expose config from forceGraph
1026
-
948
+ // Expose config from forceGraph
1027
949
  var bindFG = linkKapsule('forceGraph', CanvasForceGraph);
1028
950
  var bindBoth = linkKapsule(['forceGraph', 'shadowGraph'], CanvasForceGraph);
1029
951
  var linkedProps = Object.assign.apply(Object, _toConsumableArray(['nodeColor', 'nodeAutoColorBy', 'nodeCanvasObject', 'nodeCanvasObjectMode', 'linkColor', 'linkAutoColorBy', 'linkLineDash', 'linkWidth', 'linkCanvasObject', 'linkCanvasObjectMode', 'linkDirectionalArrowLength', 'linkDirectionalArrowColor', 'linkDirectionalArrowRelPos', 'linkDirectionalParticles', 'linkDirectionalParticleSpeed', 'linkDirectionalParticleWidth', 'linkDirectionalParticleColor', 'dagMode', 'dagLevelDistance', 'dagNodeFilter', 'onDagError', 'd3AlphaMin', 'd3AlphaDecay', 'd3VelocityDecay', 'warmupTicks', 'cooldownTicks', 'cooldownTime', 'onEngineTick', 'onEngineStop'].map(function (p) {
@@ -1034,56 +956,54 @@ var linkedProps = Object.assign.apply(Object, _toConsumableArray(['nodeColor', '
1034
956
  var linkedMethods = Object.assign.apply(Object, _toConsumableArray(['d3Force', 'd3ReheatSimulation', 'emitParticle'].map(function (p) {
1035
957
  return _defineProperty({}, p, bindFG.linkMethod(p));
1036
958
  })));
1037
-
1038
959
  function adjustCanvasSize(state) {
1039
960
  if (state.canvas) {
1040
961
  var curWidth = state.canvas.width;
1041
962
  var curHeight = state.canvas.height;
1042
-
1043
963
  if (curWidth === 300 && curHeight === 150) {
1044
964
  // Default canvas dimensions
1045
965
  curWidth = curHeight = 0;
1046
966
  }
1047
-
1048
967
  var pxScale = window.devicePixelRatio; // 2 on retina displays
1049
-
1050
968
  curWidth /= pxScale;
1051
- curHeight /= pxScale; // Resize canvases
969
+ curHeight /= pxScale;
1052
970
 
971
+ // Resize canvases
1053
972
  [state.canvas, state.shadowCanvas].forEach(function (canvas) {
1054
973
  // Element size
1055
974
  canvas.style.width = "".concat(state.width, "px");
1056
- canvas.style.height = "".concat(state.height, "px"); // Memory size (scaled to avoid blurriness)
975
+ canvas.style.height = "".concat(state.height, "px");
1057
976
 
977
+ // Memory size (scaled to avoid blurriness)
1058
978
  canvas.width = state.width * pxScale;
1059
- canvas.height = state.height * pxScale; // Normalize coordinate system to use css pixels (on init only)
979
+ canvas.height = state.height * pxScale;
1060
980
 
981
+ // Normalize coordinate system to use css pixels (on init only)
1061
982
  if (!curWidth && !curHeight) {
1062
983
  canvas.getContext('2d').scale(pxScale, pxScale);
1063
984
  }
1064
- }); // Relative center panning based on 0,0
985
+ });
1065
986
 
987
+ // Relative center panning based on 0,0
1066
988
  var k = d3Zoom.zoomTransform(state.canvas).k;
1067
989
  state.zoom.translateBy(state.zoom.__baseElem, (state.width - curWidth) / 2 / k, (state.height - curHeight) / 2 / k);
1068
990
  state.needsRedraw = true;
1069
991
  }
1070
992
  }
1071
-
1072
993
  function resetTransform(ctx) {
1073
994
  var pxRatio = window.devicePixelRatio;
1074
995
  ctx.setTransform(pxRatio, 0, 0, pxRatio, 0, 0);
1075
996
  }
1076
-
1077
997
  function clearCanvas(ctx, width, height) {
1078
998
  ctx.save();
1079
999
  resetTransform(ctx); // reset transform
1080
-
1081
1000
  ctx.clearRect(0, 0, width, height);
1082
1001
  ctx.restore(); //restore transforms
1083
- } //
1002
+ }
1084
1003
 
1004
+ //
1085
1005
 
1086
- var forceGraph = Kapsule__default["default"]({
1006
+ var forceGraph = Kapsule({
1087
1007
  props: _objectSpread2({
1088
1008
  width: {
1089
1009
  "default": window.innerWidth,
@@ -1114,10 +1034,9 @@ var forceGraph = Kapsule__default["default"]({
1114
1034
  }].forEach(hexIndex);
1115
1035
  state.forceGraph.graphData(d);
1116
1036
  state.shadowGraph.graphData(d);
1117
-
1118
1037
  function hexIndex(_ref4) {
1119
1038
  var type = _ref4.type,
1120
- objs = _ref4.objs;
1039
+ objs = _ref4.objs;
1121
1040
  objs.filter(function (d) {
1122
1041
  if (!d.hasOwnProperty('__indexColor')) return true;
1123
1042
  var cur = state.colorTracker.lookup(d.__indexColor);
@@ -1277,27 +1196,27 @@ var forceGraph = Kapsule__default["default"]({
1277
1196
  },
1278
1197
  centerAt: function centerAt(state, x, y, transitionDuration) {
1279
1198
  if (!state.canvas) return null; // no canvas yet
1280
- // setter
1281
1199
 
1200
+ // setter
1282
1201
  if (x !== undefined || y !== undefined) {
1283
1202
  var finalPos = Object.assign({}, x !== undefined ? {
1284
1203
  x: x
1285
1204
  } : {}, y !== undefined ? {
1286
1205
  y: y
1287
1206
  } : {});
1288
-
1289
1207
  if (!transitionDuration) {
1290
1208
  // no animation
1291
1209
  setCenter(finalPos);
1292
1210
  } else {
1293
- new TWEEN__default["default"].Tween(getCenter()).to(finalPos, transitionDuration).easing(TWEEN__default["default"].Easing.Quadratic.Out).onUpdate(setCenter).start();
1211
+ new TWEEN.Tween(getCenter()).to(finalPos, transitionDuration).easing(TWEEN.Easing.Quadratic.Out).onUpdate(setCenter).start();
1294
1212
  }
1295
-
1296
1213
  return this;
1297
- } // getter
1214
+ }
1298
1215
 
1216
+ // getter
1217
+ return getCenter();
1299
1218
 
1300
- return getCenter(); //
1219
+ //
1301
1220
 
1302
1221
  function getCenter() {
1303
1222
  var t = d3Zoom.zoomTransform(state.canvas);
@@ -1306,43 +1225,42 @@ var forceGraph = Kapsule__default["default"]({
1306
1225
  y: (state.height / 2 - t.y) / t.k
1307
1226
  };
1308
1227
  }
1309
-
1310
1228
  function setCenter(_ref5) {
1311
1229
  var x = _ref5.x,
1312
- y = _ref5.y;
1230
+ y = _ref5.y;
1313
1231
  state.zoom.translateTo(state.zoom.__baseElem, x === undefined ? getCenter().x : x, y === undefined ? getCenter().y : y);
1314
1232
  state.needsRedraw = true;
1315
1233
  }
1316
1234
  },
1317
1235
  zoom: function zoom(state, k, transitionDuration) {
1318
1236
  if (!state.canvas) return null; // no canvas yet
1319
- // setter
1320
1237
 
1238
+ // setter
1321
1239
  if (k !== undefined) {
1322
1240
  if (!transitionDuration) {
1323
1241
  // no animation
1324
1242
  setZoom(k);
1325
1243
  } else {
1326
- new TWEEN__default["default"].Tween({
1244
+ new TWEEN.Tween({
1327
1245
  k: getZoom()
1328
1246
  }).to({
1329
1247
  k: k
1330
- }, transitionDuration).easing(TWEEN__default["default"].Easing.Quadratic.Out).onUpdate(function (_ref6) {
1248
+ }, transitionDuration).easing(TWEEN.Easing.Quadratic.Out).onUpdate(function (_ref6) {
1331
1249
  var k = _ref6.k;
1332
1250
  return setZoom(k);
1333
1251
  }).start();
1334
1252
  }
1335
-
1336
1253
  return this;
1337
- } // getter
1254
+ }
1338
1255
 
1256
+ // getter
1257
+ return getZoom();
1339
1258
 
1340
- return getZoom(); //
1259
+ //
1341
1260
 
1342
1261
  function getZoom() {
1343
1262
  return d3Zoom.zoomTransform(state.canvas).k;
1344
1263
  }
1345
-
1346
1264
  function setZoom(k) {
1347
1265
  state.zoom.scaleTo(state.zoom.__baseElem, k);
1348
1266
  state.needsRedraw = true;
@@ -1351,13 +1269,10 @@ var forceGraph = Kapsule__default["default"]({
1351
1269
  zoomToFit: function zoomToFit(state) {
1352
1270
  var transitionDuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
1353
1271
  var padding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;
1354
-
1355
1272
  for (var _len = arguments.length, bboxArgs = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
1356
1273
  bboxArgs[_key - 3] = arguments[_key];
1357
1274
  }
1358
-
1359
1275
  var bbox = this.getGraphBbox.apply(this, bboxArgs);
1360
-
1361
1276
  if (bbox) {
1362
1277
  var center = {
1363
1278
  x: (bbox.x[0] + bbox.x[1]) / 2,
@@ -1367,19 +1282,16 @@ var forceGraph = Kapsule__default["default"]({
1367
1282
  this.centerAt(center.x, center.y, transitionDuration);
1368
1283
  this.zoom(zoomK, transitionDuration);
1369
1284
  }
1370
-
1371
1285
  return this;
1372
1286
  },
1373
1287
  getGraphBbox: function getGraphBbox(state) {
1374
1288
  var nodeFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
1375
1289
  return true;
1376
1290
  };
1377
- var getVal = accessorFn__default["default"](state.nodeVal);
1378
-
1291
+ var getVal = accessorFn(state.nodeVal);
1379
1292
  var getR = function getR(node) {
1380
1293
  return Math.sqrt(Math.max(0, getVal(node) || 1)) * state.nodeRelSize;
1381
1294
  };
1382
-
1383
1295
  var nodesPos = state.graphData.nodes.filter(nodeFilter).map(function (node) {
1384
1296
  return {
1385
1297
  x: node.x,
@@ -1405,14 +1317,12 @@ var forceGraph = Kapsule__default["default"]({
1405
1317
  cancelAnimationFrame(state.animationFrameRequestId);
1406
1318
  state.animationFrameRequestId = null;
1407
1319
  }
1408
-
1409
1320
  return this;
1410
1321
  },
1411
1322
  resumeAnimation: function resumeAnimation(state) {
1412
1323
  if (!state.animationFrameRequestId) {
1413
1324
  this._animationCycle();
1414
1325
  }
1415
-
1416
1326
  return this;
1417
1327
  },
1418
1328
  _destructor: function _destructor() {
@@ -1429,16 +1339,16 @@ var forceGraph = Kapsule__default["default"]({
1429
1339
  zoom: d3Zoom.zoom(),
1430
1340
  forceGraph: new CanvasForceGraph(),
1431
1341
  shadowGraph: new CanvasForceGraph().cooldownTicks(0).nodeColor('__indexColor').linkColor('__indexColor').isShadow(true),
1432
- colorTracker: new ColorTracker__default["default"]() // indexed objects for rgb lookup
1433
-
1342
+ colorTracker: new ColorTracker() // indexed objects for rgb lookup
1434
1343
  };
1435
1344
  },
1345
+
1436
1346
  init: function init(domNode, state) {
1437
1347
  var _this = this;
1438
-
1439
1348
  // Wipe DOM
1440
- domNode.innerHTML = ''; // Container anchor for canvas and tooltip
1349
+ domNode.innerHTML = '';
1441
1350
 
1351
+ // Container anchor for canvas and tooltip
1442
1352
  var container = document.createElement('div');
1443
1353
  container.classList.add('force-graph-container');
1444
1354
  container.style.position = 'relative';
@@ -1446,7 +1356,9 @@ var forceGraph = Kapsule__default["default"]({
1446
1356
  state.canvas = document.createElement('canvas');
1447
1357
  if (state.backgroundColor) state.canvas.style.background = state.backgroundColor;
1448
1358
  container.appendChild(state.canvas);
1449
- state.shadowCanvas = document.createElement('canvas'); // Show shadow canvas
1359
+ state.shadowCanvas = document.createElement('canvas');
1360
+
1361
+ // Show shadow canvas
1450
1362
  //state.shadowCanvas.style.position = 'absolute';
1451
1363
  //state.shadowCanvas.style.top = '0';
1452
1364
  //state.shadowCanvas.style.left = '0';
@@ -1458,22 +1370,20 @@ var forceGraph = Kapsule__default["default"]({
1458
1370
  x: -1e12,
1459
1371
  y: -1e12
1460
1372
  };
1461
-
1462
1373
  var getObjUnderPointer = function getObjUnderPointer() {
1463
1374
  var obj = null;
1464
1375
  var pxScale = window.devicePixelRatio;
1465
- var px = pointerPos.x > 0 && pointerPos.y > 0 ? shadowCtx.getImageData(pointerPos.x * pxScale, pointerPos.y * pxScale, 1, 1) : null; // Lookup object per pixel color
1466
-
1376
+ var px = pointerPos.x > 0 && pointerPos.y > 0 ? shadowCtx.getImageData(pointerPos.x * pxScale, pointerPos.y * pxScale, 1, 1) : null;
1377
+ // Lookup object per pixel color
1467
1378
  px && (obj = state.colorTracker.lookup(px.data));
1468
1379
  return obj;
1469
- }; // Setup node drag interaction
1470
-
1380
+ };
1471
1381
 
1382
+ // Setup node drag interaction
1472
1383
  d3Selection.select(state.canvas).call(d3Drag.drag().subject(function () {
1473
1384
  if (!state.enableNodeDrag) {
1474
1385
  return null;
1475
1386
  }
1476
-
1477
1387
  var obj = getObjUnderPointer();
1478
1388
  return obj && obj.type === 'Node' ? obj.d : null; // Only drag nodes
1479
1389
  }).on('start', function (ev) {
@@ -1483,14 +1393,15 @@ var forceGraph = Kapsule__default["default"]({
1483
1393
  y: obj.y,
1484
1394
  fx: obj.fx,
1485
1395
  fy: obj.fy
1486
- }; // keep engine running at low intensity throughout drag
1396
+ };
1487
1397
 
1398
+ // keep engine running at low intensity throughout drag
1488
1399
  if (!ev.active) {
1489
1400
  obj.fx = obj.x;
1490
1401
  obj.fy = obj.y; // Fix points
1491
- } // drag cursor
1492
-
1402
+ }
1493
1403
 
1404
+ // drag cursor
1494
1405
  state.canvas.classList.add('grabbable');
1495
1406
  }).on('drag', function (ev) {
1496
1407
  var obj = ev.subject;
@@ -1500,12 +1411,14 @@ var forceGraph = Kapsule__default["default"]({
1500
1411
  var translate = {
1501
1412
  x: initPos.x + (dragPos.x - initPos.x) / k - obj.x,
1502
1413
  y: initPos.y + (dragPos.y - initPos.y) / k - obj.y
1503
- }; // Move fx/fy (and x/y) of nodes based on the scaled drag distance since the drag start
1414
+ };
1504
1415
 
1416
+ // Move fx/fy (and x/y) of nodes based on the scaled drag distance since the drag start
1505
1417
  ['x', 'y'].forEach(function (c) {
1506
1418
  return obj["f".concat(c)] = obj[c] = initPos[c] + (dragPos[c] - initPos[c]) / k;
1507
- }); // prevent freeze while dragging
1419
+ });
1508
1420
 
1421
+ // prevent freeze while dragging
1509
1422
  state.forceGraph.d3AlphaTarget(0.3) // keep engine running at low intensity throughout drag
1510
1423
  .resetCountdown(); // prevent freeze while dragging
1511
1424
 
@@ -1519,39 +1432,35 @@ var forceGraph = Kapsule__default["default"]({
1519
1432
  x: obj.x - initPos.x,
1520
1433
  y: obj.y - initPos.y
1521
1434
  };
1522
-
1523
1435
  if (initPos.fx === undefined) {
1524
1436
  obj.fx = undefined;
1525
1437
  }
1526
-
1527
1438
  if (initPos.fy === undefined) {
1528
1439
  obj.fy = undefined;
1529
1440
  }
1530
-
1531
1441
  delete obj.__initialDragPos;
1532
-
1533
1442
  if (state.forceGraph.d3AlphaTarget()) {
1534
1443
  state.forceGraph.d3AlphaTarget(0) // release engine low intensity
1535
1444
  .resetCountdown(); // let the engine readjust after releasing fixed nodes
1536
- } // drag cursor
1537
-
1445
+ }
1538
1446
 
1447
+ // drag cursor
1539
1448
  state.canvas.classList.remove('grabbable');
1540
1449
  state.isPointerDragging = false;
1541
-
1542
1450
  if (obj.__dragged) {
1543
1451
  delete obj.__dragged;
1544
1452
  state.onNodeDragEnd(obj, translate);
1545
1453
  }
1546
- })); // Setup zoom / pan interaction
1454
+ }));
1547
1455
 
1456
+ // Setup zoom / pan interaction
1548
1457
  state.zoom(state.zoom.__baseElem = d3Selection.select(state.canvas)); // Attach controlling elem for easy access
1549
1458
 
1550
1459
  state.zoom.__baseElem.on('dblclick.zoom', null); // Disable double-click to zoom
1551
1460
 
1552
-
1553
1461
  state.zoom.filter(function (ev) {
1554
- return (// disable zoom interaction
1462
+ return (
1463
+ // disable zoom interaction
1555
1464
  !ev.button && state.enableZoomPanInteraction && (state.enableZoomInteraction || ev.type !== 'wheel') && (state.enablePanInteraction || ev.type === 'wheel')
1556
1465
  );
1557
1466
  }).on('zoom', function (ev) {
@@ -1562,7 +1471,6 @@ var forceGraph = Kapsule__default["default"]({
1562
1471
  c.scale(t.k, t.k);
1563
1472
  });
1564
1473
  state.onZoom && state.onZoom(_objectSpread2(_objectSpread2({}, t), _this.centerAt())); // report x,y coordinates relative to canvas center
1565
-
1566
1474
  state.needsRedraw = true;
1567
1475
  }).on('end', function (ev) {
1568
1476
  return state.onZoomEnd && state.onZoomEnd(_objectSpread2(_objectSpread2({}, ev.transform), _this.centerAt()));
@@ -1576,39 +1484,49 @@ var forceGraph = Kapsule__default["default"]({
1576
1484
  state.zoom.scaleTo(state.zoom.__baseElem, state.lastSetZoom = ZOOM2NODES_FACTOR / Math.cbrt(state.graphData.nodes.length));
1577
1485
  state.needsRedraw = true;
1578
1486
  }
1579
- }); // Setup tooltip
1487
+ });
1580
1488
 
1489
+ // Setup tooltip
1581
1490
  var toolTipElem = document.createElement('div');
1582
1491
  toolTipElem.classList.add('graph-tooltip');
1583
- container.appendChild(toolTipElem); // Capture pointer coords on move or touchstart
1492
+ container.appendChild(toolTipElem);
1584
1493
 
1494
+ // Capture pointer coords on move or touchstart
1585
1495
  ['pointermove', 'pointerdown'].forEach(function (evType) {
1586
1496
  return container.addEventListener(evType, function (ev) {
1587
1497
  if (evType === 'pointerdown') {
1588
1498
  state.isPointerPressed = true; // track click state
1589
-
1590
1499
  state.pointerDownEvent = ev;
1591
- } // detect pointer drag on canvas pan
1592
-
1500
+ }
1593
1501
 
1502
+ // detect pointer drag on canvas pan
1594
1503
  !state.isPointerDragging && ev.type === 'pointermove' && state.onBackgroundClick // only bother detecting drags this way if background clicks are enabled (so they don't trigger accidentally on canvas panning)
1595
1504
  && (ev.pressure > 0 || state.isPointerPressed) // ev.pressure always 0 on Safari, so we use the isPointerPressed tracker
1596
1505
  && (ev.pointerType !== 'touch' || ev.movementX === undefined || [ev.movementX, ev.movementY].some(function (m) {
1597
1506
  return Math.abs(m) > 1;
1598
1507
  })) // relax drag trigger sensitivity on touch events
1599
- && (state.isPointerDragging = true); // update the pointer pos
1508
+ && (state.isPointerDragging = true);
1600
1509
 
1510
+ // update the pointer pos
1601
1511
  var offset = getOffset(container);
1602
1512
  pointerPos.x = ev.pageX - offset.left;
1603
- pointerPos.y = ev.pageY - offset.top; // Move tooltip
1513
+ pointerPos.y = ev.pageY - offset.top;
1604
1514
 
1515
+ // Move tooltip
1605
1516
  toolTipElem.style.top = "".concat(pointerPos.y, "px");
1606
- toolTipElem.style.left = "".concat(pointerPos.x, "px"); //
1517
+ toolTipElem.style.left = "".concat(pointerPos.x, "px");
1518
+
1519
+ // adjust horizontal position to not exceed canvas boundaries
1520
+ toolTipElem.style.transform = "translate(-".concat(pointerPos.x / state.width * 100, "%, ").concat(
1521
+ // flip to above if near bottom
1522
+ state.height - pointerPos.y < 100 ? 'calc(-100% - 8px)' : '21px', ")");
1523
+
1524
+ //
1607
1525
 
1608
1526
  function getOffset(el) {
1609
1527
  var rect = el.getBoundingClientRect(),
1610
- scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
1611
- scrollTop = window.pageYOffset || document.documentElement.scrollTop;
1528
+ scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
1529
+ scrollTop = window.pageYOffset || document.documentElement.scrollTop;
1612
1530
  return {
1613
1531
  top: rect.top + scrollTop,
1614
1532
  left: rect.left + scrollLeft
@@ -1617,11 +1535,11 @@ var forceGraph = Kapsule__default["default"]({
1617
1535
  }, {
1618
1536
  passive: true
1619
1537
  });
1620
- }); // Handle click/touch events on nodes/links
1538
+ });
1621
1539
 
1540
+ // Handle click/touch events on nodes/links
1622
1541
  container.addEventListener('pointerup', function (ev) {
1623
1542
  state.isPointerPressed = false;
1624
-
1625
1543
  if (state.isPointerDragging) {
1626
1544
  state.isPointerDragging = false;
1627
1545
  return; // don't trigger click events after pointer drag (pan / node drag functionality)
@@ -1639,7 +1557,6 @@ var forceGraph = Kapsule__default["default"]({
1639
1557
  state.onBackgroundClick && state.onBackgroundClick.apply(state, cbEvents);
1640
1558
  }
1641
1559
  }
1642
-
1643
1560
  if (ev.button === 2) {
1644
1561
  // mouse right-click
1645
1562
  if (state.hoverObj) {
@@ -1655,77 +1572,74 @@ var forceGraph = Kapsule__default["default"]({
1655
1572
  });
1656
1573
  container.addEventListener('contextmenu', function (ev) {
1657
1574
  if (!state.onBackgroundRightClick && !state.onNodeRightClick && !state.onLinkRightClick) return true; // default contextmenu behavior
1658
-
1659
1575
  ev.preventDefault();
1660
1576
  return false;
1661
1577
  });
1662
1578
  state.forceGraph(ctx);
1663
- state.shadowGraph(shadowCtx); //
1579
+ state.shadowGraph(shadowCtx);
1580
+
1581
+ //
1664
1582
 
1665
- var refreshShadowCanvas = throttle__default["default"](function () {
1583
+ var refreshShadowCanvas = throttle(function () {
1666
1584
  // wipe canvas
1667
- clearCanvas(shadowCtx, state.width, state.height); // Adjust link hover area
1585
+ clearCanvas(shadowCtx, state.width, state.height);
1668
1586
 
1587
+ // Adjust link hover area
1669
1588
  state.shadowGraph.linkWidth(function (l) {
1670
- return accessorFn__default["default"](state.linkWidth)(l) + state.linkHoverPrecision;
1671
- }); // redraw
1589
+ return accessorFn(state.linkWidth)(l) + state.linkHoverPrecision;
1590
+ });
1672
1591
 
1592
+ // redraw
1673
1593
  var t = d3Zoom.zoomTransform(state.canvas);
1674
1594
  state.shadowGraph.globalScale(t.k).tickFrame();
1675
1595
  }, HOVER_CANVAS_THROTTLE_DELAY);
1676
1596
  state.flushShadowCanvas = refreshShadowCanvas.flush; // hook to immediately invoke shadow canvas paint
1677
- // Kick-off renderer
1678
1597
 
1598
+ // Kick-off renderer
1679
1599
  (this._animationCycle = function animate() {
1680
1600
  // IIFE
1681
1601
  var doRedraw = !state.autoPauseRedraw || !!state.needsRedraw || state.forceGraph.isEngineRunning() || state.graphData.links.some(function (d) {
1682
1602
  return d.__photons && d.__photons.length;
1683
1603
  });
1684
1604
  state.needsRedraw = false;
1685
-
1686
1605
  if (state.enablePointerInteraction) {
1687
1606
  // Update tooltip and trigger onHover events
1688
1607
  var obj = !state.isPointerDragging ? getObjUnderPointer() : null; // don't hover during drag
1689
-
1690
1608
  if (obj !== state.hoverObj) {
1691
1609
  var prevObj = state.hoverObj;
1692
1610
  var prevObjType = prevObj ? prevObj.type : null;
1693
1611
  var objType = obj ? obj.type : null;
1694
-
1695
1612
  if (prevObjType && prevObjType !== objType) {
1696
1613
  // Hover out
1697
1614
  var fn = state["on".concat(prevObjType, "Hover")];
1698
1615
  fn && fn(null, prevObj.d);
1699
1616
  }
1700
-
1701
1617
  if (objType) {
1702
1618
  // Hover in
1703
1619
  var _fn2 = state["on".concat(objType, "Hover")];
1704
1620
  _fn2 && _fn2(obj.d, prevObjType === objType ? prevObj.d : null);
1705
1621
  }
1706
-
1707
- var tooltipContent = obj ? accessorFn__default["default"](state["".concat(obj.type.toLowerCase(), "Label")])(obj.d) || '' : '';
1622
+ var tooltipContent = obj ? accessorFn(state["".concat(obj.type.toLowerCase(), "Label")])(obj.d) || '' : '';
1708
1623
  toolTipElem.style.visibility = tooltipContent ? 'visible' : 'hidden';
1709
- toolTipElem.innerHTML = tooltipContent; // set pointer if hovered object is clickable
1624
+ toolTipElem.innerHTML = tooltipContent;
1710
1625
 
1626
+ // set pointer if hovered object is clickable
1711
1627
  state.canvas.classList[obj && state["on".concat(objType, "Click")] || !obj && state.onBackgroundClick ? 'add' : 'remove']('clickable');
1712
1628
  state.hoverObj = obj;
1713
1629
  }
1714
-
1715
1630
  doRedraw && refreshShadowCanvas();
1716
1631
  }
1717
-
1718
1632
  if (doRedraw) {
1719
1633
  // Wipe canvas
1720
- clearCanvas(ctx, state.width, state.height); // Frame cycle
1634
+ clearCanvas(ctx, state.width, state.height);
1721
1635
 
1636
+ // Frame cycle
1722
1637
  var globalScale = d3Zoom.zoomTransform(state.canvas).k;
1723
1638
  state.onRenderFramePre && state.onRenderFramePre(ctx, globalScale);
1724
1639
  state.forceGraph.globalScale(globalScale).tickFrame();
1725
1640
  state.onRenderFramePost && state.onRenderFramePost(ctx, globalScale);
1726
1641
  }
1727
-
1728
- TWEEN__default["default"].update(); // update canvas animation tweens
1642
+ TWEEN.update(); // update canvas animation tweens
1729
1643
 
1730
1644
  state.animationFrameRequestId = requestAnimationFrame(animate);
1731
1645
  })();