@parca/profile 0.16.198 → 0.16.199

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/Callgraph/index.d.ts +0 -1
  3. package/dist/GraphTooltip/ExpandOnHoverValue.d.ts +0 -1
  4. package/dist/GraphTooltip/index.d.ts +0 -1
  5. package/dist/GraphTooltipArrow/ExpandOnHoverValue.d.ts +6 -0
  6. package/dist/GraphTooltipArrow/ExpandOnHoverValue.js +4 -0
  7. package/dist/GraphTooltipArrow/index.d.ts +43 -0
  8. package/dist/GraphTooltipArrow/index.js +244 -0
  9. package/dist/MatchersInput/SuggestionItem.d.ts +0 -1
  10. package/dist/MatchersInput/SuggestionsList.d.ts +0 -1
  11. package/dist/MatchersInput/index.d.ts +0 -1
  12. package/dist/MetricsCircle/index.d.ts +0 -1
  13. package/dist/MetricsGraph/MetricsTooltip/index.d.ts +0 -1
  14. package/dist/MetricsGraph/index.d.ts +0 -1
  15. package/dist/MetricsSeries/index.d.ts +0 -1
  16. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts +0 -1
  17. package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +0 -1
  18. package/dist/ProfileExplorer/index.d.ts +0 -1
  19. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts +0 -1
  20. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.d.ts +10 -0
  21. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.js +64 -0
  22. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.d.ts +48 -0
  23. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.js +150 -0
  24. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +23 -0
  25. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +110 -0
  26. package/dist/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.d.ts +14 -0
  27. package/dist/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.js +26 -0
  28. package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.d.ts +4 -0
  29. package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.js +42 -0
  30. package/dist/ProfileIcicleGraph/index.d.ts +4 -3
  31. package/dist/ProfileIcicleGraph/index.js +7 -5
  32. package/dist/ProfileMetricsGraph/index.d.ts +0 -1
  33. package/dist/ProfileSelector/CompareButton.d.ts +0 -1
  34. package/dist/ProfileSelector/index.d.ts +0 -1
  35. package/dist/ProfileSource.d.ts +0 -1
  36. package/dist/ProfileTypeSelector/index.d.ts +0 -1
  37. package/dist/ProfileView/FilterByFunctionButton.d.ts +0 -1
  38. package/dist/ProfileView/ViewSelector.d.ts +0 -1
  39. package/dist/ProfileView/index.d.ts +2 -1
  40. package/dist/ProfileView/index.js +2 -2
  41. package/dist/ProfileViewWithData.d.ts +0 -1
  42. package/dist/ProfileViewWithData.js +15 -6
  43. package/dist/components/DiffLegend.d.ts +0 -1
  44. package/dist/components/ProfileShareButton/ResultBox.d.ts +0 -1
  45. package/dist/components/ProfileShareButton/index.d.ts +0 -1
  46. package/dist/styles.css +1 -1
  47. package/package.json +6 -5
  48. package/src/GraphTooltipArrow/ExpandOnHoverValue.tsx +30 -0
  49. package/src/GraphTooltipArrow/index.tsx +564 -0
  50. package/src/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.tsx +109 -0
  51. package/src/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.tsx +327 -0
  52. package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +212 -0
  53. package/src/ProfileIcicleGraph/IcicleGraphArrow/useNodeColor.ts +52 -0
  54. package/src/ProfileIcicleGraph/IcicleGraphArrow/utils.ts +51 -0
  55. package/src/ProfileIcicleGraph/index.tsx +34 -14
  56. package/src/ProfileView/index.tsx +4 -1
  57. package/src/ProfileViewWithData.tsx +20 -6
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.relative{position:relative}.-inset-2{bottom:-.5rem;left:-.5rem;right:-.5rem;top:-.5rem}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.z-50{z-index:50}.z-10{z-index:10}.m-auto{margin:auto}.m-0{margin:0}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.mt-1{margin-top:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mb-2{margin-bottom:.5rem}.mr-6{margin-right:1.5rem}.mr-3{margin-right:.75rem}.mr-1{margin-right:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-fit{height:-moz-fit-content;height:fit-content}.h-10{height:2.5rem}.h-1{height:.25rem}.h-\[80vh\]{height:80vh}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.min-h-52{min-height:13rem}.w-full{width:100%}.w-auto{width:auto}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-40{width:10rem}.w-1\/2{width:50%}.w-8{width:2rem}.w-4{width:1rem}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.max-w-\[500px\]{max-width:500px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.\!items-center{align-items:center!important}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-1{gap:.25rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-scroll{overflow:scroll}.text-ellipsis{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.stroke-white{stroke:#fff}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pr-0{padding-right:0}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pl-2{padding-left:.5rem}.pb-2{padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-semibold{font-weight:600}.font-bold{font-weight:700}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-90{opacity:.9}.opacity-50{opacity:.5}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\]{--tw-shadow:0 0 10px 2px rgba(0,0,0,.3);--tw-shadow-colored:0 0 10px 2px var(--tw-shadow-color)}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-indigo-800:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(55 48 163/var(--tw-ring-opacity))}.group:hover .group-hover\:flex{display:flex}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:stroke-gray-700{stroke:#374151}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:1024px){.lg\:w-1\/2{width:50%}}
1
+ /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.relative{position:relative}.-inset-2{top:-.5rem;right:-.5rem;bottom:-.5rem;left:-.5rem}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.z-50{z-index:50}.z-10{z-index:10}.m-auto{margin:auto}.m-0{margin:0}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-20{margin-top:5rem;margin-bottom:5rem}.my-6{margin-top:1.5rem;margin-bottom:1.5rem}.mt-1{margin-top:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mb-2{margin-bottom:.5rem}.mr-6{margin-right:1.5rem}.mr-3{margin-right:.75rem}.mr-1{margin-right:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-fit{height:-moz-fit-content;height:fit-content}.h-10{height:2.5rem}.h-1{height:.25rem}.h-\[80vh\]{height:80vh}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.min-h-52{min-height:13rem}.w-full{width:100%}.w-auto{width:auto}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-40{width:10rem}.w-1\/2{width:50%}.w-8{width:2rem}.w-4{width:1rem}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.max-w-\[500px\]{max-width:500px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.\!items-center{align-items:center!important}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-1{gap:.25rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-scroll{overflow:scroll}.text-ellipsis{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-l{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.border{border-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.fill-transparent{fill:#0000}.fill-current{fill:currentColor}.stroke-white{stroke:#fff}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-20{padding-top:5rem;padding-bottom:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pr-0{padding-right:0}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pl-2{padding-left:.5rem}.pb-2{padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-semibold{font-weight:600}.font-bold{font-weight:700}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-90{opacity:.9}.opacity-50{opacity:.5}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\]{--tw-shadow:0 0 10px 2px #0000004d;--tw-shadow-colored:0 0 10px 2px var(--tw-shadow-color)}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.outline-none{outline:2px solid #0000;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-indigo-800:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(55 48 163/var(--tw-ring-opacity))}.group:hover .group-hover\:flex{display:flex}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:stroke-gray-700{stroke:#374151}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:1024px){.lg\:w-1\/2{width:50%}}
package/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.198",
3
+ "version": "0.16.199",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@parca/client": "^0.16.76",
7
- "@parca/components": "^0.16.158",
7
+ "@parca/components": "^0.16.159",
8
8
  "@parca/dynamicsize": "^0.16.54",
9
9
  "@parca/hooks": "^0.0.11",
10
10
  "@parca/parser": "^0.16.55",
11
- "@parca/store": "^0.16.85",
12
- "@parca/utilities": "^0.0.15",
11
+ "@parca/store": "^0.16.86",
12
+ "@parca/utilities": "^0.0.16",
13
13
  "@tanstack/react-query": "^4.0.5",
14
14
  "@types/react-beautiful-dnd": "^13.1.3",
15
+ "apache-arrow": "^12.0.0",
15
16
  "d3": "7.8.5",
16
17
  "d3-scale": "^4.0.2",
17
18
  "d3-selection": "3.0.0",
@@ -46,5 +47,5 @@
46
47
  "access": "public",
47
48
  "registry": "https://registry.npmjs.org/"
48
49
  },
49
- "gitHead": "6fb652a4800d7a5263b4af5a0eec2b9bc0f86658"
50
+ "gitHead": "f6a5f9e44f81f6722e3aed6629e4a47491562ea6"
50
51
  }
@@ -0,0 +1,30 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ interface Props {
15
+ value: string | number | undefined;
16
+ displayValue?: string | number | undefined;
17
+ }
18
+
19
+ export const ExpandOnHover = ({value, displayValue}: Props): JSX.Element => {
20
+ return (
21
+ <div className="group relative w-full">
22
+ <div className="w-full overflow-hidden text-ellipsis whitespace-nowrap">
23
+ {displayValue ?? value}
24
+ </div>
25
+ <div className="absolute -inset-2 hidden h-fit max-w-[500px] whitespace-normal break-all rounded bg-gray-50 p-2 shadow-[0_0_10px_2px_rgba(0,0,0,0.3)] group-hover:flex dark:bg-gray-900">
26
+ {value}
27
+ </div>
28
+ </div>
29
+ );
30
+ };
@@ -0,0 +1,564 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import React, {useEffect, useMemo, useState} from 'react';
15
+
16
+ import {Table} from 'apache-arrow';
17
+ import {pointer} from 'd3-selection';
18
+ import {CopyToClipboard} from 'react-copy-to-clipboard';
19
+ import {usePopper} from 'react-popper';
20
+
21
+ import {
22
+ CallgraphNode,
23
+ CallgraphNodeMeta,
24
+ FlamegraphNode,
25
+ FlamegraphNodeMeta,
26
+ FlamegraphRootNode,
27
+ } from '@parca/client';
28
+ import {
29
+ Location,
30
+ Mapping,
31
+ Function as ParcaFunction,
32
+ } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
33
+ import {useKeyDown} from '@parca/components';
34
+ import {selectHoveringRow, useAppSelector} from '@parca/store';
35
+ import {divide, getLastItem, valueFormatter} from '@parca/utilities';
36
+
37
+ import {hexifyAddress, truncateString, truncateStringReverse} from '../';
38
+ import {
39
+ FIELD_CUMULATIVE,
40
+ FIELD_DIFF,
41
+ FIELD_FUNCTION_FILE_NAME,
42
+ FIELD_FUNCTION_NAME,
43
+ FIELD_LOCATION_ADDRESS,
44
+ FIELD_MAPPING_BUILD_ID,
45
+ FIELD_MAPPING_FILE,
46
+ } from '../ProfileIcicleGraph/IcicleGraphArrow';
47
+ import {ExpandOnHover} from './ExpandOnHoverValue';
48
+
49
+ const NoData = (): React.JSX.Element => {
50
+ return <span className="rounded bg-gray-200 px-2 dark:bg-gray-800">Not available</span>;
51
+ };
52
+
53
+ interface ExtendedCallgraphNodeMeta extends CallgraphNodeMeta {
54
+ lineIndex: number;
55
+ locationIndex: number;
56
+ }
57
+
58
+ interface HoveringNode extends FlamegraphRootNode, FlamegraphNode, CallgraphNode {
59
+ diff: bigint;
60
+ meta?: FlamegraphNodeMeta | ExtendedCallgraphNodeMeta;
61
+ }
62
+
63
+ interface GraphTooltipProps {
64
+ table: Table<any>;
65
+ x?: number;
66
+ y?: number;
67
+ unit: string;
68
+ total: bigint;
69
+ totalUnfiltered: bigint;
70
+ hoveringNode?: HoveringNode;
71
+ contextElement: Element | null;
72
+ isFixed?: boolean;
73
+ virtualContextElement?: boolean;
74
+ strings?: string[];
75
+ mappings?: Mapping[];
76
+ locations?: Location[];
77
+ functions?: ParcaFunction[];
78
+ type?: string;
79
+ }
80
+
81
+ const virtualElement = {
82
+ getBoundingClientRect: () =>
83
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
84
+ ({
85
+ width: 0,
86
+ height: 0,
87
+ top: 0,
88
+ left: 0,
89
+ right: 0,
90
+ bottom: 0,
91
+ } as DOMRect),
92
+ };
93
+
94
+ function generateGetBoundingClientRect(contextElement: Element, x = 0, y = 0): () => DOMRect {
95
+ const domRect = contextElement.getBoundingClientRect();
96
+ return () =>
97
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
98
+ ({
99
+ width: 0,
100
+ height: 0,
101
+ top: domRect.y + y,
102
+ left: domRect.x + x,
103
+ right: domRect.x + x,
104
+ bottom: domRect.y + y,
105
+ } as DOMRect);
106
+ }
107
+
108
+ const TooltipMetaInfo = ({
109
+ hoveringNode,
110
+ onCopy,
111
+ strings,
112
+ mappings,
113
+ locations,
114
+ functions,
115
+ type = 'flamegraph',
116
+ }: {
117
+ hoveringNode: HoveringNode;
118
+ onCopy: () => void;
119
+ strings?: string[];
120
+ mappings?: Mapping[];
121
+ locations?: Location[];
122
+ functions?: ParcaFunction[];
123
+ type?: string;
124
+ }): React.JSX.Element => {
125
+ // populate meta from the flamegraph metadata tables
126
+ if (
127
+ type === 'flamegraph' &&
128
+ locations !== undefined &&
129
+ hoveringNode.meta?.locationIndex !== undefined &&
130
+ hoveringNode.meta.locationIndex !== 0
131
+ ) {
132
+ const location = locations[hoveringNode.meta.locationIndex - 1];
133
+ hoveringNode.meta.location = location;
134
+
135
+ if (location !== undefined) {
136
+ if (
137
+ mappings !== undefined &&
138
+ location.mappingIndex !== undefined &&
139
+ location.mappingIndex !== 0
140
+ ) {
141
+ const mapping = mappings[location.mappingIndex - 1];
142
+ if (strings !== undefined && mapping !== undefined) {
143
+ mapping.file =
144
+ mapping?.fileStringIndex !== undefined ? strings[mapping.fileStringIndex] : '';
145
+ mapping.buildId =
146
+ mapping?.buildIdStringIndex !== undefined ? strings[mapping.buildIdStringIndex] : '';
147
+ }
148
+ hoveringNode.meta.mapping = mapping;
149
+ }
150
+
151
+ if (
152
+ functions !== undefined &&
153
+ location.lines !== undefined &&
154
+ hoveringNode.meta.lineIndex !== undefined &&
155
+ hoveringNode.meta.lineIndex < location.lines.length
156
+ ) {
157
+ const func = functions[location.lines[hoveringNode.meta.lineIndex].functionIndex - 1];
158
+ if (strings !== undefined) {
159
+ func.name = strings[func.nameStringIndex];
160
+ func.systemName = strings[func.systemNameStringIndex];
161
+ func.filename = strings[func.filenameStringIndex];
162
+ }
163
+ hoveringNode.meta.function = func;
164
+ }
165
+ }
166
+ }
167
+
168
+ const getTextForFile = (hoveringNode: HoveringNode): string => {
169
+ if (hoveringNode.meta?.function == null) return '<unknown>';
170
+
171
+ return `${hoveringNode.meta.function.filename} ${
172
+ hoveringNode.meta.line?.line !== undefined && hoveringNode.meta.line?.line !== 0n
173
+ ? ` +${hoveringNode.meta.line.line.toString()}`
174
+ : `${
175
+ hoveringNode.meta.function?.startLine !== undefined &&
176
+ hoveringNode.meta.function?.startLine !== 0n
177
+ ? ` +${hoveringNode.meta.function.startLine}`
178
+ : ''
179
+ }`
180
+ }`;
181
+ };
182
+ const file = getTextForFile(hoveringNode);
183
+
184
+ return (
185
+ <>
186
+ <tr>
187
+ <td className="w-1/4">File</td>
188
+ <td className="w-3/4 break-all">
189
+ {hoveringNode.meta?.function?.filename == null ||
190
+ hoveringNode.meta?.function.filename === '' ? (
191
+ <NoData />
192
+ ) : (
193
+ <CopyToClipboard onCopy={onCopy} text={file}>
194
+ <button className="cursor-pointer whitespace-nowrap text-left">
195
+ <ExpandOnHover value={file} displayValue={truncateStringReverse(file, 40)} />
196
+ </button>
197
+ </CopyToClipboard>
198
+ )}
199
+ </td>
200
+ </tr>
201
+
202
+ <tr>
203
+ <td className="w-1/4">Address</td>
204
+ <td className="w-3/4 break-all">
205
+ {hoveringNode.meta?.location?.address == null ||
206
+ hoveringNode.meta?.location.address === 0n ? (
207
+ <NoData />
208
+ ) : (
209
+ <CopyToClipboard
210
+ onCopy={onCopy}
211
+ text={hexifyAddress(hoveringNode.meta.location.address)}
212
+ >
213
+ <button className="cursor-pointer">
214
+ {hexifyAddress(hoveringNode.meta.location.address)}
215
+ </button>
216
+ </CopyToClipboard>
217
+ )}
218
+ </td>
219
+ </tr>
220
+ <tr>
221
+ <td className="w-1/4">Binary</td>
222
+ <td className="w-3/4 break-all">
223
+ {hoveringNode.meta?.mapping == null || hoveringNode.meta.mapping.file === '' ? (
224
+ <NoData />
225
+ ) : (
226
+ <CopyToClipboard onCopy={onCopy} text={hoveringNode.meta.mapping.file}>
227
+ <button className="cursor-pointer">
228
+ {getLastItem(hoveringNode.meta.mapping.file)}
229
+ </button>
230
+ </CopyToClipboard>
231
+ )}
232
+ </td>
233
+ </tr>
234
+
235
+ <tr>
236
+ <td className="w-1/4">Build Id</td>
237
+ <td className="w-3/4 break-all">
238
+ {hoveringNode.meta?.mapping == null || hoveringNode.meta?.mapping.buildId === '' ? (
239
+ <NoData />
240
+ ) : (
241
+ <CopyToClipboard onCopy={onCopy} text={hoveringNode.meta.mapping.buildId}>
242
+ <button className="cursor-pointer">
243
+ {truncateString(getLastItem(hoveringNode.meta.mapping.buildId) as string, 28)}
244
+ </button>
245
+ </CopyToClipboard>
246
+ )}
247
+ </td>
248
+ </tr>
249
+ </>
250
+ );
251
+ };
252
+
253
+ let timeoutHandle: ReturnType<typeof setTimeout> | null = null;
254
+
255
+ export const GraphTooltipContent = ({
256
+ hoveringNode,
257
+ unit,
258
+ total,
259
+ totalUnfiltered,
260
+ isFixed,
261
+ strings,
262
+ mappings,
263
+ locations,
264
+ functions,
265
+ type = 'flamegraph',
266
+ }: {
267
+ hoveringNode: HoveringNode;
268
+ unit: string;
269
+ total: bigint;
270
+ totalUnfiltered: bigint;
271
+ isFixed: boolean;
272
+ strings?: string[];
273
+ mappings?: Mapping[];
274
+ locations?: Location[];
275
+ functions?: ParcaFunction[];
276
+ type?: string;
277
+ }): React.JSX.Element => {
278
+ const [isCopied, setIsCopied] = useState<boolean>(false);
279
+
280
+ const onCopy = (): void => {
281
+ setIsCopied(true);
282
+
283
+ if (timeoutHandle !== null) {
284
+ clearTimeout(timeoutHandle);
285
+ }
286
+ timeoutHandle = setTimeout(() => setIsCopied(false), 3000);
287
+ };
288
+
289
+ const hoveringNodeCumulative = hoveringNode.cumulative;
290
+ const diff = hoveringNode.diff;
291
+ const prevValue = hoveringNodeCumulative - diff;
292
+ const diffRatio = diff !== 0n ? divide(diff, prevValue) : 0;
293
+ const diffSign = diff > 0 ? '+' : '';
294
+ const diffValueText = diffSign + valueFormatter(diff, unit, 1);
295
+ const diffPercentageText = diffSign + (diffRatio * 100).toFixed(2) + '%';
296
+ const diffText = `${diffValueText} (${diffPercentageText})`;
297
+
298
+ const getTextForCumulative = (hoveringNodeCumulative: bigint): string => {
299
+ const filtered =
300
+ totalUnfiltered > total
301
+ ? ` / ${(100 * divide(hoveringNodeCumulative, total)).toFixed(2)}% of filtered`
302
+ : '';
303
+ return `${valueFormatter(hoveringNodeCumulative, unit, 2)}
304
+ (${(100 * divide(hoveringNodeCumulative, totalUnfiltered)).toFixed(2)}%${filtered})`;
305
+ };
306
+
307
+ return (
308
+ <div className={`flex text-sm ${isFixed ? 'w-full' : ''}`}>
309
+ <div className={`m-auto w-full ${isFixed ? 'w-full' : ''}`}>
310
+ <div className="min-h-52 flex w-[500px] flex-col justify-between rounded-lg border border-gray-300 bg-gray-50 p-3 shadow-lg dark:border-gray-500 dark:bg-gray-900">
311
+ <div className="flex flex-row">
312
+ <div className="mx-2">
313
+ <div className="flex h-10 items-center break-all font-semibold">
314
+ {hoveringNode.meta === undefined ? (
315
+ <p>root</p>
316
+ ) : (
317
+ <>
318
+ {hoveringNode.meta.function !== undefined &&
319
+ hoveringNode.meta.function.name !== '' ? (
320
+ <CopyToClipboard onCopy={onCopy} text={hoveringNode.meta.function.name}>
321
+ <button className="cursor-pointer text-left">
322
+ {hoveringNode.meta.function.name}
323
+ </button>
324
+ </CopyToClipboard>
325
+ ) : (
326
+ <>
327
+ {hoveringNode.meta.location !== undefined &&
328
+ hoveringNode.meta.location.address !== 0n ? (
329
+ <CopyToClipboard
330
+ onCopy={onCopy}
331
+ text={hexifyAddress(hoveringNode.meta.location.address)}
332
+ >
333
+ <button className="cursor-pointer text-left">
334
+ {hexifyAddress(hoveringNode.meta.location.address)}
335
+ </button>
336
+ </CopyToClipboard>
337
+ ) : (
338
+ <p>unknown</p>
339
+ )}
340
+ </>
341
+ )}
342
+ </>
343
+ )}
344
+ </div>
345
+ <table className="my-2 w-full table-fixed pr-0 text-gray-700 dark:text-gray-300">
346
+ <tbody>
347
+ <tr>
348
+ <td className="w-1/4">Cumulative</td>
349
+
350
+ <td className="w-3/4">
351
+ <CopyToClipboard
352
+ onCopy={onCopy}
353
+ text={getTextForCumulative(hoveringNodeCumulative)}
354
+ >
355
+ <button className="cursor-pointer">
356
+ {getTextForCumulative(hoveringNodeCumulative)}
357
+ </button>
358
+ </CopyToClipboard>
359
+ </td>
360
+ </tr>
361
+ {hoveringNode.diff !== undefined && diff !== 0n && (
362
+ <tr>
363
+ <td className="w-1/4">Diff</td>
364
+ <td className="w-3/4">
365
+ <CopyToClipboard onCopy={onCopy} text={diffText}>
366
+ <button className="cursor-pointer">{diffText}</button>
367
+ </CopyToClipboard>
368
+ </td>
369
+ </tr>
370
+ )}
371
+ <TooltipMetaInfo
372
+ onCopy={onCopy}
373
+ hoveringNode={hoveringNode}
374
+ strings={strings}
375
+ mappings={mappings}
376
+ locations={locations}
377
+ functions={functions}
378
+ type={type}
379
+ />
380
+ </tbody>
381
+ </table>
382
+ </div>
383
+ </div>
384
+ <span className="mx-2 block text-xs text-gray-500">
385
+ {isCopied ? 'Copied!' : 'Hold shift and click on a value to copy.'}
386
+ </span>
387
+ </div>
388
+ </div>
389
+ </div>
390
+ );
391
+ };
392
+
393
+ const GraphTooltip = ({
394
+ table,
395
+ x,
396
+ y,
397
+ unit,
398
+ total,
399
+ totalUnfiltered,
400
+ contextElement,
401
+ isFixed = false,
402
+ virtualContextElement = true,
403
+ strings,
404
+ mappings,
405
+ locations,
406
+ functions,
407
+ type = 'flamegraph',
408
+ }: GraphTooltipProps): React.JSX.Element => {
409
+ const hoveringNodeState = useAppSelector(selectHoveringRow);
410
+ const hoveringNode = useMemo<HoveringNode | undefined>(() => {
411
+ const s = hoveringNodeState;
412
+ if (s === undefined) {
413
+ return undefined;
414
+ }
415
+
416
+ const mappingFile: string = table.getChild(FIELD_MAPPING_FILE)?.get(s.row) ?? '';
417
+ const mappingBuildID: string = table.getChild(FIELD_MAPPING_BUILD_ID)?.get(s.row) ?? '';
418
+ const locationAddress: bigint = table.getChild(FIELD_LOCATION_ADDRESS)?.get(s.row) ?? 0n;
419
+ const functionName: string = table.getChild(FIELD_FUNCTION_NAME)?.get(s.row) ?? '';
420
+ const functionFileName: string = table.getChild(FIELD_FUNCTION_FILE_NAME)?.get(s.row) ?? '';
421
+ const cumulative: bigint = table.getChild(FIELD_CUMULATIVE)?.get(s.row) ?? 0n;
422
+ const diff: bigint = table.getChild(FIELD_DIFF)?.get(s.row) ?? 0n;
423
+
424
+ const fhn: HoveringNode = {
425
+ id: '',
426
+ flat: 0n,
427
+ children: [],
428
+
429
+ cumulative,
430
+ diff: diff === null ? 0n : diff,
431
+ meta: {
432
+ locationIndex: 0,
433
+ lineIndex: 0,
434
+ mapping: {
435
+ id: '',
436
+ start: 0n,
437
+ limit: 0n,
438
+ offset: 0n,
439
+ file: mappingFile,
440
+ buildId: mappingBuildID,
441
+ hasFunctions: false,
442
+ hasFilenames: false,
443
+ hasLineNumbers: false,
444
+ hasInlineFrames: false,
445
+ fileStringIndex: 0,
446
+ buildIdStringIndex: 0,
447
+ },
448
+ location: {
449
+ id: '',
450
+ address: locationAddress,
451
+ mappingId: '',
452
+ isFolded: false,
453
+ lines: [],
454
+ mappingIndex: 0,
455
+ },
456
+ function: {
457
+ id: '',
458
+ startLine: 0n,
459
+ name: functionName,
460
+ systemName: '',
461
+ filename: functionFileName,
462
+ nameStringIndex: 0,
463
+ systemNameStringIndex: 0,
464
+ filenameStringIndex: 0,
465
+ },
466
+ },
467
+ };
468
+ return fhn;
469
+ }, [table, hoveringNodeState]);
470
+
471
+ const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
472
+
473
+ const {styles, attributes, ...popperProps} = usePopper(
474
+ virtualContextElement ? virtualElement : contextElement,
475
+ popperElement,
476
+ {
477
+ placement: 'bottom-start',
478
+ strategy: 'absolute',
479
+ modifiers: [
480
+ {
481
+ name: 'preventOverflow',
482
+ options: {
483
+ tether: false,
484
+ altAxis: true,
485
+ boundary: contextElement ?? undefined,
486
+ },
487
+ },
488
+ {
489
+ name: 'offset',
490
+ options: {
491
+ offset: [30, 30],
492
+ },
493
+ },
494
+ {
495
+ name: 'flip',
496
+ options: {
497
+ boundary: contextElement ?? undefined,
498
+ },
499
+ },
500
+ ],
501
+ }
502
+ );
503
+
504
+ const {isShiftDown} = useKeyDown();
505
+
506
+ useEffect(() => {
507
+ if (contextElement === null) return;
508
+ const onMouseMove: EventListenerOrEventListenerObject = (e: Event) => {
509
+ if (isShiftDown) {
510
+ return;
511
+ }
512
+
513
+ let tooltipX = x;
514
+ let tooltipY = y;
515
+ if (tooltipX == null || tooltipY == null) {
516
+ const rel = pointer(e);
517
+ tooltipX = rel[0];
518
+ tooltipY = rel[1];
519
+ }
520
+ virtualElement.getBoundingClientRect = generateGetBoundingClientRect(
521
+ contextElement,
522
+ tooltipX,
523
+ tooltipY
524
+ );
525
+
526
+ void popperProps.update?.();
527
+ };
528
+
529
+ contextElement.addEventListener('mousemove', onMouseMove);
530
+ return () => {
531
+ contextElement.removeEventListener('mousemove', onMouseMove);
532
+ };
533
+ }, [contextElement, popperProps, isShiftDown, x, y]);
534
+
535
+ if (hoveringNode === undefined || hoveringNode == null) return <></>;
536
+
537
+ return isFixed ? (
538
+ <GraphTooltipContent
539
+ hoveringNode={hoveringNode}
540
+ unit={unit}
541
+ total={total}
542
+ totalUnfiltered={totalUnfiltered}
543
+ isFixed={isFixed}
544
+ type={type}
545
+ />
546
+ ) : (
547
+ <div ref={setPopperElement} style={styles.popper} {...attributes.popper}>
548
+ <GraphTooltipContent
549
+ hoveringNode={hoveringNode}
550
+ unit={unit}
551
+ total={total}
552
+ totalUnfiltered={totalUnfiltered}
553
+ isFixed={isFixed}
554
+ strings={strings}
555
+ mappings={mappings}
556
+ locations={locations}
557
+ functions={functions}
558
+ type={type}
559
+ />
560
+ </div>
561
+ );
562
+ };
563
+
564
+ export default GraphTooltip;