@fusedio/widget-sdk 0.1.1 → 0.2.0

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/bundle.js CHANGED
@@ -1,2 +1,2 @@
1
- var ir="parameter-updates",ae=(o=>(o.PARAM="param",o.RANGE="range",o.VIEWPORT="viewport",o.CLEAR="clear",o))(ae||{});function ur(e){if(typeof e!="object"||e===null)return!1;let n=e;return typeof n.type=="string"&&Object.values(ae).includes(n.type)&&typeof n.parameter=="string"&&"values"in n}import{createContext as ye,useContext as Re}from"react";var be=ye(null);be.displayName="FusedWidgetBridgeContext";function y(){let e=Re(be);if(!e)throw new Error("useFusedWidgetBridge: no FusedWidgetBridgeContext provider in the tree. Wrap your components with the workbench's <JsonUiProvider> or the test harness's <FusedWidgetBridgeContext.Provider value={createTestBridge()}>.");return e}var he=ye(null);he.displayName="JsonUiNodeOverrideContext";function V(){let e=y(),n=Re(he);return n?{udfUniqueId:n.udfUniqueId??e.node.udfUniqueId,udfName:n.udfName??e.node.udfName,configHash:n.configHash??e.node.configHash}:{udfUniqueId:e.node.udfUniqueId,udfName:e.node.udfName,configHash:e.node.configHash}}import{createContext as nn,useCallback as ve,useContext as rn,useRef as we,useSyncExternalStore as tn}from"react";function dr(){let e=new Map,n=new Set,r=t=>{n.forEach(o=>{o.names.has(t)&&o.cb()})};return{get(t){return e.get(t)},getSnapshot(t){let o={};for(let i of t)e.has(i)&&(o[i]=e.get(i));return o},getAll(){let t={};return e.forEach((o,i)=>{t[i]=o}),t},setField(t,o){e.has(t)&&Object.is(e.get(t),o)||(e.set(t,o),r(t))},removeField(t){e.has(t)&&(e.delete(t),r(t))},subscribe(t,o){let i={names:new Set(t),cb:o};return n.add(i),()=>{n.delete(i)}}}}var Ue=nn({store:null,isInForm:!1});Ue.displayName="JsonUiFormContext";function on(){return rn(Ue)}var xe=Object.freeze({});function j(e){let{store:n,isInForm:r}=on(),t=un(e),o=ve(f=>n?n.subscribe(t,f):()=>{},[n,t]),i=we(xe),l=ve(()=>{if(!n)return xe;let f=n.getSnapshot(t),a=i.current;return sn(a,f)?a:(i.current=f,f)},[n,t]),s=tn(o,l,l);return{inForm:r,values:s}}function sn(e,n){if(e===n)return!0;let r=Object.keys(e),t=Object.keys(n);if(r.length!==t.length)return!1;for(let o of r)if(!Object.is(e[o],n[o]))return!1;return!0}function un(e){let n=we(e),r=n.current;return r!==e&&(r.length!==e.length||r.some((t,o)=>t!==e[o]))&&(n.current=e),n.current}function an(e){return e}function ln(e){return e}import{useCallback as X,useEffect as J,useMemo as Y,useRef as I,useState as cn}from"react";function fn({param:e,debounceMs:n=300,readOnly:r=!1,defaultValue:t,broadcastDefaultValue:o=!0,validate:i,preprocess:l}){let s=y(),{configHash:f}=V(),a=!!e,R=(u,c)=>{if(!e)return;if(u==="Cleared"){s.log.log(`Cleared param "${e}"`,"info",f);return}let d=JSON.stringify(c),N=d&&d.length>100?d.slice(0,100)+"\u2026":d;s.log.log(`${u} param "${e}" = ${N}`,"info",f)},p=Y(()=>l??gn(t),[l]),C=Y(()=>i??dn(t),[i]),g=Y(()=>e?[e]:[],[e]),{inForm:b,values:h}=j(g),P=e?h[e]:void 0,T=Y(()=>{if(!(!a||!e))return s.params.getSnapshot(e)},[s,a,e]),v=()=>{let u=b&&P!==void 0?P:T;if(u==null)return t;let c=p(u);return C(c)?c:t},[D,w]=cn(v),x=I(D);x.current=D;let m=I(null),A=I(!1),L=I(!1),F=I({enabled:a,param:e});F.current={enabled:a,param:e};let E=I(s);E.current=s;let Q=I(e);J(()=>{let u=Q.current;Q.current=e,u&&u!==e&&s.params.clear(u)},[s,e]),J(()=>{if(!a||!e||A.current)return;let u=b&&P!==void 0?P:s.params.getSnapshot(e);if(u==null)return;let c=p(u);c!==x.current&&C(c)&&(w(c),R("Received",u))},[s,e,a,b,P,p,C]),J(()=>!a||!e?void 0:s.params.subscribe(e,()=>{if(A.current)return;let c=s.params.getSnapshot(e);if(c==null)return;let d=p(c);d!==x.current&&C(d)&&(w(d),R("Received",c))}),[s,e,a,p,C]);let M=X(u=>{!a||!e||(s.params.set(e,u,"param"),s.edges.stopLoading(),R("Broadcast",u))},[s,a,e]),q=X(()=>{!a||r||(m.current&&(clearTimeout(m.current),m.current=null),s.edges.startLoading(),M(x.current),A.current=!1)},[s,M,a,r]),U=X(u=>{m.current&&(clearTimeout(m.current),m.current=null),w(u),x.current=u,A.current=!1,!(!a||!e||r)&&(s.params.clear(e),s.edges.stopLoading(),R("Cleared",null))},[s,a,e,r]);J(()=>{L.current=!1},[e,a]),J(()=>{if(!a||!e||r||!o||L.current)return;let u=s.params.getSnapshot(e);if(u!=null){L.current=!0;return}if(x.current===""){L.current=!0;return}M(x.current),L.current=!0},[s,a,e,r,o,M]);let _=X(u=>{w(u),!(!a||r)&&(A.current=!0,s.edges.startLoading(),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>{M(u),A.current=!1},n))},[s,M,n,a,r]);return J(()=>()=>{m.current&&clearTimeout(m.current);let{enabled:u,param:c}=F.current;!u||!c||E.current.params.clear(c)},[]),{value:D,setValue:_,broadcastNow:q,clearValue:U}}function dn(e){return typeof e=="string"?(n=>typeof n=="string"):typeof e=="number"?(n=>typeof n=="number"):typeof e=="boolean"?(n=>typeof n=="boolean"):Array.isArray(e)?(n=>Array.isArray(n)):e!==null&&typeof e=="object"?(n=>n!==null&&typeof n=="object"&&!Array.isArray(n)):(n=>!0)}function gn(e){return typeof e=="string"?n=>typeof n=="string"?n:Array.isArray(n)?n.join(","):n!==null&&typeof n=="object"?JSON.stringify(n):String(n):n=>n}import{useCallback as ke,useRef as Pe,useSyncExternalStore as pn}from"react";var Ce=Object.freeze({});function Z(e){let n=y(),r=Sn(e),t=ke(l=>r.length===0?()=>{}:n.params.subscribeMany(r,l),[n,r]),o=Pe(Ce),i=ke(()=>{if(r.length===0)return Ce;let l=n.params.getSnapshotMany(r),s=o.current;return mn(s,l)?s:(o.current=l,l)},[n,r]);return pn(t,i,i)}function mn(e,n){if(e===n)return!0;let r=Object.keys(e),t=Object.keys(n);if(r.length!==t.length)return!1;for(let o of r)if(!Object.is(e[o],n[o]))return!1;return!0}function Sn(e){let n=Pe(e),r=n.current;return r!==e&&(r.length!==e.length||r.some((t,o)=>t!==e[o]))&&(n.current=e),n.current}import{useCallback as le,useRef as yn,useSyncExternalStore as Rn}from"react";function bn(){let e=y(),n=le(l=>e.routing.subscribeAllowedSources(l),[e]),r=yn(null),t=le(()=>{let l=e.routing.getAllowedSources(),s=r.current;return hn(s,l)?s:(r.current=l,l)},[e]),o=Rn(n,t,t),i=le((l,s)=>!o||o.length===0||!l&&!s?!0:o.some(f=>f.udfUniqueId&&f.udfUniqueId===l||f.udfName&&f.udfName===s),[o]);return{allowedSources:o,isAllowedSource:i}}function hn(e,n){return e===n?!0:e===null||n===null||e.length!==n.length?!1:e.every((r,t)=>r.udfUniqueId===n[t].udfUniqueId&&r.udfName===n[t].udfName)}import{useCallback as Ee,useRef as vn,useSyncExternalStore as xn}from"react";function wn(){let e=y(),n=Ee(o=>e.routing.subscribeAllowedSources(o),[e]),r=vn(null),t=Ee(()=>{let o=e.routing.getAllowedUdfNames(),i=r.current;return Un(i,o)?i:(r.current=o,o)},[e]);return xn(n,t,t)}function Un(e,n){if(e===n)return!0;if(e===null||n===null||e.size!==n.size)return!1;for(let r of e)if(!n.has(r))return!1;return!0}import{useEffect as kn,useMemo as $,useRef as Cn,useState as Ae,useSyncExternalStore as Pn,useCallback as Le}from"react";var Fe=/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,En=/\{\{[\s\S]*?\}\}/,Te=/\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\b/g;function ce(e,n={}){let r=e??"",t=n.preserveMissingParams??!1,o=y(),i=$(()=>An(r),[r]),l=Z(i),{inForm:s,values:f}=j(i),a=$(()=>s?{...l,...f}:l,[l,f,s]),R=$(()=>En.test(r),[r]),p=$(()=>R?"":Ln(r,a,t),[r,a,t,R]),C=$(()=>{if(!R)return[];let w=new Set,x=[];Te.lastIndex=0;let m;for(;(m=Te.exec(r))!==null;)w.has(m[1])||(w.add(m[1]),x.push(m[1]));return x},[r,R]),g=Fn(o,C),[b,h]=Ae(()=>({key:"",value:""})),[P,T]=Ae(!1),v=$(()=>JSON.stringify({template:r,paramValues:a,preserveMissingParams:t,tick:g}),[r,a,t,g]);return kn(()=>{if(!R){T(!1);return}let w=!1,x=new AbortController;return T(!0),o.template.render(r,a,{preserveMissingParams:t,signal:x.signal}).then(m=>{w||(h(A=>A.key===v&&A.value===m.value?A:{key:v,value:m.value}),T(m.loading))},m=>{w||m?.name!=="AbortError"&&T(!1)}),()=>{w=!0,x.abort()}},[o,R,r,a,t,v]),{value:$(()=>{if(!R)return p;if(b.key===v)return b.value;try{return o.template.renderLoading(r,a,{preserveMissingParams:t})}catch{return r}},[o,R,p,b,v,r,a,t]),loading:R?P:!1}}function An(e){let n=[],r=new Set;for(let t of e.matchAll(Fe)){let o=t[1];r.has(o)||(r.add(o),n.push(o))}return n}function Ln(e,n,r){return e.replace(Fe,(t,o)=>{let i=n[o];return i==null?r?t:"":Tn(i)})}function Tn(e){return e==null?"":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):JSON.stringify(e)??""}function Fn(e,n){let r=Cn(0),t=n.slice().sort().join("|"),o=Le(l=>{let s=()=>{r.current+=1,l()},f=[e.template.subscribe(s)];for(let a of n)f.push(e.udfs.subscribeOutput(a,s));return()=>f.forEach(a=>a())},[e,t]),i=Le(()=>r.current,[]);return Pn(o,i,i)}import{useCallback as ee,useEffect as Dn,useMemo as ne,useRef as On,useState as De,useSyncExternalStore as Nn}from"react";function Oe(e){let n=y(),r=ee(i=>e?n.udfs.subscribeOutput(e,i):()=>{},[n,e]),t=On(void 0),o=ee(()=>{if(!e)return;let i=n.udfs.getOutputSnapshot(e),l=t.current;return Mn(l,i)?l:(t.current=i,i)},[n,e]);return Nn(r,o,o)}function Ne(){let e=y();return ee(n=>e.udfs.requestReexecute(n),[e])}function Mn(e,n){return e===n?!0:!e||!n?!1:e.data===n.data&&e.isExecutionInProgress===n.isExecutionInProgress&&e.error===n.error&&e.vfsFilename===n.vfsFilename}var Me=/^\{\{(\w+)\.(\w+)(?:\[(\d+)\])?\}\}$/;function re(e){return!e||typeof e!="string"?!1:Me.test(e)}function fe(e){if(!re(e))return null;let n=e.match(Me);if(!n)return null;let[,r,t,o]=n,i=o!==void 0?parseInt(o,10):void 0;return{udfName:r,columnName:t,index:i}}function Bn(e){return!!e&&typeof e=="object"&&typeof e.getRows=="function"}function de({udfName:e,sampleSize:n=200}){let r=Oe(e),t=Ne(),[o,i]=De([]),[l,s]=De([]);Dn(()=>{let a=!1,R=r?.data;if(!R||!Bn(R)){i([]),s([]);return}return(async()=>{try{let p=await R.getRows(0,Math.max(0,n));if(a)return;let C=p.map(b=>{let h=b;return h&&typeof h=="object"&&h.properties&&typeof h.properties=="object"?h.properties:b});i(C);let g=Array.from(new Set(C.flatMap(b=>Object.keys(b??{}))));s(g)}catch{if(a)return;i([]),s([])}})(),()=>{a=!0}},[r?.data,n]);let f=ee(()=>{e&&t(e)},[t,e]);return{loading:r?.isExecutionInProgress??!1,errorMessage:r?.error??null,isError:!!r?.error,columns:l,rows:o,requestReexecute:f}}function qn(e,n=200){let r=re(e),t=ne(()=>r?fe(e):null,[r,e]),{rows:o,loading:i}=de({udfName:t?.udfName,sampleSize:n});return{values:ne(()=>!t||!t.columnName?[]:o.map(s=>s?.[t.columnName]).filter(s=>s!=null),[o,t]),loading:r?i:!1}}function _n(e,n=200){let r=re(e),t=ne(()=>r?fe(e):null,[r,e]),{rows:o,loading:i}=de({udfName:t?.udfName,sampleSize:n});return{value:ne(()=>{if(!t||!t.columnName||t.index===void 0)return null;let s=o[t.index];if(!s)return null;let f=s[t.columnName];return f!==void 0?f:null},[o,t]),loading:r?i:!1}}import{useCallback as Ke,useEffect as z,useMemo as O,useRef as Hn,useState as B}from"react";import{useCallback as te,useMemo as Qn,useRef as ge,useSyncExternalStore as In}from"react";var Be=Object.freeze([]);function oe(){let e=y(),{configHash:n}=V(),r=ge(e);r.current=e;let t=ge(n);t.current=n;let o=te((i,l="info")=>{r.current.log.log(i,l,t.current)},[]);return Qn(()=>({log:o}),[o])}function $n(e){let n=y(),r=te(i=>e?n.log.subscribeLogs(e,i):()=>{},[n,e]),t=ge(Be),o=te(()=>{if(!e)return Be;let i=n.log.getLogsSnapshot(e);return i===t.current?t.current:(t.current=i,i)},[n,e]);return In(r,o,o)}function Vn(e){let n=y();return te(()=>{e&&n.log.clearLogs(e)},[n,e])}function se(){let e=y();return{startLoading:e.edges.startLoading,stopLoading:e.edges.stopLoading}}var pe=/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,qe=/\{\{(\w+)(?:\?([^}]*))?\}\}/g,me=/'((?:s3|gs|fd):\/\/[^'\n]+)'/g;function jn(e){return e==null?"''":typeof e=="number"&&!Number.isNaN(e)?String(e):typeof e=="boolean"?e?"TRUE":"FALSE":`'${String(e).replace(/'/g,"''")}'`}function Jn(e,n){let r=!1;for(let t=0;t<n;t++)if(e[t]==="'"){if(r&&e[t+1]==="'"){t++;continue}r=!r}return r}function _e(e,n){return e.replace(pe,(r,t,o)=>{let i=n[t],l=i==null?"":String(i);return Jn(e,o)?l.replace(/'/g,"''"):jn(i)})}function Qe(e){let n=new Set,r=[];pe.lastIndex=0;for(let t of e.matchAll(pe)){let o=t[1];n.has(o)||(n.add(o),r.push(o))}return r}function Wn(e){if(!e)return null;let n={},r=!1;for(let t of e.split(/[&,]/)){if(!t)continue;let o=t.indexOf("=");if(o===-1)continue;let i=t.slice(0,o),l=t.slice(o+1),s,f;try{s=decodeURIComponent(i),f=decodeURIComponent(l)}catch{s=i,f=l}s&&(n[s]=f,r=!0)}return r?n:null}function Ie(e){let n=[],r;for(qe.lastIndex=0;(r=qe.exec(e))!==null;){let[t,o,i]=r;n.push({match:t,name:o,overrides:Wn(i),start:r.index,end:r.index+t.length})}return n}function $e(e){if(!e)return[];let n=new Set,r=[];me.lastIndex=0;let t;for(;(t=me.exec(e))!==null;){let o=t[1];n.has(o)||(n.add(o),r.push(o))}return r}function Ve(e,n){return e&&e.replace(me,(r,t)=>{let o=n[t];return o?`'${o}'`:r})}var je=/^\$([a-zA-Z_][a-zA-Z0-9_]*)$/;function Je(e){let n=e.trim(),r=je.exec(n);return r?r[1]:null}function We(e,n){let r=je.exec(e);if(!r)return{value:e,unresolved:!1};let t=r[1];if(!(t in n))return{value:e,unresolved:!0};let o=n[t];return o==null?{value:"",unresolved:!1}:{value:String(o),unresolved:!1}}function zn(e){return Object.keys(e).sort().map(n=>`${n}=${e[n]}`).join("&")}function ze(e,n){return n?`${e}#${zn(n)}`:e}var Ze=500,W=Object.freeze([]),G=Object.freeze([]);function He(e,n){if(/\bLIMIT\b/i.test(e))return e;let r=e.trimEnd();return`${r.endsWith(";")?r.slice(0,-1):r} LIMIT ${n}`}function Kn(e){return`"${e.replace(/"/g,'""')}"`}function Zn(e,n,r,t,o,i){let l=e.match(/^\$([a-zA-Z_][a-zA-Z0-9_]*)$/);if(l){let f=o[l[1]];return f==null?"":He(String(f),i)}let s=e;for(let f=n.length-1;f>=0;f--){let{raw:a,key:R,resolvedOverrides:p}=n[f],g=p===null&&t?t[a.name]:void 0,b;g?b=Kn(g.relationName):b=`'${r.get(R)??`${a.name}.parquet`}'`,s=s.slice(0,a.start)+b+s.slice(a.end)}return s=He(s,i),_e(s,o)}function Ge({sql:e,enabled:n=!0,maxRows:r=Ze,sourceOverrides:t}){let o=y(),{startLoading:i,stopLoading:l}=se(),{log:s}=oe(),[f,a]=B(""),[R,p]=B(!1),[C,g]=B(null),[b,h]=B(0),P=O(()=>e?Ie(e):[],[e]),T=O(()=>t?P.filter(u=>u.overrides!==null||!t[u.name]):P,[P,t]),v=O(()=>{let u=new Set;for(let c of T)if(c.overrides)for(let d of Object.values(c.overrides)){let N=Je(d);N&&u.add(N)}return Array.from(u)},[T]),D=O(()=>e?Qe(e):[],[e]),w=O(()=>{let u=new Set,c=[];for(let d of D)u.has(d)||(u.add(d),c.push(d));for(let d of v)u.has(d)||(u.add(d),c.push(d));return c},[D,v]),x=Z(w),{inForm:m,values:A}=j(w),L=O(()=>m?{...x,...A}:x,[m,x,A]),F=O(()=>T.map(u=>{if(!u.overrides)return{raw:u,key:u.name,resolvedOverrides:null,unresolved:!1};let c={},d=!1;for(let[N,H]of Object.entries(u.overrides)){let S=We(H,L);S.unresolved&&(d=!0),c[N]=S.value}return{raw:u,key:ze(u.name,c),resolvedOverrides:c,unresolved:d}}),[T,L]),E=O(()=>{let u=new Set,c=[];for(let d of F)d.unresolved||u.has(d.key)||(u.add(d.key),c.push({name:d.raw.name,key:d.key,overrides:d.resolvedOverrides??void 0}));return c},[F]),Q=O(()=>E.map(u=>`${u.key}|${u.name}|${u.overrides?Object.entries(u.overrides).sort(([c],[d])=>c.localeCompare(d)).map(([c,d])=>`${c}=${d}`).join(","):""}`).join(`
2
- `),[E]),M=Ke(()=>{h(u=>u+1)},[]);z(()=>{if(!n||E.length===0)return;let u=E.map(c=>o.udfs.subscribeOutput(c.name,()=>{h(d=>d+1)}));return()=>{u.forEach(c=>c())}},[o,n,E]),z(()=>{R?i():l()},[R,i,l]);let q=O(()=>{if(!t)return null;for(let u of P){if(u.overrides!==null)continue;let c=t[u.name];if(c?.error)return c.error}return null},[P,t]),U=O(()=>t?P.some(u=>u.overrides===null&&t[u.name]?.loading):!1,[P,t]),_=F.some(u=>u.unresolved);return z(()=>{if(!n||!e){a(""),p(!1),g(null);return}if(q){a(""),g(q),p(!1),s(`SQL preprocessing: ${q}`,"error");return}if(U||_){a(""),g(null),p(!0);return}let u=!1;return p(!0),g(null),(async()=>{let c=new Map,d;if(E.length>0)try{let S=await o.sql.resolveVfsFilenames(E);if(u)return;if(S instanceof Map)for(let k of F){if(k.resolvedOverrides)continue;let K=S.get(k.raw.name);K&&c.set(k.key,K)}else c=S.filenames,d=S.errors}catch(S){if(u)return;let k=S instanceof Error?S.message:typeof S=="string"?S:"VFS registration failed";a(""),g(k),p(!1),s(`SQL preprocessing: ${k}`,"error");return}if(d)for(let S of F){let k=d.get(S.key);if(k){if(u)return;a(""),g(k),p(!1),s(`SQL preprocessing: ${k}`,"error");return}}for(let S of F)if(!(S.unresolved||S.resolvedOverrides===null&&t?.[S.raw.name]!==void 0)&&!c.has(S.key)){if(u)return;a(""),g(null),p(!0);return}let N;try{N=Zn(e,F,c,t,L,r)}catch(S){if(u)return;let k=S instanceof Error?S.message:typeof S=="string"?S:"SQL preprocessing failed";a(""),g(k),p(!1),s(`SQL preprocessing failed: ${k}`,"error");return}let H=$e(N);if(H.length===0){if(u)return;a(N),g(null),p(!1),s("SQL preprocessing completed");return}try{let S={},k=await Promise.all(H.map(ue=>o.signUrl(ue)));if(u)return;H.forEach((ue,en)=>{S[ue]=k[en].signed});let K=Ve(N,S);a(K),g(null),p(!1),s("SQL preprocessing completed")}catch(S){if(u)return;let k=S instanceof Error?S.message:typeof S=="string"?S:"URL signing failed";a(""),g(k),p(!1),s(`SQL preprocessing failed: ${k}`,"error")}})(),()=>{u=!0}},[o,n,e,Q,F,L,t,q,U,_,r,b,s,E]),{processedSql:f,loading:R,error:C,refetch:M}}function Gn({sql:e,enabled:n=!0,maxRows:r=Ze,sourceOverrides:t}){let o=y(),{startLoading:i,stopLoading:l}=se(),{log:s}=oe(),[f,a]=B(W),[R,p]=B(G),[C,g]=B(!1),[b,h]=B(null),[P,T]=B(0),{processedSql:v,loading:D,error:w,refetch:x}=Ge({sql:e,enabled:n,maxRows:r,sourceOverrides:t}),m=Hn(""),A=n&&!!e&&!!v&&!D&&!w&&v!==m.current,L=D||C||A;z(()=>{L?i():l()},[L,i,l]);let F=Ke(()=>{m.current="",x(),T(E=>E+1)},[x]);return z(()=>{if(!n||!e){m.current="",a(W),p(G),g(!1),h(null);return}if(w){m.current="",h(w),a(W),p(G),g(!1);return}if(D||!v){m.current="",g(!1);return}let E=!1,Q=new AbortController;m.current=v,g(!0),h(null);let M=v.length>120?v.slice(0,120)+"\u2026":v;s(`SQL query started: ${M}`);let q=performance.now();return o.sql.query(v,{signal:Q.signal}).then(U=>{if(E)return;let _=Math.round(performance.now()-q);if(U.error){a(W),p(G),h(U.error),g(!1),s(`SQL failed (${_}ms): ${U.error}`,"error");return}a(U.rows.length===0?W:U.rows),p(U.columns),h(null),g(!1),s(`SQL completed: ${U.rows.length} row${U.rows.length!==1?"s":""} in ${_}ms`)},U=>{if(E||U?.name==="AbortError")return;let _=Math.round(performance.now()-q),u=U instanceof Error?U.message:typeof U=="string"?U:"SQL query failed";h(u),a(W),p(G),g(!1),s(`SQL failed (${_}ms): ${u}`,"error")}),()=>{E=!0,Q.abort()}},[o,n,e,v,D,w,P,s]),{rows:f,columns:R,loading:L,error:b,refetch:F}}function Xn(e,n=!0){let r=y(),[t,o]=B({filenames:new Map,loading:!1}),i=O(()=>e.slice().sort().join("|"),[e]);return z(()=>{if(!n||e.length===0){o({filenames:new Map,loading:!1});return}let l=!1;return o(s=>({...s,loading:!0,error:void 0})),r.sql.resolveVfsFilenames(e).then(s=>{if(l)return;let f=s instanceof Map?s:s.filenames;o({filenames:f,loading:!1})},s=>{l||o({filenames:new Map,loading:!1,error:s instanceof Error?s.message:String(s)})}),()=>{l=!0}},[r,i,n]),t}import{useCallback as Xe,useEffect as Yn,useState as ie}from"react";var Ye=["s3://","gs://","fd://"];function Se(e){return Ye.some(n=>e.startsWith(n))}function er(){let e=y();return{signUrl:Xe(r=>e.signUrl(r),[e])}}function nr(e){let n=y(),{value:r,loading:t}=ce(e),[o,i]=ie(null),[l,s]=ie(null),[f,a]=ie(!1),[R,p]=ie(0);Yn(()=>{if(t)return;if(!r){i(null),s(null),a(!1);return}if(!Se(r)){i(r),s(null),a(!1);return}let g=!1;return a(!0),s(null),n.signUrl(r).then(({signed:b})=>{g||i(b??r)}).catch(b=>{g||(s(b instanceof Error?b.message:"Failed to load media"),i(null))}).finally(()=>{g||a(!1)}),()=>{g=!0}},[n,t,r,R]);let C=Xe(async()=>{if(!r||!Se(r))return r??null;let{signed:g}=await n.signUrl(r),b=g??r;return i(b),s(null),p(h=>h+1),b},[n,r]);return{src:o,loading:t||f,error:l,refreshSignedUrl:C,resolvedSrc:r,needsSigning:!!(r&&Se(r))}}import{useEffect as rr,useState as tr}from"react";function or(e,n){let r=y(),[t,o]=tr({status:"idle"});return rr(()=>{if(!n||!e?.trim()){o({status:"idle"});return}let i=!1;return o({status:"checking"}),r.uploads.checkAccess(e).then(l=>{i||(l.ok?o({status:"allowed"}):o({status:"denied",message:l.message??"Upload access denied."}))}),()=>{i=!0}},[r,e,n]),t}function sr(){return V()}export{Ue as FormContext,be as FusedWidgetBridgeContext,he as JsonUiNodeOverrideContext,ir as PARAMETER_BROADCAST_CHANNEL,ae as ParameterMessageType,me as SIGNABLE_URL_LITERAL_REGEX,Ye as SIGNED_URL_SCHEMES,pe as SQL_PARAM_REGEX,qe as SQL_SOURCE_PLACEHOLDER_REGEX,zn as canonicalOverrideKey,ze as computePlaceholderKey,dr as createFormParamsStore,ln as defineCatalog,an as defineComponent,jn as escapeSqlValue,$e as extractSignableUrls,Qe as extractSqlParams,Je as getDollarRefName,ur as isStandardMessage,re as isUdfQuery,Wn as parseOverridesString,Ie as parseSqlUdfPlaceholders,fe as parseUdfColumnQuery,We as resolveOverrideValue,Ve as rewriteSignedUrls,_e as substituteSqlParams,bn as useAllowedSources,wn as useAllowedUdfNames,Z as useCanvasParams,Gn as useDuckDbSqlQuery,Ge as useDuckDbSqlQueryPreprocessing,on as useFormContext,j as useFormParams,fn as useFusedParam,y as useFusedWidgetBridge,se as useJsonUiEdgeAnimation,oe as useJsonUiLog,Vn as useJsonUiLogClear,$n as useJsonUiLogs,V as useJsonUiNode,sr as useJsonUiUdfInfo,nr as useMediaSrc,ce as useParamSubstitution,Ne as useRequestUdfReexecute,_n as useUdfColumnValue,qn as useUdfColumnValues,de as useUdfDataFrameSample,Oe as useUdfOutputByName,or as useUploadAccessCheck,er as useUrlSigning,Xn as useVfsRegistration};
1
+ var Sn="parameter-updates",ce=(o=>(o.PARAM="param",o.RANGE="range",o.VIEWPORT="viewport",o.CLEAR="clear",o))(ce||{});function yn(e){if(typeof e!="object"||e===null)return!1;let r=e;return typeof r.type=="string"&&Object.values(ce).includes(r.type)&&typeof r.parameter=="string"&&"values"in r}import{createContext as we,useContext as Ue}from"react";var ke=we(null);ke.displayName="FusedWidgetBridgeContext";function v(){let e=Ue(ke);if(!e)throw new Error("useFusedWidgetBridge: no FusedWidgetBridgeContext provider in the tree. Wrap your components with the workbench's <JsonUiProvider> or the test harness's <FusedWidgetBridgeContext.Provider value={createTestBridge()}>.");return e}var Ce=we(null);Ce.displayName="JsonUiNodeOverrideContext";function W(){let e=v(),r=Ue(Ce);return r?{udfUniqueId:r.udfUniqueId??e.node.udfUniqueId,udfName:r.udfName??e.node.udfName,configHash:r.configHash??e.node.configHash}:{udfUniqueId:e.node.udfUniqueId,udfName:e.node.udfName,configHash:e.node.configHash}}import{createContext as ar,useCallback as Pe,useContext as lr,useRef as Ae,useSyncExternalStore as cr}from"react";function hn(){let e=new Map,r=new Set,n=t=>{r.forEach(o=>{o.names.has(t)&&o.cb()})};return{get(t){return e.get(t)},getSnapshot(t){let o={};for(let i of t)e.has(i)&&(o[i]=e.get(i));return o},getAll(){let t={};return e.forEach((o,i)=>{t[i]=o}),t},setField(t,o){e.has(t)&&Object.is(e.get(t),o)||(e.set(t,o),n(t))},removeField(t){e.has(t)&&(e.delete(t),n(t))},subscribe(t,o){let i={names:new Set(t),cb:o};return r.add(i),()=>{r.delete(i)}}}}var Oe=ar({store:null,isInForm:!1});Oe.displayName="JsonUiFormContext";function de(){return lr(Oe)}var Ee=Object.freeze({});function J(e){let{store:r,isInForm:n}=de(),t=fr(e),o=Pe(c=>r?r.subscribe(t,c):()=>{},[r,t]),i=Ae(Ee),u=Pe(()=>{if(!r)return Ee;let c=r.getSnapshot(t),a=i.current;return dr(a,c)?a:(i.current=c,c)},[r,t]),s=cr(o,u,u);return{inForm:n,values:s}}function dr(e,r){if(e===r)return!0;let n=Object.keys(e),t=Object.keys(r);if(n.length!==t.length)return!1;for(let o of n)if(!Object.is(e[o],r[o]))return!1;return!0}function fr(e){let r=Ae(e),n=r.current;return n!==e&&(n.length!==e.length||n.some((t,o)=>t!==e[o]))&&(r.current=e),r.current}function gr(e){return e}function pr(e){return e}import{useCallback as ee,useEffect as z,useMemo as re,useRef as V,useState as mr}from"react";function fe({param:e,debounceMs:r=300,readOnly:n=!1,defaultValue:t,broadcastDefaultValue:o=!0,validate:i,preprocess:u}){let s=v(),{configHash:c}=W(),a=!!e,x=(f,C)=>{if(!e)return;if(f==="Cleared"){s.log.log(`Cleared param "${e}"`,"info",c);return}let l=JSON.stringify(C),y=l&&l.length>100?l.slice(0,100)+"\u2026":l;s.log.log(`${f} param "${e}" = ${y}`,"info",c)},m=re(()=>u??yr(t),[u]),w=re(()=>i??Sr(t),[i]),d=re(()=>e?[e]:[],[e]),{inForm:b,values:S}=J(d),q=e?S[e]:void 0,M=re(()=>{if(!(!a||!e))return s.params.getSnapshot(e)},[s,a,e]),h=()=>{let f=b&&q!==void 0?q:M;if(f==null)return t;let C=m(f);return w(C)?C:t},[L,U]=mr(h),k=V(L);k.current=L;let g=V(null),O=V(!1),N=V(!1),Q=V({enabled:a,param:e});Q.current={enabled:a,param:e};let T=V(s);T.current=s;let F=V(e);z(()=>{let f=F.current;F.current=e,f&&f!==e&&s.params.clear(f)},[s,e]),z(()=>{if(!a||!e||O.current)return;let f=b&&q!==void 0?q:s.params.getSnapshot(e);if(f==null)return;let C=m(f);C!==k.current&&w(C)&&(U(C),x("Received",f))},[s,e,a,b,q,m,w]),z(()=>!a||!e?void 0:s.params.subscribe(e,()=>{if(O.current)return;let C=s.params.getSnapshot(e);if(C==null)return;let l=m(C);l!==k.current&&w(l)&&(U(l),x("Received",C))}),[s,e,a,m,w]);let A=ee(f=>{!a||!e||(s.params.set(e,f,"param"),s.edges.stopLoading(),x("Broadcast",f))},[s,a,e]),j=ee(()=>{!a||n||(g.current&&(clearTimeout(g.current),g.current=null),s.edges.startLoading(),A(k.current),O.current=!1)},[s,A,a,n]),E=ee(f=>{g.current&&(clearTimeout(g.current),g.current=null),U(f),k.current=f,O.current=!1,!(!a||!e||n)&&(s.params.clear(e),s.edges.stopLoading(),x("Cleared",null))},[s,a,e,n]);z(()=>{N.current=!1},[e,a]),z(()=>{if(!a||!e||n||!o||N.current)return;let f=s.params.getSnapshot(e);if(f!=null){N.current=!0;return}if(k.current===""){N.current=!0;return}A(k.current),N.current=!0},[s,a,e,n,o,A]);let B=ee(f=>{U(f),!(!a||n)&&(O.current=!0,s.edges.startLoading(),g.current&&clearTimeout(g.current),g.current=setTimeout(()=>{A(f),O.current=!1},r))},[s,A,r,a,n]);return z(()=>()=>{g.current&&clearTimeout(g.current);let{enabled:f,param:C}=Q.current;!f||!C||T.current.params.clear(C)},[]),{value:L,setValue:B,broadcastNow:j,clearValue:E}}function Sr(e){return typeof e=="string"?(r=>typeof r=="string"):typeof e=="number"?(r=>typeof r=="number"):typeof e=="boolean"?(r=>typeof r=="boolean"):Array.isArray(e)?(r=>Array.isArray(r)):e!==null&&typeof e=="object"?(r=>r!==null&&typeof r=="object"&&!Array.isArray(r)):(r=>!0)}function yr(e){return typeof e=="string"?r=>typeof r=="string"?r:Array.isArray(r)?r.join(","):r!==null&&typeof r=="object"?JSON.stringify(r):String(r):r=>r}import{useEffect as Le}from"react";function Rr(e){let r=de(),n=e.param,t=!!(r.isInForm&&n),{value:o,setValue:i,broadcastNow:u,clearValue:s}=fe({...e,param:t?void 0:e.param}),c=r.store;return Le(()=>{!t||!n||!c||c.setField(n,o)},[o,t,n,c]),Le(()=>{if(!(!t||!n||!c))return()=>{c.removeField(n)}},[t,n,c]),{value:o,setValue:i,broadcastNow:u,clearValue:s,isInForm:r.isInForm}}import{useCallback as Fe,useRef as De,useSyncExternalStore as vr}from"react";var Te=Object.freeze({});function Y(e){let r=v(),n=xr(e),t=Fe(u=>n.length===0?()=>{}:r.params.subscribeMany(n,u),[r,n]),o=De(Te),i=Fe(()=>{if(n.length===0)return Te;let u=r.params.getSnapshotMany(n),s=o.current;return br(s,u)?s:(o.current=u,u)},[r,n]);return vr(t,i,i)}function br(e,r){if(e===r)return!0;let n=Object.keys(e),t=Object.keys(r);if(n.length!==t.length)return!1;for(let o of n)if(!Object.is(e[o],r[o]))return!1;return!0}function xr(e){let r=De(e),n=r.current;return n!==e&&(n.length!==e.length||n.some((t,o)=>t!==e[o]))&&(r.current=e),r.current}import{useCallback as ge,useRef as hr,useSyncExternalStore as wr}from"react";function Ur(){let e=v(),r=ge(u=>e.routing.subscribeAllowedSources(u),[e]),n=hr(null),t=ge(()=>{let u=e.routing.getAllowedSources(),s=n.current;return kr(s,u)?s:(n.current=u,u)},[e]),o=wr(r,t,t),i=ge((u,s)=>!o||o.length===0||!u&&!s?!0:o.some(c=>c.udfUniqueId&&c.udfUniqueId===u||c.udfName&&c.udfName===s),[o]);return{allowedSources:o,isAllowedSource:i}}function kr(e,r){return e===r?!0:e===null||r===null||e.length!==r.length?!1:e.every((n,t)=>n.udfUniqueId===r[t].udfUniqueId&&n.udfName===r[t].udfName)}import{useCallback as Ne,useRef as Cr,useSyncExternalStore as Pr}from"react";function Er(){let e=v(),r=Ne(o=>e.routing.subscribeAllowedSources(o),[e]),n=Cr(null),t=Ne(()=>{let o=e.routing.getAllowedUdfNames(),i=n.current;return Ar(i,o)?i:(n.current=o,o)},[e]);return Pr(r,t,t)}function Ar(e,r){if(e===r)return!0;if(e===null||r===null||e.size!==r.size)return!1;for(let n of e)if(!r.has(n))return!1;return!0}import{useEffect as Or,useMemo as $,useRef as Lr,useState as qe,useSyncExternalStore as Fr,useCallback as Me}from"react";var Ie=/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,Tr=/\{\{[\s\S]*?\}\}/,Be=/\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\b/g;function pe(e,r={}){let n=e??"",t=r.preserveMissingParams??!1,o=v(),i=$(()=>Dr(n),[n]),u=Y(i),{inForm:s,values:c}=J(i),a=$(()=>s?{...u,...c}:u,[u,c,s]),x=$(()=>Tr.test(n),[n]),m=$(()=>x?"":Nr(n,a,t),[n,a,t,x]),w=$(()=>{if(!x)return[];let U=new Set,k=[];Be.lastIndex=0;let g;for(;(g=Be.exec(n))!==null;)U.has(g[1])||(U.add(g[1]),k.push(g[1]));return k},[n,x]),d=Mr(o,w),[b,S]=qe(()=>({key:"",value:""})),[q,M]=qe(!1),h=$(()=>JSON.stringify({template:n,paramValues:a,preserveMissingParams:t,tick:d}),[n,a,t,d]);return Or(()=>{if(!x){M(!1);return}let U=!1,k=new AbortController;return M(!0),o.template.render(n,a,{preserveMissingParams:t,signal:k.signal}).then(g=>{U||(S(O=>O.key===h&&O.value===g.value?O:{key:h,value:g.value}),M(g.loading))},g=>{U||g?.name!=="AbortError"&&M(!1)}),()=>{U=!0,k.abort()}},[o,x,n,a,t,h]),{value:$(()=>{if(!x)return m;if(b.key===h)return b.value;try{return o.template.renderLoading(n,a,{preserveMissingParams:t})}catch{return n}},[o,x,m,b,h,n,a,t]),loading:x?q:!1}}function Dr(e){let r=[],n=new Set;for(let t of e.matchAll(Ie)){let o=t[1];n.has(o)||(n.add(o),r.push(o))}return r}function Nr(e,r,n){return e.replace(Ie,(t,o)=>{let i=r[o];return i==null?n?t:"":qr(i)})}function qr(e){return e==null?"":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):JSON.stringify(e)??""}function Mr(e,r){let n=Lr(0),t=r.slice().sort().join("|"),o=Me(u=>{let s=()=>{n.current+=1,u()},c=[e.template.subscribe(s)];for(let a of r)c.push(e.udfs.subscribeOutput(a,s));return()=>c.forEach(a=>a())},[e,t]),i=Me(()=>n.current,[]);return Fr(o,i,i)}import{useCallback as ne,useEffect as Br,useMemo as te,useRef as Ir,useState as _e,useSyncExternalStore as _r}from"react";function Qe(e){let r=v(),n=ne(i=>e?r.udfs.subscribeOutput(e,i):()=>{},[r,e]),t=Ir(void 0),o=ne(()=>{if(!e)return;let i=r.udfs.getOutputSnapshot(e),u=t.current;return Qr(u,i)?u:(t.current=i,i)},[r,e]);return _r(n,o,o)}function Ve(){let e=v();return ne(r=>e.udfs.requestReexecute(r),[e])}function Qr(e,r){return e===r?!0:!e||!r?!1:e.data===r.data&&e.isExecutionInProgress===r.isExecutionInProgress&&e.error===r.error&&e.vfsFilename===r.vfsFilename}var $e=/^\{\{(\w+)\.(\w+)(?:\[(\d+)\])?\}\}$/;function oe(e){return!e||typeof e!="string"?!1:$e.test(e)}function me(e){if(!oe(e))return null;let r=e.match($e);if(!r)return null;let[,n,t,o]=r,i=o!==void 0?parseInt(o,10):void 0;return{udfName:n,columnName:t,index:i}}function Vr(e){return!!e&&typeof e=="object"&&typeof e.getRows=="function"}function Se({udfName:e,sampleSize:r=200}){let n=Qe(e),t=Ve(),[o,i]=_e([]),[u,s]=_e([]);Br(()=>{let a=!1,x=n?.data;if(!x||!Vr(x)){i([]),s([]);return}return(async()=>{try{let m=await x.getRows(0,Math.max(0,r));if(a)return;let w=m.map(b=>{let S=b;return S&&typeof S=="object"&&S.properties&&typeof S.properties=="object"?S.properties:b});i(w);let d=Array.from(new Set(w.flatMap(b=>Object.keys(b??{}))));s(d)}catch{if(a)return;i([]),s([])}})(),()=>{a=!0}},[n?.data,r]);let c=ne(()=>{e&&t(e)},[t,e]);return{loading:n?.isExecutionInProgress??!1,errorMessage:n?.error??null,isError:!!n?.error,columns:u,rows:o,requestReexecute:c}}function $r(e,r=200){let n=oe(e),t=te(()=>n?me(e):null,[n,e]),{rows:o,loading:i}=Se({udfName:t?.udfName,sampleSize:r});return{values:te(()=>!t||!t.columnName?[]:o.map(s=>s?.[t.columnName]).filter(s=>s!=null),[o,t]),loading:n?i:!1}}function jr(e,r=200){let n=oe(e),t=te(()=>n?me(e):null,[n,e]),{rows:o,loading:i}=Se({udfName:t?.udfName,sampleSize:r});return{value:te(()=>{if(!t||!t.columnName||t.index===void 0)return null;let s=o[t.index];if(!s)return null;let c=s[t.columnName];return c!==void 0?c:null},[o,t]),loading:n?i:!1}}import{useCallback as nr,useEffect as K,useMemo as D,useRef as nn,useState as I}from"react";import{useCallback as se,useMemo as Wr,useRef as ye,useSyncExternalStore as Jr}from"react";var je=Object.freeze([]);function ie(){let e=v(),{configHash:r}=W(),n=ye(e);n.current=e;let t=ye(r);t.current=r;let o=se((i,u="info")=>{n.current.log.log(i,u,t.current)},[]);return Wr(()=>({log:o}),[o])}function zr(e){let r=v(),n=se(i=>e?r.log.subscribeLogs(e,i):()=>{},[r,e]),t=ye(je),o=se(()=>{if(!e)return je;let i=r.log.getLogsSnapshot(e);return i===t.current?t.current:(t.current=i,i)},[r,e]);return Jr(n,o,o)}function Hr(e){let r=v();return se(()=>{e&&r.log.clearLogs(e)},[r,e])}function ue(){let e=v();return{startLoading:e.edges.startLoading,stopLoading:e.edges.stopLoading}}import{createContext as Kr,useContext as Zr}from"react";var Gr=Object.freeze({}),Re=Kr(Gr);Re.displayName="SqlSourceOverrideContext";function ve(){return Zr(Re)}var be=/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,We=/\{\{(\w+)(?:\?([^}]*))?\}\}/g,xe=/'((?:s3|gs|fd):\/\/[^'\n]+)'/g;function Yr(e){return e==null?"''":typeof e=="number"&&!Number.isNaN(e)?String(e):typeof e=="boolean"?e?"TRUE":"FALSE":`'${String(e).replace(/'/g,"''")}'`}function Xr(e,r){let n=!1;for(let t=0;t<r;t++)if(e[t]==="'"){if(n&&e[t+1]==="'"){t++;continue}n=!n}return n}function Je(e,r){return e.replace(be,(n,t,o)=>{let i=r[t],u=i==null?"":String(i);return Xr(e,o)?u.replace(/'/g,"''"):Yr(i)})}function ze(e){let r=new Set,n=[];be.lastIndex=0;for(let t of e.matchAll(be)){let o=t[1];r.has(o)||(r.add(o),n.push(o))}return n}function en(e){if(!e)return null;let r={},n=!1;for(let t of e.split(/[&,]/)){if(!t)continue;let o=t.indexOf("=");if(o===-1)continue;let i=t.slice(0,o),u=t.slice(o+1),s,c;try{s=decodeURIComponent(i),c=decodeURIComponent(u)}catch{s=i,c=u}s&&(r[s]=c,n=!0)}return n?r:null}function He(e){let r=[],n;for(We.lastIndex=0;(n=We.exec(e))!==null;){let[t,o,i]=n;r.push({match:t,name:o,overrides:en(i),start:n.index,end:n.index+t.length})}return r}function Ke(e){if(!e)return[];let r=new Set,n=[];xe.lastIndex=0;let t;for(;(t=xe.exec(e))!==null;){let o=t[1];r.has(o)||(r.add(o),n.push(o))}return n}function Ze(e,r){return e&&e.replace(xe,(n,t)=>{let o=r[t];return o?`'${o}'`:n})}var Ge=/^\$([a-zA-Z_][a-zA-Z0-9_]*)$/;function Ye(e){let r=e.trim(),n=Ge.exec(r);return n?n[1]:null}function Xe(e,r){let n=Ge.exec(e);if(!n)return{value:e,unresolved:!1};let t=n[1];if(!(t in r))return{value:e,unresolved:!0};let o=r[t];return o==null?{value:"",unresolved:!1}:{value:String(o),unresolved:!1}}function rn(e){return Object.keys(e).sort().map(r=>`${r}=${e[r]}`).join("&")}function er(e,r){return r?`${e}#${rn(r)}`:e}var tr=500,H=Object.freeze([]),X=Object.freeze([]);function rr(e,r){if(/\bLIMIT\b/i.test(e))return e;let n=e.trimEnd();return`${n.endsWith(";")?n.slice(0,-1):n} LIMIT ${r}`}function tn(e){return`"${e.replace(/"/g,'""')}"`}function on(e,r,n,t,o,i){let u=e.match(/^\$([a-zA-Z_][a-zA-Z0-9_]*)$/);if(u){let c=o[u[1]];return c==null?"":rr(String(c),i)}let s=e;for(let c=r.length-1;c>=0;c--){let{raw:a,key:x,resolvedOverrides:m}=r[c],d=m===null&&t?t[a.name]:void 0,b;d?b=tn(d.relationName):b=`'${n.get(x)??`${a.name}.parquet`}'`,s=s.slice(0,a.start)+b+s.slice(a.end)}return s=rr(s,i),Je(s,o)}function or({sql:e,enabled:r=!0,maxRows:n=tr,sourceOverrides:t}){let o=v(),i=ve(),u=D(()=>{let l=Object.keys(i).length>0;return t?l?{...i,...t}:t:l?i:void 0},[i,t]),{startLoading:s,stopLoading:c}=ue(),{log:a}=ie(),[x,m]=I(""),[w,d]=I(!1),[b,S]=I(null),[q,M]=I(0),h=D(()=>e?He(e):[],[e]),L=D(()=>u?h.filter(l=>l.overrides!==null||!u[l.name]):h,[h,u]),U=D(()=>{let l=new Set;for(let y of L)if(y.overrides)for(let R of Object.values(y.overrides)){let _=Ye(R);_&&l.add(_)}return Array.from(l)},[L]),k=D(()=>e?ze(e):[],[e]),g=D(()=>{let l=new Set,y=[];for(let R of k)l.has(R)||(l.add(R),y.push(R));for(let R of U)l.has(R)||(l.add(R),y.push(R));return y},[k,U]),O=Y(g),{inForm:N,values:Q}=J(g),T=D(()=>N?{...O,...Q}:O,[N,O,Q]),F=D(()=>L.map(l=>{if(!l.overrides)return{raw:l,key:l.name,resolvedOverrides:null,unresolved:!1};let y={},R=!1;for(let[_,Z]of Object.entries(l.overrides)){let p=Xe(Z,T);p.unresolved&&(R=!0),y[_]=p.value}return{raw:l,key:er(l.name,y),resolvedOverrides:y,unresolved:R}}),[L,T]),A=D(()=>{let l=new Set,y=[];for(let R of F)R.unresolved||l.has(R.key)||(l.add(R.key),y.push({name:R.raw.name,key:R.key,overrides:R.resolvedOverrides??void 0}));return y},[F]),j=D(()=>A.map(l=>`${l.key}|${l.name}|${l.overrides?Object.entries(l.overrides).sort(([y],[R])=>y.localeCompare(R)).map(([y,R])=>`${y}=${R}`).join(","):""}`).join(`
2
+ `),[A]),E=nr(()=>{M(l=>l+1)},[]);K(()=>{if(!r||A.length===0)return;let l=A.map(y=>o.udfs.subscribeOutput(y.name,()=>{M(R=>R+1)}));return()=>{l.forEach(y=>y())}},[o,r,A]),K(()=>{w?s():c()},[w,s,c]);let B=D(()=>{if(!u)return null;for(let l of h){if(l.overrides!==null)continue;let y=u[l.name];if(y?.error)return y.error}return null},[h,u]),f=D(()=>u?h.some(l=>l.overrides===null&&u[l.name]?.loading):!1,[h,u]),C=F.some(l=>l.unresolved);return K(()=>{if(!r||!e){m(""),d(!1),S(null);return}if(B){m(""),S(B),d(!1),a(`SQL preprocessing: ${B}`,"error");return}if(f||C){m(""),S(null),d(!0);return}let l=!1;return d(!0),S(null),(async()=>{let y=new Map,R;if(A.length>0)try{let p=await o.sql.resolveVfsFilenames(A);if(l)return;if(p instanceof Map)for(let P of F){if(P.resolvedOverrides)continue;let G=p.get(P.raw.name);G&&y.set(P.key,G)}else y=p.filenames,R=p.errors}catch(p){if(l)return;let P=p instanceof Error?p.message:typeof p=="string"?p:"VFS registration failed";m(""),S(P),d(!1),a(`SQL preprocessing: ${P}`,"error");return}if(R)for(let p of F){let P=R.get(p.key);if(P){if(l)return;m(""),S(P),d(!1),a(`SQL preprocessing: ${P}`,"error");return}}for(let p of F)if(!(p.unresolved||p.resolvedOverrides===null&&u?.[p.raw.name]!==void 0)&&!y.has(p.key)){if(l)return;m(""),S(null),d(!0);return}let _;try{_=on(e,F,y,u,T,n)}catch(p){if(l)return;let P=p instanceof Error?p.message:typeof p=="string"?p:"SQL preprocessing failed";m(""),S(P),d(!1),a(`SQL preprocessing failed: ${P}`,"error");return}let Z=Ke(_);if(Z.length===0){if(l)return;m(_),S(null),d(!1),a("SQL preprocessing completed");return}try{let p={},P=await Promise.all(Z.map(le=>o.signUrl(le)));if(l)return;Z.forEach((le,ur)=>{p[le]=P[ur].signed});let G=Ze(_,p);m(G),S(null),d(!1),a("SQL preprocessing completed")}catch(p){if(l)return;let P=p instanceof Error?p.message:typeof p=="string"?p:"URL signing failed";m(""),S(P),d(!1),a(`SQL preprocessing failed: ${P}`,"error")}})(),()=>{l=!0}},[o,r,e,j,F,T,u,B,f,C,n,q,a,A]),{processedSql:x,loading:w,error:b,refetch:E}}function sn({sql:e,enabled:r=!0,maxRows:n=tr,sourceOverrides:t}){let o=v(),{startLoading:i,stopLoading:u}=ue(),{log:s}=ie(),[c,a]=I(H),[x,m]=I(X),[w,d]=I(!1),[b,S]=I(null),[q,M]=I(0),{processedSql:h,loading:L,error:U,refetch:k}=or({sql:e,enabled:r,maxRows:n,sourceOverrides:t}),g=nn(""),O=r&&!!e&&!!h&&!L&&!U&&h!==g.current,N=L||w||O;K(()=>{N?i():u()},[N,i,u]);let Q=nr(()=>{g.current="",k(),M(T=>T+1)},[k]);return K(()=>{if(!r||!e){g.current="",a(H),m(X),d(!1),S(null);return}if(U){g.current="",S(U),a(H),m(X),d(!1);return}if(L||!h){g.current="",d(!1);return}let T=!1,F=new AbortController;g.current=h,d(!0),S(null);let A=h.length>120?h.slice(0,120)+"\u2026":h;s(`SQL query started: ${A}`);let j=performance.now();return o.sql.query(h,{signal:F.signal}).then(E=>{if(T)return;let B=Math.round(performance.now()-j);if(E.error){a(H),m(X),S(E.error),d(!1),s(`SQL failed (${B}ms): ${E.error}`,"error");return}a(E.rows.length===0?H:E.rows),m(E.columns),S(null),d(!1),s(`SQL completed: ${E.rows.length} row${E.rows.length!==1?"s":""} in ${B}ms`)},E=>{if(T||E?.name==="AbortError")return;let B=Math.round(performance.now()-j),f=E instanceof Error?E.message:typeof E=="string"?E:"SQL query failed";S(f),a(H),m(X),d(!1),s(`SQL failed (${B}ms): ${f}`,"error")}),()=>{T=!0,F.abort()}},[o,r,e,h,L,U,q,s]),{rows:c,columns:x,loading:N,error:b,refetch:Q}}function un(e,r=!0){let n=v(),[t,o]=I({filenames:new Map,loading:!1}),i=D(()=>e.slice().sort().join("|"),[e]);return K(()=>{if(!r||e.length===0){o({filenames:new Map,loading:!1});return}let u=!1;return o(s=>({...s,loading:!0,error:void 0})),n.sql.resolveVfsFilenames(e).then(s=>{if(u)return;let c=s instanceof Map?s:s.filenames;o({filenames:c,loading:!1})},s=>{u||o({filenames:new Map,loading:!1,error:s instanceof Error?s.message:String(s)})}),()=>{u=!0}},[n,i,r]),t}import{useCallback as sr,useEffect as an,useState as ae}from"react";var ir=["s3://","gs://","fd://"];function he(e){return ir.some(r=>e.startsWith(r))}function ln(){let e=v();return{signUrl:sr(n=>e.signUrl(n),[e])}}function cn(e){let r=v(),{value:n,loading:t}=pe(e),[o,i]=ae(null),[u,s]=ae(null),[c,a]=ae(!1),[x,m]=ae(0);an(()=>{if(t)return;if(!n){i(null),s(null),a(!1);return}if(!he(n)){i(n),s(null),a(!1);return}let d=!1;return a(!0),s(null),r.signUrl(n).then(({signed:b})=>{d||i(b??n)}).catch(b=>{d||(s(b instanceof Error?b.message:"Failed to load media"),i(null))}).finally(()=>{d||a(!1)}),()=>{d=!0}},[r,t,n,x]);let w=sr(async()=>{if(!n||!he(n))return n??null;let{signed:d}=await r.signUrl(n),b=d??n;return i(b),s(null),m(S=>S+1),b},[r,n]);return{src:o,loading:t||c,error:u,refreshSignedUrl:w,resolvedSrc:n,needsSigning:!!(n&&he(n))}}import{useEffect as dn,useState as fn}from"react";function gn(e,r){let n=v(),[t,o]=fn({status:"idle"});return dn(()=>{if(!r||!e?.trim()){o({status:"idle"});return}let i=!1;return o({status:"checking"}),n.uploads.checkAccess(e).then(u=>{i||(u.ok?o({status:"allowed"}):o({status:"denied",message:u.message??"Upload access denied."}))}),()=>{i=!0}},[n,e,r]),t}function pn(){return W()}function mn(e){if(!e)return{};let r={};for(let n of e.split(";")){let t=n.indexOf(":");if(t===-1)continue;let o=n.slice(0,t).trim(),i=n.slice(t+1).trim();if(!o||!i)continue;let u=o.replace(/-([a-z])/g,(s,c)=>c.toUpperCase());r[u]=i}return r}export{Oe as FormContext,ke as FusedWidgetBridgeContext,Ce as JsonUiNodeOverrideContext,Sn as PARAMETER_BROADCAST_CHANNEL,ce as ParameterMessageType,xe as SIGNABLE_URL_LITERAL_REGEX,ir as SIGNED_URL_SCHEMES,be as SQL_PARAM_REGEX,We as SQL_SOURCE_PLACEHOLDER_REGEX,Re as SqlSourceOverrideContext,rn as canonicalOverrideKey,er as computePlaceholderKey,hn as createFormParamsStore,pr as defineCatalog,gr as defineComponent,Yr as escapeSqlValue,Ke as extractSignableUrls,ze as extractSqlParams,Ye as getDollarRefName,yn as isStandardMessage,oe as isUdfQuery,en as parseOverridesString,He as parseSqlUdfPlaceholders,mn as parseStyle,me as parseUdfColumnQuery,Xe as resolveOverrideValue,Ze as rewriteSignedUrls,Je as substituteSqlParams,Ur as useAllowedSources,Er as useAllowedUdfNames,Y as useCanvasParams,sn as useDuckDbSqlQuery,or as useDuckDbSqlQueryPreprocessing,de as useFormContext,J as useFormParams,fe as useFusedParam,Rr as useFusedParamWithForm,v as useFusedWidgetBridge,ue as useJsonUiEdgeAnimation,ie as useJsonUiLog,Hr as useJsonUiLogClear,zr as useJsonUiLogs,W as useJsonUiNode,pn as useJsonUiUdfInfo,cn as useMediaSrc,pe as useParamSubstitution,Ve as useRequestUdfReexecute,ve as useSqlSourceOverrides,jr as useUdfColumnValue,$r as useUdfColumnValues,Se as useUdfDataFrameSample,Qe as useUdfOutputByName,gn as useUploadAccessCheck,ln as useUrlSigning,un as useVfsRegistration};
@@ -5,7 +5,7 @@ import type { CatalogComponentDefinition } from "./define-component";
5
5
  * export default defineCatalog({
6
6
  * components: { "kebab-key": defineComponent({...}), ... },
7
7
  * skill, // string imported from "../SKILL.md" (esbuild text loader)
8
- * summary, // ≤120-char headline; REQUIRED when skill is present
8
+ * summary, // ≤240-char headline; REQUIRED when skill is present
9
9
  * });
