@parca/profile 0.16.122 → 0.16.124

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.
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}.top-\[-45px\]{top:-45px}.top-\[-48px\]{top:-48px}.top-\[-69px\]{top:-69px}.top-\[-54px\]{top:-54px}.top-\[-70px\]{top:-70px}.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-auto{width:auto}.w-full{width:100%}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-40{width:10rem}.w-2\/5{width:40%}.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}.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-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}}
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-auto{width:auto}.w-full{width:100%}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-40{width:10rem}.w-2\/5{width:40%}.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}.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-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}}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.122",
3
+ "version": "0.16.124",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
- "@parca/client": "^0.16.63",
7
- "@parca/components": "^0.16.102",
6
+ "@parca/client": "^0.16.64",
7
+ "@parca/components": "^0.16.103",
8
8
  "@parca/dynamicsize": "^0.16.53",
9
- "@parca/functions": "^0.16.63",
9
+ "@parca/functions": "^0.16.64",
10
10
  "@parca/parser": "^0.16.54",
11
- "@parca/store": "^0.16.59",
11
+ "@parca/store": "^0.16.60",
12
12
  "@types/react-beautiful-dnd": "^13.1.3",
13
13
  "d3": "7.8.2",
14
14
  "d3-scale": "^4.0.2",
@@ -45,5 +45,5 @@
45
45
  "access": "public",
46
46
  "registry": "https://registry.npmjs.org/"
47
47
  },
48
- "gitHead": "c2165c6991e55c1afd7d11e9c797a3de58578959"
48
+ "gitHead": "bcca09575ec917fdd2669a0b32b7e3b7e3757117"
49
49
  }
