@selvajs/compute 2.1.0-beta.3 → 2.1.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- import{b as l,c as h,d as f,e as m,h as A,i as _,j as q,m as J,n as H,p as Y,r as O}from"./chunk-XFYFC2DH.js";function p(t,e){if(!t||typeof t!="object")return;let r=t;if(e in r)return r[e];let n=e.toLowerCase();for(let s of Object.keys(r))if(s.toLowerCase()===n)return r[s]}function j(t,e){if(!t||typeof t!="object")return!1;let r=t;if(e in r)return!0;let n=e.toLowerCase();return Object.keys(r).some(s=>s.toLowerCase()===n)}function T(t,e){e||typeof window<"u"&&m().warn(`Warning: ${t} is running on the client side. For better performance and security, consider running this on the server side.`)}var Ie="Unable to load grasshopper definition";function xe(t){return t instanceof f&&t.message.includes(Ie)}function Q(t,e){if(!e)return;let r=p(t,"values");if(!Array.isArray(r)||r.length===0)return;let n=[];for(let o of r){let a=p(o,"innerTree");(!a||Object.keys(a).length===0)&&n.push(p(o,"paramName")??"<unnamed>")}if(n.length===0)return;let s=n.length===r.length?"all":`${n.length}/${r.length}`;m().warn(`Solve returned empty output(s) (${s}): ${n.join(", ")}. These parameters produced no data \u2014 check the definition's inputs and the branch feeding each.`)}async function D(t,e,r){r.debug&&T("solveGrasshopperDefinition",r.suppressBrowserWarning??r.suppressClientSideWarning);let{response:n}=await N(P(e,t),r);return n}async function X(t,e,r){return r.debug&&T("solveGrasshopperDefinitionWithCacheKey",r.suppressBrowserWarning??r.suppressClientSideWarning),N(P(e,t),r)}async function Z(t,e,r,n){n.debug&&T("solveByCacheKey",n.suppressBrowserWarning??n.suppressClientSideWarning);let s={algo:null,pointer:e,values:t};try{return{...await N(s,n),missed:!1}}catch(o){if(!xe(o))throw o;return{...await N(P(r,t),n),missed:!0}}}async function N(t,e){De(t,e);let r=await A("grasshopper",t,e);if("pointer"in r){let{pointer:n,...s}=r,o=s;return Q(o,e.debug),{response:o,cacheKey:typeof n=="string"?n:null}}return Q(r,e.debug),{response:r,cacheKey:null}}function P(t,e){let r={algo:null,pointer:null,values:e};return t instanceof Uint8Array?r.algo=Y(t):/^https?:\/\//i.test(t)?r.pointer=t:H(t)?r.algo=t:r.algo=J(t),r}function De(t,e){e.cachesolve!=null&&(t.cachesolve=e.cachesolve),e.modelunits!=null&&(t.modelunits=e.modelunits),e.angletolerance!=null&&(t.angletolerance=e.angletolerance),e.absolutetolerance!=null&&(t.absolutetolerance=e.absolutetolerance),e.dataversion!=null&&(t.dataversion=e.dataversion)}function ee(t){let e=new WeakSet,r=n=>{if(n==null)return JSON.stringify(n);if(typeof n=="number")return Number.isFinite(n)?String(n):JSON.stringify(null);if(typeof n=="string"||typeof n=="boolean")return JSON.stringify(n);if(typeof n=="bigint")return JSON.stringify(n.toString());if(n instanceof Uint8Array){let s=n.length>64?Array.from(n.slice(0,32)).concat(Array.from(n.slice(-32))):Array.from(n);return JSON.stringify({__u8:!0,len:n.length,sample:s})}return Array.isArray(n)?`[${n.map(r).join(",")}]`:typeof n=="object"?e.has(n)?JSON.stringify("[Circular]"):(e.add(n),`{${Object.keys(n).sort().map(a=>`${JSON.stringify(a)}:${r(n[a])}`).join(",")}}`):JSON.stringify(null)};return r(t)}function te(t,e){let r=2166136261;for(let n=0;n<t;n++)r^=e(n),r=r+((r<<1)+(r<<4)+(r<<7)+(r<<8)+(r<<24))>>>0;return r.toString(16).padStart(8,"0")}function re(t){return te(t.length,e=>t.charCodeAt(e))}function ne(t){return te(t.length,e=>t[e])}function F(t,e){return re(`${G(t)}|${ee(e)}`)}function G(t){return typeof t=="string"?t:`u8:${t.length}:${ne(t)}`}function Pe(t){return t instanceof Uint8Array?!0:!/^https?:\/\//i.test(t)}var C=class{constructor(e,r,n={},s){l(this,"executor");l(this,"baseConfig");l(this,"mode");l(this,"maxConcurrent");l(this,"timeoutMs");l(this,"retry");l(this,"cacheEnabled");l(this,"cacheMax");l(this,"cacheTtl");l(this,"cache",new Map);l(this,"cacheKeyExecutor");l(this,"reuseServerDefinitionCache");l(this,"serverCacheKeys",new Map);l(this,"onStart");l(this,"onSettle");l(this,"onSuperseded");l(this,"subscribers",new Set);l(this,"inFlight",new Set);l(this,"pendingForLatestWins",null);l(this,"fifoQueue",[]);l(this,"_lastResult",null);l(this,"_lastError",null);l(this,"_lastDurationMs",null);l(this,"disposed",!1);this.executor=e,this.cacheKeyExecutor=s,this.baseConfig=r,this.mode=n.mode??"latest-wins",this.maxConcurrent=Math.max(1,n.maxConcurrent??(this.mode==="parallel"?4:1)),this.timeoutMs=n.timeoutMs,this.retry=n.retry;let o=n.cache;this.cacheEnabled=o!==void 0&&o!==!1;let a=typeof o=="object"?o:{};this.cacheMax=a.maxEntries??50,this.cacheTtl=a.ttlMs??0,this.reuseServerDefinitionCache=!!s&&(n.reuseServerDefinitionCache??!0),this.onStart=n.onStart,this.onSettle=n.onSettle,this.onSuperseded=n.onSuperseded}get isSolving(){return this.inFlight.size>0}get hasPending(){return this.pendingForLatestWins!==null||this.fifoQueue.length>0}get inFlightCount(){return this.inFlight.size}get queueDepth(){return this.fifoQueue.length+(this.pendingForLatestWins?1:0)}get lastResult(){return this._lastResult}get lastError(){return this._lastError}get lastDurationMs(){return this._lastDurationMs}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(){for(let e of this.subscribers)try{e()}catch(r){m().error("[SolveScheduler] subscriber threw:",r)}}solve(e,r,n){if(this.disposed)return Promise.reject(new f("SolveScheduler has been disposed and cannot be used",h.INVALID_STATE));let s=F(e,r),o={key:s,enqueuedAt:Date.now(),startedAt:null};if(this.cacheEnabled){let a=this.readCache(s);if(a){let i={status:"success",response:a,durationMs:0,fromCache:!0};return this._lastResult=a,this._lastError=null,this._lastDurationMs=0,this.runHook(this.onStart,o),this.runHook(this.onSettle,o,i),this.notify(),Promise.resolve(a)}}return new Promise((a,i)=>{let u={definition:e,dataTree:r,ctx:o,resolve:a,reject:i,externalSignal:n?.signal};if(u.externalSignal?.aborted){this.settleError(u,this.makeAbortError(o));return}this.enqueue(u)})}enqueue(e){switch(this.mode){case"latest-wins":{this.pendingForLatestWins&&(this.supersede(this.pendingForLatestWins),this.pendingForLatestWins=null);for(let r of this.inFlight)this.supersede(r),r.controller.abort();this.inFlight.size===0?this.execute(e):this.pendingForLatestWins=e;break}case"queue":case"parallel":{this.inFlight.size<this.maxConcurrent?this.execute(e):this.fifoQueue.push(e);break}}this.notify()}async execute(e){let r=new AbortController,n={...e,controller:r};this.inFlight.add(n),e.ctx.startedAt=Date.now();let s=()=>r.abort();e.externalSignal?.addEventListener("abort",s,{once:!0}),this.runHook(this.onStart,e.ctx),this.notify();let o=performance.now();try{let a={...this.baseConfig,signal:r.signal,...this.timeoutMs!==void 0&&{timeoutMs:this.timeoutMs},...this.retry!==void 0&&{retry:this.retry}},i=await this.runExecutor(e.definition,e.dataTree,a),u=performance.now()-o;if(this.cacheEnabled&&this.writeCache(e.ctx.key,i),!this.settleSuccess(e,i))return;this._lastResult=i,this._lastError=null,this._lastDurationMs=u,this.runHook(this.onSettle,e.ctx,{status:"success",response:i,durationMs:u,fromCache:!1})}catch(a){let i=performance.now()-o,u=this.normalizeExecutionError(a,n);this._lastError=u,this._lastDurationMs=i,this.settleError(e,u)&&this.runHook(this.onSettle,e.ctx,{status:"error",error:u,durationMs:i})}finally{e.externalSignal?.removeEventListener("abort",s),this.inFlight.delete(n),this.drainNext(),this.notify()}}async runExecutor(e,r,n){if(!this.cacheKeyExecutor||!this.reuseServerDefinitionCache||!Pe(e))return this.executor(e,r,n);let s=G(e),o=this.serverCacheKeys.get(s)??null,a=await this.cacheKeyExecutor(e,r,o,n);return a.cacheKey?this.serverCacheKeys.set(s,a.cacheKey):this.serverCacheKeys.delete(s),a.response}drainNext(){if(!this.disposed){if(this.mode==="latest-wins"){if(this.pendingForLatestWins&&this.inFlight.size===0){let e=this.pendingForLatestWins;this.pendingForLatestWins=null,this.execute(e)}return}for(;this.fifoQueue.length>0&&this.inFlight.size<this.maxConcurrent;){let e=this.fifoQueue.shift();this.execute(e)}}}supersede(e){let r=new f("Superseded by newer solve",h.SUPERSEDED,{context:{key:e.ctx.key,enqueuedAt:e.ctx.enqueuedAt}});this.settleError(e,r)&&this.runHook(this.onSuperseded,e.ctx)}makeAbortError(e){return new f("Request aborted by caller",h.ABORTED,{context:{key:e.key,enqueuedAt:e.enqueuedAt}})}settleError(e,r){return e.settled?!1:(e.settled={error:r},e.reject(r),!0)}settleSuccess(e,r){return e.settled?!1:(e.settled={ok:!0},e.resolve(r),!0)}isAbortLikeError(e){if(e instanceof Error){if(e.name==="AbortError")return!0;if(typeof DOMException<"u"&&e instanceof DOMException)return e.name==="AbortError"}return!1}normalizeExecutionError(e,r){return r.settled&&"error"in r.settled?r.settled.error:e instanceof f?e:this.isAbortLikeError(e)?this.makeAbortError(r.ctx):new f(e instanceof Error?e.message:String(e),h.UNKNOWN_ERROR,{originalError:e instanceof Error?e:new Error(String(e))})}cancelAll(){for(this.pendingForLatestWins&&(this.rejectAsAborted(this.pendingForLatestWins),this.pendingForLatestWins=null);this.fifoQueue.length>0;){let e=this.fifoQueue.shift();this.rejectAsAborted(e)}for(let e of this.inFlight){let r=this.makeAbortError(e.ctx);this.settleError(e,r)&&this.runHook(this.onSettle,e.ctx,{status:"error",error:r,durationMs:e.ctx.startedAt?performance.now()-e.ctx.startedAt:0}),e.controller.abort()}this.notify()}rejectAsAborted(e){this.settleError(e,this.makeAbortError(e.ctx))}readCache(e){if(!this.cacheEnabled)return null;let r=this.cache.get(e);return r?this.cacheTtl>0&&Date.now()-r.insertedAt>this.cacheTtl?(this.cache.delete(e),null):(this.cache.delete(e),this.cache.set(e,r),r.response):null}writeCache(e,r){if(this.cacheEnabled)for(this.cache.set(e,{response:r,insertedAt:Date.now()});this.cache.size>this.cacheMax;){let n=this.cache.keys().next().value;if(n===void 0)break;this.cache.delete(n)}}clearCache(){this.cache.clear()}dispose(){this.disposed||(this.disposed=!0,this.cancelAll(),this.subscribers.clear(),this.cache.clear())}runHook(e,...r){if(e)try{e(...r)}catch(n){m().error("[SolveScheduler] hook threw:",n)}}};var R=class t{constructor(e){l(this,"config");l(this,"serverStats");l(this,"disposed",!1);this.config=this.normalizeComputeConfig(e),this.serverStats=new q(this.config.serverUrl,this.config.apiKey)}static async create(e){let r=new t(e),n=Math.max(1,(e.retry?.attempts??2)+1),s=e.retry?.baseDelayMs??250,o=e.retry?.maxDelayMs??1e3;for(let a=0;a<n;a++){if(await r.serverStats.isServerOnline())return r;if(a<n-1){let i=Math.min(s*2**a,o);await new Promise(u=>setTimeout(u,i))}}throw await r.dispose(),new f("Rhino Compute server is not online",h.NETWORK_ERROR,{context:{serverUrl:r.config.serverUrl,attempts:n}})}getConfig(){return this.ensureNotDisposed(),{...this.config}}async getIO(e){return this.ensureNotDisposed(),V(e,this.config)}async getRawIO(e){return this.ensureNotDisposed(),E(e,this.config)}async solve(e,r,n){this.ensureNotDisposed();try{if(typeof e=="string"&&!e?.trim())throw new f("Definition URL/content is required",h.INVALID_INPUT,{context:{receivedUrl:e}});if(e instanceof Uint8Array&&e.length===0)throw new f("Definition content is empty",h.INVALID_INPUT);let s={...this.config,...n?.signal!==void 0&&{signal:n.signal},...n?.timeoutMs!==void 0&&{timeoutMs:n.timeoutMs},...n?.retry!==void 0&&{retry:n.retry}},o=await D(r,e,s);if(o?.errors&&o.errors.length>0)throw new f(o.errors.join("; ")||"Computation failed",h.COMPUTATION_ERROR,{context:{definition:typeof e=="string"&&e.length<200?e:"...content...",inputs:r,errors:o.errors,warnings:o.warnings}});return o}catch(s){throw this.config.debug&&m().error("Compute failed:",s),s instanceof f?s:new f(s instanceof Error?s.message:String(s),h.COMPUTATION_ERROR,{context:{definition:typeof e=="string"&&e.length<200?e:"...content...",inputs:r},originalError:s instanceof Error?s:new Error(String(s))})}}createScheduler(e){this.ensureNotDisposed();let r=(s,o,a)=>D(o,s,a),n=(s,o,a,i)=>a===null?X(o,s,i).then(u=>({...u,missed:!1})):Z(o,a,s,i);return new C(r,this.config,e,n)}async dispose(){this.disposed||(this.disposed=!0,await this.serverStats.dispose())}ensureNotDisposed(){if(this.disposed)throw new f("GrasshopperClient has been disposed and cannot be used",h.INVALID_STATE)}normalizeComputeConfig(e){return{...e,serverUrl:_(e.serverUrl),apiKey:e.apiKey,authToken:e.authToken,debug:e.debug??!1,suppressBrowserWarning:e.suppressBrowserWarning??e.suppressClientSideWarning}}};var k=new Map;function se(t,e){k.set(t,e)}se("Rhino.Geometry.Point3d",(t,e)=>{let r=e;return!r||typeof r.X!="number"?null:new t.Point([r.X,r.Y,r.Z])});se("Rhino.Geometry.Line",(t,e)=>{let r=e;return!r||!r.From||!r.To?null:new t.Line([r.From.X,r.From.Y,r.From.Z],[r.To.X,r.To.Y,r.To.Z])});function Re(t){if(k.has(t))return k.get(t);for(let[e,r]of k)if(t.startsWith(e))return r}function Ee(t){return!t||typeof t!="object"?null:t.data??t.value??null}function oe(t,e,r){let n=Re(e);if(n)try{return n(r,t)}catch(s){m().warn(`Failed to decode Rhino type ${e}:`,s)}try{let s=Ee(t);if(s)return r.CommonObject.decode(s)}catch(s){return m().warn(`Failed to decode ${e} with CommonObject:`,s),{__decodeError:!0,type:e,raw:t}}return t}var S={STRING:"System.String",INT:"System.Int32",DOUBLE:"System.Double",BOOL:"System.Boolean"},we="Rhino.Geometry.",ve=["WebDisplay"],Ae="FileData";function ae(t){return ve.some(e=>t.includes(e))}function ie(t){if(typeof t!="string")return t;let e=t.trim();if(!(e.startsWith("{")||e.startsWith("[")||e.startsWith('"')))return t;try{let n=JSON.parse(e);if(typeof n=="string")try{return JSON.parse(n)}catch{return n}return n}catch{return t}}function Oe(t,e,r){switch(e){case S.STRING:return typeof t!="string"?t:t.replace(/^"(.*)"$/,"$1");case S.INT:return Number.parseInt(t,10);case S.DOUBLE:return Number.parseFloat(t);case S.BOOL:return String(t).toLowerCase()==="true";default:return r&&e.startsWith(we)?oe(t,e,r):t}}function ue(t,e,r,n){if(typeof t!="string")return t;let s=r?ie(t):t;return Oe(s,e,n)}function Ne(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.fileName=="string"&&typeof e.fileType=="string"&&"data"in e&&typeof e.isBase64Encoded=="boolean"&&typeof e.subFolder=="string"}function M(t,e){for(let r of Object.values(t))if(Array.isArray(r))for(let n of r)e(n)}function pe(t,e=!1,r={}){let{parseValues:n=!0,rhino:s,stringOnly:o=!1}=r,a={};for(let i of t.values)M(i.InnerTree,u=>{if(ae(u.type)||o&&u.type!==S.STRING)return;let c=e?u.id:i.ParamName;if(!c)return;let d=ue(u.data,u.type,n,s);a[c]===void 0?a[c]=d:Array.isArray(a[c])?a[c].push(d):a[c]=[a[c],d]});return{values:a}}function le(t){let e=[];for(let r of t.values)M(r.InnerTree,n=>{if(!n.type.includes(Ae))return;let s=ie(n.data);Ne(s)&&e.push(s)});return e}function L(t,e,r={}){let{parseValues:n=!0,rhino:s,stringOnly:o=!1}=r,a;if("byName"in e?a=t.values.find(u=>u.ParamName===e.byName):a=t.values.find(u=>{let c=!1;return M(u.InnerTree,d=>{d.id===e.byId&&(c=!0)}),c}),!a)return;let i=[];if(M(a.InnerTree,u=>{if("byId"in e&&u.id!==e.byId||ae(u.type)||o&&u.type!==S.STRING)return;let c=ue(u.data,u.type,n,s);i.push(c)}),i.length!==0)return i.length===1?i[0]:i}var w=class{constructor(e,r=!1){this.response=e;this.debug=r}getValues(e=!1,r={}){return pe(this.response,e,r)}getValue(e,r){return L(this.response,e,r)}getValueByParamName(e,r){return L(this.response,{byName:e},r)}getValueByParamId(e,r){return L(this.response,{byId:e},r)}async extractMeshesFromResponse(e){let r={debug:this.debug,...e},n;try{({getThreeMeshesFromComputeResponse:n}=await import("./visualization-QMK4VTCF.js"))}catch(s){throw new f("Failed to load three.js visualization module. Ensure three.js is installed as a peer dependency.",h.INVALID_STATE,{context:{originalError:s instanceof Error?s.message:String(s)}})}return n(this.response,r)}getFileData(){return le(this.response)}getAndDownloadFiles(e,r){let n=this.getFileData();O(n,e,r)}};function ce(t){return p(t,"data")}function Fe(t){return p(t,"type")}function fe(t){if(typeof t.default!="object"||t.default===null)return{schema:t};if(!j(t.default,"innerTree")){let n=`Input "${t.name??"unknown"}" default had an unrecognized shape (no innerTree key); the default was dropped.`;return m().warn("Unexpected structure in input.default:",t.default),{schema:{...t,default:null},warning:{code:"MALFORMED_DEFAULT",message:n}}}let e=p(t.default,"innerTree")??{};if(Object.keys(e).length===0)return{schema:{...t,default:void 0}};if(t.treeAccess||t.atMost&&t.atMost>1){let n={};for(let[s,o]of Object.entries(e))n[s]=o.map(a=>{let i=ce(a),u=Fe(a);if(typeof i=="string"){if(u==="System.Double"||u==="System.Int32"){let c=Number(i);return Number.isNaN(c)?i:c}if(u==="System.Boolean")return i.toLowerCase()==="true";if(u?.startsWith("Rhino.Geometry"))try{return JSON.parse(i)}catch{return i}}return i});return{schema:{...t,default:n}}}let r=[];for(let n of Object.values(e))Array.isArray(n)&&n.forEach(s=>{s&&typeof s=="object"&&j(s,"data")&&r.push(ce(s))});return r.length===0?{schema:{...t,default:void 0}}:r.length===1?{schema:{...t,default:r[0]}}:{schema:{...t,default:r}}}var U=/^\{([\d;]*)\}$/;function v(t){if(typeof t!="object"||t===null||Array.isArray(t))return!1;let e=Object.entries(t);return e.length>0&&e.every(([r,n])=>U.test(r)&&Array.isArray(n))}function I(t,e,r){if(t==null)return t;if(Array.isArray(t)){let s=t.map(e).filter(o=>o!==null);return s.length>0?s:void 0}let n=e(t);return n!==null?n:r?void 0:t}var Ge=t=>{if(typeof t=="number")return t;if(typeof t=="string"){let e=Number(t.trim());return Number.isNaN(e)?null:e}return null},Ve=t=>{if(typeof t=="boolean")return t;if(typeof t=="string"){let e=t.toLowerCase();if(e==="true")return!0;if(e==="false")return!1;throw new Error(`Invalid boolean string: "${t}"`)}return null},ke=t=>typeof t=="string"?t.startsWith('"')&&t.endsWith('"')||t.startsWith('"')?t.slice(1,-1):t:null,Me=t=>{if(typeof t=="string"){let e=t.trim();return e.startsWith('"')&&e.endsWith('"')&&(e=e.slice(1,-1).trim()),e}return null};function de(t){return e=>{if(typeof e=="object"&&e!==null)return e;if(typeof e=="string"&&e.trim()!=="")try{let r=JSON.parse(e);return typeof r=="object"&&r!==null?r:(m().warn(`Parsed value for input ${t} is not an object`),null)}catch(r){return m().warn(`Failed to parse object value "${e}" for input ${t}`,r),null}return null}}function me(t,e,r){let n=Number(t.toFixed(e));return Math.abs(t-n)<r?n:t}function Le(t,e){if(!Number.isFinite(t)||t===0)return .1;let r=Math.abs(t);if(r>=1){let y=String(t).split(".")[1];if(y&&y.length>0){let g=Math.min(y.length,12),b=Math.pow(10,-g),$=Number(b.toFixed(g));return Math.abs($-b)<e?$:b}return 1}let n=String(t),s=n.toLowerCase().match(/e(-?\d+)/);if(s){let x=Number(s[1]);if(x<0||n.toLowerCase().includes("e-")){let y=Math.abs(x),g=Math.pow(10,-y),b=Number(g.toFixed(y));return Math.abs(b-g)<e?b:g}return .1}let o=12,i=r.toFixed(o).replace(/0+$/,""),u=Math.min((i.split(".")[1]||"").length,o);if(u===0)return .1;let c=Math.pow(10,-u),d=Number(c.toFixed(u));return Math.abs(d-c)<e?d:c}function We(t,e=1e-8){let r=t.paramType==="Integer";if(v(t.default))return{default:t.default,stepSize:r?1:.1};let n=I(t.default,Ge,!0);if(r)return Array.isArray(n)?n=n.map(d=>typeof d=="number"?Math.round(d):d):typeof n=="number"&&(n=Math.round(n)),{default:n,stepSize:1};let s=Array.isArray(n)?n[0]:n,o;typeof s=="number"&&Number.isFinite(s)&&s!==0?o=s:typeof t.minimum=="number"&&Number.isFinite(t.minimum)&&t.minimum!==0?o=t.minimum:typeof t.maximum=="number"&&Number.isFinite(t.maximum)&&t.maximum!==0&&(o=t.maximum);let a=o!==void 0?Le(o,e):.1,i=0,u=String(a),c=u.toLowerCase().match(/e(-?\d+)/);if(c?i=Math.abs(Number(c[1])):i=u.split(".")[1]?.length??0,i===0&&typeof s=="number"&&s!==0&&Math.abs(s)<1){let d=Math.ceil(-Math.log10(Math.abs(s)));Number.isFinite(d)&&d>0&&(i=d)}return i=Math.min(Math.max(i,0),12),Array.isArray(n)?n=n.map(d=>typeof d=="number"?me(d,i,e):d):typeof n=="number"&&(n=me(n,i,e)),{default:n,stepSize:a}}var Be={types:["Number","Integer"],parse(t,e){let{default:r,stepSize:n}=We(t);return{...e,paramType:t.paramType,minimum:t.minimum,maximum:t.maximum,atLeast:t.atLeast,atMost:t.atMost,stepSize:n,default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:t.paramType,minimum:t.minimum,maximum:t.maximum,atLeast:t.atLeast,atMost:t.atMost,default:r?[0]:0}}},je={types:["Boolean"],parse(t,e){let r;try{r=I(t.default,Ve,!1)}catch(n){throw n instanceof Error?new f(n.message):n}return{...e,paramType:"Boolean",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Boolean",default:r?[!1]:!1}}},Ue={types:["Text"],parse(t,e){let r=I(t.default,ke,!1);return{...e,paramType:"Text",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Text",default:r?[""]:""}}},Ke={types:["ValueList"],parse(t,e){if(!t.values||typeof t.values!="object"||Object.keys(t.values).length===0)throw f.missingValues(t.nickname||"unnamed","ValueList");if(t.default!==void 0&&t.default!==null){let r=String(t.default).toLowerCase();Object.keys(t.values).some(s=>s.toLowerCase()===r)||m().warn(`ValueList input "${t.nickname||"unnamed"}" default value "${t.default}" is not in available values`)}return{...e,paramType:"ValueList",values:t.values,default:t.default}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"ValueList",values:t.values??{},default:r?[t.default]:t.default}}},he={types:["Geometry"],parse(t,e){let r=I(t.default,de(t.nickname||"unnamed"),!0);return{...e,paramType:"Geometry",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Geometry",default:r?[null]:null}}},ze={types:["File"],parse(t,e){let r=I(t.default,de(t.nickname||"unnamed"),!0);return{...e,paramType:"File",acceptedFormats:t.acceptedFormats,default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"File",default:r?[null]:null}}},$e={types:["Color"],parse(t,e){let r=I(t.default,Me,!1);return{...e,paramType:"Color",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Color",default:r?["0, 0, 0"]:"0, 0, 0"}}},_e=[Be,je,Ue,Ke,he,ze,$e],K=new Map(_e.flatMap(t=>t.types.map(e=>[e,t]))),ye=he;var qe=new Map([...K.keys()].map(t=>[t.toLowerCase(),t]));function Je(t){return qe.get(t?.toLowerCase())??t}function ge(t){return z(t).input}function z(t){let e={description:t.description,name:t.name,nickname:t.nickname,treeAccess:t.treeAccess,groupName:t.groupName??"",id:t.id},r=Je(t.paramType),{schema:n,warning:s}=fe({...t,paramType:r}),o=s&&{inputName:t.name||"unknown",paramType:r,message:s.message,code:s.code},a=K.get(r);try{if(!a)throw f.unknownParamType(r,t.name);return{input:a.parse(n,e),error:o}}catch(i){if(i instanceof f)return m().error(`Validation error for input ${t.name||"unknown"}:`,i.message),{input:(a??ye).fallback(n,e),error:{inputName:t.name||"unknown",paramType:r,message:i.message,code:i.code}};throw new f(i instanceof Error?i.message:String(i),"VALIDATION_ERROR",{context:{paramName:t.name,paramType:r},originalError:i instanceof Error?i:new Error(String(i))})}}function be(t){return W(t).inputs}function W(t){let e=[],r=[];for(let n of t){let{input:s,error:o}=z(n);e.push(s),o&&r.push(o)}return{inputs:e,parseErrors:r}}function Te(t){return{id:p(t,"id"),name:p(t,"name"),nickname:p(t,"nickname")??null,description:p(t,"description"),paramType:p(t,"paramType"),treeAccess:p(t,"treeAccess"),minimum:p(t,"minimum")??null,maximum:p(t,"maximum")??null,atLeast:p(t,"atLeast"),atMost:p(t,"atMost"),stepSize:p(t,"stepSize"),default:p(t,"default"),values:p(t,"values"),acceptedFormats:p(t,"acceptedFormats"),groupName:p(t,"groupName")??""}}function Ce(t){return{name:p(t,"name"),nickname:p(t,"nickname")??null,paramType:p(t,"paramType"),id:p(t,"id")}}async function E(t,e){let r=P(t,[]),n={};if(r.algo&&(n.algo=r.algo),r.pointer&&(n.pointer=r.pointer),!n.algo&&!n.pointer)throw new f("Definition must resolve to either a URL pointer or base64 algo",h.INVALID_INPUT,{context:{definition:t}});let s=await A("io",n,e);if(!s||typeof s!="object")throw new f("Invalid IO response structure",h.INVALID_INPUT,{context:{response:s,definition:t}});let o=Se(p(s,"warnings")),a=Se(p(s,"errors")),i=p(s,"inputs"),u=p(s,"outputs");return{inputs:Array.isArray(i)?i.map(Te):[],outputs:Array.isArray(u)?u.map(Ce):[],...o&&{loadWarnings:o},...a&&{loadErrors:a}}}function Se(t){if(!Array.isArray(t))return;let e=t.filter(r=>typeof r=="string"&&r.trim().length>0);return e.length>0?e:void 0}async function V(t,e){T("fetchParsedDefinitionIO",e.suppressBrowserWarning??e.suppressClientSideWarning);let{inputs:r,outputs:n,loadWarnings:s,loadErrors:o}=await E(t,e),{inputs:a,parseErrors:i}=W(r);return{inputs:a,outputs:n,...i.length>0&&{parseErrors:i},...s&&{loadWarnings:s},...o&&{loadErrors:o}}}var B=class t{constructor(e){l(this,"innerTree");l(this,"paramName");this.paramName=e,this.innerTree={}}append(e,r){let n=t.formatPathString(e);this.innerTree[n]||(this.innerTree[n]=[]);let s=r.map(o=>({data:t.serializeValue(o)}));return this.innerTree[n].push(...s),this}appendSingle(e,r){return this.append(e,[r])}fromDataTreeDefault(e){this.innerTree={};for(let[r,n]of Object.entries(e)){if(!Array.isArray(n))continue;let s=t.parsePathString(r);this.append(s,n)}return this}appendFlat(e){let r=Array.isArray(e)?e:[e];return this.append([0],r)}flatten(){let e=[];for(let r of Object.values(this.innerTree))if(Array.isArray(r))for(let n of r)e.push(t.deserializeValue(n.data));return e}getPaths(){return Object.keys(this.innerTree)}getPath(e){let r=t.formatPathString(e),n=this.innerTree[r];if(n)return n.map(s=>t.deserializeValue(s.data))}toComputeFormat(){return{ParamName:this.paramName,InnerTree:this.innerTree}}getInnerTree(){return this.innerTree}getParamName(){return this.paramName}static fromInputParams(e){return e.filter(r=>t.hasValidValue(r.default)).map(r=>{let n=new t(r.nickname||"unnamed"),s=r.default;if(r.treeAccess&&v(s))n.fromDataTreeDefault(s),t.isNumericInput(r)&&n.applyNumericConstraints(r.minimum,r.maximum,r.nickname||"unnamed");else{let o=Array.isArray(s)?s:[s],a=t.processValues(o,r);n.appendFlat(a)}return n.toComputeFormat()})}static fromInputParam(e){return t.hasValidValue(e.default)?t.fromInputParams([e])[0]:void 0}static replaceTreeValue(e,r,n){let s=e.length>0&&e[0]instanceof t,o=t.buildFromValue(r,n);if(s){let c=e,d=c.findIndex(x=>x.getParamName()===r);return d!==-1?c[d]=o:c.push(o),c}let a=e,i=o.toComputeFormat(),u=a.findIndex(c=>c.ParamName===r);return u!==-1?a[u]=i:a.push(i),a}static buildFromValue(e,r){let n=new t(e);return v(r)?n.fromDataTreeDefault(r):n.appendFlat(r),n}static getTreeValue(e,r){let s=e.length>0&&e[0]instanceof t?t.readFromBuilders(e,r):t.readFromDataTrees(e,r);return s===null||s.length===0?null:s.length===1?s[0]:s}static readFromBuilders(e,r){let n=e.find(s=>s.getParamName()===r);return n?n.flatten():null}static readFromDataTrees(e,r){let n=e.find(a=>a.ParamName===r);if(!n?.InnerTree)return null;let s=Object.keys(n.InnerTree)[0];if(!s)return null;let o=n.InnerTree[s];return Array.isArray(o)?o.map(a=>a?.data!==void 0?t.deserializeValue(a.data):null).filter(a=>a!==null):o?.data!==void 0?[t.deserializeValue(o.data)]:o!==void 0?[o]:null}static parsePathString(e){let r=e.match(U);return r?r[1]===""?[]:r[1].split(";").map(Number):(m().warn(`Invalid TreeBuilder path format: ${e}, using [0]`),[0])}static formatPathString(e){return`{${e.join(";")}}`}applyNumericConstraints(e,r,n){for(let s of Object.values(this.innerTree))if(Array.isArray(s))for(let o of s){let a=t.deserializeValue(o.data);if(typeof a=="number"){let i=t.clampValue(a,e,r,n);o.data=t.serializeValue(i)}}}static serializeValue(e){return typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:typeof e=="object"&&e!==null?JSON.stringify(e):String(e)}static deserializeValue(e){if(typeof e=="boolean"||typeof e=="number"||typeof e!="string")return e;if(e.startsWith("{")||e.startsWith("["))try{return JSON.parse(e)}catch{return e}return isNaN(Number(e))?e==="true"?!0:e==="false"?!1:e:Number(e)}static hasValidValue(e){return e==null?!1:typeof e=="string"?!0:!(Array.isArray(e)&&e.length===0||typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===0)}static isNumericInput(e){return e.paramType==="Number"||e.paramType==="Integer"}static processValues(e,r){return e.map(n=>t.isNumericInput(r)&&typeof n=="number"?t.clampValue(n,r.minimum,r.maximum,r.nickname||"unnamed"):n).filter(n=>n!=null)}static clampValue(e,r,n,s){let o=e;return r!=null&&o<r&&(m().warn(`${s}: ${e} below min ${r}, clamping`),o=r),n!=null&&o>n&&(m().warn(`${s}: ${e} above max ${n}, clamping`),o=n),o}};export{D as a,F as b,C as c,R as d,w as e,ge as f,be as g,E as h,V as i,B as j};
2
- //# sourceMappingURL=chunk-QAS2VM6Q.js.map
1
+ import{b as l,c as h,d as f,e as m,h as A,i as _,j as q,m as J,n as H,p as Y,r as O}from"./chunk-XFYFC2DH.js";function p(t,e){if(!t||typeof t!="object")return;let r=t;if(e in r)return r[e];let n=e.toLowerCase();for(let s of Object.keys(r))if(s.toLowerCase()===n)return r[s]}function j(t,e){if(!t||typeof t!="object")return!1;let r=t;if(e in r)return!0;let n=e.toLowerCase();return Object.keys(r).some(s=>s.toLowerCase()===n)}function T(t,e){e||typeof window<"u"&&m().warn(`Warning: ${t} is running on the client side. For better performance and security, consider running this on the server side.`)}var Ie="Unable to load grasshopper definition";function xe(t){return t instanceof f&&t.message.includes(Ie)}function Q(t,e){if(!e)return;let r=p(t,"values");if(!Array.isArray(r)||r.length===0)return;let n=[];for(let o of r){let a=p(o,"innerTree");(!a||Object.keys(a).length===0)&&n.push(p(o,"paramName")??"<unnamed>")}if(n.length===0)return;let s=n.length===r.length?"all":`${n.length}/${r.length}`;m().warn(`Solve returned empty output(s) (${s}): ${n.join(", ")}. These parameters produced no data \u2014 check the definition's inputs and the branch feeding each.`)}async function D(t,e,r){r.debug&&T("solveGrasshopperDefinition",r.suppressBrowserWarning??r.suppressClientSideWarning);let{response:n}=await N(P(e,t),r);return n}async function X(t,e,r){return r.debug&&T("solveGrasshopperDefinitionWithCacheKey",r.suppressBrowserWarning??r.suppressClientSideWarning),N(P(e,t),r)}async function Z(t,e,r,n){n.debug&&T("solveByCacheKey",n.suppressBrowserWarning??n.suppressClientSideWarning);let s={algo:null,pointer:e,values:t};try{return{...await N(s,n),missed:!1}}catch(o){if(!xe(o))throw o;return{...await N(P(r,t),n),missed:!0}}}async function N(t,e){De(t,e);let r=await A("grasshopper",t,e);if("pointer"in r){let{pointer:n,...s}=r,o=s;return Q(o,e.debug),{response:o,cacheKey:typeof n=="string"?n:null}}return Q(r,e.debug),{response:r,cacheKey:null}}function P(t,e){let r={algo:null,pointer:null,values:e};return t instanceof Uint8Array?r.algo=Y(t):/^https?:\/\//i.test(t)?r.pointer=t:H(t)?r.algo=t:r.algo=J(t),r}function De(t,e){e.cachesolve!=null&&(t.cachesolve=e.cachesolve),e.modelunits!=null&&(t.modelunits=e.modelunits),e.angletolerance!=null&&(t.angletolerance=e.angletolerance),e.absolutetolerance!=null&&(t.absolutetolerance=e.absolutetolerance),e.dataversion!=null&&(t.dataversion=e.dataversion)}function ee(t){let e=new WeakSet,r=n=>{if(n==null)return JSON.stringify(n);if(typeof n=="number")return Number.isFinite(n)?String(n):JSON.stringify(null);if(typeof n=="string"||typeof n=="boolean")return JSON.stringify(n);if(typeof n=="bigint")return JSON.stringify(n.toString());if(n instanceof Uint8Array){let s=n.length>64?Array.from(n.slice(0,32)).concat(Array.from(n.slice(-32))):Array.from(n);return JSON.stringify({__u8:!0,len:n.length,sample:s})}return Array.isArray(n)?`[${n.map(r).join(",")}]`:typeof n=="object"?e.has(n)?JSON.stringify("[Circular]"):(e.add(n),`{${Object.keys(n).sort().map(a=>`${JSON.stringify(a)}:${r(n[a])}`).join(",")}}`):JSON.stringify(null)};return r(t)}function te(t,e){let r=2166136261;for(let n=0;n<t;n++)r^=e(n),r=r+((r<<1)+(r<<4)+(r<<7)+(r<<8)+(r<<24))>>>0;return r.toString(16).padStart(8,"0")}function re(t){return te(t.length,e=>t.charCodeAt(e))}function ne(t){return te(t.length,e=>t[e])}function F(t,e){return re(`${G(t)}|${ee(e)}`)}function G(t){return typeof t=="string"?t:`u8:${t.length}:${ne(t)}`}function Pe(t){return t instanceof Uint8Array?!0:!/^https?:\/\//i.test(t)}var C=class{constructor(e,r,n={},s){l(this,"executor");l(this,"baseConfig");l(this,"mode");l(this,"maxConcurrent");l(this,"timeoutMs");l(this,"retry");l(this,"cacheEnabled");l(this,"cacheMax");l(this,"cacheTtl");l(this,"cache",new Map);l(this,"cacheKeyExecutor");l(this,"reuseServerDefinitionCache");l(this,"serverCacheKeys",new Map);l(this,"onStart");l(this,"onSettle");l(this,"onSuperseded");l(this,"subscribers",new Set);l(this,"inFlight",new Set);l(this,"pendingForLatestWins",null);l(this,"fifoQueue",[]);l(this,"_lastResult",null);l(this,"_lastError",null);l(this,"_lastDurationMs",null);l(this,"disposed",!1);this.executor=e,this.cacheKeyExecutor=s,this.baseConfig=r,this.mode=n.mode??"latest-wins",this.maxConcurrent=Math.max(1,n.maxConcurrent??(this.mode==="parallel"?4:1)),this.timeoutMs=n.timeoutMs,this.retry=n.retry;let o=n.cache;this.cacheEnabled=o!==void 0&&o!==!1;let a=typeof o=="object"?o:{};this.cacheMax=a.maxEntries??50,this.cacheTtl=a.ttlMs??0,this.reuseServerDefinitionCache=!!s&&(n.reuseServerDefinitionCache??!0),this.onStart=n.onStart,this.onSettle=n.onSettle,this.onSuperseded=n.onSuperseded}get isSolving(){return this.inFlight.size>0}get hasPending(){return this.pendingForLatestWins!==null||this.fifoQueue.length>0}get inFlightCount(){return this.inFlight.size}get queueDepth(){return this.fifoQueue.length+(this.pendingForLatestWins?1:0)}get lastResult(){return this._lastResult}get lastError(){return this._lastError}get lastDurationMs(){return this._lastDurationMs}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(){for(let e of this.subscribers)try{e()}catch(r){m().error("[SolveScheduler] subscriber threw:",r)}}solve(e,r,n){if(this.disposed)return Promise.reject(new f("SolveScheduler has been disposed and cannot be used",h.INVALID_STATE));let s=F(e,r),o={key:s,enqueuedAt:Date.now(),startedAt:null};if(this.cacheEnabled){let a=this.readCache(s);if(a){let i={status:"success",response:a,durationMs:0,fromCache:!0};return this._lastResult=a,this._lastError=null,this._lastDurationMs=0,this.runHook(this.onStart,o),this.runHook(this.onSettle,o,i),this.notify(),Promise.resolve(a)}}return new Promise((a,i)=>{let u={definition:e,dataTree:r,ctx:o,resolve:a,reject:i,externalSignal:n?.signal};if(u.externalSignal?.aborted){this.settleError(u,this.makeAbortError(o));return}this.enqueue(u)})}enqueue(e){switch(this.mode){case"latest-wins":{this.pendingForLatestWins&&(this.supersede(this.pendingForLatestWins),this.pendingForLatestWins=null);for(let r of this.inFlight)this.supersede(r),r.controller.abort();this.inFlight.size===0?this.execute(e):this.pendingForLatestWins=e;break}case"queue":case"parallel":{this.inFlight.size<this.maxConcurrent?this.execute(e):this.fifoQueue.push(e);break}}this.notify()}async execute(e){let r=new AbortController,n={...e,controller:r};this.inFlight.add(n),e.ctx.startedAt=Date.now();let s=()=>r.abort();e.externalSignal?.addEventListener("abort",s,{once:!0}),this.runHook(this.onStart,e.ctx),this.notify();let o=performance.now();try{let a={...this.baseConfig,signal:r.signal,...this.timeoutMs!==void 0&&{timeoutMs:this.timeoutMs},...this.retry!==void 0&&{retry:this.retry}},i=await this.runExecutor(e.definition,e.dataTree,a),u=performance.now()-o;if(this.cacheEnabled&&this.writeCache(e.ctx.key,i),!this.settleSuccess(e,i))return;this._lastResult=i,this._lastError=null,this._lastDurationMs=u,this.runHook(this.onSettle,e.ctx,{status:"success",response:i,durationMs:u,fromCache:!1})}catch(a){let i=performance.now()-o,u=this.normalizeExecutionError(a,n);this._lastError=u,this._lastDurationMs=i,this.settleError(e,u)&&this.runHook(this.onSettle,e.ctx,{status:"error",error:u,durationMs:i})}finally{e.externalSignal?.removeEventListener("abort",s),this.inFlight.delete(n),this.drainNext(),this.notify()}}async runExecutor(e,r,n){if(!this.cacheKeyExecutor||!this.reuseServerDefinitionCache||!Pe(e))return this.executor(e,r,n);let s=G(e),o=this.serverCacheKeys.get(s)??null,a=await this.cacheKeyExecutor(e,r,o,n);return a.cacheKey?this.serverCacheKeys.set(s,a.cacheKey):this.serverCacheKeys.delete(s),a.response}drainNext(){if(!this.disposed){if(this.mode==="latest-wins"){if(this.pendingForLatestWins&&this.inFlight.size===0){let e=this.pendingForLatestWins;this.pendingForLatestWins=null,this.execute(e)}return}for(;this.fifoQueue.length>0&&this.inFlight.size<this.maxConcurrent;){let e=this.fifoQueue.shift();this.execute(e)}}}supersede(e){let r=new f("Superseded by newer solve",h.SUPERSEDED,{context:{key:e.ctx.key,enqueuedAt:e.ctx.enqueuedAt}});this.settleError(e,r)&&this.runHook(this.onSuperseded,e.ctx)}makeAbortError(e){return new f("Request aborted by caller",h.ABORTED,{context:{key:e.key,enqueuedAt:e.enqueuedAt}})}settleError(e,r){return e.settled?!1:(e.settled={error:r},e.reject(r),!0)}settleSuccess(e,r){return e.settled?!1:(e.settled={ok:!0},e.resolve(r),!0)}isAbortLikeError(e){if(e instanceof Error){if(e.name==="AbortError")return!0;if(typeof DOMException<"u"&&e instanceof DOMException)return e.name==="AbortError"}return!1}normalizeExecutionError(e,r){return r.settled&&"error"in r.settled?r.settled.error:e instanceof f?e:this.isAbortLikeError(e)?this.makeAbortError(r.ctx):new f(e instanceof Error?e.message:String(e),h.UNKNOWN_ERROR,{originalError:e instanceof Error?e:new Error(String(e))})}cancelAll(){for(this.pendingForLatestWins&&(this.rejectAsAborted(this.pendingForLatestWins),this.pendingForLatestWins=null);this.fifoQueue.length>0;){let e=this.fifoQueue.shift();this.rejectAsAborted(e)}for(let e of this.inFlight){let r=this.makeAbortError(e.ctx);this.settleError(e,r)&&this.runHook(this.onSettle,e.ctx,{status:"error",error:r,durationMs:e.ctx.startedAt?performance.now()-e.ctx.startedAt:0}),e.controller.abort()}this.notify()}rejectAsAborted(e){this.settleError(e,this.makeAbortError(e.ctx))}readCache(e){if(!this.cacheEnabled)return null;let r=this.cache.get(e);return r?this.cacheTtl>0&&Date.now()-r.insertedAt>this.cacheTtl?(this.cache.delete(e),null):(this.cache.delete(e),this.cache.set(e,r),r.response):null}writeCache(e,r){if(this.cacheEnabled)for(this.cache.set(e,{response:r,insertedAt:Date.now()});this.cache.size>this.cacheMax;){let n=this.cache.keys().next().value;if(n===void 0)break;this.cache.delete(n)}}clearCache(){this.cache.clear()}dispose(){this.disposed||(this.disposed=!0,this.cancelAll(),this.subscribers.clear(),this.cache.clear())}runHook(e,...r){if(e)try{e(...r)}catch(n){m().error("[SolveScheduler] hook threw:",n)}}};var R=class t{constructor(e){l(this,"config");l(this,"serverStats");l(this,"disposed",!1);this.config=this.normalizeComputeConfig(e),this.serverStats=new q(this.config.serverUrl,this.config.apiKey)}static async create(e){let r=new t(e),n=Math.max(1,(e.retry?.attempts??2)+1),s=e.retry?.baseDelayMs??250,o=e.retry?.maxDelayMs??1e3;for(let a=0;a<n;a++){if(await r.serverStats.isServerOnline())return r;if(a<n-1){let i=Math.min(s*2**a,o);await new Promise(u=>setTimeout(u,i))}}throw await r.dispose(),new f("Rhino Compute server is not online",h.NETWORK_ERROR,{context:{serverUrl:r.config.serverUrl,attempts:n}})}getConfig(){return this.ensureNotDisposed(),{...this.config}}async getIO(e){return this.ensureNotDisposed(),V(e,this.config)}async getRawIO(e){return this.ensureNotDisposed(),E(e,this.config)}async solve(e,r,n){this.ensureNotDisposed();try{if(typeof e=="string"&&!e?.trim())throw new f("Definition URL/content is required",h.INVALID_INPUT,{context:{receivedUrl:e}});if(e instanceof Uint8Array&&e.length===0)throw new f("Definition content is empty",h.INVALID_INPUT);let s={...this.config,...n?.signal!==void 0&&{signal:n.signal},...n?.timeoutMs!==void 0&&{timeoutMs:n.timeoutMs},...n?.retry!==void 0&&{retry:n.retry}},o=await D(r,e,s);if(o?.errors&&o.errors.length>0)throw new f(o.errors.join("; ")||"Computation failed",h.COMPUTATION_ERROR,{context:{definition:typeof e=="string"&&e.length<200?e:"...content...",inputs:r,errors:o.errors,warnings:o.warnings}});return o}catch(s){throw this.config.debug&&m().error("Compute failed:",s),s instanceof f?s:new f(s instanceof Error?s.message:String(s),h.COMPUTATION_ERROR,{context:{definition:typeof e=="string"&&e.length<200?e:"...content...",inputs:r},originalError:s instanceof Error?s:new Error(String(s))})}}createScheduler(e){this.ensureNotDisposed();let r=(s,o,a)=>D(o,s,a),n=(s,o,a,i)=>a===null?X(o,s,i).then(u=>({...u,missed:!1})):Z(o,a,s,i);return new C(r,this.config,e,n)}async dispose(){this.disposed||(this.disposed=!0,await this.serverStats.dispose())}ensureNotDisposed(){if(this.disposed)throw new f("GrasshopperClient has been disposed and cannot be used",h.INVALID_STATE)}normalizeComputeConfig(e){return{...e,serverUrl:_(e.serverUrl),apiKey:e.apiKey,authToken:e.authToken,debug:e.debug??!1,suppressBrowserWarning:e.suppressBrowserWarning??e.suppressClientSideWarning}}};var k=new Map;function se(t,e){k.set(t,e)}se("Rhino.Geometry.Point3d",(t,e)=>{let r=e;return!r||typeof r.X!="number"?null:new t.Point([r.X,r.Y,r.Z])});se("Rhino.Geometry.Line",(t,e)=>{let r=e;return!r||!r.From||!r.To?null:new t.Line([r.From.X,r.From.Y,r.From.Z],[r.To.X,r.To.Y,r.To.Z])});function Re(t){if(k.has(t))return k.get(t);for(let[e,r]of k)if(t.startsWith(e))return r}function Ee(t){return!t||typeof t!="object"?null:t.data??t.value??null}function oe(t,e,r){let n=Re(e);if(n)try{return n(r,t)}catch(s){m().warn(`Failed to decode Rhino type ${e}:`,s)}try{let s=Ee(t);if(s)return r.CommonObject.decode(s)}catch(s){return m().warn(`Failed to decode ${e} with CommonObject:`,s),{__decodeError:!0,type:e,raw:t}}return t}var S={STRING:"System.String",INT:"System.Int32",DOUBLE:"System.Double",BOOL:"System.Boolean"},we="Rhino.Geometry.",ve=["WebDisplay"],Ae="FileData";function ae(t){return ve.some(e=>t.includes(e))}function ie(t){if(typeof t!="string")return t;let e=t.trim();if(!(e.startsWith("{")||e.startsWith("[")||e.startsWith('"')))return t;try{let n=JSON.parse(e);if(typeof n=="string")try{return JSON.parse(n)}catch{return n}return n}catch{return t}}function Oe(t,e,r){switch(e){case S.STRING:return typeof t!="string"?t:t.replace(/^"(.*)"$/,"$1");case S.INT:return Number.parseInt(t,10);case S.DOUBLE:return Number.parseFloat(t);case S.BOOL:return String(t).toLowerCase()==="true";default:return r&&e.startsWith(we)?oe(t,e,r):t}}function ue(t,e,r,n){if(typeof t!="string")return t;let s=r?ie(t):t;return Oe(s,e,n)}function Ne(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.fileName=="string"&&typeof e.fileType=="string"&&"data"in e&&typeof e.isBase64Encoded=="boolean"&&typeof e.subFolder=="string"}function M(t,e){for(let r of Object.values(t))if(Array.isArray(r))for(let n of r)e(n)}function pe(t,e=!1,r={}){let{parseValues:n=!0,rhino:s,stringOnly:o=!1}=r,a={};for(let i of t.values)M(i.InnerTree,u=>{if(ae(u.type)||o&&u.type!==S.STRING)return;let c=e?u.id:i.ParamName;if(!c)return;let d=ue(u.data,u.type,n,s);a[c]===void 0?a[c]=d:Array.isArray(a[c])?a[c].push(d):a[c]=[a[c],d]});return{values:a}}function le(t){let e=[];for(let r of t.values)M(r.InnerTree,n=>{if(!n.type.includes(Ae))return;let s=ie(n.data);Ne(s)&&e.push(s)});return e}function L(t,e,r={}){let{parseValues:n=!0,rhino:s,stringOnly:o=!1}=r,a;if("byName"in e?a=t.values.find(u=>u.ParamName===e.byName):a=t.values.find(u=>{let c=!1;return M(u.InnerTree,d=>{d.id===e.byId&&(c=!0)}),c}),!a)return;let i=[];if(M(a.InnerTree,u=>{if("byId"in e&&u.id!==e.byId||ae(u.type)||o&&u.type!==S.STRING)return;let c=ue(u.data,u.type,n,s);i.push(c)}),i.length!==0)return i.length===1?i[0]:i}var w=class{constructor(e,r=!1){this.response=e;this.debug=r}getValues(e=!1,r={}){return pe(this.response,e,r)}getValue(e,r){return L(this.response,e,r)}getValueByParamName(e,r){return L(this.response,{byName:e},r)}getValueByParamId(e,r){return L(this.response,{byId:e},r)}async extractMeshesFromResponse(e){let r={debug:this.debug,...e},n;try{({getThreeMeshesFromComputeResponse:n}=await import("./visualization-JZLL7SOB.js"))}catch(s){throw new f("Failed to load three.js visualization module. Ensure three.js is installed as a peer dependency.",h.INVALID_STATE,{context:{originalError:s instanceof Error?s.message:String(s)}})}return n(this.response,r)}getFileData(){return le(this.response)}getAndDownloadFiles(e,r){let n=this.getFileData();O(n,e,r)}};function ce(t){return p(t,"data")}function Fe(t){return p(t,"type")}function fe(t){if(typeof t.default!="object"||t.default===null)return{schema:t};if(!j(t.default,"innerTree")){let n=`Input "${t.name??"unknown"}" default had an unrecognized shape (no innerTree key); the default was dropped.`;return m().warn("Unexpected structure in input.default:",t.default),{schema:{...t,default:null},warning:{code:"MALFORMED_DEFAULT",message:n}}}let e=p(t.default,"innerTree")??{};if(Object.keys(e).length===0)return{schema:{...t,default:void 0}};if(t.treeAccess||t.atMost&&t.atMost>1){let n={};for(let[s,o]of Object.entries(e))n[s]=o.map(a=>{let i=ce(a),u=Fe(a);if(typeof i=="string"){if(u==="System.Double"||u==="System.Int32"){let c=Number(i);return Number.isNaN(c)?i:c}if(u==="System.Boolean")return i.toLowerCase()==="true";if(u?.startsWith("Rhino.Geometry"))try{return JSON.parse(i)}catch{return i}}return i});return{schema:{...t,default:n}}}let r=[];for(let n of Object.values(e))Array.isArray(n)&&n.forEach(s=>{s&&typeof s=="object"&&j(s,"data")&&r.push(ce(s))});return r.length===0?{schema:{...t,default:void 0}}:r.length===1?{schema:{...t,default:r[0]}}:{schema:{...t,default:r}}}var U=/^\{([\d;]*)\}$/;function v(t){if(typeof t!="object"||t===null||Array.isArray(t))return!1;let e=Object.entries(t);return e.length>0&&e.every(([r,n])=>U.test(r)&&Array.isArray(n))}function I(t,e,r){if(t==null)return t;if(Array.isArray(t)){let s=t.map(e).filter(o=>o!==null);return s.length>0?s:void 0}let n=e(t);return n!==null?n:r?void 0:t}var Ge=t=>{if(typeof t=="number")return t;if(typeof t=="string"){let e=Number(t.trim());return Number.isNaN(e)?null:e}return null},Ve=t=>{if(typeof t=="boolean")return t;if(typeof t=="string"){let e=t.toLowerCase();if(e==="true")return!0;if(e==="false")return!1;throw new Error(`Invalid boolean string: "${t}"`)}return null},ke=t=>typeof t=="string"?t.startsWith('"')&&t.endsWith('"')||t.startsWith('"')?t.slice(1,-1):t:null,Me=t=>{if(typeof t=="string"){let e=t.trim();return e.startsWith('"')&&e.endsWith('"')&&(e=e.slice(1,-1).trim()),e}return null};function de(t){return e=>{if(typeof e=="object"&&e!==null)return e;if(typeof e=="string"&&e.trim()!=="")try{let r=JSON.parse(e);return typeof r=="object"&&r!==null?r:(m().warn(`Parsed value for input ${t} is not an object`),null)}catch(r){return m().warn(`Failed to parse object value "${e}" for input ${t}`,r),null}return null}}function me(t,e,r){let n=Number(t.toFixed(e));return Math.abs(t-n)<r?n:t}function Le(t,e){if(!Number.isFinite(t)||t===0)return .1;let r=Math.abs(t);if(r>=1){let y=String(t).split(".")[1];if(y&&y.length>0){let g=Math.min(y.length,12),b=Math.pow(10,-g),$=Number(b.toFixed(g));return Math.abs($-b)<e?$:b}return 1}let n=String(t),s=n.toLowerCase().match(/e(-?\d+)/);if(s){let x=Number(s[1]);if(x<0||n.toLowerCase().includes("e-")){let y=Math.abs(x),g=Math.pow(10,-y),b=Number(g.toFixed(y));return Math.abs(b-g)<e?b:g}return .1}let o=12,i=r.toFixed(o).replace(/0+$/,""),u=Math.min((i.split(".")[1]||"").length,o);if(u===0)return .1;let c=Math.pow(10,-u),d=Number(c.toFixed(u));return Math.abs(d-c)<e?d:c}function We(t,e=1e-8){let r=t.paramType==="Integer";if(v(t.default))return{default:t.default,stepSize:r?1:.1};let n=I(t.default,Ge,!0);if(r)return Array.isArray(n)?n=n.map(d=>typeof d=="number"?Math.round(d):d):typeof n=="number"&&(n=Math.round(n)),{default:n,stepSize:1};let s=Array.isArray(n)?n[0]:n,o;typeof s=="number"&&Number.isFinite(s)&&s!==0?o=s:typeof t.minimum=="number"&&Number.isFinite(t.minimum)&&t.minimum!==0?o=t.minimum:typeof t.maximum=="number"&&Number.isFinite(t.maximum)&&t.maximum!==0&&(o=t.maximum);let a=o!==void 0?Le(o,e):.1,i=0,u=String(a),c=u.toLowerCase().match(/e(-?\d+)/);if(c?i=Math.abs(Number(c[1])):i=u.split(".")[1]?.length??0,i===0&&typeof s=="number"&&s!==0&&Math.abs(s)<1){let d=Math.ceil(-Math.log10(Math.abs(s)));Number.isFinite(d)&&d>0&&(i=d)}return i=Math.min(Math.max(i,0),12),Array.isArray(n)?n=n.map(d=>typeof d=="number"?me(d,i,e):d):typeof n=="number"&&(n=me(n,i,e)),{default:n,stepSize:a}}var Be={types:["Number","Integer"],parse(t,e){let{default:r,stepSize:n}=We(t);return{...e,paramType:t.paramType,minimum:t.minimum,maximum:t.maximum,atLeast:t.atLeast,atMost:t.atMost,stepSize:n,default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:t.paramType,minimum:t.minimum,maximum:t.maximum,atLeast:t.atLeast,atMost:t.atMost,default:r?[0]:0}}},je={types:["Boolean"],parse(t,e){let r;try{r=I(t.default,Ve,!1)}catch(n){throw n instanceof Error?new f(n.message):n}return{...e,paramType:"Boolean",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Boolean",default:r?[!1]:!1}}},Ue={types:["Text"],parse(t,e){let r=I(t.default,ke,!1);return{...e,paramType:"Text",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Text",default:r?[""]:""}}},Ke={types:["ValueList"],parse(t,e){if(!t.values||typeof t.values!="object"||Object.keys(t.values).length===0)throw f.missingValues(t.nickname||"unnamed","ValueList");if(t.default!==void 0&&t.default!==null){let r=String(t.default).toLowerCase();Object.keys(t.values).some(s=>s.toLowerCase()===r)||m().warn(`ValueList input "${t.nickname||"unnamed"}" default value "${t.default}" is not in available values`)}return{...e,paramType:"ValueList",values:t.values,default:t.default}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"ValueList",values:t.values??{},default:r?[t.default]:t.default}}},he={types:["Geometry"],parse(t,e){let r=I(t.default,de(t.nickname||"unnamed"),!0);return{...e,paramType:"Geometry",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Geometry",default:r?[null]:null}}},ze={types:["File"],parse(t,e){let r=I(t.default,de(t.nickname||"unnamed"),!0);return{...e,paramType:"File",acceptedFormats:t.acceptedFormats,default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"File",default:r?[null]:null}}},$e={types:["Color"],parse(t,e){let r=I(t.default,Me,!1);return{...e,paramType:"Color",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Color",default:r?["0, 0, 0"]:"0, 0, 0"}}},_e=[Be,je,Ue,Ke,he,ze,$e],K=new Map(_e.flatMap(t=>t.types.map(e=>[e,t]))),ye=he;var qe=new Map([...K.keys()].map(t=>[t.toLowerCase(),t]));function Je(t){return qe.get(t?.toLowerCase())??t}function ge(t){return z(t).input}function z(t){let e={description:t.description,name:t.name,nickname:t.nickname,treeAccess:t.treeAccess,groupName:t.groupName??"",id:t.id},r=Je(t.paramType),{schema:n,warning:s}=fe({...t,paramType:r}),o=s&&{inputName:t.name||"unknown",paramType:r,message:s.message,code:s.code},a=K.get(r);try{if(!a)throw f.unknownParamType(r,t.name);return{input:a.parse(n,e),error:o}}catch(i){if(i instanceof f)return m().error(`Validation error for input ${t.name||"unknown"}:`,i.message),{input:(a??ye).fallback(n,e),error:{inputName:t.name||"unknown",paramType:r,message:i.message,code:i.code}};throw new f(i instanceof Error?i.message:String(i),"VALIDATION_ERROR",{context:{paramName:t.name,paramType:r},originalError:i instanceof Error?i:new Error(String(i))})}}function be(t){return W(t).inputs}function W(t){let e=[],r=[];for(let n of t){let{input:s,error:o}=z(n);e.push(s),o&&r.push(o)}return{inputs:e,parseErrors:r}}function Te(t){return{id:p(t,"id"),name:p(t,"name"),nickname:p(t,"nickname")??null,description:p(t,"description"),paramType:p(t,"paramType"),treeAccess:p(t,"treeAccess"),minimum:p(t,"minimum")??null,maximum:p(t,"maximum")??null,atLeast:p(t,"atLeast"),atMost:p(t,"atMost"),stepSize:p(t,"stepSize"),default:p(t,"default"),values:p(t,"values"),acceptedFormats:p(t,"acceptedFormats"),groupName:p(t,"groupName")??""}}function Ce(t){return{name:p(t,"name"),nickname:p(t,"nickname")??null,paramType:p(t,"paramType"),id:p(t,"id")}}async function E(t,e){let r=P(t,[]),n={};if(r.algo&&(n.algo=r.algo),r.pointer&&(n.pointer=r.pointer),!n.algo&&!n.pointer)throw new f("Definition must resolve to either a URL pointer or base64 algo",h.INVALID_INPUT,{context:{definition:t}});let s=await A("io",n,e);if(!s||typeof s!="object")throw new f("Invalid IO response structure",h.INVALID_INPUT,{context:{response:s,definition:t}});let o=Se(p(s,"warnings")),a=Se(p(s,"errors")),i=p(s,"inputs"),u=p(s,"outputs");return{inputs:Array.isArray(i)?i.map(Te):[],outputs:Array.isArray(u)?u.map(Ce):[],...o&&{loadWarnings:o},...a&&{loadErrors:a}}}function Se(t){if(!Array.isArray(t))return;let e=t.filter(r=>typeof r=="string"&&r.trim().length>0);return e.length>0?e:void 0}async function V(t,e){T("fetchParsedDefinitionIO",e.suppressBrowserWarning??e.suppressClientSideWarning);let{inputs:r,outputs:n,loadWarnings:s,loadErrors:o}=await E(t,e),{inputs:a,parseErrors:i}=W(r);return{inputs:a,outputs:n,...i.length>0&&{parseErrors:i},...s&&{loadWarnings:s},...o&&{loadErrors:o}}}var B=class t{constructor(e){l(this,"innerTree");l(this,"paramName");this.paramName=e,this.innerTree={}}append(e,r){let n=t.formatPathString(e);this.innerTree[n]||(this.innerTree[n]=[]);let s=r.map(o=>({data:t.serializeValue(o)}));return this.innerTree[n].push(...s),this}appendSingle(e,r){return this.append(e,[r])}fromDataTreeDefault(e){this.innerTree={};for(let[r,n]of Object.entries(e)){if(!Array.isArray(n))continue;let s=t.parsePathString(r);this.append(s,n)}return this}appendFlat(e){let r=Array.isArray(e)?e:[e];return this.append([0],r)}flatten(){let e=[];for(let r of Object.values(this.innerTree))if(Array.isArray(r))for(let n of r)e.push(t.deserializeValue(n.data));return e}getPaths(){return Object.keys(this.innerTree)}getPath(e){let r=t.formatPathString(e),n=this.innerTree[r];if(n)return n.map(s=>t.deserializeValue(s.data))}toComputeFormat(){return{ParamName:this.paramName,InnerTree:this.innerTree}}getInnerTree(){return this.innerTree}getParamName(){return this.paramName}static fromInputParams(e){return e.filter(r=>t.hasValidValue(r.default)).map(r=>{let n=new t(r.nickname||"unnamed"),s=r.default;if(r.treeAccess&&v(s))n.fromDataTreeDefault(s),t.isNumericInput(r)&&n.applyNumericConstraints(r.minimum,r.maximum,r.nickname||"unnamed");else{let o=Array.isArray(s)?s:[s],a=t.processValues(o,r);n.appendFlat(a)}return n.toComputeFormat()})}static fromInputParam(e){return t.hasValidValue(e.default)?t.fromInputParams([e])[0]:void 0}static replaceTreeValue(e,r,n){let s=e.length>0&&e[0]instanceof t,o=t.buildFromValue(r,n);if(s){let c=e,d=c.findIndex(x=>x.getParamName()===r);return d!==-1?c[d]=o:c.push(o),c}let a=e,i=o.toComputeFormat(),u=a.findIndex(c=>c.ParamName===r);return u!==-1?a[u]=i:a.push(i),a}static buildFromValue(e,r){let n=new t(e);return v(r)?n.fromDataTreeDefault(r):n.appendFlat(r),n}static getTreeValue(e,r){let s=e.length>0&&e[0]instanceof t?t.readFromBuilders(e,r):t.readFromDataTrees(e,r);return s===null||s.length===0?null:s.length===1?s[0]:s}static readFromBuilders(e,r){let n=e.find(s=>s.getParamName()===r);return n?n.flatten():null}static readFromDataTrees(e,r){let n=e.find(a=>a.ParamName===r);if(!n?.InnerTree)return null;let s=Object.keys(n.InnerTree)[0];if(!s)return null;let o=n.InnerTree[s];return Array.isArray(o)?o.map(a=>a?.data!==void 0?t.deserializeValue(a.data):null).filter(a=>a!==null):o?.data!==void 0?[t.deserializeValue(o.data)]:o!==void 0?[o]:null}static parsePathString(e){let r=e.match(U);return r?r[1]===""?[]:r[1].split(";").map(Number):(m().warn(`Invalid TreeBuilder path format: ${e}, using [0]`),[0])}static formatPathString(e){return`{${e.join(";")}}`}applyNumericConstraints(e,r,n){for(let s of Object.values(this.innerTree))if(Array.isArray(s))for(let o of s){let a=t.deserializeValue(o.data);if(typeof a=="number"){let i=t.clampValue(a,e,r,n);o.data=t.serializeValue(i)}}}static serializeValue(e){return typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:typeof e=="object"&&e!==null?JSON.stringify(e):String(e)}static deserializeValue(e){if(typeof e=="boolean"||typeof e=="number"||typeof e!="string")return e;if(e.startsWith("{")||e.startsWith("["))try{return JSON.parse(e)}catch{return e}return isNaN(Number(e))?e==="true"?!0:e==="false"?!1:e:Number(e)}static hasValidValue(e){return e==null?!1:typeof e=="string"?!0:!(Array.isArray(e)&&e.length===0||typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===0)}static isNumericInput(e){return e.paramType==="Number"||e.paramType==="Integer"}static processValues(e,r){return e.map(n=>t.isNumericInput(r)&&typeof n=="number"?t.clampValue(n,r.minimum,r.maximum,r.nickname||"unnamed"):n).filter(n=>n!=null)}static clampValue(e,r,n,s){let o=e;return r!=null&&o<r&&(m().warn(`${s}: ${e} below min ${r}, clamping`),o=r),n!=null&&o>n&&(m().warn(`${s}: ${e} above max ${n}, clamping`),o=n),o}};export{D as a,F as b,C as c,R as d,w as e,ge as f,be as g,E as h,V as i,B as j};
2
+ //# sourceMappingURL=chunk-YUMCH6ZU.js.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkZLBFTV7Mcjs = require('./chunk-ZLBFTV7M.cjs');var _chunkJZFH67EScjs = require('./chunk-JZFH67ES.cjs');exports.GrasshopperClient = _chunkZLBFTV7Mcjs.d; exports.GrasshopperResponseProcessor = _chunkZLBFTV7Mcjs.e; exports.RhinoComputeError = _chunkJZFH67EScjs.d; exports.SolveScheduler = _chunkZLBFTV7Mcjs.c; exports.TreeBuilder = _chunkZLBFTV7Mcjs.j; exports.downloadFileData = _chunkJZFH67EScjs.r; exports.extractFilesFromComputeResponse = _chunkJZFH67EScjs.q; exports.fetchDefinitionIO = _chunkZLBFTV7Mcjs.h; exports.fetchParsedDefinitionIO = _chunkZLBFTV7Mcjs.i; exports.hashSolveInput = _chunkZLBFTV7Mcjs.b; exports.processInput = _chunkZLBFTV7Mcjs.f; exports.processInputs = _chunkZLBFTV7Mcjs.g; exports.solveGrasshopperDefinition = _chunkZLBFTV7Mcjs.a;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkKU7ND4EVcjs = require('./chunk-KU7ND4EV.cjs');var _chunkJZFH67EScjs = require('./chunk-JZFH67ES.cjs');exports.GrasshopperClient = _chunkKU7ND4EVcjs.d; exports.GrasshopperResponseProcessor = _chunkKU7ND4EVcjs.e; exports.RhinoComputeError = _chunkJZFH67EScjs.d; exports.SolveScheduler = _chunkKU7ND4EVcjs.c; exports.TreeBuilder = _chunkKU7ND4EVcjs.j; exports.downloadFileData = _chunkJZFH67EScjs.r; exports.extractFilesFromComputeResponse = _chunkJZFH67EScjs.q; exports.fetchDefinitionIO = _chunkKU7ND4EVcjs.h; exports.fetchParsedDefinitionIO = _chunkKU7ND4EVcjs.i; exports.hashSolveInput = _chunkKU7ND4EVcjs.b; exports.processInput = _chunkKU7ND4EVcjs.f; exports.processInputs = _chunkKU7ND4EVcjs.g; exports.solveGrasshopperDefinition = _chunkKU7ND4EVcjs.a;
2
2
  //# sourceMappingURL=grasshopper.cjs.map
@@ -1,2 +1,2 @@
1
- import{a as d,b as e,c as f,d as g,e as h,f as i,g as j,h as k,i as l,j as m}from"./chunk-QAS2VM6Q.js";import{d as a,q as b,r as c}from"./chunk-XFYFC2DH.js";export{g as GrasshopperClient,h as GrasshopperResponseProcessor,a as RhinoComputeError,f as SolveScheduler,m as TreeBuilder,c as downloadFileData,b as extractFilesFromComputeResponse,k as fetchDefinitionIO,l as fetchParsedDefinitionIO,e as hashSolveInput,i as processInput,j as processInputs,d as solveGrasshopperDefinition};
1
+ import{a as d,b as e,c as f,d as g,e as h,f as i,g as j,h as k,i as l,j as m}from"./chunk-YUMCH6ZU.js";import{d as a,q as b,r as c}from"./chunk-XFYFC2DH.js";export{g as GrasshopperClient,h as GrasshopperResponseProcessor,a as RhinoComputeError,f as SolveScheduler,m as TreeBuilder,c as downloadFileData,b as extractFilesFromComputeResponse,k as fetchDefinitionIO,l as fetchParsedDefinitionIO,e as hashSolveInput,i as processInput,j as processInputs,d as solveGrasshopperDefinition};
2
2
  //# sourceMappingURL=grasshopper.js.map
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkZLBFTV7Mcjs = require('./chunk-ZLBFTV7M.cjs');var _chunkJZFH67EScjs = require('./chunk-JZFH67ES.cjs');exports.ComputeServerStats = _chunkJZFH67EScjs.j; exports.ErrorCodes = _chunkJZFH67EScjs.c; exports.GrasshopperClient = _chunkZLBFTV7Mcjs.d; exports.GrasshopperResponseProcessor = _chunkZLBFTV7Mcjs.e; exports.RhinoComputeError = _chunkJZFH67EScjs.d; exports.SolveScheduler = _chunkZLBFTV7Mcjs.c; exports.TreeBuilder = _chunkZLBFTV7Mcjs.j; exports.camelcaseKeys = _chunkJZFH67EScjs.l; exports.downloadFileData = _chunkJZFH67EScjs.r; exports.enableDebugLogging = _chunkJZFH67EScjs.g; exports.extractFilesFromComputeResponse = _chunkJZFH67EScjs.q; exports.fetchDefinitionIO = _chunkZLBFTV7Mcjs.h; exports.fetchParsedDefinitionIO = _chunkZLBFTV7Mcjs.i; exports.fetchRhinoCompute = _chunkJZFH67EScjs.h; exports.getLogger = _chunkJZFH67EScjs.e; exports.hashSolveInput = _chunkZLBFTV7Mcjs.b; exports.processInput = _chunkZLBFTV7Mcjs.f; exports.processInputs = _chunkZLBFTV7Mcjs.g; exports.setLogger = _chunkJZFH67EScjs.f; exports.solveGrasshopperDefinition = _chunkZLBFTV7Mcjs.a; exports.toCamelCase = _chunkJZFH67EScjs.k;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkKU7ND4EVcjs = require('./chunk-KU7ND4EV.cjs');var _chunkJZFH67EScjs = require('./chunk-JZFH67ES.cjs');exports.ComputeServerStats = _chunkJZFH67EScjs.j; exports.ErrorCodes = _chunkJZFH67EScjs.c; exports.GrasshopperClient = _chunkKU7ND4EVcjs.d; exports.GrasshopperResponseProcessor = _chunkKU7ND4EVcjs.e; exports.RhinoComputeError = _chunkJZFH67EScjs.d; exports.SolveScheduler = _chunkKU7ND4EVcjs.c; exports.TreeBuilder = _chunkKU7ND4EVcjs.j; exports.camelcaseKeys = _chunkJZFH67EScjs.l; exports.downloadFileData = _chunkJZFH67EScjs.r; exports.enableDebugLogging = _chunkJZFH67EScjs.g; exports.extractFilesFromComputeResponse = _chunkJZFH67EScjs.q; exports.fetchDefinitionIO = _chunkKU7ND4EVcjs.h; exports.fetchParsedDefinitionIO = _chunkKU7ND4EVcjs.i; exports.fetchRhinoCompute = _chunkJZFH67EScjs.h; exports.getLogger = _chunkJZFH67EScjs.e; exports.hashSolveInput = _chunkKU7ND4EVcjs.b; exports.processInput = _chunkKU7ND4EVcjs.f; exports.processInputs = _chunkKU7ND4EVcjs.g; exports.setLogger = _chunkJZFH67EScjs.f; exports.solveGrasshopperDefinition = _chunkKU7ND4EVcjs.a; exports.toCamelCase = _chunkJZFH67EScjs.k;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{a as d,b as g,c as h,d as i,e as j,f as k,g as l,h as n,i as q,j as s}from"./chunk-QAS2VM6Q.js";import{c as o,d as r,e,f,g as m,h as p,j as t,k as x,l as a,q as b,r as c}from"./chunk-XFYFC2DH.js";export{t as ComputeServerStats,o as ErrorCodes,i as GrasshopperClient,j as GrasshopperResponseProcessor,r as RhinoComputeError,h as SolveScheduler,s as TreeBuilder,a as camelcaseKeys,c as downloadFileData,m as enableDebugLogging,b as extractFilesFromComputeResponse,n as fetchDefinitionIO,q as fetchParsedDefinitionIO,p as fetchRhinoCompute,e as getLogger,g as hashSolveInput,k as processInput,l as processInputs,f as setLogger,d as solveGrasshopperDefinition,x as toCamelCase};
1
+ import{a as d,b as g,c as h,d as i,e as j,f as k,g as l,h as n,i as q,j as s}from"./chunk-YUMCH6ZU.js";import{c as o,d as r,e,f,g as m,h as p,j as t,k as x,l as a,q as b,r as c}from"./chunk-XFYFC2DH.js";export{t as ComputeServerStats,o as ErrorCodes,i as GrasshopperClient,j as GrasshopperResponseProcessor,r as RhinoComputeError,h as SolveScheduler,s as TreeBuilder,a as camelcaseKeys,c as downloadFileData,m as enableDebugLogging,b as extractFilesFromComputeResponse,n as fetchDefinitionIO,q as fetchParsedDefinitionIO,p as fetchRhinoCompute,e as getLogger,g as hashSolveInput,k as processInput,l as processInputs,f as setLogger,d as solveGrasshopperDefinition,x as toCamelCase};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,2 +1,2 @@
1
- import{A as u,a as e,b as r,c as o,d as t,e as a,f as s,g as p,h as i,i as n,j as m,k as l,l as f,m as y,n as d,o as h,p as x,q as C,r as g,s as M,t as c,u as B,v as j,w as E,x as D,y as O,z as b}from"./chunk-PGOKADJC.js";import"./chunk-XFYFC2DH.js";export{M as BINARY_MESH_MAGIC,c as BINARY_MESH_VERSION,i as EDGE_USERDATA_KIND,B as FLAG_FLOAT32,C as Materials,b as SCALE_FACTORS,n as addEdges,o as applyOffset,t as computeCombinedBoundingBox,a as createCameraController,s as createGrid,y as createLabelLayer,h as createMeasureTool,f as createRenderPipeline,p as createViewGizmo,u as getThreeMeshesFromComputeResponse,x as initThree,m as isEdgeOverlay,j as parseBinaryMeshBatch,r as parseColor,g as parseDisplayItems,E as parseMeshBatch,O as parseMeshBatchBlob,D as parseMeshBatchObject,l as removeEdges,d as snapToVertex,e as updateScene};
2
- //# sourceMappingURL=visualization-QMK4VTCF.js.map
1
+ import{A as u,a as e,b as r,c as o,d as t,e as a,f as s,g as p,h as i,i as n,j as m,k as l,l as f,m as y,n as d,o as h,p as x,q as C,r as g,s as M,t as c,u as B,v as j,w as E,x as D,y as O,z as b}from"./chunk-45AYUHMT.js";import"./chunk-XFYFC2DH.js";export{M as BINARY_MESH_MAGIC,c as BINARY_MESH_VERSION,i as EDGE_USERDATA_KIND,B as FLAG_FLOAT32,C as Materials,b as SCALE_FACTORS,n as addEdges,o as applyOffset,t as computeCombinedBoundingBox,a as createCameraController,s as createGrid,y as createLabelLayer,h as createMeasureTool,f as createRenderPipeline,p as createViewGizmo,u as getThreeMeshesFromComputeResponse,x as initThree,m as isEdgeOverlay,j as parseBinaryMeshBatch,r as parseColor,g as parseDisplayItems,E as parseMeshBatch,O as parseMeshBatchBlob,D as parseMeshBatchObject,l as removeEdges,d as snapToVertex,e as updateScene};
2
+ //# sourceMappingURL=visualization-JZLL7SOB.js.map
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk6YCTAJ6Ncjs = require('./chunk-6YCTAJ6N.cjs');require('./chunk-JZFH67ES.cjs');exports.BINARY_MESH_MAGIC = _chunk6YCTAJ6Ncjs.s; exports.BINARY_MESH_VERSION = _chunk6YCTAJ6Ncjs.t; exports.EDGE_USERDATA_KIND = _chunk6YCTAJ6Ncjs.h; exports.FLAG_FLOAT32 = _chunk6YCTAJ6Ncjs.u; exports.Materials = _chunk6YCTAJ6Ncjs.q; exports.SCALE_FACTORS = _chunk6YCTAJ6Ncjs.z; exports.addEdges = _chunk6YCTAJ6Ncjs.i; exports.applyOffset = _chunk6YCTAJ6Ncjs.c; exports.computeCombinedBoundingBox = _chunk6YCTAJ6Ncjs.d; exports.createCameraController = _chunk6YCTAJ6Ncjs.e; exports.createGrid = _chunk6YCTAJ6Ncjs.f; exports.createLabelLayer = _chunk6YCTAJ6Ncjs.m; exports.createMeasureTool = _chunk6YCTAJ6Ncjs.o; exports.createRenderPipeline = _chunk6YCTAJ6Ncjs.l; exports.createViewGizmo = _chunk6YCTAJ6Ncjs.g; exports.getThreeMeshesFromComputeResponse = _chunk6YCTAJ6Ncjs.A; exports.initThree = _chunk6YCTAJ6Ncjs.p; exports.isEdgeOverlay = _chunk6YCTAJ6Ncjs.j; exports.parseBinaryMeshBatch = _chunk6YCTAJ6Ncjs.v; exports.parseColor = _chunk6YCTAJ6Ncjs.b; exports.parseDisplayItems = _chunk6YCTAJ6Ncjs.r; exports.parseMeshBatch = _chunk6YCTAJ6Ncjs.w; exports.parseMeshBatchBlob = _chunk6YCTAJ6Ncjs.y; exports.parseMeshBatchObject = _chunk6YCTAJ6Ncjs.x; exports.removeEdges = _chunk6YCTAJ6Ncjs.k; exports.snapToVertex = _chunk6YCTAJ6Ncjs.n; exports.updateScene = _chunk6YCTAJ6Ncjs.a;
2
+ //# sourceMappingURL=visualization-U76H2KBD.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/visualization-YWPVPKCI.cjs"],"names":[],"mappings":"AAAA,iIAA8N,gCAA6B,owCAA+kB","file":"/home/runner/work/selva-compute/selva-compute/dist/visualization-YWPVPKCI.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/visualization-U76H2KBD.cjs"],"names":[],"mappings":"AAAA,iIAA8N,gCAA6B,owCAA+kB","file":"/home/runner/work/selva-compute/selva-compute/dist/visualization-U76H2KBD.cjs"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk7RLHTZZQcjs = require('./chunk-7RLHTZZQ.cjs');require('./chunk-JZFH67ES.cjs');exports.EDGE_USERDATA_KIND = _chunk7RLHTZZQcjs.h; exports.Materials = _chunk7RLHTZZQcjs.q; exports.SCALE_FACTORS = _chunk7RLHTZZQcjs.z; exports.addEdges = _chunk7RLHTZZQcjs.i; exports.applyOffset = _chunk7RLHTZZQcjs.c; exports.computeCombinedBoundingBox = _chunk7RLHTZZQcjs.d; exports.createCameraController = _chunk7RLHTZZQcjs.e; exports.createGrid = _chunk7RLHTZZQcjs.f; exports.createLabelLayer = _chunk7RLHTZZQcjs.m; exports.createMeasureTool = _chunk7RLHTZZQcjs.o; exports.createRenderPipeline = _chunk7RLHTZZQcjs.l; exports.createViewGizmo = _chunk7RLHTZZQcjs.g; exports.getThreeMeshesFromComputeResponse = _chunk7RLHTZZQcjs.A; exports.initThree = _chunk7RLHTZZQcjs.p; exports.isEdgeOverlay = _chunk7RLHTZZQcjs.j; exports.parseColor = _chunk7RLHTZZQcjs.b; exports.parseDisplayItems = _chunk7RLHTZZQcjs.r; exports.parseMeshBatchBlob = _chunk7RLHTZZQcjs.y; exports.parseMeshBatchObject = _chunk7RLHTZZQcjs.x; exports.removeEdges = _chunk7RLHTZZQcjs.k; exports.snapToVertex = _chunk7RLHTZZQcjs.n; exports.updateScene = _chunk7RLHTZZQcjs.a;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk6YCTAJ6Ncjs = require('./chunk-6YCTAJ6N.cjs');require('./chunk-JZFH67ES.cjs');exports.EDGE_USERDATA_KIND = _chunk6YCTAJ6Ncjs.h; exports.Materials = _chunk6YCTAJ6Ncjs.q; exports.SCALE_FACTORS = _chunk6YCTAJ6Ncjs.z; exports.addEdges = _chunk6YCTAJ6Ncjs.i; exports.applyOffset = _chunk6YCTAJ6Ncjs.c; exports.computeCombinedBoundingBox = _chunk6YCTAJ6Ncjs.d; exports.createCameraController = _chunk6YCTAJ6Ncjs.e; exports.createGrid = _chunk6YCTAJ6Ncjs.f; exports.createLabelLayer = _chunk6YCTAJ6Ncjs.m; exports.createMeasureTool = _chunk6YCTAJ6Ncjs.o; exports.createRenderPipeline = _chunk6YCTAJ6Ncjs.l; exports.createViewGizmo = _chunk6YCTAJ6Ncjs.g; exports.getThreeMeshesFromComputeResponse = _chunk6YCTAJ6Ncjs.A; exports.initThree = _chunk6YCTAJ6Ncjs.p; exports.isEdgeOverlay = _chunk6YCTAJ6Ncjs.j; exports.parseColor = _chunk6YCTAJ6Ncjs.b; exports.parseDisplayItems = _chunk6YCTAJ6Ncjs.r; exports.parseMeshBatchBlob = _chunk6YCTAJ6Ncjs.y; exports.parseMeshBatchObject = _chunk6YCTAJ6Ncjs.x; exports.removeEdges = _chunk6YCTAJ6Ncjs.k; exports.snapToVertex = _chunk6YCTAJ6Ncjs.n; exports.updateScene = _chunk6YCTAJ6Ncjs.a;
2
2
  //# sourceMappingURL=visualization.cjs.map
@@ -109,8 +109,11 @@ type MeasureConfig = {
109
109
  color?: THREE.ColorRepresentation;
110
110
  /** CSS class for the distance label. */
111
111
  labelClassName?: string;
112
- /** Format the distance number → label text. Default 3 sig-digits + " m". */
113
- format?: (distance: number) => string;
112
+ /**
113
+ * Format the measurement → label text. Receives the straight-line `distance` and per-axis `delta`.
114
+ * Default renders the total plus a Δx/Δy/Δz breakdown.
115
+ */
116
+ format?: (distance: number, delta: THREE.Vector3) => string;
114
117
  };
115
118
  type ThreeInitializerOptions = {
116
119
  sceneScale?: 'mm' | 'cm' | 'm' | 'inches' | 'feet';
@@ -178,6 +181,13 @@ interface CameraController {
178
181
  toggleProjection(): CameraProjection;
179
182
  /** Move the camera to a preset orientation, framing current scene content. Animated. */
180
183
  setView(preset: ViewPreset, animate?: boolean): void;
184
+ /**
185
+ * Frame current content viewed from `direction` (a world-space vector from target toward camera).
186
+ * Like {@link setView} but takes an explicit direction — used by the nav-cube, whose clicked axis
187
+ * is a world axis, not a named preset. Pole directions are nudged off-axis to avoid the orbit
188
+ * singularity.
189
+ */
190
+ setViewDirection(direction: THREE.Vector3, animate?: boolean): void;
181
191
  /** Enable/disable orbit rotation at runtime (pan/zoom unaffected). */
182
192
  setRotateEnabled(enabled: boolean): void;
183
193
  /** Whether rotation is currently enabled. */
@@ -191,6 +201,12 @@ interface CameraControllerDeps {
191
201
  controls: OrbitControls;
192
202
  /** Called whenever the active camera identity changes, so callers can re-point the renderer/raycaster. */
193
203
  onActiveCameraChange: (camera: THREE.Camera) => void;
204
+ /**
205
+ * The scene's up axis. Presets, the orthographic camera's up, and the iso direction are all derived
206
+ * from this so the controller is correct in any up convention (Three's native Y-up, Rhino's Z-up, …)
207
+ * without hardcoding an axis. Defaults to Y-up.
208
+ */
209
+ up?: THREE.Vector3;
194
210
  }
195
211
  declare function createCameraController(deps: CameraControllerDeps): CameraController;
196
212
 
@@ -230,21 +246,21 @@ interface Grid {
230
246
  declare function createGrid(options?: GridOptions): Grid;
231
247
 
232
248
  /**
233
- * The corner nav-cube/axis gizmo. Wraps three's {@link ViewHelper} (the standard, well-tested
234
- * widget) and uses its built-in click animate behavior, which we keep rather than reimplement:
235
- * ViewHelper's hit-test depends on private internals (`dim`, `interactiveObjects`, viewport math),
236
- * so replicating it is fragile. We let it drive the perspective camera directly.
249
+ * The corner nav-cube/axis gizmo. Uses three's {@link ViewHelper} purely as the rendered widget, but
250
+ * NOT its click→animate behavior: ViewHelper's built-in snap assumes a Y-up world and animates the
251
+ * camera straight onto the up axis, which in our Z-up scene rolls the view and makes the gizmo jitter
252
+ * at the pole. Instead we hit-test the axis sprites ourselves and drive the viewer's up-aware camera
253
+ * controller, which snaps (no animation) with a pole nudge so the orbit basis never degenerates.
237
254
  *
238
- * Two integration points with the viewer's dual-camera setup:
239
- * 1. Before each click we point `helper.center` at the live orbit target, so the snap rotates about
240
- * what the user is looking at (not the world origin).
241
- * 2. ViewHelper only drives the perspective camera. The nav cube is inherently a 3D-orientation
242
- * tool, so if the viewer is in orthographic (2D) mode when the gizmo is clicked, we first flip
243
- * back to perspective — then ViewHelper animates as usual. Using the cube returns you to 3D.
255
+ * Integration points with the viewer's dual-camera setup:
256
+ * 1. The snap frames the current orbit target via the controller, so it rotates about what the user
257
+ * is looking at (not the world origin).
258
+ * 2. The nav cube is inherently a 3D-orientation tool, so if the viewer is in orthographic (2D) mode
259
+ * when the gizmo is clicked, we first flip back to perspective.
244
260
  *
245
261
  * Caller responsibilities (mirror ViewHelper's own contract):
246
262
  * - call {@link ViewGizmo.render} *after* the main scene render each frame (overlay viewport),
247
- * - call {@link ViewGizmo.update} each frame with the frame delta (drives the snap animation),
263
+ * - call {@link ViewGizmo.update} each frame (no-op now; kept for API symmetry),
248
264
  * - forward pointer clicks to {@link ViewGizmo.handleClick}.
249
265
  */
250
266
  interface ViewGizmo {
@@ -259,10 +275,9 @@ interface ViewGizmo {
259
275
  dispose(): void;
260
276
  }
261
277
  interface ViewGizmoDeps {
262
- /** The perspective (primary) camera ViewHelper orients and animates. */
278
+ /** The perspective (primary) camera the gizmo visualizes and re-orients. */
263
279
  camera: THREE.PerspectiveCamera;
264
280
  domElement: HTMLElement;
265
- controls: OrbitControls;
266
281
  controller: CameraController;
267
282
  }
268
283
  declare function createViewGizmo(deps: ViewGizmoDeps): ViewGizmo;
@@ -321,6 +336,12 @@ interface MeasureTool {
321
336
  isEnabled(): boolean;
322
337
  /** Process a click. Returns true if the tool consumed it (caller should not also select). */
323
338
  handleClick(event: MouseEvent): boolean;
339
+ /**
340
+ * Process pointer movement to preview the next snap point — a ghost marker tracks the cursor and
341
+ * jumps to the vertex a click would snap to, so users can aim before committing. No-op when the
342
+ * tool is disabled. The caller forwards mousemove; nothing is consumed.
343
+ */
344
+ handleMove(event: MouseEvent): void;
324
345
  /** Clear the current measurement (markers, line, label). */
325
346
  clear(): void;
326
347
  dispose(): void;
@@ -332,8 +353,12 @@ interface MeasureOptions {
332
353
  color?: THREE.ColorRepresentation;
333
354
  /** CSS class applied to the distance label, for styling. */
334
355
  labelClassName?: string;
335
- /** Format the distance number → label text. Default: 3 significant digits + " m". */
336
- format?: (distance: number) => string;
356
+ /**
357
+ * Format the measurement → label text. Receives the straight-line `distance` and the per-axis
358
+ * `delta` (|b − a| on each axis). May return multi-line text or HTML; the default renders the
359
+ * total plus a Δx/Δy/Δz breakdown. Old `(distance) => string` callbacks remain valid.
360
+ */
361
+ format?: (distance: number, delta: THREE.Vector3) => string;
337
362
  }
338
363
  interface MeasureDeps {
339
364
  canvas: HTMLCanvasElement;
@@ -109,8 +109,11 @@ type MeasureConfig = {
109
109
  color?: THREE.ColorRepresentation;
110
110
  /** CSS class for the distance label. */
111
111
  labelClassName?: string;
112
- /** Format the distance number → label text. Default 3 sig-digits + " m". */
113
- format?: (distance: number) => string;
112
+ /**
113
+ * Format the measurement → label text. Receives the straight-line `distance` and per-axis `delta`.
114
+ * Default renders the total plus a Δx/Δy/Δz breakdown.
115
+ */
116
+ format?: (distance: number, delta: THREE.Vector3) => string;
114
117
  };
115
118
  type ThreeInitializerOptions = {
116
119
  sceneScale?: 'mm' | 'cm' | 'm' | 'inches' | 'feet';
@@ -178,6 +181,13 @@ interface CameraController {
178
181
  toggleProjection(): CameraProjection;
179
182
  /** Move the camera to a preset orientation, framing current scene content. Animated. */
180
183
  setView(preset: ViewPreset, animate?: boolean): void;
184
+ /**
185
+ * Frame current content viewed from `direction` (a world-space vector from target toward camera).
186
+ * Like {@link setView} but takes an explicit direction — used by the nav-cube, whose clicked axis
187
+ * is a world axis, not a named preset. Pole directions are nudged off-axis to avoid the orbit
188
+ * singularity.
189
+ */
190
+ setViewDirection(direction: THREE.Vector3, animate?: boolean): void;
181
191
  /** Enable/disable orbit rotation at runtime (pan/zoom unaffected). */
182
192
  setRotateEnabled(enabled: boolean): void;
183
193
  /** Whether rotation is currently enabled. */
@@ -191,6 +201,12 @@ interface CameraControllerDeps {
191
201
  controls: OrbitControls;
192
202
  /** Called whenever the active camera identity changes, so callers can re-point the renderer/raycaster. */
193
203
  onActiveCameraChange: (camera: THREE.Camera) => void;
204
+ /**
205
+ * The scene's up axis. Presets, the orthographic camera's up, and the iso direction are all derived
206
+ * from this so the controller is correct in any up convention (Three's native Y-up, Rhino's Z-up, …)
207
+ * without hardcoding an axis. Defaults to Y-up.
208
+ */
209
+ up?: THREE.Vector3;
194
210
  }
195
211
  declare function createCameraController(deps: CameraControllerDeps): CameraController;
196
212
 
@@ -230,21 +246,21 @@ interface Grid {
230
246
  declare function createGrid(options?: GridOptions): Grid;
231
247
 
232
248
  /**
233
- * The corner nav-cube/axis gizmo. Wraps three's {@link ViewHelper} (the standard, well-tested
234
- * widget) and uses its built-in click animate behavior, which we keep rather than reimplement:
235
- * ViewHelper's hit-test depends on private internals (`dim`, `interactiveObjects`, viewport math),
236
- * so replicating it is fragile. We let it drive the perspective camera directly.
249
+ * The corner nav-cube/axis gizmo. Uses three's {@link ViewHelper} purely as the rendered widget, but
250
+ * NOT its click→animate behavior: ViewHelper's built-in snap assumes a Y-up world and animates the
251
+ * camera straight onto the up axis, which in our Z-up scene rolls the view and makes the gizmo jitter
252
+ * at the pole. Instead we hit-test the axis sprites ourselves and drive the viewer's up-aware camera
253
+ * controller, which snaps (no animation) with a pole nudge so the orbit basis never degenerates.
237
254
  *
238
- * Two integration points with the viewer's dual-camera setup:
239
- * 1. Before each click we point `helper.center` at the live orbit target, so the snap rotates about
240
- * what the user is looking at (not the world origin).
241
- * 2. ViewHelper only drives the perspective camera. The nav cube is inherently a 3D-orientation
242
- * tool, so if the viewer is in orthographic (2D) mode when the gizmo is clicked, we first flip
243
- * back to perspective — then ViewHelper animates as usual. Using the cube returns you to 3D.
255
+ * Integration points with the viewer's dual-camera setup:
256
+ * 1. The snap frames the current orbit target via the controller, so it rotates about what the user
257
+ * is looking at (not the world origin).
258
+ * 2. The nav cube is inherently a 3D-orientation tool, so if the viewer is in orthographic (2D) mode
259
+ * when the gizmo is clicked, we first flip back to perspective.
244
260
  *
245
261
  * Caller responsibilities (mirror ViewHelper's own contract):
246
262
  * - call {@link ViewGizmo.render} *after* the main scene render each frame (overlay viewport),
247
- * - call {@link ViewGizmo.update} each frame with the frame delta (drives the snap animation),
263
+ * - call {@link ViewGizmo.update} each frame (no-op now; kept for API symmetry),
248
264
  * - forward pointer clicks to {@link ViewGizmo.handleClick}.
249
265
  */
250
266
  interface ViewGizmo {
@@ -259,10 +275,9 @@ interface ViewGizmo {
259
275
  dispose(): void;
260
276
  }
261
277
  interface ViewGizmoDeps {
262
- /** The perspective (primary) camera ViewHelper orients and animates. */
278
+ /** The perspective (primary) camera the gizmo visualizes and re-orients. */
263
279
  camera: THREE.PerspectiveCamera;
264
280
  domElement: HTMLElement;
265
- controls: OrbitControls;
266
281
  controller: CameraController;
267
282
  }
268
283
  declare function createViewGizmo(deps: ViewGizmoDeps): ViewGizmo;
@@ -321,6 +336,12 @@ interface MeasureTool {
321
336
  isEnabled(): boolean;
322
337
  /** Process a click. Returns true if the tool consumed it (caller should not also select). */
323
338
  handleClick(event: MouseEvent): boolean;
339
+ /**
340
+ * Process pointer movement to preview the next snap point — a ghost marker tracks the cursor and
341
+ * jumps to the vertex a click would snap to, so users can aim before committing. No-op when the
342
+ * tool is disabled. The caller forwards mousemove; nothing is consumed.
343
+ */
344
+ handleMove(event: MouseEvent): void;
324
345
  /** Clear the current measurement (markers, line, label). */
325
346
  clear(): void;
326
347
  dispose(): void;
@@ -332,8 +353,12 @@ interface MeasureOptions {
332
353
  color?: THREE.ColorRepresentation;
333
354
  /** CSS class applied to the distance label, for styling. */
334
355
  labelClassName?: string;
335
- /** Format the distance number → label text. Default: 3 significant digits + " m". */
336
- format?: (distance: number) => string;
356
+ /**
357
+ * Format the measurement → label text. Receives the straight-line `distance` and the per-axis
358
+ * `delta` (|b − a| on each axis). May return multi-line text or HTML; the default renders the
359
+ * total plus a Δx/Δy/Δz breakdown. Old `(distance) => string` callbacks remain valid.
360
+ */
361
+ format?: (distance: number, delta: THREE.Vector3) => string;
337
362
  }
338
363
  interface MeasureDeps {
339
364
  canvas: HTMLCanvasElement;
@@ -1,2 +1,2 @@
1
- import{A as j,a as e,b as r,c as t,d as o,e as i,f as a,g as s,h as p,i as n,j as l,k as f,l as m,m as y,n as u,o as d,p as x,q as C,r as g,x as h,y as c,z as v}from"./chunk-PGOKADJC.js";import"./chunk-XFYFC2DH.js";export{p as EDGE_USERDATA_KIND,C as Materials,v as SCALE_FACTORS,n as addEdges,t as applyOffset,o as computeCombinedBoundingBox,i as createCameraController,a as createGrid,y as createLabelLayer,d as createMeasureTool,m as createRenderPipeline,s as createViewGizmo,j as getThreeMeshesFromComputeResponse,x as initThree,l as isEdgeOverlay,r as parseColor,g as parseDisplayItems,c as parseMeshBatchBlob,h as parseMeshBatchObject,f as removeEdges,u as snapToVertex,e as updateScene};
1
+ import{A as j,a as e,b as r,c as t,d as o,e as i,f as a,g as s,h as p,i as n,j as l,k as f,l as m,m as y,n as u,o as d,p as x,q as C,r as g,x as h,y as c,z as v}from"./chunk-45AYUHMT.js";import"./chunk-XFYFC2DH.js";export{p as EDGE_USERDATA_KIND,C as Materials,v as SCALE_FACTORS,n as addEdges,t as applyOffset,o as computeCombinedBoundingBox,i as createCameraController,a as createGrid,y as createLabelLayer,d as createMeasureTool,m as createRenderPipeline,s as createViewGizmo,j as getThreeMeshesFromComputeResponse,x as initThree,l as isEdgeOverlay,r as parseColor,g as parseDisplayItems,c as parseMeshBatchBlob,h as parseMeshBatchObject,f as removeEdges,u as snapToVertex,e as updateScene};
2
2
  //# sourceMappingURL=visualization.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selvajs/compute",
3
- "version": "2.1.0-beta.3",
3
+ "version": "2.1.0-beta.4",
4
4
  "description": "TypeScript library for Rhino Compute Server - Grasshopper and RhinoCommon",
5
5
  "author": "VektorNode",
6
6
  "license": "MIT",