@graphysdk/react-renderer 1.9.0-beta.1790263076123 → 1.9.0-beta.1790336418293

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require('./index.css');const i=require("./use-target-boundary-CfIbCLSH.cjs"),se=require("./theme.contract.css-DKDKSByt.cjs");let m=require("@graphysdk/viz-engine"),l=require("react"),a=require("react/jsx-runtime"),Y=require("zustand"),O=require("zustand/vanilla"),L=require("clsx");L=i.__toESM(L,1);var ne="_1a5iqpb0",oe="_1a5iqpb1";var ae="_1a5iqpb3",ie="_1a5iqpb4",ce="_1a5iqpb5";var B=({errors:e})=>{const[t,...s]=e;return(0,a.jsxs)("div",{role:"alert",className:ne,children:[(0,a.jsx)("strong",{className:oe,children:"This chart could not be rendered."}),t&&(0,a.jsx)(F,{diagnostic:t}),s.length>0&&(0,a.jsx)("ul",{className:"_1a5iqpb2",children:s.map((r,o)=>(0,a.jsx)("li",{children:(0,a.jsx)(F,{diagnostic:r})},`${r.code}-${o}`))})]})},F=({diagnostic:e})=>(0,a.jsxs)("div",{className:ae,children:[(0,a.jsx)("span",{className:ie,children:e.code}),(0,a.jsx)("p",{className:ce,children:e.message}),e.suggestion&&(0,a.jsx)("p",{className:"_1a5iqpb6",children:e.suggestion})]});function le(e=[],t=[]){return e.length===t.length&&e.every((s,r)=>Object.is(s,t[r]))}var X=class extends l.Component{constructor(...e){super(...e),this.state={caughtDiagnostic:null}}static getDerivedStateFromError(e){return{caughtDiagnostic:(0,m.buildDiagnostic)(e)}}componentDidCatch(e,t){const s=(0,m.buildDiagnostic)(e);i.logDiagnostics([s]),this.props.onError?.([s]),console.error("Chart render component stack:",t.componentStack)}componentDidUpdate(e){this.state.caughtDiagnostic&&!le(e.resetKeys,this.props.resetKeys)&&this.setState({caughtDiagnostic:null})}render(){const{caughtDiagnostic:e}=this.state;if(e)return(0,a.jsx)(B,{errors:[e]});const{forcedErrors:t,children:s}=this.props;return t&&t.length>0?(0,a.jsx)(B,{errors:t}):s}},Q=e=>typeof e=="object"&&"geom"in e&&"render"in e,de=e=>{const t=(0,m.resolveDefinition)(e);return t instanceof m.Geom?t:null},J=(e,t)=>{const s=e.filter(r=>ue(r,t));return s.length===e.length?e:s},ue=(e,t)=>e.kind==="annotation"?(0,m.findAnnotation)(t.annotations,e.id)!==null:e.kind==="observations"||e.kind==="layer"&&e.layerId!==void 0?(0,m.findLayerById)(t.layers,e.layerId)!==void 0:!0,V=[],ge=()=>(0,O.createStore)(e=>({selection:V,setSelection:t=>e(s=>he(s.selection,t)?s:{selection:t}),clearSelection:()=>e(t=>t.selection.length===0?t:{selection:V})})),he=(e,t)=>e===t?!0:e.length!==t.length?!1:e.every((s,r)=>{const o=t[r];return o!==void 0&&(0,m.areEditTargetsEqual)(s,o)}),me=process.env.NODE_ENV!=="production",pe=5,ve=e=>{if(!me)return{emit:()=>{},subscribe:()=>ye,getLastTrigger:()=>null,getLastCompile:()=>null,getCacheStats:()=>e.getCacheStats()};const t=new Set;let s=null;return{emit:r=>{const o=e.getLastCompile();if(o){s=r;for(const d of t)d(r,o)}},subscribe:r=>(t.add(r),()=>{t.delete(r)}),getLastTrigger:()=>s,getLastCompile:()=>e.getLastCompile(),getCacheStats:()=>e.getCacheStats()}},fe=()=>(0,O.createStore)(e=>({lastCompile:null,history:[],nextId:1,lastSnapshot:null,recordCompile:(t,s)=>e(r=>{if(r.lastSnapshot===s)return r;const o={id:r.nextId,label:Se(t),stages:s.stages,stageDurationsMs:s.stageDurationsMs,durationMs:s.durationMs};return{lastCompile:o,history:be(r.history,o,pe),nextId:r.nextId+1,lastSnapshot:s}})})),ye=()=>{},Se=e=>{switch(e.kind){case"init":return"init";case"spec":return"spec change";case"data":return"data change";case"command":return e.command.metadata.description}},be=(e,t,s)=>{const r=e.length>=s?e.length-(s-1):0;return[...e.slice(r),t]};function Ee(e){const t=e.filter(Q),s=new Set([...Object.keys(i.BUILT_IN_GEOM_RENDERERS),...t.map(u=>u.geom)]),r=[],o=new Set;for(const u of e){const h=de(u);h===null||s.has(h.type)||o.has(h.type)||(o.add(h.type),r.push({kind:"user-input",severity:"error",code:"MISSING_GEOM_RENDERER",message:`Custom geom '${h.type}' is registered but has no renderer.`,context:{requested:h.type,kind:"geom-renderer"},suggestion:`Add a render half for it: \`defineGeomRenderer(${h.type}Geom, { coord, render })\`, then include it in \`plugins\`.`}))}const d=new Map;for(const u of t){if("definition"in u)continue;const h=`${u.geom}|${u.coord}`,p=d.get(h);p?p.count+=1:d.set(h,{geom:u.geom,coord:u.coord,count:1})}const c=[];for(const{geom:u,coord:h,count:p}of d.values())p<2||c.push({kind:"user-input",severity:"warning",code:"DUPLICATE_REGISTERED_TYPE",message:`Multiple render-only overrides register ('${u}', '${h}') (${p} entries); the last in the array wins.`,context:{requested:`${u}@${h}`,kind:"geom-renderer"},suggestion:`Keep a single render-only override for ('${u}', '${h}').`});return{errors:r,warnings:c}}function Te(e,t){const{coordSystem:s,layers:r}=e,o=new Set,d=[];for(const c of r)t(c.geom,s.type)!==null||o.has(c.geom)||(o.add(c.geom),d.push({kind:"user-input",severity:"warning",code:"MISSING_GEOM_RENDERER",message:`No renderer for geom '${c.geom}' under ${s.type} coords; the layer is not painted.`,context:{requested:c.geom,kind:"geom-renderer"},suggestion:`Register a renderer for ('${c.geom}', '${s.type}') via \`defineGeomRenderer\`.`}));return d}function xe(e,t){const{coordSystem:s,layers:r}=e,o=new Set,d=[];for(const c of r){if(c.interactive===!1||c.spatialKind!=="render-hit-test"||o.has(c.geom))continue;const u=t(c.geom,s.type);u===null||u.hitTest||i.isOverlayHosted(u)||(o.add(c.geom),d.push({kind:"user-input",severity:"warning",code:"MISSING_RENDER_HIT_TEST",message:`Geom '${c.geom}' declares spatialKind 'render-hit-test' but its renderer provides no hit-test; the layer has no hover.`,context:{requested:c.geom,kind:"geom-renderer"},suggestion:`Add a \`hitTest\` factory (precomputed geometry) or an overlay render (\`{ fn, options: { overlay: true } }\`, live simulation) to the renderer for ('${c.geom}', '${s.type}').`}))}return d}function Re(e){const t=new Set,s=[];for(const r of e.layers){const o=r.identityKey;r.interactive!==!1&&(r.spatialKind!=="render-hit-test"||typeof o!="object"||t.has(r.geom)||r.data.hasVariable(o.variable)||(t.add(r.geom),s.push({kind:"user-input",severity:"warning",code:"RENDER_HIT_TEST_IDENTITY",message:`Geom '${r.geom}' keys its identity on '${o.variable}', a column its compile output does not emit; its hover lookup is empty.`,context:{requested:r.geom,kind:"geom-renderer"},suggestion:`Emit the '${o.variable}' column from the geom's \`compile()\`, or point \`identityKey\` at a column it does emit.`})))}return s}function Ce(e,t){const{coordSystem:s,layers:r}=e,o=new Set,d=[];for(const c of r){if(c.interactive===!1||c.spatialKind!=="render-hit-test"||o.has(c.geom))continue;const u=t(c.geom,s.type);u===null||!u.hitTest||!i.isOverlayHosted(u)||(o.add(c.geom),d.push({kind:"user-input",severity:"warning",code:"CONFLICTING_RENDER_HIT_TEST",message:`Geom '${c.geom}' declares both a \`hitTest\` factory and an overlay render; these are alternatives, so only the overlay is used.`,context:{requested:c.geom,kind:"geom-renderer"},suggestion:"Keep one: a `hitTest` factory for precomputed geometry, OR an overlay render (`{ fn, options: { overlay: true } }`) for a live simulation."}))}return d}function Ge(e,t){const s=new Set,r=[];for(const o of e.layers)o.interactive!==!1&&(o.spatialKind!=="render-hit-test"||s.has(o.geom)||t.hasCapability(o.geom)||(s.add(o.geom),r.push({kind:"user-input",severity:"warning",code:"MISSING_ANCHOR_CAPABILITY",message:`Geom '${o.geom}' declares no \`resolveAnchorPosition\`; its observations cannot be annotated, so the editor overlay paints no creation trigger on them.`,context:{requested:o.geom,kind:"geom-renderer"},suggestion:"Implement `resolveAnchorPosition(observation, context)` on the geom, returning the normalised panel position an annotation on that observation belongs at."})));return r}function qe(e,t){const{coordSystem:s,layers:r}=e,o=new Set,d=[];for(const c of r){if(c.interactive===!1||c.spatialKind==="render-hit-test"||o.has(c.geom))continue;const u=t(c.geom,s.type);u===null||!i.isOverlayHosted(u)||(o.add(c.geom),d.push({kind:"user-input",severity:"warning",code:"OVERLAY_REQUIRES_RENDER_HIT_TEST",message:`Geom '${c.geom}' declares an overlay render but its layer's spatialKind is '${c.spatialKind}', not 'render-hit-test'; the overlay's push-path hover resolves to nothing.`,context:{requested:c.geom,kind:"geom-renderer"},suggestion:"Have the geom's manifest yield spatialKind 'render-hit-test' so the scene layer carries the `byKey` index the overlay's `pushHover` resolves against."}))}return d}var ke=e=>(0,O.createStore)(t=>({scene:e,setScene:s=>t(r=>r.scene===s?r:{scene:s})})),Ne=({spec:e,data:t,customPalettes:s,colorScheme:r,plugins:o,resolveRenderer:d,anchorResolver:c,onSpecChange:u,onError:h,onWarnings:p})=>{const T=i.useLatestRef(u),j=i.useLatestRef(h),G=i.useLatestRef(p),[{session:v,compileBus:g}]=(0,l.useState)(()=>{const n=(0,m.createCompiler)({plugins:o});return{session:new m.GraphCompilationSession(n),compileBus:ve(n)}}),[y]=(0,l.useState)(()=>Ee(o??[])),q=(0,l.useRef)(null),[S]=(0,l.useState)(je),x=(0,l.useRef)(null),k=(0,l.useCallback)(n=>y.errors.length===0?n:[...y.errors,...n??[]],[y]),R=(0,l.useCallback)(n=>{if(!n.ok)return n.errors;if(x.current)x.current.getState().setScene(n.scene);else{const f=ke(n.scene);f.subscribe(S.notify),x.current=f,S.notify()}return null},[S]),[H,D]=(0,l.useState)(()=>{const n=v.compile({spec:e,data:t,customPalettes:s,colorScheme:r});return q.current=n,k(R(n))}),C=(0,l.useCallback)(n=>n.ok?[...n.warnings,...Te(n.scene,d),...xe(n.scene,d),...Re(n.scene),...Ce(n.scene,d),...qe(n.scene,d),...Ge(n.scene,c)]:n.warnings,[d,c]),N=(0,l.useCallback)(n=>{n.length!==0&&(i.logDiagnostics(n),j.current?.(n))},[j]),b=(0,l.useCallback)(n=>{n.length!==0&&(i.logDiagnostics(n),G.current?.(n))},[G]);(0,l.useEffect)(()=>{const n=q.current;n&&(N([...y.errors,...n.ok?[]:n.errors]),b([...y.warnings,...C(n)]),n.ok&&g.emit({kind:"init"}))},[g,N,b,y,C]),(0,l.useEffect)(()=>{const n=v.update({spec:e,data:t,customPalettes:s,colorScheme:r});if(!n)return;n.committedSpec&&T.current?.(n.committedSpec);const f=R(n.result);D(k(f)),f&&N(f),b(C(n.result)),f||g.emit({kind:n.specChanged?"spec":"data"})},[e,t,s,r,v,g,R,N,b,k,C,T]);const I=(0,l.useCallback)(n=>{D(f=>f===null?f:k(null)),b(C(n))},[k,b,C]),_=(0,l.useCallback)(n=>{n.scene&&x.current?.getState().setScene(n.scene),n.result&&I(n.result),n.command&&g.emit({kind:"command",command:n.command}),n.spec&&T.current?.(n.spec),n.errors&&N([...n.errors])},[I,g,T,N]),E=(0,l.useCallback)(n=>{for(const f of n)_(f);return n.some(f=>!!f.scene)},[_]),M=(0,l.useCallback)((n,f)=>{E(v.applyCommand(n,f))},[v,E]),$=(0,l.useCallback)(()=>{E(v.commit())},[v,E]),K=(0,l.useCallback)(()=>E(v.undo()),[v,E]),U=(0,l.useCallback)(()=>E(v.redo()),[v,E]),te=(0,l.useMemo)(()=>({stack:v.history,undo:K,redo:U}),[v,K,U]),re=(0,l.useCallback)(()=>x.current?.getState().scene??null,[]);return{store:x.current,dispatch:M,commit:$,history:te,subscribe:S.subscribe,getScene:re,compileBus:g,compileErrors:H}},je=()=>{const e=new Set;return{subscribe:t=>(e.add(t),()=>{e.delete(t)}),notify:()=>e.forEach(t=>t())}},Z=({data:e,spec:t,plugins:s=[],formattingLocale:r,handleRef:o,onSpecChange:d,onError:c,onWarnings:u,customPalettes:h,colorScheme:p="light",children:T})=>{const[j]=(0,l.useState)(()=>i.createGeomRendererResolver(s.filter(Q))),G=(0,l.useId)(),[v]=(0,l.useState)(()=>(0,m.createAnchorResolver)(s)),[g]=(0,l.useState)(()=>ge()),[y]=(0,l.useState)(()=>i.createTargetBoundaryStore()),q=(0,l.useMemo)(()=>(0,m.createStyleResolver)({colorScheme:p}),[p]),{store:S,dispatch:x,commit:k,history:R,subscribe:H,getScene:D,compileBus:C,compileErrors:N}=Ne({spec:t,data:e,customPalettes:h,colorScheme:p,plugins:s,resolveRenderer:j,anchorResolver:v,onSpecChange:d,onError:c,onWarnings:u});(0,l.useEffect)(()=>{if(S)return S.subscribe((_,E)=>{if(_.scene.spec===E.scene.spec)return;const{selection:M,setSelection:$}=g.getState();M.length!==0&&$(J(M,_.scene.spec))})},[S,g]);const b=(0,l.useMemo)(()=>({dispatch:x,commit:k}),[x,k]);(0,l.useImperativeHandle)(o,()=>({commands:b,undo:R.undo,redo:R.redo,subscribe:H,getScene:D,getSelection:()=>g.getState().selection,setSelection:_=>g.getState().setSelection(_),subscribeSelection:g.subscribe}),[b,R,H,D,g]);const I=(0,l.useMemo)(()=>S?{chartId:G,store:S,selectionStore:g,targetBoundaryStore:y,commands:b,history:R,formattingLocale:r,compileBus:C,colorScheme:p,styleResolver:q,anchorResolver:v}:null,[G,S,g,y,b,R,r,C,p,q,v]);return(0,a.jsx)(X,{forcedErrors:N,onError:c,resetKeys:[t,e],children:I?(0,a.jsx)(i.GraphContext.Provider,{value:I,children:(0,a.jsx)(i.GeomRendererResolverProvider,{value:j,children:T})}):null})};function _e(e){const t=(0,m.createSpecBuilder)(e);return{...t,GraphProvider:r=>(0,a.jsx)(Z,{...r,plugins:t.plugins})}}var De=({children:e,...t})=>(0,a.jsx)("svg",{viewBox:"0 0 1 1",preserveAspectRatio:"none",width:"100%",height:"100%",pointerEvents:"none",...t,children:e}),Ie=({box:e,children:t})=>(0,a.jsx)("svg",{x:(0,m.toPercent)(e.x0),y:(0,m.toPercent)(e.y0),width:(0,m.toPercent)(e.x1-e.x0),height:(0,m.toPercent)(e.y1-e.y0),overflow:"hidden",pointerEvents:"none",children:t}),we="drqe3u0",He="drqe3u1",Me="drqe3u2",Pe="drqe3u3",w="drqe3u4",$e="drqe3u5",Le="drqe3u6",Be="drqe3u7",P="drqe3u8",Oe="drqe3u9",Ae="drqe3ua";var Ke="drqe3uc",Ue="drqe3ud",Ye="drqe3ue",Fe="drqe3uf";var Ve="drqe3uh",We="drqe3ui",W={enabled:"drqe3uk drqe3uj",disabled:"drqe3ul drqe3uj"},z={ran:"drqe3un drqe3um",dim:"drqe3uo drqe3um"},ee={ran:"drqe3uq drqe3up",cached:"drqe3ur drqe3up",untouched:"drqe3us drqe3up"},ze=({width:e=440,style:t,className:s}={})=>{const{compileBus:r}=i.useGraphContext(),[o]=(0,l.useState)(()=>fe()),[d,c]=(0,l.useState)(!1),[u,h]=(0,l.useState)(m.isCompilerCachingEnabled);(0,l.useEffect)(()=>{const{recordCompile:g}=o.getState(),y=r.getLastTrigger(),q=r.getLastCompile();return y&&q&&g(y,q),r.subscribe(g)},[o,r]);const p=(0,Y.useStore)(o,g=>g.lastCompile),T=(0,Y.useStore)(o,g=>g.history),j=r.getCacheStats(),G=p===null&&T.length===0,v=()=>{h(g=>{const y=!g;return(0,m.setCompilerCachingEnabled)(y),y})};return(0,a.jsxs)("div",{className:(0,L.default)(Ae,s),style:{width:e,...t},children:[(0,a.jsxs)("div",{className:we,children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("div",{className:He,children:"compile cache"}),(0,a.jsx)("div",{className:Ye,children:G?"production: stats disabled":p?`last: ${p.label} · ${A(p.durationMs)}`:"awaiting first compile…"})]}),(0,a.jsx)("button",{type:"button",onClick:()=>c(g=>!g),className:Fe,children:d?"▾":"▴"})]}),!d&&(0,a.jsxs)("div",{className:"drqe3ub",children:[(0,a.jsxs)("button",{type:"button",onClick:v,className:u?W.enabled:W.disabled,"aria-pressed":u,children:["cache ",u?"enabled":"disabled"]}),(0,a.jsx)("span",{className:"drqe3ug",children:"next compile reflects this toggle"})]}),!d&&!G&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(Xe,{delta:p?.stages,durations:p?.stageDurationsMs,cumulative:j}),(0,a.jsx)(Qe,{entries:T})]})]})},Xe=({delta:e,durations:t,cumulative:s})=>(0,a.jsxs)("table",{className:Me,children:[(0,a.jsx)("thead",{children:(0,a.jsxs)("tr",{className:Ve,children:[(0,a.jsx)("th",{className:Pe,children:"stage"}),(0,a.jsx)("th",{className:w,children:"time"}),(0,a.jsx)("th",{className:w,children:"Δ miss"}),(0,a.jsx)("th",{className:w,children:"Δ hit"}),(0,a.jsx)("th",{className:w,children:"total miss"}),(0,a.jsx)("th",{className:w,children:"total hit"})]})}),(0,a.jsx)("tbody",{children:m.COMPILER_STAGE_KEYS.map(r=>{const o=e?.[r],d=Je(o);return(0,a.jsxs)("tr",{className:Ke,children:[(0,a.jsxs)("td",{className:$e,children:[(0,a.jsx)("span",{className:ee[d],"aria-hidden":!0})," ",r]}),(0,a.jsx)("td",{className:P,children:t===void 0||d==="untouched"?"—":A(t[r])}),(0,a.jsx)("td",{className:d==="ran"?z.ran:z.dim,children:o?.misses??0}),(0,a.jsx)("td",{className:P,children:o?.hits??0}),(0,a.jsx)("td",{className:P,children:s[r].misses}),(0,a.jsx)("td",{className:P,children:s[r].hits})]},r)})})]}),Qe=({entries:e})=>e.length===0?null:(0,a.jsxs)("div",{className:Ue,children:[(0,a.jsx)("div",{className:We,children:"recent compiles"}),e.map(t=>{const s=Ze(t.stages,d=>d.misses>0),r=m.COMPILER_STAGE_KEYS.length,o=s===0?"cached":"ran";return(0,a.jsxs)("div",{className:Le,children:[(0,a.jsx)("span",{className:ee[o],"aria-hidden":!0}),(0,a.jsx)("span",{className:Be,title:t.label,children:t.label}),(0,a.jsxs)("span",{className:Oe,children:[s,"/",r," ran · ",A(t.durationMs)]})]},t.id)})]}),Je=e=>!e||e.hits===0&&e.misses===0?"untouched":e.misses>0?"ran":"cached",Ze=(e,t)=>{let s=0;for(const r of m.COMPILER_STAGE_KEYS)t(e[r])&&(s+=1);return s},A=e=>e<.1?"<0.1ms":e>=10?`${e.toFixed(0)}ms`:`${e.toFixed(2)}ms`,et=()=>{const{history:e}=i.useGraphContext(),{stack:t,undo:s,redo:r}=e,o=(0,l.useCallback)(u=>t.subscribe(u),[t]),d=(0,l.useCallback)(()=>t.getSnapshot(),[t]),c=(0,l.useSyncExternalStore)(o,d,d);return(0,l.useMemo)(()=>({...c,undo:s,redo:r}),[c,s,r])},tt=new Set(["button","checkbox","color","file","hidden","image","radio","range","reset","submit"]),rt=(e,t={})=>{const{target:s,enabled:r=!0}=t;(0,l.useEffect)(()=>{const o=st(s);if(!r||!o)return;const d=c=>{if(!nt(c)||c.defaultPrevented||ot(c.target))return;const u=i.resolveHistoryStep(c);if(!u)return;const h=e.current;h&&(u==="undo"?h.undo():h.redo())&&c.preventDefault()};return o.addEventListener("keydown",d),()=>o.removeEventListener("keydown",d)},[e,s,r])},st=e=>e===void 0?window:e!==null&&"current"in e?e.current:e,nt=e=>"key"in e,ot=e=>e instanceof HTMLInputElement?!tt.has(e.type):e instanceof HTMLElement?e.isContentEditable||e.tagName==="TEXTAREA":!1;exports.BrandMark=i.BrandMark;exports.CanvasTextMeasurer=i.CanvasTextMeasurer;exports.DefaultFooter=i.DefaultFooter;exports.DefaultGrid=i.DefaultGrid;exports.DefaultHeader=i.DefaultHeader;exports.DefaultSwatch=i.DefaultSwatch;exports.DefaultTooltip=i.DefaultTooltip;exports.DevToolsPanel=ze;exports.GRAPH_MODES=i.GRAPH_MODES;exports.GraphErrorBoundary=X;exports.GraphErrorPanel=B;exports.GraphProvider=Z;exports.GraphRenderer=i.GraphRenderer;exports.HoverProvider=i.HoverProvider;exports.TextMeasurerProvider=i.TextMeasurerProvider;exports.ThemeProvider=i.ThemeProvider;exports.UnitBoxSvg=Ie;exports.UnitSpaceSvg=De;exports.createGraphyKit=_e;exports.darkTheme=i.darkTheme;exports.defineGeomRenderer=i.defineGeomRenderer;exports.lightTheme=i.lightTheme;exports.lightenCss=i.lightenCss;exports.pruneSelection=J;exports.resolveBrandMarkVisual=i.resolveBrandMarkVisual;exports.stampAxisEditTarget=i.stampAxisEditTarget;exports.stampGridEditTarget=i.stampGridEditTarget;exports.stampLegendEditTarget=i.stampLegendEditTarget;exports.useElementScreenRect=i.useElementScreenRect;exports.useGeomHitTest=i.useGeomHitTest;exports.useGeomHover=i.useGeomHover;exports.useGeomReaderTree=i.useGeomReaderTree;exports.useGraphCommands=i.useGraphCommands;exports.useGraphHandle=i.useGraphHandle;exports.useGraphHistory=et;exports.useGraphHistoryShortcuts=rt;exports.useGraphSelection=i.useGraphSelection;exports.useGuidesTakePress=i.useGuidesTakePress;exports.useHandleScene=i.useHandleScene;exports.useHoverState=i.useHoverState;exports.useResolvedStyle=i.useResolvedStyle;exports.useSceneSelector=i.useSceneSelector;exports.useStyleReaderTree=i.useStyleReaderTree;exports.useStyleReaders=i.useStyleReaders;exports.useStyleResolver=i.useStyleResolver;exports.useTargetBoundary=i.useTargetBoundary;exports.useTextMeasurer=i.useTextMeasurer;exports.vars=se.vars;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require('./index.css');const a=require("./use-target-boundary-CfPZiZ0A.cjs"),ae=require("./theme.contract.css-DKDKSByt.cjs");let h=require("@graphysdk/viz-engine"),d=require("react"),i=require("react/jsx-runtime"),U=require("zustand"),X=require("motion/react"),O=require("zustand/vanilla"),A=require("clsx");A=a.__toESM(A,1);var oe="_1a5iqpb0",ie="_1a5iqpb1";var ce="_1a5iqpb3",le="_1a5iqpb4",de="_1a5iqpb5";var B=({errors:e})=>{const[t,...s]=e;return(0,i.jsxs)("div",{role:"alert",className:oe,children:[(0,i.jsx)("strong",{className:ie,children:"This chart could not be rendered."}),t&&(0,i.jsx)(Y,{diagnostic:t}),s.length>0&&(0,i.jsx)("ul",{className:"_1a5iqpb2",children:s.map((r,n)=>(0,i.jsx)("li",{children:(0,i.jsx)(Y,{diagnostic:r})},`${r.code}-${n}`))})]})},Y=({diagnostic:e})=>(0,i.jsxs)("div",{className:ce,children:[(0,i.jsx)("span",{className:le,children:e.code}),(0,i.jsx)("p",{className:de,children:e.message}),e.suggestion&&(0,i.jsx)("p",{className:"_1a5iqpb6",children:e.suggestion})]});function ue(e=[],t=[]){return e.length===t.length&&e.every((s,r)=>Object.is(s,t[r]))}var Q=class extends d.Component{constructor(...e){super(...e),this.state={caughtDiagnostic:null}}static getDerivedStateFromError(e){return{caughtDiagnostic:(0,h.buildDiagnostic)(e)}}componentDidCatch(e,t){const s=(0,h.buildDiagnostic)(e);a.logDiagnostics([s]),this.props.onError?.([s]),console.error("Chart render component stack:",t.componentStack)}componentDidUpdate(e){this.state.caughtDiagnostic&&!ue(e.resetKeys,this.props.resetKeys)&&this.setState({caughtDiagnostic:null})}render(){const{caughtDiagnostic:e}=this.state;if(e)return(0,i.jsx)(B,{errors:[e]});const{forcedErrors:t,children:s}=this.props;return t&&t.length>0?(0,i.jsx)(B,{errors:t}):s}},J=e=>typeof e=="object"&&"geom"in e&&"render"in e,Z=e=>{const t=(0,h.resolveDefinition)(e);return t instanceof h.Geom?t:null},ee=(e,t)=>{const s=e.filter(r=>me(r,t));return s.length===e.length?e:s},me=(e,t)=>e.kind==="annotation"?(0,h.findAnnotation)(t.annotations,e.id)!==null:e.kind==="observations"||e.kind==="layer"&&e.layerId!==void 0?(0,h.findLayerById)(t.layers,e.layerId)!==void 0:!0,W=[],ge=()=>(0,O.createStore)(e=>({selection:W,setSelection:t=>e(s=>he(s.selection,t)?s:{selection:t}),clearSelection:()=>e(t=>t.selection.length===0?t:{selection:W})})),he=(e,t)=>e===t?!0:e.length!==t.length?!1:e.every((s,r)=>{const n=t[r];return n!==void 0&&(0,h.areEditTargetsEqual)(s,n)}),pe=process.env.NODE_ENV!=="production",fe=5,ve=e=>{if(!pe)return{emit:()=>{},subscribe:()=>Se,getLastTrigger:()=>null,getLastCompile:()=>null,getCacheStats:()=>e.getCacheStats()};const t=new Set;let s=null;return{emit:r=>{const n=e.getLastCompile();if(n){s=r;for(const l of t)l(r,n)}},subscribe:r=>(t.add(r),()=>{t.delete(r)}),getLastTrigger:()=>s,getLastCompile:()=>e.getLastCompile(),getCacheStats:()=>e.getCacheStats()}},ye=()=>(0,O.createStore)(e=>({lastCompile:null,history:[],nextId:1,lastSnapshot:null,recordCompile:(t,s)=>e(r=>{if(r.lastSnapshot===s)return r;const n={id:r.nextId,label:be(t),stages:s.stages,stageDurationsMs:s.stageDurationsMs,durationMs:s.durationMs};return{lastCompile:n,history:Ee(r.history,n,fe),nextId:r.nextId+1,lastSnapshot:s}})})),Se=()=>{},be=e=>{switch(e.kind){case"init":return"init";case"spec":return"spec change";case"data":return"data change";case"command":return e.command.metadata.description}},Ee=(e,t,s)=>{const r=e.length>=s?e.length-(s-1):0;return[...e.slice(r),t]};function Te(e){const t=e.filter(J),s=new Set([...Object.keys(a.BUILT_IN_GEOM_RENDERERS),...t.map(u=>u.geom)]),r=[],n=new Set;for(const u of e){const m=Z(u);m===null||s.has(m.type)||n.has(m.type)||(n.add(m.type),r.push({kind:"user-input",severity:"error",code:"MISSING_GEOM_RENDERER",message:`Custom geom '${m.type}' is registered but has no renderer.`,context:{requested:m.type,kind:"geom-renderer"},suggestion:`Add a render half for it: \`defineGeomRenderer(${m.type}Geom, { coord, render })\`, then include it in \`plugins\`.`}))}const l=new Map;for(const u of t){if("definition"in u)continue;const m=`${u.geom}|${u.coord}`,f=l.get(m);f?f.count+=1:l.set(m,{geom:u.geom,coord:u.coord,count:1})}const c=[];for(const{geom:u,coord:m,count:f}of l.values())f<2||c.push({kind:"user-input",severity:"warning",code:"DUPLICATE_REGISTERED_TYPE",message:`Multiple render-only overrides register ('${u}', '${m}') (${f} entries); the last in the array wins.`,context:{requested:`${u}@${m}`,kind:"geom-renderer"},suggestion:`Keep a single render-only override for ('${u}', '${m}').`});return c.push(...je(e)),{errors:r,warnings:c}}function xe(e,t){const{coordSystem:s,layers:r}=e,n=new Set,l=[];for(const c of r)t(c.geom,s.type)!==null||n.has(c.geom)||(n.add(c.geom),l.push({kind:"user-input",severity:"warning",code:"MISSING_GEOM_RENDERER",message:`No renderer for geom '${c.geom}' under ${s.type} coords; the layer is not painted.`,context:{requested:c.geom,kind:"geom-renderer"},suggestion:`Register a renderer for ('${c.geom}', '${s.type}') via \`defineGeomRenderer\`.`}));return l}function Ce(e,t){const{coordSystem:s,layers:r}=e,n=new Set,l=[];for(const c of r){if(c.interactive===!1||c.spatialKind!=="render-hit-test"||n.has(c.geom))continue;const u=t(c.geom,s.type);u===null||u.hitTest||a.isOverlayHosted(u)||(n.add(c.geom),l.push({kind:"user-input",severity:"warning",code:"MISSING_RENDER_HIT_TEST",message:`Geom '${c.geom}' declares spatialKind 'render-hit-test' but its renderer provides no hit-test; the layer has no hover.`,context:{requested:c.geom,kind:"geom-renderer"},suggestion:`Add a \`hitTest\` factory (precomputed geometry) or an overlay render (\`{ fn, options: { overlay: true } }\`, live simulation) to the renderer for ('${c.geom}', '${s.type}').`}))}return l}function Re(e){const t=new Set,s=[];for(const r of e.layers){const n=r.identityKey;r.interactive!==!1&&(r.spatialKind!=="render-hit-test"||typeof n!="object"||t.has(r.geom)||r.data.hasVariable(n.variable)||(t.add(r.geom),s.push({kind:"user-input",severity:"warning",code:"RENDER_HIT_TEST_IDENTITY",message:`Geom '${r.geom}' keys its identity on '${n.variable}', a column its compile output does not emit; its hover lookup is empty.`,context:{requested:r.geom,kind:"geom-renderer"},suggestion:`Emit the '${n.variable}' column from the geom's \`compile()\`, or point \`identityKey\` at a column it does emit.`})))}return s}function Ge(e,t){const{coordSystem:s,layers:r}=e,n=new Set,l=[];for(const c of r){if(c.interactive===!1||c.spatialKind!=="render-hit-test"||n.has(c.geom))continue;const u=t(c.geom,s.type);u===null||!u.hitTest||!a.isOverlayHosted(u)||(n.add(c.geom),l.push({kind:"user-input",severity:"warning",code:"CONFLICTING_RENDER_HIT_TEST",message:`Geom '${c.geom}' declares both a \`hitTest\` factory and an overlay render; these are alternatives, so only the overlay is used.`,context:{requested:c.geom,kind:"geom-renderer"},suggestion:"Keep one: a `hitTest` factory for precomputed geometry, OR an overlay render (`{ fn, options: { overlay: true } }`) for a live simulation."}))}return l}function Ne(e,t){const s=new Set,r=[];for(const n of e.layers)n.interactive!==!1&&(n.spatialKind!=="render-hit-test"||s.has(n.geom)||t.hasCapability(n.geom)||(s.add(n.geom),r.push({kind:"user-input",severity:"warning",code:"MISSING_ANCHOR_CAPABILITY",message:`Geom '${n.geom}' declares no \`resolveAnchorPosition\`; its observations cannot be annotated, so the editor overlay paints no creation trigger on them.`,context:{requested:n.geom,kind:"geom-renderer"},suggestion:"Implement `resolveAnchorPosition(observation, context)` on the geom, returning the normalised panel position an annotation on that observation belongs at."})));return r}function _e(e,t){const{coordSystem:s,layers:r}=e,n=new Set,l=[];for(const c of r){if(c.interactive===!1||c.spatialKind==="render-hit-test"||n.has(c.geom))continue;const u=t(c.geom,s.type);u===null||!a.isOverlayHosted(u)||(n.add(c.geom),l.push({kind:"user-input",severity:"warning",code:"OVERLAY_REQUIRES_RENDER_HIT_TEST",message:`Geom '${c.geom}' declares an overlay render but its layer's spatialKind is '${c.spatialKind}', not 'render-hit-test'; the overlay's push-path hover resolves to nothing.`,context:{requested:c.geom,kind:"geom-renderer"},suggestion:"Have the geom's manifest yield spatialKind 'render-hit-test' so the scene layer carries the `byKey` index the overlay's `pushHover` resolves against."}))}return l}function je(e){const t=new Set,s=[];for(const r of e){const n=Z(r);n===null||t.has(n.type)||n.dataLabelCoordTypes.length===0||n.getDataLabelPlacements!==void 0||(t.add(n.type),s.push({kind:"user-input",severity:"warning",code:"MISSING_DATA_LABEL_PLACEMENT",message:`Geom '${n.type}' declares \`dataLabelCoordTypes\` but implements no \`getDataLabelPlacements\`; its layers paint no data labels.`,context:{requested:n.type,kind:"geom-renderer"},suggestion:"Implement `getDataLabelPlacements(context)` on the geom, or drop `dataLabelCoordTypes` so the compiler warns the author off the flag."}))}return s}var qe=e=>(0,O.createStore)(t=>({scene:e,setScene:s=>t(r=>r.scene===s?r:{scene:s})})),ke=({spec:e,data:t,customPalettes:s,colorScheme:r,plugins:n,resolveRenderer:l,anchorResolver:c,onSpecChange:u,onError:m,onWarnings:f})=>{const E=a.useLatestRef(u),_=a.useLatestRef(m),C=a.useLatestRef(f),[{session:v,compileBus:g}]=(0,d.useState)(()=>{const o=(0,h.createCompiler)({plugins:n});return{session:new h.GraphCompilationSession(o),compileBus:ve(o)}}),[p]=(0,d.useState)(()=>Te(n??[])),R=(0,d.useRef)(null),[j]=(0,d.useState)(De),S=(0,d.useRef)(null),G=(0,d.useCallback)(o=>p.errors.length===0?o:[...p.errors,...o??[]],[p]),D=(0,d.useCallback)(o=>{if(!o.ok)return o.errors;if(S.current)S.current.getState().setScene(o.scene);else{const y=qe(o.scene);y.subscribe(j.notify),S.current=y,j.notify()}return null},[j]),[q,I]=(0,d.useState)(()=>{const o=v.compile({spec:e,data:t,customPalettes:s,colorScheme:r});return R.current=o,G(D(o))}),T=(0,d.useCallback)(o=>o.ok?[...o.warnings,...xe(o.scene,l),...Ce(o.scene,l),...Re(o.scene),...Ge(o.scene,l),..._e(o.scene,l),...Ne(o.scene,c)]:o.warnings,[l,c]),x=(0,d.useCallback)(o=>{o.length!==0&&(a.logDiagnostics(o),_.current?.(o))},[_]),N=(0,d.useCallback)(o=>{o.length!==0&&(a.logDiagnostics(o),C.current?.(o))},[C]);(0,d.useEffect)(()=>{const o=R.current;o&&(x([...p.errors,...o.ok?[]:o.errors]),N([...p.warnings,...T(o)]),o.ok&&g.emit({kind:"init"}))},[g,x,N,p,T]),(0,d.useEffect)(()=>{const o=v.update({spec:e,data:t,customPalettes:s,colorScheme:r});if(!o)return;o.committedSpec&&E.current?.(o.committedSpec);const y=D(o.result);I(G(y)),y&&x(y),N(T(o.result)),y||g.emit({kind:o.specChanged?"spec":"data"})},[e,t,s,r,v,g,D,x,N,G,T,E]);const k=(0,d.useCallback)(o=>{I(y=>y===null?y:G(null)),N(T(o))},[G,N,T]),P=(0,d.useCallback)(o=>{o.scene&&S.current?.getState().setScene(o.scene),o.result&&k(o.result),o.command&&g.emit({kind:"command",command:o.command}),o.spec&&E.current?.(o.spec),o.errors&&x([...o.errors])},[k,g,E,x]),b=(0,d.useCallback)(o=>{for(const y of o)P(y);return o.some(y=>!!y.scene)},[P]),$=(0,d.useCallback)((o,y)=>{b(v.applyCommand(o,y))},[v,b]),L=(0,d.useCallback)(()=>{b(v.commit())},[v,b]),M=(0,d.useCallback)(()=>b(v.undo()),[v,b]),F=(0,d.useCallback)(()=>b(v.redo()),[v,b]),se=(0,d.useMemo)(()=>({stack:v.history,undo:M,redo:F}),[v,M,F]),ne=(0,d.useCallback)(()=>S.current?.getState().scene??null,[]);return{store:S.current,dispatch:$,commit:L,history:se,subscribe:j.subscribe,getScene:ne,compileBus:g,compileErrors:q}},De=()=>{const e=new Set;return{subscribe:t=>(e.add(t),()=>{e.delete(t)}),notify:()=>e.forEach(t=>t())}},te=({data:e,spec:t,plugins:s=[],formattingLocale:r,handleRef:n,onSpecChange:l,onError:c,onWarnings:u,customPalettes:m,colorScheme:f="light",children:E})=>{const[_]=(0,d.useState)(()=>a.createGeomRendererResolver(s.filter(J))),C=(0,d.useId)(),[v]=(0,d.useState)(()=>(0,h.createAnchorResolver)(s)),[g]=(0,d.useState)(()=>(0,h.createDataLabelPlacementResolver)(s)),[p]=(0,d.useState)(()=>ge()),[R]=(0,d.useState)(()=>a.createTargetBoundaryStore()),j=(0,d.useMemo)(()=>(0,h.createStyleResolver)({colorScheme:f}),[f]),{store:S,dispatch:G,commit:D,history:q,subscribe:I,getScene:T,compileBus:x,compileErrors:N}=ke({spec:t,data:e,customPalettes:m,colorScheme:f,plugins:s,resolveRenderer:_,anchorResolver:v,onSpecChange:l,onError:c,onWarnings:u});(0,d.useEffect)(()=>{if(S)return S.subscribe((b,$)=>{if(b.scene.spec===$.scene.spec)return;const{selection:L,setSelection:M}=p.getState();L.length!==0&&M(ee(L,b.scene.spec))})},[S,p]);const k=(0,d.useMemo)(()=>({dispatch:G,commit:D}),[G,D]);(0,d.useImperativeHandle)(n,()=>({commands:k,undo:q.undo,redo:q.redo,subscribe:I,getScene:T,getSelection:()=>p.getState().selection,setSelection:b=>p.getState().setSelection(b),subscribeSelection:p.subscribe,canPlaceDataLabels:g.hasCapability,canFormatDataLabelsAsPercentages:g.hasPercentageFormat}),[k,q,I,T,p,g]);const P=(0,d.useMemo)(()=>S?{chartId:C,store:S,selectionStore:p,targetBoundaryStore:R,commands:k,history:q,formattingLocale:r,compileBus:x,colorScheme:f,styleResolver:j,anchorResolver:v}:null,[C,S,p,R,k,q,r,x,f,j,v]);return(0,i.jsx)(Q,{forcedErrors:N,onError:c,resetKeys:[t,e],children:P?(0,i.jsx)(a.GraphContext.Provider,{value:P,children:(0,i.jsx)(a.GeomRendererResolverProvider,{value:_,children:(0,i.jsx)(a.DataLabelPlacementResolverProvider,{value:g,children:E})})}):null})};function Ie(e){const t=(0,h.createSpecBuilder)(e);return{...t,GraphProvider:r=>(0,i.jsx)(te,{...r,plugins:t.plugins})}}var Pe=({shouldAnimateTransitions:e,cx:t,cy:s,r,...n})=>e?(0,i.jsx)(X.motion.circle,{initial:!1,animate:{cx:t,cy:s,r},transition:a.DEFAULT_SPRING_TRANSITION,...n}):(0,i.jsx)("circle",{cx:t,cy:s,r,...n}),we=({shouldAnimateTransitions:e,x1:t,y1:s,x2:r,y2:n,...l})=>e?(0,i.jsx)(X.motion.line,{initial:!1,animate:{x1:t,y1:s,x2:r,y2:n},transition:a.DEFAULT_SPRING_TRANSITION,...l}):(0,i.jsx)("line",{x1:t,y1:s,x2:r,y2:n,...l}),Le=({children:e,...t})=>(0,i.jsx)("svg",{viewBox:"0 0 1 1",preserveAspectRatio:"none",width:"100%",height:"100%",pointerEvents:"none",...t,children:e}),Me=({box:e,children:t})=>(0,i.jsx)("svg",{x:(0,h.toPercent)(e.x0),y:(0,h.toPercent)(e.y0),width:(0,h.toPercent)(e.x1-e.x0),height:(0,h.toPercent)(e.y1-e.y0),overflow:"hidden",pointerEvents:"none",children:t}),He="drqe3u0",$e="drqe3u1",Ae="drqe3u2",Be="drqe3u3",w="drqe3u4",Oe="drqe3u5",Ke="drqe3u6",Fe="drqe3u7",H="drqe3u8",Ue="drqe3u9",Ye="drqe3ua";var We="drqe3uc",Ve="drqe3ud",ze="drqe3ue",Xe="drqe3uf";var Qe="drqe3uh",Je="drqe3ui",V={enabled:"drqe3uk drqe3uj",disabled:"drqe3ul drqe3uj"},z={ran:"drqe3un drqe3um",dim:"drqe3uo drqe3um"},re={ran:"drqe3uq drqe3up",cached:"drqe3ur drqe3up",untouched:"drqe3us drqe3up"},Ze=({width:e=440,style:t,className:s}={})=>{const{compileBus:r}=a.useGraphContext(),[n]=(0,d.useState)(()=>ye()),[l,c]=(0,d.useState)(!1),[u,m]=(0,d.useState)(h.isCompilerCachingEnabled);(0,d.useEffect)(()=>{const{recordCompile:g}=n.getState(),p=r.getLastTrigger(),R=r.getLastCompile();return p&&R&&g(p,R),r.subscribe(g)},[n,r]);const f=(0,U.useStore)(n,g=>g.lastCompile),E=(0,U.useStore)(n,g=>g.history),_=r.getCacheStats(),C=f===null&&E.length===0,v=()=>{m(g=>{const p=!g;return(0,h.setCompilerCachingEnabled)(p),p})};return(0,i.jsxs)("div",{className:(0,A.default)(Ye,s),style:{width:e,...t},children:[(0,i.jsxs)("div",{className:He,children:[(0,i.jsxs)("div",{children:[(0,i.jsx)("div",{className:$e,children:"compile cache"}),(0,i.jsx)("div",{className:ze,children:C?"production: stats disabled":f?`last: ${f.label} · ${K(f.durationMs)}`:"awaiting first compile…"})]}),(0,i.jsx)("button",{type:"button",onClick:()=>c(g=>!g),className:Xe,children:l?"▾":"▴"})]}),!l&&(0,i.jsxs)("div",{className:"drqe3ub",children:[(0,i.jsxs)("button",{type:"button",onClick:v,className:u?V.enabled:V.disabled,"aria-pressed":u,children:["cache ",u?"enabled":"disabled"]}),(0,i.jsx)("span",{className:"drqe3ug",children:"next compile reflects this toggle"})]}),!l&&!C&&(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(et,{delta:f?.stages,durations:f?.stageDurationsMs,cumulative:_}),(0,i.jsx)(tt,{entries:E})]})]})},et=({delta:e,durations:t,cumulative:s})=>(0,i.jsxs)("table",{className:Ae,children:[(0,i.jsx)("thead",{children:(0,i.jsxs)("tr",{className:Qe,children:[(0,i.jsx)("th",{className:Be,children:"stage"}),(0,i.jsx)("th",{className:w,children:"time"}),(0,i.jsx)("th",{className:w,children:"Δ miss"}),(0,i.jsx)("th",{className:w,children:"Δ hit"}),(0,i.jsx)("th",{className:w,children:"total miss"}),(0,i.jsx)("th",{className:w,children:"total hit"})]})}),(0,i.jsx)("tbody",{children:h.COMPILER_STAGE_KEYS.map(r=>{const n=e?.[r],l=rt(n);return(0,i.jsxs)("tr",{className:We,children:[(0,i.jsxs)("td",{className:Oe,children:[(0,i.jsx)("span",{className:re[l],"aria-hidden":!0})," ",r]}),(0,i.jsx)("td",{className:H,children:t===void 0||l==="untouched"?"—":K(t[r])}),(0,i.jsx)("td",{className:l==="ran"?z.ran:z.dim,children:n?.misses??0}),(0,i.jsx)("td",{className:H,children:n?.hits??0}),(0,i.jsx)("td",{className:H,children:s[r].misses}),(0,i.jsx)("td",{className:H,children:s[r].hits})]},r)})})]}),tt=({entries:e})=>e.length===0?null:(0,i.jsxs)("div",{className:Ve,children:[(0,i.jsx)("div",{className:Je,children:"recent compiles"}),e.map(t=>{const s=st(t.stages,l=>l.misses>0),r=h.COMPILER_STAGE_KEYS.length,n=s===0?"cached":"ran";return(0,i.jsxs)("div",{className:Ke,children:[(0,i.jsx)("span",{className:re[n],"aria-hidden":!0}),(0,i.jsx)("span",{className:Fe,title:t.label,children:t.label}),(0,i.jsxs)("span",{className:Ue,children:[s,"/",r," ran · ",K(t.durationMs)]})]},t.id)})]}),rt=e=>!e||e.hits===0&&e.misses===0?"untouched":e.misses>0?"ran":"cached",st=(e,t)=>{let s=0;for(const r of h.COMPILER_STAGE_KEYS)t(e[r])&&(s+=1);return s},K=e=>e<.1?"<0.1ms":e>=10?`${e.toFixed(0)}ms`:`${e.toFixed(2)}ms`,nt=()=>{const{history:e}=a.useGraphContext(),{stack:t,undo:s,redo:r}=e,n=(0,d.useCallback)(u=>t.subscribe(u),[t]),l=(0,d.useCallback)(()=>t.getSnapshot(),[t]),c=(0,d.useSyncExternalStore)(n,l,l);return(0,d.useMemo)(()=>({...c,undo:s,redo:r}),[c,s,r])},at=new Set(["button","checkbox","color","file","hidden","image","radio","range","reset","submit"]),ot=(e,t={})=>{const{target:s,enabled:r=!0}=t;(0,d.useEffect)(()=>{const n=it(s);if(!r||!n)return;const l=c=>{if(!ct(c)||c.defaultPrevented||lt(c.target))return;const u=a.resolveHistoryStep(c);if(!u)return;const m=e.current;m&&(u==="undo"?m.undo():m.redo())&&c.preventDefault()};return n.addEventListener("keydown",l),()=>n.removeEventListener("keydown",l)},[e,s,r])},it=e=>e===void 0?window:e!==null&&"current"in e?e.current:e,ct=e=>"key"in e,lt=e=>e instanceof HTMLInputElement?!at.has(e.type):e instanceof HTMLElement?e.isContentEditable||e.tagName==="TEXTAREA":!1;exports.BrandMark=a.BrandMark;exports.CanvasTextMeasurer=a.CanvasTextMeasurer;exports.DefaultFooter=a.DefaultFooter;exports.DefaultGrid=a.DefaultGrid;exports.DefaultHeader=a.DefaultHeader;exports.DefaultSwatch=a.DefaultSwatch;exports.DefaultTooltip=a.DefaultTooltip;exports.DevToolsPanel=Ze;exports.GRAPH_MODES=a.GRAPH_MODES;exports.GeomCircle=Pe;exports.GeomLine=we;exports.GraphErrorBoundary=Q;exports.GraphErrorPanel=B;exports.GraphProvider=te;exports.GraphRenderer=a.GraphRenderer;exports.HoverProvider=a.HoverProvider;exports.IntroFade=a.IntroFade;exports.IntroWipeClip=a.IntroWipeClip;exports.TextMeasurerProvider=a.TextMeasurerProvider;exports.ThemeProvider=a.ThemeProvider;exports.UnitBoxSvg=Me;exports.UnitSpaceSvg=Le;exports.buildDotsEditOutlineShapes=a.buildDotsEditOutlineShapes;exports.createGraphyKit=Ie;exports.darkTheme=a.darkTheme;exports.defineGeomRenderer=a.defineGeomRenderer;exports.lightTheme=a.lightTheme;exports.lightenCss=a.lightenCss;exports.projectPointCartesian=a.projectPointCartesian;exports.pruneSelection=ee;exports.resolveBrandMarkVisual=a.resolveBrandMarkVisual;exports.scalePointToPanel=a.scalePointToPanel;exports.stampAxisEditTarget=a.stampAxisEditTarget;exports.stampGridEditTarget=a.stampGridEditTarget;exports.stampLegendEditTarget=a.stampLegendEditTarget;exports.useElementScreenRect=a.useElementScreenRect;exports.useGeomHitTest=a.useGeomHitTest;exports.useGeomHover=a.useGeomHover;exports.useGeomReaderTree=a.useGeomReaderTree;exports.useGraphCommands=a.useGraphCommands;exports.useGraphHandle=a.useGraphHandle;exports.useGraphHistory=nt;exports.useGraphHistoryShortcuts=ot;exports.useGraphSelection=a.useGraphSelection;exports.useGuidesTakePress=a.useGuidesTakePress;exports.useHandleScene=a.useHandleScene;exports.useHoverState=a.useHoverState;exports.useResolvedStyle=a.useResolvedStyle;exports.useSceneSelector=a.useSceneSelector;exports.useStyleReaderTree=a.useStyleReaderTree;exports.useStyleReaders=a.useStyleReaders;exports.useStyleResolver=a.useStyleResolver;exports.useTargetBoundary=a.useTargetBoundary;exports.useTextMeasurer=a.useTextMeasurer;exports.vars=ae.vars;
package/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ import { Edge } from '@graphysdk/viz-engine';
16
16
  import { EdgeSizes } from '@graphysdk/viz-engine';