@@ -119,7 +119,13 @@ const MetricsTooltip = ({
119
119
  <tr>
120
120
  <td className="w-1/4">Value</td>
121
121
  <td className="w-3/4">
122
- {valueFormatter(highlighted.value, sampleUnit, 1)}
122
+ {valueFormatter(highlighted.valuePerSecond, sampleUnit, 5)}
123
+ </td>
124
+ </tr>
125
+ <tr>
126
+ <td className="w-1/4">Total</td>
127
+ <td className="w-3/4">
128
+ {valueFormatter(highlighted.value, sampleUnit, 2)}
123
129
  </td>
124
130
  </tr>
125
131
  <tr>
@@ -49,6 +49,7 @@ export interface HighlightedSeries {
49
49
  labels: Label[];
50
50
  timestamp: number;
51
51
  value: number;
52
+ valuePerSecond: number;
52
53
  x: number;
53
54
  y: number;
54
55
  }
@@ -134,9 +135,9 @@ export const RawMetricsGraph = ({
134
135
  agg.push({
135
136
  metric: s.labelset.labels,
136
137
  values: s.samples.reduce<number[][]>(function (agg: number[][], d: MetricsSample) {
137
- if (d.timestamp !== undefined && d.value !== undefined) {
138
+ if (d.timestamp !== undefined && d.valuePerSecond !== undefined) {
138
139
  const t = (+d.timestamp.seconds * 1e9 + d.timestamp.nanos) / 1e6; // https://github.com/microsoft/TypeScript/issues/5710#issuecomment-157886246
139
- agg.push([t, parseFloat(d.value)]);
140
+ agg.push([t, d.valuePerSecond, parseFloat(d.value)]);
140
141
  }
141
142
  return agg;
142
143
  }, []),
@@ -202,7 +203,8 @@ export const RawMetricsGraph = ({
202
203
  seriesIndex: closestSeriesIndex,
203
204
  labels: series[closestSeriesIndex].metric,
204
205
  timestamp: point[0],
205
- value: point[1],
206
+ valuePerSecond: point[1],
207
+ value: point[2],
206
208
  x: xScale(point[0]),
207
209
  y: yScale(point[1]),
208
210
  };
@@ -295,14 +297,14 @@ export const RawMetricsGraph = ({
295
297
  let seriesIndex = -1;
296
298
 
297
299
  outer: for (let i = 0; i < series.length; i++) {
298
- const keys = profile.labels.map(e => e.name);
300
+ const keys = profile.query.matchers.map(e => e.key);
299
301
  for (let j = 0; j < keys.length; j++) {
300
- const labelName = keys[j];
301
- const label = series[i].metric.find(e => e.name === labelName);
302
+ const matcherKey = keys[j];
303
+ const label = series[i].metric.find(e => e.name === matcherKey);
302
304
  if (label === undefined) {
303
305
  continue outer; // label doesn't exist to begin with
304
306
  }
305
- if (profile.labels[j].value !== label.value) {
307
+ if (profile.query.matchers[j].value !== label.value) {
306
308
  continue outer; // label values don't match
307
309
  }
308
310
  }
@@ -325,7 +327,8 @@ export const RawMetricsGraph = ({
325
327
  labels: [],
326
328
  seriesIndex,
327
329
  timestamp: sample[0],
328
- value: sample[1],
330
+ valuePerSecond: sample[1],
331
+ value: sample[2],
329
332
  x: xScale(sample[0]),
330
333
  y: yScale(sample[1]),
331
334
  };
@@ -13,13 +13,10 @@
13
13
 
14
14
  import {memo, useEffect, useMemo, useRef, useState} from 'react';
15
15
 
16
- import cx from 'classnames';
17
16
  import {scaleLinear} from 'd3-scale';
18
17
 
19
18
  import {Flamegraph, FlamegraphNode, FlamegraphRootNode} from '@parca/client';
20
- import {Button, useURLState} from '@parca/components';
21
19
  import {selectQueryParam, type NavigateFunction} from '@parca/functions';
22
- import useUserPreference, {USER_PREFERENCES} from '@parca/functions/useUserPreference';
23
20
 
24
21
  import GraphTooltip, {type HoveringNode} from '../../GraphTooltip';
25
22
  import ColorStackLegend from './ColorStackLegend';
@@ -33,7 +30,6 @@ interface IcicleGraphProps {
33
30
  curPath: string[];
34
31
  setCurPath: (path: string[]) => void;
35
32
  navigateTo?: NavigateFunction;
36
- isTrimmed?: boolean;
37
33
  }
38
34
 
39
35
  export const IcicleGraph = memo(function IcicleGraph({
@@ -43,7 +39,6 @@ export const IcicleGraph = memo(function IcicleGraph({
43
39
  curPath,
44
40
  sampleUnit,
45
41
  navigateTo,
46
- isTrimmed = false,
47
42
  }: IcicleGraphProps): JSX.Element {
48
43
  const [hoveringNode, setHoveringNode] = useState<
49
44
  FlamegraphNode | FlamegraphRootNode | undefined
@@ -51,20 +46,12 @@ export const IcicleGraph = memo(function IcicleGraph({
51
46
  const [height, setHeight] = useState(0);
52
47
  const svg = useRef(null);
53
48
  const ref = useRef<SVGGElement>(null);
54
- const [rawDashboardItems] = useURLState({
55
- param: 'dashboard_items',
56
- });
57
49
 
58
- const dashboardItems = rawDashboardItems as string[];
59
50
  const coloredGraph = useColoredGraph(graph);
60
51
  const currentSearchString = (selectQueryParam('search_string') as string) ?? '';
61
52
  const compareMode: boolean =
62
53
  selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
63
54
 
64
- const [colorProfileName] = useUserPreference<string>(
65
- USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key
66
- );
67
-
68
55
  useEffect(() => {
69
56
  if (ref.current != null) {
70
57
  setHeight(ref?.current.getBoundingClientRect().height);
@@ -83,8 +70,6 @@ export const IcicleGraph = memo(function IcicleGraph({
83
70
  return <></>;
84
71
  }
85
72
 
86
- const isColorStackLegendVisible = colorProfileName !== 'default';
87
-
88
73
  return (
89
74
  <div onMouseLeave={() => setHoveringNode(undefined)}>
90
75
  <ColorStackLegend navigateTo={navigateTo} compareMode={compareMode} />
@@ -98,32 +83,6 @@ export const IcicleGraph = memo(function IcicleGraph({
98
83
  locations={coloredGraph.locations}
99
84
  functions={coloredGraph.function}
100
85
  />
101
- <div
102
- className={cx('flex justify-start absolute', {
103
- 'top-[-48px]': dashboardItems.length <= 1 && !isTrimmed && !isColorStackLegendVisible,
104
- 'top-[-69px]': dashboardItems.length <= 1 && !isTrimmed && isColorStackLegendVisible,
105
- 'top-[-54px]': dashboardItems.length <= 1 && isTrimmed && isColorStackLegendVisible,
106
- 'top-[-54px] ': dashboardItems.length <= 1 && isTrimmed && !isColorStackLegendVisible,
107
- 'top-[-54px] left-[25px]':
108
- dashboardItems.length > 1 && isTrimmed && isColorStackLegendVisible,
109
- 'top-[-54px] left-[25px] ':
110
- dashboardItems.length > 1 && isTrimmed && !isColorStackLegendVisible,
111
- 'top-[-70px] left-[25px]':
112
- dashboardItems.length > 1 && !isTrimmed && isColorStackLegendVisible,
113
- 'top-[-46px] left-[25px]':
114
- dashboardItems.length > 1 && !isTrimmed && !isColorStackLegendVisible,
115
- })}
116
- >
117
- <Button
118
- color="neutral"
119
- onClick={() => setCurPath([])}
120
- disabled={curPath.length === 0}
121
- className="w-auto"
122
- variant="neutral"
123
- >
124
- Reset View
125
- </Button>
126
- </div>
127
86
  <svg
128
87
  className="font-robotoMono"
129
88
  width={width}
@@ -14,11 +14,12 @@
14
14
  import {useEffect, useMemo} from 'react';
15
15
 
16
16
  import {Flamegraph} from '@parca/client';
17
+ import {Button} from '@parca/components';
17
18
  import {useContainerDimensions} from '@parca/dynamicsize';
18
19
  import {selectQueryParam, type NavigateFunction} from '@parca/functions';
19
20
 
20
21
  import DiffLegend from '../components/DiffLegend';
21
- import IcicleGraph from './IcicleGraph';
22
+ import {IcicleGraph} from './IcicleGraph';
22
23
 
23
24
  const numberFormatter = new Intl.NumberFormat('en-US');
24
25
 
@@ -33,6 +34,7 @@ interface ProfileIcicleGraphProps {
33
34
  onContainerResize?: ResizeHandler;
34
35
  navigateTo?: NavigateFunction;
35
36
  loading: boolean;
37
+ setActionButtons?: (buttons: JSX.Element) => void;
36
38
  }
37
39
 
38
40
  const ProfileIcicleGraph = ({
@@ -43,6 +45,7 @@ const ProfileIcicleGraph = ({
43
45
  onContainerResize,
44
46
  navigateTo,
45
47
  loading,
48
+ setActionButtons,
46
49
  }: ProfileIcicleGraphProps): JSX.Element => {
47
50
  const compareMode: boolean =
48
51
  selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
@@ -75,6 +78,25 @@ const ProfileIcicleGraph = ({
75
78
  ];
76
79
  }, [graph]);
77
80
 
81
+ useEffect(() => {
82
+ if (setActionButtons === undefined) {
83
+ return;
84
+ }
85
+ setActionButtons(
86
+ <>
87
+ <Button
88
+ color="neutral"
89
+ onClick={() => setNewCurPath([])}
90
+ disabled={curPath.length === 0}
91
+ className="w-auto"
92
+ variant="neutral"
93
+ >
94
+ Reset View
95
+ </Button>
96
+ </>
97
+ );
98
+ }, [setNewCurPath, curPath, setActionButtons]);
99
+
78
100
  if (graph === undefined) return <div>no data...</div>;
79
101
 
80
102
  const total = graph.total;
@@ -97,7 +119,6 @@ const ProfileIcicleGraph = ({
97
119
  setCurPath={setNewCurPath}
98
120
  sampleUnit={sampleUnit}
99
121
  navigateTo={navigateTo}
100
- isTrimmed={isTrimmed}
101
122
  />
102
123
  </div>
103
124
  </div>
@@ -157,6 +157,7 @@ const ProfileSelector = ({
157
157
  const newValue = value.includes('\\') ? value.replaceAll('\\', '\\\\') : value;
158
158
  const [newQuery, changed] = Query.parse(queryExpressionString).setMatcher(key, newValue);
159
159
  if (changed) {
160
+ // TODO: Change this to store the query object
160
161
  setNewQueryExpression(newQuery.toString());
161
162
  }
162
163
  };
@@ -261,14 +262,22 @@ const ProfileSelector = ({
261
262
  }}
262
263
  addLabelMatcher={addLabelMatcher}
263
264
  onPointClick={(timestamp, labels, queryExpression) => {
265
+ // TODO: Pass the query object via click rather than queryExpression
266
+ let query = Query.parse(queryExpression);
267
+ labels.forEach(l => {
268
+ const [newQuery, updated] = query.setMatcher(l.name, l.value);
269
+ if (updated) {
270
+ query = newQuery;
271
+ }
272
+ });
273
+
264
274
  const stepDuration = getStepDuration(querySelection.from, querySelection.to);
265
275
  const stepDurationInMilliseconds = getStepDurationInMilliseconds(stepDuration);
266
- const isDeltaType = Query.parse(queryExpression).profileType().delta;
267
276
  const mergeFrom = timestamp;
268
- const mergeTo = isDeltaType ? mergeFrom + stepDurationInMilliseconds : mergeFrom;
269
- selectProfile(
270
- new MergedProfileSelection(mergeFrom, mergeTo, labels, queryExpression)
271
- );
277
+ const mergeTo = query.profileType().delta
278
+ ? mergeFrom + stepDurationInMilliseconds
279
+ : mergeFrom;
280
+ selectProfile(new MergedProfileSelection(mergeFrom, mergeTo, query));
272
281
  }}
273
282
  />
274
283
  ) : (
@@ -21,7 +21,7 @@ import {
21
21
  Timestamp,
22
22
  } from '@parca/client';
23
23
  import {formatDate} from '@parca/functions';
24
- import {ProfileType, Query} from '@parca/parser';
24
+ import {Matcher, ProfileType, Query} from '@parca/parser';
25
25
 
26
26
  export interface ProfileSource {
27
27
  QueryRequest: () => QueryRequest;
@@ -56,10 +56,12 @@ export function SuffixParams(params: {[key: string]: any}, suffix: string): {[ke
56
56
  }
57
57
 
58
58
  export function ParseLabels(labels: string[]): Label[] {
59
- return labels.map(function (labelString): Label {
60
- const parts = labelString.split('=', 2);
61
- return {name: parts[0], value: parts[1]};
62
- });
59
+ return labels
60
+ .filter(str => str !== '')
61
+ .map(function (labelString): Label {
62
+ const parts = labelString.split('=', 2);
63
+ return {name: parts[0], value: parts[1]};
64
+ });
63
65
  }
64
66
 
65
67
  export function ProfileSelectionFromParams(
@@ -78,13 +80,16 @@ export function ProfileSelectionFromParams(
78
80
  mergeTo !== undefined &&
79
81
  expression !== undefined
80
82
  ) {
81
- return new MergedProfileSelection(
82
- parseInt(mergeFrom),
83
- parseInt(mergeTo),
84
- ParseLabels(labels ?? ['']),
85
- expression,
86
- filterQuery
87
- );
83
+ // TODO: Refactor parsing the query and adding matchers
84
+ let query = Query.parse(expression);
85
+ ParseLabels(labels ?? ['']).forEach(l => {
86
+ const [newQuery, changed] = query.setMatcher(l.name, l.value);
87
+ if (changed) {
88
+ query = newQuery;
89
+ }
90
+ });
91
+
92
+ return new MergedProfileSelection(parseInt(mergeFrom), parseInt(mergeTo), query, filterQuery);
88
93
  }
89
94
 
90
95
  return null;
@@ -93,26 +98,18 @@ export function ProfileSelectionFromParams(
93
98
  export class MergedProfileSelection implements ProfileSelection {
94
99
  mergeFrom: number;
95
100
  mergeTo: number;
96
- query: string;
101
+ query: Query;
97
102
  filterQuery: string | undefined;
98
- labels: Label[];
99
103
 
100
- constructor(
101
- mergeFrom: number,
102
- mergeTo: number,
103
- labels: Label[],
104
- query: string,
105
- filterQuery?: string
106
- ) {
104
+ constructor(mergeFrom: number, mergeTo: number, query: Query, filterQuery?: string) {
107
105
  this.mergeFrom = mergeFrom;
108
106
  this.mergeTo = mergeTo;
109
107
  this.query = query;
110
108
  this.filterQuery = filterQuery;
111
- this.labels = labels;
112
109
  }
113
110
 
114
111
  ProfileName(): string {
115
- return Query.parse(this.query).profileName();
112
+ return this.query.profileName();
116
113
  }
117
114
 
118
115
  HistoryParams(): {[key: string]: any} {
@@ -121,7 +118,7 @@ export class MergedProfileSelection implements ProfileSelection {
121
118
  merge_to: this.mergeTo.toString(),
122
119
  query: this.query,
123
120
  profile_name: this.ProfileName(),
124
- labels: this.labels.map(label => `${label.name}=${encodeURIComponent(label.value)}`),
121
+ labels: this.query.matchers.map(m => `${m.key}=${encodeURIComponent(m.value)}`),
125
122
  };
126
123
  }
127
124
 
@@ -130,13 +127,7 @@ export class MergedProfileSelection implements ProfileSelection {
130
127
  }
131
128
 
132
129
  ProfileSource(): ProfileSource {
133
- return new MergedProfileSource(
134
- this.mergeFrom,
135
- this.mergeTo,
136
- this.labels,
137
- this.query,
138
- this.filterQuery
139
- );
130
+ return new MergedProfileSource(this.mergeFrom, this.mergeTo, this.query, this.filterQuery);
140
131
  }
141
132
  }
142
133
 
@@ -190,20 +181,12 @@ export class ProfileDiffSource implements ProfileSource {
190
181
  export class MergedProfileSource implements ProfileSource {
191
182
  mergeFrom: number;
192
183
  mergeTo: number;
193
- labels: Label[];
194
- query: string;
184
+ query: Query;
195
185
  filterQuery: string | undefined;
196
186
 
197
- constructor(
198
- mergeFrom: number,
199
- mergeTo: number,
200
- labels: Label[],
201
- query: string,
202
- filterQuery?: string
203
- ) {
187
+ constructor(mergeFrom: number, mergeTo: number, query: Query, filterQuery?: string) {
204
188
  this.mergeFrom = mergeFrom;
205
189
  this.mergeTo = mergeTo;
206
- this.labels = labels;
207
190
  this.query = query;
208
191
  this.filterQuery = filterQuery;
209
192
  }
@@ -215,7 +198,7 @@ export class MergedProfileSource implements ProfileSource {
215
198
  merge: {
216
199
  start: Timestamp.fromDate(new Date(this.mergeFrom)),
217
200
  end: Timestamp.fromDate(new Date(this.mergeTo)),
218
- query: this.query,
201
+ query: this.query.toString(),
219
202
  },
220
203
  },
221
204
  mode: ProfileDiffSelection_Mode.MERGE,
@@ -229,7 +212,7 @@ export class MergedProfileSource implements ProfileSource {
229
212
  merge: {
230
213
  start: Timestamp.fromDate(new Date(this.mergeFrom)),
231
214
  end: Timestamp.fromDate(new Date(this.mergeTo)),
232
- query: this.query,
215
+ query: this.query.toString(),
233
216
  },
234
217
  },
235
218
  reportType: QueryRequest_ReportType.FLAMEGRAPH_UNSPECIFIED,
@@ -239,26 +222,26 @@ export class MergedProfileSource implements ProfileSource {
239
222
  }
240
223
 
241
224
  ProfileType(): ProfileType {
242
- return ProfileType.fromString(Query.parse(this.query).profileName());
225
+ return ProfileType.fromString(Query.parse(this.query.toString()).profileName());
243
226
  }
244
227
 
245
228
  Describe(): JSX.Element {
246
229
  return (
247
230
  <a>
248
- Merge of &quot;{this.query}&quot; from {formatDate(this.mergeFrom, timeFormat)} to{' '}
249
- {formatDate(this.mergeTo, timeFormat)}
231
+ Merge of &quot;{this.query.toString()}&quot; from {formatDate(this.mergeFrom, timeFormat)}{' '}
232
+ to {formatDate(this.mergeTo, timeFormat)}
250
233
  </a>
251
234
  );
252
235
  }
253
236
 
254
- stringLabels(): string[] {
255
- return this.labels
256
- .filter((label: Label) => label.name !== '__name__')
257
- .map((label: Label) => `${label.name}=${label.value}`);
237
+ stringMatchers(): string[] {
238
+ return this.query.matchers
239
+ .filter((m: Matcher) => m.key !== '__name__')
240
+ .map((m: Matcher) => `${m.key}=${m.value}`);
258
241
  }
259
242
 
260
243
  toString(): string {
261
- return `merged profiles of query "${this.query}" from ${formatDate(
244
+ return `merged profiles of query "${this.query.toString()}" from ${formatDate(
262
245
  this.mergeFrom,
263
246
  timeFormat
264
247
  )} to ${formatDate(this.mergeTo, timeFormat)}`;
@@ -0,0 +1,79 @@
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, {useState} from 'react';
15
+
16
+ import {Icon} from '@iconify/react';
17
+ import cx from 'classnames';
18
+ import type {DraggableProvidedDragHandleProps} from 'react-beautiful-dnd';
19
+
20
+ import type {NavigateFunction} from '@parca/functions';
21
+ import {CloseIcon} from '@parca/icons';
22
+
23
+ import ViewSelector from './ViewSelector';
24
+
25
+ interface Props {
26
+ dashboardItem: string;
27
+ index: number;
28
+ isMultiPanelView: boolean;
29
+ handleClosePanel: (dashboardItem: string) => void;
30
+ navigateTo: NavigateFunction | undefined;
31
+ dragHandleProps: DraggableProvidedDragHandleProps | null | undefined;
32
+ getDashboardItemByType: (props: {
33
+ type: string;
34
+ isHalfScreen: boolean;
35
+ setActionButtons: (actionButtons: JSX.Element) => void;
36
+ }) => JSX.Element;
37
+ }
38
+
39
+ export const VisualizationPanel = React.memo(function VisualizationPanel({
40
+ dashboardItem,
41
+ index,
42
+ isMultiPanelView,
43
+ handleClosePanel,
44
+ navigateTo,
45
+ dragHandleProps,
46
+ getDashboardItemByType,
47
+ }: Props): JSX.Element {
48
+ const [actionButtons, setActionButtons] = useState<JSX.Element>(<></>);
49
+
50
+ return (
51
+ <>
52
+ <div className="w-full flex justify-end pb-2">
53
+ <div className="w-full flex justify-between items-center">
54
+ <div className="flex">
55
+ <div
56
+ className={cx(isMultiPanelView ? 'visible' : 'invisible', 'flex items-center')}
57
+ {...dragHandleProps}
58
+ >
59
+ <Icon className="text-xl" icon="material-symbols:drag-indicator" />
60
+ </div>
61
+ <>{actionButtons}</>
62
+ </div>
63
+ <ViewSelector defaultValue={dashboardItem} navigateTo={navigateTo} position={index} />
64
+ </div>
65
+
66
+ {isMultiPanelView && (
67
+ <button type="button" onClick={() => handleClosePanel(dashboardItem)} className="pl-2">
68
+ <CloseIcon />
69
+ </button>
70
+ )}
71
+ </div>
72
+ {getDashboardItemByType({
73
+ type: dashboardItem,
74
+ isHalfScreen: isMultiPanelView,
75
+ setActionButtons,
76
+ })}
77
+ </>
78
+ );
79
+ });