@parca/profile 0.16.22 → 0.16.43

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 (39) hide show
  1. package/CHANGELOG.md +35 -48
  2. package/dist/Callgraph/Edge/index.d.ts +1 -0
  3. package/dist/Callgraph/Node/index.d.ts +2 -1
  4. package/dist/Callgraph/index.d.ts +1 -0
  5. package/dist/GraphTooltip/index.d.ts +1 -0
  6. package/dist/GraphTooltip/index.js +51 -15
  7. package/dist/IcicleGraph.d.ts +1 -0
  8. package/dist/IcicleGraph.js +23 -4
  9. package/dist/MatchersInput/index.d.ts +1 -0
  10. package/dist/MetricsCircle/index.d.ts +1 -0
  11. package/dist/MetricsGraph/index.d.ts +1 -0
  12. package/dist/MetricsGraph/index.js +5 -27
  13. package/dist/MetricsSeries/index.d.ts +1 -0
  14. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts +1 -0
  15. package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +1 -0
  16. package/dist/ProfileExplorer/index.d.ts +1 -0
  17. package/dist/ProfileIcicleGraph.d.ts +1 -0
  18. package/dist/ProfileMetricsGraph/index.d.ts +1 -0
  19. package/dist/ProfileSelector/CompareButton.d.ts +1 -0
  20. package/dist/ProfileSelector/MergeButton.d.ts +1 -0
  21. package/dist/ProfileSelector/index.d.ts +1 -0
  22. package/dist/ProfileSource.d.ts +1 -0
  23. package/dist/ProfileTypeSelector/index.d.ts +1 -0
  24. package/dist/ProfileView.d.ts +1 -0
  25. package/dist/ProfileViewWithData.d.ts +1 -0
  26. package/dist/TopTable.d.ts +2 -1
  27. package/dist/components/DiffLegend.d.ts +1 -0
  28. package/dist/components/ProfileShareButton/ResultBox.d.ts +1 -0
  29. package/dist/components/ProfileShareButton/index.d.ts +1 -0
  30. package/dist/stories/ProfileTypeSelector.stories.d.ts +5 -0
  31. package/dist/stories/ProfileTypeSelector.stories.js +77 -0
  32. package/dist/stories/ProfileView.stories.d.ts +5 -0
  33. package/dist/stories/ProfileView.stories.js +22 -0
  34. package/dist/stories/mockdata/flamegraphData.json +7960 -0
  35. package/dist/styles.css +1 -1
  36. package/package.json +5 -4
  37. package/src/GraphTooltip/index.tsx +116 -21
  38. package/src/IcicleGraph.tsx +25 -5
  39. package/src/MetricsGraph/index.tsx +6 -31
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- /*! tailwindcss v3.1.8 | 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-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%}*,: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: }::-webkit-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: }::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}}.absolute{position:absolute}.relative{position:relative}.left-0{left:0}.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}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mr-3{margin-right:.75rem}.ml-auto{margin-left:auto}.ml-2{margin-left:.5rem}.mr-6{margin-right:1.5rem}.mt-1{margin-top:.25rem}.mb-2{margin-bottom:.5rem}.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}.h-36{height:9rem}.h-1{height:.25rem}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.w-full{width:100%}.w-2\/5{width:40%}.w-auto{width:auto}.w-1\/2{width:50%}.w-\[150px\]{width:150px}.w-1\/5{width:20%}.w-4\/5{width:80%}.w-fit{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-40{width:10rem}.w-8{width:2rem}.w-16{width:4rem}.w-\[420px\]{width:420px}.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-not-allowed{cursor:not-allowed}.cursor-default{cursor:default}.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}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.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))}.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))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(229 231 235/var(--tw-divide-opacity))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-scroll{overflow-x:scroll}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded{border-radius:.25rem}.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}.rounded-tr-none{border-top-right-radius:0}.rounded-br-none{border-bottom-right-radius:0}.rounded-tl-none{border-top-left-radius:0}.rounded-bl-none{border-bottom-left-radius:0}.border{border-width:1px}.border-l-0{border-left-width:0}.border-r-0{border-right-width:0}.border-b{border-bottom-width:1px}.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-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.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-inherit{background-color:inherit}.fill-\[\#161616\]{fill:#161616}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.p-10{padding:2.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pt-2{padding-top:.5rem}.pb-2{padding-bottom:.5rem}.pl-2{padding-left:.5rem}.pr-2{padding-right:.5rem}.pb-4{padding-bottom:1rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-base{font-size:1rem;line-height:1.5rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/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-90{opacity:.9}.opacity-100{opacity:1}.opacity-0{opacity:0}.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);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.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)}.hover\:bg-\[\#62626212\]:hover{background-color:#62626212}.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))}.dark .dark\:divide-gray-700>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(55 65 81/var(--tw-divide-opacity))}.dark .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}.dark .dark\:border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.dark .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.dark .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.dark .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.dark .dark\:fill-\[\#ffffff\]{fill:#fff}.dark .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}.dark .dark\:hover\:bg-\[\#ffffff12\]:hover{background-color:#ffffff12}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
1
+ /*! tailwindcss v3.1.8 | 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-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%}*,: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}}.absolute{position:absolute}.relative{position:relative}.left-0{left:0}.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}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mr-3{margin-right:.75rem}.ml-auto{margin-left:auto}.ml-2{margin-left:.5rem}.mr-6{margin-right:1.5rem}.mt-2{margin-top:.5rem}.mt-1{margin-top:.25rem}.mb-2{margin-bottom:.5rem}.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}.h-36{height:9rem}.h-1{height:.25rem}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.w-full{width:100%}.w-2\/5{width:40%}.w-auto{width:auto}.w-1\/2{width:50%}.w-\[150px\]{width:150px}.w-1\/5{width:20%}.w-4\/5{width:80%}.w-fit{width:-moz-fit-content;width:fit-content}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-40{width:10rem}.w-8{width:2rem}.w-16{width:4rem}.w-\[420px\]{width:420px}.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-not-allowed{cursor:not-allowed}.cursor-default{cursor:default}.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}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.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))}.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))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(229 231 235/var(--tw-divide-opacity))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-scroll{overflow-x:scroll}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded{border-radius:.25rem}.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}.rounded-tr-none{border-top-right-radius:0}.rounded-br-none{border-bottom-right-radius:0}.rounded-tl-none{border-top-left-radius:0}.rounded-bl-none{border-bottom-left-radius:0}.border{border-width:1px}.border-l-0{border-left-width:0}.border-r-0{border-right-width:0}.border-b{border-bottom-width:1px}.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-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.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-inherit{background-color:inherit}.fill-\[\#161616\]{fill:#161616}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.p-10{padding:2.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pt-2{padding-top:.5rem}.pb-2{padding-bottom:.5rem}.pl-2{padding-left:.5rem}.pr-2{padding-right:.5rem}.pb-4{padding-bottom:1rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-base{font-size:1rem;line-height:1.5rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.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-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/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-90{opacity:.9}.opacity-100{opacity:1}.opacity-0{opacity:0}.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);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.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)}.hover\:bg-\[\#62626212\]:hover{background-color:#62626212}.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))}.dark .dark\:divide-gray-700>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(55 65 81/var(--tw-divide-opacity))}.dark .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}.dark .dark\:border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.dark .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.dark .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.dark .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.dark .dark\:fill-\[\#ffffff\]{fill:#fff}.dark .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}.dark .dark\:hover\:bg-\[\#ffffff12\]:hover{background-color:#ffffff12}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.22",
3
+ "version": "0.16.43",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@iconify/react": "^3.2.2",
7
7
  "@parca/client": "^0.16.22",
8
- "@parca/components": "^0.16.22",
8
+ "@parca/components": "^0.16.43",
9
9
  "@parca/dynamicsize": "^0.16.22",
10
10
  "@parca/functions": "^0.16.22",
11
11
  "@parca/parser": "^0.16.22",
@@ -21,7 +21,8 @@
21
21
  "scripts": {
22
22
  "test": "jest --coverage --config ../../../jest.config.js ./src/*",
23
23
  "prepublish": "yarn build",
24
- "build": "tsc && tailwindcss -o dist/styles.css --minify && cp src/*.css ./dist/"
24
+ "build": "tsc && tailwindcss -o dist/styles.css --minify && cp src/*.css ./dist/",
25
+ "watch": "tsc-watch --onSuccess 'tailwindcss -o dist/styles.css --minify'"
25
26
  },
26
27
  "keywords": [],
27
28
  "author": "",
@@ -30,5 +31,5 @@
30
31
  "access": "public",
31
32
  "registry": "https://registry.npmjs.org/"
32
33
  },
33
- "gitHead": "b7dc2d8947b27f8fd5e62e1473c1cb41272c7850"
34
+ "gitHead": "6abe2900480e4d043611fb7587b898c12f4f1518"
34
35
  }
@@ -11,11 +11,14 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
+ import {CopyToClipboard} from 'react-copy-to-clipboard';
15
+ import {useState, useEffect} from 'react';
16
+ import {usePopper} from 'react-popper';
17
+
14
18
  import {CallgraphNode, FlamegraphNode, FlamegraphRootNode} from '@parca/client';
15
19
  import {getLastItem, valueFormatter} from '@parca/functions';
20
+ import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
16
21
  import {hexifyAddress} from '../';
17
- import {useState, useEffect} from 'react';
18
- import {usePopper} from 'react-popper';
19
22
 
20
23
  interface GraphTooltipProps {
21
24
  x: number;
@@ -55,9 +58,31 @@ function generateGetBoundingClientRect(contextElement: Element, x = 0, y = 0): (
55
58
  } as DOMRect);
56
59
  }
57
60
 
58
- const TooltipMetaInfo = ({hoveringNode}: {hoveringNode: FlamegraphNode}): JSX.Element => {
61
+ const TooltipMetaInfo = ({
62
+ hoveringNode,
63
+ onCopy,
64
+ }: {
65
+ hoveringNode: FlamegraphNode;
66
+ onCopy: () => void;
67
+ }): JSX.Element => {
59
68
  if (hoveringNode.meta === undefined) return <></>;
60
69
 
70
+ const getTextForFile = (hoveringNode: FlamegraphNode): string => {
71
+ if (hoveringNode.meta === undefined) return '<unknown>';
72
+
73
+ // @ts-expect-error
74
+ return `${hoveringNode.meta.function.filename} ${
75
+ hoveringNode.meta.line?.line !== undefined && hoveringNode.meta.line?.line !== '0'
76
+ ? ` +${hoveringNode.meta.line.line.toString()}`
77
+ : `${
78
+ hoveringNode.meta.function?.startLine !== undefined &&
79
+ hoveringNode.meta.function?.startLine !== '0'
80
+ ? ` +${hoveringNode.meta.function.startLine}`
81
+ : ''
82
+ }`
83
+ }`;
84
+ };
85
+
61
86
  return (
62
87
  <>
63
88
  {hoveringNode.meta.function?.filename !== undefined &&
@@ -65,15 +90,9 @@ const TooltipMetaInfo = ({hoveringNode}: {hoveringNode: FlamegraphNode}): JSX.El
65
90
  <tr>
66
91
  <td className="w-1/5">File</td>
67
92
  <td className="w-4/5 break-all">
68
- {hoveringNode.meta.function.filename}
69
- {hoveringNode.meta.line?.line !== undefined && hoveringNode.meta.line?.line !== '0'
70
- ? ` +${hoveringNode.meta.line.line.toString()}`
71
- : `${
72
- hoveringNode.meta.function?.startLine !== undefined &&
73
- hoveringNode.meta.function?.startLine !== '0'
74
- ? ` +${hoveringNode.meta.function.startLine}`
75
- : ''
76
- }`}
93
+ <CopyToClipboard onCopy={onCopy} text={getTextForFile(hoveringNode)}>
94
+ <button className="cursor-pointer text-left">{getTextForFile(hoveringNode)}</button>
95
+ </CopyToClipboard>
77
96
  </td>
78
97
  </tr>
79
98
  )}
@@ -82,14 +101,39 @@ const TooltipMetaInfo = ({hoveringNode}: {hoveringNode: FlamegraphNode}): JSX.El
82
101
  <tr>
83
102
  <td className="w-1/5">Address</td>
84
103
  <td className="w-4/5 break-all">
85
- {' 0x' + hoveringNode.meta.location.address.toString()}
104
+ <CopyToClipboard
105
+ onCopy={onCopy}
106
+ text={' 0x' + hoveringNode.meta.location.address.toString()}
107
+ >
108
+ <button className="cursor-pointer">
109
+ {' 0x' + hoveringNode.meta.location.address.toString()}
110
+ </button>
111
+ </CopyToClipboard>
86
112
  </td>
87
113
  </tr>
88
114
  )}
89
115
  {hoveringNode.meta.mapping !== undefined && hoveringNode.meta.mapping.file !== '' && (
90
116
  <tr>
91
117
  <td className="w-1/5">Binary</td>
92
- <td className="w-4/5 break-all">{getLastItem(hoveringNode.meta.mapping.file)}</td>
118
+ <td className="w-4/5 break-all">
119
+ <CopyToClipboard onCopy={onCopy} text={hoveringNode.meta.mapping.file}>
120
+ <button className="cursor-pointer">
121
+ {getLastItem(hoveringNode.meta.mapping.file)}
122
+ </button>
123
+ </CopyToClipboard>
124
+ </td>
125
+ </tr>
126
+ )}
127
+ {hoveringNode.meta.mapping !== undefined && hoveringNode.meta.mapping.buildId !== '' && (
128
+ <tr>
129
+ <td className="w-1/5">Build Id</td>
130
+ <td className="w-4/5 break-all">
131
+ <CopyToClipboard onCopy={onCopy} text={hoveringNode.meta.mapping.buildId}>
132
+ <button className="cursor-pointer">
133
+ {getLastItem(hoveringNode.meta.mapping.buildId)}
134
+ </button>
135
+ </CopyToClipboard>
136
+ </td>
93
137
  </tr>
94
138
  )}
95
139
  </>
@@ -101,6 +145,8 @@ export interface HoveringNode extends CallgraphNode, FlamegraphRootNode {
101
145
  meta?: {[key: string]: any};
102
146
  }
103
147
 
148
+ let timeoutHandle: ReturnType<typeof setTimeout> | null = null;
149
+
104
150
  const GraphTooltipContent = ({
105
151
  hoveringNode,
106
152
  unit,
@@ -112,6 +158,17 @@ const GraphTooltipContent = ({
112
158
  total: number;
113
159
  isFixed: boolean;
114
160
  }): JSX.Element => {
161
+ const [isCopied, setIsCopied] = useState<boolean>(false);
162
+
163
+ const onCopy = (): void => {
164
+ setIsCopied(true);
165
+
166
+ if (timeoutHandle !== null) {
167
+ clearTimeout(timeoutHandle);
168
+ }
169
+ timeoutHandle = setTimeout(() => setIsCopied(false), 3000);
170
+ };
171
+
115
172
  const hoveringNodeCumulative = parseFloat(hoveringNode.cumulative);
116
173
  const diff = hoveringNode.diff === undefined ? 0 : parseFloat(hoveringNode.diff);
117
174
  const prevValue = hoveringNodeCumulative - diff;
@@ -121,7 +178,16 @@ const GraphTooltipContent = ({
121
178
  const diffPercentageText = diffSign + (diffRatio * 100).toFixed(2) + '%';
122
179
  const diffText = `${diffValueText} (${diffPercentageText})`;
123
180
  const metaRows =
124
- hoveringNode.meta === undefined ? <></> : <TooltipMetaInfo hoveringNode={hoveringNode} />;
181
+ hoveringNode.meta === undefined ? (
182
+ <></>
183
+ ) : (
184
+ <TooltipMetaInfo onCopy={onCopy} hoveringNode={hoveringNode} />
185
+ );
186
+
187
+ const getTextForCumulative = (hoveringNodeCumulative: number): string => {
188
+ return `${valueFormatter(hoveringNodeCumulative, unit, 2)} (
189
+ ${((hoveringNodeCumulative * 100) / total).toFixed(2)}%)`;
190
+ };
125
191
 
126
192
  return (
127
193
  <div className={`flex ${isFixed ? 'w-full h-36' : ''}`}>
@@ -139,12 +205,23 @@ const GraphTooltipContent = ({
139
205
  <>
140
206
  {hoveringNode.meta.function !== undefined &&
141
207
  hoveringNode.meta.function.name !== '' ? (
142
- <p>{hoveringNode.meta.function.name}</p>
208
+ <CopyToClipboard onCopy={onCopy} text={hoveringNode.meta.function.name}>
209
+ <button className="cursor-pointer text-left">
210
+ {hoveringNode.meta.function.name}
211
+ </button>
212
+ </CopyToClipboard>
143
213
  ) : (
144
214
  <>
145
215
  {hoveringNode.meta.location !== undefined &&
146
216
  parseInt(hoveringNode.meta.location.address, 10) !== 0 ? (
147
- <p>{hexifyAddress(hoveringNode.meta.location.address)}</p>
217
+ <CopyToClipboard
218
+ onCopy={onCopy}
219
+ text={hexifyAddress(hoveringNode.meta.location.address)}
220
+ >
221
+ <button className="cursor-pointer text-left">
222
+ {hexifyAddress(hoveringNode.meta.location.address)}
223
+ </button>
224
+ </CopyToClipboard>
148
225
  ) : (
149
226
  <p>unknown</p>
150
227
  )}
@@ -158,21 +235,36 @@ const GraphTooltipContent = ({
158
235
  <tbody>
159
236
  <tr>
160
237
  <td className="w-1/5">Cumulative</td>
238
+
161
239
  <td className="w-4/5">
162
- {valueFormatter(hoveringNodeCumulative, unit, 2)} (
163
- {((hoveringNodeCumulative * 100) / total).toFixed(2)}%)
240
+ <CopyToClipboard
241
+ onCopy={onCopy}
242
+ text={getTextForCumulative(hoveringNodeCumulative)}
243
+ >
244
+ <button className="cursor-pointer">
245
+ {getTextForCumulative(hoveringNodeCumulative)}
246
+ </button>
247
+ </CopyToClipboard>
164
248
  </td>
165
249
  </tr>
166
250
  {hoveringNode.diff !== undefined && diff !== 0 && (
167
251
  <tr>
168
252
  <td className="w-1/5">Diff</td>
169
- <td className="w-4/5">{diffText}</td>
253
+ <td className="w-4/5">
254
+ <CopyToClipboard onCopy={onCopy} text={diffText}>
255
+ <button className="cursor-pointer">{diffText}</button>
256
+ </CopyToClipboard>
257
+ </td>
170
258
  </tr>
171
259
  )}
172
260
  {metaRows}
173
261
  </tbody>
174
262
  </table>
175
263
  </span>
264
+
265
+ <span className="block text-gray-500 text-xs mt-2">
266
+ {isCopied ? 'Copied!' : 'Hold shift and click on a value to copy.'}
267
+ </span>
176
268
  </div>
177
269
  </div>
178
270
  </div>
@@ -218,13 +310,16 @@ const GraphTooltip = ({
218
310
  );
219
311
 
220
312
  const update = popperProps.update;
313
+ const isShiftDown = useIsShiftDown();
221
314
 
222
315
  useEffect(() => {
223
316
  if (contextElement != null) {
317
+ if (isShiftDown) return;
318
+
224
319
  virtualElement.getBoundingClientRect = generateGetBoundingClientRect(contextElement, x, y);
225
320
  void update?.();
226
321
  }
227
- }, [x, y, contextElement, update]);
322
+ }, [x, y, contextElement, update, isShiftDown]);
228
323
 
229
324
  if (hoveringNode === undefined || hoveringNode == null) return <></>;
230
325
 
@@ -16,11 +16,12 @@ import React, {MouseEvent, useEffect, useRef, useState} from 'react';
16
16
  import {throttle} from 'lodash';
17
17
  import {pointer} from 'd3-selection';
18
18
  import {scaleLinear} from 'd3-scale';
19
+
19
20
  import {Flamegraph, FlamegraphNode, FlamegraphRootNode} from '@parca/client';
20
21
  import GraphTooltip from './GraphTooltip';
21
22
  import {getLastItem, diffColor, isSearchMatch} from '@parca/functions';
22
23
  import {useAppSelector, selectDarkMode, selectSearchNodeString} from '@parca/store';
23
-
24
+ import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
24
25
  import {hexifyAddress} from './utils';
25
26
  import type {HoveringNode} from './GraphTooltip';
26
27
 
@@ -161,6 +162,7 @@ export function IcicleGraphNodes({
161
162
  curPath,
162
163
  }: IcicleGraphNodesProps): JSX.Element {
163
164
  const isDarkMode = useAppSelector(selectDarkMode);
165
+ const isShiftDown = useIsShiftDown();
164
166
 
165
167
  const nodes =
166
168
  curPath.length === 0 ? data : data.filter(d => d != null && curPath[0] === nodeLabel(d));
@@ -200,8 +202,16 @@ export function IcicleGraphNodes({
200
202
  ? scaleLinear().domain([0, cumulative]).range([0, totalWidth])
201
203
  : xScale;
202
204
 
203
- const onMouseEnter = (): void => setHoveringNode(d);
204
- const onMouseLeave = (): void => setHoveringNode(undefined);
205
+ const onMouseEnter = (): void => {
206
+ if (isShiftDown) return;
207
+
208
+ setHoveringNode(d);
209
+ };
210
+ const onMouseLeave = (): void => {
211
+ if (isShiftDown) return;
212
+
213
+ setHoveringNode(undefined);
214
+ };
205
215
 
206
216
  return (
207
217
  <React.Fragment key={`node-${key}`}>
@@ -253,14 +263,24 @@ export function IcicleGraphRootNode({
253
263
  curPath,
254
264
  }: IcicleGraphRootNodeProps): JSX.Element {
255
265
  const isDarkMode = useAppSelector(selectDarkMode);
266
+ const isShiftDown = useIsShiftDown();
256
267
 
257
268
  const cumulative = parseFloat(node.cumulative);
258
269
  const diff = parseFloat(node.diff);
259
270
  const color = diffColor(diff, cumulative, isDarkMode);
260
271
 
261
272
  const onClick = (): void => setCurPath([]);
262
- const onMouseEnter = (): void => setHoveringNode(node);
263
- const onMouseLeave = (): void => setHoveringNode(undefined);
273
+ const onMouseEnter = (): void => {
274
+ if (isShiftDown) return;
275
+
276
+ setHoveringNode(node);
277
+ };
278
+ const onMouseLeave = (): void => {
279
+ if (isShiftDown) return;
280
+
281
+ setHoveringNode(undefined);
282
+ };
283
+
264
284
  const path: string[] = [];
265
285
 
266
286
  return (
@@ -13,8 +13,6 @@
13
13
 
14
14
  import React, {useEffect, useRef, useState} from 'react';
15
15
  import * as d3 from 'd3';
16
- import MetricsSeries from '../MetricsSeries';
17
- import MetricsCircle from '../MetricsCircle';
18
16
  import {pointer} from 'd3-selection';
19
17
  import {formatForTimespan} from '@parca/functions/time';
20
18
  import {SingleProfileSelection, timeFormat} from '..';
@@ -26,6 +24,10 @@ import type {VirtualElement} from '@popperjs/core';
26
24
  import {valueFormatter, formatDate} from '@parca/functions';
27
25
  import {DateTimeRange} from '@parca/components';
28
26
  import {useContainerDimensions} from '@parca/dynamicsize';
27
+ import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
28
+
29
+ import MetricsSeries from '../MetricsSeries';
30
+ import MetricsCircle from '../MetricsCircle';
29
31
 
30
32
  interface RawMetricsGraphProps {
31
33
  data: MetricsSeriesPb[];
@@ -244,34 +246,8 @@ export const RawMetricsGraph = ({
244
246
  const [hovering, setHovering] = useState(false);
245
247
  const [relPos, setRelPos] = useState(-1);
246
248
  const [pos, setPos] = useState([0, 0]);
247
- const [freezeTooltip, setFreezeTooltip] = useState(false);
248
249
  const metricPointRef = useRef(null);
249
-
250
- useEffect(() => {
251
- const handleShiftDown = (event: {keyCode: number}): void => {
252
- if (event.keyCode === 16) {
253
- setFreezeTooltip(true);
254
- }
255
- };
256
- window.addEventListener('keydown', handleShiftDown);
257
-
258
- return () => {
259
- window.removeEventListener('keydown', handleShiftDown);
260
- };
261
- }, []);
262
-
263
- useEffect(() => {
264
- const handleShiftUp = (event: {keyCode: number}): void => {
265
- if (event.keyCode === 16) {
266
- setFreezeTooltip(false);
267
- }
268
- };
269
- window.addEventListener('keyup', handleShiftUp);
270
-
271
- return () => {
272
- window.removeEventListener('keyup', handleShiftUp);
273
- };
274
- }, []);
250
+ const isShiftDown = useIsShiftDown();
275
251
 
276
252
  const time: number = parseFloat(profile?.HistoryParams().time);
277
253
 
@@ -431,7 +407,7 @@ export const RawMetricsGraph = ({
431
407
  const yCoordinate = rel[1];
432
408
  const yCoordinateWithoutMargin = yCoordinate - margin;
433
409
 
434
- if (!freezeTooltip) {
410
+ if (!isShiftDown) {
435
411
  throttledSetPos([xCoordinateWithoutMargin, yCoordinateWithoutMargin]);
436
412
  }
437
413
  };
@@ -505,7 +481,6 @@ export const RawMetricsGraph = ({
505
481
  ref={graph}
506
482
  onMouseEnter={function () {
507
483
  setHovering(true);
508
- setFreezeTooltip(false);
509
484
  }}
510
485
  onMouseLeave={() => setHovering(false)}
511
486
  >