dbml-erd-viewer 0.1.1 → 0.1.2
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/README.md +36 -7
- package/dist/dbml-erd-viewer.css +1 -1
- package/dist/dbml-erd-viewer.js +517 -382
- package/dist/dbml-erd-viewer.umd.cjs +1 -1
- package/dist/index.d.ts +22 -3
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@xyflow/react"),require("@dbml/core"),require("react/jsx-runtime")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@xyflow/react`,`@dbml/core`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.DbmlErdViewer={},e.React,e.XYFlowReact,e.DbmlCore,e.jsxRuntime))})(this,function(e,t,n,r,i){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var a=Object.create,o=Object.defineProperty,s=Object.getOwnPropertyDescriptor,c=Object.getOwnPropertyNames,l=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty,d=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=c(t),a=0,l=i.length,d;a<l;a++)d=i[a],!u.call(e,d)&&d!==n&&o(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=s(t,d))||r.enumerable});return e};r=((e,t,n)=>(n=e==null?{}:a(l(e)),d(t||!e||!e.__esModule?o(n,`default`,{value:e,enumerable:!0}):n,e)))(r,1);var f=r,p=f.Parser??f.default?.Parser;if(!p)throw Error("Could not resolve `Parser` export from @dbml/core.");var m=p,h=`public`,g=class extends Error{diagnostics;constructor(e,t){super(e,t),this.name=`DbmlParseError`,this.diagnostics=t?.diagnostics??[]}};function _(e){let t=e?.diags;return Array.isArray(t)?t.map(e=>({message:e.message??`Unknown error`,line:e.location?.start?.line,column:e.location?.start?.column,code:e.code})):[]}function v(e,t){if(e.length===0)return`Failed to parse DBML: ${t}`;let n=e.map(e=>` • ${e.line==null?``:`Line ${e.line}${e.column==null?``:`:${e.column}`} — `}${e.message}`);return`${e.length===1?`Failed to parse DBML:`:`Failed to parse DBML (${e.length} errors):`}\n${n.join(`
|
|
2
|
-
`)}`}function y(e){if(e)return typeof e==`string`?e:e.value??void 0}function b(e,t){return e&&e!==h?`${e}.${t}`:t}function x(e){let t=new Set;for(let n of e.fields)n.pk&&t.add(n.name);for(let n of e.indexes??[])if(n.pk)for(let e of n.columns??[])e.type===`column`&&e.value&&t.add(e.value);return t}function S(e){let t;try{t=new m().parse(e,`dbmlv2`)}catch(e){let t=_(e);throw new g(v(t,e instanceof Error?e.message:String(e)),{cause:e,diagnostics:t})}let n=new Map;for(let e of t.schemas)for(let t of e.tables){let r=b(e.name,t.name),i=x(t),a=new Map;for(let e of t.fields){let t=i.has(e.name);a.set(e.name,{pk:t,notNull:t||!!e.not_null,note:y(e.note)})}n.set(r,a)}let r=e=>{let t=n.get(e.tableId);return!t||e.columns.length===0?!1:e.columns.every(e=>t.get(e)?.pk===!0)},i=e=>e.columns.some(t=>{let r=n.get(e.tableId)?.get(t);return r?!r.notNull&&!r.pk:!0}),a=e=>e.columns.some(t=>n.get(e.tableId)?.get(t)?.note?.toLowerCase().includes(`optional`)??!1),o=[],s=new Set;for(let e of t.schemas)for(let t of e.refs){if(t.endpoints.length!==2)continue;let[n,c]=t.endpoints.map(t=>({tableId:b(t.schemaName??e.name,t.tableName),columns:t.fieldNames,relation:t.relation})),l,u,d=n.relation===`*`;if(d!==(c.relation===`*`))l=d?n:c,u=d?c:n;else{let e=r(n),t=r(c);e&&!t?(l=c,u=n):(l=n,u=c)}let f=r(l),p=i(l);l.columns.forEach(e=>s.add(`${l.tableId}::${e}`)),o.push({id:`${l.tableId}.${l.columns.join(`-`)}__${u.tableId}.${u.columns.join(`-`)}`,kind:f?`identifying`:`non-identifying`,from:{...l,optional:a(l)?!0:void 0},to:{...u,optional:p}})}let c=[];for(let e of t.schemas){let t=e.name;for(let n of e.tables){let e=b(t,n.name),r=x(n),i=n.fields.map(t=>({name:t.name,type:t.type?.type_name??`unknown`,pk:r.has(t.name),notNull:r.has(t.name)||!!t.not_null,unique:!!t.unique,increment:!!t.increment,defaultValue:t.dbdefault?.value,note:y(t.note),isForeignKey:s.has(`${e}::${t.name}`)}));c.push({id:e,name:n.name,schema:t===h?void 0:t,note:y(n.note),headerColor:n.headerColor??void 0,columns:i})}}return{tables:c,relations:o}}var C=160,w=320,T=320,E=40,D=28;function O(e){return 40+Math.max(e.columns.length,1)*28}var k=24,A=8,j=24,M=12,N=24,P=6.8,F=7.4;function I(e,t={}){let n=t.minWidth??160,r=t.maxWidth??320,i=N+L(e)*F;for(let t of e.columns){let e=(t.pk||t.isForeignKey?j:0)+t.name.length*P,n=t.type.length*P+M;i=Math.max(i,k+e+A+n)}return Math.round(Math.min(r,Math.max(n,i)))}function L(e){return(e.schema?e.schema.length+1:0)+e.name.length}function R(e){let t=new Map;for(let n of e.tables)t.set(n.id,0);let n=e.relations.map(e=>[e.from.tableId,e.to.tableId]).filter(([e,n])=>e!==n&&t.has(e)&&t.has(n));for(let r=0;r<e.tables.length;r++){let e=!1;for(let[r,i]of n){let n=t.get(r)+1;t.get(i)<n&&(t.set(i,n),e=!0)}if(!e)break}return t}function z(e,t={}){let n=t.horizontalGap??120,r=t.verticalGap??40,i={minWidth:t.minNodeWidth,maxWidth:t.maxNodeWidth},a=R(e),o=new Map;for(let t of e.tables){let e=a.get(t.id)??0,n=o.get(e);n||(n=[],o.set(e,n)),n.push(t)}let s=new Map,c=[...o.keys()].sort((e,t)=>e-t),l=0;for(let e of c){let t=o.get(e).sort((e,t)=>e.name.localeCompare(t.name)),a=0,c=0;for(let e of t){let t=I(e,i),n=O(e);s.set(e.id,{x:l,y:c,width:t,height:n}),a=Math.max(a,t),c+=n+r}l+=a+n}return s}async function B(e,t={}){let n=await import(`@dagrejs/dagre`),r=t.horizontalGap??120,i=t.verticalGap??40,a={minWidth:t.minNodeWidth,maxWidth:t.maxNodeWidth},o=t.direction===`TB`?`TB`:`LR`,s=new n.graphlib.Graph;s.setGraph({rankdir:o,ranksep:r,nodesep:i}),s.setDefaultEdgeLabel(()=>({}));for(let t of e.tables)s.setNode(t.id,{width:I(t,a),height:O(t)});for(let t of e.relations)s.hasNode(t.from.tableId)&&s.hasNode(t.to.tableId)&&s.setEdge(t.from.tableId,t.to.tableId);n.layout(s);let c=new Map;for(let e of s.nodes()){let t=s.node(e);t&&c.set(e,{x:t.x-t.width/2,y:t.y-t.height/2,width:t.width,height:t.height})}return c}async function V(e,t={}){let n=new(await(import(`elkjs/lib/elk.bundled.js`))).default,r=t.horizontalGap??120,i=t.verticalGap??40,a={minWidth:t.minNodeWidth,maxWidth:t.maxNodeWidth},o={id:`root`,layoutOptions:{"elk.algorithm":`layered`,"elk.direction":t.direction===`TB`?`DOWN`:`RIGHT`,"elk.layered.spacing.nodeNodeBetweenLayers":String(r),"elk.spacing.nodeNode":String(i)},children:e.tables.map(e=>({id:e.id,width:I(e,a),height:O(e)})),edges:e.relations.map((e,t)=>({id:`e${t}`,sources:[e.from.tableId],targets:[e.to.tableId]}))},s=await n.layout(o),c=new Map;for(let e of s.children??[])c.set(e.id,{x:e.x??0,y:e.y??0,width:e.width??160,height:e.height??0});return c}var H=class extends Error{constructor(e,t){super(e,t),this.name=`LayoutError`}};async function U(e,t={}){let n=t.algorithm??`simple`;if(n===`simple`)return z(e,t);try{return n===`dagre`?await B(e,t):await V(e,t)}catch(e){throw new H(`"${n}" layout failed. Is the optional dependency "${n===`dagre`?`@dagrejs/dagre`:`elkjs`}" installed? (${e instanceof Error?e.message:String(e)})`,{cause:e})}}var ee=[`--dv-canvas`,`--dv-bg`,`--dv-border`,`--dv-header-bg`,`--dv-header-fg`,`--dv-row-fg`,`--dv-type-fg`,`--dv-row-hover`,`--dv-row-highlight`,`--dv-pk`,`--dv-fk`,`--dv-null`,`--dv-edge`,`--dv-edge-active`,`--dv-font`],W=class extends Error{constructor(e,t){super(e,t),this.name=`ExportError`}};function te(e,t){let n=e.x,r=e.y,i=e.x+e.width,a=e.y+e.height;for(let e of t.querySelectorAll(`.dv-erd-edge`)){let t;try{t=e.getBBox()}catch{continue}t.width===0&&t.height===0||(n=Math.min(n,t.x),r=Math.min(r,t.y),i=Math.max(i,t.x+t.width),a=Math.max(a,t.y+t.height))}return{x:n,y:r,width:i-n,height:a-r}}async function G(e,t,n={}){let{type:r=`png`,padding:i=24,backgroundColor:a,pixelRatio:o=2}=n,s;try{s=await import(`html-to-image`)}catch(e){throw new W(`Export requires the optional dependency "html-to-image". Install it to enable PNG/SVG export.`,{cause:e})}if(typeof document<`u`&&document.fonts?.ready)try{await document.fonts.ready}catch{}let c=Math.ceil(t.width+i*2),l=Math.ceil(t.height+i*2),u=`translate(${-t.x+i}px, ${-t.y+i}px) scale(1)`,d={width:c,height:l,backgroundColor:a,style:{width:`${c}px`,height:`${l}px`,transform:u}},f=K(e,t,i);try{return r===`svg`?await s.toSvg(e,d):await s.toPng(e,{...d,pixelRatio:o})}catch(e){throw new W(`Failed to render diagram image: ${e instanceof Error?e.message:String(e)}`,{cause:e})}finally{f()}}function K(e,t,n){let r=[],i=e.closest(`.dv-viewer`);if(i){let t=getComputedStyle(i);for(let n of ee){let i=t.getPropertyValue(n);if(!i)continue;let a=e.style.getPropertyValue(n);e.style.setProperty(n,i),r.push(()=>{a?e.style.setProperty(n,a):e.style.removeProperty(n)})}}let a=`${Math.ceil(t.x+t.width+n)}px`,o=`${Math.ceil(t.y+t.height+n)}px`;for(let t of e.querySelectorAll(`.react-flow__edges svg`)){let{width:e,height:n}=t.style;t.style.width=a,t.style.height=o,r.push(()=>{t.style.width=e,t.style.height=n})}return()=>r.forEach(e=>e())}function q(e,t){let n=document.createElement(`a`);n.href=e,n.download=t,n.click()}function J(e,t,n){return`${e}__${t}__${n}`}function Y(e){return 40+e*28+28/2}function X({column:e,top:t}){let r={top:t,opacity:0};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.Handle,{id:J(e,`left`,`target`),type:`target`,position:n.Position.Left,style:r,isConnectable:!1}),(0,i.jsx)(n.Handle,{id:J(e,`left`,`source`),type:`source`,position:n.Position.Left,style:r,isConnectable:!1}),(0,i.jsx)(n.Handle,{id:J(e,`right`,`target`),type:`target`,position:n.Position.Right,style:r,isConnectable:!1}),(0,i.jsx)(n.Handle,{id:J(e,`right`,`source`),type:`source`,position:n.Position.Right,style:r,isConnectable:!1})]})}function ne({data:e}){let{table:t,highlightedColumns:n,widthBounds:r}=e;return(0,i.jsxs)(`div`,{className:`dv-table`,style:{width:I(t,r)},children:[(0,i.jsxs)(`div`,{className:`dv-table__header`,style:t.headerColor?{background:t.headerColor,height:40}:{height:40},title:t.note,children:[t.schema&&(0,i.jsxs)(`span`,{className:`dv-table__schema`,children:[t.schema,`.`]}),(0,i.jsx)(`span`,{className:`dv-table__name`,title:t.name,children:t.name})]}),(0,i.jsx)(`div`,{className:`dv-table__body`,children:t.columns.map((e,t)=>{let r=n?.has(e.name);return(0,i.jsxs)(`div`,{className:`dv-row${r?` dv-row--highlighted`:``}`,style:{height:28},title:e.note,children:[(0,i.jsxs)(`span`,{className:`dv-row__name${e.pk?` dv-row__name--pk`:``}`,children:[e.pk&&(0,i.jsx)(`span`,{className:`dv-badge dv-badge--pk`,title:`Primary key`,children:`PK`}),e.isForeignKey&&!e.pk&&(0,i.jsx)(`span`,{className:`dv-badge dv-badge--fk`,title:`Foreign key`,children:`FK`}),(0,i.jsx)(`span`,{className:`dv-row__label`,title:e.name,children:e.name})]}),(0,i.jsxs)(`span`,{className:`dv-row__type`,children:[(0,i.jsx)(`span`,{className:`dv-row__typename`,title:e.type,children:e.type}),(0,i.jsx)(`span`,{className:`dv-row__null${e.notNull?` dv-row__null--notnull`:``}`,title:e.notNull?`Not null`:`Nullable`})]}),(0,i.jsx)(X,{column:e.name,top:Y(t)})]},e.name)})})]})}var Z=(0,t.memo)(ne),Q=8,re=13,ie=7,ae=13,oe=16;function $(e,t,r,a,o,s){let c=-(r===n.Position.Left?1:-1),l=[],u={stroke:o,strokeWidth:s},d=(n,r)=>l.push((0,i.jsx)(`line`,{x1:e+c*n,y1:t-Q,x2:e+c*n,y2:t+Q,style:u},r)),f=(n,r)=>l.push((0,i.jsx)(`circle`,{cx:e+c*n,cy:t,r:4,style:{stroke:o,strokeWidth:s,fill:`var(--dv-bg)`}},r));if(a.cardinality===`*`){let n=e+c*re;l.push((0,i.jsx)(`line`,{x1:n,y1:t,x2:e,y2:t-Q,style:u},`cf1`),(0,i.jsx)(`line`,{x1:n,y1:t,x2:e,y2:t,style:u},`cf2`),(0,i.jsx)(`line`,{x1:n,y1:t,x2:e,y2:t+Q,style:u},`cf3`)),a.optional===!0?f(17,`fr`):d(14,`fb`)}else d(ie,`b1`),a.optional===!0?f(oe,`r`):a.optional===!1&&d(ae,`b2`);return(0,i.jsx)(`g`,{className:`dv-erd-marker`,children:l})}function se({sourceX:e,sourceY:t,targetX:r,targetY:a,sourcePosition:o,targetPosition:s,data:c,selected:l}){let[u]=(0,n.getSmoothStepPath)({sourceX:e,sourceY:t,sourcePosition:o,targetX:r,targetY:a,targetPosition:s,borderRadius:8}),d=c,f=d?.kind===`non-identifying`,p=l||d?.hovered,m=p?`var(--dv-edge-active)`:`var(--dv-edge)`,h=p?2:1.5;return(0,i.jsxs)(`g`,{className:`dv-erd-edge${p?` dv-erd-edge--active`:``}`,children:[(0,i.jsx)(`path`,{className:`dv-erd-edge__interaction`,d:u,fill:`none`}),(0,i.jsx)(`path`,{className:`dv-erd-edge__path`,d:u,fill:`none`,style:{stroke:m,strokeWidth:h},strokeDasharray:f?`6 4`:void 0}),d&&$(e,t,o,d.sourceEnd,m,h),d&&$(r,a,s,d.targetEnd,m,h)]})}var ce=(0,t.memo)(se);function le(e,n,r){let[i,a]=(0,t.useState)(null),o=(0,t.useMemo)(()=>{let t=new Map;for(let n of e)t.set(n.id,n);return t},[e]),s=(0,t.useMemo)(()=>{let e=new Map,t=i?o.get(i):void 0;if(!t)return e;for(let n of[t.from,t.to]){let t=e.get(n.tableId)??new Set;n.columns.forEach(e=>t.add(e)),e.set(n.tableId,t)}return e},[i,o]);return{displayNodes:(0,t.useMemo)(()=>i?n.map(e=>{let t=s.get(e.id);return t?{...e,data:{...e.data,highlightedColumns:t}}:e}):n,[n,i,s]),displayEdges:(0,t.useMemo)(()=>i?r.map(e=>e.id===i?{...e,data:{...e.data,hovered:!0},zIndex:1}:e):r,[r,i]),onEdgeMouseEnter:(0,t.useCallback)((e,t)=>a(t.id),[]),onEdgeMouseLeave:(0,t.useCallback)(()=>a(null),[])}}var ue={canvas:`--dv-canvas`,background:`--dv-bg`,border:`--dv-border`,headerBackground:`--dv-header-bg`,headerForeground:`--dv-header-fg`,rowForeground:`--dv-row-fg`,typeForeground:`--dv-type-fg`,rowHover:`--dv-row-hover`,rowHighlight:`--dv-row-highlight`,primaryKey:`--dv-pk`,foreignKey:`--dv-fk`,edge:`--dv-edge`,edgeActive:`--dv-edge-active`,fontFamily:`--dv-font`},de={canvas:`#fafbfc`,background:`#ffffff`,border:`#d9dee5`,headerBackground:`#2d3748`,headerForeground:`#ffffff`,rowForeground:`#1a202c`,typeForeground:`#718096`,rowHover:`#f1f5f9`,rowHighlight:`#dbeafe`,primaryKey:`#b7791f`,foreignKey:`#2b6cb0`,edge:`#94a3b8`,edgeActive:`#2b6cb0`},fe={canvas:`#0f172a`,background:`#1e293b`,border:`#334155`,headerBackground:`#334155`,headerForeground:`#f1f5f9`,rowForeground:`#e2e8f0`,typeForeground:`#94a3b8`,rowHover:`#334155`,rowHighlight:`#1e3a5f`,primaryKey:`#d69e2e`,foreignKey:`#4299e1`,edge:`#64748b`,edgeActive:`#60a5fa`};function pe(e){if(!e)return{};let t={};for(let n of Object.keys(e)){let r=e[n];r!=null&&(t[ue[n]]=r)}return t}var me=[],he={table:Z},ge={erd:ce};function _e(){return(0,i.jsxs)(`svg`,{viewBox:`0 0 24 24`,width:`100%`,height:`100%`,fill:`currentColor`,"aria-hidden":`true`,children:[(0,i.jsx)(`rect`,{x:`3`,y:`3`,width:`8`,height:`8`,rx:`1.5`}),(0,i.jsx)(`rect`,{x:`13`,y:`3`,width:`8`,height:`8`,rx:`1.5`}),(0,i.jsx)(`rect`,{x:`3`,y:`13`,width:`8`,height:`8`,rx:`1.5`}),(0,i.jsx)(`rect`,{x:`13`,y:`13`,width:`8`,height:`8`,rx:`1.5`})]})}function ve(e,t,n,r){let i=new Map;for(let a of e.tables){let e=t.get(a.id);i.set(a.id,n?.[a.id]??r?.get(a.id)??{x:e?.x??0,y:e?.y??0})}return i}function ye(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}function be(e,t,n){return e.x<t.x+t.w+n&&e.x+e.w+n>t.x&&e.y<t.y+t.h+n&&e.y+e.h+n>t.y}function xe(e,t,n,r,i){let a=(e,t)=>({x:t.x,y:t.y,w:I(e,i),h:O(e)}),o=[];for(let r of e.tables)n(r.id)&&o.push(a(r,t.get(r.id)));for(let i of e.tables){if(n(i.id))continue;let e=t.get(i.id),s=a(i,e),c=0;for(;c++<1e3;){let t=o.filter(e=>be(s,e,r));if(t.length===0)break;let n=Math.max(...t.map(e=>e.y+e.h));e={x:e.x,y:n+r},s=a(i,e)}t.set(i.id,e),o.push(s)}}async function Se(e,t,n){try{return await U(e,t)}catch(r){return n(r instanceof H?r:new H(String(r),{cause:r})),z(e,t)}}function Ce(e,t,n){return e.tables.map(e=>({id:e.id,type:`table`,position:t.get(e.id)??{x:0,y:0},data:{table:e,widthBounds:n}}))}function we(e,t){return e.relations.map(e=>{let n=t.get(e.from.tableId),r=t.get(e.to.tableId),i=(n?.x??0)>(r?.x??0),a=i?`left`:`right`,o=i?`right`:`left`,s=e.from.columns[0]??``,c=e.to.columns[0]??``;return{id:e.id,source:e.from.tableId,target:e.to.tableId,sourceHandle:J(s,a,`source`),targetHandle:J(c,o,`target`),type:`erd`,data:{kind:e.kind,sourceEnd:{cardinality:e.from.relation,optional:e.from.optional},targetEnd:{cardinality:e.to.relation,optional:e.to.optional}}}})}var Te=(0,t.forwardRef)(function({dbml:e,className:r,style:a,theme:o,fitView:s=!0,showControls:c=!0,showMiniMap:l=!1,showBackground:u=!0,layoutOptions:d,onParseError:f,onLayoutError:p,nodePositions:m,onNodePositionsChange:h},_){let v=(0,t.useMemo)(()=>{try{return{ok:!0,schema:S(e)}}catch(e){return{ok:!1,error:e instanceof g?e:new g(String(e),{cause:e})}}},[e]),[y,b,x]=(0,n.useNodesState)([]),[C,w,T]=(0,n.useEdgesState)([]),E=(0,t.useRef)(null),D=(0,t.useRef)(null),O=(0,t.useRef)(y);O.current=y,(0,t.useImperativeHandle)(_,()=>{let e=async e=>{let t=E.current,r=D.current?.querySelector(`.react-flow__viewport`);if(!t||!r)throw new W(`The diagram is not ready to export yet.`);let i=te((0,n.getNodesBounds)(t.getNodes()),r),a=e?.backgroundColor??(D.current?getComputedStyle(D.current).backgroundColor:void 0);return G(r,i,{...e,backgroundColor:a})};return{toDataUrl:e,download:async(t,n)=>{q(await e(n),t)},fitView:e=>E.current?.fitView(e),zoomIn:e=>E.current?.zoomIn(e),zoomOut:e=>E.current?.zoomOut(e),zoomTo:(e,t)=>E.current?.zoomTo(e,t),setCenter:(e,t,n)=>E.current?.setCenter(e,t,n),fitBounds:(e,t)=>E.current?.fitBounds(e,t),setViewport:(e,t)=>E.current?.setViewport(e,t),getViewport:()=>E.current?.getViewport()}},[]);let k=(0,t.useRef)(p);k.current=p;let A=(0,t.useRef)(h);A.current=h;let j=(0,t.useRef)(m);j.current=m;let M=(0,t.useCallback)(()=>{let e=A.current;if(!e)return;let t={};for(let e of O.current)t[e.id]={x:e.position.x,y:e.position.y};e(t)},[]),{algorithm:N=`simple`,direction:P=`LR`,horizontalGap:F,verticalGap:I,minNodeWidth:L,maxNodeWidth:R}=d??{},z=(0,t.useRef)(null),B=`${N}|${P}|${F}|${I}|${L}|${R}`,V=(0,t.useCallback)((e,t,n,r,i)=>{let a={minWidth:L,maxWidth:R},o=ve(e,r,i.saved,i.prior);if(i.prior){let t=i.prior,n=i.saved;xe(e,o,e=>t.has(e)||n?.[e]!==void 0,I??40,a)}if(b(Ce(e,o,a)),w(we(e,o)),z.current={ids:t,optionsKey:n},i.emit){let e={};o.forEach((t,n)=>{e[n]=t}),A.current?.(e)}i.fit&&requestAnimationFrame(()=>void E.current?.fitView())},[b,w,I,L,R]);(0,t.useEffect)(()=>{if(!v.ok){b([]),w([]),z.current=null;return}let e=v.schema,t={algorithm:N,direction:P,horizontalGap:F,verticalGap:I,minNodeWidth:L,maxNodeWidth:R},n=e.tables.map(e=>e.id),r=new Map(O.current.map(e=>[e.id,{x:e.position.x,y:e.position.y}])),i=z.current,a=n.every(e=>r.has(e));if(i&&i.optionsKey===B&&a&&ye(i.ids,n)){V(e,n,B,new Map,{prior:r});return}let o=i&&i.optionsKey===B?r:void 0,c=!1;return Se(e,t,e=>k.current?.(e)).then(t=>{c||V(e,n,B,t,{saved:j.current,prior:o,fit:s})}),()=>{c=!0}},[v,N,P,F,I,L,R,B,s,V,b,w]);let H=(0,t.useCallback)(()=>{if(!v.ok)return;let e=v.schema,t={algorithm:N,direction:P,horizontalGap:F,verticalGap:I,minNodeWidth:L,maxNodeWidth:R},n=e.tables.map(e=>e.id);Se(e,t,e=>k.current?.(e)).then(t=>{V(e,n,B,t,{emit:!0,fit:!0})})},[v,N,P,F,I,L,R,B,V]),U=(0,t.useCallback)(()=>{v.ok||f?.(v.error)},[v,f]);(0,t.useEffect)(U,[U]);let{displayNodes:ee,displayEdges:K,onEdgeMouseEnter:J,onEdgeMouseLeave:Y}=le(v.ok?v.schema.relations:me,y,C),X={width:`100%`,height:`100%`,...pe(o),...a};return v.ok?(0,i.jsx)(`div`,{ref:D,className:`dv-viewer${r?` ${r}`:``}`,style:X,children:(0,i.jsxs)(n.ReactFlow,{nodes:ee,edges:K,nodeTypes:he,edgeTypes:ge,onNodesChange:x,onEdgesChange:T,onEdgeMouseEnter:J,onEdgeMouseLeave:Y,onNodeDragStop:M,onInit:e=>{E.current=e},fitView:s,nodesConnectable:!1,elementsSelectable:!0,minZoom:.1,proOptions:{hideAttribution:!0},children:[u&&(0,i.jsx)(n.Background,{}),c&&(0,i.jsx)(n.Controls,{children:(0,i.jsx)(n.ControlButton,{onClick:H,title:`Auto layout`,"aria-label":`Auto layout`,children:(0,i.jsx)(_e,{})})}),l&&(0,i.jsx)(n.MiniMap,{pannable:!0,zoomable:!0})]})}):(0,i.jsx)(`div`,{className:`dv-error${r?` ${r}`:``}`,style:X,children:(0,i.jsx)(`pre`,{className:`dv-error__message`,children:v.error.message})})});e.DbmlParseError=g,e.DbmlViewer=Te,e.ErdEdge=ce,e.ExportError=W,e.HEADER_HEIGHT=E,e.LayoutError=H,e.MAX_NODE_WIDTH=w,e.MIN_NODE_WIDTH=C,e.NODE_WIDTH=T,e.ROW_HEIGHT=D,e.TableNode=Z,e.computeLayout=U,e.darkTheme=fe,e.downloadDataUrl=q,e.layoutSchema=z,e.lightTheme=de,e.parseDbml=S,e.renderDiagram=G,e.tableHeight=O,e.tableWidth=I,e.themeToCssVars=pe});
|
|
2
|
+
`)}`}function y(e){if(e)return typeof e==`string`?e:e.value??void 0}function b(e,t){return e&&e!==h?`${e}.${t}`:t}function x(e){let t=new Set;for(let n of e.fields)n.pk&&t.add(n.name);for(let n of e.indexes??[])if(n.pk)for(let e of n.columns??[])e.type===`column`&&e.value&&t.add(e.value);return t}function ee(e){let t;try{t=new m().parse(e,`dbmlv2`)}catch(e){let t=_(e);throw new g(v(t,e instanceof Error?e.message:String(e)),{cause:e,diagnostics:t})}let n=new Map;for(let e of t.schemas)for(let t of e.tables){let r=b(e.name,t.name),i=x(t),a=new Map;for(let e of t.fields){let t=i.has(e.name);a.set(e.name,{pk:t,notNull:t||!!e.not_null,note:y(e.note)})}n.set(r,a)}let r=e=>{let t=n.get(e.tableId);return!t||e.columns.length===0?!1:e.columns.every(e=>t.get(e)?.pk===!0)},i=e=>e.columns.some(t=>{let r=n.get(e.tableId)?.get(t);return r?!r.notNull&&!r.pk:!0}),a=e=>e.columns.some(t=>n.get(e.tableId)?.get(t)?.note?.toLowerCase().includes(`optional`)??!1),o=[],s=new Set;for(let e of t.schemas)for(let t of e.refs){if(t.endpoints.length!==2)continue;let[n,c]=t.endpoints.map(t=>({tableId:b(t.schemaName??e.name,t.tableName),columns:t.fieldNames,relation:t.relation})),l,u,d=n.relation===`*`;if(d!==(c.relation===`*`))l=d?n:c,u=d?c:n;else{let e=r(n),t=r(c);e&&!t?(l=c,u=n):(l=n,u=c)}let f=r(l),p=i(l);l.columns.forEach(e=>s.add(`${l.tableId}::${e}`)),o.push({id:`${l.tableId}.${l.columns.join(`-`)}__${u.tableId}.${u.columns.join(`-`)}`,kind:f?`identifying`:`non-identifying`,from:{...l,optional:a(l)?!0:void 0},to:{...u,optional:p}})}let c=[];for(let e of t.schemas){let t=e.name;for(let n of e.tables){let e=b(t,n.name),r=x(n),i=n.fields.map(t=>({name:t.name,type:t.type?.type_name??`unknown`,pk:r.has(t.name),notNull:r.has(t.name)||!!t.not_null,unique:!!t.unique,increment:!!t.increment,defaultValue:t.dbdefault?.value,note:y(t.note),isForeignKey:s.has(`${e}::${t.name}`)}));c.push({id:e,name:n.name,schema:t===h?void 0:t,note:y(n.note),headerColor:n.headerColor??void 0,columns:i})}}return{tables:c,relations:o}}var S=160,C=320,w=320,te=40,T=28;function E(e){return 40+Math.max(e.columns.length,1)*28}var D=24,O=8,k=24,A=12,ne=24,j=6.8,M=7.4;function N(e,t={}){let n=t.minWidth??160,r=t.maxWidth??320,i=ne+P(e)*M;for(let t of e.columns){let e=(t.pk||t.isForeignKey?k:0)+t.name.length*j,n=t.type.length*j+A;i=Math.max(i,D+e+O+n)}return Math.round(Math.min(r,Math.max(n,i)))}function P(e){return(e.schema?e.schema.length+1:0)+e.name.length}function F(e,t){let n=new Map;for(let t of e)n.set(t.id,0);let r=t.map(e=>[e.from.tableId,e.to.tableId]).filter(([e,t])=>e!==t&&n.has(e)&&n.has(t));for(let t=0;t<e.length;t++){let e=!1;for(let[t,i]of r){let r=n.get(t)+1;n.get(i)<r&&(n.set(i,r),e=!0)}if(!e)break}return n}function I(e,t={}){let n=t.horizontalGap??120,r=t.verticalGap??40,i={minWidth:t.minNodeWidth,maxWidth:t.maxNodeWidth},a=new Set;for(let t of e.relations)a.add(t.from.tableId),a.add(t.to.tableId);let o=e.tables.filter(e=>a.has(e.id)),s=e.tables.filter(e=>!a.has(e.id)),c=new Map,l=F(o,e.relations),u=new Map;for(let e of o){let t=l.get(e.id)??0,n=u.get(t);n||(n=[],u.set(t,n)),n.push(e)}let d=0,f=0,p=0;for(let e of[...u.keys()].sort((e,t)=>e-t)){let t=u.get(e).sort((e,t)=>e.name.localeCompare(t.name)),a=0,o=0;for(let e of t){let t=N(e,i),n=E(e);c.set(e.id,{x:p,y:o,width:t,height:n}),a=Math.max(a,t),o+=n+r}d=Math.max(d,p+a),f=Math.max(f,o-r),p+=a+n}if(s.length>0){let e=d>0?d:Math.ceil(Math.sqrt(s.length))*(320+n),t=0,a=f>0?f+r*2:0,o=0;for(let l of[...s].sort((e,t)=>e.name.localeCompare(t.name))){let s=N(l,i),u=E(l);t>0&&t+s>e&&(t=0,a+=o+r,o=0),c.set(l.id,{x:t,y:a,width:s,height:u}),t+=s+n,o=Math.max(o,u)}}return c}async function L(e,t={}){let n=await import(`@dagrejs/dagre`),r=t.horizontalGap??120,i=t.verticalGap??40,a={minWidth:t.minNodeWidth,maxWidth:t.maxNodeWidth},o=t.direction===`TB`?`TB`:`LR`,s=new n.graphlib.Graph;s.setGraph({rankdir:o,ranksep:r,nodesep:i}),s.setDefaultEdgeLabel(()=>({}));for(let t of e.tables)s.setNode(t.id,{width:N(t,a),height:E(t)});for(let t of e.relations)s.hasNode(t.from.tableId)&&s.hasNode(t.to.tableId)&&s.setEdge(t.from.tableId,t.to.tableId);n.layout(s);let c=new Map;for(let e of s.nodes()){let t=s.node(e);t&&c.set(e,{x:t.x-t.width/2,y:t.y-t.height/2,width:t.width,height:t.height})}return c}async function R(e,t={}){let n=new(await(import(`elkjs/lib/elk.bundled.js`))).default,r=t.horizontalGap??120,i=t.verticalGap??40,a={minWidth:t.minNodeWidth,maxWidth:t.maxNodeWidth},o={id:`root`,layoutOptions:{"elk.algorithm":`layered`,"elk.direction":t.direction===`TB`?`DOWN`:`RIGHT`,"elk.layered.spacing.nodeNodeBetweenLayers":String(r),"elk.spacing.nodeNode":String(i)},children:e.tables.map(e=>({id:e.id,width:N(e,a),height:E(e)})),edges:e.relations.map((e,t)=>({id:`e${t}`,sources:[e.from.tableId],targets:[e.to.tableId]}))},s=await n.layout(o),c=new Map;for(let e of s.children??[])c.set(e.id,{x:e.x??0,y:e.y??0,width:e.width??160,height:e.height??0});return c}var z=class extends Error{constructor(e,t){super(e,t),this.name=`LayoutError`}};async function B(e,t={}){let n=t.algorithm??`simple`;if(n===`simple`)return I(e,t);try{return n===`dagre`?await L(e,t):await R(e,t)}catch(e){throw new z(`"${n}" layout failed. Is the optional dependency "${n===`dagre`?`@dagrejs/dagre`:`elkjs`}" installed? (${e instanceof Error?e.message:String(e)})`,{cause:e})}}var V=[`--dv-canvas`,`--dv-bg`,`--dv-border`,`--dv-header-bg`,`--dv-header-fg`,`--dv-row-fg`,`--dv-type-fg`,`--dv-row-hover`,`--dv-row-highlight`,`--dv-pk`,`--dv-fk`,`--dv-null`,`--dv-edge`,`--dv-edge-active`,`--dv-font`],H=class extends Error{constructor(e,t){super(e,t),this.name=`ExportError`}};function re(e,t){let n=e.x,r=e.y,i=e.x+e.width,a=e.y+e.height;for(let e of t.querySelectorAll(`.dv-erd-edge`)){let t;try{t=e.getBBox()}catch{continue}t.width===0&&t.height===0||(n=Math.min(n,t.x),r=Math.min(r,t.y),i=Math.max(i,t.x+t.width),a=Math.max(a,t.y+t.height))}return{x:n,y:r,width:i-n,height:a-r}}async function U(e,t,n={}){let{type:r=`png`,padding:i=24,backgroundColor:a,pixelRatio:o=2}=n,s;try{s=await import(`html-to-image`)}catch(e){throw new H(`Export requires the optional dependency "html-to-image". Install it to enable PNG/SVG export.`,{cause:e})}if(typeof document<`u`&&document.fonts?.ready)try{await document.fonts.ready}catch{}let c=Math.ceil(t.width+i*2),l=Math.ceil(t.height+i*2),u=`translate(${-t.x+i}px, ${-t.y+i}px) scale(1)`,d={width:c,height:l,backgroundColor:a,style:{width:`${c}px`,height:`${l}px`,transform:u}},f=W(e,t,i);try{return r===`svg`?await s.toSvg(e,d):await s.toPng(e,{...d,pixelRatio:o})}catch(e){throw new H(`Failed to render diagram image: ${e instanceof Error?e.message:String(e)}`,{cause:e})}finally{f()}}function W(e,t,n){let r=[],i=e.closest(`.dv-viewer`);if(i){let t=getComputedStyle(i);for(let n of V){let i=t.getPropertyValue(n);if(!i)continue;let a=e.style.getPropertyValue(n);e.style.setProperty(n,i),r.push(()=>{a?e.style.setProperty(n,a):e.style.removeProperty(n)})}}let a=`${Math.ceil(t.x+t.width+n)}px`,o=`${Math.ceil(t.y+t.height+n)}px`;for(let t of e.querySelectorAll(`.react-flow__edges svg`)){let{width:e,height:n}=t.style;t.style.width=a,t.style.height=o,r.push(()=>{t.style.width=e,t.style.height=n})}return()=>r.forEach(e=>e())}function G(e,t){let n=document.createElement(`a`);n.href=e,n.download=t,n.click()}function K(e,t,n){return`${e}__${t}__${n}`}var q=(0,t.createContext)(void 0),J=(0,t.createContext)(`column`);function Y(e){return 40+e*28+28/2}var X=4;function ie({column:e,top:t}){let r={top:t-X,opacity:0},a={top:t+X,opacity:0};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.Handle,{id:K(e,`left`,`target`),type:`target`,position:n.Position.Left,style:a,isConnectable:!1}),(0,i.jsx)(n.Handle,{id:K(e,`left`,`source`),type:`source`,position:n.Position.Left,style:r,isConnectable:!1}),(0,i.jsx)(n.Handle,{id:K(e,`right`,`target`),type:`target`,position:n.Position.Right,style:a,isConnectable:!1}),(0,i.jsx)(n.Handle,{id:K(e,`right`,`source`),type:`source`,position:n.Position.Right,style:r,isConnectable:!1})]})}function Z({data:e}){let{table:r,highlightedColumns:a,widthBounds:o,connectedColumns:s}=e,c=(0,t.useContext)(q),l=(0,t.useContext)(J)===`floating`;return(0,i.jsxs)(`div`,{className:`dv-table`,style:{width:N(r,o)},children:[l&&(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.Handle,{type:`source`,position:n.Position.Right,style:{opacity:0},isConnectable:!1}),(0,i.jsx)(n.Handle,{type:`target`,position:n.Position.Left,style:{opacity:0},isConnectable:!1})]}),(0,i.jsxs)(`div`,{className:`dv-table__header`,style:r.headerColor?{background:r.headerColor,height:40}:{height:40},title:r.note,children:[r.schema&&(0,i.jsxs)(`span`,{className:`dv-table__schema`,children:[r.schema,`.`]}),(0,i.jsx)(`span`,{className:`dv-table__name`,title:r.name,children:r.name})]}),(0,i.jsx)(`div`,{className:`dv-table__body`,children:r.columns.map((e,t)=>{let n=a?.has(e.name);return(0,i.jsxs)(`div`,{className:`dv-row${n?` dv-row--highlighted`:``}`,style:{height:28},title:e.note,onMouseEnter:()=>c?.(r.id,e.name),onMouseLeave:()=>c?.(r.id,null),children:[(0,i.jsxs)(`span`,{className:`dv-row__name${e.pk?` dv-row__name--pk`:``}`,children:[e.pk&&(0,i.jsx)(`span`,{className:`dv-badge dv-badge--pk`,title:`Primary key`,children:`PK`}),e.isForeignKey&&!e.pk&&(0,i.jsx)(`span`,{className:`dv-badge dv-badge--fk`,title:`Foreign key`,children:`FK`}),(0,i.jsx)(`span`,{className:`dv-row__label`,title:e.name,children:e.name})]}),(0,i.jsxs)(`span`,{className:`dv-row__type`,children:[(0,i.jsx)(`span`,{className:`dv-row__typename`,title:e.type,children:e.type}),(0,i.jsx)(`span`,{className:`dv-row__null${e.notNull?` dv-row__null--notnull`:``}`,title:e.notNull?`Not null`:`Nullable`})]}),!l&&s?.has(e.name)&&(0,i.jsx)(ie,{column:e.name,top:Y(t)})]},e.name)})})]})}var ae=(0,t.memo)(Z),oe=8,Q=13,se=7,ce=13,le=16,ue={[n.Position.Right]:0,[n.Position.Left]:180,[n.Position.Top]:-90,[n.Position.Bottom]:90};function de(e,t,n,r,a,o){let s=[],c={stroke:a,strokeWidth:o},l=(e,t)=>s.push((0,i.jsx)(`line`,{x1:e,y1:-8,x2:e,y2:oe,style:c},t)),u=(e,t)=>s.push((0,i.jsx)(`circle`,{cx:e,cy:0,r:4,style:{stroke:a,strokeWidth:o,fill:`var(--dv-bg)`}},t));return r.cardinality===`*`?(s.push((0,i.jsx)(`line`,{x1:Q,y1:0,x2:0,y2:-8,style:c},`cf1`),(0,i.jsx)(`line`,{x1:Q,y1:0,x2:0,y2:0,style:c},`cf2`),(0,i.jsx)(`line`,{x1:Q,y1:0,x2:0,y2:oe,style:c},`cf3`)),r.optional===!0?u(17,`fr`):l(14,`fb`)):(l(se,`b1`),r.optional===!0?u(le,`r`):r.optional===!1&&l(ce,`b2`)),(0,i.jsx)(`g`,{className:`dv-erd-marker`,transform:`translate(${e}, ${t}) rotate(${ue[n]})`,children:s})}function fe(e,t,n,r,a,o,s,c,l){let u=t?.kind===`non-identifying`,d=n?`var(--dv-edge-active)`:`var(--dv-edge)`,f=n?2:1.5;return(0,i.jsxs)(`g`,{className:`dv-erd-edge${n?` dv-erd-edge--active`:``}`,children:[(0,i.jsx)(`path`,{className:`dv-erd-edge__interaction`,d:e,fill:`none`}),(0,i.jsx)(`path`,{className:`dv-erd-edge__path`,d:e,fill:`none`,style:{stroke:d,strokeWidth:f},strokeDasharray:u?`6 4`:void 0}),t&&de(r,a,o,t.sourceEnd,d,f),t&&de(s,c,l,t.targetEnd,d,f)]})}function pe({sourceX:e,sourceY:t,targetX:r,targetY:i,sourcePosition:a,targetPosition:o,data:s,selected:c}){let[l]=(0,n.getSmoothStepPath)({sourceX:e,sourceY:t,sourcePosition:a,targetX:r,targetY:i,targetPosition:o,borderRadius:8}),u=s;return fe(l,u,!!(c||u?.hovered),e,t,a,r,i,o)}var me=(0,t.memo)(pe);function $(e){let t=e.measured?.width??0,n=e.measured?.height??0,{x:r,y:i}=e.internals.positionAbsolute;return{x:r,y:i,w:t,h:n,cx:r+t/2,cy:i+n/2}}function he(e,t){let n=$(e),r=$(t),i=n.w/2,a=n.h/2,o=(r.cx-n.cx)/(2*i)-(r.cy-n.cy)/(2*a),s=(r.cx-n.cx)/(2*i)+(r.cy-n.cy)/(2*a),c=1/(Math.abs(o)+Math.abs(s)||1);return{x:i*c*(o+s)+n.cx,y:a*c*(-o+s)+n.cy}}function ge(e,t){let r=$(e),i=Math.round(t.x),a=Math.round(t.y);return i<=Math.round(r.x)+1?n.Position.Left:i>=Math.round(r.x+r.w)-1?n.Position.Right:a<=Math.round(r.y)+1?n.Position.Top:n.Position.Bottom}var _e=14;function ve({id:e,source:t,target:r,data:i,selected:a}){let o=(0,n.useInternalNode)(t),s=(0,n.useInternalNode)(r);if(!o||!s)return null;let c=i,l=!!(a||c?.hovered),u,d,f,p,m,h;if(t===r){let e=$(o);u=f=e.x+e.w,d=e.cy-_e,p=e.cy+_e,m=h=n.Position.Right}else{let e=he(o,s),t=he(s,o);u=e.x,d=e.y,f=t.x,p=t.y,m=ge(o,e),h=ge(s,t)}let[g]=(0,n.getBezierPath)({sourceX:u,sourceY:d,sourcePosition:m,targetX:f,targetY:p,targetPosition:h});return fe(g,c,l,u,d,m,f,p,h)}var ye=(0,t.memo)(ve);function be(e,n,r){let[i,a]=(0,t.useState)(null),[o,s]=(0,t.useState)(null),c=(0,t.useMemo)(()=>{let t=new Map;for(let n of e)t.set(n.id,n);return t},[e]),l=(0,t.useMemo)(()=>{let t=new Set;if(i&&t.add(i),o)for(let n of e){let e=e=>e.tableId===o.tableId&&e.columns.includes(o.column);(e(n.from)||e(n.to))&&t.add(n.id)}return t},[i,o,e]),u=(0,t.useMemo)(()=>{let e=new Map;for(let t of l){let n=c.get(t);if(n)for(let t of[n.from,n.to]){let n=e.get(t.tableId)??new Set;t.columns.forEach(e=>n.add(e)),e.set(t.tableId,n)}}return e},[l,c]),d=(0,t.useCallback)((e,t)=>{s(t?{tableId:e,column:t}:null)},[]);return{displayNodes:(0,t.useMemo)(()=>l.size===0?n:n.map(e=>{let t=u.get(e.id);return t?{...e,data:{...e.data,highlightedColumns:t}}:e}),[n,l,u]),displayEdges:(0,t.useMemo)(()=>l.size===0?r:r.map(e=>l.has(e.id)?{...e,data:{...e.data,hovered:!0},zIndex:1}:e),[r,l]),onEdgeMouseEnter:(0,t.useCallback)((e,t)=>a(t.id),[]),onEdgeMouseLeave:(0,t.useCallback)(()=>a(null),[]),onColumnHover:d}}var xe={canvas:`--dv-canvas`,background:`--dv-bg`,border:`--dv-border`,headerBackground:`--dv-header-bg`,headerForeground:`--dv-header-fg`,rowForeground:`--dv-row-fg`,typeForeground:`--dv-type-fg`,rowHover:`--dv-row-hover`,rowHighlight:`--dv-row-highlight`,primaryKey:`--dv-pk`,foreignKey:`--dv-fk`,edge:`--dv-edge`,edgeActive:`--dv-edge-active`,fontFamily:`--dv-font`},Se={canvas:`#fafbfc`,background:`#ffffff`,border:`#d9dee5`,headerBackground:`#2d3748`,headerForeground:`#ffffff`,rowForeground:`#1a202c`,typeForeground:`#718096`,rowHover:`#f1f5f9`,rowHighlight:`#dbeafe`,primaryKey:`#b7791f`,foreignKey:`#2b6cb0`,edge:`#94a3b8`,edgeActive:`#2b6cb0`},Ce={canvas:`#0f172a`,background:`#1e293b`,border:`#334155`,headerBackground:`#334155`,headerForeground:`#f1f5f9`,rowForeground:`#e2e8f0`,typeForeground:`#94a3b8`,rowHover:`#334155`,rowHighlight:`#1e3a5f`,primaryKey:`#d69e2e`,foreignKey:`#4299e1`,edge:`#64748b`,edgeActive:`#60a5fa`};function we(e){if(!e)return{};let t={};for(let n of Object.keys(e)){let r=e[n];r!=null&&(t[xe[n]]=r)}return t}var Te=[],Ee={table:ae},De={erd:me,"erd-floating":ye};function Oe(){return(0,i.jsxs)(`svg`,{viewBox:`0 0 24 24`,width:`100%`,height:`100%`,fill:`currentColor`,"aria-hidden":`true`,children:[(0,i.jsx)(`rect`,{x:`3`,y:`3`,width:`8`,height:`8`,rx:`1.5`}),(0,i.jsx)(`rect`,{x:`13`,y:`3`,width:`8`,height:`8`,rx:`1.5`}),(0,i.jsx)(`rect`,{x:`3`,y:`13`,width:`8`,height:`8`,rx:`1.5`}),(0,i.jsx)(`rect`,{x:`13`,y:`13`,width:`8`,height:`8`,rx:`1.5`})]})}function ke(e,t,n,r){let i=new Map;for(let a of e.tables){let e=t.get(a.id);i.set(a.id,n?.[a.id]??r?.get(a.id)??{x:e?.x??0,y:e?.y??0})}return i}function Ae(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}function je(e,t,n){return e.x<t.x+t.w+n&&e.x+e.w+n>t.x&&e.y<t.y+t.h+n&&e.y+e.h+n>t.y}function Me(e,t,n,r,i){let a=(e,t)=>({x:t.x,y:t.y,w:N(e,i),h:E(e)}),o=[];for(let r of e.tables)n(r.id)&&o.push(a(r,t.get(r.id)));for(let i of e.tables){if(n(i.id))continue;let e=t.get(i.id),s=a(i,e),c=0;for(;c++<1e3;){let t=o.filter(e=>je(s,e,r));if(t.length===0)break;let n=Math.max(...t.map(e=>e.y+e.h));e={x:e.x,y:n+r},s=a(i,e)}t.set(i.id,e),o.push(s)}}async function Ne(e,t,n){try{return await B(e,t)}catch(r){return n(r instanceof z?r:new z(String(r),{cause:r})),I(e,t)}}function Pe(e){let t=new Map,n=(e,n)=>{if(!n)return;let r=t.get(e);r||(r=new Set,t.set(e,r)),r.add(n)};for(let t of e.relations)t.from.columns.forEach(e=>n(t.from.tableId,e)),t.to.columns.forEach(e=>n(t.to.tableId,e));return t}function Fe(e,t,n,r){return e.tables.map(e=>({id:e.id,type:`table`,position:t.get(e.id)??{x:0,y:0},data:{table:e,widthBounds:n,connectedColumns:r.get(e.id)}}))}function Ie(e,t){let n=e.from.tableId===e.to.tableId,r=n?!1:(t.get(e.from.tableId)?.x??0)>(t.get(e.to.tableId)?.x??0),i=r?`left`:`right`,a=n||r?`right`:`left`;return{sourceHandle:K(e.from.columns[0]??``,i,`source`),targetHandle:K(e.to.columns[0]??``,a,`target`)}}function Le(e,t,n){let r=n===`floating`;return e.relations.map(e=>{let n=r?{sourceHandle:void 0,targetHandle:void 0}:Ie(e,t);return{id:e.id,source:e.from.tableId,target:e.to.tableId,...n,type:r?`erd-floating`:`erd`,data:{kind:e.kind,sourceEnd:{cardinality:e.from.relation,optional:e.from.optional},targetEnd:{cardinality:e.to.relation,optional:e.to.optional}}}})}var Re=(0,t.forwardRef)(function({dbml:e,className:r,style:a,theme:o,fitView:s=!0,showControls:c=!0,showMiniMap:l=!1,showBackground:u=!0,layoutOptions:d,edgeConnection:f=`column`,onParseError:p,onLayoutError:m,nodePositions:h,onNodePositionsChange:_},v){let y=(0,t.useMemo)(()=>{try{return{ok:!0,schema:ee(e)}}catch(e){return{ok:!1,error:e instanceof g?e:new g(String(e),{cause:e})}}},[e]),[b,x,S]=(0,n.useNodesState)([]),[C,w,te]=(0,n.useEdgesState)([]),T=(0,t.useRef)(null),E=(0,t.useRef)(null),D=(0,t.useRef)(b);D.current=b,(0,t.useImperativeHandle)(v,()=>{let e=async e=>{let t=T.current,r=E.current?.querySelector(`.react-flow__viewport`);if(!t||!r)throw new H(`The diagram is not ready to export yet.`);let i=re((0,n.getNodesBounds)(t.getNodes()),r),a=e?.backgroundColor??(E.current?getComputedStyle(E.current).backgroundColor:void 0);return U(r,i,{...e,backgroundColor:a})};return{toDataUrl:e,download:async(t,n)=>{G(await e(n),t)},fitView:e=>T.current?.fitView(e),zoomIn:e=>T.current?.zoomIn(e),zoomOut:e=>T.current?.zoomOut(e),zoomTo:(e,t)=>T.current?.zoomTo(e,t),setCenter:(e,t,n)=>T.current?.setCenter(e,t,n),fitBounds:(e,t)=>T.current?.fitBounds(e,t),setViewport:(e,t)=>T.current?.setViewport(e,t),getViewport:()=>T.current?.getViewport()}},[]);let O=(0,t.useRef)(m);O.current=m;let k=(0,t.useRef)(_);k.current=_;let A=(0,t.useRef)(h);A.current=h;let ne=(0,t.useCallback)(()=>{let e=k.current;if(!e)return;let t={};for(let e of D.current)t[e.id]={x:e.position.x,y:e.position.y};e(t)},[]),{algorithm:j=`simple`,direction:M=`LR`,horizontalGap:N,verticalGap:P,minNodeWidth:F,maxNodeWidth:I}=d??{},L=(0,t.useRef)(null),R=`${j}|${M}|${N}|${P}|${F}|${I}`,z=(0,t.useCallback)((e,t,n,r,i)=>{let a={minWidth:F,maxWidth:I},o=ke(e,r,i.saved,i.prior);if(i.prior){let t=i.prior,n=i.saved;Me(e,o,e=>t.has(e)||n?.[e]!==void 0,P??40,a)}if(x(Fe(e,o,a,Pe(e))),w(Le(e,o,f)),L.current={ids:t,optionsKey:n},i.emit){let e={};o.forEach((t,n)=>{e[n]=t}),k.current?.(e)}i.fit&&requestAnimationFrame(()=>void T.current?.fitView())},[x,w,P,F,I,f]);(0,t.useEffect)(()=>{if(!y.ok){x([]),w([]),L.current=null;return}let e=y.schema,t={algorithm:j,direction:M,horizontalGap:N,verticalGap:P,minNodeWidth:F,maxNodeWidth:I},n=e.tables.map(e=>e.id),r=new Map(D.current.map(e=>[e.id,{x:e.position.x,y:e.position.y}])),i=L.current,a=n.every(e=>r.has(e));if(i&&i.optionsKey===R&&a&&Ae(i.ids,n)){z(e,n,R,new Map,{prior:r});return}let o=i&&i.optionsKey===R?r:void 0,c=!1;return Ne(e,t,e=>O.current?.(e)).then(t=>{c||z(e,n,R,t,{saved:A.current,prior:o,fit:s})}),()=>{c=!0}},[y,j,M,N,P,F,I,R,s,z,x,w]);let B=(0,t.useCallback)(()=>{if(!y.ok)return;let e=y.schema,t={algorithm:j,direction:M,horizontalGap:N,verticalGap:P,minNodeWidth:F,maxNodeWidth:I},n=e.tables.map(e=>e.id);Ne(e,t,e=>O.current?.(e)).then(t=>{z(e,n,R,t,{emit:!0,fit:!0})})},[y,j,M,N,P,F,I,R,z]),V=(0,t.useCallback)(()=>{y.ok||p?.(y.error)},[y,p]);(0,t.useEffect)(V,[V]);let{displayNodes:W,displayEdges:K,onEdgeMouseEnter:Y,onEdgeMouseLeave:X,onColumnHover:ie}=be(y.ok?y.schema.relations:Te,b,C),Z={width:`100%`,height:`100%`,...we(o),...a};return y.ok?(0,i.jsx)(`div`,{ref:E,className:`dv-viewer${r?` ${r}`:``}`,style:Z,children:(0,i.jsx)(J.Provider,{value:f,children:(0,i.jsx)(q.Provider,{value:ie,children:(0,i.jsxs)(n.ReactFlow,{nodes:W,edges:K,nodeTypes:Ee,edgeTypes:De,onNodesChange:S,onEdgesChange:te,onEdgeMouseEnter:Y,onEdgeMouseLeave:X,onNodeDragStop:ne,onInit:e=>{T.current=e},fitView:s,nodesConnectable:!1,elementsSelectable:!0,minZoom:.1,proOptions:{hideAttribution:!0},children:[u&&(0,i.jsx)(n.Background,{}),c&&(0,i.jsx)(n.Controls,{children:(0,i.jsx)(n.ControlButton,{onClick:B,title:`Auto layout`,"aria-label":`Auto layout`,children:(0,i.jsx)(Oe,{})})}),l&&(0,i.jsx)(n.MiniMap,{pannable:!0,zoomable:!0})]})})})}):(0,i.jsx)(`div`,{className:`dv-error${r?` ${r}`:``}`,style:Z,children:(0,i.jsx)(`pre`,{className:`dv-error__message`,children:y.error.message})})});e.DbmlParseError=g,e.DbmlViewer=Re,e.ErdEdge=me,e.ExportError=H,e.HEADER_HEIGHT=te,e.LayoutError=z,e.MAX_NODE_WIDTH=C,e.MIN_NODE_WIDTH=S,e.NODE_WIDTH=w,e.ROW_HEIGHT=T,e.TableNode=ae,e.computeLayout=B,e.darkTheme=Ce,e.downloadDataUrl=G,e.layoutSchema=I,e.lightTheme=Se,e.parseDbml=ee,e.renderDiagram=U,e.tableHeight=E,e.tableWidth=N,e.themeToCssVars=we});
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { JSX } from 'react';
|
|
|
6
6
|
import { MemoExoticComponent } from 'react';
|
|
7
7
|
import { Node as Node_2 } from '@xyflow/react';
|
|
8
8
|
import { NodeProps } from '@xyflow/react';
|
|
9
|
+
import { ReactNode } from 'react';
|
|
9
10
|
import { Rect } from '@xyflow/react';
|
|
10
11
|
import { RefAttributes } from 'react';
|
|
11
12
|
import { SetCenterOptions } from '@xyflow/react';
|
|
@@ -127,6 +128,12 @@ export declare interface DbmlViewerProps {
|
|
|
127
128
|
showBackground?: boolean;
|
|
128
129
|
/** Layout tuning: algorithm (`'simple'` | `'dagre'` | `'elk'`), direction, gaps. */
|
|
129
130
|
layoutOptions?: LayoutOptions;
|
|
131
|
+
/**
|
|
132
|
+
* How edges attach to tables. `'column'` (default) anchors each edge to its specific
|
|
133
|
+
* FK/PK column rows. `'floating'` connects table-to-table, attaching wherever the two
|
|
134
|
+
* tables face each other and following them as they move.
|
|
135
|
+
*/
|
|
136
|
+
edgeConnection?: EdgeConnection;
|
|
130
137
|
/** Called when the DBML fails to parse. */
|
|
131
138
|
onParseError?: (error: DbmlParseError) => void;
|
|
132
139
|
/** Called when a non-default layout fails (e.g. optional dependency missing). */
|
|
@@ -191,6 +198,9 @@ export declare interface DiagramExportOptions {
|
|
|
191
198
|
/** Trigger a browser download of a data URL. */
|
|
192
199
|
export declare function downloadDataUrl(dataUrl: string, filename: string): void;
|
|
193
200
|
|
|
201
|
+
/** How edges attach to tables. */
|
|
202
|
+
export declare type EdgeConnection = 'column' | 'floating';
|
|
203
|
+
|
|
194
204
|
/** Cardinality + optionality of one rendered edge end. */
|
|
195
205
|
export declare interface EdgeEndSpec {
|
|
196
206
|
cardinality: Cardinality;
|
|
@@ -200,7 +210,11 @@ export declare interface EdgeEndSpec {
|
|
|
200
210
|
|
|
201
211
|
export declare const ErdEdge: MemoExoticComponent<typeof ErdEdgeComponent>;
|
|
202
212
|
|
|
203
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Column-anchored edge: endpoints are fixed to per-column handles on the left/right of each
|
|
215
|
+
* table (the default rendering). React Flow supplies the resolved handle coordinates.
|
|
216
|
+
*/
|
|
217
|
+
declare function ErdEdgeComponent({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data, selected, }: EdgeProps): ReactNode;
|
|
204
218
|
|
|
205
219
|
export declare interface ErdEdgeData {
|
|
206
220
|
kind: RelationKind;
|
|
@@ -265,8 +279,11 @@ export declare interface LayoutOptions {
|
|
|
265
279
|
/**
|
|
266
280
|
* Compute node positions for the parsed schema.
|
|
267
281
|
*
|
|
268
|
-
*
|
|
269
|
-
* vertically within each layer.
|
|
282
|
+
* FK-connected tables are arranged left-to-right by their layer in the FK graph and stacked
|
|
283
|
+
* vertically within each layer. Tables with no relations at all are packed into a grid below
|
|
284
|
+
* that layout — filled left-to-right then wrapped — spanning roughly its width, so a large
|
|
285
|
+
* number of unrelated tables no longer pile up in a single tall left-hand column. The result
|
|
286
|
+
* is keyed by {@link TableInfo.id}.
|
|
270
287
|
*/
|
|
271
288
|
export declare function layoutSchema(schema: ParsedSchema, options?: LayoutOptions): Map<string, NodeBox>;
|
|
272
289
|
|
|
@@ -397,6 +414,8 @@ export declare type TableNodeData = {
|
|
|
397
414
|
highlightedColumns?: Set<string>;
|
|
398
415
|
/** Min/max width bounds; must match what layout used so render and layout agree. */
|
|
399
416
|
widthBounds?: NodeWidthBounds;
|
|
417
|
+
/** Columns that an edge attaches to; only these get connection handles. */
|
|
418
|
+
connectedColumns?: Set<string>;
|
|
400
419
|
};
|
|
401
420
|
|
|
402
421
|
export declare type TableNodeType = Node_2<TableNodeData, 'table'>;
|