17
17
  import { EditTarget } from '@graphysdk/viz-engine';
18
18
  import { ErrorInfo } from 'react';
19
+ import { FadeIntroPlan } from '@graphysdk/viz-engine';
19
20
  import { FontSpec } from '@graphysdk/viz-engine';
20
21
  import { FormattedAxis } from '@graphysdk/viz-engine';
21
22
  import { FormattedHeadline } from '@graphysdk/viz-engine';
@@ -24,6 +25,7 @@ import { Geom } from '@graphysdk/viz-engine';
24
25
  import { GeomName } from '@graphysdk/viz-engine';
25
26
  import { GeomStyleReaders } from '@graphysdk/viz-engine';
26
27
  import { GraphLayout } from '@graphysdk/viz-engine';
28
+ import { GrowIntroPlan } from '@graphysdk/viz-engine';
27
29
  import { HeadlineMeasurer } from '@graphysdk/viz-engine';
28
30
  import { HoverHit } from '@graphysdk/viz-engine';
29
31
  import { HoverState } from '@graphysdk/viz-engine';
@@ -63,6 +65,7 @@ import { TextMeasurer } from '@graphysdk/viz-engine';
63
65
  import { TextStyle } from '@graphysdk/viz-engine';
64
66
  import { TooltipContent } from '@graphysdk/viz-engine';
