beads-map 0.3.3 → 0.3.4
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/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +2 -2
- package/.next/app-path-routes-manifest.json +1 -1
- package/.next/build-manifest.json +2 -2
- package/.next/next-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/api/beads.body +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +2 -2
- package/.next/server/app/page.js +3 -3
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +5 -5
- package/.next/server/functions-config-manifest.json +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/app/page-cf8e14cb4afc8112.js +1 -0
- package/.next/static/css/ade5301262971664.css +3 -0
- package/app/page.tsx +43 -3
- package/components/BeadsGraph.tsx +108 -10
- package/components/ContextMenu.tsx +51 -5
- package/package.json +1 -1
- package/.next/static/chunks/app/page-4a4f07fcb5bd4637.js +0 -1
- package/.next/static/css/df2737696baac0fa.css +0 -3
- /package/.next/static/{bsmkR-2y8Ra7VuoNZWLzB → JmL0suxsggbSwPxWcmUFV}/_buildManifest.js +0 -0
- /package/.next/static/{bsmkR-2y8Ra7VuoNZWLzB → JmL0suxsggbSwPxWcmUFV}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
*,: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-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--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: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::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-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--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: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*
|
|
2
|
+
! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com
|
|
3
|
+
*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:JetBrains Mono,Fira Code,monospace;font-feature-settings:normal;font-variation-settings:normal;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{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-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}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}body,html{height:100%;overflow:hidden}body{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-feature-settings:"rlig" 1,"calt" 1}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.status-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.75rem;line-height:1rem;font-weight:500}.custom-scrollbar::-webkit-scrollbar{width:4px}.custom-scrollbar::-webkit-scrollbar-track{background-color:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{border-radius:9999px;--tw-bg-opacity:1;background-color:rgb(228 228 231/var(--tw-bg-opacity,1))}.custom-scrollbar::-webkit-scrollbar-thumb:hover{--tw-bg-opacity:1;background-color:rgb(212 212 216/var(--tw-bg-opacity,1))}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{left:0;right:0}.bottom-0{bottom:0}.bottom-2{bottom:.5rem}.bottom-4{bottom:1rem}.left-0{left:0}.left-2{left:.5rem}.left-3{left:.75rem}.left-4{left:1rem}.right-0{right:0}.right-2{right:.5rem}.right-3{right:.75rem}.top-0{top:0}.top-2{top:.5rem}.top-3{top:.75rem}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-50{z-index:50}.z-\[100\]{z-index:100}.z-\[1\]{z-index:1}.z-\[55\]{z-index:55}.z-\[56\]{z-index:56}.z-\[60\]{z-index:60}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.-mr-0\.5{margin-right:-.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-2\.5{margin-bottom:.625rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.ml-auto{margin-left:auto}.mr-1\.5{margin-right:.375rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.mt-\[6px\]{margin-top:6px}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-40{max-height:10rem}.max-h-72{max-height:18rem}.max-h-\[260px\]{max-height:260px}.max-h-\[60vh\]{max-height:60vh}.max-h-\[70vh\]{max-height:70vh}.max-h-\[80vh\]{max-height:80vh}.min-h-\[300px\]{min-height:300px}.w-0\.5{width:.125rem}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-44{width:11rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-\[360px\]{width:360px}.w-\[90vw\]{width:90vw}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0}.min-w-\[18px\]{min-width:18px}.min-w-\[280px\]{min-width:280px}.max-w-2xl{max-width:42rem}.max-w-\[100px\]{max-width:100px}.max-w-\[140px\]{max-width:140px}.max-w-\[180px\]{max-width:180px}.max-w-\[480px\]{max-width:480px}.max-w-\[80px\]{max-width:80px}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-full{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-x-full{--tw-translate-x:100%}.translate-y-0{--tw-translate-y:0px}.translate-y-0,.translate-y-full{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-full{--tw-translate-y:100%}.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))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-crosshair{cursor:crosshair}.cursor-e-resize{cursor:e-resize}.cursor-n-resize{cursor:n-resize}.cursor-ne-resize{cursor:ne-resize}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-1{row-gap:.25rem}.gap-y-1\.5{row-gap:.375rem}.space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-zinc-50>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(250 250 250/var(--tw-divide-opacity,1))}.self-stretch{align-self:stretch}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-t-2xl{border-top-left-radius:1rem;border-top-right-radius:1rem}.rounded-t-lg{border-top-left-radius:.5rem}.rounded-t-lg,.rounded-tr-lg{border-top-right-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-t{border-top-width:1px}.border-emerald-200{--tw-border-opacity:1;border-color:rgb(167 243 208/var(--tw-border-opacity,1))}.border-emerald-500{--tw-border-opacity:1;border-color:rgb(16 185 129/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.border-zinc-100{--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1))}.border-zinc-100\/60{border-color:hsla(240,5%,96%,.6)}.border-zinc-100\/80{border-color:hsla(240,5%,96%,.8)}.border-zinc-200{--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.border-zinc-200\/60{border-color:hsla(240,6%,90%,.6)}.border-zinc-200\/80{border-color:hsla(240,6%,90%,.8)}.border-zinc-50{--tw-border-opacity:1;border-color:rgb(250 250 250/var(--tw-border-opacity,1))}.border-t-emerald-500{--tw-border-opacity:1;border-top-color:rgb(16 185 129/var(--tw-border-opacity,1))}.border-t-zinc-400{--tw-border-opacity:1;border-top-color:rgb(161 161 170/var(--tw-border-opacity,1))}.bg-amber-400{--tw-bg-opacity:1;background-color:rgb(251 191 36/var(--tw-bg-opacity,1))}.bg-amber-500{--tw-bg-opacity:1;background-color:rgb(245 158 11/var(--tw-bg-opacity,1))}.bg-black\/20{background-color:rgba(0,0,0,.2)}.bg-black\/40{background-color:rgba(0,0,0,.4)}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(96 165 250/var(--tw-bg-opacity,1))}.bg-emerald-100{--tw-bg-opacity:1;background-color:rgb(209 250 229/var(--tw-bg-opacity,1))}.bg-emerald-400{--tw-bg-opacity:1;background-color:rgb(52 211 153/var(--tw-bg-opacity,1))}.bg-emerald-50{--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity,1))}.bg-emerald-50\/30{background-color:rgba(236,253,245,.3)}.bg-emerald-50\/90{background-color:rgba(236,253,245,.9)}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-emerald-600{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.bg-red-300{--tw-bg-opacity:1;background-color:rgb(252 165 165/var(--tw-bg-opacity,1))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-rose-300{--tw-bg-opacity:1;background-color:rgb(253 164 175/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.bg-violet-500{--tw-bg-opacity:1;background-color:rgb(139 92 246/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/90{background-color:hsla(0,0%,100%,.9)}.bg-white\/95{background-color:hsla(0,0%,100%,.95)}.bg-zinc-100{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.bg-zinc-200{--tw-bg-opacity:1;background-color:rgb(228 228 231/var(--tw-bg-opacity,1))}.bg-zinc-300{--tw-bg-opacity:1;background-color:rgb(212 212 216/var(--tw-bg-opacity,1))}.bg-zinc-400{--tw-bg-opacity:1;background-color:rgb(161 161 170/var(--tw-bg-opacity,1))}.bg-zinc-50{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.bg-zinc-50\/30{background-color:hsla(0,0%,98%,.3)}.bg-zinc-50\/50{background-color:hsla(0,0%,98%,.5)}.bg-zinc-50\/80{background-color:hsla(0,0%,98%,.8)}.bg-zinc-50\/95{background-color:hsla(0,0%,98%,.95)}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-6{padding:1.5rem}.p-\[18px_20px\]{padding:18px 20px}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-6{padding-bottom:1.5rem}.pl-3{padding-left:.75rem}.pr-1{padding-right:.25rem}.pr-3{padding-right:.75rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-\[20vh\]{padding-top:20vh}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:JetBrains Mono,Fira Code,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[7px\]{font-size:7px}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity,1))}.text-emerald-600{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.text-emerald-700{--tw-text-opacity:1;color:rgb(4 120 87/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-rose-400{--tw-text-opacity:1;color:rgb(251 113 133/var(--tw-text-opacity,1))}.text-rose-500{--tw-text-opacity:1;color:rgb(244 63 94/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-zinc-200{--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.text-zinc-300{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.text-zinc-500{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.text-zinc-700{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.text-zinc-800{--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1))}.text-zinc-900{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.placeholder-zinc-400::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(161 161 170/var(--tw-placeholder-opacity,1))}.placeholder-zinc-400::placeholder{--tw-placeholder-opacity:1;color:rgb(161 161 170/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.opacity-\[0\.03\]{opacity:.03}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.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)}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px 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{--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(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.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)}.ring-2{--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(2px + 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-emerald-400\/60{--tw-ring-color:rgba(52,211,153,.6)}.ring-zinc-100{--tw-ring-opacity:1;--tw-ring-color:rgb(244 244 245/var(--tw-ring-opacity,1))}.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)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[right\]{transition-property:right;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes fadeIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.animate-fade-in{animation:fadeIn .3s ease-out forwards}@keyframes pulseSoft{0%,to{opacity:1}50%{opacity:.6}}.animate-pulse-soft{animation:pulseSoft 2s ease-in-out infinite}@keyframes beadTooltipFade{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.description-markdown h1,.description-markdown h2,.description-markdown h3,.description-markdown h4{margin-top:.5rem;margin-bottom:.25rem;font-weight:600;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.description-markdown h1{font-size:.85rem}.description-markdown h2{font-size:.8rem}.description-markdown h3{font-size:.75rem}.description-markdown h4{font-size:.7rem}.description-markdown p{margin-bottom:.375rem}.description-markdown p:last-child{margin-bottom:0}.description-markdown ol,.description-markdown ul{margin-bottom:.375rem}.description-markdown ol>:not([hidden])~:not([hidden]),.description-markdown ul>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.description-markdown ol,.description-markdown ul{padding-left:1rem}.description-markdown ul{list-style-type:disc}.description-markdown ol{list-style-type:decimal}.description-markdown code{border-radius:.25rem;background-color:hsla(240,6%,90%,.6);padding:.125rem .25rem;font-family:JetBrains Mono,Fira Code,monospace;font-size:10px;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.description-markdown pre{margin-bottom:.375rem;overflow-x:auto;border-radius:.375rem;background-color:hsla(240,6%,90%,.6);padding:.5rem}.description-markdown pre code{background-color:transparent;padding:0;font-size:10px}.description-markdown a{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1));text-decoration-line:underline;text-underline-offset:2px}.description-markdown a:hover{--tw-text-opacity:1;color:rgb(4 120 87/var(--tw-text-opacity,1))}.description-markdown blockquote{margin-top:.375rem;margin-bottom:.375rem;border-left-width:2px;--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));padding-left:.5rem;font-style:italic;--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.description-markdown table{margin-bottom:.375rem;width:100%;border-collapse:collapse;font-size:10px}.description-markdown th{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding-bottom:.125rem;padding-right:.5rem;text-align:left;font-weight:600;--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.description-markdown td{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding-top:.125rem;padding-bottom:.125rem;padding-right:.5rem}.description-markdown hr{margin-top:.5rem;margin-bottom:.5rem;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.description-markdown strong{font-weight:600;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.description-markdown img{max-width:100%;border-radius:.25rem}.timeline-slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;cursor:pointer}.timeline-slider::-webkit-slider-runnable-track{height:4px;background:#e4e4e7;border-radius:2px}.timeline-slider::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;background:#10b981;border-radius:50%;margin-top:-4px;cursor:pointer;-webkit-transition:transform .1s ease;transition:transform .1s ease}.timeline-slider::-webkit-slider-thumb:hover{transform:scale(1.2)}.timeline-slider::-moz-range-track{height:4px;background:#e4e4e7;border-radius:2px;border:none}.timeline-slider::-moz-range-thumb{width:12px;height:12px;background:#10b981;border-radius:50%;border:none;cursor:pointer}.force-graph-container canvas{border-radius:.5rem;touch-action:none}.placeholder\:text-zinc-300::-moz-placeholder{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.placeholder\:text-zinc-300::placeholder{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.placeholder\:text-zinc-400::-moz-placeholder{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.placeholder\:text-zinc-400::placeholder{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.first\:mt-0:first-child{margin-top:0}.hover\:border-zinc-200:hover{--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.hover\:border-zinc-300:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.hover\:bg-emerald-100:hover{--tw-bg-opacity:1;background-color:rgb(209 250 229/var(--tw-bg-opacity,1))}.hover\:bg-emerald-200\/50:hover{background-color:rgba(167,243,208,.5)}.hover\:bg-emerald-50:hover{--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity,1))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.hover\:bg-emerald-700:hover{--tw-bg-opacity:1;background-color:rgb(4 120 87/var(--tw-bg-opacity,1))}.hover\:bg-red-50:hover{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.hover\:bg-zinc-100:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.hover\:bg-zinc-100\/50:hover{background-color:hsla(240,5%,96%,.5)}.hover\:bg-zinc-200\/60:hover{background-color:hsla(240,6%,90%,.6)}.hover\:bg-zinc-300\/40:hover{background-color:hsla(240,5%,84%,.4)}.hover\:bg-zinc-50:hover{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.hover\:bg-zinc-50\/50:hover{background-color:hsla(0,0%,98%,.5)}.hover\:bg-zinc-50\/60:hover{background-color:hsla(0,0%,98%,.6)}.hover\:text-emerald-600:hover{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.hover\:text-emerald-700:hover{--tw-text-opacity:1;color:rgb(4 120 87/var(--tw-text-opacity,1))}.hover\:text-red-400:hover{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.hover\:text-rose-500:hover{--tw-text-opacity:1;color:rgb(244 63 94/var(--tw-text-opacity,1))}.hover\:text-zinc-500:hover{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.hover\:text-zinc-600:hover{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.hover\:text-zinc-700:hover{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.hover\:text-zinc-900:hover{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:border-emerald-400:focus{--tw-border-opacity:1;border-color:rgb(52 211 153/var(--tw-border-opacity,1))}.focus\:border-emerald-500:focus{--tw-border-opacity:1;border-color:rgb(16 185 129/var(--tw-border-opacity,1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--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)}.focus\:ring-1:focus,.focus\:ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-2:focus{--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(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-emerald-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(16 185 129/var(--tw-ring-opacity,1))}.focus\:ring-emerald-500\/30:focus{--tw-ring-color:rgba(16,185,129,.3)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05;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))}.group:hover .group-hover\:text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity,1))}.group:hover .group-hover\:text-emerald-700{--tw-text-opacity:1;color:rgb(4 120 87/var(--tw-text-opacity,1))}.group:hover .group-hover\:text-zinc-700{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:left-4{left:1rem}.sm\:right-4{right:1rem}.sm\:top-4{top:1rem}.sm\:block{display:block}.sm\:inline-block{display:inline-block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:hidden{display:none}.sm\:gap-2{gap:.5rem}}@media (min-width:768px){.md\:flex{display:flex}.md\:hidden{display:none}}
|
package/app/page.tsx
CHANGED
|
@@ -191,6 +191,7 @@ export default function Home() {
|
|
|
191
191
|
const [selectedNode, setSelectedNode] = useState<GraphNode | null>(null);
|
|
192
192
|
const [hoveredNode, setHoveredNode] = useState<GraphNode | null>(null);
|
|
193
193
|
const [collapsedEpicIds, setCollapsedEpicIds] = useState<Set<string>>(new Set());
|
|
194
|
+
const [focusedEpicId, setFocusedEpicId] = useState<string | null>(null);
|
|
194
195
|
const [colorMode, setColorMode] = useState<ColorMode>("status");
|
|
195
196
|
const [projectName, setProjectName] = useState("Beads");
|
|
196
197
|
const [repoCount, setRepoCount] = useState(0);
|
|
@@ -252,16 +253,28 @@ export default function Home() {
|
|
|
252
253
|
const [helpPanelOpen, setHelpPanelOpen] = useState(false);
|
|
253
254
|
const [tutorialStep, setTutorialStep] = useState<number | null>(null);
|
|
254
255
|
|
|
256
|
+
// Set of node IDs in the local graph — used to filter global comments/activity
|
|
257
|
+
// to only events relevant to beads in this repo
|
|
258
|
+
const localNodeIds = useMemo(() => {
|
|
259
|
+
if (!data) return new Set<string>();
|
|
260
|
+
return new Set(data.graphData.nodes.map((n) => n.id));
|
|
261
|
+
}, [data]);
|
|
262
|
+
|
|
255
263
|
// Rebuild historical feed when data or comments change
|
|
264
|
+
// Filter comments to only those targeting nodes in our graph, since the
|
|
265
|
+
// Hypergoat indexer returns comments globally across all repos using beads
|
|
256
266
|
useEffect(() => {
|
|
257
267
|
if (!data) return;
|
|
268
|
+
const localComments = allComments
|
|
269
|
+
? allComments.filter((c) => localNodeIds.has(c.nodeId))
|
|
270
|
+
: null;
|
|
258
271
|
const historical = buildHistoricalFeed(
|
|
259
272
|
data.graphData.nodes,
|
|
260
273
|
data.graphData.links,
|
|
261
|
-
|
|
274
|
+
localComments
|
|
262
275
|
);
|
|
263
276
|
setActivityFeed((prev) => mergeFeedEvents(prev, historical));
|
|
264
|
-
}, [data, allComments]);
|
|
277
|
+
}, [data, allComments, localNodeIds]);
|
|
265
278
|
|
|
266
279
|
// Context menu state for right-click (phase 1: shows ContextMenu)
|
|
267
280
|
const [contextMenu, setContextMenu] = useState<{
|
|
@@ -583,6 +596,14 @@ export default function Home() {
|
|
|
583
596
|
setCollapsedEpicIds(new Set());
|
|
584
597
|
}, []);
|
|
585
598
|
|
|
599
|
+
const handleFocusEpic = useCallback((epicId: string) => {
|
|
600
|
+
setFocusedEpicId(epicId);
|
|
601
|
+
}, []);
|
|
602
|
+
|
|
603
|
+
const handleExitFocusedEpic = useCallback(() => {
|
|
604
|
+
setFocusedEpicId(null);
|
|
605
|
+
}, []);
|
|
606
|
+
|
|
586
607
|
// --- Tutorial callbacks ---
|
|
587
608
|
const handleStartTutorial = useCallback(() => {
|
|
588
609
|
setHelpPanelOpen(true);
|
|
@@ -1323,6 +1344,8 @@ export default function Home() {
|
|
|
1323
1344
|
collapsedEpicIds={collapsedEpicIds}
|
|
1324
1345
|
onCollapseAll={handleCollapseAll}
|
|
1325
1346
|
onExpandAll={handleExpandAll}
|
|
1347
|
+
focusedEpicId={focusedEpicId}
|
|
1348
|
+
onExitFocusedEpic={handleExitFocusedEpic}
|
|
1326
1349
|
colorMode={colorMode}
|
|
1327
1350
|
onColorModeChange={setColorMode}
|
|
1328
1351
|
autoFit={autoFit}
|
|
@@ -1429,6 +1452,23 @@ export default function Home() {
|
|
|
1429
1452
|
}
|
|
1430
1453
|
: undefined
|
|
1431
1454
|
}
|
|
1455
|
+
onFocusEpic={
|
|
1456
|
+
contextMenu.node.issueType === "epic" && !focusedEpicId
|
|
1457
|
+
? () => {
|
|
1458
|
+
handleFocusEpic(contextMenu.node.id);
|
|
1459
|
+
setContextMenu(null);
|
|
1460
|
+
}
|
|
1461
|
+
: undefined
|
|
1462
|
+
}
|
|
1463
|
+
onExitFocusEpic={
|
|
1464
|
+
contextMenu.node.issueType === "epic" &&
|
|
1465
|
+
focusedEpicId === contextMenu.node.id
|
|
1466
|
+
? () => {
|
|
1467
|
+
handleExitFocusedEpic();
|
|
1468
|
+
setContextMenu(null);
|
|
1469
|
+
}
|
|
1470
|
+
: undefined
|
|
1471
|
+
}
|
|
1432
1472
|
onClose={() => setContextMenu(null)}
|
|
1433
1473
|
/>
|
|
1434
1474
|
)}
|
|
@@ -1645,7 +1685,7 @@ export default function Home() {
|
|
|
1645
1685
|
<AllCommentsPanel
|
|
1646
1686
|
isOpen={allCommentsPanelOpen}
|
|
1647
1687
|
onClose={() => setAllCommentsPanelOpen(false)}
|
|
1648
|
-
allComments={allComments}
|
|
1688
|
+
allComments={allComments.filter((c) => localNodeIds.has(c.nodeId))}
|
|
1649
1689
|
onNodeNavigate={(nodeId) => {
|
|
1650
1690
|
handleNodeNavigate(nodeId);
|
|
1651
1691
|
setAllCommentsPanelOpen(false);
|
|
@@ -62,6 +62,10 @@ interface BeadsGraphProps {
|
|
|
62
62
|
showPulse?: boolean;
|
|
63
63
|
/** Callback to toggle pulse animation */
|
|
64
64
|
onShowPulseToggle?: () => void;
|
|
65
|
+
/** When set, only show this epic and its connected subgraph */
|
|
66
|
+
focusedEpicId?: string | null;
|
|
67
|
+
/** Callback to exit focused epic mode */
|
|
68
|
+
onExitFocusedEpic?: () => void;
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
// Node size calculation
|
|
@@ -254,6 +258,8 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
254
258
|
pulseNodeId,
|
|
255
259
|
showPulse = true,
|
|
256
260
|
onShowPulseToggle,
|
|
261
|
+
focusedEpicId,
|
|
262
|
+
onExitFocusedEpic,
|
|
257
263
|
}, ref) {
|
|
258
264
|
const graphRef = useRef<any>(null);
|
|
259
265
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
@@ -347,11 +353,64 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
347
353
|
// then removes child nodes and remaps their links to the parent epic.
|
|
348
354
|
// Must be declared BEFORE effects that reference viewNodes/viewLinks.
|
|
349
355
|
const { viewNodes, viewLinks } = useMemo(() => {
|
|
350
|
-
|
|
356
|
+
let currentNodes = nodes;
|
|
357
|
+
let currentLinks = links;
|
|
358
|
+
|
|
359
|
+
// === PHASE 1: Epic focus mode ===
|
|
360
|
+
// When focused on an epic, filter to only the epic's subgraph
|
|
361
|
+
if (focusedEpicId) {
|
|
362
|
+
// Build child->parent map
|
|
363
|
+
const childToParent = new Map<string, string>();
|
|
364
|
+
for (const link of currentLinks) {
|
|
365
|
+
const src = typeof link.source === "object" ? (link.source as any).id : link.source;
|
|
366
|
+
const tgt = typeof link.target === "object" ? (link.target as any).id : link.target;
|
|
367
|
+
if (link.type === "parent-child") {
|
|
368
|
+
childToParent.set(tgt, src);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const nodeIdSet = new Set(currentNodes.map((n) => n.id));
|
|
372
|
+
for (const node of currentNodes) {
|
|
373
|
+
if (!childToParent.has(node.id) && node.id.includes(".")) {
|
|
374
|
+
const parentId = node.id.split(".")[0];
|
|
375
|
+
if (nodeIdSet.has(parentId)) {
|
|
376
|
+
childToParent.set(node.id, parentId);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Collect epic + direct children
|
|
382
|
+
const subgraphIds = new Set<string>();
|
|
383
|
+
subgraphIds.add(focusedEpicId);
|
|
384
|
+
for (const [childId, parentId] of childToParent) {
|
|
385
|
+
if (parentId === focusedEpicId) {
|
|
386
|
+
subgraphIds.add(childId);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Add 1-hop neighbors connected via blocks/relates_to links
|
|
391
|
+
for (const link of currentLinks) {
|
|
392
|
+
const src = typeof link.source === "object" ? (link.source as any).id : link.source;
|
|
393
|
+
const tgt = typeof link.target === "object" ? (link.target as any).id : link.target;
|
|
394
|
+
if (link.type !== "parent-child") {
|
|
395
|
+
if (subgraphIds.has(src) && nodeIdSet.has(tgt)) subgraphIds.add(tgt);
|
|
396
|
+
if (subgraphIds.has(tgt) && nodeIdSet.has(src)) subgraphIds.add(src);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
currentNodes = currentNodes.filter((n) => subgraphIds.has(n.id));
|
|
401
|
+
currentLinks = currentLinks.filter((link) => {
|
|
402
|
+
const src = typeof link.source === "object" ? (link.source as any).id : link.source;
|
|
403
|
+
const tgt = typeof link.target === "object" ? (link.target as any).id : link.target;
|
|
404
|
+
return subgraphIds.has(src) && subgraphIds.has(tgt);
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// === PHASE 2: Collapse mode ===
|
|
409
|
+
if (!collapsedEpicIds || collapsedEpicIds.size === 0) return { viewNodes: currentNodes, viewLinks: currentLinks };
|
|
351
410
|
|
|
352
411
|
// Build child->parent map from parent-child links
|
|
353
412
|
const childToParent = new Map<string, string>();
|
|
354
|
-
for (const link of
|
|
413
|
+
for (const link of currentLinks) {
|
|
355
414
|
const src = typeof link.source === "object" ? (link.source as any).id : link.source;
|
|
356
415
|
const tgt = typeof link.target === "object" ? (link.target as any).id : link.target;
|
|
357
416
|
if (link.type === "parent-child") {
|
|
@@ -360,8 +419,8 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
360
419
|
}
|
|
361
420
|
}
|
|
362
421
|
// Fallback: infer from hierarchical IDs (e.g., "beads-map-3r3.1" -> parent "beads-map-3r3")
|
|
363
|
-
const nodeIds = new Set(
|
|
364
|
-
for (const node of
|
|
422
|
+
const nodeIds = new Set(currentNodes.map((n) => n.id));
|
|
423
|
+
for (const node of currentNodes) {
|
|
365
424
|
if (!childToParent.has(node.id) && node.id.includes(".")) {
|
|
366
425
|
const parentId = node.id.split(".")[0];
|
|
367
426
|
if (nodeIds.has(parentId)) {
|
|
@@ -378,7 +437,7 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
378
437
|
}
|
|
379
438
|
}
|
|
380
439
|
|
|
381
|
-
if (childIds.size === 0) return { viewNodes:
|
|
440
|
+
if (childIds.size === 0) return { viewNodes: currentNodes, viewLinks: currentLinks };
|
|
382
441
|
|
|
383
442
|
// Also build a filtered childToParent for only the collapsed children (for link remapping)
|
|
384
443
|
const collapsedChildToParent = new Map<string, string>();
|
|
@@ -392,7 +451,7 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
392
451
|
const extraDependentCount = new Map<string, number>();
|
|
393
452
|
for (const [childId, parentId] of collapsedChildToParent) {
|
|
394
453
|
collapsedCounts.set(parentId, (collapsedCounts.get(parentId) || 0) + 1);
|
|
395
|
-
const child =
|
|
454
|
+
const child = currentNodes.find((n) => n.id === childId);
|
|
396
455
|
if (child) {
|
|
397
456
|
extraBlockerCount.set(parentId, (extraBlockerCount.get(parentId) || 0) + child.blockerCount);
|
|
398
457
|
extraDependentCount.set(parentId, (extraDependentCount.get(parentId) || 0) + child.dependentCount);
|
|
@@ -400,7 +459,7 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
400
459
|
}
|
|
401
460
|
|
|
402
461
|
// Filter nodes: remove collapsed children, augment their parents
|
|
403
|
-
const filteredNodes: GraphNode[] =
|
|
462
|
+
const filteredNodes: GraphNode[] = currentNodes
|
|
404
463
|
.filter((n) => !childIds.has(n.id))
|
|
405
464
|
.map((n) => ({
|
|
406
465
|
...n,
|
|
@@ -412,7 +471,7 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
412
471
|
// Remap links: replace collapsed child IDs with parent IDs, drop internal parent-child links
|
|
413
472
|
const remappedLinks: GraphLink[] = [];
|
|
414
473
|
const linkSeen = new Set<string>();
|
|
415
|
-
for (const link of
|
|
474
|
+
for (const link of currentLinks) {
|
|
416
475
|
let src = typeof link.source === "object" ? (link.source as any).id : link.source;
|
|
417
476
|
let tgt = typeof link.target === "object" ? (link.target as any).id : link.target;
|
|
418
477
|
// Drop parent-child links where the child is collapsed
|
|
@@ -428,7 +487,7 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
428
487
|
}
|
|
429
488
|
|
|
430
489
|
return { viewNodes: filteredNodes, viewLinks: remappedLinks };
|
|
431
|
-
}, [nodes, links, collapsedEpicIds]);
|
|
490
|
+
}, [nodes, links, collapsedEpicIds, focusedEpicId]);
|
|
432
491
|
|
|
433
492
|
// Keep viewNodesRef in sync for mousemove avatar hit-testing
|
|
434
493
|
viewNodesRef.current = viewNodes;
|
|
@@ -897,6 +956,24 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
897
956
|
}
|
|
898
957
|
}, [nodes.length, timelineActive, autoFit]);
|
|
899
958
|
|
|
959
|
+
// Auto zoom-to-fit when entering/exiting epic focus mode (unconditional)
|
|
960
|
+
const prevFocusedEpicIdRef = useRef<string | null | undefined>(undefined);
|
|
961
|
+
useEffect(() => {
|
|
962
|
+
// Skip on mount (initial render)
|
|
963
|
+
if (prevFocusedEpicIdRef.current === undefined) {
|
|
964
|
+
prevFocusedEpicIdRef.current = focusedEpicId ?? null;
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
prevFocusedEpicIdRef.current = focusedEpicId ?? null;
|
|
968
|
+
const graph = graphRef.current;
|
|
969
|
+
if (!graph) return;
|
|
970
|
+
// Small delay to let the force graph process the new node set
|
|
971
|
+
const timer = setTimeout(() => {
|
|
972
|
+
graph.zoomToFit(400, 60);
|
|
973
|
+
}, 100);
|
|
974
|
+
return () => clearTimeout(timer);
|
|
975
|
+
}, [focusedEpicId]);
|
|
976
|
+
|
|
900
977
|
// Memoize graphData so the object reference stays stable across renders.
|
|
901
978
|
// This prevents react-force-graph from treating it as "new data" and
|
|
902
979
|
// re-heating the simulation on every hover/selection change.
|
|
@@ -1822,8 +1899,29 @@ const BeadsGraph = forwardRef<BeadsGraphHandle, BeadsGraphProps>(function BeadsG
|
|
|
1822
1899
|
|
|
1823
1900
|
return (
|
|
1824
1901
|
<div ref={containerRef} className="w-full h-full relative" data-tutorial="graph">
|
|
1825
|
-
{/* Top-left controls
|
|
1902
|
+
{/* Top-left controls */}
|
|
1826
1903
|
<div className="absolute top-3 left-3 sm:top-4 sm:left-4 z-10 flex flex-col gap-1.5 sm:gap-2">
|
|
1904
|
+
{/* Focus mode banner */}
|
|
1905
|
+
{focusedEpicId && onExitFocusedEpic && (
|
|
1906
|
+
<div className="flex items-center gap-2 px-3 py-1.5 text-xs font-medium bg-emerald-50/90 backdrop-blur-sm rounded-lg border border-emerald-200 shadow-sm text-emerald-700">
|
|
1907
|
+
<svg className="w-3.5 h-3.5 text-emerald-500 flex-shrink-0" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
|
|
1908
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M7.5 3.75H6A2.25 2.25 0 003.75 6v1.5M16.5 3.75H18A2.25 2.25 0 0120.25 6v1.5M16.5 20.25H18A2.25 2.25 0 0020.25 18v-1.5M7.5 20.25H6A2.25 2.25 0 013.75 18v-1.5" />
|
|
1909
|
+
</svg>
|
|
1910
|
+
<span className="truncate max-w-[180px]">
|
|
1911
|
+
Focused: <span className="font-semibold">{nodes.find((n) => n.id === focusedEpicId)?.title || focusedEpicId}</span>
|
|
1912
|
+
</span>
|
|
1913
|
+
<button
|
|
1914
|
+
onClick={onExitFocusedEpic}
|
|
1915
|
+
className="ml-auto p-0.5 rounded hover:bg-emerald-200/50 transition-colors flex-shrink-0"
|
|
1916
|
+
title="Show full graph"
|
|
1917
|
+
>
|
|
1918
|
+
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
|
|
1919
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
1920
|
+
</svg>
|
|
1921
|
+
</button>
|
|
1922
|
+
</div>
|
|
1923
|
+
)}
|
|
1924
|
+
|
|
1827
1925
|
{/* Row 1: Layout shape controls */}
|
|
1828
1926
|
<div className="flex items-start gap-1.5 sm:gap-2">
|
|
1829
1927
|
{/* Layout mode toggle */}
|
|
@@ -13,6 +13,8 @@ interface ContextMenuProps {
|
|
|
13
13
|
onUnclaimTask?: () => void;
|
|
14
14
|
onCollapseEpic?: () => void;
|
|
15
15
|
onUncollapseEpic?: () => void;
|
|
16
|
+
onFocusEpic?: () => void;
|
|
17
|
+
onExitFocusEpic?: () => void;
|
|
16
18
|
onClose: () => void;
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -26,6 +28,8 @@ export function ContextMenu({
|
|
|
26
28
|
onUnclaimTask,
|
|
27
29
|
onCollapseEpic,
|
|
28
30
|
onUncollapseEpic,
|
|
31
|
+
onFocusEpic,
|
|
32
|
+
onExitFocusEpic,
|
|
29
33
|
onClose,
|
|
30
34
|
}: ContextMenuProps) {
|
|
31
35
|
const menuRef = useRef<HTMLDivElement>(null);
|
|
@@ -119,7 +123,7 @@ export function ContextMenu({
|
|
|
119
123
|
)}
|
|
120
124
|
<button
|
|
121
125
|
onClick={onAddComment}
|
|
122
|
-
className={`w-full px-3 py-2.5 text-xs text-zinc-700 hover:bg-zinc-50 flex items-center gap-2 transition-colors${onClaimTask || onUnclaimTask || onCollapseEpic || onUncollapseEpic ? " border-b border-zinc-100" : ""}`}
|
|
126
|
+
className={`w-full px-3 py-2.5 text-xs text-zinc-700 hover:bg-zinc-50 flex items-center gap-2 transition-colors${onClaimTask || onUnclaimTask || onCollapseEpic || onUncollapseEpic || onFocusEpic || onExitFocusEpic ? " border-b border-zinc-100" : ""}`}
|
|
123
127
|
>
|
|
124
128
|
<svg
|
|
125
129
|
className="w-3.5 h-3.5 text-zinc-400"
|
|
@@ -139,7 +143,7 @@ export function ContextMenu({
|
|
|
139
143
|
{onClaimTask && (
|
|
140
144
|
<button
|
|
141
145
|
onClick={onClaimTask}
|
|
142
|
-
className={`w-full px-3 py-2.5 text-xs text-zinc-700 hover:bg-zinc-50 flex items-center gap-2 transition-colors${onCollapseEpic || onUncollapseEpic ? " border-b border-zinc-100" : ""}`}
|
|
146
|
+
className={`w-full px-3 py-2.5 text-xs text-zinc-700 hover:bg-zinc-50 flex items-center gap-2 transition-colors${onCollapseEpic || onUncollapseEpic || onFocusEpic || onExitFocusEpic ? " border-b border-zinc-100" : ""}`}
|
|
143
147
|
>
|
|
144
148
|
<svg
|
|
145
149
|
className="w-3.5 h-3.5 text-zinc-400"
|
|
@@ -160,7 +164,7 @@ export function ContextMenu({
|
|
|
160
164
|
{onUnclaimTask && (
|
|
161
165
|
<button
|
|
162
166
|
onClick={onUnclaimTask}
|
|
163
|
-
className={`w-full px-3 py-2.5 text-xs text-red-500 hover:bg-red-50 flex items-center gap-2 transition-colors${onCollapseEpic || onUncollapseEpic ? " border-b border-zinc-100" : ""}`}
|
|
167
|
+
className={`w-full px-3 py-2.5 text-xs text-red-500 hover:bg-red-50 flex items-center gap-2 transition-colors${onCollapseEpic || onUncollapseEpic || onFocusEpic || onExitFocusEpic ? " border-b border-zinc-100" : ""}`}
|
|
164
168
|
>
|
|
165
169
|
<svg
|
|
166
170
|
className="w-3.5 h-3.5 text-red-400"
|
|
@@ -181,7 +185,7 @@ export function ContextMenu({
|
|
|
181
185
|
{onCollapseEpic && (
|
|
182
186
|
<button
|
|
183
187
|
onClick={onCollapseEpic}
|
|
184
|
-
className=
|
|
188
|
+
className={`w-full px-3 py-2.5 text-xs text-zinc-700 hover:bg-zinc-50 flex items-center gap-2 transition-colors${onFocusEpic || onExitFocusEpic ? " border-b border-zinc-100" : ""}`}
|
|
185
189
|
>
|
|
186
190
|
<svg
|
|
187
191
|
className="w-3.5 h-3.5 text-zinc-400"
|
|
@@ -202,7 +206,7 @@ export function ContextMenu({
|
|
|
202
206
|
{onUncollapseEpic && (
|
|
203
207
|
<button
|
|
204
208
|
onClick={onUncollapseEpic}
|
|
205
|
-
className=
|
|
209
|
+
className={`w-full px-3 py-2.5 text-xs text-zinc-700 hover:bg-zinc-50 flex items-center gap-2 transition-colors${onFocusEpic || onExitFocusEpic ? " border-b border-zinc-100" : ""}`}
|
|
206
210
|
>
|
|
207
211
|
<svg
|
|
208
212
|
className="w-3.5 h-3.5 text-zinc-400"
|
|
@@ -220,6 +224,48 @@ export function ContextMenu({
|
|
|
220
224
|
Uncollapse epic
|
|
221
225
|
</button>
|
|
222
226
|
)}
|
|
227
|
+
{onFocusEpic && (
|
|
228
|
+
<button
|
|
229
|
+
onClick={onFocusEpic}
|
|
230
|
+
className="w-full px-3 py-2.5 text-xs text-zinc-700 hover:bg-zinc-50 flex items-center gap-2 transition-colors"
|
|
231
|
+
>
|
|
232
|
+
<svg
|
|
233
|
+
className="w-3.5 h-3.5 text-zinc-400"
|
|
234
|
+
fill="none"
|
|
235
|
+
viewBox="0 0 24 24"
|
|
236
|
+
strokeWidth={1.5}
|
|
237
|
+
stroke="currentColor"
|
|
238
|
+
>
|
|
239
|
+
<path
|
|
240
|
+
strokeLinecap="round"
|
|
241
|
+
strokeLinejoin="round"
|
|
242
|
+
d="M7.5 3.75H6A2.25 2.25 0 003.75 6v1.5M16.5 3.75H18A2.25 2.25 0 0120.25 6v1.5M16.5 20.25H18A2.25 2.25 0 0020.25 18v-1.5M7.5 20.25H6A2.25 2.25 0 013.75 18v-1.5"
|
|
243
|
+
/>
|
|
244
|
+
</svg>
|
|
245
|
+
Focus on epic
|
|
246
|
+
</button>
|
|
247
|
+
)}
|
|
248
|
+
{onExitFocusEpic && (
|
|
249
|
+
<button
|
|
250
|
+
onClick={onExitFocusEpic}
|
|
251
|
+
className="w-full px-3 py-2.5 text-xs text-emerald-600 hover:bg-emerald-50 flex items-center gap-2 transition-colors"
|
|
252
|
+
>
|
|
253
|
+
<svg
|
|
254
|
+
className="w-3.5 h-3.5 text-emerald-500"
|
|
255
|
+
fill="none"
|
|
256
|
+
viewBox="0 0 24 24"
|
|
257
|
+
strokeWidth={1.5}
|
|
258
|
+
stroke="currentColor"
|
|
259
|
+
>
|
|
260
|
+
<path
|
|
261
|
+
strokeLinecap="round"
|
|
262
|
+
strokeLinejoin="round"
|
|
263
|
+
d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
|
|
264
|
+
/>
|
|
265
|
+
</svg>
|
|
266
|
+
Show full graph
|
|
267
|
+
</button>
|
|
268
|
+
)}
|
|
223
269
|
</div>
|
|
224
270
|
</div>
|
|
225
271
|
);
|