10
10
  *
11
11
  * `skill` and `summary` are co-required at the **type level** via function
@@ -36,9 +36,11 @@ export interface CatalogDefinitionWithSkill extends CatalogDefinitionBase {
36
36
  */
37
37
  skill: string;
38
38
  /**
39
- * ≤120-char headline shown in the system prompt's
39
+ * ≤240-char headline shown in the system prompt's
40
40
  * `<available_catalog_skills>` block so the AI can decide whether the
41
- * catalog is relevant before fetching the full skill.
41
+ * catalog is relevant before fetching the full skill. A longer summary is
42
+ * truncated to 240 chars by the workbench loader (with a console warning)
43
+ * rather than failing the catalog load.
42
44
  */
43
45
  summary: string;
44
46
  }
@@ -0,0 +1,16 @@
1
+ export interface SqlSourceOverride {
2
+ /** In-memory DuckDB relation name to substitute for the `{{name}}` placeholder. */
3
+ relationName: string;
4
+ /** Error from materializing the source, if any. */
5
+ error?: string;
6
+ /** True while the source is still materializing. */
7
+ loading?: boolean;
8
+ }
9
+ export type SqlSourceOverrideMap = Record<string, SqlSourceOverride>;
10
+ /**
11
+ * Provided by hosts that expose named in-memory SQL sources to descendant
12
+ * widgets. Defaults to empty — most hosts and most subtrees have no overrides.
13
+ */
14
+ export declare const SqlSourceOverrideContext: import("react").Context<SqlSourceOverrideMap>;
15
+ /** Read the ancestor-provided SQL source overrides (empty map when none). */
16
+ export declare function useSqlSourceOverrides(): SqlSourceOverrideMap;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SqlSourceOverrideContext = void 0;
4
+ exports.useSqlSourceOverrides = useSqlSourceOverrides;
5
+ /**
6
+ * Host-provided SQL source overrides.
7
+ *
8
+ * Lets a host replace `{{name}}` SQL placeholders with an in-memory DuckDB
9
+ * relation instead of the UDF's VFS Parquet file. The Fused workbench's
10
+ * `sql-runner` component provides these for its descendant json-ui widgets
11
+ * (so a chart/metric/text nested under a sql-runner reads its in-memory tab);
12
+ * other hosts (MCP, test harness) leave it empty.
13
+ *
14
+ * The SDK SQL hooks (`useDuckDbSqlQuery` / `useDuckDbSqlQueryPreprocessing`)
15
+ * read this context automatically and merge it with any explicit
16
+ * `sourceOverrides` option, so component authors never thread it manually.
17
+ */
18
+ const react_1 = require("react");
19
+ const EMPTY_OVERRIDES = Object.freeze({});
20
+ /**
21
+ * Provided by hosts that expose named in-memory SQL sources to descendant
22
+ * widgets. Defaults to empty — most hosts and most subtrees have no overrides.
23
+ */
24
+ exports.SqlSourceOverrideContext = (0, react_1.createContext)(EMPTY_OVERRIDES);
25
+ exports.SqlSourceOverrideContext.displayName = "SqlSourceOverrideContext";
26
+ /** Read the ancestor-provided SQL source overrides (empty map when none). */
27
+ function useSqlSourceOverrides() {
28
+ return (0, react_1.useContext)(exports.SqlSourceOverrideContext);
29
+ }
@@ -43,7 +43,7 @@ export interface UseDuckDbSqlQueryPreprocessingResult {
43
43
  * Preprocess SQL: resolve placeholders, register UDFs via the bridge,
44
44
  * substitute params, sign URLs, append LIMIT. Returns the prepared SQL.
45
45
  */
46
- export declare function useDuckDbSqlQueryPreprocessing({ sql, enabled, maxRows, sourceOverrides, }: UseDuckDbSqlQueryOptions): UseDuckDbSqlQueryPreprocessingResult;
46
+ export declare function useDuckDbSqlQueryPreprocessing({ sql, enabled, maxRows, sourceOverrides: explicitSourceOverrides, }: UseDuckDbSqlQueryOptions): UseDuckDbSqlQueryPreprocessingResult;
47
47
  /**
48
48
  * Execute a DuckDB SQL query against UDF Parquet outputs. Uses
49
49
  * `useDuckDbSqlQueryPreprocessing` to prepare the SQL string, then runs
@@ -24,6 +24,7 @@ const form_1 = require("../form");
24
24
  const use_json_ui_log_1 = require("./use-json-ui-log");
25
25
  const use_json_ui_edge_animation_1 = require("./use-json-ui-edge-animation");
26
26
  const use_canvas_params_1 = require("./use-canvas-params");
27
+ const sql_source_overrides_1 = require("./sql-source-overrides");
27
28
  const sql_placeholders_1 = require("../utils/sql-placeholders");
28
29
  const DEFAULT_MAX_ROWS = 500;
29
30
  const EMPTY_ROWS = Object.freeze([]);
@@ -74,8 +75,22 @@ function buildProcessedSql(sql, resolved, fileNameMap, sourceOverrides, sqlParam
74
75
  * Preprocess SQL: resolve placeholders, register UDFs via the bridge,
75
76
  * substitute params, sign URLs, append LIMIT. Returns the prepared SQL.
76
77
  */
77
- function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides, }) {
78
+ function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides: explicitSourceOverrides, }) {
78
79
  const bridge = (0, bridge_1.useFusedWidgetBridge)();
80
+ // Auto-detect host-provided source overrides (e.g. the workbench's
81
+ // sql-runner exposes in-memory relations to descendants) and merge them with
82
+ // any explicit option. Explicit overrides win on key collision. Component
83
+ // authors never thread this manually.
84
+ const contextSourceOverrides = (0, sql_source_overrides_1.useSqlSourceOverrides)();
85
+ const sourceOverrides = (0, react_1.useMemo)(() => {
86
+ const hasContext = Object.keys(contextSourceOverrides).length > 0;
87
+ if (!explicitSourceOverrides) {
88
+ return hasContext ? contextSourceOverrides : undefined;
89
+ }
90
+ if (!hasContext)
91
+ return explicitSourceOverrides;
92
+ return { ...contextSourceOverrides, ...explicitSourceOverrides };
93
+ }, [contextSourceOverrides, explicitSourceOverrides]);
79
94
  const { startLoading: startEdgeLoading, stopLoading: stopEdgeLoading } = (0, use_json_ui_edge_animation_1.useJsonUiEdgeAnimation)();
80
95
  const { log } = (0, use_json_ui_log_1.useJsonUiLog)();
81
96
  const [processedSql, setProcessedSql] = (0, react_1.useState)("");
@@ -0,0 +1,18 @@
1
+ import type { UseFusedParamOptions, UseFusedParamReturn } from "../types";
2
+ /**
3
+ * Form-aware variant of {@link useFusedParam}.
4
+ *
5
+ * When the component is rendered inside a built-in Form, the field becomes
6
+ * local state (its value is NOT broadcast to the canvas) and its live value is
7
+ * mirrored into the form's subscription store, so sibling components (a
8
+ * dropdown's SQL options, a chart, a text binding, …) can react to it before
9
+ * the form is submitted. Outside a form it behaves exactly like
10
+ * `useFusedParam` — two-way canvas binding with debounced broadcast.
11
+ *
12
+ * Requires a `FusedWidgetBridgeContext` ancestor (like `useFusedParam`) and a
13
+ * `FormContext` ancestor for the in-form behavior (the built-in Form component
14
+ * provides one).
15
+ */
16
+ export declare function useFusedParamWithForm<T extends string | number>(options: UseFusedParamOptions<T>): UseFusedParamReturn<T> & {
17
+ isInForm: boolean;
18
+ };
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFusedParamWithForm = useFusedParamWithForm;
4
+ const react_1 = require("react");
5
+ const form_1 = require("../form");
6
+ const use_fused_param_1 = require("./use-fused-param");
7
+ /**
8
+ * Form-aware variant of {@link useFusedParam}.
9
+ *
10
+ * When the component is rendered inside a built-in Form, the field becomes
11
+ * local state (its value is NOT broadcast to the canvas) and its live value is
12
+ * mirrored into the form's subscription store, so sibling components (a
13
+ * dropdown's SQL options, a chart, a text binding, …) can react to it before
14
+ * the form is submitted. Outside a form it behaves exactly like
15
+ * `useFusedParam` — two-way canvas binding with debounced broadcast.
16
+ *
17
+ * Requires a `FusedWidgetBridgeContext` ancestor (like `useFusedParam`) and a
18
+ * `FormContext` ancestor for the in-form behavior (the built-in Form component
19
+ * provides one).
20
+ */
21
+ function useFusedParamWithForm(options) {
22
+ const formContext = (0, form_1.useFormContext)();
23
+ const param = options.param;
24
+ const isFormField = Boolean(formContext.isInForm && param);
25
+ // Hook handles both cases: with param (canvas sync) or without (local state).
26
+ // Disable canvas messaging when inside a form by withholding the param.
27
+ const { value, setValue, broadcastNow, clearValue } = (0, use_fused_param_1.useFusedParam)({
28
+ ...options,
29
+ param: isFormField ? undefined : options.param,
30
+ });
31
+ // Mirror the live value into the form's subscription store so sibling
32
+ // components can react to it. Value updates use a dedicated effect so we
33
+ // don't briefly remove the field from the store between renders —
34
+ // unregistration runs only when the binding (store/param) actually changes
35
+ // or on unmount.
36
+ const store = formContext.store;
37
+ (0, react_1.useEffect)(() => {
38
+ if (!isFormField || !param || !store)
39
+ return;
40
+ store.setField(param, value);
41
+ }, [value, isFormField, param, store]);
42
+ (0, react_1.useEffect)(() => {
43
+ if (!isFormField || !param || !store)
44
+ return;
45
+ return () => {
46
+ store.removeField(param);
47
+ };
48
+ }, [isFormField, param, store]);
49
+ return {
50
+ value,
51
+ setValue,
52
+ broadcastNow,
53
+ clearValue,
54
+ isInForm: formContext.isInForm,
55
+ };
56
+ }
package/dist/index.d.ts CHANGED
@@ -21,15 +21,18 @@ export * from "./types";
21
21
  export { defineComponent, type CatalogComponentDefinition, } from "./define-component";
22
22
  export { defineCatalog, type CatalogDefinition, type CatalogDefinitionBase, type CatalogDefinitionWithSkill, } from "./define-catalog";
23
23
  export { useFusedParam } from "./hooks/use-fused-param";
24
+ export { useFusedParamWithForm } from "./hooks/use-fused-param-with-form";
24
25
  export { useCanvasParams } from "./hooks/use-canvas-params";
25
26
  export { useAllowedSources } from "./hooks/use-allowed-sources";
26
27
  export { useAllowedUdfNames } from "./hooks/use-allowed-udf-names";
27
28
  export { useParamSubstitution } from "./hooks/use-param-substitution";
28
29
  export { useUdfOutputByName, useRequestUdfReexecute, useUdfDataFrameSample, useUdfColumnValue, useUdfColumnValues, isUdfQuery, parseUdfColumnQuery, type ParsedUdfQuery, type UseUdfDataFrameSampleOptions, type UseUdfDataFrameSampleResult, type UseUdfColumnValueResult, type UseUdfColumnValuesResult, } from "./hooks/use-udf-output";
29
30
  export { useDuckDbSqlQuery, useDuckDbSqlQueryPreprocessing, useVfsRegistration, type UseDuckDbSqlQueryOptions, type UseDuckDbSqlQueryResult, type UseDuckDbSqlQueryPreprocessingResult, } from "./hooks/use-duckdb-sql";
31
+ export { SqlSourceOverrideContext, useSqlSourceOverrides, type SqlSourceOverride, type SqlSourceOverrideMap, } from "./hooks/sql-source-overrides";
30
32
  export { useUrlSigning, useMediaSrc, SIGNED_URL_SCHEMES, type UseMediaSrcResult, } from "./hooks/use-url-signing";
31
33
  export { useUploadAccessCheck, type UploadAccessState, } from "./hooks/use-upload-access-check";
32
34
  export { useJsonUiLog, useJsonUiLogs, useJsonUiLogClear, } from "./hooks/use-json-ui-log";
33
35
  export { useJsonUiUdfInfo } from "./hooks/use-json-ui-udf-info";
34
36
  export { useJsonUiEdgeAnimation } from "./hooks/use-json-ui-edge-animation";
35
37
  export * from "./utils/sql-placeholders";
38
+ export { parseStyle } from "./utils/parse-style";
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
30
30
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.useJsonUiEdgeAnimation = exports.useJsonUiUdfInfo = exports.useJsonUiLogClear = exports.useJsonUiLogs = exports.useJsonUiLog = exports.useUploadAccessCheck = exports.SIGNED_URL_SCHEMES = exports.useMediaSrc = exports.useUrlSigning = exports.useVfsRegistration = exports.useDuckDbSqlQueryPreprocessing = exports.useDuckDbSqlQuery = exports.parseUdfColumnQuery = exports.isUdfQuery = exports.useUdfColumnValues = exports.useUdfColumnValue = exports.useUdfDataFrameSample = exports.useRequestUdfReexecute = exports.useUdfOutputByName = exports.useParamSubstitution = exports.useAllowedUdfNames = exports.useAllowedSources = exports.useCanvasParams = exports.useFusedParam = exports.defineCatalog = exports.defineComponent = void 0;
33
+ exports.parseStyle = exports.useJsonUiEdgeAnimation = exports.useJsonUiUdfInfo = exports.useJsonUiLogClear = exports.useJsonUiLogs = exports.useJsonUiLog = exports.useUploadAccessCheck = exports.SIGNED_URL_SCHEMES = exports.useMediaSrc = exports.useUrlSigning = exports.useSqlSourceOverrides = exports.SqlSourceOverrideContext = exports.useVfsRegistration = exports.useDuckDbSqlQueryPreprocessing = exports.useDuckDbSqlQuery = exports.parseUdfColumnQuery = exports.isUdfQuery = exports.useUdfColumnValues = exports.useUdfColumnValue = exports.useUdfDataFrameSample = exports.useRequestUdfReexecute = exports.useUdfOutputByName = exports.useParamSubstitution = exports.useAllowedUdfNames = exports.useAllowedSources = exports.useCanvasParams = exports.useFusedParamWithForm = exports.useFusedParam = exports.defineCatalog = exports.defineComponent = void 0;
34
34
  // ── Part 1: Provider contract ────────────────────────────────────────────────
35
35
  __exportStar(require("./protocol"), exports);
36
36
  __exportStar(require("./bridge"), exports);
@@ -45,6 +45,8 @@ Object.defineProperty(exports, "defineCatalog", { enumerable: true, get: functio
45
45
  // ── Part 2: Hooks ────────────────────────────────────────────────────────────
46
46
  var use_fused_param_1 = require("./hooks/use-fused-param");
47
47
  Object.defineProperty(exports, "useFusedParam", { enumerable: true, get: function () { return use_fused_param_1.useFusedParam; } });
48
+ var use_fused_param_with_form_1 = require("./hooks/use-fused-param-with-form");
49
+ Object.defineProperty(exports, "useFusedParamWithForm", { enumerable: true, get: function () { return use_fused_param_with_form_1.useFusedParamWithForm; } });
48
50
  var use_canvas_params_1 = require("./hooks/use-canvas-params");
49
51
  Object.defineProperty(exports, "useCanvasParams", { enumerable: true, get: function () { return use_canvas_params_1.useCanvasParams; } });
50
52
  var use_allowed_sources_1 = require("./hooks/use-allowed-sources");
@@ -65,6 +67,9 @@ var use_duckdb_sql_1 = require("./hooks/use-duckdb-sql");
65
67
  Object.defineProperty(exports, "useDuckDbSqlQuery", { enumerable: true, get: function () { return use_duckdb_sql_1.useDuckDbSqlQuery; } });
66
68
  Object.defineProperty(exports, "useDuckDbSqlQueryPreprocessing", { enumerable: true, get: function () { return use_duckdb_sql_1.useDuckDbSqlQueryPreprocessing; } });
67
69
  Object.defineProperty(exports, "useVfsRegistration", { enumerable: true, get: function () { return use_duckdb_sql_1.useVfsRegistration; } });
70
+ var sql_source_overrides_1 = require("./hooks/sql-source-overrides");
71
+ Object.defineProperty(exports, "SqlSourceOverrideContext", { enumerable: true, get: function () { return sql_source_overrides_1.SqlSourceOverrideContext; } });
72
+ Object.defineProperty(exports, "useSqlSourceOverrides", { enumerable: true, get: function () { return sql_source_overrides_1.useSqlSourceOverrides; } });
68
73
  var use_url_signing_1 = require("./hooks/use-url-signing");
69
74
  Object.defineProperty(exports, "useUrlSigning", { enumerable: true, get: function () { return use_url_signing_1.useUrlSigning; } });
70
75
  Object.defineProperty(exports, "useMediaSrc", { enumerable: true, get: function () { return use_url_signing_1.useMediaSrc; } });
@@ -81,3 +86,5 @@ var use_json_ui_edge_animation_1 = require("./hooks/use-json-ui-edge-animation")
81
86
  Object.defineProperty(exports, "useJsonUiEdgeAnimation", { enumerable: true, get: function () { return use_json_ui_edge_animation_1.useJsonUiEdgeAnimation; } });
82
87
  // ── Pure utilities (re-exported for advanced workbench paths) ────────────────
83
88
  __exportStar(require("./utils/sql-placeholders"), exports);
89
+ var parse_style_1 = require("./utils/parse-style");
90
+ Object.defineProperty(exports, "parseStyle", { enumerable: true, get: function () { return parse_style_1.parseStyle; } });
@@ -0,0 +1,9 @@
1
+ import type { CSSProperties } from "react";
2
+ /**
3
+ * Parses a plain CSS string into a React CSSProperties object.
4
+ * e.g. "color: red; font-size: 16px" → { color: "red", fontSize: "16px" }
5
+ *
6
+ * Pure — no bridge, no context. Used by every json-ui component that accepts
7
+ * a `style` string prop, across all hosts (workbench, MCP, test harness).
8
+ */
9
+ export declare function parseStyle(style: string | undefined): CSSProperties;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseStyle = parseStyle;
4
+ /**
5
+ * Parses a plain CSS string into a React CSSProperties object.
6
+ * e.g. "color: red; font-size: 16px" → { color: "red", fontSize: "16px" }
7
+ *
8
+ * Pure — no bridge, no context. Used by every json-ui component that accepts
9
+ * a `style` string prop, across all hosts (workbench, MCP, test harness).
10
+ */
11
+ function parseStyle(style) {
12
+ if (!style)
13
+ return {};
14
+ const result = {};
15
+ for (const declaration of style.split(";")) {
16
+ const colonIdx = declaration.indexOf(":");
17
+ if (colonIdx === -1)
18
+ continue;
19
+ const property = declaration.slice(0, colonIdx).trim();
20
+ const value = declaration.slice(colonIdx + 1).trim();
21
+ if (!property || !value)
22
+ continue;
23
+ const camelCase = property.replace(/-([a-z])/g, (_, l) => l.toUpperCase());
24
+ result[camelCase] = value;
25
+ }
26
+ return result;
27
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusedio/widget-sdk",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "SDK for building custom json-ui components for the Fused workbench",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",