65
67
  import { VizDiagnostic } from '@graphysdk/viz-engine';
68
+ import { WipeIntroPlan } from '@graphysdk/viz-engine';
66
69
  import { XYPoint } from '@graphysdk/viz-engine';
67
70
 
68
71
  /** The axis identity and optional tick address spread onto a label's containing group. */
@@ -95,6 +98,14 @@ export declare interface AxisTicksSlotProps {
95
98
  tickRects: Partial<Record<Edge, Rect>>;
96
99
  }
97
100
 
101
+ /**
102
+ * A {@link GeomRendererDefinition} holding exactly `Definition`. Intersecting with the base instead would
103
+ * merge each declared field with its base type, so a typed `styleTarget` would lose its part names.
104
+ */
105
+ export declare type BoundGeomRendererDefinition<Definition extends Geom<unknown>> = Omit<GeomRendererDefinition, 'definition'> & {
106
+ readonly definition: Definition;
107
+ };
108
+
98
109
  /** Made with Graphy provenance badge — capsule + glyph + system-face copy. */
99
110
  export declare const BrandMark: ({ visual, placement }: BrandMarkProps) => JSX.Element;
100
111
 
@@ -111,6 +122,15 @@ declare interface BrandMarkProps {
111
122
  */
112
123
  export declare type BrandMarkVisual = 'full' | 'mini' | 'hidden';
113
124
 
125
+ /**
126
+ * The dots outline for centres already in panel pixels, one shape per size they cover. A geom pairs each
127
+ * centre with the diameter it paints — its size plus its border, half of which lies outside the rim.
128
+ */
129
+ export declare const buildDotsEditOutlineShapes: (dots: ReadonlyArray<{
130
+ center: XYPoint;
131
+ size: number;
132
+ }>) => EditOutlineDots[];
133
+
114
134
  /**
115
135
  * Browser text measurer backed by OffscreenCanvas.
116
136
  *
@@ -172,7 +192,7 @@ declare type CoordSystemFor<C extends CoordKind> = C extends 'cartesian' ? Carte
172
192
 
173
193
  /**
174
194
  * Ergonomic entry point for a React app: pass `plugins` once and get back a {@link GraphyKit} — the
175
- * typed builder plus a `GraphProvider` that already carries them. Pure sugar over the primitives
195
+ * full typed builder plus a `GraphProvider` that already carries them. Pure sugar over the primitives
176
196
  * (`createSpecBuilder`, `<GraphProvider plugins>`); use those directly for headless or advanced
177
197
  * wiring. The `const` type parameter captures the `plugins` tuple literally, so `kit.geom.<customName>`
178
198
  * is typed.
@@ -240,9 +260,7 @@ export declare const DefaultTooltip: ({ content }: TooltipSlotProps) => JSX.Elem
240
260
  * The name is constrained to {@link GeomName}, so a by-name override of an unknown built-in is a
241
261
  * compile-time error. To restyle a *custom* geom, rebind its definition (which you hold) via the first form.
242
262
  */
243
- export declare function defineGeomRenderer<Definition extends Geom<unknown>>(definition: Definition, contract: GeomRenderContract): GeomRendererDefinition & {
244
- readonly definition: Definition;
245
- };
263
+ export declare function defineGeomRenderer<Definition extends Geom<unknown>>(definition: Definition, contract: GeomRenderContract): BoundGeomRendererDefinition<Definition>;
246
264
 
247
265
  export declare function defineGeomRenderer<G extends GeomName>(geom: G, contract: GeomRenderContract): ResolvedGeomRenderer;
248
266
 
@@ -328,6 +346,8 @@ export declare interface EditOutlineStroke extends MorphingEditOutlineShape {
328
346
  width: number;
329
347
  }
330
348
 
349
+ export { FadeIntroPlan }
350
+
331
351
  /**
332
352
  * Props for the Footer slot, overridable via `slots.Footer` on `GraphRenderer`. Caption editing in
333
353
  * `editable` mode is internal to this default — it hands off to the editor `/editable` supplies —
@@ -351,6 +371,34 @@ export declare interface FooterSlotProps {
351
371
  brandMark: BrandMarkVisual;
352
372
  }
353
373
 
374
+ /**
375
+ * A circle that follows a data change the way a built-in geom's marks do: its centre and radius
376
+ * spring to their new values, or snap when the graph has transitions off. The element keeps its
377
+ * identity across renders, so give it a key that survives the change you want tweened.
378
+ *
379
+ * Geometry reaches the element only through `animate`, so the mark mounts with `initial={false}` —
380
+ * at its position rather than travelling to it from an unset attribute at the panel's origin. An
381
+ * entrance is the layer's to play, through {@link IntroFade} or {@link IntroWipeClip}.
382
+ */
383
+ export declare const GeomCircle: ({ shouldAnimateTransitions, cx, cy, r, ...paint }: GeomCircleProps) => JSX.Element;
384
+
385
+ declare interface GeomCircleProps {
386
+ cx: MarkPosition;
387
+ cy: MarkPosition;
388
+ /** Radius in pixels. */
389
+ r: number;
390
+ fill?: string;
391
+ opacity?: number;
392
+ fillOpacity?: number;
393
+ stroke?: string;
394
+ strokeOpacity?: number;
395
+ strokeWidth?: number;
396
+ /** Whether a change of centre or radius springs to the new one. Snaps when false. */
397
+ shouldAnimateTransitions: boolean;
398
+ /** A geom's own test hook, since the primitive owns the painted element. */
399
+ 'data-testid'?: string;
400
+ }
401
+
354
402
  /** A custom geom `getEditOutlineShapes` handler's input: the observations to outline as a layer, plus `sourceLayer`. */
355
403
  export declare type GeomEditOutlineShapesRendererInput = EditOutlineShapesInput;
356
404
 
@@ -377,6 +425,24 @@ export declare interface GeomHoverPush {
377
425
  /** A custom geom `renderHover` handler's input: the hovered layer plus the primary/group/related hover hits. */
378
426
  export declare type GeomHoverRendererInput = HoverRenderInput;
379
427
 
428
+ /** A straight line whose endpoints spring to their new positions — {@link GeomCircle} for a segment. */
429
+ export declare const GeomLine: ({ shouldAnimateTransitions, x1, y1, x2, y2, ...paint }: GeomLineProps) => JSX.Element;
430
+
431
+ declare interface GeomLineProps {
432
+ x1: MarkPosition;
433
+ y1: MarkPosition;
434
+ x2: MarkPosition;
435
+ y2: MarkPosition;
436
+ stroke?: string;
437
+ strokeOpacity?: number;
438
+ strokeWidth?: number;
439
+ strokeDasharray?: string;
440
+ strokeLinecap?: 'butt' | 'round' | 'square';
441
+ /** Whether a change of either endpoint springs to the new one. Snaps when false. */
442
+ shouldAnimateTransitions: boolean;
443
+ 'data-testid'?: string;
444
+ }
445
+
380
446
  /** A custom geom `getOverlayAnchor` handler's input: the layer, coord system, and the matched observation. */
381
447
  export declare type GeomOverlayAnchorRendererInput = OverlayAnchorInput;
382
448
 
@@ -647,6 +713,10 @@ export declare interface GraphHandle {
647
713
  setSelection: (next: readonly EditTarget[]) => void;
648
714
  /** Registers a listener fired on every change to the selection; returns the unsubscribe. */
649
715
  subscribeSelection: (onSelectionChange: () => void) => () => void;
716
+ /** Whether this geom places data labels under these coords, per the plugins the graph was built with. */
717
+ canPlaceDataLabels: (geom: string, coordType: CoordSystem['type']) => boolean;
718
+ /** Whether this layer's data labels can read as percentages, per the plugins the graph was built with. */
719
+ canFormatDataLabelsAsPercentages: (layer: SceneLayer, coordType: CoordSystem['type']) => boolean;
650
720
  }
651
721
 
652
722
  /** Undo/redo controls plus the command stack's own snapshot, which a history UI reads. */
@@ -786,10 +856,11 @@ export declare interface GraphSlots {
786
856
  }
787
857
 
788
858
  /**
789
- * A plugin-bound authoring kit: the typed `geom`/`stat`/`transform`/`scale`/`coord` factories plus
790
- * `createSpec`/`pipe`, and a `GraphProvider` pre-bound to the same `plugins` — so what can be written
791
- * and what can render derive from one array and cannot diverge. Generic over the `plugins` tuple so
792
- * the typed per-plugin builder methods (`geom.<name>`, …) flow through to the React entry point.
859
+ * A plugin-bound authoring kit: the whole typed {@link SpecBuilder} surface — every spec-item factory
860
+ * plus `createSpec`/`pipe` — and a `GraphProvider` pre-bound to the same `plugins`, so what can be
861
+ * written and what can render derive from one array and cannot diverge. Generic over the `plugins`
862
+ * tuple so the typed per-plugin builder methods (`geom.<name>`, …) flow through to the React entry
863
+ * point.
793
864
  */
794
865
  export declare interface GraphyKit<P extends readonly Plugin_2[] = readonly Plugin_2[]> extends SpecBuilder<P> {
795
866
  GraphProvider: (props: Omit<GraphProviderProps, 'plugins'>) => ReactElement;
@@ -818,6 +889,8 @@ export declare interface GridSlotProps {
818
889
  panelRect: GraphLayout['panel'];
819
890
  }
820
891
 
892
+ export { GrowIntroPlan }
893
+
821
894
  /**
822
895
  * Props for the Header slot, overridable via `slots.Header` on `GraphRenderer`. Title editing in
823
896
  * `editable` mode is internal to this default — it hands off to the editor `/editable` supplies —
@@ -969,6 +1042,37 @@ declare interface IntroAnimationOptions {
969
1042
  staggerOrder: IntroStaggerOrder;
970
1043
  }
971
1044
 
1045
+ /**
1046
+ * A whole layer fading up from transparent on one clock — the entrance for marks with no extent to
1047
+ * grow and no continuous path to reveal (a tile grid, a dumbbell).
1048
+ *
1049
+ * The opacity rides the group rather than each mark, so marks that overlap don't show through one
1050
+ * another mid-fade.
1051
+ */
1052
+ export declare const IntroFade: ({ intro, children }: IntroFadeProps) => JSX.Element;
1053
+
1054
+ declare interface IntroFadeProps {
1055
+ intro: FadeIntroPlan;
1056
+ children: ReactNode;
1057
+ }
1058
+
1059
+ /**
1060
+ * One clip-rect reveal for a whole layer, travelling along the plan's axis — the line/area entrance.
1061
+ *
1062
+ * Sized in percentages of the enclosing viewport, so the same reveal tracks resize whether the geom
1063
+ * paints in a unit-space nested SVG (`viewBox="0 0 1 1"`, where `100%` is one user unit) or straight
1064
+ * into the panel in percentages. The rect overscans the viewport so `non-scaling-stroke` pixels at
1065
+ * the panel edges aren't shaved.
1066
+ */
1067
+ export declare const IntroWipeClip: ({ intro, children }: IntroWipeClipProps) => JSX.Element;
1068
+
1069
+ declare interface IntroWipeClipProps {
1070
+ intro: WipeIntroPlan;
1071
+ children: ReactNode;
1072
+ }
1073
+
1074
+ export { LayerIntroPlan }
1075
+
972
1076
  /** Which of the chart's drawn legends a pill belongs to. */
973
1077
  declare const LEGEND_INDEX_ATTRIBUTE = "data-legend-index";
974
1078
 
@@ -1015,6 +1119,12 @@ export declare const lightenCss: (colorString: string, amount: number) => string
1015
1119
  /** vanilla-extract class that binds the light token values; the default theme. */
1016
1120
  export declare const lightTheme: string;
1017
1121
 
1122
+ /**
1123
+ * A position in the space the geom paints in: a panel percentage (`'42.5%'`) or a user coordinate
1124
+ * inside a unit-space nested SVG. Both sides of a transition must be in the same units to spring.
1125
+ */
1126
+ declare type MarkPosition = string | number;
1127
+
1018
1128
  declare interface MorphingEditOutlineShape {
1019
1129
  /** SVG path data in panel pixels. */
1020
1130
  pathData: string;
@@ -1039,6 +1149,16 @@ declare interface OverlayAnchorInput<G extends GeomName | string = string, C ext
1039
1149
  observation: Observation;
1040
1150
  }
1041
1151
 
1152
+ /**
1153
+ * How a point's `(x, y)` becomes SVG coordinates — the only thing that differs between a cartesian point
1154
+ * and a polar (radar) point. Each coord's geom-renderer and hover container supply their own projection;
1155
+ * the shared point atoms (`Point`, `PrimaryPoint`, `CompanionPoint`) draw through it.
1156
+ */
1157
+ declare type PointProjection = (x: number, y: number) => XYPoint;
1158
+
1159
+ /** Cartesian: normalized data-space `[0,1]` into panel view-box coords (formatted to percent at paint). */
1160
+ export declare const projectPointCartesian: PointProjection;
1161
+
1042
1162
  /**
1043
1163
  * Drops the selected targets `spec` no longer holds, and hands back the same list when it holds all
1044
1164
  * of them — a selection that survived a command must not churn its subscribers.
@@ -1078,6 +1198,12 @@ export declare interface ResolvedGeomRenderer extends GeomRenderContract {
1078
1198
  geom: string;
1079
1199
  }
1080
1200
 
1201
+ /** A point a point projection placed as a fraction of the panel, in panel pixels from the top left. */
1202
+ export declare const scalePointToPanel: (point: XYPoint, panelSize: {
1203
+ width: number;
1204
+ height: number;
1205
+ }) => XYPoint;
1206
+
1081
1207
  /**
1082
1208
  * The compiled layer a renderer's handlers receive. A built-in renderer keyed to a `GeomName` gets
1083
1209
  * its param-narrowed `SceneLayerFor<G>`; a custom renderer (`G = string`) is downstream of
@@ -1723,4 +1849,6 @@ export declare const vars: {
1723
1849
 
1724
1850
  export { VizDiagnostic }
1725
1851
 
1852
+ export { WipeIntroPlan }
1853
+
1726
1854
  export { }