1
2
3
4
5
6 package d3flamegraph
7
8
9 const JSSource = `
10 (function (global, factory) {
11 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3')) :
12 typeof define === 'function' && define.amd ? define(['exports', 'd3'], factory) :
13 (factory((global.d3 = global.d3 || {}),global.d3));
14 }(this, (function (exports,d3) { 'use strict';
15
16 var d3__default = 'default' in d3 ? d3['default'] : d3;
17
18 var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
19
20
21
22
23
24 function createCommonjsModule(fn, module) {
25 return module = { exports: {} }, fn(module, module.exports), module.exports;
26 }
27
28 var d3Tip = createCommonjsModule(function (module) {
29 // d3.tip
30 // Copyright (c) 2013 Justin Palmer
31 //
32 // Tooltips for d3.js SVG visualizations
33
34 (function (root, factory) {
35 if (typeof undefined === 'function' && undefined.amd) {
36 // AMD. Register as an anonymous module with d3 as a dependency.
37 undefined(['d3'], factory);
38 } else if ('object' === 'object' && module.exports) {
39 // CommonJS
40 var d3$$1 = d3__default;
41 module.exports = factory(d3$$1);
42 } else {
43 // Browser global.
44 root.d3.tip = factory(root.d3);
45 }
46 }(commonjsGlobal, function (d3$$1) {
47
48 // Public - contructs a new tooltip
49 //
50 // Returns a tip
51 return function() {
52 var direction = d3_tip_direction,
53 offset = d3_tip_offset,
54 html = d3_tip_html,
55 node = initNode(),
56 svg = null,
57 point = null,
58 target = null;
59
60 function tip(vis) {
61 svg = getSVGNode(vis);
62 point = svg.createSVGPoint();
63 document.body.appendChild(node);
64 }
65
66 // Public - show the tooltip on the screen
67 //
68 // Returns a tip
69 tip.show = function() {
70 var args = Array.prototype.slice.call(arguments);
71 if(args[args.length - 1] instanceof SVGElement) target = args.pop();
72
73 var content = html.apply(this, args),
74 poffset = offset.apply(this, args),
75 dir = direction.apply(this, args),
76 nodel = getNodeEl(),
77 i = directions.length,
78 coords,
79 scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
80 scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
81
82 nodel.html(content)
83 .style('opacity', 1).style('pointer-events', 'all');
84
85 while(i--) nodel.classed(directions[i], false);
86 coords = direction_callbacks.get(dir).apply(this);
87 nodel.classed(dir, true)
88 .style('top', (coords.top + poffset[0]) + scrollTop + 'px')
89 .style('left', (coords.left + poffset[1]) + scrollLeft + 'px');
90
91 return tip;
92 };
93
94 // Public - hide the tooltip
95 //
96 // Returns a tip
97 tip.hide = function() {
98 var nodel = getNodeEl();
99 nodel.style('opacity', 0).style('pointer-events', 'none');
100 return tip
101 };
102
103 // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
104 //
105 // n - name of the attribute
106 // v - value of the attribute
107 //
108 // Returns tip or attribute value
109 tip.attr = function(n, v) {
110 if (arguments.length < 2 && typeof n === 'string') {
111 return getNodeEl().attr(n)
112 } else {
113 var args = Array.prototype.slice.call(arguments);
114 d3$$1.selection.prototype.attr.apply(getNodeEl(), args);
115 }
116
117 return tip
118 };
119
120 // Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
121 //
122 // n - name of the property
123 // v - value of the property
124 //
125 // Returns tip or style property value
126 tip.style = function(n, v) {
127 if (arguments.length < 2 && typeof n === 'string') {
128 return getNodeEl().style(n)
129 } else {
130 var args = Array.prototype.slice.call(arguments);
131 d3$$1.selection.prototype.style.apply(getNodeEl(), args);
132 }
133
134 return tip
135 };
136
137 // Public: Set or get the direction of the tooltip
138 //
139 // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
140 // sw(southwest), ne(northeast) or se(southeast)
141 //
142 // Returns tip or direction
143 tip.direction = function(v) {
144 if (!arguments.length) return direction
145 direction = v == null ? v : functor(v);
146
147 return tip
148 };
149
150 // Public: Sets or gets the offset of the tip
151 //
152 // v - Array of [x, y] offset
153 //
154 // Returns offset or
155 tip.offset = function(v) {
156 if (!arguments.length) return offset
157 offset = v == null ? v : functor(v);
158
159 return tip
160 };
161
162 // Public: sets or gets the html value of the tooltip
163 //
164 // v - String value of the tip
165 //
166 // Returns html value or tip
167 tip.html = function(v) {
168 if (!arguments.length) return html
169 html = v == null ? v : functor(v);
170
171 return tip
172 };
173
174 // Public: destroys the tooltip and removes it from the DOM
175 //
176 // Returns a tip
177 tip.destroy = function() {
178 if(node) {
179 getNodeEl().remove();
180 node = null;
181 }
182 return tip;
183 };
184
185 function d3_tip_direction() { return 'n' }
186 function d3_tip_offset() { return [0, 0] }
187 function d3_tip_html() { return ' ' }
188
189 var direction_callbacks = d3$$1.map({
190 n: direction_n,
191 s: direction_s,
192 e: direction_e,
193 w: direction_w,
194 nw: direction_nw,
195 ne: direction_ne,
196 sw: direction_sw,
197 se: direction_se
198 }),
199
200 directions = direction_callbacks.keys();
201
202 function direction_n() {
203 var bbox = getScreenBBox();
204 return {
205 top: bbox.n.y - node.offsetHeight,
206 left: bbox.n.x - node.offsetWidth / 2
207 }
208 }
209
210 function direction_s() {
211 var bbox = getScreenBBox();
212 return {
213 top: bbox.s.y,
214 left: bbox.s.x - node.offsetWidth / 2
215 }
216 }
217
218 function direction_e() {
219 var bbox = getScreenBBox();
220 return {
221 top: bbox.e.y - node.offsetHeight / 2,
222 left: bbox.e.x
223 }
224 }
225
226 function direction_w() {
227 var bbox = getScreenBBox();
228 return {
229 top: bbox.w.y - node.offsetHeight / 2,
230 left: bbox.w.x - node.offsetWidth
231 }
232 }
233
234 function direction_nw() {
235 var bbox = getScreenBBox();
236 return {
237 top: bbox.nw.y - node.offsetHeight,
238 left: bbox.nw.x - node.offsetWidth
239 }
240 }
241
242 function direction_ne() {
243 var bbox = getScreenBBox();
244 return {
245 top: bbox.ne.y - node.offsetHeight,
246 left: bbox.ne.x
247 }
248 }
249
250 function direction_sw() {
251 var bbox = getScreenBBox();
252 return {
253 top: bbox.sw.y,
254 left: bbox.sw.x - node.offsetWidth
255 }
256 }
257
258 function direction_se() {
259 var bbox = getScreenBBox();
260 return {
261 top: bbox.se.y,
262 left: bbox.e.x
263 }
264 }
265
266 function initNode() {
267 var node = d3$$1.select(document.createElement('div'));
268 node.style('position', 'absolute').style('top', 0).style('opacity', 0)
269 .style('pointer-events', 'none').style('box-sizing', 'border-box');
270
271 return node.node()
272 }
273
274 function getSVGNode(el) {
275 el = el.node();
276 if(el.tagName.toLowerCase() === 'svg')
277 return el
278
279 return el.ownerSVGElement
280 }
281
282 function getNodeEl() {
283 if(node === null) {
284 node = initNode();
285 // re-add node to DOM
286 document.body.appendChild(node);
287 }
288 return d3$$1.select(node);
289 }
290
291 // Private - gets the screen coordinates of a shape
292 //
293 // Given a shape on the screen, will return an SVGPoint for the directions
294 // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
295 // sw(southwest).
296 //
297 // +-+-+
298 // | |
299 // + +
300 // | |
301 // +-+-+
302 //
303 // Returns an Object {n, s, e, w, nw, sw, ne, se}
304 function getScreenBBox() {
305 var targetel = target || d3$$1.event.target;
306
307 while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) {
308 targetel = targetel.parentNode;
309 }
310
311 var bbox = {},
312 matrix = targetel.getScreenCTM(),
313 tbbox = targetel.getBBox(),
314 width = tbbox.width,
315 height = tbbox.height,
316 x = tbbox.x,
317 y = tbbox.y;
318
319 point.x = x;
320 point.y = y;
321 bbox.nw = point.matrixTransform(matrix);
322 point.x += width;
323 bbox.ne = point.matrixTransform(matrix);
324 point.y += height;
325 bbox.se = point.matrixTransform(matrix);
326 point.x -= width;
327 bbox.sw = point.matrixTransform(matrix);
328 point.y -= height / 2;
329 bbox.w = point.matrixTransform(matrix);
330 point.x += width;
331 bbox.e = point.matrixTransform(matrix);
332 point.x -= width / 2;
333 point.y -= height / 2;
334 bbox.n = point.matrixTransform(matrix);
335 point.y += height;
336 bbox.s = point.matrixTransform(matrix);
337
338 return bbox
339 }
340
341 // Private - replace D3JS 3.X d3.functor() function
342 function functor(v) {
343 return typeof v === "function" ? v : function() {
344 return v
345 }
346 }
347
348 return tip
349 };
350
351 }));
352 });
353
354 var flamegraph = function () {
355 var w = 960; // graph width
356 var h = null; // graph height
357 var c = 18; // cell height
358 var selection = null; // selection
359 var tooltip = true; // enable tooltip
360 var title = ''; // graph title
361 var transitionDuration = 750;
362 var transitionEase = d3.easeCubic; // tooltip offset
363 var sort = false;
364 var inverted = false; // invert the graph direction
365 var clickHandler = null;
366 var minFrameSize = 0;
367 var details = null;
368
369 var tip = d3Tip()
370 .direction('s')
371 .offset([8, 0])
372 .attr('class', 'd3-flame-graph-tip')
373 .html(function (d) { return label(d) });
374
375 var svg;
376
377 function name (d) {
378 return d.data.n || d.data.name
379 }
380
381 function libtype (d) {
382 return d.data.l || d.data.libtype
383 }
384
385 function children (d) {
386 return d.c || d.children
387 }
388
389 function value (d) {
390 return d.v || d.value
391 }
392
393 var label = function (d) {
394 return name(d) + ' (' + d3.format('.3f')(100 * (d.x1 - d.x0), 3) + '%, ' + value(d) + ' samples)'
395 };
396
397 function setDetails (t) {
398 if (details) { details.innerHTML = t; }
399 }
400
401 var colorMapper = function (d) {
402 return d.highlight ? '#E600E6' : colorHash(name(d), libtype(d))
403 };
404
405 function generateHash (name) {
406 // Return a vector (0.0->1.0) that is a hash of the input string.
407 // The hash is computed to favor early characters over later ones, so
408 // that strings with similar starts have similar vectors. Only the first
409 // 6 characters are considered.
410 const MAX_CHAR = 6;
411
412 var hash = 0;
413 var maxHash = 0;
414 var weight = 1;
415 var mod = 10;
416
417 if (name) {
418 for (var i = 0; i < name.length; i++) {
419 if (i > MAX_CHAR) { break }
420 hash += weight * (name.charCodeAt(i) % mod);
421 maxHash += weight * (mod - 1);
422 weight *= 0.70;
423 }
424 if (maxHash > 0) { hash = hash / maxHash; }
425 }
426 return hash
427 }
428
429 function colorHash (name, libtype) {
430 // Return a color for the given name and library type. The library type
431 // selects the hue, and the name is hashed to a color in that hue.
432
433 var r;
434 var g;
435 var b;
436
437 // Select hue. Order is important.
438 var hue;
439 if (typeof libtype === 'undefined' || libtype === '') {
440 // default when libtype is not in use
441 hue = 'warm';
442 } else {
443 hue = 'red';
444 if (name.match(/::/)) {
445 hue = 'yellow';
446 }
447 if (libtype === 'kernel') {
448 hue = 'orange';
449 } else if (libtype === 'jit') {
450 hue = 'green';
451 } else if (libtype === 'inlined') {
452 hue = 'aqua';
453 }
454 }
455
456 // calculate hash
457 var vector = 0;
458 if (name) {
459 var nameArr = name.split('` + "`" + `');
460 if (nameArr.length > 1) {
461 name = nameArr[nameArr.length - 1]; // drop module name if present
462 }
463 name = name.split('(')[0]; // drop extra info
464 vector = generateHash(name);
465 }
466
467 // calculate color
468 if (hue === 'red') {
469 r = 200 + Math.round(55 * vector);
470 g = 50 + Math.round(80 * vector);
471 b = g;
472 } else if (hue === 'orange') {
473 r = 190 + Math.round(65 * vector);
474 g = 90 + Math.round(65 * vector);
475 b = 0;
476 } else if (hue === 'yellow') {
477 r = 175 + Math.round(55 * vector);
478 g = r;
479 b = 50 + Math.round(20 * vector);
480 } else if (hue === 'green') {
481 r = 50 + Math.round(60 * vector);
482 g = 200 + Math.round(55 * vector);
483 b = r;
484 } else if (hue === 'aqua') {
485 r = 50 + Math.round(60 * vector);
486 g = 165 + Math.round(55 * vector);
487 b = g;
488 } else {
489 // original warm palette
490 r = 200 + Math.round(55 * vector);
491 g = 0 + Math.round(230 * (1 - vector));
492 b = 0 + Math.round(55 * (1 - vector));
493 }
494
495 return 'rgb(' + r + ',' + g + ',' + b + ')'
496 }
497
498 function hide (d) {
499 d.data.hide = true;
500 if (children(d)) {
501 children(d).forEach(hide);
502 }
503 }
504
505 function show (d) {
506 d.data.fade = false;
507 d.data.hide = false;
508 if (children(d)) {
509 children(d).forEach(show);
510 }
511 }
512
513 function getSiblings (d) {
514 var siblings = [];
515 if (d.parent) {
516 var me = d.parent.children.indexOf(d);
517 siblings = d.parent.children.slice(0);
518 siblings.splice(me, 1);
519 }
520 return siblings
521 }
522
523 function hideSiblings (d) {
524 var siblings = getSiblings(d);
525 siblings.forEach(function (s) {
526 hide(s);
527 });
528 if (d.parent) {
529 hideSiblings(d.parent);
530 }
531 }
532
533 function fadeAncestors (d) {
534 if (d.parent) {
535 d.parent.data.fade = true;
536 fadeAncestors(d.parent);
537 }
538 }
539
540 // function getRoot (d) {
541 // if (d.parent) {
542 // return getRoot(d.parent)
543 // }
544 // return d
545 // }
546
547 function zoom (d) {
548 tip.hide(d);
549 hideSiblings(d);
550 show(d);
551 fadeAncestors(d);
552 update();
553 if (typeof clickHandler === 'function') {
554 clickHandler(d);
555 }
556 }
557
558 function searchTree (d, term) {
559 var re = new RegExp(term);
560 var searchResults = [];
561
562 function searchInner (d) {
563 var label = name(d);
564
565 if (children(d)) {
566 children(d).forEach(function (child) {
567 searchInner(child);
568 });
569 }
570
571 if (label.match(re)) {
572 d.highlight = true;
573 searchResults.push(d);
574 } else {
575 d.highlight = false;
576 }
577 }
578
579 searchInner(d);
580 return searchResults
581 }
582
583 function clear (d) {
584 d.highlight = false;
585 if (children(d)) {
586 children(d).forEach(function (child) {
587 clear(child);
588 });
589 }
590 }
591
592 function doSort (a, b) {
593 if (typeof sort === 'function') {
594 return sort(a, b)
595 } else if (sort) {
596 return d3.ascending(name(a), name(b))
597 }
598 }
599
600 var p = d3.partition();
601
602 function filterNodes (root) {
603 var nodeList = root.descendants();
604 if (minFrameSize > 0) {
605 var kx = w / (root.x1 - root.x0);
606 nodeList = nodeList.filter(function (el) {
607 return ((el.x1 - el.x0) * kx) > minFrameSize
608 });
609 }
610 return nodeList
611 }
612
613 function update () {
614 selection.each(function (root) {
615 var x = d3.scaleLinear().range([0, w]);
616 var y = d3.scaleLinear().range([0, c]);
617
618 if (sort) root.sort(doSort);
619 root.sum(function (d) {
620 if (d.fade || d.hide) {
621 return 0
622 }
623 // The node's self value is its total value minus all children.
624 var v = value(d);
625 if (children(d)) {
626 var c = children(d);
627 for (var i = 0; i < c.length; i++) {
628 v -= value(c[i]);
629 }
630 }
631 return v
632 });
633 p(root);
634
635 var kx = w / (root.x1 - root.x0);
636 function width (d) { return (d.x1 - d.x0) * kx }
637
638 var descendants = filterNodes(root);
639 var g = d3.select(this).select('svg').selectAll('g').data(descendants, function (d) { return d.id });
640
641 g.transition()
642 .duration(transitionDuration)
643 .ease(transitionEase)
644 .attr('transform', function (d) { return 'translate(' + x(d.x0) + ',' + (inverted ? y(d.depth) : (h - y(d.depth) - c)) + ')' });
645
646 g.select('rect')
647 .attr('width', width);
648
649 var node = g.enter()
650 .append('svg:g')
651 .attr('transform', function (d) { return 'translate(' + x(d.x0) + ',' + (inverted ? y(d.depth) : (h - y(d.depth) - c)) + ')' });
652
653 node.append('svg:rect')
654 .transition()
655 .delay(transitionDuration / 2)
656 .attr('width', width);
657
658 if (!tooltip) { node.append('svg:title'); }
659
660 node.append('foreignObject')
661 .append('xhtml:div');
662
663 // Now we have to re-select to see the new elements (why?).
664 g = d3.select(this).select('svg').selectAll('g').data(descendants, function (d) { return d.id });
665
666 g.attr('width', width)
667 .attr('height', function (d) { return c })
668 .attr('name', function (d) { return name(d) })
669 .attr('class', function (d) { return d.data.fade ? 'frame fade' : 'frame' });
670
671 g.select('rect')
672 .attr('height', function (d) { return c })
673 .attr('fill', function (d) { return colorMapper(d) });
674
675 if (!tooltip) {
676 g.select('title')
677 .text(label);
678 }
679
680 g.select('foreignObject')
681 .attr('width', width)
682 .attr('height', function (d) { return c })
683 .select('div')
684 .attr('class', 'd3-flame-graph-label')
685 .style('display', function (d) { return (width(d) < 35) ? 'none' : 'block' })
686 .transition()
687 .delay(transitionDuration)
688 .text(name);
689
690 g.on('click', zoom);
691
692 g.exit()
693 .remove();
694
695 g.on('mouseover', function (d) {
696 if (tooltip) tip.show(d, this);
697 setDetails(label(d));
698 }).on('mouseout', function (d) {
699 if (tooltip) tip.hide(d);
700 setDetails('');
701 });
702 });
703 }
704
705 function merge (data, samples) {
706 samples.forEach(function (sample) {
707 var node = data.find(function (element) {
708 return (element.name === sample.name)
709 });
710
711 if (node) {
712 if (node.original) {
713 node.original += sample.value;
714 } else {
715 node.value += sample.value;
716 }
717 if (sample.children) {
718 if (!node.children) {
719 node.children = [];
720 }
721 merge(node.children, sample.children);
722 }
723 } else {
724 data.push(sample);
725 }
726 });
727 }
728
729 function s4 () {
730 return Math.floor((1 + Math.random()) * 0x10000)
731 .toString(16)
732 .substring(1)
733 }
734
735 function injectIds (node) {
736 node.id = s4() + '-' + s4() + '-' + '-' + s4() + '-' + s4();
737 var children = node.c || node.children || [];
738 for (var i = 0; i < children.length; i++) {
739 injectIds(children[i]);
740 }
741 }
742
743 function chart (s) {
744 var root = d3.hierarchy(
745 s.datum(), function (d) { return children(d) }
746 );
747 injectIds(root);
748 selection = s.datum(root);
749
750 if (!arguments.length) return chart
751
752 if (!h) {
753 h = (root.height + 2) * c;
754 }
755
756 selection.each(function (data) {
757 if (!svg) {
758 svg = d3.select(this)
759 .append('svg:svg')
760 .attr('width', w)
761 .attr('height', h)
762 .attr('class', 'partition d3-flame-graph')
763 .call(tip);
764
765 svg.append('svg:text')
766 .attr('class', 'title')
767 .attr('text-anchor', 'middle')
768 .attr('y', '25')
769 .attr('x', w / 2)
770 .attr('fill', '#808080')
771 .text(title);
772 }
773 });
774
775 // first draw
776 update();
777 }
778
779 chart.height = function (_) {
780 if (!arguments.length) { return h }
781 h = _;
782 return chart
783 };
784
785 chart.width = function (_) {
786 if (!arguments.length) { return w }
787 w = _;
788 return chart
789 };
790
791 chart.cellHeight = function (_) {
792 if (!arguments.length) { return c }
793 c = _;
794 return chart
795 };
796
797 chart.tooltip = function (_) {
798 if (!arguments.length) { return tooltip }
799 if (typeof _ === 'function') {
800 tip = _;
801 }
802 tooltip = !!_;
803 return chart
804 };
805
806 chart.title = function (_) {
807 if (!arguments.length) { return title }
808 title = _;
809 return chart
810 };
811
812 chart.transitionDuration = function (_) {
813 if (!arguments.length) { return transitionDuration }
814 transitionDuration = _;
815 return chart
816 };
817
818 chart.transitionEase = function (_) {
819 if (!arguments.length) { return transitionEase }
820 transitionEase = _;
821 return chart
822 };
823
824 chart.sort = function (_) {
825 if (!arguments.length) { return sort }
826 sort = _;
827 return chart
828 };
829
830 chart.inverted = function (_) {
831 if (!arguments.length) { return inverted }
832 inverted = _;
833 return chart
834 };
835
836 chart.label = function (_) {
837 if (!arguments.length) { return label }
838 label = _;
839 return chart
840 };
841
842 chart.search = function (term) {
843 var searchResults = [];
844 selection.each(function (data) {
845 searchResults = searchTree(data, term);
846 update();
847 });
848 return searchResults
849 };
850
851 chart.clear = function () {
852 selection.each(function (data) {
853 clear(data);
854 update();
855 });
856 };
857
858 chart.zoomTo = function (d) {
859 zoom(d);
860 };
861
862 chart.resetZoom = function () {
863 selection.each(function (data) {
864 zoom(data); // zoom to root
865 });
866 };
867
868 chart.onClick = function (_) {
869 if (!arguments.length) {
870 return clickHandler
871 }
872 clickHandler = _;
873 return chart
874 };
875
876 chart.merge = function (samples) {
877 var newRoot; // Need to re-create hierarchy after data changes.
878 selection.each(function (root) {
879 merge([root.data], [samples]);
880 newRoot = d3.hierarchy(root.data, function (d) { return children(d) });
881 injectIds(newRoot);
882 });
883 selection = selection.datum(newRoot);
884 update();
885 };
886
887 chart.color = function (_) {
888 if (!arguments.length) { return colorMapper }
889 colorMapper = _;
890 return chart
891 };
892
893 chart.minFrameSize = function (_) {
894 if (!arguments.length) { return minFrameSize }
895 minFrameSize = _;
896 return chart
897 };
898
899 chart.details = function (_) {
900 if (!arguments.length) { return details }
901 details = _;
902 return chart
903 };
904
905 return chart
906 };
907
908 exports.flamegraph = flamegraph;
909
910 Object.defineProperty(exports, '__esModule', { value: true });
911
912 })));
913 `
914
915
916 const CSSSource = `
917 .d3-flame-graph rect {
918 stroke: #EEEEEE;
919 fill-opacity: .8;
920 }
921
922 .d3-flame-graph rect:hover {
923 stroke: #474747;
924 stroke-width: 0.5;
925 cursor: pointer;
926 }
927
928 .d3-flame-graph-label {
929 pointer-events: none;
930 white-space: nowrap;
931 text-overflow: ellipsis;
932 overflow: hidden;
933 font-size: 12px;
934 font-family: Verdana;
935 margin-left: 4px;
936 margin-right: 4px;
937 line-height: 1.5;
938 padding: 0 0 0;
939 font-weight: 400;
940 color: black;
941 text-align: left;
942 }
943
944 .d3-flame-graph .fade {
945 opacity: 0.6 !important;
946 }
947
948 .d3-flame-graph .title {
949 font-size: 20px;
950 font-family: Verdana;
951 }
952
953 .d3-flame-graph-tip {
954 line-height: 1;
955 font-family: Verdana;
956 font-size: 12px;
957 padding: 12px;
958 background: rgba(0, 0, 0, 0.8);
959 color: #fff;
960 border-radius: 2px;
961 pointer-events: none;
962 }
963
964 /* Creates a small triangle extender for the tooltip */
965 .d3-flame-graph-tip:after {
966 box-sizing: border-box;
967 display: inline;
968 font-size: 10px;
969 width: 100%;
970 line-height: 1;
971 color: rgba(0, 0, 0, 0.8);
972 position: absolute;
973 pointer-events: none;
974 }
975
976 /* Northward tooltips */
977 .d3-flame-graph-tip.n:after {
978 content: "\25BC";
979 margin: -1px 0 0 0;
980 top: 100%;
981 left: 0;
982 text-align: center;
983 }
984
985 /* Eastward tooltips */
986 .d3-flame-graph-tip.e:after {
987 content: "\25C0";
988 margin: -4px 0 0 0;
989 top: 50%;
990 left: -8px;
991 }
992
993 /* Southward tooltips */
994 .d3-flame-graph-tip.s:after {
995 content: "\25B2";
996 margin: 0 0 1px 0;
997 top: -8px;
998 left: 0;
999 text-align: center;
1000 }
1001
1002 /* Westward tooltips */
1003 .d3-flame-graph-tip.w:after {
1004 content: "\25B6";
1005 margin: -4px 0 0 -1px;
1006 top: 50%;
1007 left: 100%;
1008 }
1009 `
1010
View as plain text