@kazurolabs/psql-explorer 0.3.0 → 0.3.1
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/RELEASES.md +8 -0
- package/dist/explorer/explain.js +29 -12
- package/dist/explorer/rows.js +79 -6
- package/dist/explorer/session.js +8 -1
- package/dist/web/server.js +2 -2
- package/package.json +2 -1
- package/web/dist/assets/{button-ClA70PLR.js → button-BiFx4Lyw.js} +1 -1
- package/web/dist/assets/{code-xml-CXkpHeU9.js → code-xml-CPEjNFOw.js} +1 -1
- package/web/dist/assets/{compare-view-DKl5l_Jw.js → compare-view-COQ3yE76.js} +1 -1
- package/web/dist/assets/{copy-CCXzeW-s.js → copy-C2N9tUYJ.js} +1 -1
- package/web/dist/assets/{cypher-view-Pd0WFH8F.js → cypher-view-BzyL4mNU.js} +1 -1
- package/web/dist/assets/{design-view-CIHSmH4u.js → design-view-BPm7dSTY.js} +1 -1
- package/web/dist/assets/{erd-view-CV7mFGAN.js → erd-view-DqGDws2_.js} +1 -1
- package/web/dist/assets/{format-sql-BLj5_RDZ.js → format-sql-CoddYUOF.js} +1 -1
- package/web/dist/assets/{graph-force-yBLyErpS.js → graph-force-ChCGXQUt.js} +1 -1
- package/web/dist/assets/{graph-link-OCo_s0zO.js → graph-link-C8P9s_0W.js} +1 -1
- package/web/dist/assets/{graph-view-sM1OlByf.js → graph-view-BpoUrUCP.js} +1 -1
- package/web/dist/assets/{index-CDcnUacl.js → index-CpHnjRLv.js} +3 -3
- package/web/dist/assets/{key-round-Cv_7QeED.js → key-round-JiGCgCWS.js} +1 -1
- package/web/dist/assets/{loader-circle-BK_GMdvN.js → loader-circle-BxDJOoJO.js} +1 -1
- package/web/dist/assets/{query-builder-view-ChNFb51g.js → query-builder-view-CtRexMEX.js} +1 -1
- package/web/dist/assets/{rotate-ccw-CdCaf7Q6.js → rotate-ccw-CwdA-J3t.js} +1 -1
- package/web/dist/assets/{route-DO6IZ7of.js → route-7eu-iAqD.js} +1 -1
- package/web/dist/assets/{seed-view-DFNB8WHE.js → seed-view-BIkBTiU6.js} +1 -1
- package/web/dist/assets/{shield-alert-CMS-3j4U.js → shield-alert-keJIAND5.js} +1 -1
- package/web/dist/assets/{sliders-horizontal-Dg51yc-C.js → sliders-horizontal-DKtL_ql7.js} +1 -1
- package/web/dist/assets/sql-tabs-DUSXdYCr.js +2 -0
- package/web/dist/assets/{table-DfMz2f8M.js → table-Drc_n1gF.js} +1 -1
- package/web/dist/assets/{triangle-alert-COGnHCD1.js → triangle-alert-C5nF69rW.js} +1 -1
- package/web/dist/assets/{zone-D9dXk8tn.js → zone-CHDOrDBF.js} +1 -1
- package/web/dist/index.html +8 -8
- package/web/dist/assets/sql-tabs-B4jt6bQj.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{at as e,ct as t,o as n,ot as r,rt as i}from"./route-DO6IZ7of.js";import{t as a,z as o}from"./button-ClA70PLR.js";import{l as s}from"./zone-D9dXk8tn.js";import{a as c,i as l,n as u,o as d,r as f,t as p}from"./table-DfMz2f8M.js";var m={name:`chart-column`,size:24,node:[[`path`,{d:`M3 3v16a2 2 0 0 0 2 2h16`,key:`c24i48`}],[`path`,{d:`M18 17V9`,key:`2bz60n`}],[`path`,{d:`M13 17V5`,key:`1frdt8`}],[`path`,{d:`M8 17v-3`,key:`17ska0`}]],aliases:[`bar-chart-3`]};m.node;var h=e(m),g={name:`image-down`,size:24,node:[[`path`,{d:`M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10l-3.1-3.1a2 2 0 0 0-2.814.014L6 21`,key:`9csbqa`}],[`path`,{d:`m14 19 3 3v-5.5`,key:`9ldu5r`}],[`path`,{d:`m17 22 3-3`,key:`1nkfve`}],[`circle`,{cx:`9`,cy:`9`,r:`2`,key:`af1f0g`}]]};g.node;var _=e(g),v={name:`waypoints`,size:24,node:[[`path`,{d:`m10.586 5.414-5.172 5.172`,key:`4mc350`}],[`path`,{d:`m18.586 13.414-5.172 5.172`,key:`8c96vv`}],[`path`,{d:`M6 12h12`,key:`8npq4p`}],[`circle`,{cx:`12`,cy:`20`,r:`2`,key:`144qzu`}],[`circle`,{cx:`12`,cy:`4`,r:`2`,key:`muu5ef`}],[`circle`,{cx:`20`,cy:`12`,r:`2`,key:`1xzzfp`}],[`circle`,{cx:`4`,cy:`12`,r:`2`,key:`1hvhnz`}]]};v.node;var y=e(v),b=t(r(),1),x=/^(smallint|integer|bigint|numeric|decimal|real|double precision|oid|money)/,S=/^(date|timestamp|time)/,C=e=>x.test(e),w=e=>S.test(e);function T(e){if(e===null||e.trim()===``)return;let t=Number(e.replace(/^\$/,``).replaceAll(`,`,``));return Number.isFinite(t)?t:void 0}function E(e){if(e===null)return;let t=e.replace(/(\d:\d\d(?::\d\d(?:\.\d+)?)?)([+-]\d\d)$/,`$1$2:00`),n=Date.parse(/^\d{4}-\d\d-\d\d \d/.test(t)?t.replace(` `,`T`):t);return Number.isFinite(n)?n:void 0}function D(e,t){return w(t)?E(e):T(e)}var O=[`count`,`sum`,`avg`,`min`,`max`];function k({column:e,aggregate:t}){return t===`count`&&!e?`count`:`${t}(${e})`}function A(e,t,n){let r=t=>{let n=e.columns.findIndex(e=>e.name===t);if(n<0)throw Error(`no column "${t}"`);return n},i=t.map(r),a=new Map;for(let t of e.rows){let e=i.map(e=>t[e]??null),n=JSON.stringify(e),r=a.get(n);r?r.rows.push(t):a.set(n,{key:e,rows:[t]})}return{columns:[...t.map((t,n)=>({name:t,type:e.columns[i[n]].type})),...n.map(e=>({name:k(e),type:`double precision`}))],rows:[...a.values()].map(({key:e,rows:t})=>[...e,...n.map(({column:e,aggregate:n})=>{if(n===`count`&&!e)return String(t.length);let i=r(e),a=t.flatMap(e=>T(e[i]??null)??[]);return n===`count`?String(t.filter(e=>e[i]!==null).length):a.length===0?null:String(n===`sum`?a.reduce((e,t)=>e+t,0):n===`avg`?a.reduce((e,t)=>e+t,0)/a.length:n===`min`?Math.min(...a):Math.max(...a))})])}}function j(e){return e.columns.map((t,n)=>{let r=e.rows.map(e=>e[n]??null),i=r.filter(e=>e!==null),a={name:t.name,type:t.type,count:r.length,nulls:r.length-i.length,distinct:new Set(i).size,min:null,max:null};if(C(t.type)){let e=i.flatMap(e=>T(e)??[]).sort((e,t)=>e-t);if(e.length>0){let t=e.reduce((e,t)=>e+t,0),n=t/e.length,r=Math.floor(e.length/2);a.min=String(e[0]),a.max=String(e[e.length-1]),a.sum=t,a.mean=n,a.median=e.length%2?e[r]:(e[r-1]+e[r])/2,a.stddev=Math.sqrt(e.reduce((e,t)=>e+(t-n)**2,0)/e.length)}}else if(i.length>0){let e=[...i].sort();a.min=e[0],a.max=e[e.length-1]}return a})}var M=[{id:`bar`,label:`Bar`},{id:`line`,label:`Line`},{id:`area`,label:`Area`},{id:`scatter`,label:`Scatter`},{id:`radar`,label:`Radar (spider web)`},{id:`pie`,label:`Pie`},{id:`donut`,label:`Donut`}],N=e=>e===`radar`||e===`pie`||e===`donut`,ee=[`none`,`hour`,`day`,`week`,`month`,`year`],P=864e5;function F(e,t){let n=new Date(e),r=n.getUTCFullYear(),i=n.getUTCMonth(),a;switch(t){case`hour`:a=Math.floor(e/36e5)*36e5;break;case`day`:a=Math.floor(e/P)*P;break;case`week`:{let t=Math.floor(e/P)*P;a=t-(new Date(t).getUTCDay()+6)%7*P;break}case`month`:a=Date.UTC(r,i,1);break;case`year`:a=Date.UTC(r,0,1)}let o=new Date(a).toISOString(),s=t===`hour`?o.slice(0,13).replace(`T`,` `)+`:00`:t===`month`?o.slice(0,7):t===`year`?o.slice(0,4):o.slice(0,10);return{start:a,label:s}}function te(e,t,n,r,i={}){let a=t=>{let n=e.columns.findIndex(e=>e.name===t);if(n<0)throw Error(`no column "${t}"`);return n},o=a(n),s=e.columns[o].type,c=C(s)||w(s),l=i.bucket&&i.bucket!==`none`&&w(s)?i.bucket:void 0,u=(t===`line`||t===`area`||t===`scatter`)&&c&&!l;if(t===`scatter`&&!c)throw Error(`a scatter chart needs a number or time for x`);let d=i.group&&r.length>0?a(i.group):-1,f=[],p=0;if(d>=0){let t=a(r[0]),n=new Set;for(let t of e.rows)n.add(t[d]??null);for(let e of n)f.length>=8?p++:f.push({name:e??`NULL`,at:t,group:e})}else for(let e of r)f.push({name:e,at:a(e)});let m=0,h=new Map,g=f.map(()=>new Map),_=f.map(()=>[]);if(f.forEach((t,n)=>{for(let r of e.rows){if(t.group!==void 0&&(r[d]??null)!==t.group)continue;let e=T(r[t.at]??null),i=r[o]??null;if(e===void 0){m++;continue}if(u){let t=D(i,s);if(t===void 0){m++;continue}_[n].push({x:t,y:e,label:i??``});continue}let a=i??`NULL`,c=h.size;if(l){let e=E(i);if(e===void 0){m++;continue}let t=F(e,l);a=t.label,c=t.start}if(!h.has(a)){if(h.size>=60){p++;continue}h.set(a,c)}g[n].set(a,(g[n].get(a)??0)+e)}}),u)return{kind:t,series:f.map((e,t)=>({name:e.name,points:_[t].sort((e,t)=>e.x-t.x)})),xIsTime:w(s),skipped:m,clipped:p};let v=[...h.keys()];return l&&v.sort((e,t)=>h.get(e)-h.get(t)),{kind:t,series:f.map((e,t)=>({name:e.name,points:v.flatMap((e,n)=>g[t].has(e)?[{x:n,y:g[t].get(e),label:e}]:[])})),categories:v,xIsTime:!1,skipped:m,clipped:p}}function I(e,t,n=5){if(!(t>e))return[e];let r=(t-e)/Math.max(n,1),i=10**Math.floor(Math.log10(r)),a=[1,2,5,10].map(e=>e*i).find(e=>e>=r),o=[];for(let n=Math.ceil(e/a)*a;n<=t+a*1e-9;n+=a)o.push(Number(n.toPrecision(12)));return o}function L(e){let t=Math.abs(e);return t>=1e9?`${+(e/1e9).toPrecision(3)}B`:t>=1e6?`${+(e/1e6).toPrecision(3)}M`:t>=1e4?`${+(e/1e3).toPrecision(3)}k`:String(Number.isInteger(e)?e:+e.toPrecision(3))}function ne(e,t){let n=new Date(e).toISOString();return t>=1728e5?n.slice(0,10):n.slice(0,16).replace(`T`,` `)}var R=i(),z={colors:[`#0ea5e9`,`#14b8a6`,`#6366f1`,`#f59e0b`,`#f43f5e`],ink:`#111827`,muted:`#6b7280`,paper:`#ffffff`,border:`#e5e7eb`,bodyFont:`ui-sans-serif, system-ui, sans-serif`,headingFont:`ui-sans-serif, system-ui, sans-serif`,radius:10,glow:0};function B(){let e=getComputedStyle(document.documentElement),t=(t,n)=>e.getPropertyValue(t).trim()||n,n=t(`--radius`,`0.625rem`),r=parseFloat(getComputedStyle(document.documentElement).fontSize)||16,i=n.endsWith(`rem`)?parseFloat(n)*r:parseFloat(n);return{colors:[1,2,3,4,5].map(e=>t(`--chart-${e}`,z.colors[e-1])),ink:t(`--foreground`,z.ink),muted:t(`--muted-foreground`,z.muted),paper:t(`--background`,z.paper),border:t(`--border`,z.border),bodyFont:t(`--body-font`,z.bodyFont),headingFont:t(`--heading-font`,z.headingFont),radius:Number.isFinite(i)?i:z.radius,glow:parseFloat(t(`--chart-glow`,`0`))||0}}function re(){let[e,t]=(0,b.useState)(B);return(0,b.useEffect)(()=>{let e=()=>t(B());e();let n=new MutationObserver(e);return n.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`,`class`]}),()=>n.disconnect()},[]),e}function V(e,t){let n=e.colors.length,r=e.colors[t%n],i=Math.floor(t/n);return i===0?r:`color-mix(in oklab, ${r} ${i===1?62:40}%, ${e.ink})`}var H=(e,t)=>e.length>t?`${e.slice(0,t-1)}…`:e;function ie(e,t,n,r,i,a){let o=Math.max(0,Math.min(i,n/2,r));return a?`M${e} ${t+r}V${t+o}Q${e} ${t} ${e+o} ${t}H${e+n-o}Q${e+n} ${t} ${e+n} ${t+o}V${t+r}Z`:`M${e} ${t}V${t+r-o}Q${e} ${t+r} ${e+o} ${t+r}H${e+n-o}Q${e+n} ${t+r} ${e+n} ${t+r-o}V${t}Z`}function ae(e){let t=e.length;if(t===0)return``;if(t<3)return e.map((e,t)=>`${t?`L`:`M`}${e.x.toFixed(1)} ${e.y.toFixed(1)}`).join(``);let n=[],r=[];for(let i=0;i<t-1;i++)n.push(e[i+1].x-e[i].x),r.push(n[i]===0?0:(e[i+1].y-e[i].y)/n[i]);let i=[r[0]];for(let e=1;e<t-1;e++)i.push(r[e-1]*r[e]<=0?0:(r[e-1]+r[e])/2);i.push(r[t-2]);for(let e=0;e<t-1;e++){if(r[e]===0){i[e]=0,i[e+1]=0;continue}let t=i[e]/r[e],n=i[e+1]/r[e],a=t*t+n*n;if(a>9){let o=3/Math.sqrt(a);i[e]=o*t*r[e],i[e+1]=o*n*r[e]}}let a=`M${e[0].x.toFixed(1)} ${e[0].y.toFixed(1)}`;for(let r=0;r<t-1;r++){let t=e[r],o=e[r+1],s=n[r]/3;a+=`C${(t.x+s).toFixed(1)} ${(t.y+i[r]*s).toFixed(1)} ${(o.x-s).toFixed(1)} ${(o.y-i[r+1]*s).toFixed(1)} ${o.x.toFixed(1)} ${o.y.toFixed(1)}`}return a}var U=(e,t,n,r)=>({x:e+n*Math.cos(r),y:t+n*Math.sin(r)});function oe(e,t,n,r,i,a){if(a-i>=Math.PI*2-1e-6){let i=n=>`M${e-n} ${t}a${n} ${n} 0 1 0 ${2*n} 0a${n} ${n} 0 1 0 ${-2*n} 0Z`;return i(n)+(r>0?i(r):``)}let o=+(a-i>Math.PI),s=U(e,t,n,i),c=U(e,t,n,a),l=`M${s.x.toFixed(2)} ${s.y.toFixed(2)}A${n} ${n} 0 ${o} 1 ${c.x.toFixed(2)} ${c.y.toFixed(2)}`;if(r<=0)return`${l}L${e} ${t}Z`;let u=U(e,t,r,a),d=U(e,t,r,i);return`${l}L${u.x.toFixed(2)} ${u.y.toFixed(2)}A${r} ${r} 0 ${o} 0 ${d.x.toFixed(2)} ${d.y.toFixed(2)}Z`}function W({names:e,theme:t,y:n,glow:r}){let i=56;return(0,R.jsx)(`g`,{children:e.map((e,a)=>{let o=i;return i+=30+Math.min(e.length,24)*7,(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`circle`,{cx:o+5,cy:n-4,r:5,fill:V(t,a),filter:r}),(0,R.jsx)(`text`,{x:o+16,y:n,fontSize:11,fill:t.ink,children:H(e,24)})]},e)})})}function G({theme:e,children:t}){return(0,R.jsx)(`text`,{x:360,y:210,fontSize:13,textAnchor:`middle`,fill:e.muted,children:t})}function K({chart:e,theme:t,glow:n,top:r,bottomSpace:i}){let a=e.kind===`donut`,o=e.categories??[],s=e.series[0],c=(s?.points??[]).filter(e=>e.y>0).map(e=>({label:o[e.x]??e.label,value:e.y})).sort((e,t)=>t.value-e.value);if(c.length>12){let e=c.slice(11);c=[...c.slice(0,11),{label:`Other (${e.length})`,value:e.reduce((e,t)=>e+t.value,0)}]}let l=c.reduce((e,t)=>e+t.value,0);if(l<=0)return(0,R.jsx)(G,{theme:t,children:`Nothing to draw: pick a column that holds positive numbers.`});let u=420-r-i,d=Math.min(u/2-4,150),f=56+d+8,p=r+u/2,m=a?d*.62:0,h=f+d+44,g=Math.min(24,u/c.length),_=p-c.length*g/2,v=-Math.PI/2;return(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`g`,{filter:n,children:c.map((e,n)=>{let r=v,i=e.value/l*Math.PI*2;v+=i;let o=r+i/2,s=U(f,p,a?(d+m)/2:d*.66,o);return(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`path`,{d:oe(f,p,d,m,r,r+i),fill:V(t,n),fillRule:`evenodd`,stroke:t.paper,strokeWidth:2,strokeLinejoin:`round`,children:(0,R.jsx)(`title`,{children:`${e.label}: ${e.value} (${(e.value/l*100).toFixed(1)}%)`})}),i>.4&&(0,R.jsxs)(`text`,{x:s.x,y:s.y+4,fontSize:11,fontWeight:600,textAnchor:`middle`,fill:t.paper,children:[Math.round(e.value/l*100),`%`]})]},n)})}),a&&(0,R.jsxs)(`g`,{textAnchor:`middle`,children:[(0,R.jsx)(`text`,{x:f,y:p+4,fontSize:22,fontWeight:600,fontFamily:t.headingFont,fill:t.ink,children:L(l)}),(0,R.jsx)(`text`,{x:f,y:p+22,fontSize:10,letterSpacing:.8,fill:t.muted,children:H(s?.name??`total`,18)})]}),c.map((e,r)=>(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`circle`,{cx:h+5,cy:_+r*g+g/2,r:5,fill:V(t,r),filter:n}),(0,R.jsx)(`text`,{x:h+18,y:_+r*g+g/2+4,fontSize:11,fill:t.ink,children:H(e.label,22)}),(0,R.jsxs)(`text`,{x:696,y:_+r*g+g/2+4,fontSize:11,textAnchor:`end`,fill:t.muted,children:[L(e.value),` ·`,` `,(e.value/l*100).toFixed(+(e.value/l<.1)),`%`]})]},r))]})}function se({chart:e,theme:t,glow:n,top:r,bottomSpace:i}){let a=e.categories??[],o=a.length,s=e.series.map(e=>{let t=new Map(e.points.map(e=>[e.x,Math.max(e.y,0)]));return a.map((e,n)=>t.get(n)??0)}),c=Math.max(0,...s.flat());if(o<3||c<=0)return(0,R.jsx)(G,{theme:t,children:o<3?`A radar chart needs at least three categories.`:`Nothing to draw: pick columns that hold positive numbers.`});let l=I(0,c,4).filter(e=>e>0),u=l[l.length-1],d=420-r-i,f=Math.min(d/2-26,260),p=r+d/2,m=e=>-Math.PI/2+e/o*Math.PI*2,h=e=>a.map((t,n)=>{let r=U(360,p,f*e,m(n));return`${n?`L`:`M`}${r.x.toFixed(1)} ${r.y.toFixed(1)}`}).join(``)+`Z`;return(0,R.jsxs)(`g`,{children:[l.map(e=>(0,R.jsx)(`path`,{d:h(e/u),fill:`none`,stroke:t.muted,strokeOpacity:.28,strokeLinejoin:`round`},e)),a.map((e,n)=>{let r=U(360,p,f,m(n)),i=U(360,p,f+20,m(n)),a=Math.cos(m(n));return(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`line`,{x1:360,y1:p,x2:r.x,y2:r.y,stroke:t.muted,strokeOpacity:.2}),(0,R.jsx)(`text`,{x:i.x,y:i.y+(Math.sin(m(n))>.5?8:Math.sin(m(n))<-.5?-4:4),fontSize:11,textAnchor:a>.3?`start`:a<-.3?`end`:`middle`,fill:t.ink,children:H(e,14)})]},n)}),l.map(e=>(0,R.jsx)(`text`,{x:364,y:p-e/u*f-3,fontSize:9,fill:t.muted,children:L(e)},e)),e.series.map((r,i)=>{let o=V(t,i),c=s[i].map((e,t)=>U(360,p,f*e/u,m(t))),l=c.map((e,t)=>`${t?`L`:`M`}${e.x.toFixed(1)} ${e.y.toFixed(1)}`).join(``)+`Z`;return(0,R.jsxs)(`g`,{filter:n,children:[(0,R.jsx)(`path`,{d:l,fill:o,fillOpacity:.2,stroke:o,strokeWidth:2.5,strokeLinejoin:`round`}),c.map((n,c)=>(0,R.jsx)(`circle`,{cx:n.x,cy:n.y,r:3.5,fill:t.paper,stroke:o,strokeWidth:2,children:(0,R.jsx)(`title`,{children:`${a[c]}: ${s[i][c]}${e.series.length>1?` (${r.name})`:``}`})},c))]},r.name)})]})}function ce({chart:e,text:t,theme:n,uid:r,glow:i,top:a,bottomSpace:o}){let{series:s,categories:c,kind:l}=e,u=s.length>1,d=!!c&&c.length>8,f=d?56:28,p=f+(t.xLabel?22:0)+o,m=420-a-p,h=Math.min(Math.max(n.radius*.6,0),8),g=s.flatMap(e=>e.points),_=g.map(e=>e.x),v=g.map(e=>e.y),y=g.length===0,b=y?0:Math.min(...v),x=y?1:Math.max(...v);(l===`bar`||l===`area`)&&(b=Math.min(b,0),x=Math.max(x,0)),x===b&&(x=b+1);let S=I(b,x,5),C=Math.min(b,S[0]),w=Math.max(x,S[S.length-1]),T=e=>a+m-(e-C)/(w-C)*m,E,D,O=c?.length??0;if(c){let e=640/Math.max(O,1);E=t=>56+e*(t+.5);let t=Math.max(1,Math.ceil(O/Math.max(Math.floor(640/(d?18:70)),1)));D=c.flatMap((e,n)=>n%t===0?[{at:E(n),label:H(e,d?16:10)}]:[])}else{let t=y?0:Math.min(..._),n=y?1:Math.max(..._);n===t&&(--t,n+=1),E=e=>56+(e-t)/(n-t)*640,D=e.xIsTime?[0,1,2,3,4].map(e=>{let r=t+(n-t)*e/4;return{at:E(r),label:ne(r,n-t)}}):I(t,n,6).map(e=>({at:E(e),label:L(e)}))}let k=c?640/Math.max(O,1):0,A=c?Math.min(k*.72/s.length,44):0,j=a+m,M=l===`bar`||l===`area`?T(0):j,N=j+(d?14:20);return(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`defs`,{children:s.map((e,t)=>(0,R.jsxs)(`g`,{children:[(0,R.jsxs)(`linearGradient`,{id:`${r}bar${t}`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,R.jsx)(`stop`,{offset:`0`,stopColor:V(n,t),stopOpacity:1}),(0,R.jsx)(`stop`,{offset:`1`,stopColor:V(n,t),stopOpacity:.45})]}),(0,R.jsxs)(`linearGradient`,{id:`${r}area${t}`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,R.jsx)(`stop`,{offset:`0`,stopColor:V(n,t),stopOpacity:l===`area`?.5:.28}),(0,R.jsx)(`stop`,{offset:`1`,stopColor:V(n,t),stopOpacity:0})]})]},t))}),S.map(e=>(0,R.jsx)(`text`,{x:46,y:T(e)+4,fontSize:11,textAnchor:`end`,fill:n.muted,children:L(e)},e)),(0,R.jsx)(`line`,{x1:56,x2:696,y1:M,y2:M,stroke:n.muted,strokeOpacity:.6}),D.map((e,t)=>(0,R.jsx)(`text`,{x:e.at,y:N,fontSize:11,fill:n.muted,textAnchor:d||e.at>690?`end`:`middle`,transform:d?`rotate(-40 ${e.at} ${N})`:void 0,children:e.label},t)),t.yLabel&&(0,R.jsx)(`text`,{transform:`translate(16 ${a+m/2}) rotate(-90)`,fontSize:11,letterSpacing:.6,textAnchor:`middle`,fill:n.muted,children:t.yLabel}),y&&(0,R.jsx)(`text`,{x:376,y:a+m/2,fontSize:13,textAnchor:`middle`,fill:n.muted,children:`Nothing to draw: pick columns that hold numbers.`}),s.map((e,t)=>{let a=V(n,t);if(l===`bar`)return(0,R.jsx)(`g`,{filter:i,children:e.points.map((n,i)=>{let o=Math.max(A-3,2),c=E(n.x)-A*s.length/2+A*t+1.5,l=Math.min(T(n.y),T(0)),d=Math.max(Math.abs(T(n.y)-T(0)),1);return(0,R.jsx)(`path`,{d:ie(c,l,o,d,h,n.y>=0),fill:`url(#${r}bar${t})`,stroke:a,strokeOpacity:.9,strokeWidth:1,children:(0,R.jsx)(`title`,{children:`${n.label}: ${n.y}${u?` (${e.name})`:``}`})},i)})},e.name);let o=e.points.map(e=>({x:E(e.x),y:T(e.y)})),c=ae(o);return(0,R.jsxs)(`g`,{children:[(l===`line`||l===`area`)&&o.length>1&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`path`,{d:`${c}L${o[o.length-1].x.toFixed(1)} ${M}L${o[0].x.toFixed(1)} ${M}Z`,fill:`url(#${r}area${t})`}),(0,R.jsx)(`path`,{d:c,fill:`none`,stroke:a,strokeWidth:2.5,strokeLinejoin:`round`,strokeLinecap:`round`,filter:i})]}),(l===`scatter`||l===`line`&&e.points.length<=60||l===`area`&&e.points.length<=24)&&(0,R.jsx)(`g`,{filter:i,children:e.points.map((t,r)=>(0,R.jsx)(`circle`,{cx:o[r].x,cy:o[r].y,r:l===`scatter`?5:3.5,fill:l===`scatter`?a:n.paper,fillOpacity:l===`scatter`?.8:1,stroke:a,strokeWidth:l===`scatter`?1.5:2,children:(0,R.jsx)(`title`,{children:`${t.label}: ${t.y}${u?` (${e.name})`:``}`})},r))})]},e.name)}),t.xLabel&&(0,R.jsx)(`text`,{x:376,y:j+f+14,fontSize:11,letterSpacing:.6,textAnchor:`middle`,fill:n.muted,children:t.xLabel})]})}var le=(0,b.forwardRef)(function({chart:e,text:t},n){let r=re(),i=(0,b.useId)().replace(/[^a-zA-Z0-9]/g,``),{kind:a,series:o}=e,s=o.length>1&&a!==`pie`&&a!==`donut`,c=t.title?56:28,l=(s?26:0)+(t.caption?26:0)+8,u=Math.min(r.radius,18),d=r.glow>0?`url(#${i}glow)`:void 0,f={chart:e,text:t,theme:r,uid:i,glow:d,top:c,bottomSpace:l};return(0,R.jsxs)(`svg`,{ref:n,xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 720 420`,width:720,height:420,role:`img`,"aria-label":t.title||`Chart`,fontFamily:r.bodyFont,style:{maxWidth:`100%`,height:`auto`,display:`block`,position:`relative`,zIndex:51},children:[(0,R.jsx)(`defs`,{children:r.glow>0&&(0,R.jsxs)(`filter`,{id:`${i}glow`,x:`-20%`,y:`-20%`,width:`140%`,height:`140%`,children:[(0,R.jsx)(`feGaussianBlur`,{in:`SourceGraphic`,stdDeviation:r.glow/2,result:`blur`}),(0,R.jsxs)(`feMerge`,{children:[(0,R.jsx)(`feMergeNode`,{in:`blur`}),(0,R.jsx)(`feMergeNode`,{in:`SourceGraphic`})]})]})}),(0,R.jsx)(`rect`,{x:.5,y:.5,width:719,height:419,rx:u,fill:r.paper,stroke:r.border,strokeOpacity:.55}),t.title&&(0,R.jsx)(`text`,{x:56,y:34,fontSize:18,fontFamily:r.headingFont,fontWeight:600,fill:r.ink,letterSpacing:.3,children:H(t.title,70)}),a===`pie`||a===`donut`?(0,R.jsx)(K,{...f}):a===`radar`?(0,R.jsx)(se,{...f}):(0,R.jsx)(ce,{...f}),s&&(0,R.jsx)(W,{names:o.map(e=>e.name),theme:r,y:406-(t.caption?24:0),glow:d}),t.caption&&(0,R.jsx)(`text`,{x:56,y:406,fontSize:11,fontStyle:`italic`,fill:r.muted,children:H(t.caption,110)})]})}),ue=`http://www.w3.org/2000/svg`;function q(e){let t=e.cloneNode(!0);return t.setAttribute(`xmlns`,ue),t.removeAttribute(`style`),`<?xml version="1.0" encoding="UTF-8"?>\n${new XMLSerializer().serializeToString(t)}\n`}function de(e,t=2){return J(q(e),e.viewBox.baseVal.width,e.viewBox.baseVal.height,t)}function J(e,t,n,r=2){let i=URL.createObjectURL(new Blob([e],{type:`image/svg+xml;charset=utf-8`}));return new Promise((e,a)=>{let o=new Image;o.onload=()=>{let s=document.createElement(`canvas`);s.width=t*r,s.height=n*r;let c=s.getContext(`2d`);c?(c.drawImage(o,0,0,s.width,s.height),URL.revokeObjectURL(i),s.toBlob(t=>t?e(t):a(Error(`The image could not be made`)),`image/png`)):a(Error(`This browser cannot draw the image`))},o.onerror=()=>{URL.revokeObjectURL(i),a(Error(`The chart could not be turned into an image`))},o.src=i})}function Y(e,t){let n=URL.createObjectURL(e),r=document.createElement(`a`);r.href=n,r.download=t,document.body.append(r),r.click(),r.remove(),URL.revokeObjectURL(n)}var X=(e,t)=>e.trim().toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,60)||t,Z=`border-input bg-background rounded-lg border px-2 py-1 text-sm`;function Q({label:e,children:t}){return(0,R.jsxs)(`label`,{className:`flex flex-col gap-1 text-xs`,children:[(0,R.jsx)(`span`,{className:`text-muted-foreground`,children:e}),t]})}function fe({data:e,filename:t}){let n=e.columns.filter(e=>C(e.type)),[r,i]=(0,b.useState)(()=>e.columns[0]&&w(e.columns[0].type)?`line`:`bar`),[c,l]=(0,b.useState)(e.columns[0]?.name??``),[u,d]=(0,b.useState)(``),[f,p]=(0,b.useState)(`none`),[m,h]=(0,b.useState)(()=>{let t=n.find(t=>t.name!==e.columns[0]?.name)??n[0];return t?[t.name]:[]}),[g,v]=(0,b.useState)({title:``,caption:``,xLabel:``,yLabel:``}),[y,x]=(0,b.useState)(),[S,T]=(0,b.useState)(),E=(0,b.useRef)(null),D=e.columns.find(e=>e.name===c)?.type??``,O=(0,b.useMemo)(()=>{try{let t=u&&u!==c&&!m.includes(u)&&r!==`pie`&&r!==`donut`;return{chart:te(e,r,c,m,{group:t?u:void 0,bucket:f})}}catch(e){return{error:e instanceof Error?e.message:String(e)}}},[e,r,c,m,u,f]),k=e=>v({...g,...e}),A=e=>h(m.includes(e)?m.filter(t=>t!==e):[...m,e].slice(-5)),j=async e=>{if(E.current){x(void 0);try{let n=`${X(g.title,t)}.${e}`;Y(e===`svg`?new Blob([q(E.current)],{type:`image/svg+xml`}):await de(E.current),n),T(e),window.setTimeout(()=>T(void 0),1500)}catch(e){x(e instanceof Error?e.message:String(e))}}};return(0,R.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,R.jsxs)(`div`,{className:`flex flex-wrap items-end gap-3`,children:[(0,R.jsx)(Q,{label:`Chart`,children:(0,R.jsx)(`select`,{"aria-label":`Chart type`,value:r,onChange:e=>i(e.target.value),className:Z,children:M.map(e=>(0,R.jsx)(`option`,{value:e.id,children:e.label},e.id))})}),(0,R.jsx)(Q,{label:`X axis`,children:(0,R.jsx)(`select`,{"aria-label":`X column`,value:c,onChange:e=>l(e.target.value),className:Z,children:e.columns.map(e=>(0,R.jsx)(`option`,{children:e.name},e.name))})}),w(D)&&r!==`scatter`&&(0,R.jsx)(Q,{label:`Group times by`,children:(0,R.jsx)(`select`,{"aria-label":`Time step`,value:f,onChange:e=>p(e.target.value),className:Z,children:ee.map(e=>(0,R.jsx)(`option`,{value:e,children:e===`none`?`as they are`:e},e))})}),r!==`pie`&&r!==`donut`&&(0,R.jsx)(Q,{label:`Colour by group`,children:(0,R.jsxs)(`select`,{"aria-label":`Group column`,value:u,onChange:e=>d(e.target.value),className:Z,children:[(0,R.jsx)(`option`,{value:``,children:`no groups`}),e.columns.filter(e=>e.name!==c).map(e=>(0,R.jsx)(`option`,{children:e.name},e.name))]})}),(0,R.jsxs)(`fieldset`,{className:`flex flex-col gap-1 text-xs`,children:[(0,R.jsx)(`legend`,{className:`text-muted-foreground mb-1`,children:r===`pie`||r===`donut`||u?`Y axis (first number is used)`:`Y axis (numbers)`}),(0,R.jsxs)(`div`,{className:`flex flex-wrap gap-x-3 gap-y-1`,children:[n.length===0&&(0,R.jsx)(`span`,{className:`text-muted-foreground`,children:`no numeric columns`}),n.map(e=>(0,R.jsxs)(`label`,{className:`flex items-center gap-1 text-sm`,children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:m.includes(e.name),onChange:()=>A(e.name)}),e.name]},e.name))]})]})]}),(0,R.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,R.jsx)(Q,{label:`Title`,children:(0,R.jsx)(`input`,{"aria-label":`Chart title`,value:g.title,onChange:e=>k({title:e.target.value}),className:Z})}),(0,R.jsx)(Q,{label:`Caption`,children:(0,R.jsx)(`input`,{"aria-label":`Chart caption`,value:g.caption,onChange:e=>k({caption:e.target.value}),placeholder:`Source, date, notes`,className:Z})}),!N(r)&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(Q,{label:`X axis label`,children:(0,R.jsx)(`input`,{"aria-label":`X axis label`,value:g.xLabel,onChange:e=>k({xLabel:e.target.value}),placeholder:c,className:Z})}),(0,R.jsx)(Q,{label:`Y axis label`,children:(0,R.jsx)(`input`,{"aria-label":`Y axis label`,value:g.yLabel,onChange:e=>k({yLabel:e.target.value}),placeholder:m.join(`, `),className:Z})})]})]}),O.error?(0,R.jsx)(`p`,{className:`text-destructive text-sm`,children:O.error}):(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`div`,{className:`max-w-full overflow-x-auto`,children:(0,R.jsx)(le,{ref:E,chart:O.chart,text:g})}),(O.chart.skipped>0||O.chart.clipped>0)&&(0,R.jsxs)(`p`,{className:`text-muted-foreground text-xs`,role:`status`,children:[O.chart.skipped>0&&`${O.chart.skipped.toLocaleString()} values left out because they are not numbers. `,O.chart.clipped>0&&`Only the first categories are drawn; group the result to see fewer.`]})]}),(0,R.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,R.jsxs)(a,{variant:`outline`,size:`sm`,disabled:!!O.error,onClick:()=>j(`png`),children:[S===`png`?(0,R.jsx)(o,{}):(0,R.jsx)(_,{}),` Save PNG`]}),(0,R.jsxs)(a,{variant:`outline`,size:`sm`,disabled:!!O.error,onClick:()=>j(`svg`),children:[S===`svg`?(0,R.jsx)(o,{}):(0,R.jsx)(s,{}),` Save SVG`]}),y&&(0,R.jsx)(`span`,{role:`status`,className:`text-destructive text-xs`,children:y})]})]})}function pe({data:e,onGrouped:t}){let[n,r]=(0,b.useState)([]),[i,o]=(0,b.useState)(``),[s,m]=(0,b.useState)(`count`),h=e.columns.filter(e=>C(e.type)),g={column:s===`count`?``:i||h[0]?.name||``,aggregate:s},_=(0,b.useMemo)(()=>{try{return A(e,n,[g])}catch{return}},[e,n,s,i]),v=s!==`count`&&!g.column;return(0,R.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,R.jsxs)(`div`,{className:`flex flex-wrap items-end gap-3`,children:[(0,R.jsxs)(`fieldset`,{className:`flex flex-col gap-1 text-xs`,children:[(0,R.jsx)(`legend`,{className:`text-muted-foreground mb-1`,children:`Group by`}),(0,R.jsx)(`div`,{className:`flex flex-wrap gap-x-3 gap-y-1`,children:e.columns.map(e=>(0,R.jsxs)(`label`,{className:`flex items-center gap-1 text-sm`,children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:n.includes(e.name),onChange:()=>r(n.includes(e.name)?n.filter(t=>t!==e.name):[...n,e.name])}),e.name]},e.name))})]}),(0,R.jsx)(Q,{label:`Measure`,children:(0,R.jsx)(`select`,{"aria-label":`Aggregate`,value:s,onChange:e=>m(e.target.value),className:Z,children:O.map(e=>(0,R.jsx)(`option`,{children:e},e))})}),s!==`count`&&(0,R.jsx)(Q,{label:`of`,children:(0,R.jsx)(`select`,{"aria-label":`Aggregate column`,value:g.column,onChange:e=>o(e.target.value),className:Z,children:h.map(e=>(0,R.jsx)(`option`,{children:e.name},e.name))})}),(0,R.jsx)(a,{size:`sm`,disabled:v||!_,onClick:()=>t(_),children:`Use for the chart`}),(0,R.jsx)(a,{variant:`outline`,size:`sm`,onClick:()=>t(void 0),children:`Chart the result`})]}),v?(0,R.jsxs)(`p`,{className:`text-muted-foreground text-sm`,children:[`There is no numeric column to `,s,`.`]}):_&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`p`,{className:`text-muted-foreground text-xs`,children:[_.rows.length.toLocaleString(),` groups: `,k(g),n.length>0&&` by ${n.join(`, `)}`]}),(0,R.jsx)(`div`,{className:`max-h-72 overflow-auto`,children:(0,R.jsxs)(p,{children:[(0,R.jsx)(c,{children:(0,R.jsx)(d,{children:_.columns.map(e=>(0,R.jsx)(l,{children:e.name},e.name))})}),(0,R.jsx)(u,{children:_.rows.slice(0,200).map((e,t)=>(0,R.jsx)(d,{children:e.map((e,t)=>(0,R.jsx)(f,{children:e===null?(0,R.jsx)(`span`,{className:`text-muted-foreground italic`,children:`NULL`}):e},t))},t))})]})})]})]})}function me({data:e}){let t=(0,b.useMemo)(()=>j(e),[e]),n=e=>e===void 0?``:L(e);return(0,R.jsx)(`div`,{className:`overflow-x-auto`,children:(0,R.jsxs)(p,{children:[(0,R.jsx)(c,{children:(0,R.jsx)(d,{children:[`column`,`rows`,`nulls`,`distinct`,`min`,`max`,`mean`,`median`,`sum`,`std dev`].map(e=>(0,R.jsx)(l,{children:e},e))})}),(0,R.jsx)(u,{children:t.map(e=>(0,R.jsxs)(d,{children:[(0,R.jsx)(f,{title:e.type,children:e.name}),(0,R.jsx)(f,{children:e.count.toLocaleString()}),(0,R.jsx)(f,{children:e.nulls.toLocaleString()}),(0,R.jsx)(f,{children:e.distinct.toLocaleString()}),(0,R.jsx)(f,{children:(0,R.jsx)(`span`,{className:`block max-w-40 truncate`,title:e.min??``,children:e.min??``})}),(0,R.jsx)(f,{children:(0,R.jsx)(`span`,{className:`block max-w-40 truncate`,title:e.max??``,children:e.max??``})}),(0,R.jsx)(f,{children:n(e.mean)}),(0,R.jsx)(f,{children:n(e.median)}),(0,R.jsx)(f,{children:n(e.sum)}),(0,R.jsx)(f,{children:n(e.stddev)})]},e.name))})]})})}function he({data:e,fetchAll:t,filename:n}){let[r,i]=(0,b.useState)(!1),[a,o]=(0,b.useState)(`chart`),[s,c]=(0,b.useState)(),[l,u]=(0,b.useState)(!1),[d,f]=(0,b.useState)(!1),[p,m]=(0,b.useState)(),[g,_]=(0,b.useState)(),v=l&&s?s:e,y=async e=>{if(m(void 0),_(void 0),e&&!s){f(!0);try{c(await t())}catch(e){m(e instanceof Error?e.message:String(e)),f(!1);return}f(!1)}u(e)};return e.columns.length>0&&e.rows.length>0?(0,R.jsxs)(`section`,{className:`mb-3`,"aria-label":`Analyze the result`,children:[(0,R.jsxs)(`button`,{type:`button`,onClick:()=>i(!r),"aria-expanded":r,className:`text-muted-foreground hover:text-foreground flex items-center gap-1 text-xs`,children:[(0,R.jsx)(h,{className:`size-4`}),` `,r?`Hide`:`Chart and analyze`]}),r&&(0,R.jsxs)(`div`,{className:`border-input bg-card mt-2 flex flex-col gap-3 border p-3`,children:[(0,R.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 text-xs`,children:[(0,R.jsx)(`div`,{role:`tablist`,className:`flex gap-1`,children:[[`chart`,`Chart`],[`group`,`Group by`],[`stats`,`Column stats`]].map(([e,t])=>(0,R.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":a===e,onClick:()=>o(e),className:`rounded-lg px-2.5 py-1 text-sm ${a===e?`bg-secondary text-secondary-foreground`:`text-muted-foreground hover:text-foreground`}`,children:t},e))}),(0,R.jsx)(`span`,{className:`text-muted-foreground ml-auto`,children:`Rows`}),(0,R.jsxs)(`select`,{"aria-label":`Rows to analyze`,value:l?`all`:`page`,disabled:d,onChange:e=>void y(e.target.value===`all`),className:Z,children:[(0,R.jsxs)(`option`,{value:`page`,children:[`this page (`,e.rows.length.toLocaleString(),`)`]}),(0,R.jsxs)(`option`,{value:`all`,children:[`all rows`,s?` (${s.rows.length.toLocaleString()}${s.truncated?`+`:``})`:``]})]}),d&&(0,R.jsx)(`span`,{role:`status`,children:`Reading...`})]}),p&&(0,R.jsx)(`p`,{className:`text-destructive text-sm`,children:p}),a===`chart`&&(0,R.jsxs)(R.Fragment,{children:[g&&(0,R.jsxs)(`p`,{className:`text-muted-foreground text-xs`,children:[`Charting the grouping (`,g.columns.map(e=>e.name).join(`, `),`).`]}),(0,R.jsx)(fe,{data:g??v,filename:n},`${l}-${g?g.columns.map(e=>e.name).join(`|`):`rows`}-${v.rows.length}`)]}),a===`group`&&(0,R.jsx)(pe,{data:v,onGrouped:e=>{_(e),o(`chart`)}}),a===`stats`&&(0,R.jsx)(me,{data:v})]})]}):null}function ge(e,t){let n=e.filter(e=>e.primaryKey);return(n.length>0?n:e.filter(e=>e.type!==`json`&&e.type!==`xml`)).map(({name:e})=>{let n=t[e];return n==null?{column:e,op:`null`}:{column:e,op:`eq`,value:n}})}function $(e,t,r){return n({environment:e,graph:{schema:t.schema,table:t.name,keys:r}})}function _e(e,t,r){return n({environment:e,graph:{schema:t.schema,table:t.name,filters:r}})}function ve(e,t,n){let r=new Set(t.map(e=>e.name)),i=e=>{let t=e.columns.filter(e=>e.primaryKey);return t.length>0&&t.every(e=>r.has(e.name))},a=e.filter((t,n)=>e.findIndex(e=>e.schema===t.schema&&e.name===t.name)===n),o=n.filter(e=>!a.some(t=>t.schema===e.schema&&t.name===e.name));return[...a,...o].filter(i)}function ye(e,t,n){let r=e.columns.filter(e=>e.primaryKey).map(e=>t.findIndex(t=>t.name===e.name)),i=new Set,a=[];for(let e of n){let t=r.map(t=>e[t]??null);if(t.some(e=>e===null))continue;let n=t,o=JSON.stringify(n);i.has(o)||(i.add(o),a.push(n))}return a}export{ge as a,Y as c,h as d,ye as i,J as l,$ as n,he as o,ve as r,X as s,_e as t,y as u};
|
|
1
|
+
import{at as e,ct as t,o as n,ot as r,rt as i}from"./route-7eu-iAqD.js";import{t as a,z as o}from"./button-BiFx4Lyw.js";import{l as s}from"./zone-CHDOrDBF.js";import{a as c,i as l,n as u,o as d,r as f,t as p}from"./table-Drc_n1gF.js";var m={name:`chart-column`,size:24,node:[[`path`,{d:`M3 3v16a2 2 0 0 0 2 2h16`,key:`c24i48`}],[`path`,{d:`M18 17V9`,key:`2bz60n`}],[`path`,{d:`M13 17V5`,key:`1frdt8`}],[`path`,{d:`M8 17v-3`,key:`17ska0`}]],aliases:[`bar-chart-3`]};m.node;var h=e(m),g={name:`image-down`,size:24,node:[[`path`,{d:`M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10l-3.1-3.1a2 2 0 0 0-2.814.014L6 21`,key:`9csbqa`}],[`path`,{d:`m14 19 3 3v-5.5`,key:`9ldu5r`}],[`path`,{d:`m17 22 3-3`,key:`1nkfve`}],[`circle`,{cx:`9`,cy:`9`,r:`2`,key:`af1f0g`}]]};g.node;var _=e(g),v={name:`waypoints`,size:24,node:[[`path`,{d:`m10.586 5.414-5.172 5.172`,key:`4mc350`}],[`path`,{d:`m18.586 13.414-5.172 5.172`,key:`8c96vv`}],[`path`,{d:`M6 12h12`,key:`8npq4p`}],[`circle`,{cx:`12`,cy:`20`,r:`2`,key:`144qzu`}],[`circle`,{cx:`12`,cy:`4`,r:`2`,key:`muu5ef`}],[`circle`,{cx:`20`,cy:`12`,r:`2`,key:`1xzzfp`}],[`circle`,{cx:`4`,cy:`12`,r:`2`,key:`1hvhnz`}]]};v.node;var y=e(v),b=t(r(),1),x=/^(smallint|integer|bigint|numeric|decimal|real|double precision|oid|money)/,S=/^(date|timestamp|time)/,C=e=>x.test(e),w=e=>S.test(e);function T(e){if(e===null||e.trim()===``)return;let t=Number(e.replace(/^\$/,``).replaceAll(`,`,``));return Number.isFinite(t)?t:void 0}function E(e){if(e===null)return;let t=e.replace(/(\d:\d\d(?::\d\d(?:\.\d+)?)?)([+-]\d\d)$/,`$1$2:00`),n=Date.parse(/^\d{4}-\d\d-\d\d \d/.test(t)?t.replace(` `,`T`):t);return Number.isFinite(n)?n:void 0}function D(e,t){return w(t)?E(e):T(e)}var O=[`count`,`sum`,`avg`,`min`,`max`];function k({column:e,aggregate:t}){return t===`count`&&!e?`count`:`${t}(${e})`}function A(e,t,n){let r=t=>{let n=e.columns.findIndex(e=>e.name===t);if(n<0)throw Error(`no column "${t}"`);return n},i=t.map(r),a=new Map;for(let t of e.rows){let e=i.map(e=>t[e]??null),n=JSON.stringify(e),r=a.get(n);r?r.rows.push(t):a.set(n,{key:e,rows:[t]})}return{columns:[...t.map((t,n)=>({name:t,type:e.columns[i[n]].type})),...n.map(e=>({name:k(e),type:`double precision`}))],rows:[...a.values()].map(({key:e,rows:t})=>[...e,...n.map(({column:e,aggregate:n})=>{if(n===`count`&&!e)return String(t.length);let i=r(e),a=t.flatMap(e=>T(e[i]??null)??[]);return n===`count`?String(t.filter(e=>e[i]!==null).length):a.length===0?null:String(n===`sum`?a.reduce((e,t)=>e+t,0):n===`avg`?a.reduce((e,t)=>e+t,0)/a.length:n===`min`?Math.min(...a):Math.max(...a))})])}}function j(e){return e.columns.map((t,n)=>{let r=e.rows.map(e=>e[n]??null),i=r.filter(e=>e!==null),a={name:t.name,type:t.type,count:r.length,nulls:r.length-i.length,distinct:new Set(i).size,min:null,max:null};if(C(t.type)){let e=i.flatMap(e=>T(e)??[]).sort((e,t)=>e-t);if(e.length>0){let t=e.reduce((e,t)=>e+t,0),n=t/e.length,r=Math.floor(e.length/2);a.min=String(e[0]),a.max=String(e[e.length-1]),a.sum=t,a.mean=n,a.median=e.length%2?e[r]:(e[r-1]+e[r])/2,a.stddev=Math.sqrt(e.reduce((e,t)=>e+(t-n)**2,0)/e.length)}}else if(i.length>0){let e=[...i].sort();a.min=e[0],a.max=e[e.length-1]}return a})}var M=[{id:`bar`,label:`Bar`},{id:`line`,label:`Line`},{id:`area`,label:`Area`},{id:`scatter`,label:`Scatter`},{id:`radar`,label:`Radar (spider web)`},{id:`pie`,label:`Pie`},{id:`donut`,label:`Donut`}],N=e=>e===`radar`||e===`pie`||e===`donut`,ee=[`none`,`hour`,`day`,`week`,`month`,`year`],P=864e5;function F(e,t){let n=new Date(e),r=n.getUTCFullYear(),i=n.getUTCMonth(),a;switch(t){case`hour`:a=Math.floor(e/36e5)*36e5;break;case`day`:a=Math.floor(e/P)*P;break;case`week`:{let t=Math.floor(e/P)*P;a=t-(new Date(t).getUTCDay()+6)%7*P;break}case`month`:a=Date.UTC(r,i,1);break;case`year`:a=Date.UTC(r,0,1)}let o=new Date(a).toISOString(),s=t===`hour`?o.slice(0,13).replace(`T`,` `)+`:00`:t===`month`?o.slice(0,7):t===`year`?o.slice(0,4):o.slice(0,10);return{start:a,label:s}}function te(e,t,n,r,i={}){let a=t=>{let n=e.columns.findIndex(e=>e.name===t);if(n<0)throw Error(`no column "${t}"`);return n},o=a(n),s=e.columns[o].type,c=C(s)||w(s),l=i.bucket&&i.bucket!==`none`&&w(s)?i.bucket:void 0,u=(t===`line`||t===`area`||t===`scatter`)&&c&&!l;if(t===`scatter`&&!c)throw Error(`a scatter chart needs a number or time for x`);let d=i.group&&r.length>0?a(i.group):-1,f=[],p=0;if(d>=0){let t=a(r[0]),n=new Set;for(let t of e.rows)n.add(t[d]??null);for(let e of n)f.length>=8?p++:f.push({name:e??`NULL`,at:t,group:e})}else for(let e of r)f.push({name:e,at:a(e)});let m=0,h=new Map,g=f.map(()=>new Map),_=f.map(()=>[]);if(f.forEach((t,n)=>{for(let r of e.rows){if(t.group!==void 0&&(r[d]??null)!==t.group)continue;let e=T(r[t.at]??null),i=r[o]??null;if(e===void 0){m++;continue}if(u){let t=D(i,s);if(t===void 0){m++;continue}_[n].push({x:t,y:e,label:i??``});continue}let a=i??`NULL`,c=h.size;if(l){let e=E(i);if(e===void 0){m++;continue}let t=F(e,l);a=t.label,c=t.start}if(!h.has(a)){if(h.size>=60){p++;continue}h.set(a,c)}g[n].set(a,(g[n].get(a)??0)+e)}}),u)return{kind:t,series:f.map((e,t)=>({name:e.name,points:_[t].sort((e,t)=>e.x-t.x)})),xIsTime:w(s),skipped:m,clipped:p};let v=[...h.keys()];return l&&v.sort((e,t)=>h.get(e)-h.get(t)),{kind:t,series:f.map((e,t)=>({name:e.name,points:v.flatMap((e,n)=>g[t].has(e)?[{x:n,y:g[t].get(e),label:e}]:[])})),categories:v,xIsTime:!1,skipped:m,clipped:p}}function I(e,t,n=5){if(!(t>e))return[e];let r=(t-e)/Math.max(n,1),i=10**Math.floor(Math.log10(r)),a=[1,2,5,10].map(e=>e*i).find(e=>e>=r),o=[];for(let n=Math.ceil(e/a)*a;n<=t+a*1e-9;n+=a)o.push(Number(n.toPrecision(12)));return o}function L(e){let t=Math.abs(e);return t>=1e9?`${+(e/1e9).toPrecision(3)}B`:t>=1e6?`${+(e/1e6).toPrecision(3)}M`:t>=1e4?`${+(e/1e3).toPrecision(3)}k`:String(Number.isInteger(e)?e:+e.toPrecision(3))}function ne(e,t){let n=new Date(e).toISOString();return t>=1728e5?n.slice(0,10):n.slice(0,16).replace(`T`,` `)}var R=i(),z={colors:[`#0ea5e9`,`#14b8a6`,`#6366f1`,`#f59e0b`,`#f43f5e`],ink:`#111827`,muted:`#6b7280`,paper:`#ffffff`,border:`#e5e7eb`,bodyFont:`ui-sans-serif, system-ui, sans-serif`,headingFont:`ui-sans-serif, system-ui, sans-serif`,radius:10,glow:0};function B(){let e=getComputedStyle(document.documentElement),t=(t,n)=>e.getPropertyValue(t).trim()||n,n=t(`--radius`,`0.625rem`),r=parseFloat(getComputedStyle(document.documentElement).fontSize)||16,i=n.endsWith(`rem`)?parseFloat(n)*r:parseFloat(n);return{colors:[1,2,3,4,5].map(e=>t(`--chart-${e}`,z.colors[e-1])),ink:t(`--foreground`,z.ink),muted:t(`--muted-foreground`,z.muted),paper:t(`--background`,z.paper),border:t(`--border`,z.border),bodyFont:t(`--body-font`,z.bodyFont),headingFont:t(`--heading-font`,z.headingFont),radius:Number.isFinite(i)?i:z.radius,glow:parseFloat(t(`--chart-glow`,`0`))||0}}function re(){let[e,t]=(0,b.useState)(B);return(0,b.useEffect)(()=>{let e=()=>t(B());e();let n=new MutationObserver(e);return n.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`,`class`]}),()=>n.disconnect()},[]),e}function V(e,t){let n=e.colors.length,r=e.colors[t%n],i=Math.floor(t/n);return i===0?r:`color-mix(in oklab, ${r} ${i===1?62:40}%, ${e.ink})`}var H=(e,t)=>e.length>t?`${e.slice(0,t-1)}…`:e;function ie(e,t,n,r,i,a){let o=Math.max(0,Math.min(i,n/2,r));return a?`M${e} ${t+r}V${t+o}Q${e} ${t} ${e+o} ${t}H${e+n-o}Q${e+n} ${t} ${e+n} ${t+o}V${t+r}Z`:`M${e} ${t}V${t+r-o}Q${e} ${t+r} ${e+o} ${t+r}H${e+n-o}Q${e+n} ${t+r} ${e+n} ${t+r-o}V${t}Z`}function ae(e){let t=e.length;if(t===0)return``;if(t<3)return e.map((e,t)=>`${t?`L`:`M`}${e.x.toFixed(1)} ${e.y.toFixed(1)}`).join(``);let n=[],r=[];for(let i=0;i<t-1;i++)n.push(e[i+1].x-e[i].x),r.push(n[i]===0?0:(e[i+1].y-e[i].y)/n[i]);let i=[r[0]];for(let e=1;e<t-1;e++)i.push(r[e-1]*r[e]<=0?0:(r[e-1]+r[e])/2);i.push(r[t-2]);for(let e=0;e<t-1;e++){if(r[e]===0){i[e]=0,i[e+1]=0;continue}let t=i[e]/r[e],n=i[e+1]/r[e],a=t*t+n*n;if(a>9){let o=3/Math.sqrt(a);i[e]=o*t*r[e],i[e+1]=o*n*r[e]}}let a=`M${e[0].x.toFixed(1)} ${e[0].y.toFixed(1)}`;for(let r=0;r<t-1;r++){let t=e[r],o=e[r+1],s=n[r]/3;a+=`C${(t.x+s).toFixed(1)} ${(t.y+i[r]*s).toFixed(1)} ${(o.x-s).toFixed(1)} ${(o.y-i[r+1]*s).toFixed(1)} ${o.x.toFixed(1)} ${o.y.toFixed(1)}`}return a}var U=(e,t,n,r)=>({x:e+n*Math.cos(r),y:t+n*Math.sin(r)});function oe(e,t,n,r,i,a){if(a-i>=Math.PI*2-1e-6){let i=n=>`M${e-n} ${t}a${n} ${n} 0 1 0 ${2*n} 0a${n} ${n} 0 1 0 ${-2*n} 0Z`;return i(n)+(r>0?i(r):``)}let o=+(a-i>Math.PI),s=U(e,t,n,i),c=U(e,t,n,a),l=`M${s.x.toFixed(2)} ${s.y.toFixed(2)}A${n} ${n} 0 ${o} 1 ${c.x.toFixed(2)} ${c.y.toFixed(2)}`;if(r<=0)return`${l}L${e} ${t}Z`;let u=U(e,t,r,a),d=U(e,t,r,i);return`${l}L${u.x.toFixed(2)} ${u.y.toFixed(2)}A${r} ${r} 0 ${o} 0 ${d.x.toFixed(2)} ${d.y.toFixed(2)}Z`}function W({names:e,theme:t,y:n,glow:r}){let i=56;return(0,R.jsx)(`g`,{children:e.map((e,a)=>{let o=i;return i+=30+Math.min(e.length,24)*7,(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`circle`,{cx:o+5,cy:n-4,r:5,fill:V(t,a),filter:r}),(0,R.jsx)(`text`,{x:o+16,y:n,fontSize:11,fill:t.ink,children:H(e,24)})]},e)})})}function G({theme:e,children:t}){return(0,R.jsx)(`text`,{x:360,y:210,fontSize:13,textAnchor:`middle`,fill:e.muted,children:t})}function K({chart:e,theme:t,glow:n,top:r,bottomSpace:i}){let a=e.kind===`donut`,o=e.categories??[],s=e.series[0],c=(s?.points??[]).filter(e=>e.y>0).map(e=>({label:o[e.x]??e.label,value:e.y})).sort((e,t)=>t.value-e.value);if(c.length>12){let e=c.slice(11);c=[...c.slice(0,11),{label:`Other (${e.length})`,value:e.reduce((e,t)=>e+t.value,0)}]}let l=c.reduce((e,t)=>e+t.value,0);if(l<=0)return(0,R.jsx)(G,{theme:t,children:`Nothing to draw: pick a column that holds positive numbers.`});let u=420-r-i,d=Math.min(u/2-4,150),f=56+d+8,p=r+u/2,m=a?d*.62:0,h=f+d+44,g=Math.min(24,u/c.length),_=p-c.length*g/2,v=-Math.PI/2;return(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`g`,{filter:n,children:c.map((e,n)=>{let r=v,i=e.value/l*Math.PI*2;v+=i;let o=r+i/2,s=U(f,p,a?(d+m)/2:d*.66,o);return(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`path`,{d:oe(f,p,d,m,r,r+i),fill:V(t,n),fillRule:`evenodd`,stroke:t.paper,strokeWidth:2,strokeLinejoin:`round`,children:(0,R.jsx)(`title`,{children:`${e.label}: ${e.value} (${(e.value/l*100).toFixed(1)}%)`})}),i>.4&&(0,R.jsxs)(`text`,{x:s.x,y:s.y+4,fontSize:11,fontWeight:600,textAnchor:`middle`,fill:t.paper,children:[Math.round(e.value/l*100),`%`]})]},n)})}),a&&(0,R.jsxs)(`g`,{textAnchor:`middle`,children:[(0,R.jsx)(`text`,{x:f,y:p+4,fontSize:22,fontWeight:600,fontFamily:t.headingFont,fill:t.ink,children:L(l)}),(0,R.jsx)(`text`,{x:f,y:p+22,fontSize:10,letterSpacing:.8,fill:t.muted,children:H(s?.name??`total`,18)})]}),c.map((e,r)=>(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`circle`,{cx:h+5,cy:_+r*g+g/2,r:5,fill:V(t,r),filter:n}),(0,R.jsx)(`text`,{x:h+18,y:_+r*g+g/2+4,fontSize:11,fill:t.ink,children:H(e.label,22)}),(0,R.jsxs)(`text`,{x:696,y:_+r*g+g/2+4,fontSize:11,textAnchor:`end`,fill:t.muted,children:[L(e.value),` ·`,` `,(e.value/l*100).toFixed(+(e.value/l<.1)),`%`]})]},r))]})}function se({chart:e,theme:t,glow:n,top:r,bottomSpace:i}){let a=e.categories??[],o=a.length,s=e.series.map(e=>{let t=new Map(e.points.map(e=>[e.x,Math.max(e.y,0)]));return a.map((e,n)=>t.get(n)??0)}),c=Math.max(0,...s.flat());if(o<3||c<=0)return(0,R.jsx)(G,{theme:t,children:o<3?`A radar chart needs at least three categories.`:`Nothing to draw: pick columns that hold positive numbers.`});let l=I(0,c,4).filter(e=>e>0),u=l[l.length-1],d=420-r-i,f=Math.min(d/2-26,260),p=r+d/2,m=e=>-Math.PI/2+e/o*Math.PI*2,h=e=>a.map((t,n)=>{let r=U(360,p,f*e,m(n));return`${n?`L`:`M`}${r.x.toFixed(1)} ${r.y.toFixed(1)}`}).join(``)+`Z`;return(0,R.jsxs)(`g`,{children:[l.map(e=>(0,R.jsx)(`path`,{d:h(e/u),fill:`none`,stroke:t.muted,strokeOpacity:.28,strokeLinejoin:`round`},e)),a.map((e,n)=>{let r=U(360,p,f,m(n)),i=U(360,p,f+20,m(n)),a=Math.cos(m(n));return(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`line`,{x1:360,y1:p,x2:r.x,y2:r.y,stroke:t.muted,strokeOpacity:.2}),(0,R.jsx)(`text`,{x:i.x,y:i.y+(Math.sin(m(n))>.5?8:Math.sin(m(n))<-.5?-4:4),fontSize:11,textAnchor:a>.3?`start`:a<-.3?`end`:`middle`,fill:t.ink,children:H(e,14)})]},n)}),l.map(e=>(0,R.jsx)(`text`,{x:364,y:p-e/u*f-3,fontSize:9,fill:t.muted,children:L(e)},e)),e.series.map((r,i)=>{let o=V(t,i),c=s[i].map((e,t)=>U(360,p,f*e/u,m(t))),l=c.map((e,t)=>`${t?`L`:`M`}${e.x.toFixed(1)} ${e.y.toFixed(1)}`).join(``)+`Z`;return(0,R.jsxs)(`g`,{filter:n,children:[(0,R.jsx)(`path`,{d:l,fill:o,fillOpacity:.2,stroke:o,strokeWidth:2.5,strokeLinejoin:`round`}),c.map((n,c)=>(0,R.jsx)(`circle`,{cx:n.x,cy:n.y,r:3.5,fill:t.paper,stroke:o,strokeWidth:2,children:(0,R.jsx)(`title`,{children:`${a[c]}: ${s[i][c]}${e.series.length>1?` (${r.name})`:``}`})},c))]},r.name)})]})}function ce({chart:e,text:t,theme:n,uid:r,glow:i,top:a,bottomSpace:o}){let{series:s,categories:c,kind:l}=e,u=s.length>1,d=!!c&&c.length>8,f=d?56:28,p=f+(t.xLabel?22:0)+o,m=420-a-p,h=Math.min(Math.max(n.radius*.6,0),8),g=s.flatMap(e=>e.points),_=g.map(e=>e.x),v=g.map(e=>e.y),y=g.length===0,b=y?0:Math.min(...v),x=y?1:Math.max(...v);(l===`bar`||l===`area`)&&(b=Math.min(b,0),x=Math.max(x,0)),x===b&&(x=b+1);let S=I(b,x,5),C=Math.min(b,S[0]),w=Math.max(x,S[S.length-1]),T=e=>a+m-(e-C)/(w-C)*m,E,D,O=c?.length??0;if(c){let e=640/Math.max(O,1);E=t=>56+e*(t+.5);let t=Math.max(1,Math.ceil(O/Math.max(Math.floor(640/(d?18:70)),1)));D=c.flatMap((e,n)=>n%t===0?[{at:E(n),label:H(e,d?16:10)}]:[])}else{let t=y?0:Math.min(..._),n=y?1:Math.max(..._);n===t&&(--t,n+=1),E=e=>56+(e-t)/(n-t)*640,D=e.xIsTime?[0,1,2,3,4].map(e=>{let r=t+(n-t)*e/4;return{at:E(r),label:ne(r,n-t)}}):I(t,n,6).map(e=>({at:E(e),label:L(e)}))}let k=c?640/Math.max(O,1):0,A=c?Math.min(k*.72/s.length,44):0,j=a+m,M=l===`bar`||l===`area`?T(0):j,N=j+(d?14:20);return(0,R.jsxs)(`g`,{children:[(0,R.jsx)(`defs`,{children:s.map((e,t)=>(0,R.jsxs)(`g`,{children:[(0,R.jsxs)(`linearGradient`,{id:`${r}bar${t}`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,R.jsx)(`stop`,{offset:`0`,stopColor:V(n,t),stopOpacity:1}),(0,R.jsx)(`stop`,{offset:`1`,stopColor:V(n,t),stopOpacity:.45})]}),(0,R.jsxs)(`linearGradient`,{id:`${r}area${t}`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,R.jsx)(`stop`,{offset:`0`,stopColor:V(n,t),stopOpacity:l===`area`?.5:.28}),(0,R.jsx)(`stop`,{offset:`1`,stopColor:V(n,t),stopOpacity:0})]})]},t))}),S.map(e=>(0,R.jsx)(`text`,{x:46,y:T(e)+4,fontSize:11,textAnchor:`end`,fill:n.muted,children:L(e)},e)),(0,R.jsx)(`line`,{x1:56,x2:696,y1:M,y2:M,stroke:n.muted,strokeOpacity:.6}),D.map((e,t)=>(0,R.jsx)(`text`,{x:e.at,y:N,fontSize:11,fill:n.muted,textAnchor:d||e.at>690?`end`:`middle`,transform:d?`rotate(-40 ${e.at} ${N})`:void 0,children:e.label},t)),t.yLabel&&(0,R.jsx)(`text`,{transform:`translate(16 ${a+m/2}) rotate(-90)`,fontSize:11,letterSpacing:.6,textAnchor:`middle`,fill:n.muted,children:t.yLabel}),y&&(0,R.jsx)(`text`,{x:376,y:a+m/2,fontSize:13,textAnchor:`middle`,fill:n.muted,children:`Nothing to draw: pick columns that hold numbers.`}),s.map((e,t)=>{let a=V(n,t);if(l===`bar`)return(0,R.jsx)(`g`,{filter:i,children:e.points.map((n,i)=>{let o=Math.max(A-3,2),c=E(n.x)-A*s.length/2+A*t+1.5,l=Math.min(T(n.y),T(0)),d=Math.max(Math.abs(T(n.y)-T(0)),1);return(0,R.jsx)(`path`,{d:ie(c,l,o,d,h,n.y>=0),fill:`url(#${r}bar${t})`,stroke:a,strokeOpacity:.9,strokeWidth:1,children:(0,R.jsx)(`title`,{children:`${n.label}: ${n.y}${u?` (${e.name})`:``}`})},i)})},e.name);let o=e.points.map(e=>({x:E(e.x),y:T(e.y)})),c=ae(o);return(0,R.jsxs)(`g`,{children:[(l===`line`||l===`area`)&&o.length>1&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`path`,{d:`${c}L${o[o.length-1].x.toFixed(1)} ${M}L${o[0].x.toFixed(1)} ${M}Z`,fill:`url(#${r}area${t})`}),(0,R.jsx)(`path`,{d:c,fill:`none`,stroke:a,strokeWidth:2.5,strokeLinejoin:`round`,strokeLinecap:`round`,filter:i})]}),(l===`scatter`||l===`line`&&e.points.length<=60||l===`area`&&e.points.length<=24)&&(0,R.jsx)(`g`,{filter:i,children:e.points.map((t,r)=>(0,R.jsx)(`circle`,{cx:o[r].x,cy:o[r].y,r:l===`scatter`?5:3.5,fill:l===`scatter`?a:n.paper,fillOpacity:l===`scatter`?.8:1,stroke:a,strokeWidth:l===`scatter`?1.5:2,children:(0,R.jsx)(`title`,{children:`${t.label}: ${t.y}${u?` (${e.name})`:``}`})},r))})]},e.name)}),t.xLabel&&(0,R.jsx)(`text`,{x:376,y:j+f+14,fontSize:11,letterSpacing:.6,textAnchor:`middle`,fill:n.muted,children:t.xLabel})]})}var le=(0,b.forwardRef)(function({chart:e,text:t},n){let r=re(),i=(0,b.useId)().replace(/[^a-zA-Z0-9]/g,``),{kind:a,series:o}=e,s=o.length>1&&a!==`pie`&&a!==`donut`,c=t.title?56:28,l=(s?26:0)+(t.caption?26:0)+8,u=Math.min(r.radius,18),d=r.glow>0?`url(#${i}glow)`:void 0,f={chart:e,text:t,theme:r,uid:i,glow:d,top:c,bottomSpace:l};return(0,R.jsxs)(`svg`,{ref:n,xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 720 420`,width:720,height:420,role:`img`,"aria-label":t.title||`Chart`,fontFamily:r.bodyFont,style:{maxWidth:`100%`,height:`auto`,display:`block`,position:`relative`,zIndex:51},children:[(0,R.jsx)(`defs`,{children:r.glow>0&&(0,R.jsxs)(`filter`,{id:`${i}glow`,x:`-20%`,y:`-20%`,width:`140%`,height:`140%`,children:[(0,R.jsx)(`feGaussianBlur`,{in:`SourceGraphic`,stdDeviation:r.glow/2,result:`blur`}),(0,R.jsxs)(`feMerge`,{children:[(0,R.jsx)(`feMergeNode`,{in:`blur`}),(0,R.jsx)(`feMergeNode`,{in:`SourceGraphic`})]})]})}),(0,R.jsx)(`rect`,{x:.5,y:.5,width:719,height:419,rx:u,fill:r.paper,stroke:r.border,strokeOpacity:.55}),t.title&&(0,R.jsx)(`text`,{x:56,y:34,fontSize:18,fontFamily:r.headingFont,fontWeight:600,fill:r.ink,letterSpacing:.3,children:H(t.title,70)}),a===`pie`||a===`donut`?(0,R.jsx)(K,{...f}):a===`radar`?(0,R.jsx)(se,{...f}):(0,R.jsx)(ce,{...f}),s&&(0,R.jsx)(W,{names:o.map(e=>e.name),theme:r,y:406-(t.caption?24:0),glow:d}),t.caption&&(0,R.jsx)(`text`,{x:56,y:406,fontSize:11,fontStyle:`italic`,fill:r.muted,children:H(t.caption,110)})]})}),ue=`http://www.w3.org/2000/svg`;function q(e){let t=e.cloneNode(!0);return t.setAttribute(`xmlns`,ue),t.removeAttribute(`style`),`<?xml version="1.0" encoding="UTF-8"?>\n${new XMLSerializer().serializeToString(t)}\n`}function de(e,t=2){return J(q(e),e.viewBox.baseVal.width,e.viewBox.baseVal.height,t)}function J(e,t,n,r=2){let i=URL.createObjectURL(new Blob([e],{type:`image/svg+xml;charset=utf-8`}));return new Promise((e,a)=>{let o=new Image;o.onload=()=>{let s=document.createElement(`canvas`);s.width=t*r,s.height=n*r;let c=s.getContext(`2d`);c?(c.drawImage(o,0,0,s.width,s.height),URL.revokeObjectURL(i),s.toBlob(t=>t?e(t):a(Error(`The image could not be made`)),`image/png`)):a(Error(`This browser cannot draw the image`))},o.onerror=()=>{URL.revokeObjectURL(i),a(Error(`The chart could not be turned into an image`))},o.src=i})}function Y(e,t){let n=URL.createObjectURL(e),r=document.createElement(`a`);r.href=n,r.download=t,document.body.append(r),r.click(),r.remove(),URL.revokeObjectURL(n)}var X=(e,t)=>e.trim().toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,60)||t,Z=`border-input bg-background rounded-lg border px-2 py-1 text-sm`;function Q({label:e,children:t}){return(0,R.jsxs)(`label`,{className:`flex flex-col gap-1 text-xs`,children:[(0,R.jsx)(`span`,{className:`text-muted-foreground`,children:e}),t]})}function fe({data:e,filename:t}){let n=e.columns.filter(e=>C(e.type)),[r,i]=(0,b.useState)(()=>e.columns[0]&&w(e.columns[0].type)?`line`:`bar`),[c,l]=(0,b.useState)(e.columns[0]?.name??``),[u,d]=(0,b.useState)(``),[f,p]=(0,b.useState)(`none`),[m,h]=(0,b.useState)(()=>{let t=n.find(t=>t.name!==e.columns[0]?.name)??n[0];return t?[t.name]:[]}),[g,v]=(0,b.useState)({title:``,caption:``,xLabel:``,yLabel:``}),[y,x]=(0,b.useState)(),[S,T]=(0,b.useState)(),E=(0,b.useRef)(null),D=e.columns.find(e=>e.name===c)?.type??``,O=(0,b.useMemo)(()=>{try{let t=u&&u!==c&&!m.includes(u)&&r!==`pie`&&r!==`donut`;return{chart:te(e,r,c,m,{group:t?u:void 0,bucket:f})}}catch(e){return{error:e instanceof Error?e.message:String(e)}}},[e,r,c,m,u,f]),k=e=>v({...g,...e}),A=e=>h(m.includes(e)?m.filter(t=>t!==e):[...m,e].slice(-5)),j=async e=>{if(E.current){x(void 0);try{let n=`${X(g.title,t)}.${e}`;Y(e===`svg`?new Blob([q(E.current)],{type:`image/svg+xml`}):await de(E.current),n),T(e),window.setTimeout(()=>T(void 0),1500)}catch(e){x(e instanceof Error?e.message:String(e))}}};return(0,R.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,R.jsxs)(`div`,{className:`flex flex-wrap items-end gap-3`,children:[(0,R.jsx)(Q,{label:`Chart`,children:(0,R.jsx)(`select`,{"aria-label":`Chart type`,value:r,onChange:e=>i(e.target.value),className:Z,children:M.map(e=>(0,R.jsx)(`option`,{value:e.id,children:e.label},e.id))})}),(0,R.jsx)(Q,{label:`X axis`,children:(0,R.jsx)(`select`,{"aria-label":`X column`,value:c,onChange:e=>l(e.target.value),className:Z,children:e.columns.map(e=>(0,R.jsx)(`option`,{children:e.name},e.name))})}),w(D)&&r!==`scatter`&&(0,R.jsx)(Q,{label:`Group times by`,children:(0,R.jsx)(`select`,{"aria-label":`Time step`,value:f,onChange:e=>p(e.target.value),className:Z,children:ee.map(e=>(0,R.jsx)(`option`,{value:e,children:e===`none`?`as they are`:e},e))})}),r!==`pie`&&r!==`donut`&&(0,R.jsx)(Q,{label:`Colour by group`,children:(0,R.jsxs)(`select`,{"aria-label":`Group column`,value:u,onChange:e=>d(e.target.value),className:Z,children:[(0,R.jsx)(`option`,{value:``,children:`no groups`}),e.columns.filter(e=>e.name!==c).map(e=>(0,R.jsx)(`option`,{children:e.name},e.name))]})}),(0,R.jsxs)(`fieldset`,{className:`flex flex-col gap-1 text-xs`,children:[(0,R.jsx)(`legend`,{className:`text-muted-foreground mb-1`,children:r===`pie`||r===`donut`||u?`Y axis (first number is used)`:`Y axis (numbers)`}),(0,R.jsxs)(`div`,{className:`flex flex-wrap gap-x-3 gap-y-1`,children:[n.length===0&&(0,R.jsx)(`span`,{className:`text-muted-foreground`,children:`no numeric columns`}),n.map(e=>(0,R.jsxs)(`label`,{className:`flex items-center gap-1 text-sm`,children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:m.includes(e.name),onChange:()=>A(e.name)}),e.name]},e.name))]})]})]}),(0,R.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,R.jsx)(Q,{label:`Title`,children:(0,R.jsx)(`input`,{"aria-label":`Chart title`,value:g.title,onChange:e=>k({title:e.target.value}),className:Z})}),(0,R.jsx)(Q,{label:`Caption`,children:(0,R.jsx)(`input`,{"aria-label":`Chart caption`,value:g.caption,onChange:e=>k({caption:e.target.value}),placeholder:`Source, date, notes`,className:Z})}),!N(r)&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(Q,{label:`X axis label`,children:(0,R.jsx)(`input`,{"aria-label":`X axis label`,value:g.xLabel,onChange:e=>k({xLabel:e.target.value}),placeholder:c,className:Z})}),(0,R.jsx)(Q,{label:`Y axis label`,children:(0,R.jsx)(`input`,{"aria-label":`Y axis label`,value:g.yLabel,onChange:e=>k({yLabel:e.target.value}),placeholder:m.join(`, `),className:Z})})]})]}),O.error?(0,R.jsx)(`p`,{className:`text-destructive text-sm`,children:O.error}):(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`div`,{className:`max-w-full overflow-x-auto`,children:(0,R.jsx)(le,{ref:E,chart:O.chart,text:g})}),(O.chart.skipped>0||O.chart.clipped>0)&&(0,R.jsxs)(`p`,{className:`text-muted-foreground text-xs`,role:`status`,children:[O.chart.skipped>0&&`${O.chart.skipped.toLocaleString()} values left out because they are not numbers. `,O.chart.clipped>0&&`Only the first categories are drawn; group the result to see fewer.`]})]}),(0,R.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,R.jsxs)(a,{variant:`outline`,size:`sm`,disabled:!!O.error,onClick:()=>j(`png`),children:[S===`png`?(0,R.jsx)(o,{}):(0,R.jsx)(_,{}),` Save PNG`]}),(0,R.jsxs)(a,{variant:`outline`,size:`sm`,disabled:!!O.error,onClick:()=>j(`svg`),children:[S===`svg`?(0,R.jsx)(o,{}):(0,R.jsx)(s,{}),` Save SVG`]}),y&&(0,R.jsx)(`span`,{role:`status`,className:`text-destructive text-xs`,children:y})]})]})}function pe({data:e,onGrouped:t}){let[n,r]=(0,b.useState)([]),[i,o]=(0,b.useState)(``),[s,m]=(0,b.useState)(`count`),h=e.columns.filter(e=>C(e.type)),g={column:s===`count`?``:i||h[0]?.name||``,aggregate:s},_=(0,b.useMemo)(()=>{try{return A(e,n,[g])}catch{return}},[e,n,s,i]),v=s!==`count`&&!g.column;return(0,R.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,R.jsxs)(`div`,{className:`flex flex-wrap items-end gap-3`,children:[(0,R.jsxs)(`fieldset`,{className:`flex flex-col gap-1 text-xs`,children:[(0,R.jsx)(`legend`,{className:`text-muted-foreground mb-1`,children:`Group by`}),(0,R.jsx)(`div`,{className:`flex flex-wrap gap-x-3 gap-y-1`,children:e.columns.map(e=>(0,R.jsxs)(`label`,{className:`flex items-center gap-1 text-sm`,children:[(0,R.jsx)(`input`,{type:`checkbox`,checked:n.includes(e.name),onChange:()=>r(n.includes(e.name)?n.filter(t=>t!==e.name):[...n,e.name])}),e.name]},e.name))})]}),(0,R.jsx)(Q,{label:`Measure`,children:(0,R.jsx)(`select`,{"aria-label":`Aggregate`,value:s,onChange:e=>m(e.target.value),className:Z,children:O.map(e=>(0,R.jsx)(`option`,{children:e},e))})}),s!==`count`&&(0,R.jsx)(Q,{label:`of`,children:(0,R.jsx)(`select`,{"aria-label":`Aggregate column`,value:g.column,onChange:e=>o(e.target.value),className:Z,children:h.map(e=>(0,R.jsx)(`option`,{children:e.name},e.name))})}),(0,R.jsx)(a,{size:`sm`,disabled:v||!_,onClick:()=>t(_),children:`Use for the chart`}),(0,R.jsx)(a,{variant:`outline`,size:`sm`,onClick:()=>t(void 0),children:`Chart the result`})]}),v?(0,R.jsxs)(`p`,{className:`text-muted-foreground text-sm`,children:[`There is no numeric column to `,s,`.`]}):_&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`p`,{className:`text-muted-foreground text-xs`,children:[_.rows.length.toLocaleString(),` groups: `,k(g),n.length>0&&` by ${n.join(`, `)}`]}),(0,R.jsx)(`div`,{className:`max-h-72 overflow-auto`,children:(0,R.jsxs)(p,{children:[(0,R.jsx)(c,{children:(0,R.jsx)(d,{children:_.columns.map(e=>(0,R.jsx)(l,{children:e.name},e.name))})}),(0,R.jsx)(u,{children:_.rows.slice(0,200).map((e,t)=>(0,R.jsx)(d,{children:e.map((e,t)=>(0,R.jsx)(f,{children:e===null?(0,R.jsx)(`span`,{className:`text-muted-foreground italic`,children:`NULL`}):e},t))},t))})]})})]})]})}function me({data:e}){let t=(0,b.useMemo)(()=>j(e),[e]),n=e=>e===void 0?``:L(e);return(0,R.jsx)(`div`,{className:`overflow-x-auto`,children:(0,R.jsxs)(p,{children:[(0,R.jsx)(c,{children:(0,R.jsx)(d,{children:[`column`,`rows`,`nulls`,`distinct`,`min`,`max`,`mean`,`median`,`sum`,`std dev`].map(e=>(0,R.jsx)(l,{children:e},e))})}),(0,R.jsx)(u,{children:t.map(e=>(0,R.jsxs)(d,{children:[(0,R.jsx)(f,{title:e.type,children:e.name}),(0,R.jsx)(f,{children:e.count.toLocaleString()}),(0,R.jsx)(f,{children:e.nulls.toLocaleString()}),(0,R.jsx)(f,{children:e.distinct.toLocaleString()}),(0,R.jsx)(f,{children:(0,R.jsx)(`span`,{className:`block max-w-40 truncate`,title:e.min??``,children:e.min??``})}),(0,R.jsx)(f,{children:(0,R.jsx)(`span`,{className:`block max-w-40 truncate`,title:e.max??``,children:e.max??``})}),(0,R.jsx)(f,{children:n(e.mean)}),(0,R.jsx)(f,{children:n(e.median)}),(0,R.jsx)(f,{children:n(e.sum)}),(0,R.jsx)(f,{children:n(e.stddev)})]},e.name))})]})})}function he({data:e,fetchAll:t,filename:n}){let[r,i]=(0,b.useState)(!1),[a,o]=(0,b.useState)(`chart`),[s,c]=(0,b.useState)(),[l,u]=(0,b.useState)(!1),[d,f]=(0,b.useState)(!1),[p,m]=(0,b.useState)(),[g,_]=(0,b.useState)(),v=l&&s?s:e,y=async e=>{if(m(void 0),_(void 0),e&&!s){f(!0);try{c(await t())}catch(e){m(e instanceof Error?e.message:String(e)),f(!1);return}f(!1)}u(e)};return e.columns.length>0&&e.rows.length>0?(0,R.jsxs)(`section`,{className:`mb-3`,"aria-label":`Analyze the result`,children:[(0,R.jsxs)(`button`,{type:`button`,onClick:()=>i(!r),"aria-expanded":r,className:`text-muted-foreground hover:text-foreground flex items-center gap-1 text-xs`,children:[(0,R.jsx)(h,{className:`size-4`}),` `,r?`Hide`:`Chart and analyze`]}),r&&(0,R.jsxs)(`div`,{className:`border-input bg-card mt-2 flex flex-col gap-3 border p-3`,children:[(0,R.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 text-xs`,children:[(0,R.jsx)(`div`,{role:`tablist`,className:`flex gap-1`,children:[[`chart`,`Chart`],[`group`,`Group by`],[`stats`,`Column stats`]].map(([e,t])=>(0,R.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":a===e,onClick:()=>o(e),className:`rounded-lg px-2.5 py-1 text-sm ${a===e?`bg-secondary text-secondary-foreground`:`text-muted-foreground hover:text-foreground`}`,children:t},e))}),(0,R.jsx)(`span`,{className:`text-muted-foreground ml-auto`,children:`Rows`}),(0,R.jsxs)(`select`,{"aria-label":`Rows to analyze`,value:l?`all`:`page`,disabled:d,onChange:e=>void y(e.target.value===`all`),className:Z,children:[(0,R.jsxs)(`option`,{value:`page`,children:[`this page (`,e.rows.length.toLocaleString(),`)`]}),(0,R.jsxs)(`option`,{value:`all`,children:[`all rows`,s?` (${s.rows.length.toLocaleString()}${s.truncated?`+`:``})`:``]})]}),d&&(0,R.jsx)(`span`,{role:`status`,children:`Reading...`})]}),p&&(0,R.jsx)(`p`,{className:`text-destructive text-sm`,children:p}),a===`chart`&&(0,R.jsxs)(R.Fragment,{children:[g&&(0,R.jsxs)(`p`,{className:`text-muted-foreground text-xs`,children:[`Charting the grouping (`,g.columns.map(e=>e.name).join(`, `),`).`]}),(0,R.jsx)(fe,{data:g??v,filename:n},`${l}-${g?g.columns.map(e=>e.name).join(`|`):`rows`}-${v.rows.length}`)]}),a===`group`&&(0,R.jsx)(pe,{data:v,onGrouped:e=>{_(e),o(`chart`)}}),a===`stats`&&(0,R.jsx)(me,{data:v})]})]}):null}function ge(e,t){let n=e.filter(e=>e.primaryKey);return(n.length>0?n:e.filter(e=>e.type!==`json`&&e.type!==`xml`)).map(({name:e})=>{let n=t[e];return n==null?{column:e,op:`null`}:{column:e,op:`eq`,value:n}})}function $(e,t,r){return n({environment:e,graph:{schema:t.schema,table:t.name,keys:r}})}function _e(e,t,r){return n({environment:e,graph:{schema:t.schema,table:t.name,filters:r}})}function ve(e,t,n){let r=new Set(t.map(e=>e.name)),i=e=>{let t=e.columns.filter(e=>e.primaryKey);return t.length>0&&t.every(e=>r.has(e.name))},a=e.filter((t,n)=>e.findIndex(e=>e.schema===t.schema&&e.name===t.name)===n),o=n.filter(e=>!a.some(t=>t.schema===e.schema&&t.name===e.name));return[...a,...o].filter(i)}function ye(e,t,n){let r=e.columns.filter(e=>e.primaryKey).map(e=>t.findIndex(t=>t.name===e.name)),i=new Set,a=[];for(let e of n){let t=r.map(t=>e[t]??null);if(t.some(e=>e===null))continue;let n=t,o=JSON.stringify(n);i.has(o)||(i.add(o),a.push(n))}return a}export{ge as a,Y as c,h as d,ye as i,J as l,$ as n,he as o,ve as r,X as s,_e as t,y as u};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{$ as e,a as t,at as n,ct as r,o as i,ot as a,rt as o}from"./route-DO6IZ7of.js";import{c as s,l as c,s as l,u}from"./graph-link-OCo_s0zO.js";import{z as d}from"./button-ClA70PLR.js";import{c as f,l as p}from"./zone-D9dXk8tn.js";import{t as m}from"./loader-circle-BK_GMdvN.js";import{a as h,c as g,d as _,f as v,i as ee,l as y,m as b,o as x,p as S,r as C,s as te,t as ne,u as w}from"./graph-force-yBLyErpS.js";import{t as T}from"./sliders-horizontal-Dg51yc-C.js";import{Gt as E,Wt as D,X as O,Y as k,qt as re,tn as A}from"./index-CDcnUacl.js";var j={name:`eye-off`,size:24,node:[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]};j.node;var M=n(j),N={name:`layout-grid`,size:24,node:[[`rect`,{width:`7`,height:`7`,x:`3`,y:`3`,rx:`1`,key:`1g98yp`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`3`,rx:`1`,key:`6d4xhi`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`14`,rx:`1`,key:`nxv5o0`}],[`rect`,{width:`7`,height:`7`,x:`3`,y:`14`,rx:`1`,key:`1bb6yr`}]]};N.node;var ie=n(N),P={name:`undo-2`,size:24,node:[[`path`,{d:`M9 14 4 9l5-5`,key:`102s5s`}],[`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11`,key:`f3b9sd`}]]};P.node;var F=n(P),I=r(a(),1),L=()=>({labels:{},hidden:[],skipped:[],confirmed:[]}),R=e=>`${e.schema}.${e.name}`,z=e=>`psql-explorer-graph:${e}`,B=()=>globalThis.localStorage,V=e=>Array.isArray(e)&&e.every(e=>typeof e==`string`);function ae(e){try{let t=JSON.parse(B().getItem(z(e))??`null`);if(!t||typeof t!=`object`)return L();let n={};for(let[e,r]of Object.entries(t.labels??{}))V(r)&&r.length>0&&(n[e]=r);return{labels:n,hidden:(Array.isArray(t.hidden)?t.hidden:[]).filter(e=>typeof e?.schema==`string`&&typeof e.name==`string`),skipped:V(t.skipped)?t.skipped:[],confirmed:V(t.confirmed)?t.confirmed:[]}}catch{return L()}}function oe(e,t){try{B().setItem(z(e),JSON.stringify(t))}catch{}}var se=e=>JSON.stringify([e.from.schema,e.from.name,e.name]);function ce(e,t){let n=e=>new Set([...e.hidden.map(e=>`t:${R(e)}`),...e.skipped.map(e=>`k:${e}`)]),[r,i]=[n(e),n(t)];return[...r].filter(e=>!i.has(e)).length+[...i].filter(e=>!r.has(e)).length}function H(e,t){if(!t||t.length===0)return e.label;let n=t.filter(t=>t in e.row).map(t=>e.row[t]??`NULL`).join(`, `);return n===``?e.label:n.length>60?`${n.slice(0,59)}…`:n}function le(e,t){let n=(t??[]).filter(t=>t in e.row);return n.length>0&&n.every(t=>e.row[t]===null)}function ue(e,t){let n=new Map;for(let[r,i]of e){if(le(i,t[R(i.table)]))continue;let e=H(i,t[R(i.table)]);n.set(r,e===i.label?i:{...i,label:e})}return n}function de(e,t){let n=new Map;for(let t of e)n.set(t.id,R(t.table));let r=new Map;for(let e of t){let t=n.get(e.from);t&&!e.via&&r.set(t,(r.get(t)??new Set).add(e.constraint))}return new Set([...r].filter(([,e])=>e.size>=2).map(([e])=>e))}var U=o(),W=22,fe=(e,t)=>e.length>t?`${e.slice(0,t-1)}…`:e;function pe(e,t,n){let[r,i]=[n.x-e.x,n.y-e.y];if(r===0&&i===0)return e;let a=Math.min(r===0?1/0:t/2/Math.abs(r),i===0?1/0:W/2/Math.abs(i));return{x:e.x+r*a,y:e.y+i*a}}function me({environment:t,schema:n,start:r,settings:i,counts:a,onToggleTable:o,onToggleKey:s}){let c=D(async()=>{let[r,i]=await Promise.all([e.erd(t,n),e.schemaForeignKeys(t,n)]);return{tables:r,keys:i}},`${t}/${n}`),{frame:l,view:u,setView:d,dragged:f,startDrag:p,zoomBy:m}=w(),h=(0,I.useMemo)(()=>{if(!c.data)return;let e=new Map,t=t=>{let r=R(t);if(e.has(r))return;let i=t.schema===n?t.name:r;e.set(r,{key:r,table:{schema:t.schema,name:t.name},label:i,width:Math.max(72,fe(i,28).length*6.6+30)})};for(let e of c.data.tables)t(e);for(let e of c.data.keys)t(e.from),t(e.to);let r=[...e.values()].map(e=>({id:e.key,r:e.width/2})),i=c.data.keys.filter(e=>R(e.from)!==R(e.to)).map(e=>({source:R(e.from),target:R(e.to)})),a=x(r,i);return te(a,i),{pills:e,at:new Map(a.map(e=>[e.id,{x:e.x,y:e.y}])),keys:c.data.keys}},[c.data,n]),g=(0,I.useCallback)(()=>{let e=l.current?.getBoundingClientRect();if(!h||!e)return;let[t,n,r,i]=[1/0,1/0,-1/0,-1/0];for(let e of h.pills.values()){let a=h.at.get(e.key);t=Math.min(t,a.x-e.width/2),r=Math.max(r,a.x+e.width/2),n=Math.min(n,a.y-W/2-30),i=Math.max(i,a.y+W/2)}if(t===1/0)return;let a={x:t,y:n,width:r-t,height:i-n},o=S(a,e,16);d({k:o.k,x:o.x-a.x*o.k,y:o.y-a.y*o.k})},[h,l,d]);if((0,I.useLayoutEffect)(g,[g]),c.error)return(0,U.jsxs)(`p`,{className:`text-destructive mb-3 text-sm`,children:[`Could not load the schema: `,String(c.error)]});if(!h)return(0,U.jsx)(E,{className:`mb-3 h-48`});let v=new Set(i.hidden.map(R)),ee=new Set(i.skipped),b=new Map,C=e=>{let t=[R(e.from),R(e.to)].sort().join(`|`),n=b.get(t)??0;return b.set(t,n+1),n};return(0,U.jsxs)(`div`,{className:`relative mb-3`,children:[(0,U.jsx)(y,{zoomBy:m,fit:g}),(0,U.jsx)(`div`,{ref:l,onPointerDown:p,className:`border-border h-72 touch-none overflow-hidden border`,children:(0,U.jsxs)(`svg`,{role:`img`,"aria-label":`Schema map`,width:`100%`,height:`100%`,className:`cursor-grab select-none active:cursor-grabbing`,children:[(0,U.jsx)(`defs`,{children:(0,U.jsx)(`marker`,{id:`map-arrow`,viewBox:`0 0 10 10`,refX:9,refY:5,markerWidth:7,markerHeight:7,orient:`auto-start-reverse`,children:(0,U.jsx)(`path`,{d:`M0,0 L10,5 L0,10 z`,className:`fill-accent-text`})})}),(0,U.jsxs)(`g`,{transform:`translate(${u.x},${u.y}) scale(${u.k})`,children:[h.keys.map(e=>{let[t,n]=[h.at.get(R(e.from)),h.at.get(R(e.to))],[r,i]=[h.pills.get(R(e.from)),h.pills.get(R(e.to))];if(!t||!n||!r||!i)return null;let a=se(e),o=ee.has(a),c=`${e.name} (${e.fromColumns.join(`, `)} → ${e.toColumns.join(`, `)}): ${o?`not followed, click to follow`:`followed, click to stop following`}`,l=C(e),u;if(r===i){let[e,n]=[t.x,t.y-W/2];u=`M${e-12},${n} C${e-34-l*12},${n-40-l*10} ${e+34+l*12},${n-40-l*10} ${e+12},${n}`}else{let e={x:(t.x+n.x)/2,y:(t.y+n.y)/2},[a,o]=[n.x-t.x,n.y-t.y],s=Math.hypot(a,o)||1,c=l===0?0:(l%2?1:-1)*Math.ceil(l/2)*26,d={x:e.x-o/s*c,y:e.y+a/s*c},[f,p]=[pe(t,r.width,d),pe(n,i.width+6,d)];u=`M${f.x},${f.y} Q${d.x},${d.y} ${p.x},${p.y}`}return(0,U.jsxs)(`g`,{"data-key":e.name,"data-followed":!o,className:`cursor-pointer`,onClick:()=>!f.current&&s(a),children:[(0,U.jsx)(`path`,{d:u,fill:`none`,className:o?`stroke-muted-foreground`:`stroke-accent-text`,strokeWidth:1.4,strokeDasharray:o?`4 4`:void 0,opacity:o?.45:.85,markerEnd:`url(#map-arrow)`}),(0,U.jsx)(`path`,{d:u,fill:`none`,stroke:`transparent`,strokeWidth:12,children:(0,U.jsx)(`title`,{children:c})})]},a)}),[...h.pills.values()].map(e=>{let t=h.at.get(e.key),n=e.key===R(r),i=v.has(e.key),s=a.get(e.key),c=_(e.key);return(0,U.jsxs)(`g`,{transform:`translate(${t.x},${t.y})`,"data-table":e.key,"data-shown":!i,role:`button`,"aria-label":`${e.key}${i?` (left out)`:``}`,"aria-pressed":!i,className:n?`cursor-default`:`cursor-pointer`,opacity:i?.5:1,onClick:()=>!f.current&&!n&&o(e.table),children:[(0,U.jsx)(`title`,{children:n?`${e.key}: where the graph starts`:i?`${e.key}: left out, click to draw it`:`${e.key}: click to leave it out`}),(0,U.jsx)(`rect`,{x:-e.width/2,y:-11,width:e.width,height:W,rx:W/2,className:`fill-card`,stroke:n?`var(--primary)`:c,strokeWidth:n?2.5:1.5,strokeDasharray:i?`4 3`:void 0}),(0,U.jsx)(`circle`,{cx:-e.width/2+11,r:4,fill:c}),(0,U.jsx)(`text`,{x:6,y:4,textAnchor:`middle`,className:`fill-foreground text-[11px]`,textDecoration:i?`line-through`:void 0,children:fe(e.label,28)}),s!==void 0&&!i&&(0,U.jsx)(`text`,{x:e.width/2,y:-14,textAnchor:`end`,className:`fill-muted-foreground text-[9px]`,children:s})]},e.key)})]})]})})]})}var G=e=>`more:${e.node}|${e.constraint}`,K=24,he=50,q={background:`#ffffff`,card:`#f8fafc`,border:`#cbd5e1`,text:`#0f172a`,muted:`#64748b`,edge:`#2563eb`,start:`#7c3aed`},J=e=>`${e.schema}.${e.name}`,Y=(e,t)=>e.length>t?`${e.slice(0,t-1)}…`:e;function X(e){return e.replace(/[&<>"']/g,e=>`&#${e.charCodeAt(0)};`)}function ge(e,t=!1){let n=0,r=0;for(let t of e.values())n=Math.max(n,t.x+t.width),r=Math.max(r,t.y+t.height);return{width:n+48+(t?he:0),height:r+48}}var Z=e=>e.via?`${e.constraint}`:`${e.constraint} (${e.fromColumns.join(`, `)} → ${e.toColumns.join(`, `)})`;function _e({nodes:e,edges:t,more:n},r){let[i,a,o,s]=[1/0,1/0,-1/0,-1/0];for(let e of r.values())i=Math.min(i,e.x-Math.max(e.r,70)),o=Math.max(o,e.x+Math.max(e.r,70)),a=Math.min(a,e.y-e.r-(t.length>0?e.r*4:0)),s=Math.max(s,e.y+e.r+34);r.size===0&&([i,a,o,s]=[0,0,0,0]);let c=Math.ceil(o-i+48),l=Math.ceil(s-a+48),u=[`<?xml version="1.0" encoding="UTF-8"?>\n<svg xmlns="http://www.w3.org/2000/svg" width="${c}" height="${l}" viewBox="0 0 ${c} ${l}" font-family="system-ui, sans-serif">`,`<defs><marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="${q.edge}"/></marker></defs>`,`<rect width="${c}" height="${l}" fill="${q.background}"/>`,`<g transform="translate(${K-i},${K-a})">`],d=(e,t,n,r,i,a=1)=>`<text x="${e}" y="${t}" font-size="${n}" text-anchor="middle" fill="${r}" opacity="${a}" stroke="${q.background}" stroke-width="3" stroke-linejoin="round" paint-order="stroke">${X(i)}</text>`;for(let e of t){let[t,n]=[r.get(e.from),r.get(e.to)];if(!t||!n)continue;let i=`<title>${X(Z(e))}</title>`;if(e.from===e.to){u.push(`<path d="${h(t.x,t.y,t.r)}" fill="none" stroke="${q.edge}" stroke-width="1.5" opacity="0.6" marker-end="url(#arrow)">${i}</path>`);continue}let a=C(t,n,!e.via);u.push(`<line x1="${a.x1}" y1="${a.y1}" x2="${a.x2}" y2="${a.y2}" stroke="${q.edge}" stroke-width="1.5" opacity="0.6"${e.via?` stroke-dasharray="5 4"`:` marker-end="url(#arrow)"`}>${i}</line>`)}for(let e of n){let t=r.get(G(e)),n=r.get(e.node);if(!t)continue;if(n){let e=C(n,t,!1);u.push(`<line x1="${e.x1}" y1="${e.y1}" x2="${e.x2}" y2="${e.y2}" stroke="${q.muted}" stroke-width="1" stroke-dasharray="3 3" opacity="0.6"/>`)}let i=e.count-e.shown;u.push(`<circle cx="${t.x}" cy="${t.y}" r="${t.r}" fill="none" stroke="${q.muted}" stroke-dasharray="4 3"/>`,d(t.x,t.y+t.r+13,11,q.text,`+${i.toLocaleString(`en-US`)}${e.capped?`+`:``} more in ${e.table.name}`))}for(let t of e){let e=r.get(t.id);e&&u.push(`<circle cx="${e.x}" cy="${e.y}" r="${e.r}" fill="${_(J(t.table))}" stroke="${t.start?q.start:q.background}" stroke-width="${t.start?3:1.5}"/>`,d(e.x,e.y+e.r+13,11,q.text,Y(t.label,24)),d(e.x,e.y+e.r+25,9,q.muted,J(t.table),.8))}return u.push(`</g>`,`</svg>`,``),u.join(`
|
|
1
|
+
import{$ as e,a as t,at as n,ct as r,o as i,ot as a,rt as o}from"./route-7eu-iAqD.js";import{c as s,l as c,s as l,u}from"./graph-link-C8P9s_0W.js";import{z as d}from"./button-BiFx4Lyw.js";import{c as f,l as p}from"./zone-CHDOrDBF.js";import{t as m}from"./loader-circle-BxDJOoJO.js";import{a as h,c as g,d as _,f as v,i as ee,l as y,m as b,o as x,p as S,r as C,s as te,t as ne,u as w}from"./graph-force-ChCGXQUt.js";import{t as T}from"./sliders-horizontal-DKtL_ql7.js";import{Gt as E,Wt as D,X as O,Y as k,qt as re,tn as A}from"./index-CpHnjRLv.js";var j={name:`eye-off`,size:24,node:[[`path`,{d:`M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49`,key:`ct8e1f`}],[`path`,{d:`M14.084 14.158a3 3 0 0 1-4.242-4.242`,key:`151rxh`}],[`path`,{d:`M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143`,key:`13bj9a`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]};j.node;var M=n(j),N={name:`layout-grid`,size:24,node:[[`rect`,{width:`7`,height:`7`,x:`3`,y:`3`,rx:`1`,key:`1g98yp`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`3`,rx:`1`,key:`6d4xhi`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`14`,rx:`1`,key:`nxv5o0`}],[`rect`,{width:`7`,height:`7`,x:`3`,y:`14`,rx:`1`,key:`1bb6yr`}]]};N.node;var ie=n(N),P={name:`undo-2`,size:24,node:[[`path`,{d:`M9 14 4 9l5-5`,key:`102s5s`}],[`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11`,key:`f3b9sd`}]]};P.node;var F=n(P),I=r(a(),1),L=()=>({labels:{},hidden:[],skipped:[],confirmed:[]}),R=e=>`${e.schema}.${e.name}`,z=e=>`psql-explorer-graph:${e}`,B=()=>globalThis.localStorage,V=e=>Array.isArray(e)&&e.every(e=>typeof e==`string`);function ae(e){try{let t=JSON.parse(B().getItem(z(e))??`null`);if(!t||typeof t!=`object`)return L();let n={};for(let[e,r]of Object.entries(t.labels??{}))V(r)&&r.length>0&&(n[e]=r);return{labels:n,hidden:(Array.isArray(t.hidden)?t.hidden:[]).filter(e=>typeof e?.schema==`string`&&typeof e.name==`string`),skipped:V(t.skipped)?t.skipped:[],confirmed:V(t.confirmed)?t.confirmed:[]}}catch{return L()}}function oe(e,t){try{B().setItem(z(e),JSON.stringify(t))}catch{}}var se=e=>JSON.stringify([e.from.schema,e.from.name,e.name]);function ce(e,t){let n=e=>new Set([...e.hidden.map(e=>`t:${R(e)}`),...e.skipped.map(e=>`k:${e}`)]),[r,i]=[n(e),n(t)];return[...r].filter(e=>!i.has(e)).length+[...i].filter(e=>!r.has(e)).length}function H(e,t){if(!t||t.length===0)return e.label;let n=t.filter(t=>t in e.row).map(t=>e.row[t]??`NULL`).join(`, `);return n===``?e.label:n.length>60?`${n.slice(0,59)}…`:n}function le(e,t){let n=(t??[]).filter(t=>t in e.row);return n.length>0&&n.every(t=>e.row[t]===null)}function ue(e,t){let n=new Map;for(let[r,i]of e){if(le(i,t[R(i.table)]))continue;let e=H(i,t[R(i.table)]);n.set(r,e===i.label?i:{...i,label:e})}return n}function de(e,t){let n=new Map;for(let t of e)n.set(t.id,R(t.table));let r=new Map;for(let e of t){let t=n.get(e.from);t&&!e.via&&r.set(t,(r.get(t)??new Set).add(e.constraint))}return new Set([...r].filter(([,e])=>e.size>=2).map(([e])=>e))}var U=o(),W=22,fe=(e,t)=>e.length>t?`${e.slice(0,t-1)}…`:e;function pe(e,t,n){let[r,i]=[n.x-e.x,n.y-e.y];if(r===0&&i===0)return e;let a=Math.min(r===0?1/0:t/2/Math.abs(r),i===0?1/0:W/2/Math.abs(i));return{x:e.x+r*a,y:e.y+i*a}}function me({environment:t,schema:n,start:r,settings:i,counts:a,onToggleTable:o,onToggleKey:s}){let c=D(async()=>{let[r,i]=await Promise.all([e.erd(t,n),e.schemaForeignKeys(t,n)]);return{tables:r,keys:i}},`${t}/${n}`),{frame:l,view:u,setView:d,dragged:f,startDrag:p,zoomBy:m}=w(),h=(0,I.useMemo)(()=>{if(!c.data)return;let e=new Map,t=t=>{let r=R(t);if(e.has(r))return;let i=t.schema===n?t.name:r;e.set(r,{key:r,table:{schema:t.schema,name:t.name},label:i,width:Math.max(72,fe(i,28).length*6.6+30)})};for(let e of c.data.tables)t(e);for(let e of c.data.keys)t(e.from),t(e.to);let r=[...e.values()].map(e=>({id:e.key,r:e.width/2})),i=c.data.keys.filter(e=>R(e.from)!==R(e.to)).map(e=>({source:R(e.from),target:R(e.to)})),a=x(r,i);return te(a,i),{pills:e,at:new Map(a.map(e=>[e.id,{x:e.x,y:e.y}])),keys:c.data.keys}},[c.data,n]),g=(0,I.useCallback)(()=>{let e=l.current?.getBoundingClientRect();if(!h||!e)return;let[t,n,r,i]=[1/0,1/0,-1/0,-1/0];for(let e of h.pills.values()){let a=h.at.get(e.key);t=Math.min(t,a.x-e.width/2),r=Math.max(r,a.x+e.width/2),n=Math.min(n,a.y-W/2-30),i=Math.max(i,a.y+W/2)}if(t===1/0)return;let a={x:t,y:n,width:r-t,height:i-n},o=S(a,e,16);d({k:o.k,x:o.x-a.x*o.k,y:o.y-a.y*o.k})},[h,l,d]);if((0,I.useLayoutEffect)(g,[g]),c.error)return(0,U.jsxs)(`p`,{className:`text-destructive mb-3 text-sm`,children:[`Could not load the schema: `,String(c.error)]});if(!h)return(0,U.jsx)(E,{className:`mb-3 h-48`});let v=new Set(i.hidden.map(R)),ee=new Set(i.skipped),b=new Map,C=e=>{let t=[R(e.from),R(e.to)].sort().join(`|`),n=b.get(t)??0;return b.set(t,n+1),n};return(0,U.jsxs)(`div`,{className:`relative mb-3`,children:[(0,U.jsx)(y,{zoomBy:m,fit:g}),(0,U.jsx)(`div`,{ref:l,onPointerDown:p,className:`border-border h-72 touch-none overflow-hidden border`,children:(0,U.jsxs)(`svg`,{role:`img`,"aria-label":`Schema map`,width:`100%`,height:`100%`,className:`cursor-grab select-none active:cursor-grabbing`,children:[(0,U.jsx)(`defs`,{children:(0,U.jsx)(`marker`,{id:`map-arrow`,viewBox:`0 0 10 10`,refX:9,refY:5,markerWidth:7,markerHeight:7,orient:`auto-start-reverse`,children:(0,U.jsx)(`path`,{d:`M0,0 L10,5 L0,10 z`,className:`fill-accent-text`})})}),(0,U.jsxs)(`g`,{transform:`translate(${u.x},${u.y}) scale(${u.k})`,children:[h.keys.map(e=>{let[t,n]=[h.at.get(R(e.from)),h.at.get(R(e.to))],[r,i]=[h.pills.get(R(e.from)),h.pills.get(R(e.to))];if(!t||!n||!r||!i)return null;let a=se(e),o=ee.has(a),c=`${e.name} (${e.fromColumns.join(`, `)} → ${e.toColumns.join(`, `)}): ${o?`not followed, click to follow`:`followed, click to stop following`}`,l=C(e),u;if(r===i){let[e,n]=[t.x,t.y-W/2];u=`M${e-12},${n} C${e-34-l*12},${n-40-l*10} ${e+34+l*12},${n-40-l*10} ${e+12},${n}`}else{let e={x:(t.x+n.x)/2,y:(t.y+n.y)/2},[a,o]=[n.x-t.x,n.y-t.y],s=Math.hypot(a,o)||1,c=l===0?0:(l%2?1:-1)*Math.ceil(l/2)*26,d={x:e.x-o/s*c,y:e.y+a/s*c},[f,p]=[pe(t,r.width,d),pe(n,i.width+6,d)];u=`M${f.x},${f.y} Q${d.x},${d.y} ${p.x},${p.y}`}return(0,U.jsxs)(`g`,{"data-key":e.name,"data-followed":!o,className:`cursor-pointer`,onClick:()=>!f.current&&s(a),children:[(0,U.jsx)(`path`,{d:u,fill:`none`,className:o?`stroke-muted-foreground`:`stroke-accent-text`,strokeWidth:1.4,strokeDasharray:o?`4 4`:void 0,opacity:o?.45:.85,markerEnd:`url(#map-arrow)`}),(0,U.jsx)(`path`,{d:u,fill:`none`,stroke:`transparent`,strokeWidth:12,children:(0,U.jsx)(`title`,{children:c})})]},a)}),[...h.pills.values()].map(e=>{let t=h.at.get(e.key),n=e.key===R(r),i=v.has(e.key),s=a.get(e.key),c=_(e.key);return(0,U.jsxs)(`g`,{transform:`translate(${t.x},${t.y})`,"data-table":e.key,"data-shown":!i,role:`button`,"aria-label":`${e.key}${i?` (left out)`:``}`,"aria-pressed":!i,className:n?`cursor-default`:`cursor-pointer`,opacity:i?.5:1,onClick:()=>!f.current&&!n&&o(e.table),children:[(0,U.jsx)(`title`,{children:n?`${e.key}: where the graph starts`:i?`${e.key}: left out, click to draw it`:`${e.key}: click to leave it out`}),(0,U.jsx)(`rect`,{x:-e.width/2,y:-11,width:e.width,height:W,rx:W/2,className:`fill-card`,stroke:n?`var(--primary)`:c,strokeWidth:n?2.5:1.5,strokeDasharray:i?`4 3`:void 0}),(0,U.jsx)(`circle`,{cx:-e.width/2+11,r:4,fill:c}),(0,U.jsx)(`text`,{x:6,y:4,textAnchor:`middle`,className:`fill-foreground text-[11px]`,textDecoration:i?`line-through`:void 0,children:fe(e.label,28)}),s!==void 0&&!i&&(0,U.jsx)(`text`,{x:e.width/2,y:-14,textAnchor:`end`,className:`fill-muted-foreground text-[9px]`,children:s})]},e.key)})]})]})})]})}var G=e=>`more:${e.node}|${e.constraint}`,K=24,he=50,q={background:`#ffffff`,card:`#f8fafc`,border:`#cbd5e1`,text:`#0f172a`,muted:`#64748b`,edge:`#2563eb`,start:`#7c3aed`},J=e=>`${e.schema}.${e.name}`,Y=(e,t)=>e.length>t?`${e.slice(0,t-1)}…`:e;function X(e){return e.replace(/[&<>"']/g,e=>`&#${e.charCodeAt(0)};`)}function ge(e,t=!1){let n=0,r=0;for(let t of e.values())n=Math.max(n,t.x+t.width),r=Math.max(r,t.y+t.height);return{width:n+48+(t?he:0),height:r+48}}var Z=e=>e.via?`${e.constraint}`:`${e.constraint} (${e.fromColumns.join(`, `)} → ${e.toColumns.join(`, `)})`;function _e({nodes:e,edges:t,more:n},r){let[i,a,o,s]=[1/0,1/0,-1/0,-1/0];for(let e of r.values())i=Math.min(i,e.x-Math.max(e.r,70)),o=Math.max(o,e.x+Math.max(e.r,70)),a=Math.min(a,e.y-e.r-(t.length>0?e.r*4:0)),s=Math.max(s,e.y+e.r+34);r.size===0&&([i,a,o,s]=[0,0,0,0]);let c=Math.ceil(o-i+48),l=Math.ceil(s-a+48),u=[`<?xml version="1.0" encoding="UTF-8"?>\n<svg xmlns="http://www.w3.org/2000/svg" width="${c}" height="${l}" viewBox="0 0 ${c} ${l}" font-family="system-ui, sans-serif">`,`<defs><marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="${q.edge}"/></marker></defs>`,`<rect width="${c}" height="${l}" fill="${q.background}"/>`,`<g transform="translate(${K-i},${K-a})">`],d=(e,t,n,r,i,a=1)=>`<text x="${e}" y="${t}" font-size="${n}" text-anchor="middle" fill="${r}" opacity="${a}" stroke="${q.background}" stroke-width="3" stroke-linejoin="round" paint-order="stroke">${X(i)}</text>`;for(let e of t){let[t,n]=[r.get(e.from),r.get(e.to)];if(!t||!n)continue;let i=`<title>${X(Z(e))}</title>`;if(e.from===e.to){u.push(`<path d="${h(t.x,t.y,t.r)}" fill="none" stroke="${q.edge}" stroke-width="1.5" opacity="0.6" marker-end="url(#arrow)">${i}</path>`);continue}let a=C(t,n,!e.via);u.push(`<line x1="${a.x1}" y1="${a.y1}" x2="${a.x2}" y2="${a.y2}" stroke="${q.edge}" stroke-width="1.5" opacity="0.6"${e.via?` stroke-dasharray="5 4"`:` marker-end="url(#arrow)"`}>${i}</line>`)}for(let e of n){let t=r.get(G(e)),n=r.get(e.node);if(!t)continue;if(n){let e=C(n,t,!1);u.push(`<line x1="${e.x1}" y1="${e.y1}" x2="${e.x2}" y2="${e.y2}" stroke="${q.muted}" stroke-width="1" stroke-dasharray="3 3" opacity="0.6"/>`)}let i=e.count-e.shown;u.push(`<circle cx="${t.x}" cy="${t.y}" r="${t.r}" fill="none" stroke="${q.muted}" stroke-dasharray="4 3"/>`,d(t.x,t.y+t.r+13,11,q.text,`+${i.toLocaleString(`en-US`)}${e.capped?`+`:``} more in ${e.table.name}`))}for(let t of e){let e=r.get(t.id);e&&u.push(`<circle cx="${e.x}" cy="${e.y}" r="${e.r}" fill="${_(J(t.table))}" stroke="${t.start?q.start:q.background}" stroke-width="${t.start?3:1.5}"/>`,d(e.x,e.y+e.r+13,11,q.text,Y(t.label,24)),d(e.x,e.y+e.r+25,9,q.muted,J(t.table),.8))}return u.push(`</g>`,`</svg>`,``),u.join(`
|
|
2
2
|
`)}function ve(e){if(e.dots)return _e(e,e.dots);let{nodes:t,edges:n,more:r,placed:i}=e,{width:a,height:o}=ge(i,n.some(e=>e.from===e.to)),s=[];s.push(`<?xml version="1.0" encoding="UTF-8"?>\n<svg xmlns="http://www.w3.org/2000/svg" width="${a}" height="${o}" viewBox="0 0 ${a} ${o}" font-family="system-ui, sans-serif">`,`<defs><marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="${q.edge}"/></marker></defs>`,`<rect width="${a}" height="${o}" fill="${q.background}"/>`,`<g transform="translate(${K},${K})">`);for(let e of n){let t=i.get(e.from),n=i.get(e.to);t&&n&&s.push(`<path d="${v(t,n).d}" fill="none" stroke="${q.edge}" stroke-width="1.5" opacity="0.85" marker-end="url(#arrow)"><title>${X(Z(e))}</title></path>`)}for(let e of r){let t=i.get(G(e));if(!t)continue;let n=e.count-e.shown;s.push(`<g transform="translate(${t.x},${t.y})"><rect width="190" height="30" rx="6" fill="none" stroke="${q.muted}" stroke-dasharray="4 3"/><text x="95" y="19" text-anchor="middle" font-size="12" fill="${q.text}">${X(`+${n.toLocaleString(`en-US`)}${e.capped?`+`:``} more in ${e.table.name}`)}</text></g>`)}for(let e of t){let t=i.get(e.id);if(!t)continue;let n=Object.entries(e.key).map(([e,t])=>`${e} = ${t??`null`}`).join(`, `);s.push(`<g transform="translate(${t.x},${t.y})">`,`<rect width="190" height="52" rx="6" fill="${q.card}" stroke="${e.start?q.start:q.border}" stroke-width="${e.start?2.5:1}"/>`,`<path d="M0,6 a6,6 0 0 1 6,-6 h178 a6,6 0 0 1 6,6 v10 h-190 z" fill="${b(J(e.table))}"/>`,`<text x="8" y="12" font-size="10" font-weight="bold" fill="#ffffff">${X(Y(J(e.table),28))}</text>`,`<text x="8" y="31" font-size="12" fill="${q.text}">${X(Y(e.label,26))}</text>`,`<text x="8" y="45" font-size="10" fill="${q.muted}">${X(Y(n,32))}</text>`,`</g>`)}return s.push(`</g>`,`</svg>`,``),s.join(`
|
|
3
3
|
`)}function ye({nodes:e,edges:t}){return JSON.stringify({nodes:e.map(({id:e,table:t,key:n,label:r,row:i,distance:a,start:o})=>({id:e,table:t,key:n,label:r,row:i,distance:a,start:o})),edges:t.map(({id:e,from:t,to:n,constraint:r,fromColumns:i,toColumns:a,via:o})=>({id:e,from:t,to:n,constraint:r,fromColumns:i,toColumns:a,...o?{via:o}:{}}))},null,2)}function be(e){let t=/<svg[^>]*\swidth="(\d+(?:\.\d+)?)"[^>]*\sheight="(\d+(?:\.\d+)?)"/.exec(e);return t?{width:Number(t[1]),height:Number(t[2])}:void 0}var Q=`border-input bg-background rounded-lg border px-2 py-1 text-sm`,$=e=>`${e.schema}.${e.name}`,xe=(e,t)=>e.length>t?`${e.slice(0,t-1)}…`:e,Se=()=>({nodes:new Map,edges:new Map,more:new Map,moreStart:!1,truncated:!1});function Ce(e,t,n){let r=new Map(e.nodes);for(let e of t.nodes)r.has(e.id)||r.set(e.id,e);let i=new Map(e.edges);for(let e of t.edges)i.has(e.id)||i.set(e.id,e);let a=new Map(e.more);n&&a.delete(G(n));for(let e of t.more)a.set(G(e),e);return{nodes:r,edges:i,more:a,moreStart:e.moreStart,truncated:e.truncated||t.truncated}}var we=e=>Object.entries(e.key).map(([e,t])=>t===null?{column:e,op:`null`}:{column:e,op:`eq`,value:t});function Te({environment:e,node:t,onClose:n}){(0,I.useEffect)(()=>{let e=e=>e.key===`Escape`&&n();return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]);let r=i({environment:e,object:{kind:`table`,schema:t.table.schema,name:t.table.name},rows:{filters:we(t),sort:[]}});return(0,U.jsxs)(`aside`,{"aria-label":`Row`,className:`bg-background border-border fixed top-14 right-0 bottom-0 z-20 flex w-full max-w-md flex-col border-l shadow-xl`,children:[(0,U.jsxs)(`header`,{className:`border-border flex items-center justify-between gap-3 border-b px-4 py-3`,children:[(0,U.jsx)(`h3`,{className:`text-accent-text truncate`,children:$(t.table)}),(0,U.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,U.jsxs)(`a`,{href:r,className:`text-accent-text flex items-center gap-1 text-sm`,children:[`Open in table `,(0,U.jsx)(f,{className:`size-3`})]}),(0,U.jsx)(`button`,{type:`button`,onClick:n,"aria-label":`Close row`,children:(0,U.jsx)(re,{className:`size-4`})})]})]}),(0,U.jsx)(`dl`,{className:`flex-1 overflow-y-auto p-4 text-sm`,children:Object.entries(t.row).map(([e,t])=>(0,U.jsxs)(`div`,{className:`border-border border-b py-2`,children:[(0,U.jsx)(`dt`,{className:`text-muted-foreground text-xs`,children:e}),(0,U.jsx)(`dd`,{className:`mt-0.5 font-mono break-all whitespace-pre-wrap`,children:t===null?(0,U.jsx)(`span`,{className:`text-muted-foreground italic`,children:`NULL`}):t})]},e))})]})}function Ee({drawing:e,hidden:t,onToggle:n}){let r=new Map;for(let t of e.nodes.values()){let e=$(t.table);r.set(e,(r.get(e)??0)+1)}let i=new Map;for(let t of e.edges.values())i.set(t.constraint,(i.get(t.constraint)??0)+1);let a=e=>`flex items-center gap-1.5 rounded-lg border px-2 py-0.5 text-xs ${e?`text-muted-foreground border-dashed line-through opacity-60`:`border-input`}`;return(0,U.jsxs)(`div`,{"aria-label":`Legend`,className:`mb-3 flex flex-wrap items-center gap-x-6 gap-y-2`,children:[(0,U.jsx)(`ul`,{className:`flex flex-wrap gap-1.5`,"aria-label":`Tables`,children:[...r].sort().map(([e,r])=>(0,U.jsx)(`li`,{children:(0,U.jsxs)(`button`,{type:`button`,"aria-pressed":!t.tables.has(e),onClick:()=>n(`tables`,e),className:a(t.tables.has(e)),title:t.tables.has(e)?`Show these rows`:`Hide these rows`,children:[(0,U.jsx)(`span`,{className:`size-2.5 rounded-full`,style:{background:_(e)}}),e,` `,(0,U.jsx)(`span`,{className:`text-muted-foreground`,children:r})]})},e))}),i.size>0&&(0,U.jsx)(`ul`,{className:`flex flex-wrap gap-1.5`,"aria-label":`Keys`,children:[...i].sort().map(([e,r])=>(0,U.jsx)(`li`,{children:(0,U.jsxs)(`button`,{type:`button`,"aria-pressed":!t.keys.has(e),onClick:()=>n(`keys`,e),className:a(t.keys.has(e)),title:t.keys.has(e)?`Show these links`:`Hide these links`,children:[(0,U.jsx)(`span`,{className:`text-accent-text`,children:`→`}),e,` `,(0,U.jsx)(`span`,{className:`text-muted-foreground`,children:r})]})},e))})]})}function De({environment:t,initial:n,busy:r,onDraw:i}){let a=D(()=>e.schemas(t),t).data,[o,s]=(0,I.useState)(n.schema??``),[c,l]=(0,I.useState)(n.table??``),[u,d]=(0,I.useState)(n.filters??[]),[f,p]=(0,I.useState)(n.depth??1),[m,h]=(0,I.useState)(n.direction??`both`),[g,_]=(0,I.useState)(n.keys??[]),v=o||a?.find(e=>e.tables>0)?.name||``,ee=D(()=>v?e.objects(t,v):Promise.resolve(void 0),`${t}/${v}`).data?.tables.filter(e=>e.kind===`table`||e.kind===`partitioned`)??[],y=D(()=>v&&c?e.relation(t,{kind:`table`,schema:v,name:c}):Promise.resolve(void 0),`${t}/${v}/${c}`),b=y.data?.columns??[],x=(0,I.useRef)(!1),S=(0,I.useCallback)(e=>i({schema:v,table:c,filters:e.filter(O),depth:f,...g.length>0?{keys:g}:{}},m),[i,v,c,f,m,g]);return(0,I.useEffect)(()=>{!x.current&&n.table&&y.data&&(x.current=!0,i({schema:v,table:c,filters:(n.filters??[]).filter(O),depth:f,...g.length>0?{keys:g}:{}},m,n.expanded))},[n.table,y.data]),(0,U.jsxs)(`div`,{className:`mb-4 flex flex-col gap-3`,children:[(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,U.jsx)(`select`,{"aria-label":`Schema`,value:v,onChange:e=>{s(e.target.value),l(``),_([]),d([])},className:Q,children:a?.map(e=>(0,U.jsx)(`option`,{children:e.name},e.name))}),(0,U.jsxs)(`select`,{"aria-label":`Table`,value:c,onChange:e=>{l(e.target.value),_([]),d([])},className:Q,children:[(0,U.jsx)(`option`,{value:``,children:`pick a table`}),ee.map(e=>(0,U.jsx)(`option`,{children:e.name},e.name))]}),(0,U.jsxs)(`label`,{className:`text-muted-foreground flex items-center gap-1 text-sm`,children:[`depth`,(0,U.jsx)(`select`,{"aria-label":`Depth`,value:f,onChange:e=>p(Number(e.target.value)),className:Q,children:[0,1,2,3].map(e=>(0,U.jsx)(`option`,{children:e},e))})]}),(0,U.jsxs)(`select`,{"aria-label":`Direction`,value:m,onChange:e=>h(e.target.value),className:Q,children:[(0,U.jsx)(`option`,{value:`both`,children:`both ways`}),(0,U.jsx)(`option`,{value:`out`,children:`rows it points at`}),(0,U.jsx)(`option`,{value:`in`,children:`rows pointing at it`})]}),(0,U.jsx)(`button`,{type:`button`,onClick:()=>S(u),disabled:!c||r,className:`bg-primary text-primary-foreground rounded-lg px-3 py-1 text-sm disabled:opacity-50`,children:`Draw`})]}),g.length>0&&(0,U.jsxs)(`p`,{className:`text-muted-foreground flex items-center gap-2 text-sm`,children:[`Starting from `,g.length,` `,g.length===1?`row`:`rows`,` picked in a query; the filters are not used.`,(0,U.jsx)(`button`,{type:`button`,onClick:()=>_([]),className:`border-input hover:text-accent-text rounded-lg border px-2 py-0.5 text-xs`,children:`Use filters instead`})]}),b.length>0&&g.length===0&&(0,U.jsx)(k,{columns:b,draft:u,onChange:d,onApply:()=>S(u)})]})}function Oe(e,t){let n=[...e.nodes.values()].filter(e=>!t.tables.has($(e.table))),r=new Set(n.map(e=>e.id));return{nodes:n,edges:[...e.edges.values()].filter(e=>!t.keys.has(e.constraint)&&r.has(e.from)&&r.has(e.to)),more:[...e.more.values()].filter(e=>r.has(e.node)&&!t.tables.has($(e.table))&&!t.keys.has(e.constraint))}}var ke=8,Ae=12,je=9,Me=e=>e.start?Ae:ke;function Ne({drawing:e,hidden:t,expanding:n,expanded:r,fitSignal:i,onExpand:a,onOpen:o,onLoadMore:s,onDrawn:c}){let{frame:l,view:u,setView:d,startDrag:f,zoomBy:p}=w(),[m,v]=(0,I.useState)(),[b,T]=(0,I.useState)(),[E,D]=(0,I.useState)(new Map),O=(0,I.useRef)({nodes:[],links:[],alpha:0,frame:0}),k=(0,I.useRef)(-1),re=(0,I.useRef)(u);(0,I.useEffect)(()=>{re.current=u},[u]);let A=(0,I.useMemo)(()=>Oe(e,t),[e,t]),j=(0,I.useCallback)(()=>{D(new Map(O.current.nodes.map(e=>[e.id,{x:e.x,y:e.y,r:e.r}])))},[]),M=(0,I.useCallback)(()=>{let e=O.current;if(e.frame)return;let t=()=>{e.alpha<=.012?e.frame=0:(g(e.nodes,e.links,e.alpha),e.alpha*=1-ne,j(),e.frame=requestAnimationFrame(t))};e.frame=requestAnimationFrame(t)},[j]);(0,I.useEffect)(()=>{let e=O.current;return()=>cancelAnimationFrame(e.frame)},[]);let N=(0,I.useCallback)(()=>{let e=l.current?.getBoundingClientRect();if(!e||O.current.nodes.length===0)return;let t=ee(O.current.nodes),n=S(t,e);d({k:n.k,x:n.x-t.x*n.k,y:n.y-t.y*n.k})},[l,d]);(0,I.useLayoutEffect)(()=>{let e=O.current,t=[...A.nodes.map(e=>({id:e.id,r:Me(e)})),...A.more.map(e=>({id:G(e),r:je}))],n=[...A.edges.map(e=>({source:e.from,target:e.to})),...A.more.map(e=>({source:e.node,target:G(e)}))],r=k.current!==i,a=r?void 0:new Map(e.nodes.map(e=>[e.id,{x:e.x,y:e.y}]));e.nodes=x(t,n,a),e.links=n,r?(k.current=i,te(e.nodes,n),e.alpha=0,j(),N()):(e.alpha=.5,M())},[A,i]),(0,I.useEffect)(()=>{c(()=>{let e=new Map(O.current.nodes.map(e=>[e.id,{x:e.x,y:e.y,r:e.r}]));return{nodes:A.nodes,edges:A.edges,more:A.more,placed:new Map,dots:e}})},[A,c]);let ie=(e,t)=>{if(e.button!==0)return;e.stopPropagation();let n=l.current?.getBoundingClientRect(),r=O.current.nodes.find(e=>e.id===t.id);if(!n||!r)return;let i={x:e.clientX,y:e.clientY},s=e.shiftKey,c=!1,u=e=>{if(!c&&Math.hypot(e.clientX-i.x,e.clientY-i.y)<4)return;c=!0;let t=re.current;r.pinned=!0,r.x=(e.clientX-n.left-t.x)/t.k,r.y=(e.clientY-n.top-t.y)/t.k,O.current.alpha=Math.max(O.current.alpha,.35),M()},d=()=>{window.removeEventListener(`pointermove`,u),window.removeEventListener(`pointerup`,d),r.pinned=!1,!c&&(s||!t.expandable?o(t):a(t))};window.addEventListener(`pointermove`,u),window.addEventListener(`pointerup`,d)},P=(0,I.useMemo)(()=>{if(!m)return;let e=new Set([m]);for(let t of A.edges)t.from===m&&e.add(t.to),t.to===m&&e.add(t.from);for(let t of A.more)t.node===m&&e.add(G(t));return e},[m,A]),F=b?e.edges.get(b):void 0,L=F&&E.get(F.from),R=F&&E.get(F.to),z={paintOrder:`stroke`};return(0,U.jsxs)(`div`,{className:`relative`,children:[(0,U.jsx)(y,{zoomBy:p,fit:N}),(0,U.jsx)(`div`,{ref:l,onPointerDown:f,className:`border-border h-[70vh] min-h-96 touch-none overflow-hidden border`,children:(0,U.jsxs)(`svg`,{role:`img`,"aria-label":`Record graph`,width:`100%`,height:`100%`,className:`cursor-grab select-none active:cursor-grabbing`,children:[(0,U.jsx)(`defs`,{children:(0,U.jsx)(`marker`,{id:`graph-arrow`,viewBox:`0 0 10 10`,refX:9,refY:5,markerWidth:7,markerHeight:7,orient:`auto-start-reverse`,children:(0,U.jsx)(`path`,{d:`M0,0 L10,5 L0,10 z`,className:`fill-accent-text`})})}),(0,U.jsxs)(`g`,{transform:`translate(${u.x},${u.y}) scale(${u.k})`,children:[A.edges.map(e=>{let t=E.get(e.from),n=E.get(e.to);if(!t||!n)return null;let r=b===e.id||(P?P.has(e.from)&&P.has(e.to)&&(e.from===m||e.to===m):!1),i=P&&!r?.12:b&&b!==e.id?.3:r?.95:.5,a=e.via?e.constraint:`${e.constraint} (${e.fromColumns.join(`, `)} → ${e.toColumns.join(`, `)})`,o=e.from===e.to?void 0:C(t,n,!e.via);return(0,U.jsx)(`g`,{"data-edge":e.constraint,children:o?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`line`,{...o,className:`stroke-accent-text`,strokeWidth:r?2.2:1.4,strokeDasharray:e.via?`5 4`:void 0,opacity:i,markerEnd:e.via?void 0:`url(#graph-arrow)`}),(0,U.jsx)(`line`,{...o,stroke:`transparent`,strokeWidth:12,pointerEvents:`stroke`,onPointerEnter:()=>T(e.id),onPointerLeave:()=>T(void 0),children:(0,U.jsx)(`title`,{children:a})})]}):(0,U.jsx)(`path`,{d:h(t.x,t.y,t.r),fill:`none`,className:`stroke-accent-text`,strokeWidth:1.4,opacity:i,markerEnd:`url(#graph-arrow)`,children:(0,U.jsx)(`title`,{children:a})})},e.id)}),A.more.map(e=>{let t=E.get(G(e)),r=E.get(e.node);if(!t)return null;let i=e.count-e.shown,a=n.has(G(e)),o=P&&!P.has(G(e));return(0,U.jsxs)(`g`,{opacity:o?.2:1,children:[r&&(0,U.jsx)(`line`,{...C(r,t,!1),className:`stroke-muted-foreground`,strokeWidth:1,strokeDasharray:`3 3`,opacity:.6}),(0,U.jsxs)(`g`,{transform:`translate(${t.x},${t.y})`,className:`cursor-pointer`,role:`button`,"aria-label":`more in ${e.table.name}`,onPointerDown:e=>e.stopPropagation(),onClick:()=>!a&&s(e),children:[(0,U.jsx)(`circle`,{r:t.r,fill:`var(--background)`,strokeDasharray:`4 3`,className:`stroke-muted-foreground`}),(0,U.jsx)(`text`,{y:t.r+13,textAnchor:`middle`,className:`fill-foreground text-[11px]`,stroke:`var(--background)`,strokeWidth:3,strokeLinejoin:`round`,style:z,children:a?`loading…`:`+${i.toLocaleString()}${e.capped?`+`:``} more in ${e.table.name}`})]})]},G(e))}),A.nodes.map(e=>{let t=E.get(e.id);if(!t)return null;let i=_($(e.table)),a=n.has(e.id),o=Object.entries(e.key).map(([e,t])=>`${e} = ${t??`null`}`).join(`, `);return(0,U.jsxs)(`g`,{transform:`translate(${t.x},${t.y})`,"data-node":e.id,role:`button`,"aria-label":`${$(e.table)} ${e.label}`,className:e.expandable?`cursor-pointer`:`cursor-default`,opacity:P&&!P.has(e.id)?.2:1,onPointerDown:t=>ie(t,e),onPointerEnter:()=>v(e.id),onPointerLeave:()=>v(void 0),children:[(0,U.jsx)(`title`,{children:`${$(e.table)}\n${o}`}),(0,U.jsx)(`circle`,{r:t.r+6,fill:`transparent`}),(0,U.jsx)(`circle`,{r:t.r,fill:i,stroke:e.start?`var(--primary)`:`var(--background)`,strokeWidth:e.start?3:1.5}),r.has(e.id)&&!a&&(0,U.jsx)(`circle`,{r:t.r+4,fill:`none`,className:`stroke-accent-text`,strokeWidth:1.2,opacity:.7}),a&&(0,U.jsx)(`circle`,{r:t.r+5,fill:`none`,className:`stroke-accent-text`,strokeWidth:2,strokeDasharray:`14 14`,"aria-label":`Loading`,children:(0,U.jsx)(`animateTransform`,{attributeName:`transform`,type:`rotate`,from:`0`,to:`360`,dur:`0.8s`,repeatCount:`indefinite`})}),(0,U.jsx)(`text`,{y:t.r+14,textAnchor:`middle`,className:`fill-foreground text-[11px]`,stroke:`var(--background)`,strokeWidth:3,strokeLinejoin:`round`,style:z,children:xe(e.label,24)}),(0,U.jsx)(`text`,{y:t.r+26,textAnchor:`middle`,className:`fill-muted-foreground text-[9px]`,opacity:.75,stroke:`var(--background)`,strokeWidth:3,strokeLinejoin:`round`,style:z,children:$(e.table)})]},e.id)}),F&&L&&R&&(0,U.jsxs)(`g`,{transform:`translate(${(L.x+R.x)/2},${(L.y+R.y)/2})`,pointerEvents:`none`,children:[(0,U.jsx)(`rect`,{x:-4,y:-18,width:F.constraint.length*6.4+8,height:18,rx:4,className:`fill-card stroke-border`}),(0,U.jsx)(`text`,{y:-5,className:`fill-foreground text-[11px]`,children:F.constraint})]})]})]})})]})}function Pe({rows:e,settings:t,open:n,onToggle:r,onLabel:i,onRemove:a,onRestore:o,onDone:s,asking:c}){let l=e=>`rounded-md border px-1.5 py-0.5 font-mono text-[11px] ${e?`border-primary bg-primary/15 text-foreground`:`border-input text-muted-foreground hover:text-foreground`}`;return(0,U.jsxs)(`section`,{"aria-label":`Rows and tables`,className:`mb-3 text-sm`,children:[(0,U.jsxs)(`button`,{type:`button`,onClick:r,"aria-expanded":n,className:`border-input hover:text-accent-text flex items-center gap-1.5 rounded-lg border px-2 py-1 text-xs`,children:[(0,U.jsx)(T,{className:`size-3`}),`Labels and tables`,t.hidden.length>0&&(0,U.jsxs)(`span`,{className:`text-muted-foreground`,children:[`· `,t.hidden.length,` removed`]}),c&&!n&&(0,U.jsx)(`span`,{className:`bg-primary size-1.5 rounded-full`,"aria-label":`Needs a look`})]}),n&&(0,U.jsxs)(`div`,{className:`border-border mt-2 rounded-lg border p-3`,children:[(0,U.jsxs)(`p`,{className:`text-muted-foreground mb-3 text-xs`,children:[c?`Each kind of row in the graph is named by its key. Pick the fields to name it by instead (several are joined), and remove join tables: `:`Pick the fields that name each kind of row (several are joined), and remove join tables: `,`the graph then goes through them, linking the rows at either end directly.`]}),(0,U.jsx)(`ul`,{className:`flex max-h-72 flex-col gap-3 overflow-y-auto`,children:e.map(e=>{let n=t.labels[R(e.table)],r=n??e.keyColumns;return(0,U.jsxs)(`li`,{className:`flex flex-col gap-1.5`,"data-entity":e.name,children:[(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,U.jsx)(`span`,{className:`size-3 rounded-full`,style:{background:_(e.name)}}),(0,U.jsx)(`span`,{className:`font-medium`,children:e.name}),(0,U.jsx)(`span`,{className:`text-muted-foreground text-xs`,children:e.count}),e.join&&(0,U.jsx)(`span`,{className:`text-accent-text text-xs`,children:`looks like a join table`}),n&&(0,U.jsxs)(`button`,{type:`button`,onClick:()=>i(e.table,[]),className:`text-muted-foreground hover:text-foreground flex items-center gap-1 text-xs`,children:[(0,U.jsx)(F,{className:`size-3`}),` use the key`]}),(0,U.jsxs)(`button`,{type:`button`,onClick:()=>a(e.table),title:`Leave this table out of the graph; the rows on either side of it are linked directly`,className:`border-input hover:text-accent-text ml-auto flex items-center gap-1 rounded-lg border px-2 py-0.5 text-xs`,children:[(0,U.jsx)(M,{className:`size-3`}),` Remove from graph`]})]}),(0,U.jsx)(`div`,{className:`flex flex-wrap gap-1`,role:`group`,"aria-label":`Fields that name ${e.name}`,children:e.columns.map(t=>{let n=r.includes(t);return(0,U.jsx)(`button`,{type:`button`,"aria-pressed":n,className:l(n),title:e.keyColumns.includes(t)?`Part of the key`:void 0,onClick:()=>{let a=e.columns.filter(e=>e===t?!n:r.includes(e)),o=a.length===e.keyColumns.length&&a.every(t=>e.keyColumns.includes(t));i(e.table,a.length===0||o?[]:a)},children:t},t)})})]},e.name)})}),t.hidden.length>0&&(0,U.jsxs)(`div`,{className:`mt-3 flex flex-wrap items-center gap-1.5 text-xs`,"aria-label":`Removed tables`,children:[(0,U.jsx)(`span`,{className:`text-muted-foreground`,children:`Removed:`}),t.hidden.map(e=>(0,U.jsxs)(`button`,{type:`button`,onClick:()=>o(e),title:`Put this table back in the graph`,className:`border-input hover:text-accent-text flex items-center gap-1 rounded-lg border px-2 py-0.5`,children:[(0,U.jsx)(F,{className:`size-3`}),` `,R(e)]},R(e)))]}),(0,U.jsx)(`div`,{className:`mt-3 flex justify-end`,children:(0,U.jsx)(`button`,{type:`button`,onClick:s,className:`bg-primary text-primary-foreground rounded-lg px-3 py-1 text-xs`,children:`Done`})})]})]})}function Fe({environment:n,graph:r}){let[i,a]=(0,I.useState)(),[o,f]=(0,I.useState)(),[h,g]=(0,I.useState)(!1),[_,v]=(0,I.useState)(`both`),[ee,y]=(0,I.useState)(new Set),[b,x]=(0,I.useState)(new Set),[S,C]=(0,I.useState)(0),[te,ne]=(0,I.useState)({tables:new Set,keys:new Set}),[w,T]=(0,I.useState)(),[D,O]=(0,I.useState)(),k=(0,I.useRef)(void 0),re=(0,I.useCallback)(e=>{k.current=e},[]),j=(0,I.useRef)(void 0);(0,I.useEffect)(()=>{j.current=i},[i]);let[M,N]=(0,I.useState)(()=>ae(n)),[P,F]=(0,I.useState)(n);P!==n&&(F(n),N(ae(n)));let L=(0,I.useRef)(M);(0,I.useEffect)(()=>{L.current=M,P===n&&oe(n,M)},[M,P,n]);let[z,B]=(0,I.useState)(),[V,se]=(0,I.useState)(()=>({hidden:M.hidden,skipped:M.skipped})),H=(0,I.useRef)(V),le=(0,I.useCallback)((t,r,i=[],o=!1)=>{let{hidden:s,skipped:c}=L.current;H.current={hidden:s,skipped:c},se({hidden:s,skipped:c}),g(!0),f(void 0),v(r),O(t),e.graph(n,{schema:t.schema,name:t.table},{filters:t.filters,...t.keys?{keys:t.keys}:{},depth:t.depth,direction:r,hide:s,skipKeys:c}).then(async t=>{let l={...Ce(Se(),t),moreStart:t.moreStart},u=new Set;for(let t of i){let i=l.nodes.get(t);if(i?.expandable)try{let a=await e.expandGraph(n,{node:t,drawn:[...l.nodes.keys(),...l.edges.keys()],distance:i.distance,direction:r,hide:s,skipKeys:c});l=Ce(l,a),u.add(t)}catch{break}}a(l),x(u),ne({tables:new Set,keys:new Set}),T(void 0),C(e=>e+1),o||B([...l.nodes.values()].some(e=>!L.current.confirmed.includes(R(e.table))))}).catch(e=>f(e.message)).finally(()=>g(!1))},[n]),W=(0,I.useCallback)((t,r,i)=>{let o=j.current;if(!o)return;let s=i?G(i):t;y(e=>new Set(e).add(s)),e.expandGraph(n,{node:t,drawn:[...o.nodes.keys(),...o.edges.keys()],distance:r,direction:_,...i?{key:i.constraint,skip:i.shown}:{},hide:H.current.hidden,skipKeys:H.current.skipped}).then(e=>{a(t=>t&&Ce(t,e,i)),i||x(e=>new Set(e).add(t))}).catch(e=>f(e.message)).finally(()=>y(e=>{let t=new Set(e);return t.delete(s),t}))},[n,_]);(0,I.useEffect)(()=>{D&&t({environment:n,graph:{...D,direction:_,...b.size>0?{expanded:[...b]}:{}}})},[n,D,_,b]);let[fe,pe]=(0,I.useState)(),[K,he]=(0,I.useState)(),q=async e=>{let t=k.current?.();if(!t||t.nodes.length===0)return;he(void 0);let n=l(`graph-${D?.table??`rows`}`,`graph`);try{if(e===`json`)s(new Blob([ye(t)],{type:`application/json`}),`${n}.json`);else{let r=ve(t);if(e===`svg`)s(new Blob([r],{type:`image/svg+xml`}),`${n}.svg`);else{let e=be(r)??ge(t.placed),i=Math.min(2,8e3/Math.max(e.width,e.height));s(await c(r,e.width,e.height,i),`${n}.png`)}}pe(e),window.setTimeout(()=>pe(void 0),1500)}catch(e){he(e instanceof Error?e.message:String(e))}},J=(e,t)=>ne(n=>{let r=new Set(n[e]);return r.delete(t)||r.add(t),{...n,[e]:r}}),Y=(0,I.useMemo)(()=>i&&{...i,nodes:ue(i.nodes,M.labels)},[i,M.labels]),X=(0,I.useMemo)(()=>{if(!i)return[];let e=de(i.nodes.values(),i.edges.values()),t=new Map;for(let n of i.nodes.values()){let r=$(n.table),i=t.get(r);i?i.count++:t.set(r,{table:n.table,name:r,count:1,columns:Object.keys(n.row),keyColumns:Object.keys(n.key),join:e.has(r)})}return[...t.values()].sort((e,t)=>e.name.localeCompare(t.name))},[i]),Z=X.some(e=>!M.confirmed.includes(R(e.table))),_e=(e,t)=>N(n=>{let r={...n.labels};return t.length===0?delete r[R(e)]:r[R(e)]=t,{...n,labels:r}}),Q=e=>N(t=>({...t,hidden:t.hidden.some(t=>R(t)===R(e))?t.hidden.filter(t=>R(t)!==R(e)):[...t.hidden,e]})),xe=e=>N(t=>({...t,skipped:t.skipped.includes(e)?t.skipped.filter(t=>t!==e):[...t.skipped,e]})),we=ce(V,M),Oe=(0,I.useMemo)(()=>{let e=new Map;for(let t of i?.nodes.values()??[])e.set(R(t.table),(e.get(R(t.table))??0)+1);return e},[i]),ke=w?Y?.nodes.get(w):void 0;return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsxs)(`h2`,{className:`text-accent-text mb-1 flex items-center gap-2 text-2xl`,children:[(0,U.jsx)(u,{className:`size-6`}),`Graph`]}),(0,U.jsx)(`p`,{className:`text-muted-foreground mb-4 text-sm`,children:`Pick some rows and see the rows linked to them through foreign keys. Click a dot to follow its links; shift-click to see the row. Drag a dot to move it, drag the background to move around, scroll to zoom.`}),(0,U.jsx)(De,{environment:n,initial:r,busy:h,onDraw:le}),o&&(0,U.jsx)(`p`,{className:`text-destructive mb-3 text-sm`,children:o}),h&&!i?(0,U.jsx)(E,{className:`h-80`}):i?i.nodes.size===0?(0,U.jsxs)(`p`,{className:`text-muted-foreground flex items-center gap-2 text-sm`,children:[(0,U.jsx)(A,{className:`size-4`}),` No rows matched.`]}):(0,U.jsxs)(U.Fragment,{children:[(0,U.jsxs)(`p`,{className:`text-muted-foreground mb-2 flex items-center gap-2 text-xs`,children:[h&&(0,U.jsx)(m,{className:`size-3 animate-spin`}),i.nodes.size,` rows, `,i.edges.size,` links`,i.moreStart&&` · more rows matched than were drawn`,i.truncated&&` · the limit on rows was reached, so some linked rows are missing`]}),(0,U.jsxs)(`div`,{className:`text-muted-foreground mb-3 flex flex-wrap items-center gap-2 text-xs`,children:[(0,U.jsxs)(`button`,{type:`button`,onClick:()=>C(e=>e+1),title:`Lay the graph out afresh and fit it to the screen`,className:`border-input hover:text-accent-text flex items-center gap-1 rounded-lg border px-2 py-1`,children:[(0,U.jsx)(ie,{className:`size-3`}),` Re-layout`]}),(0,U.jsx)(`span`,{className:`ml-2`,children:`Export`}),[`svg`,`png`,`json`].map(e=>(0,U.jsxs)(`button`,{type:`button`,onClick:()=>void q(e),className:`border-input hover:text-accent-text flex items-center gap-1 rounded-lg border px-2 py-1 uppercase`,children:[fe===e?(0,U.jsx)(d,{className:`size-3`}):(0,U.jsx)(p,{className:`size-3`}),` `,e]},e)),K&&(0,U.jsx)(`span`,{role:`alert`,className:`text-destructive`,children:K})]}),D&&(0,U.jsx)(`p`,{className:`text-muted-foreground mb-1 text-xs`,children:`Schema map: click a table to leave it out of the graph (it is gone through, like a join table), and click an arrow to stop following that key.`}),D&&(0,U.jsx)(me,{environment:n,schema:D.schema,start:{schema:D.schema,name:D.table},settings:M,counts:Oe,onToggleTable:Q,onToggleKey:xe}),we>0&&D&&(0,U.jsxs)(`p`,{className:`mb-3 flex flex-wrap items-center gap-2 text-sm`,role:`status`,children:[we,` `,we===1?`change`:`changes`,` to the tables and keys in the graph.`,(0,U.jsx)(`button`,{type:`button`,onClick:()=>le(D,_,[...b],!0),disabled:h,className:`bg-primary text-primary-foreground rounded-lg px-3 py-1 text-xs disabled:opacity-50`,children:`Draw again`}),(0,U.jsx)(`button`,{type:`button`,onClick:()=>N(e=>({...e,hidden:V.hidden,skipped:V.skipped})),className:`border-input hover:text-accent-text rounded-lg border px-2 py-1 text-xs`,children:`Undo`})]}),(0,U.jsx)(Pe,{rows:X,settings:M,open:z??Z,asking:Z,onToggle:()=>B(!(z??Z)),onLabel:_e,onRemove:Q,onRestore:Q,onDone:()=>{N(e=>({...e,confirmed:[...new Set([...e.confirmed,...X.map(e=>R(e.table))])]})),B(!1)}}),(0,U.jsx)(Ee,{drawing:Y??i,hidden:te,onToggle:J}),(0,U.jsx)(Ne,{drawing:Y??i,hidden:te,expanding:ee,expanded:b,fitSignal:S,onExpand:e=>W(e.id,e.distance),onOpen:e=>T(e.id),onLoadMore:e=>W(e.node,i.nodes.get(e.node)?.distance??0,e),onDrawn:re})]}):null,ke&&(0,U.jsx)(Te,{environment:n,node:ke,onClose:()=>T(void 0)})]})}export{Fe as GraphView};
|