calcplot 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/dist/calcplot-client-deno.js +1 -0
- package/dist/calcplot-client-deno.js.map +7 -0
- package/dist/calcplot-client.js +1 -0
- package/dist/calcplot-client.js.map +7 -0
- package/dist/calcplot.js +33 -0
- package/dist/index.js +33 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Vadim Kudriavtsev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# calcplot
|
|
2
|
+
|
|
3
|
+
> Interactive numerical simulations with beautiful visualizations for TypeScript/JavaScript
|
|
4
|
+
|
|
5
|
+
Declarative API for solving differential equations and creating interactive plots - inspired by Mathematica's Manipulate and SageMath's @interact, but lightweight and web-native.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🧮 **RK4 Solver** with automatic event detection (zero-crossing with bisection)
|
|
10
|
+
- 📊 **Composable visualizations** - scenes, plots, vectors, multiple views
|
|
11
|
+
- 🎛️ **Interactive controls** - sliders update simulations in real-time
|
|
12
|
+
- 🚀 **Works everywhere** - Deno Jupyter, Node.js, browser
|
|
13
|
+
- 📦 **Self-contained output** - generates single HTML file with everything embedded
|
|
14
|
+
- 🎨 **Smart defaults** - auto-calculated bounds
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
```bash
|
|
18
|
+
npm install calcplot
|
|
19
|
+
# or
|
|
20
|
+
deno add calcplot
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
```typescript
|
|
25
|
+
const ballisticModel = defineIVP({
|
|
26
|
+
state: { x: 0, y: 0, vx: 0, vy: 0 },
|
|
27
|
+
params: { g: 9.81, k: 0 },
|
|
28
|
+
derivatives: {
|
|
29
|
+
x: (s) => s.vx,
|
|
30
|
+
y: (s) => s.vy,
|
|
31
|
+
vx: (s, p) => -p.k * s.vx,
|
|
32
|
+
vy: (s, p) => -p.g - p.k * s.vy
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
explore(
|
|
37
|
+
ballisticModel,
|
|
38
|
+
{
|
|
39
|
+
params: {
|
|
40
|
+
v0: slider(5, 50, 20, 'Initial Speed (m/s)'),
|
|
41
|
+
angle: slider(0, 90, 45, 'Angle (°)'),
|
|
42
|
+
k: slider(0, 0.5, 0.1, 'Air Resistance')
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
initial: (p) => {
|
|
46
|
+
const rad = (p.angle * Math.PI) / 180;
|
|
47
|
+
return {
|
|
48
|
+
x: 0,
|
|
49
|
+
y: 0,
|
|
50
|
+
vx: p.v0 * Math.cos(rad),
|
|
51
|
+
vy: p.v0 * Math.sin(rad)
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
view: [
|
|
56
|
+
// First view: trajectory plot
|
|
57
|
+
view()
|
|
58
|
+
.plot((s) => [s.x, s.y], { color: 'blue', label: 'Trajectory' })
|
|
59
|
+
.grid()
|
|
60
|
+
.axis({ x: 'Range (m)', y: 'Height (m)', aspectRatio: 'equal' }),
|
|
61
|
+
|
|
62
|
+
// Second view: velocity and height over time
|
|
63
|
+
view()
|
|
64
|
+
.plot((s) => Math.sqrt(s.vx ** 2 + s.vy ** 2), { color: 'red', label: 'Velocity' })
|
|
65
|
+
.plot((s) => s.y, { color: 'green', label: 'Height' })
|
|
66
|
+
.grid()
|
|
67
|
+
.axis({ x: 'Time (s)', y: 'Value' })
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## API Overview
|
|
76
|
+
|
|
77
|
+
### Core Functions
|
|
78
|
+
|
|
79
|
+
- `defineIVP(config)` - Define initial value problem
|
|
80
|
+
- `explore(model, config)` - Interactive exploration with controls
|
|
81
|
+
- `show(timeline, view)` - Static visualization (no controls)
|
|
82
|
+
- `simulate(model)` - Programmatic simulation
|
|
83
|
+
|
|
84
|
+
### Controls
|
|
85
|
+
|
|
86
|
+
- `slider(min, max, default, label?, step?)`
|
|
87
|
+
- `checkbox(default, label?)`
|
|
88
|
+
|
|
89
|
+
### View Builders
|
|
90
|
+
|
|
91
|
+
- `canvas(options?)` - Create canvas view
|
|
92
|
+
- `plot(selector, options?)` - Add plot layer
|
|
93
|
+
- `scene(drawFn)` - Custom drawing
|
|
94
|
+
- `grid(options?)` - Grid layer
|
|
95
|
+
- `axis(options?)` - Axes with labels
|
|
96
|
+
- `vector(at, dir, options?)` - Arrow vectors
|
|
97
|
+
- `marker(at, options?)` - Point marker
|
|
98
|
+
|
|
99
|
+
### Draw Context (in `scene()`)
|
|
100
|
+
|
|
101
|
+
- `ctx.line(from, to, options?)`
|
|
102
|
+
- `ctx.circle(center, radius, options?)`
|
|
103
|
+
- `ctx.arrow(from, to, options?)`
|
|
104
|
+
- `ctx.text(pos, text, options?)`
|
|
105
|
+
- `ctx.rect(topLeft, width, height, options?)`
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Comparison
|
|
110
|
+
|
|
111
|
+
| Feature | calcplot | SciPy | Mathematica | SageMath |
|
|
112
|
+
|---------|----------|-------|-------------|----------|
|
|
113
|
+
| Language | TypeScript/JS | Python | Wolfram | Python |
|
|
114
|
+
| ODE Solver | ✅ RK4 | ✅ Many | ✅ Many | ✅ Many |
|
|
115
|
+
| Event Detection | ✅ Built-in | ✅ Manual | ✅ Built-in | ⚠️ Limited |
|
|
116
|
+
| Interactive UI | ✅ Auto | ❌ Manual | ✅ Manipulate | ✅ @interact |
|
|
117
|
+
| Visualization | ✅ Built-in | ❌ Separate | ✅ Built-in | ✅ Built-in |
|
|
118
|
+
| Web Native | ✅ Yes | ❌ No | ❌ Desktop | ❌ Server |
|
|
119
|
+
| Output | HTML file | Code | Notebook | Notebook |
|
|
120
|
+
| License | MIT | BSD | Proprietary | GPL |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Development
|
|
125
|
+
```bash
|
|
126
|
+
# Install
|
|
127
|
+
npm install
|
|
128
|
+
|
|
129
|
+
# Build client runtime
|
|
130
|
+
npm run build
|
|
131
|
+
|
|
132
|
+
# Watch mode
|
|
133
|
+
npm run dev
|
|
134
|
+
|
|
135
|
+
# Run examples
|
|
136
|
+
npm run example
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT © Vadim Kudriavtsev
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var b=class{static parseFunction(t){let e=t.trim(),i=e.match(/^\(([^)]+)\)\s*=>\s*\{([\s\S]*)\}$/);if(i)return i[2].trim();let n=e.match(/^(\w+)\s*=>\s*\{([\s\S]*)\}$/);if(n)return n[2].trim();let r=e.match(/^\(([^)]+)\)\s*=>\s*(.+)$/s);if(r)return`return ${r[2].trim()}`;let s=e.match(/^(\w+)\s*=>\s*(.+)$/s);if(s)return`return ${s[2].trim()}`;let c=e.match(/^function\s*\([^)]*\)\s*\{([\s\S]*)\}$/);return c?c[1].trim():e}static createFunction(t,e){return new Function(...t,e)}static parseAndCreateFunction(t,e){let i=this.parseFunction(e);return this.createFunction(t,i)}};function _(u){return{state:u.state,params:u.params,derivatives:D(u.derivatives),events:u.events?D(u.events):void 0}}function X(u){let t={};for(let[e,i]of Object.entries(u))t[e]={type:i.type||"slider",min:i.min,max:i.max,default:i.default,label:i.label||e,step:i.step||.01};return t}function J(u){return{times:u.times,states:u.states}}function K(u){let t={};for(let[e,i]of Object.entries(u))t[e]=i.default;return t}function Q(serialized){let functions={};for(let[key,fnStr]of Object.entries(serialized))try{fnStr.includes("=>")?functions[key]=eval(`(${fnStr})`):fnStr.startsWith("function")?functions[key]=eval(`(${fnStr})`):functions[key]=eval(`(state, params) => ${fnStr}`)}catch(u){console.error("Error deserializing function",key,u),functions[key]=()=>0}return functions}function D(u){let t={};for(let[e,i]of Object.entries(u))typeof i=="function"?t[e]=i.toString():typeof i=="object"&&i!==null?t[e]=JSON.stringify(i):t[e]=String(i);return t}var R=class{constructor(t){this.log=t}simulateTrajectory(t,e,i){if(!e||typeof e!="object")throw new Error(`Invalid initialState: expected object, got ${typeof e}. Value: ${e}`);let s={...t.model?.params||{},...i||{}},{dt:c=.01,maxTime:a=10}=t.options||{},o=[],l={};Object.keys(e).forEach(p=>{l[p]=[]});let h={...e},d=0,f=t.model?.derivatives||t.derivatives;if(!f)throw new Error("No derivatives found in data.model.derivatives or data.derivatives");let x={};for(Object.entries(f).forEach(([p,m])=>{x[p]=b.parseAndCreateFunction(["s","p"],m)});d<=a&&h.y>=0;){o.push(d),Object.keys(h).forEach(m=>{l[m].push(h[m])});let p={};Object.entries(x).forEach(([m,v])=>{p[m]=v(h,s)}),Object.keys(h).forEach(m=>{p[m]!==void 0&&(h[m]+=p[m]*c)}),d+=c}return{times:o,states:l}}parseInitialFunction(t){try{return b.parseAndCreateFunction(["p"],t)}catch(e){throw console.error("\u274C parseInitialFunction error:",e),e}}};var k=class{constructor(t,e,i=.1){this.canvasWidth=t;this.canvasHeight=e;this.padding=i;this.dataBounds={x:[0,1],y:[0,1]};this.viewBounds={x:[0,1],y:[0,1]};this.plotArea=this.calculateDefaultPlotArea(),this.originalViewBounds={...this.viewBounds}}calculateDefaultPlotArea(){let e=this.canvasWidth-50,i=50,n=this.canvasHeight-80;return{left:80,top:i,right:e,bottom:n,width:e-80,height:n-i}}updateDataBounds(t,e){if(t.length===0||e.length===0)return;let i=Math.min(...t),n=Math.max(...t),r=Math.min(...e),s=Math.max(...e);i===n?this.dataBounds.x=[i-1,n+1]:this.dataBounds.x=[i,n],r===s?this.dataBounds.y=[r-1,s+1]:this.dataBounds.y=[r,s]}autoScale(){let[t,e]=this.dataBounds.x,[i,n]=this.dataBounds.y,r=e-t||1,s=n-i||1;this.originalViewBounds={x:[t-r*this.padding,e+r*this.padding],y:[i-s*this.padding,n+s*this.padding]},this.viewBounds={...this.originalViewBounds}}adjustAspectRatio(t="auto"){if(t==="auto"){this.originalViewBounds&&(this.viewBounds={...this.originalViewBounds});return}let[e,i]=this.viewBounds.x,[n,r]=this.viewBounds.y,s=i-e,c=r-n;if(s===0||c===0)return;let a=this.plotArea.width/s,o=this.plotArea.height/c;if(a!==o)if(a<o){let l=s*(this.plotArea.height/this.plotArea.width),h=(n+r)/2;this.viewBounds.y=[h-l/2,h+l/2]}else{let l=c*(this.plotArea.width/this.plotArea.height),h=(e+i)/2;this.viewBounds.x=[h-l/2,h+l/2]}}toCanvas(t,e){let[i,n]=this.viewBounds.x,[r,s]=this.viewBounds.y,c=n-i||1,a=s-r||1,o=this.plotArea.left+(t-i)/c*this.plotArea.width,l=this.plotArea.bottom-(e-r)/a*this.plotArea.height;return[o,l]}getViewBounds(){return{...this.viewBounds}}getPlotArea(){return{...this.plotArea}}setViewBounds(t){this.viewBounds={...t},this.originalViewBounds={...t}}updatePlotArea(t){this.plotArea={...this.plotArea,...t,width:(t.right??this.plotArea.right)-(t.left??this.plotArea.left),height:(t.bottom??this.plotArea.bottom)-(t.top??this.plotArea.top)}}isInPlotArea(t,e){let[i,n]=this.toCanvas(t,e);return i>=this.plotArea.left&&i<=this.plotArea.right&&n>=this.plotArea.top&&n<=this.plotArea.bottom}getDataCenter(){let[t,e]=this.dataBounds.x,[i,n]=this.dataBounds.y;return[(t+e)/2,(i+n)/2]}};var y=class{static calculateNiceStep(t,e){if(t<=0)return 1;let i=t/e,n=Math.floor(Math.log10(i)),r=i/Math.pow(10,n),s;return r<=1.5?s=1:r<=3?s=2:r<=7?s=5:s=10,s*Math.pow(10,n)}static formatTickLabel(t,e){if(e>=1e3||e<.01&&e>0)return t.toExponential(1);let i=0;return e<1&&(i=Math.ceil(-Math.log10(e))),t.toFixed(i).replace(/\.0+$/,"")}static interpolateData(t,e,i=100){if(t.length<2)return{x:t,y:e};let n=[],r=[];for(let s=0;s<i;s++){let a=s/(i-1)*(t.length-1),o=Math.floor(a),l=Math.min(o+1,t.length-1),h=a-o;n.push(t[o]*(1-h)+t[l]*h),r.push(e[o]*(1-h)+e[l]*h)}return{x:n,y:r}}static getColorByIndex(t){let e=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#14b8a6","#f97316"];return e[t%e.length]}};var E=class{constructor(t,e,i,n){this.ctx=t;this.getBounds=e;this.toCanvas=i;this.getPlotArea=n}drawGrid(t={}){let{showGrid:e=!0,gridColor:i="#e0e0e0"}=t;if(!e)return;let n=this.getBounds(),r=this.getPlotArea(),{xTicks:s,yTicks:c}=this.calculateTicks();this.ctx.save(),this.ctx.strokeStyle=i,this.ctx.lineWidth=1,this.ctx.setLineDash([2,2]),s.values.forEach(a=>{if(a===0)return;let[o,l]=this.toCanvas(a,n.y[0]),[,h]=this.toCanvas(a,n.y[1]);this.ctx.beginPath(),this.ctx.moveTo(o,Math.max(l,r.top)),this.ctx.lineTo(o,Math.min(h,r.bottom)),this.ctx.stroke()}),c.values.forEach(a=>{if(a===0)return;let[o,l]=this.toCanvas(n.x[0],a),[h]=this.toCanvas(n.x[1],a);this.ctx.beginPath(),this.ctx.moveTo(Math.max(o,r.left),l),this.ctx.lineTo(Math.min(h,r.right),l),this.ctx.stroke()}),this.ctx.restore()}drawAxes(t,e,i={}){let{showTicks:n=!0,showLabels:r=!0}=i,{xTicks:s,yTicks:c}=this.calculateTicks();this.ctx.save(),this.ctx.strokeStyle="#666",this.ctx.fillStyle="#666",this.ctx.lineWidth=2,this.ctx.font="12px sans-serif";let[a,o]=this.toCanvas(0,0),[l,h]=this.toCanvas(0,0),d=this.getPlotArea();o>=d.top&&o<=d.bottom&&(this.ctx.beginPath(),this.ctx.moveTo(d.left,o),this.ctx.lineTo(d.right,o),this.ctx.stroke()),l>=d.left&&l<=d.right&&(this.ctx.beginPath(),this.ctx.moveTo(l,d.top),this.ctx.lineTo(l,d.bottom),this.ctx.stroke()),(n||r)&&(this.ctx.textAlign="center",this.ctx.textBaseline="top",s.values.forEach(f=>{let[x,p]=this.toCanvas(f,0),m=this.getPlotArea();x>=m.left&&x<=m.right&&(n&&(this.ctx.beginPath(),this.ctx.moveTo(x,p-5),this.ctx.lineTo(x,p+5),this.ctx.stroke()),r&&f!==0&&this.ctx.fillText(s.labels[s.values.indexOf(f)],x,p+10))}),this.ctx.textAlign="right",this.ctx.textBaseline="middle",c.values.forEach(f=>{let[x,p]=this.toCanvas(0,f),m=this.getPlotArea();p>=m.top&&p<=m.bottom&&(n&&(this.ctx.beginPath(),this.ctx.moveTo(x-5,p),this.ctx.lineTo(x+5,p),this.ctx.stroke()),r&&f!==0&&this.ctx.fillText(c.labels[c.values.indexOf(f)],x-10,p))})),this.ctx.restore(),(t||e)&&(this.ctx.save(),this.ctx.fillStyle="#333",this.ctx.font="14px sans-serif",t&&(this.ctx.textAlign="center",this.ctx.textBaseline="top",this.ctx.fillText(t,d.left+d.width/2,d.bottom+40)),e&&(this.ctx.save(),this.ctx.textAlign="center",this.ctx.translate(25,d.top+d.height/2),this.ctx.rotate(-Math.PI/2),this.ctx.fillText(e,0,0),this.ctx.restore()),this.ctx.restore())}calculateTicks(){let t=this.getBounds(),e=t.x[1]-t.x[0],i=t.y[1]-t.y[0],n=y.calculateNiceStep(e,6),r=y.calculateNiceStep(i,5),s=Math.ceil(t.x[0]/n)*n,c=Math.ceil(t.y[0]/r)*r,a=[],o=[];for(let l=s;l<=t.x[1];l+=n)a.push(l);for(let l=c;l<=t.y[1];l+=r)o.push(l);return{xTicks:{values:a,labels:a.map(l=>y.formatTickLabel(l,n)),step:n},yTicks:{values:o,labels:o.map(l=>y.formatTickLabel(l,r)),step:r}}}};var z=class{constructor(t,e,i){this.ctx=t;this.toCanvas=e;this.getPlotArea=i}plot(t,e,i={}){if(t.length===0)return;let{lineColor:n="#3b82f6",lineWidth:r=2,marker:s="none",smooth:c=!0}=i;this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(this.getPlotArea().left,this.getPlotArea().top,this.getPlotArea().width,this.getPlotArea().height),this.ctx.clip(),this.ctx.strokeStyle=n,this.ctx.fillStyle=n,this.ctx.lineWidth=r,this.ctx.lineJoin="round",this.ctx.lineCap="round";let a=c&&t.length>2?y.interpolateData(t,e):{x:t,y:e};this.ctx.beginPath();for(let o=0;o<a.x.length;o++){let[l,h]=this.toCanvas(a.x[o],a.y[o]);o===0?this.ctx.moveTo(l,h):this.ctx.lineTo(l,h)}if(this.ctx.stroke(),s!=="none")for(let o=0;o<t.length;o++){let[l,h]=this.toCanvas(t[o],e[o]);s==="circle"?(this.ctx.beginPath(),this.ctx.arc(l,h,3,0,Math.PI*2),this.ctx.fill()):s==="square"&&this.ctx.fillRect(l-3,h-3,6,6)}this.ctx.restore()}drawVectors(t,e,i,n,r={}){let{scale:s=this.calculateAutoScale(i,n),color:c="#10b981",headSize:a=8}=r;this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(this.getPlotArea().left,this.getPlotArea().top,this.getPlotArea().width,this.getPlotArea().height),this.ctx.clip(),this.ctx.strokeStyle=c,this.ctx.fillStyle=c,this.ctx.lineWidth=2;for(let o=0;o<t.length;o++){let l=this.toCanvas(t[o],e[o]),h=this.toCanvas(t[o]+i[o]/s,e[o]+n[o]/s);this.ctx.beginPath(),this.ctx.moveTo(l[0],l[1]),this.ctx.lineTo(h[0],h[1]),this.ctx.stroke(),this.drawArrowhead(h[0],h[1],l,a)}this.ctx.restore()}calculateAutoScale(t,e){let i=t.map((r,s)=>Math.sqrt(r*r+e[s]*e[s])),n=Math.max(...i);return n>0?n/30:1}drawArrowhead(t,e,i,n){let r=Math.atan2(e-i[1],t-i[0]);this.ctx.beginPath(),this.ctx.moveTo(t,e),this.ctx.lineTo(t-n*Math.cos(r-Math.PI/6),e-n*Math.sin(r-Math.PI/6)),this.ctx.lineTo(t-n*Math.cos(r+Math.PI/6),e-n*Math.sin(r+Math.PI/6)),this.ctx.closePath(),this.ctx.fill()}};var L=class{constructor(t,e){this.ctx=t;this.getPlotArea=e}drawTitle(t){this.ctx.save(),this.ctx.font="bold 16px sans-serif",this.ctx.fillStyle="#333",this.ctx.textAlign="center",this.ctx.fillText(t,this.getPlotArea().left+this.getPlotArea().width/2,25),this.ctx.restore()}drawAxisLabels(t,e){this.ctx.save(),this.ctx.fillStyle="#333",this.ctx.font="14px sans-serif",t&&(this.ctx.textAlign="center",this.ctx.fillText(t,this.getPlotArea().left+this.getPlotArea().width/2,this.getPlotArea().bottom+40)),e&&(this.ctx.save(),this.ctx.textAlign="center",this.ctx.translate(25,this.getPlotArea().top+this.getPlotArea().height/2),this.ctx.rotate(-Math.PI/2),this.ctx.fillText(e,0,0),this.ctx.restore()),this.ctx.restore()}drawLegend(t,e="top-right"){if(t.length===0)return;this.ctx.save(),this.ctx.font="12px sans-serif";let i=20,n=10,r=30,c=Math.max(...t.map(d=>this.ctx.measureText(d.label).width))+r+n*3,a=t.length*i+n*2,o,l,h=10;switch(e){case"top-right":o=this.getPlotArea().right-c-h,l=this.getPlotArea().top+h;break;case"top-left":o=this.getPlotArea().left+h,l=this.getPlotArea().top+h;break;case"bottom-right":o=this.getPlotArea().right-c-h,l=this.getPlotArea().bottom-a-h;break;case"bottom-left":o=this.getPlotArea().left+h,l=this.getPlotArea().bottom-a-h;break;default:o=this.getPlotArea().right-c-h,l=this.getPlotArea().top+h}this.ctx.fillStyle="rgba(255, 255, 255, 0.95)",this.ctx.strokeStyle="#ccc",this.ctx.lineWidth=1,this.ctx.fillRect(o,l,c,a),this.ctx.strokeRect(o,l,c,a),t.forEach((d,f)=>{let x=l+n+f*i+i/2;this.ctx.strokeStyle=d.color,this.ctx.lineWidth=d.lineStyle?.width||2,d.lineStyle?.dash?this.ctx.setLineDash(d.lineStyle.dash):this.ctx.setLineDash([]),this.ctx.beginPath(),this.ctx.moveTo(o+n,x),this.ctx.lineTo(o+n+r,x),this.ctx.stroke(),this.ctx.fillStyle="#333",this.ctx.setLineDash([]),this.ctx.fillText(d.label,o+n+r+10,x+4)}),this.ctx.restore()}};var T=class{constructor(t,e,i){this.ctx=t;this.width=e;this.height=i;this.bounds=new k(e,i),this.axisRenderer=new E(t,()=>this.bounds.getViewBounds(),(n,r)=>this.bounds.toCanvas(n,r),()=>this.bounds.getPlotArea()),this.data=new z(t,(n,r)=>this.bounds.toCanvas(n,r),()=>this.bounds.getPlotArea()),this.labels=new L(t,()=>this.bounds.getPlotArea())}plot(t,e,i={}){return this.clear(),this.bounds.updateDataBounds(t,e),i.autoScale!==!1&&this.bounds.autoScale(),i.aspectRatio==="equal"?this.bounds.adjustAspectRatio("equal"):this.bounds.adjustAspectRatio("auto"),this.axisRenderer.drawGrid(i),this.axisRenderer.drawAxes(i.xLabel,i.yLabel,i),this.data.plot(t,e,i),i.title&&this.labels.drawTitle(i.title),this.labels.drawAxisLabels(i.xLabel,i.yLabel),this}plotMultiple(t,e={}){this.clear();let i=[],n=[];return t.forEach(r=>{i.push(...r.x),n.push(...r.y)}),this.bounds.updateDataBounds(i,n),e.autoScale!==!1&&this.bounds.autoScale(),e.aspectRatio==="equal"?this.bounds.adjustAspectRatio("equal"):this.bounds.adjustAspectRatio("auto"),this.axisRenderer.drawGrid(e),this.axisRenderer.drawAxes(e.xLabel,e.yLabel,e),t.forEach((r,s)=>{this.data.plot(r.x,r.y,{...e,lineColor:r.color||y.getColorByIndex(s)})}),e.title&&this.labels.drawTitle(e.title),this.labels.drawAxisLabels(e.xLabel,e.yLabel),this}drawVectors(t,e,i,n,r={}){return this.data.drawVectors(t,e,i,n,r),this}addLegend(t,e="top-right"){this.labels.drawLegend(t,e)}clear(){this.ctx.fillStyle="#f8f9fa",this.ctx.fillRect(0,0,this.width,this.height)}setBounds(t){this.bounds.setViewBounds(t)}getPlotArea(){return this.bounds.getPlotArea()}drawGrid(t={}){this.axisRenderer.drawGrid(t)}drawAxis(t={}){this.axisRenderer.drawAxes(t.x,t.y,t)}setBoundsWithAuto(t,e){t.x&&Array.isArray(t.x)?this.setBounds(t):e&&this.setBounds(e)}setBoundsWithAutoAndAspectRatio(t,e){t.x&&Array.isArray(t.x)?this.setBounds(t):e&&(this.setBounds(e),this.bounds.adjustAspectRatio("equal"))}createDrawContext(){let t=this;return{plot:(e,i,n={})=>{t.data.plot(e,i,n)},line:(e,i,n={})=>{let[r,s]=t.bounds.toCanvas(e[0],e[1]),[c,a]=t.bounds.toCanvas(i[0],i[1]);t.ctx.beginPath(),t.ctx.moveTo(r,s),t.ctx.lineTo(c,a),t.ctx.strokeStyle=n.color||"#2563eb",t.ctx.lineWidth=n.width||1,n.dash?t.ctx.setLineDash(n.dash):t.ctx.setLineDash([]),t.ctx.stroke()},circle:(e,i,n={})=>{let[r,s]=t.bounds.toCanvas(e[0],e[1]),c=t.bounds.getViewBounds(),a=t.bounds.getPlotArea(),o=c.x[1]-c.x[0],l=a.width/o,h=i*l;t.ctx.beginPath(),t.ctx.arc(r,s,h,0,2*Math.PI),n.fill&&(t.ctx.fillStyle=n.fill,t.ctx.fill()),n.stroke&&(t.ctx.strokeStyle=n.stroke,t.ctx.lineWidth=n.width||1,t.ctx.stroke())},arrow:(e,i,n={})=>{let[r,s]=t.bounds.toCanvas(e[0],e[1]),[c,a]=t.bounds.toCanvas(i[0],i[1]),o=n.headSize||10;t.ctx.beginPath(),t.ctx.moveTo(r,s),t.ctx.lineTo(c,a),t.ctx.strokeStyle=n.color||"#2563eb",t.ctx.lineWidth=n.width||2,t.ctx.stroke();let l=Math.atan2(a-s,c-r);t.ctx.beginPath(),t.ctx.moveTo(c,a),t.ctx.lineTo(c-o*Math.cos(l-Math.PI/6),a-o*Math.sin(l-Math.PI/6)),t.ctx.moveTo(c,a),t.ctx.lineTo(c-o*Math.cos(l+Math.PI/6),a-o*Math.sin(l+Math.PI/6)),t.ctx.stroke()},text:(e,i,n={})=>{let[r,s]=t.bounds.toCanvas(e[0],e[1]);t.ctx.font=`${n.size||14}px ${n.font||"system-ui"}`,t.ctx.fillStyle=n.color||"#1f2937",t.ctx.fillText(i,r,s)}}}debugInfo(){return{viewBounds:this.bounds.getViewBounds(),plotArea:this.bounds.getPlotArea(),dataBounds:this.bounds.dataBounds}}};var w=class{constructor(t,e=800,i=600,n){this.container=t,this.log=n,this.targetWidth=e,this.targetHeight=i,this.canvas=this.createCanvas(e,i),this.renderer=new T(this.canvas.getContext("2d"),this.canvas.width,this.canvas.height),this.setupResizeObserver()}createCanvas(t,e){let i=document.createElement("div");i.innerHTML=`<canvas width="${t}" height="${e}"></canvas>`;let n=i.firstChild;return n.style&&(n.style.width="100%",n.style.height="100%",n.style.display="block"),this.container.appendChild(n),n}setupResizeObserver(){typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(t=>{for(let e of t){let{width:i,height:n}=e.contentRect;(i!==this.targetWidth||n!==this.targetHeight)&&this.updateCanvasSize(i,n)}}),this.resizeObserver.observe(this.container))}updateCanvasSize(t,e){this.canvas.width=Math.floor(t),this.canvas.height=Math.floor(e),this.targetWidth=Math.floor(t),this.targetHeight=Math.floor(e),this.renderer=new T(this.canvas.getContext("2d"),this.canvas.width,this.canvas.height),this.currentData&&this.renderInternal(this.currentData)}renderInternal(t){let e=t.layers||[];t.viewDescriptor&&t.viewDescriptor.layers&&(e=t.viewDescriptor.layers),this.renderer.clear();let i=e.find(a=>a.type==="bounds");if(i&&i.bounds){console.log("Found explicit bounds:",JSON.stringify(i.bounds));let a=this.calculateBoundsFromTimeline(t.timeline),l=e.find(h=>h.type==="axis")?.options?.aspectRatio==="equal";console.log("Has aspectRatio equal:",l),l?this.renderer.setBoundsWithAutoAndAspectRatio(i.bounds,a):this.renderer.setBoundsWithAuto(i.bounds,a)}else{console.log("No explicit bounds found, using auto bounds");let a=this.calculateBoundsFromTimeline(t.timeline,e);this.renderer.setBounds(a)}let n={grid:1,axis:2,plot:3},r=e.filter(a=>a.type!=="bounds").sort((a,o)=>(n[a.type]||999)-(n[o.type]||999)),s=[],c=[];if(r.forEach((a,o)=>{switch(a.type){case"grid":this.renderer.drawGrid(a.options||{});break;case"axis":this.renderer.drawAxis(a.options||{});break;case"plot":if(a.selector){a.options?.label&&s.push({label:a.options.label,color:a.options.color||"#2563eb",lineStyle:{width:a.options.lineWidth||2,dash:a.options.dash||[]}});let l=this.extractPlotData(t.timeline,a);l&&c.push({x:l.xValues,y:l.yValues,color:a.options?.color})}break;case"scene":a.draw&&this.renderScene(t.timeline,a);break;default:break}}),c.length>0){let a={},o=r.find(l=>l.type==="axis");o&&(a=o.options||{}),this.renderer.plotMultiple(c,{...t.options,aspectRatio:a.aspectRatio,autoScale:!1})}s.length>0&&this.renderer.addLegend(s,"top-right")}render(t){t.timeline&&(this.currentData=t,this.renderInternal(t))}extractPlotData(t,e){let{selector:i}=e,n=!1;try{let s={x:0,y:0},c=b.parseAndCreateFunction(["s"],i)(s);n=Array.isArray(c)&&c.length===2}catch{n=!1}let r;try{r=b.parseAndCreateFunction(["s"],i)}catch(s){return this.log("\u26A0\uFE0F Failed to compile selector:",s),null}if(n){let c=t.times.map((l,h)=>{let d=Object.keys(t.states).reduce((f,x)=>(f[x]=t.states[x][h],f),{});return r(d)}).filter(l=>Array.isArray(l)&&l.length===2&&typeof l[0]=="number"&&typeof l[1]=="number"),a=c.map(l=>l[0]),o=c.map(l=>l[1]);return{xValues:a,yValues:o}}else{let s=t.times.map((c,a)=>{let o=Object.keys(t.states).reduce((l,h)=>(l[h]=t.states[h][a],l),{});return r(o)});return{xValues:t.times,yValues:s}}}renderPlot(t,e){let{selector:i,options:n={}}=e,r=!1;try{let c={x:0,y:0},a=b.parseAndCreateFunction(["s"],i)(c);r=Array.isArray(a)&&a.length===2}catch{r=!1}let s;try{s=b.parseAndCreateFunction(["s"],i),this.log("\u2705 selector created successfully")}catch(c){this.log("\u26A0\uFE0F Failed to compile selector:",c),s=a=>0}if(r){let a=t.times.map((h,d)=>{let f=Object.keys(t.states).reduce((x,p)=>(x[p]=t.states[p][d],x),{});return s(f)}).filter(h=>Array.isArray(h)&&h.length===2&&typeof h[0]=="number"&&typeof h[1]=="number"),o=a.map(h=>h[0]),l=a.map(h=>h[1]);this.renderer.plot(o,l,n)}else{let c=t.times.map((a,o)=>{let l=Object.keys(t.states).reduce((h,d)=>(h[d]=t.states[d][o],h),{});return s(l)});this.renderer.plot(t.times,c,n)}}renderScene(t,e){let{draw:i}=e;if(!i)return;let n;try{n=b.parseAndCreateFunction(["ctx","state"],i)}catch(r){this.log("\u26A0\uFE0F Failed to compile scene function:",r);return}t.times.forEach((r,s)=>{let c=Object.keys(t.states).reduce((a,o)=>(a[o]=t.states[o][s],a),{});try{n(this.renderer.createDrawContext(),c)}catch(a){this.log("\u26A0\uFE0F Error in scene function:",a)}})}renderExplore(t,e){this.currentTimeline=e,this.render({type:"view",timeline:e,layers:t.layers,options:t.options,viewDescriptor:t.viewDescriptor})}calculateBoundsFromTimeline(t,e){let i=1/0,n=-1/0,r=1/0,s=-1/0;if(e){let o=e.filter(l=>l.type==="plot"&&l.selector);for(let l of o)try{let h=b.parseAndCreateFunction(["s"],l.selector),f=h({x:0,y:0});if(Array.isArray(f)&&f.length===2){let p=t.times.map((m,v)=>{let O=Object.keys(t.states).reduce((C,S)=>(C[S]=t.states[S][v],C),{});return h(O)}).filter(m=>Array.isArray(m)&&m.length===2&&typeof m[0]=="number"&&typeof m[1]=="number");for(let m of p)i=Math.min(i,m[0]),n=Math.max(n,m[0]),r=Math.min(r,m[1]),s=Math.max(s,m[1])}else{let p=t.times.map((m,v)=>{let O=Object.keys(t.states).reduce((C,S)=>(C[S]=t.states[S][v],C),{});return h(O)}).filter(m=>typeof m=="number");i=Math.min(i,...t.times),n=Math.max(n,...t.times),r=Math.min(r,...p),s=Math.max(s,...p)}}catch(h){this.log("\u26A0\uFE0F Failed to analyze selector for bounds:",h)}}i===1/0&&t.times&&(i=Math.min(...t.times),n=Math.max(...t.times)),i===1/0&&(i=0),n===-1/0&&(n=10),r===1/0&&(r=-10),s===-1/0&&(s=10);let c=(n-i)*.1||1,a=(s-r)*.1||1;return{x:[i-c,n+c],y:[r-a,s+a]}}};function g(u,t={},...e){let i=document.createElement(u);return Object.entries(t).forEach(([n,r])=>{n==="className"?i.className=r:n.startsWith("data-")?i.setAttribute(n,String(r)):n in i?i[n]=r:i.setAttribute(n,String(r))}),e.flat().forEach(n=>{typeof n=="string"?i.appendChild(document.createTextNode(n)):n instanceof HTMLElement&&i.appendChild(n)}),i}var V=(u={},...t)=>g("div",u,...t),j=(u={},...t)=>g("span",u,...t),F=(u={})=>g("input",u),H=(u={},...t)=>g("label",u,...t);function A(u,t){let e=`input-${t.id}`,i=`val-${t.id}`,n=j({className:"value-display",id:i},typeof t.value=="number"?t.value.toFixed(2):String(t.value)),r=F({type:"range",id:e,min:String(t.control.min),max:String(t.control.max),step:String(t.control.step||.01),value:String(t.value),"data-slider-id":t.id});r.addEventListener("input",a=>{let o=parseFloat(a.target.value);n.textContent=o.toFixed(2),t.onChange&&t.onChange(t.id,o)});let s=H({htmlFor:e},t.control.label),c=V({className:"control-group"},s,r,n);return u.appendChild(c),r}function M(u,t){let e=`input-${t.id}`,i=F({type:"checkbox",id:e,checked:t.value||!1,"data-checkbox-id":t.id});i.addEventListener("change",s=>{let c=s.target.checked;t.onChange&&t.onChange(t.id,c)});let n=H({htmlFor:e},t.control.label),r=V({className:"control-group"},n,i);return u.appendChild(r),i}var I=class{constructor(t){this.layers=[];this.timeline=t}scene(t){return this.layers.push({type:"scene",draw:this.serializeFunction(t)}),this}plot(t,e={}){let i=this.detectParametricSelector(t);return this.layers.push({type:"plot",selector:this.serializeFunction(t),parametric:i,options:{color:"#2563eb",lineWidth:2,fill:!1,dash:[],label:"",alpha:1,...e}}),this}vector(t,e,i={}){return this.layers.push({type:"vector",at:this.serializeFunction(t),dir:this.serializeFunction(e),options:{color:"#0ff",scale:1,width:2,...i}}),this}bounds(t){return this.layers.push({type:"bounds",bounds:t}),this}grid(t={}){return this.layers.push({type:"grid",options:t}),this}axis(t={}){return this.layers.push({type:"axis",options:t}),this}getLayers(){return[...this.layers]}getTimeline(){return this.timeline}setTimeline(t){this.timeline=t}serializeFunction(t){return t.toString()}detectParametricSelector(t){try{let i=t({x:1,y:2,z:3});return Array.isArray(i)&&i.length===2}catch{return!1}}toDescriptor(){return{timeline:{times:this.timeline?.times||[],states:this.timeline?.states||{}},layers:this.layers}}executeWithTimeline(t){let e=this.timeline;this.timeline=t;let i=this.toDescriptor();return this.timeline=e,i}};function P(u){return new I(u)}typeof globalThis<"u"&&(globalThis.CalcPlotComponents={createSlider:A,createCheckbox:M,view:P});function $(u,t,e,i){i(" Creating controls for:",Object.keys(u.params));let n=g("div",{style:"padding: 10px; border-bottom: 1px solid #ccc;"});t.appendChild(n),Object.entries(u.params).forEach(([r,s])=>{if(s.type==="slider"){let c=window.CalcPlotComponents.createSlider;c?c(n,{id:r,control:s,value:s.default,onChange:(a,o)=>{e()}}):i("\u274C createSlider not available")}else if(s.type==="checkbox"){let c=window.CalcPlotComponents.createCheckbox;c?c(n,{id:r,control:s,value:s.default,onChange:(a,o)=>{i(`\u2611\uFE0F Checkbox ${a} changed to ${o}`),e()}}):i("\u274C createCheckbox not available")}})}function W(u,t,e,i){let n=g("div",{style:"display: flex; width: 100%; height: 100%;"});return u.appendChild(n),n}function N(u,t,e,i,n){let r={columns:u.length,rows:1,gaps:10};return u.map(s=>{let c=g("div",{style:"flex: 1; width: 0; height: 100%;"});return t.appendChild(c),new w(c,e/r.columns,i/r.rows,n)})}function q(u,t,e,i,n,r){let s={columns:t.length,rows:1,gaps:10};t.forEach((c,a)=>{let o;if(c.layers&&Array.isArray(c.layers))o={timeline:{times:e.times,states:e.states},layers:c.layers};else throw new Error("Invalid view configuration: expected layers array");u[a].render({type:"view",timeline:e,layers:o.layers,width:n/s.columns,height:r/s.rows})})}function G(u,t,e){e(" Initializing explore mode...");try{let l=function(){let h={};Object.entries(u.params).forEach(([d,f])=>{let x=document.getElementById(`input-${d}`);x?h[d]=parseFloat(x.value):h[d]=f.default});try{let d=new R(e),x=d.parseInitialFunction(u.initial)(h),p=d.simulateTrajectory(u,x,h);if(r)q(o,n,p,h,s,c);else{let m=n[0];if(m){let v;if(m.layers&&Array.isArray(m.layers))v={timeline:{times:p.times,states:p.states},layers:m.layers};else throw new Error("Invalid view configuration: expected layers array");o[0].render({type:"view",timeline:p,layers:v.layers,width:s,height:c})}}}catch(d){e("\u274C Error in simulation:",d.message)}};var i=l;let n=u.views||[],r=n.length>1,s=u.width||800,c=u.height||600;u.params&&$(u,t,l,e);let a=r?W(t,s,c,10):t,o=r?N(n,a,s,c,e):[new w(a,s,c,e)];l(),e(`\u2705 ${r?"Multi-view":"Single"} explore mode initialized`)}catch(n){e("\u274C Error in explore initialization:",n.message)}}function U(u,t,e){e("\u{1F4CA} Initializing show mode...");try{let i=u.views||[];if(i.length>1){let r=u.layout||{columns:i.length,rows:1,gaps:10},s=u.width||800,c=u.height||600,a=g("div",{style:`display: flex; flex-wrap: wrap; gap: ${r.gaps}px; width: ${s}px; height: ${c}px;`});t.appendChild(a),i.forEach(o=>{let l=g("div",{style:"flex: 1 1 calc(50% - 5px); min-width: 300px; height: calc(50% - 5px);"});a.appendChild(l),new w(l,o.width||s/r.columns,o.height||c/r.rows,e).render(o)}),e("\u2705 Multi-view show mode initialized")}else{let r=i[0];r&&new w(t,r.width||800,r.height||600,e).render(r),e("\u2705 Show mode initialized")}}catch(i){e("\u274C Error in show initialization:",i.message)}}function Y(u,t,e){e("\u{1F4CA} Initializing compare mode...");try{new w(t,u.width||800,u.height||600,e).render(u),e("\u2705 Compare mode initialized")}catch(i){e("\u274C Error in compare initialization:",i.message)}}function B(u,t,e){let i=e||function(...r){console.log("[calcplot]",...r)};i("\u{1F680} Starting CalcPlot...");let n=t||window.calcPlotData;if(!n){i("\u274C No calcplot data found");return}if(!u){i("\u274C No container provided - visualization skipped");return}i("\u{1F4E6} Data received:",n.type),i("\u{1F4E6} Using container:",u.id||"unnamed"),n.type==="explore"?G(n,u,i):n.type==="show"?U(n,u,i):n.type==="compare"?Y(n,u,i):i("\u274C Unknown data type:",n.type)}typeof globalThis<"u"&&(globalThis.CalcPlotComponents={initializeClient:B,createSlider:A,createCheckbox:M,view:P});typeof globalThis<"u"&&(globalThis.CalcPlotClient={initializeClient:B,createCheckbox:M,createSlider:A,view:P});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/runtime/serialization.ts", "../src/runtime/client/SimulationEngine.ts", "../src/ui/CanvasRenderer.ts", "../src/runtime/client/ViewRenderer.ts", "../src/utils/html-tag.ts", "../src/ui/components/Slider.ts", "../src/ui/components/Checkbox.ts", "../src/ui/ViewBuilder.ts", "../src/runtime/client/init.ts", "../src/runtime/client/index.ts", "../src/runtime/client-bundle.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * CalcPlot API Serialization\n * Handles serialization/deserialization of models, params, functions, and timelines\n */\n\nexport interface SerializedModel {\n state: Record<string, number>;\n params: Record<string, number>;\n derivatives: Record<string, string>;\n events?: Record<string, string>;\n}\n\nexport interface SerializedParams {\n [key: string]: {\n type: string;\n min: number;\n max: number;\n default: number;\n label: string;\n step: number;\n };\n}\n\nexport interface SerializedTimeline {\n times: number[];\n states: Record<string, number[]>;\n}\n\n/**\n * Function serialization utilities\n */\nexport class FunctionSerializer {\n /**\n * Parse function string and extract the body\n * Handles various formats:\n * - \"(p)=>{ return p.x; }\" \u2192 \"return p.x;\"\n * - \"(s)=>s.vx\" \u2192 \"return s.vx\"\n * - \"s=>s.vx\" \u2192 \"return s.vx\"\n * - \"function(p){ return p.x; }\" \u2192 \"return p.x;\"\n */\n static parseFunction(fnStr: string): string {\n const trimmed = fnStr.trim();\n\n // If it's an arrow function wrapped in parentheses with block body\n const arrowMatch = trimmed.match(/^\\(([^)]+)\\)\\s*=>\\s*\\{([\\s\\S]*)\\}$/);\n if (arrowMatch) {\n return arrowMatch[2].trim();\n }\n\n // If it's a simple arrow function without parentheses with block body\n const simpleArrowBlockMatch = trimmed.match(/^(\\w+)\\s*=>\\s*\\{([\\s\\S]*)\\}$/);\n if (simpleArrowBlockMatch) {\n return simpleArrowBlockMatch[2].trim();\n }\n\n // If it's an arrow function wrapped in parentheses with expression body\n const arrowExprMatch = trimmed.match(/^\\(([^)]+)\\)\\s*=>\\s*(.+)$/s);\n if (arrowExprMatch) {\n return `return ${arrowExprMatch[2].trim()}`;\n }\n\n // If it's a simple arrow function without parentheses and without block\n const simpleArrowMatch = trimmed.match(/^(\\w+)\\s*=>\\s*(.+)$/s);\n if (simpleArrowMatch) {\n return `return ${simpleArrowMatch[2].trim()}`;\n }\n\n // If it's a regular function, extract the body\n const functionMatch = trimmed.match(/^function\\s*\\([^)]*\\)\\s*\\{([\\s\\S]*)\\}$/);\n if (functionMatch) {\n return functionMatch[1].trim();\n }\n\n // Otherwise return as is (might be a simple expression)\n return trimmed;\n }\n\n /**\n * Create function from parsed string\n */\n static createFunction(params: string[], body: string): (...args: any[]) => any {\n return new Function(...params, body) as (...args: any[]) => any;\n }\n\n /**\n * Parse and create function in one step\n */\n static parseAndCreateFunction(params: string[], fnStr: string): (...args: any[]) => any {\n const parsedBody = this.parseFunction(fnStr);\n return this.createFunction(params, parsedBody);\n }\n}\n\n/**\n * Serialize model for HTML embedding\n */\nexport function serializeModel(model: any): SerializedModel {\n return {\n state: model.state,\n params: model.params,\n derivatives: serializeFunctions(model.derivatives),\n events: model.events ? serializeFunctions(model.events) : undefined\n };\n}\n\n/**\n * Serialize parameters (sliders) for HTML embedding\n */\nexport function serializeParams(params: Record<string, any>): SerializedParams {\n const serialized: SerializedParams = {};\n for (const [key, control] of Object.entries(params)) {\n serialized[key] = {\n type: control.type || 'slider',\n min: control.min,\n max: control.max,\n default: control.default,\n label: control.label || key,\n step: control.step || 0.01\n };\n }\n return serialized;\n}\n\n/**\n * Serialize timeline for HTML embedding\n */\nexport function serializeTimeline(timeline: any): SerializedTimeline {\n return {\n times: timeline.times,\n states: timeline.states\n };\n}\n\n/**\n * Deserialize parameters from sliders to values\n */\nexport function deserializeParams(serializedParams: SerializedParams): Record<string, number> {\n const params: Record<string, number> = {};\n for (const [key, control] of Object.entries(serializedParams)) {\n params[key] = control.default;\n }\n return params;\n}\n\n/**\n * Deserialize functions from strings\n */\nexport function deserializeFunctions(\n serialized: Record<string, string>\n): Record<string, (...args: any[]) => any> {\n const functions: Record<string, (...args: any[]) => any> = {};\n for (const [key, fnStr] of Object.entries(serialized)) {\n try {\n // Handle different function formats\n if (fnStr.includes('=>')) {\n // Arrow function - use as is\n functions[key] = eval(`(${fnStr})`);\n } else if (fnStr.startsWith('function')) {\n // Regular function declaration - use as is\n functions[key] = eval(`(${fnStr})`);\n } else {\n // Simple expression - wrap in return statement\n functions[key] = eval(`(state, params) => ${fnStr}`);\n }\n } catch (e) {\n console.error('Error deserializing function', key, e);\n // Fallback: simple identity function\n functions[key] = () => 0;\n }\n }\n return functions;\n}\n\n/**\n * Helper: serialize object with functions\n */\nfunction serializeFunctions(obj: any): Record<string, string> {\n const serialized: Record<string, string> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'function') {\n serialized[key] = value.toString();\n } else if (typeof value === 'object' && value !== null) {\n serialized[key] = JSON.stringify(value);\n } else {\n serialized[key] = String(value);\n }\n }\n return serialized;\n}\n", "/**\n * Client-side simulation engine for interactive explore mode\n * Uses core simulation logic but adapted for client-side\n */\n\nimport { FunctionSerializer } from '../serialization';\n\nexport interface SimulationData {\n model: any;\n params: any;\n derivatives: Record<string, string>;\n options: any;\n}\n\nexport class SimulationEngine {\n private log: (...args: any[]) => void;\n\n constructor(log: (...args: any[]) => void) {\n this.log = log;\n }\n\n simulateTrajectory(data: SimulationData, initialState: any, params: any): any {\n // Validate initialState and merge model params with explore params\n if (!initialState || typeof initialState !== 'object') {\n throw new Error(\n `Invalid initialState: expected object, got ${typeof initialState}. Value: ${initialState}`\n );\n }\n\n // Merge model params with explore params for complete parameter set\n const modelParams = data.model?.params || {};\n const exploreParams = params || {};\n const allParams = { ...modelParams, ...exploreParams };\n\n const { dt = 0.01, maxTime = 10 } = data.options || {};\n const times = [];\n const states: Record<string, number[]> = {};\n\n // Initialize states object with all state variables\n Object.keys(initialState).forEach((key) => {\n states[key] = [];\n });\n\n let state = { ...initialState };\n let t = 0;\n\n // Parse derivative functions from model\n const derivatives = data.model?.derivatives || data.derivatives;\n if (!derivatives) {\n throw new Error('No derivatives found in data.model.derivatives or data.derivatives');\n }\n\n const derivativeFns: Record<string, Function> = {};\n Object.entries(derivatives).forEach(([key, fn]) => {\n derivativeFns[key] = FunctionSerializer.parseAndCreateFunction(['s', 'p'], fn as string);\n });\n\n while (t <= maxTime && state.y >= 0) {\n times.push(t);\n\n // Store current state\n Object.keys(state).forEach((key) => {\n states[key].push(state[key]);\n });\n\n // Calculate derivatives\n const derivatives2: Record<string, number> = {};\n Object.entries(derivativeFns).forEach(([key, fn]) => {\n derivatives2[key] = fn(state, allParams);\n });\n\n // Update state\n Object.keys(state).forEach((key) => {\n if (derivatives2[key] !== undefined) {\n state[key] += derivatives2[key] * dt;\n }\n });\n\n t += dt;\n }\n\n return { times, states };\n }\n\n parseInitialFunction(initial: string): Function {\n try {\n const fn = FunctionSerializer.parseAndCreateFunction(['p'], initial);\n return fn;\n } catch (error) {\n console.error('\u274C parseInitialFunction error:', error);\n throw error;\n }\n }\n}\n", "/**\n * Canvas drawing context with coordinate transformation and advanced rendering\n */\n\nimport { DrawContext } from './ViewBuilder';\n\nexport interface Bounds {\n x: [number, number];\n y: [number, number];\n}\n\nexport interface BoundsInput {\n x?: [number, number] | 'auto';\n y?: [number, number] | 'auto';\n}\n\nexport interface GridOptions {\n color?: string;\n alpha?: number;\n major?: boolean;\n minor?: boolean;\n}\n\nexport interface AxisOptions {\n x?: string;\n y?: string;\n color?: string;\n showTicks?: boolean;\n showLabels?: boolean;\n}\n\nexport interface Transform {\n scale: number;\n offsetX: number;\n offsetY: number;\n}\n\nexport class CanvasRenderer {\n private ctx: CanvasRenderingContext2D;\n private bounds: Bounds;\n private width: number;\n private height: number;\n private margin = 50; // Space for axes and labels\n\n constructor(ctx: CanvasRenderingContext2D, width: number, height: number) {\n this.ctx = ctx;\n this.width = width;\n this.height = height;\n\n // Default bounds\n this.bounds = {\n x: [-10, 10],\n y: [-10, 10]\n };\n }\n\n /**\n * Set bounds for coordinate system\n */\n setBounds(bounds: Bounds): void {\n this.bounds = bounds;\n }\n\n /**\n * Set bounds with auto support (for mixed bounds)\n */\n setBoundsWithAuto(bounds: BoundsInput, dataBounds?: Bounds): void {\n const finalBounds: Bounds = {\n x: bounds.x === 'auto' && dataBounds ? dataBounds.x : (bounds.x as [number, number]),\n y: bounds.y === 'auto' && dataBounds ? dataBounds.y : (bounds.y as [number, number])\n };\n this.bounds = finalBounds;\n }\n\n /**\n * Convert mathematical coordinates to canvas coordinates\n */\n private toCanvas(x: number, y: number): [number, number] {\n const [xMin, xMax] = this.bounds.x;\n const [yMin, yMax] = this.bounds.y;\n\n // X: from margin to width-margin\n const sx = this.margin + ((x - xMin) / (xMax - xMin)) * (this.width - 2 * this.margin);\n\n // Y: from height-margin to margin (inverted)\n const sy =\n this.height - this.margin - ((y - yMin) / (yMax - yMin)) * (this.height - 2 * this.margin);\n\n return [sx, sy];\n }\n\n /**\n * Convert screen coordinates back to mathematical coordinates\n */\n toScreen(x: number, y: number): [number, number] {\n const [xMin, xMax] = this.bounds.x;\n const [yMin, yMax] = this.bounds.y;\n\n const mx = xMin + ((x - this.margin) / (this.width - 2 * this.margin)) * (xMax - xMin);\n const my =\n yMin + ((this.height - this.margin - y) / (this.height - 2 * this.margin)) * (yMax - yMin);\n\n return [mx, my];\n }\n\n /**\n * Calculate \"nice\" step for axis divisions\n */\n private calculateNiceStep(range: number, targetSteps: number): number {\n const rawStep = range / targetSteps;\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n\n // Round to 1, 2, 5 or 10\n let niceNormalized;\n if (normalized < 1.5) niceNormalized = 1;\n else if (normalized < 3) niceNormalized = 2;\n else if (normalized < 7) niceNormalized = 5;\n else niceNormalized = 10;\n\n return niceNormalized * magnitude;\n }\n\n /**\n * Format numbers for axis labels\n */\n private formatNumber(n: number): string {\n // Remove insignificant zeros\n if (Math.abs(n) < 0.01 || Math.abs(n) > 1000) {\n return n.toExponential(1);\n }\n return n.toFixed(2).replace(/\\.?0+$/, '');\n }\n\n /**\n * Draw grid with nice divisions\n */\n grid(options: GridOptions = {}): void {\n const { color = '#333', alpha = 0.2, major = true, minor = false } = options;\n\n this.ctx.save();\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = 1;\n this.ctx.globalAlpha = alpha;\n\n const [xMin, xMax] = this.bounds.x;\n const [yMin, yMax] = this.bounds.y;\n\n // Calculate nice intervals\n const xStep = this.calculateNiceStep(xMax - xMin, 5);\n const yStep = this.calculateNiceStep(yMax - yMin, 5);\n\n // Vertical lines\n const xStart = Math.ceil(xMin / xStep) * xStep;\n for (let x = xStart; x <= xMax; x += xStep) {\n const [sx, sy0] = this.toCanvas(x, yMin);\n const [, sy1] = this.toCanvas(x, yMax);\n\n this.ctx.beginPath();\n this.ctx.moveTo(sx, sy0);\n this.ctx.lineTo(sx, sy1);\n this.ctx.stroke();\n }\n\n // Horizontal lines\n const yStart = Math.ceil(yMin / yStep) * yStep;\n for (let y = yStart; y <= yMax; y += yStep) {\n const [sx0, sy] = this.toCanvas(xMin, y);\n const [sx1] = this.toCanvas(xMax, y);\n\n this.ctx.beginPath();\n this.ctx.moveTo(sx0, sy);\n this.ctx.lineTo(sx1, sy);\n this.ctx.stroke();\n }\n\n this.ctx.restore();\n }\n\n /**\n * Draw axes with ticks and labels\n */\n axis(options: AxisOptions = {}): void {\n const { x: xLabel, y: yLabel, color = '#666', showTicks = true, showLabels = true } = options;\n\n this.ctx.save();\n this.ctx.strokeStyle = color;\n this.ctx.fillStyle = color;\n this.ctx.lineWidth = 2;\n this.ctx.font = '12px sans-serif';\n\n const [xMin, xMax] = this.bounds.x;\n const [yMin, yMax] = this.bounds.y;\n\n // X axis\n const [x0, yAxis] = this.toCanvas(xMin, 0);\n const [x1] = this.toCanvas(xMax, 0);\n\n this.ctx.beginPath();\n this.ctx.moveTo(x0, yAxis);\n this.ctx.lineTo(x1, yAxis);\n this.ctx.stroke();\n\n // Y axis\n const [xAxis, y0] = this.toCanvas(0, yMin);\n const [, y1] = this.toCanvas(0, yMax);\n\n this.ctx.beginPath();\n this.ctx.moveTo(xAxis, y0);\n this.ctx.lineTo(xAxis, y1);\n this.ctx.stroke();\n\n if (showTicks || showLabels) {\n const xStep = this.calculateNiceStep(xMax - xMin, 5);\n const yStep = this.calculateNiceStep(yMax - yMin, 5);\n\n // X ticks and labels\n const xStart = Math.ceil(xMin / xStep) * xStep;\n for (let x = xStart; x <= xMax; x += xStep) {\n const [sx, sy] = this.toCanvas(x, 0);\n\n if (showTicks) {\n this.ctx.beginPath();\n this.ctx.moveTo(sx, sy - 5);\n this.ctx.lineTo(sx, sy + 5);\n this.ctx.stroke();\n }\n\n if (showLabels && x !== 0) {\n this.ctx.fillText(this.formatNumber(x), sx - 10, sy + 20);\n }\n }\n\n // Y ticks and labels\n const yStart = Math.ceil(yMin / yStep) * yStep;\n for (let y = yStart; y <= yMax; y += yStep) {\n const [sx, sy] = this.toCanvas(0, y);\n\n if (showTicks) {\n this.ctx.beginPath();\n this.ctx.moveTo(sx - 5, sy);\n this.ctx.lineTo(sx + 5, sy);\n this.ctx.stroke();\n }\n\n if (showLabels && y !== 0) {\n this.ctx.fillText(this.formatNumber(y), sx - 35, sy + 4);\n }\n }\n }\n\n // Axis labels\n if (xLabel) {\n this.ctx.fillText(xLabel, this.width - this.margin + 10, yAxis + 4);\n }\n if (yLabel) {\n this.ctx.save();\n this.ctx.translate(xAxis - 4, this.margin - 10);\n this.ctx.rotate(-Math.PI / 2);\n this.ctx.fillText(yLabel, 0, 0);\n this.ctx.restore();\n }\n\n this.ctx.restore();\n }\n\n /**\n * Clear canvas\n */\n clear(): void {\n this.ctx.clearRect(0, 0, this.width, this.height);\n this.ctx.fillStyle = '#f8f9fa';\n this.ctx.fillRect(0, 0, this.width, this.height);\n }\n\n /**\n * Create draw context with coordinate transformation\n */\n createDrawContext(): DrawContext {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n return {\n line: (from: [number, number], to: [number, number], options = {}) => {\n const [x1, y1] = self.toCanvas(from[0], from[1]);\n const [x2, y2] = self.toCanvas(to[0], to[1]);\n\n self.ctx.beginPath();\n self.ctx.moveTo(x1, y1);\n self.ctx.lineTo(x2, y2);\n self.ctx.strokeStyle = options.color || '#2563eb';\n self.ctx.lineWidth = options.width || 1;\n\n if (options.dash) {\n self.ctx.setLineDash(options.dash);\n } else {\n self.ctx.setLineDash([]);\n }\n\n self.ctx.stroke();\n },\n\n circle: (center: [number, number], radius: number, options = {}) => {\n const [cx, cy] = self.toCanvas(center[0], center[1]);\n const r = radius * self.calculateScale();\n\n self.ctx.beginPath();\n self.ctx.arc(cx, cy, r, 0, 2 * Math.PI);\n\n if (options.fill) {\n self.ctx.fillStyle = options.fill;\n self.ctx.fill();\n }\n\n if (options.stroke) {\n self.ctx.strokeStyle = options.stroke;\n self.ctx.lineWidth = options.width || 1;\n self.ctx.stroke();\n }\n },\n\n arrow: (from: [number, number], to: [number, number], options = {}) => {\n const [x1, y1] = self.toCanvas(from[0], from[1]);\n const [x2, y2] = self.toCanvas(to[0], to[1]);\n const headSize = options.headSize || 10;\n\n // Draw line\n self.ctx.beginPath();\n self.ctx.moveTo(x1, y1);\n self.ctx.lineTo(x2, y2);\n self.ctx.strokeStyle = options.color || '#2563eb';\n self.ctx.lineWidth = options.width || 2;\n self.ctx.stroke();\n\n // Draw arrowhead\n const angle = Math.atan2(y2 - y1, x2 - x1);\n self.ctx.beginPath();\n self.ctx.moveTo(x2, y2);\n self.ctx.lineTo(\n x2 - headSize * Math.cos(angle - Math.PI / 6),\n y2 - headSize * Math.sin(angle - Math.PI / 6)\n );\n self.ctx.moveTo(x2, y2);\n self.ctx.lineTo(\n x2 - headSize * Math.cos(angle + Math.PI / 6),\n y2 - headSize * Math.sin(angle + Math.PI / 6)\n );\n self.ctx.stroke();\n },\n\n text: (pos: [number, number], text: string, options = {}) => {\n const [x, y] = self.toCanvas(pos[0], pos[1]);\n self.ctx.font = `${options.size || 14}px ${options.font || 'system-ui'}`;\n self.ctx.fillStyle = options.color || '#1f2937';\n self.ctx.fillText(text, x, y);\n },\n\n plot: (xValues: number[], yValues: number[], options = {}) => {\n if (xValues.length !== yValues.length || xValues.length === 0) {\n return;\n }\n\n // Filter out invalid values\n const validYValues = yValues.filter((v) => typeof v === 'number' && !isNaN(v));\n if (validYValues.length === 0) {\n return;\n }\n\n self.ctx.beginPath();\n self.ctx.strokeStyle = options.color || '#000';\n self.ctx.lineWidth = options.lineWidth || 2;\n\n // Draw lines using bounds-based coordinates\n for (let i = 0; i < xValues.length; i++) {\n const yVal = yValues[i];\n if (typeof yVal !== 'number' || isNaN(yVal)) {\n continue; // Skip invalid points\n }\n\n const [x, y] = self.toCanvas(xValues[i], yVal);\n\n if (i === 0) {\n self.ctx.moveTo(x, y);\n } else {\n self.ctx.lineTo(x, y);\n }\n }\n\n self.ctx.stroke();\n }\n };\n }\n\n /**\n * Calculate current scale for transformations\n */\n private calculateScale(): number {\n const [xMin, xMax] = this.bounds.x;\n return (this.width - 2 * this.margin) / (xMax - xMin);\n }\n\n /**\n * Get current bounds\n */\n getBounds(): Bounds {\n return { ...this.bounds };\n }\n\n /**\n * Fluent API method for chaining\n */\n setBoundsFluent(bounds: BoundsInput): CanvasRenderer {\n this.setBoundsWithAuto(bounds);\n return this;\n }\n\n /**\n * Fluent API method for grid\n */\n gridFluent(options: GridOptions = {}): CanvasRenderer {\n this.grid(options);\n return this;\n }\n\n /**\n * Fluent API method for axis\n */\n axisFluent(options: AxisOptions = {}): CanvasRenderer {\n this.axis(options);\n return this;\n }\n}\n", "/**\n * View Renderer - handles canvas creation and rendering\n */\n\nimport { Bounds, CanvasRenderer } from '../../ui/CanvasRenderer';\nimport { FunctionSerializer } from '../serialization';\n\nexport interface VisualizationData {\n type: 'view' | 'explore';\n timeline?: any;\n layers?: any;\n params?: any;\n viewDescriptor?: any; // Add viewDescriptor with layers\n options?: any;\n width?: number;\n height?: number;\n}\n\nexport class ViewRenderer {\n private container: HTMLElement;\n private canvas: HTMLCanvasElement;\n private renderer: CanvasRenderer;\n private log: (...args: any[]) => void;\n private resizeObserver?: ResizeObserver;\n private targetWidth: number;\n private targetHeight: number;\n private currentData?: VisualizationData;\n private currentTimeline?: any;\n\n constructor(\n container: HTMLElement,\n width: number = 800,\n height: number = 600,\n log: (...args: any[]) => void\n ) {\n this.container = container;\n this.log = log;\n this.targetWidth = width;\n this.targetHeight = height;\n this.canvas = this.createCanvas(width, height);\n this.renderer = new CanvasRenderer(\n this.canvas.getContext('2d')!,\n this.canvas.width,\n this.canvas.height\n );\n this.setupResizeObserver();\n }\n\n /**\n * Create and append canvas to container\n */\n private createCanvas(width: number, height: number): HTMLCanvasElement {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = `<canvas width=\"${width}\" height=\"${height}\"></canvas>`;\n const canvas = tempDiv.firstChild as HTMLCanvasElement;\n\n // Make canvas responsive - check if style exists (for test environments)\n if (canvas.style) {\n canvas.style.width = '100%';\n canvas.style.height = '100%';\n canvas.style.display = 'block';\n }\n\n this.container.appendChild(canvas);\n\n return canvas;\n }\n\n /**\n * Setup ResizeObserver to handle container size changes\n */\n private setupResizeObserver(): void {\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n\n // Only update if size actually changed and not already updating\n if (width !== this.targetWidth || height !== this.targetHeight) {\n this.updateCanvasSize(width, height);\n }\n }\n });\n this.resizeObserver.observe(this.container);\n }\n }\n\n /**\n * Update canvas size based on container dimensions\n */\n private updateCanvasSize(containerWidth: number, containerHeight: number): void {\n // Use actual container dimensions instead of target dimensions\n this.canvas.width = Math.floor(containerWidth);\n this.canvas.height = Math.floor(containerHeight);\n this.targetWidth = Math.floor(containerWidth);\n this.targetHeight = Math.floor(containerHeight);\n this.renderer = new CanvasRenderer(\n this.canvas.getContext(\"2d\")!,\n this.canvas.width,\n this.canvas.height\n );\n if (this.currentData) {\n this.renderInternal(this.currentData);\n }\n }\n\n /**\n * Internal render method without saving data\n */\n private renderInternal(data: VisualizationData): void {\n let layers = data.layers || [];\n if (data.viewDescriptor && data.viewDescriptor.layers) {\n layers = data.viewDescriptor.layers;\n }\n\n this.renderer.clear();\n const bounds = this.calculateBoundsFromTimeline(data.timeline, layers);\n this.renderer.setBounds(bounds);\n const drawCtx = this.renderer.createDrawContext();\n\n // Sort layers by priority: bounds > grid > axis > plot\n const layerPriority: Record<string, number> = {\n bounds: 1,\n grid: 2,\n axis: 3,\n plot: 4\n };\n\n const sortedLayers = [...layers].sort(\n (a, b) => (layerPriority[a.type] || 999) - (layerPriority[b.type] || 999)\n );\n\n sortedLayers.forEach((layer, index) => {\n switch (layer.type) {\n case 'bounds':\n if (layer.bounds) {\n const timelineBounds = this.calculateBoundsFromTimeline(data.timeline);\n this.renderer.setBoundsWithAuto(layer.bounds, timelineBounds);\n }\n break;\n case 'grid':\n this.renderer.grid(layer.options || {});\n break;\n case 'axis':\n this.renderer.axis(layer.options || {});\n break;\n case 'plot':\n if (layer.selector) {\n this.renderPlot(drawCtx, data.timeline, layer);\n }\n break;\n case 'scene':\n if (layer.draw) {\n this.renderScene(drawCtx, data.timeline, layer);\n }\n break;\n default:\n break;\n }\n });\n }\n\n /**\n * Main rendering method\n */\n render(data: VisualizationData): void {\n if (!data.timeline) {\n return;\n }\n\n // Save current data for resize handling\n this.currentData = data;\n\n // Use internal render method\n this.renderInternal(data);\n }\n\n private renderPlot(drawCtx: any, timeline: any, layer: any): void {\n const { selector, options = {} } = layer;\n\n // Determine if this is a parametric plot by checking the selector\n let isParametric = false;\n try {\n const testState = { x: 0, y: 0 };\n const result = FunctionSerializer.parseAndCreateFunction(['s'], selector)(testState);\n isParametric = Array.isArray(result) && result.length === 2;\n } catch (e) {\n isParametric = false;\n }\n\n // Create function from selector string\n let selectFn: (s: any) => any;\n try {\n selectFn = FunctionSerializer.parseAndCreateFunction(['s'], selector) as (s: any) => any;\n this.log('\u2705 selector created successfully');\n } catch (e) {\n this.log('\u26A0\uFE0F Failed to compile selector:', e);\n selectFn = (s: any) => 0;\n }\n\n if (isParametric) {\n // Extract x,y pairs for parametric plot\n const points = timeline.times.map((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n return selectFn(state);\n });\n\n const validPoints = points.filter(\n (p) =>\n Array.isArray(p) && p.length === 2 && typeof p[0] === 'number' && typeof p[1] === 'number'\n );\n\n const xValues = validPoints.map((p) => p[0]);\n const yValues = validPoints.map((p) => p[1]);\n\n drawCtx.plot(xValues, yValues, options);\n } else {\n // Extract y values for regular plot\n const yValues = timeline.times.map((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n return selectFn(state);\n });\n\n drawCtx.plot(timeline.times, yValues, options);\n }\n }\n\n private renderScene(drawCtx: any, timeline: any, layer: any): void {\n const { draw } = layer;\n\n if (!draw) {\n return;\n }\n\n let drawFn: (ctx: any, state: any) => void;\n try {\n drawFn = FunctionSerializer.parseAndCreateFunction(['ctx', 'state'], draw) as (\n ctx: any,\n state: any\n ) => void;\n } catch (e) {\n this.log('\u26A0\uFE0F Failed to compile scene function:', e);\n return;\n }\n\n timeline.times.forEach((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n\n try {\n drawFn(drawCtx, state);\n } catch (e) {\n this.log('\u26A0\uFE0F Error in scene function:', e);\n }\n });\n }\n\n renderExplore(data: VisualizationData, timeline: any): void {\n // Save timeline for resize handling\n this.currentTimeline = timeline;\n\n this.render({\n type: 'view',\n timeline: timeline,\n layers: data.layers,\n options: data.options,\n viewDescriptor: data.viewDescriptor\n });\n }\n\n /**\n * Calculate bounds from timeline data\n */\n private calculateBoundsFromTimeline(timeline: any, layers?: any[]): Bounds {\n let xMin = Infinity,\n xMax = -Infinity;\n let yMin = Infinity,\n yMax = -Infinity;\n\n // First try to find bounds from selectors in plot layers\n if (layers) {\n const plotLayers = layers.filter(layer => layer.type === 'plot' && layer.selector);\n \n for (const layer of plotLayers) {\n try {\n const selectFn = FunctionSerializer.parseAndCreateFunction(['s'], layer.selector);\n \n // Test if selector is parametric\n const testState = { x: 0, y: 0 };\n const result = selectFn(testState);\n const isParametric = Array.isArray(result) && result.length === 2;\n \n if (isParametric) {\n // Extract all points from timeline\n const points = timeline.times.map((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n return selectFn(state);\n }).filter(p => Array.isArray(p) && p.length === 2 && typeof p[0] === 'number' && typeof p[1] === 'number');\n \n // Update bounds from points\n for (const point of points) {\n xMin = Math.min(xMin, point[0]);\n xMax = Math.max(xMax, point[0]);\n yMin = Math.min(yMin, point[1]);\n yMax = Math.max(yMax, point[1]);\n }\n } else {\n // For non-parametric plots, use time as x and selector result as y\n const yValues = timeline.times.map((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n return selectFn(state);\n }).filter(v => typeof v === 'number');\n \n xMin = Math.min(xMin, ...timeline.times);\n xMax = Math.max(xMax, ...timeline.times);\n yMin = Math.min(yMin, ...yValues);\n yMax = Math.max(yMax, ...yValues);\n }\n } catch (e) {\n // If selector analysis fails, fall back to key-based analysis\n this.log('\u26A0\uFE0F Failed to analyze selector for bounds:', e);\n }\n }\n }\n \n // Fallback: use time for x-axis if bounds not found from selectors\n if (xMin === Infinity && timeline.times) {\n xMin = Math.min(...timeline.times);\n xMax = Math.max(...timeline.times);\n }\n\n // Default values if still not found\n if (xMin === Infinity) xMin = 0;\n if (xMax === -Infinity) xMax = 10;\n if (yMin === Infinity) yMin = -10;\n if (yMax === -Infinity) yMax = 10;\n\n const xPadding = (xMax - xMin) * 0.1 || 1;\n const yPadding = (yMax - yMin) * 0.1 || 1;\n\n return {\n x: [xMin - xPadding, xMax + xPadding],\n y: [yMin - yPadding, yMax + yPadding]\n };\n }\n}\n", "/**\n * HTML tag builder for component-based architecture\n */\n\nexport interface HtmlAttrs {\n [key: string]: any;\n}\n\n// DOM element creation functions\nexport function createElement(\n tag: string,\n attrs: HtmlAttrs = {},\n ...children: (HTMLElement | string)[]\n): HTMLElement {\n const element = document.createElement(tag);\n\n // Set attributes\n Object.entries(attrs).forEach(([key, val]) => {\n if (key === 'className') {\n element.className = val;\n } else if (key.startsWith('data-')) {\n element.setAttribute(key, String(val));\n } else if (key in element) {\n (element as any)[key] = val;\n } else {\n element.setAttribute(key, String(val));\n }\n });\n\n // Append children\n children.flat().forEach((child) => {\n if (typeof child === 'string') {\n element.appendChild(document.createTextNode(child));\n } else if (child instanceof HTMLElement) {\n element.appendChild(child);\n }\n });\n\n return element;\n}\n\n// Common shortcuts for DOM elements\nexport const div = (attrs: HtmlAttrs = {}, ...children: (HTMLElement | string)[]) =>\n createElement('div', attrs, ...children);\nexport const span = (attrs: HtmlAttrs = {}, ...children: (HTMLElement | string)[]) =>\n createElement('span', attrs, ...children);\nexport const input = (attrs: HtmlAttrs = {}) => createElement('input', attrs);\nexport const label = (attrs: HtmlAttrs = {}, ...children: (HTMLElement | string)[]) =>\n createElement('label', attrs, ...children);\nexport const button = (attrs: HtmlAttrs = {}, ...children: (HTMLElement | string)[]) =>\n createElement('button', attrs, ...children);\nexport const canvas = (attrs: HtmlAttrs = {}) => createElement('canvas', attrs);\n\n// HTML string generation function (for compatibility)\nexport function h(tag: string, attrs: HtmlAttrs = {}, ...children: any[]): string {\n const attrStr = Object.entries(attrs)\n .filter(([_, val]) => val !== undefined && val !== null && val !== false)\n .map(([key, val]) => {\n const attrName = key === 'className' ? 'class' : key;\n const attrValue = typeof val === 'boolean' ? '' : `=\"${val}\"`;\n return `${attrName}${attrValue}`;\n })\n .join(' ');\n\n const childrenStr = children\n .flat()\n .filter((child) => child !== null && child !== undefined && child !== false)\n .map((child) => (typeof child === 'string' ? child : String(child)))\n .join('');\n\n return `<${tag}${attrStr ? ' ' + attrStr : ''}>${childrenStr}</${tag}>`;\n}\n\n// Common shortcuts for HTML strings\nexport const divStr = (attrs: HtmlAttrs = {}, ...children: any[]) => h('div', attrs, ...children);\nexport const spanStr = (attrs: HtmlAttrs = {}, ...children: any[]) => h('span', attrs, ...children);\nexport const inputStr = (attrs: HtmlAttrs = {}) => h('input', attrs);\nexport const labelStr = (attrs: HtmlAttrs = {}, ...children: any[]) =>\n h('label', attrs, ...children);\nexport const buttonStr = (attrs: HtmlAttrs = {}, ...children: any[]) =>\n h('button', attrs, ...children);\nexport const canvasStr = (attrs: HtmlAttrs = {}) => h('canvas', attrs);\nexport const style = (content: string) => h('style', {}, content);\nexport const script = (content: string, attrs: HtmlAttrs = {}) => h('script', attrs, content);\n", "/**\n * Slider component for parameter controls\n */\n\nimport { div, input, label, span } from '../../utils/html-tag';\nimport { Control } from '../controls';\n\nexport interface SliderProps {\n id: string;\n control: Control;\n value?: number | boolean;\n onChange?: (id: string, value: number | boolean) => void;\n}\n\n/**\n * Create slider element with event listener\n */\nexport function createSlider(container: HTMLElement, props: SliderProps): HTMLInputElement {\n const inputId = `input-${props.id}`;\n const valueId = `val-${props.id}`;\n\n // Create value display\n const valueDisplay = span(\n {\n className: 'value-display',\n id: valueId\n },\n typeof props.value === 'number' ? props.value.toFixed(2) : String(props.value)\n );\n\n // Create input\n const inputElement = input({\n type: 'range',\n id: inputId,\n min: String(props.control.min),\n max: String(props.control.max),\n step: String(props.control.step || 0.01),\n value: String(props.value),\n 'data-slider-id': props.id\n }) as HTMLInputElement;\n\n // Add event listener\n inputElement.addEventListener('input', (e) => {\n const value = parseFloat((e.target as HTMLInputElement).value);\n\n // Update value display\n valueDisplay.textContent = value.toFixed(2);\n\n // Call onChange callback\n if (props.onChange) {\n props.onChange(props.id, value);\n }\n });\n\n // Create label\n const labelElement = label({ htmlFor: inputId }, props.control.label);\n\n // Create control group\n const controlGroup = div(\n { className: 'control-group' },\n labelElement,\n inputElement,\n valueDisplay\n );\n container.appendChild(controlGroup);\n\n return inputElement;\n}\n", "/**\n * Checkbox component for boolean parameters\n */\n\nimport { div, input, label } from '../../utils/html-tag';\nimport { Control } from '../controls';\n\nexport interface CheckboxProps {\n id: string;\n control: Control;\n value?: boolean;\n onChange?: (id: string, value: boolean) => void;\n}\n\n/**\n * Create checkbox element with event listener\n */\nexport function createCheckbox(container: HTMLElement, props: CheckboxProps): HTMLInputElement {\n const inputId = `input-${props.id}`;\n\n // Create input\n const inputElement = input({\n type: 'checkbox',\n id: inputId,\n checked: props.value || false,\n 'data-checkbox-id': props.id\n }) as HTMLInputElement;\n\n // Add event listener\n inputElement.addEventListener('change', (e) => {\n const checked = (e.target as HTMLInputElement).checked;\n\n // Call onChange callback\n if (props.onChange) {\n props.onChange(props.id, checked);\n }\n });\n\n // Create label\n const labelElement = label({ htmlFor: inputId }, props.control.label);\n\n // Create control group\n const controlGroup = div({ className: 'control-group' }, labelElement, inputElement);\n container.appendChild(controlGroup);\n\n return inputElement;\n}\n", "/**\n * Chainable API for building visualizations\n */\n\nimport { State, Timeline } from '../core/ivp';\n\nexport interface GridOptions {\n color?: string;\n alpha?: number;\n spacing?: number;\n}\n\nexport interface PlotOptions {\n color?: string;\n lineWidth?: number;\n dash?: number[];\n label?: string;\n}\n\nexport interface VectorOptions {\n color?: string;\n label?: string;\n scale?: number;\n width?: number;\n}\n\nexport interface SceneFunction {\n (ctx: DrawContext, state: State): void;\n}\n\nexport interface SelectorFunction {\n (state: State): number | [number, number];\n}\n\nexport interface VectorFunction {\n (state: State): [number, number];\n}\n\nexport interface DrawContext {\n line: (\n from: [number, number],\n to: [number, number],\n options?: { width?: number; color?: string; dash?: number[] }\n ) => void;\n circle: (\n center: [number, number],\n radius: number,\n options?: { fill?: string; stroke?: string; width?: number }\n ) => void;\n arrow: (\n from: [number, number],\n to: [number, number],\n options?: { width?: number; color?: string; headSize?: number }\n ) => void;\n text: (\n pos: [number, number],\n text: string,\n options?: { color?: string; size?: number; font?: string }\n ) => void;\n plot: (xValues: number[], yValues: number[], options?: PlotOptions) => void;\n}\n\nexport interface Layer {\n type: 'grid' | 'scene' | 'plot' | 'vector' | 'bounds' | 'axis';\n options?: any;\n draw?: string; // serialized function\n selector?: string; // serialized function\n at?: string; // serialized function\n dir?: string; // serialized function\n bounds?: { x?: [number, number] | 'auto'; y?: [number, number] | 'auto' };\n parametric?: boolean; // true for [x, y] plots\n}\n\nexport class ViewBuilder {\n private layers: Layer[] = [];\n private timeline?: Timeline;\n\n constructor(timeline?: Timeline) {\n this.timeline = timeline;\n }\n\n /**\n * Add custom scene drawing layer\n */\n scene(drawFn: SceneFunction): ViewBuilder {\n this.layers.push({\n type: 'scene',\n draw: this.serializeFunction(drawFn)\n });\n return this;\n }\n\n /**\n * Add plot layer\n */\n plot(selector: SelectorFunction, options: PlotOptions = {}): ViewBuilder {\n // Detect if selector is parametric (returns [x, y]) by testing it\n const isParametric = this.detectParametricSelector(selector);\n\n this.layers.push({\n type: 'plot',\n selector: this.serializeFunction(selector),\n parametric: isParametric,\n options: {\n color: '#2563eb',\n lineWidth: 2,\n fill: false,\n dash: [],\n label: '',\n alpha: 1,\n ...options\n }\n });\n return this;\n }\n\n /**\n * Add vector layer\n */\n vector(at: VectorFunction, dir: VectorFunction, options: VectorOptions = {}): ViewBuilder {\n this.layers.push({\n type: 'vector',\n at: this.serializeFunction(at),\n dir: this.serializeFunction(dir),\n options: {\n color: '#0ff',\n scale: 1,\n width: 2,\n ...options\n }\n });\n return this;\n }\n\n /**\n * Set bounds for coordinate system\n */\n bounds(bounds: { x?: [number, number] | 'auto'; y?: [number, number] | 'auto' }): ViewBuilder {\n this.layers.push({\n type: 'bounds',\n bounds: bounds\n });\n return this;\n }\n\n /**\n * Add grid layer\n */\n grid(options: any = {}): ViewBuilder {\n this.layers.push({\n type: 'grid',\n options: options\n });\n return this;\n }\n\n /**\n * Add axis layer\n */\n axis(options: any = {}): ViewBuilder {\n this.layers.push({\n type: 'axis',\n options: options\n });\n return this;\n }\n\n /**\n * Get all layers\n */\n getLayers(): Layer[] {\n return [...this.layers];\n }\n\n /**\n * Get timeline\n */\n getTimeline(): Timeline | undefined {\n return this.timeline;\n }\n\n /**\n * Set timeline (for when timeline is provided later)\n */\n setTimeline(timeline: Timeline): void {\n this.timeline = timeline;\n }\n\n /**\n * Serialize function or selector for HTML embedding\n */\n private serializeFunction(fn: (...args: any[]) => any): string {\n return fn.toString();\n }\n\n /**\n * Detect if selector function is parametric (returns [x, y])\n */\n private detectParametricSelector(selector: SelectorFunction): boolean {\n try {\n // Test with sample state to see if function returns array (parametric) or number (scalar)\n const testState = { x: 1, y: 2, z: 3 };\n const result = selector(testState);\n return Array.isArray(result) && result.length === 2;\n } catch {\n // If we can't determine, assume non-parametric\n return false;\n }\n }\n\n /**\n * Convert to ViewDescriptor for HTML rendering\n */\n toDescriptor(): {\n timeline: { times: number[]; states: Record<string, number[]> };\n layers: Layer[];\n } {\n return {\n timeline: {\n times: this.timeline?.times || [],\n states: this.timeline?.states || {}\n },\n layers: this.layers\n };\n }\n\n /**\n * Execute with timeline and return descriptor\n */\n executeWithTimeline(timeline: Timeline): {\n timeline: { times: number[]; states: Record<string, number[]> };\n layers: Layer[];\n } {\n const tempTimeline = this.timeline;\n this.timeline = timeline;\n const descriptor = this.toDescriptor();\n this.timeline = tempTimeline;\n return descriptor;\n }\n}\n\n/**\n * Main view function - now timeline-agnostic\n */\nexport function view(timeline?: Timeline): ViewBuilder {\n return new ViewBuilder(timeline);\n}\n", "/**\n * CalcPlot Client Initialization\n * Handles setup and initialization of visualizations\n */\n\nimport { SimulationEngine } from './SimulationEngine';\nimport { ViewRenderer } from './ViewRenderer';\nimport { createSlider } from '../../ui/components/Slider';\nimport { createCheckbox } from '../../ui/components/Checkbox';\nimport { createElement } from '../../utils/html-tag';\nimport { view } from '../../ui/ViewBuilder';\n\n// Make components available globally for client\nif (typeof globalThis !== 'undefined') {\n (globalThis as any).CalcPlotComponents = {\n createSlider: createSlider,\n createCheckbox: createCheckbox,\n view: view\n };\n}\n\n// Create controls for explore mode\nfunction createControls(\n data: any,\n container: HTMLElement,\n updateSimulation: () => void,\n log: (...args: any[]) => void\n): void {\n log(' Creating controls for:', Object.keys(data.params));\n const controlsDiv = createElement('div', {\n style: 'padding: 10px; border-bottom: 1px solid #ccc;'\n });\n container.appendChild(controlsDiv);\n\n Object.entries(data.params).forEach(([key, param]: [string, any]) => {\n if (param.type === 'slider') {\n const createSlider = (window as any).CalcPlotComponents.createSlider;\n if (createSlider) {\n createSlider(controlsDiv, {\n id: key,\n control: param,\n value: param.default, // Add initial value\n onChange: (id: string, value: number) => {\n updateSimulation();\n }\n });\n } else {\n log('\u274C createSlider not available');\n }\n } else if (param.type === 'checkbox') {\n const createCheckbox = (window as any).CalcPlotComponents.createCheckbox;\n if (createCheckbox) {\n createCheckbox(controlsDiv, {\n id: key,\n control: param,\n value: param.default,\n onChange: (id: string, value: boolean) => {\n log(`\u2611\uFE0F Checkbox ${id} changed to ${value}`);\n updateSimulation();\n }\n });\n } else {\n log('\u274C createCheckbox not available');\n }\n }\n });\n}\n\n// Create container wrapper for multiple views\nfunction createWrapper(container: HTMLElement, width: number, height: number, gaps: number): HTMLElement {\n const wrapper = createElement('div', {\n style: `display: flex; width: 100%; height: 100%;`\n });\n container.appendChild(wrapper);\n return wrapper;\n}\n\n// Initialize multiple views in container\nfunction initializeViews(views: any[], container: HTMLElement, width: number, height: number, log: (...args: any[]) => void): ViewRenderer[] {\n const layout = { columns: views.length, rows: 1, gaps: 10 };\n\n return views.map((viewData: any) => {\n const viewContainer = createElement('div', {\n style: `flex: 1; width: 0; height: 100%;`\n });\n container.appendChild(viewContainer);\n\n return new ViewRenderer(\n viewContainer,\n width / layout.columns,\n height / layout.rows,\n log\n );\n });\n}\n\n// Update all views with new data\nfunction updateViews(renderers: ViewRenderer[], views: any[], timeline: any, params: any, width: number, height: number): void {\n const layout = { columns: views.length, rows: 1, gaps: 10 };\n\n views.forEach((viewData: any, index: number) => {\n let descriptor;\n \n // Handle ViewBuilder layers\n if (viewData.layers && Array.isArray(viewData.layers)) {\n descriptor = {\n timeline: {\n times: timeline.times,\n states: timeline.states\n },\n layers: viewData.layers\n };\n } else {\n throw new Error('Invalid view configuration: expected layers array');\n }\n\n renderers[index].render({\n type: 'view',\n timeline,\n layers: descriptor.layers,\n width: width / layout.columns,\n height: height / layout.rows\n });\n });\n}\n\n// Initialize explore mode with controls and simulation\nfunction initializeExplore(data: any, container: HTMLElement, log: (...args: any[]) => void): void {\n log(' Initializing explore mode...');\n\n try {\n const views = data.views || [];\n const isMultiView = views.length > 1;\n const containerWidth = data.width || 800;\n const containerHeight = data.height || 600;\n\n // Create controls\n if (data.params) {\n createControls(data, container, updateSimulation, log);\n }\n\n const canvasContainer = isMultiView ? createWrapper(container, containerWidth, containerHeight, 10) : container;\n const renderers = isMultiView ? initializeViews(views, canvasContainer, containerWidth, containerHeight, log) : [new ViewRenderer(canvasContainer, containerWidth, containerHeight, log)];\n\n // Update simulation function\n function updateSimulation(): void {\n const currentParams: Record<string, any> = {};\n Object.entries(data.params).forEach(([key, param]: [string, any]) => {\n const slider = document.getElementById(`input-${key}`) as HTMLInputElement;\n if (slider) {\n currentParams[key] = parseFloat(slider.value);\n } else {\n currentParams[key] = param.default;\n }\n });\n\n try {\n const engine = new SimulationEngine(log);\n const initialFn = engine.parseInitialFunction(data.initial);\n const initialState = initialFn(currentParams);\n const trajectory = engine.simulateTrajectory(data, initialState, currentParams);\n\n if (isMultiView) {\n updateViews(renderers, views, trajectory, currentParams, containerWidth, containerHeight);\n } else {\n const viewData = views[0];\n if (viewData) {\n let descriptor;\n \n // Handle ViewBuilder layers\n if (viewData.layers && Array.isArray(viewData.layers)) {\n descriptor = {\n timeline: {\n times: trajectory.times,\n states: trajectory.states\n },\n layers: viewData.layers\n };\n } else {\n throw new Error('Invalid view configuration: expected layers array');\n }\n\n renderers[0].render({\n type: 'view',\n timeline: trajectory,\n layers: descriptor.layers,\n width: containerWidth,\n height: containerHeight\n });\n }\n }\n } catch (error: any) {\n log('\u274C Error in simulation:', error.message);\n }\n }\n\n updateSimulation();\n log(`\u2705 ${isMultiView ? 'Multi-view' : 'Single'} explore mode initialized`);\n } catch (error: any) {\n log('\u274C Error in explore initialization:', error.message);\n }\n}\n\n// Initialize show mode with pre-computed timeline\nfunction initializeShow(data: any, container: HTMLElement, log: (...args: any[]) => void): void {\n log('\uD83D\uDCCA Initializing show mode...');\n\n try {\n const views = data.views || [];\n const isMultiView = views.length > 1;\n\n if (isMultiView) {\n // Multi-view layout\n const layout = data.layout || { columns: views.length, rows: 1, gaps: 10 };\n const containerWidth = data.width || 800;\n const containerHeight = data.height || 600;\n\n const multiViewContainer = createElement('div', {\n style: `display: flex; flex-wrap: wrap; gap: ${layout.gaps}px; width: ${containerWidth}px; height: ${containerHeight}px;`\n });\n container.appendChild(multiViewContainer);\n\n // Create renderers for each view\n views.forEach((viewData: any) => {\n const viewContainer = createElement('div', {\n style: `flex: 1 1 calc(50% - 5px); min-width: 300px; height: calc(50% - 5px);`\n });\n multiViewContainer.appendChild(viewContainer);\n\n const renderer = new ViewRenderer(\n viewContainer,\n viewData.width || containerWidth / layout.columns,\n viewData.height || containerHeight / layout.rows,\n log\n );\n\n renderer.render(viewData);\n });\n\n log('\u2705 Multi-view show mode initialized');\n } else {\n // Single view\n const viewData = views[0];\n if (viewData) {\n const renderer = new ViewRenderer(container, viewData.width || 800, viewData.height || 600, log);\n renderer.render(viewData);\n }\n log('\u2705 Show mode initialized');\n }\n } catch (error: any) {\n log('\u274C Error in show initialization:', error.message);\n }\n}\n\n// Initialize compare mode with pre-computed timeline\nfunction initializeCompare(data: any, container: HTMLElement, log: (...args: any[]) => void): void {\n log('\uD83D\uDCCA Initializing compare mode...');\n\n try {\n const renderer = new ViewRenderer(container, data.width || 800, data.height || 600, log);\n renderer.render(data);\n log('\u2705 Compare mode initialized');\n } catch (error: any) {\n log('\u274C Error in compare initialization:', error.message);\n }\n}\n\n// Main initialization function\nexport function initializeClient(\n container: HTMLElement,\n data?: any,\n debugLog?: (...args: any[]) => void\n): void {\n const log =\n debugLog ||\n function (...args: any[]) {\n console.log('[calcplot]', ...args);\n };\n\n log('\uD83D\uDE80 Starting CalcPlot...');\n\n const calcData = data || (window as any).calcPlotData;\n if (!calcData) {\n log('\u274C No calcplot data found');\n return;\n }\n\n if (!container) {\n log('\u274C No container provided - visualization skipped');\n return;\n }\n\n log('\uD83D\uDCE6 Data received:', calcData.type);\n log('\uD83D\uDCE6 Using container:', container.id || 'unnamed');\n\n // Handle different data types\n if (calcData.type === 'explore') {\n initializeExplore(calcData, container, log);\n } else if (calcData.type === 'show') {\n initializeShow(calcData, container, log);\n } else if (calcData.type === 'compare') {\n initializeCompare(calcData, container, log);\n } else {\n log('\u274C Unknown data type:', calcData.type);\n }\n}\n", "export { initializeClient } from './init';\n\n// Re-export UI creation functions for client use\nexport { createCheckbox } from '../../ui/components/Checkbox';\nexport { createSlider } from '../../ui/components/Slider';\nexport { view } from '../../ui/ViewBuilder';\n\n// Make components available globally for client\nimport { initializeClient } from './init';\nimport { createCheckbox } from '../../ui/components/Checkbox';\nimport { createSlider } from '../../ui/components/Slider';\nimport { view } from '../../ui/ViewBuilder';\n\n// Create global components object\nif (typeof globalThis !== 'undefined') {\n (globalThis as any).CalcPlotComponents = {\n initializeClient: initializeClient,\n createSlider: createSlider,\n createCheckbox: createCheckbox,\n view: view\n };\n}\n", "/**\n * CalcPlot Client Bundle\n * Runtime components for browser visualization\n */\n\n// Import and export all client runtime components\nimport { initializeClient, createCheckbox, createSlider } from './client/index';\nimport { view } from '../ui/ViewBuilder';\n\n// Make available globally for IIFE bundle\nif (typeof globalThis !== 'undefined') {\n (globalThis as any).CalcPlotClient = {\n initializeClient,\n createCheckbox,\n createSlider,\n view\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["fnStr", "serialized", "key", "key", "key", "key", "key", "createSlider", "createCheckbox", "updateSimulation"]
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var CalcPlotClient=(()=>{var b=class{static parseFunction(t){let e=t.trim(),i=e.match(/^\(([^)]+)\)\s*=>\s*\{([\s\S]*)\}$/);if(i)return i[2].trim();let n=e.match(/^(\w+)\s*=>\s*\{([\s\S]*)\}$/);if(n)return n[2].trim();let r=e.match(/^\(([^)]+)\)\s*=>\s*(.+)$/s);if(r)return`return ${r[2].trim()}`;let s=e.match(/^(\w+)\s*=>\s*(.+)$/s);if(s)return`return ${s[2].trim()}`;let c=e.match(/^function\s*\([^)]*\)\s*\{([\s\S]*)\}$/);return c?c[1].trim():e}static createFunction(t,e){return new Function(...t,e)}static parseAndCreateFunction(t,e){let i=this.parseFunction(e);return this.createFunction(t,i)}};function _(u){return{state:u.state,params:u.params,derivatives:D(u.derivatives),events:u.events?D(u.events):void 0}}function X(u){let t={};for(let[e,i]of Object.entries(u))t[e]={type:i.type||"slider",min:i.min,max:i.max,default:i.default,label:i.label||e,step:i.step||.01};return t}function J(u){return{times:u.times,states:u.states}}function K(u){let t={};for(let[e,i]of Object.entries(u))t[e]=i.default;return t}function Q(serialized){let functions={};for(let[key,fnStr]of Object.entries(serialized))try{fnStr.includes("=>")?functions[key]=eval(`(${fnStr})`):fnStr.startsWith("function")?functions[key]=eval(`(${fnStr})`):functions[key]=eval(`(state, params) => ${fnStr}`)}catch(u){console.error("Error deserializing function",key,u),functions[key]=()=>0}return functions}function D(u){let t={};for(let[e,i]of Object.entries(u))typeof i=="function"?t[e]=i.toString():typeof i=="object"&&i!==null?t[e]=JSON.stringify(i):t[e]=String(i);return t}var R=class{constructor(t){this.log=t}simulateTrajectory(t,e,i){if(!e||typeof e!="object")throw new Error(`Invalid initialState: expected object, got ${typeof e}. Value: ${e}`);let s={...t.model?.params||{},...i||{}},{dt:c=.01,maxTime:a=10}=t.options||{},o=[],l={};Object.keys(e).forEach(p=>{l[p]=[]});let h={...e},d=0,f=t.model?.derivatives||t.derivatives;if(!f)throw new Error("No derivatives found in data.model.derivatives or data.derivatives");let x={};for(Object.entries(f).forEach(([p,m])=>{x[p]=b.parseAndCreateFunction(["s","p"],m)});d<=a&&h.y>=0;){o.push(d),Object.keys(h).forEach(m=>{l[m].push(h[m])});let p={};Object.entries(x).forEach(([m,v])=>{p[m]=v(h,s)}),Object.keys(h).forEach(m=>{p[m]!==void 0&&(h[m]+=p[m]*c)}),d+=c}return{times:o,states:l}}parseInitialFunction(t){try{return b.parseAndCreateFunction(["p"],t)}catch(e){throw console.error("\u274C parseInitialFunction error:",e),e}}};var k=class{constructor(t,e,i=.1){this.canvasWidth=t;this.canvasHeight=e;this.padding=i;this.dataBounds={x:[0,1],y:[0,1]};this.viewBounds={x:[0,1],y:[0,1]};this.plotArea=this.calculateDefaultPlotArea(),this.originalViewBounds={...this.viewBounds}}calculateDefaultPlotArea(){let e=this.canvasWidth-50,i=50,n=this.canvasHeight-80;return{left:80,top:i,right:e,bottom:n,width:e-80,height:n-i}}updateDataBounds(t,e){if(t.length===0||e.length===0)return;let i=Math.min(...t),n=Math.max(...t),r=Math.min(...e),s=Math.max(...e);i===n?this.dataBounds.x=[i-1,n+1]:this.dataBounds.x=[i,n],r===s?this.dataBounds.y=[r-1,s+1]:this.dataBounds.y=[r,s]}autoScale(){let[t,e]=this.dataBounds.x,[i,n]=this.dataBounds.y,r=e-t||1,s=n-i||1;this.originalViewBounds={x:[t-r*this.padding,e+r*this.padding],y:[i-s*this.padding,n+s*this.padding]},this.viewBounds={...this.originalViewBounds}}adjustAspectRatio(t="auto"){if(t==="auto"){this.originalViewBounds&&(this.viewBounds={...this.originalViewBounds});return}let[e,i]=this.viewBounds.x,[n,r]=this.viewBounds.y,s=i-e,c=r-n;if(s===0||c===0)return;let a=this.plotArea.width/s,o=this.plotArea.height/c;if(a!==o)if(a<o){let l=s*(this.plotArea.height/this.plotArea.width),h=(n+r)/2;this.viewBounds.y=[h-l/2,h+l/2]}else{let l=c*(this.plotArea.width/this.plotArea.height),h=(e+i)/2;this.viewBounds.x=[h-l/2,h+l/2]}}toCanvas(t,e){let[i,n]=this.viewBounds.x,[r,s]=this.viewBounds.y,c=n-i||1,a=s-r||1,o=this.plotArea.left+(t-i)/c*this.plotArea.width,l=this.plotArea.bottom-(e-r)/a*this.plotArea.height;return[o,l]}getViewBounds(){return{...this.viewBounds}}getPlotArea(){return{...this.plotArea}}setViewBounds(t){this.viewBounds={...t},this.originalViewBounds={...t}}updatePlotArea(t){this.plotArea={...this.plotArea,...t,width:(t.right??this.plotArea.right)-(t.left??this.plotArea.left),height:(t.bottom??this.plotArea.bottom)-(t.top??this.plotArea.top)}}isInPlotArea(t,e){let[i,n]=this.toCanvas(t,e);return i>=this.plotArea.left&&i<=this.plotArea.right&&n>=this.plotArea.top&&n<=this.plotArea.bottom}getDataCenter(){let[t,e]=this.dataBounds.x,[i,n]=this.dataBounds.y;return[(t+e)/2,(i+n)/2]}};var y=class{static calculateNiceStep(t,e){if(t<=0)return 1;let i=t/e,n=Math.floor(Math.log10(i)),r=i/Math.pow(10,n),s;return r<=1.5?s=1:r<=3?s=2:r<=7?s=5:s=10,s*Math.pow(10,n)}static formatTickLabel(t,e){if(e>=1e3||e<.01&&e>0)return t.toExponential(1);let i=0;return e<1&&(i=Math.ceil(-Math.log10(e))),t.toFixed(i).replace(/\.0+$/,"")}static interpolateData(t,e,i=100){if(t.length<2)return{x:t,y:e};let n=[],r=[];for(let s=0;s<i;s++){let a=s/(i-1)*(t.length-1),o=Math.floor(a),l=Math.min(o+1,t.length-1),h=a-o;n.push(t[o]*(1-h)+t[l]*h),r.push(e[o]*(1-h)+e[l]*h)}return{x:n,y:r}}static getColorByIndex(t){let e=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#14b8a6","#f97316"];return e[t%e.length]}};var E=class{constructor(t,e,i,n){this.ctx=t;this.getBounds=e;this.toCanvas=i;this.getPlotArea=n}drawGrid(t={}){let{showGrid:e=!0,gridColor:i="#e0e0e0"}=t;if(!e)return;let n=this.getBounds(),r=this.getPlotArea(),{xTicks:s,yTicks:c}=this.calculateTicks();this.ctx.save(),this.ctx.strokeStyle=i,this.ctx.lineWidth=1,this.ctx.setLineDash([2,2]),s.values.forEach(a=>{if(a===0)return;let[o,l]=this.toCanvas(a,n.y[0]),[,h]=this.toCanvas(a,n.y[1]);this.ctx.beginPath(),this.ctx.moveTo(o,Math.max(l,r.top)),this.ctx.lineTo(o,Math.min(h,r.bottom)),this.ctx.stroke()}),c.values.forEach(a=>{if(a===0)return;let[o,l]=this.toCanvas(n.x[0],a),[h]=this.toCanvas(n.x[1],a);this.ctx.beginPath(),this.ctx.moveTo(Math.max(o,r.left),l),this.ctx.lineTo(Math.min(h,r.right),l),this.ctx.stroke()}),this.ctx.restore()}drawAxes(t,e,i={}){let{showTicks:n=!0,showLabels:r=!0}=i,{xTicks:s,yTicks:c}=this.calculateTicks();this.ctx.save(),this.ctx.strokeStyle="#666",this.ctx.fillStyle="#666",this.ctx.lineWidth=2,this.ctx.font="12px sans-serif";let[a,o]=this.toCanvas(0,0),[l,h]=this.toCanvas(0,0),d=this.getPlotArea();o>=d.top&&o<=d.bottom&&(this.ctx.beginPath(),this.ctx.moveTo(d.left,o),this.ctx.lineTo(d.right,o),this.ctx.stroke()),l>=d.left&&l<=d.right&&(this.ctx.beginPath(),this.ctx.moveTo(l,d.top),this.ctx.lineTo(l,d.bottom),this.ctx.stroke()),(n||r)&&(this.ctx.textAlign="center",this.ctx.textBaseline="top",s.values.forEach(f=>{let[x,p]=this.toCanvas(f,0),m=this.getPlotArea();x>=m.left&&x<=m.right&&(n&&(this.ctx.beginPath(),this.ctx.moveTo(x,p-5),this.ctx.lineTo(x,p+5),this.ctx.stroke()),r&&f!==0&&this.ctx.fillText(s.labels[s.values.indexOf(f)],x,p+10))}),this.ctx.textAlign="right",this.ctx.textBaseline="middle",c.values.forEach(f=>{let[x,p]=this.toCanvas(0,f),m=this.getPlotArea();p>=m.top&&p<=m.bottom&&(n&&(this.ctx.beginPath(),this.ctx.moveTo(x-5,p),this.ctx.lineTo(x+5,p),this.ctx.stroke()),r&&f!==0&&this.ctx.fillText(c.labels[c.values.indexOf(f)],x-10,p))})),this.ctx.restore(),(t||e)&&(this.ctx.save(),this.ctx.fillStyle="#333",this.ctx.font="14px sans-serif",t&&(this.ctx.textAlign="center",this.ctx.textBaseline="top",this.ctx.fillText(t,d.left+d.width/2,d.bottom+40)),e&&(this.ctx.save(),this.ctx.textAlign="center",this.ctx.translate(25,d.top+d.height/2),this.ctx.rotate(-Math.PI/2),this.ctx.fillText(e,0,0),this.ctx.restore()),this.ctx.restore())}calculateTicks(){let t=this.getBounds(),e=t.x[1]-t.x[0],i=t.y[1]-t.y[0],n=y.calculateNiceStep(e,6),r=y.calculateNiceStep(i,5),s=Math.ceil(t.x[0]/n)*n,c=Math.ceil(t.y[0]/r)*r,a=[],o=[];for(let l=s;l<=t.x[1];l+=n)a.push(l);for(let l=c;l<=t.y[1];l+=r)o.push(l);return{xTicks:{values:a,labels:a.map(l=>y.formatTickLabel(l,n)),step:n},yTicks:{values:o,labels:o.map(l=>y.formatTickLabel(l,r)),step:r}}}};var z=class{constructor(t,e,i){this.ctx=t;this.toCanvas=e;this.getPlotArea=i}plot(t,e,i={}){if(t.length===0)return;let{lineColor:n="#3b82f6",lineWidth:r=2,marker:s="none",smooth:c=!0}=i;this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(this.getPlotArea().left,this.getPlotArea().top,this.getPlotArea().width,this.getPlotArea().height),this.ctx.clip(),this.ctx.strokeStyle=n,this.ctx.fillStyle=n,this.ctx.lineWidth=r,this.ctx.lineJoin="round",this.ctx.lineCap="round";let a=c&&t.length>2?y.interpolateData(t,e):{x:t,y:e};this.ctx.beginPath();for(let o=0;o<a.x.length;o++){let[l,h]=this.toCanvas(a.x[o],a.y[o]);o===0?this.ctx.moveTo(l,h):this.ctx.lineTo(l,h)}if(this.ctx.stroke(),s!=="none")for(let o=0;o<t.length;o++){let[l,h]=this.toCanvas(t[o],e[o]);s==="circle"?(this.ctx.beginPath(),this.ctx.arc(l,h,3,0,Math.PI*2),this.ctx.fill()):s==="square"&&this.ctx.fillRect(l-3,h-3,6,6)}this.ctx.restore()}drawVectors(t,e,i,n,r={}){let{scale:s=this.calculateAutoScale(i,n),color:c="#10b981",headSize:a=8}=r;this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(this.getPlotArea().left,this.getPlotArea().top,this.getPlotArea().width,this.getPlotArea().height),this.ctx.clip(),this.ctx.strokeStyle=c,this.ctx.fillStyle=c,this.ctx.lineWidth=2;for(let o=0;o<t.length;o++){let l=this.toCanvas(t[o],e[o]),h=this.toCanvas(t[o]+i[o]/s,e[o]+n[o]/s);this.ctx.beginPath(),this.ctx.moveTo(l[0],l[1]),this.ctx.lineTo(h[0],h[1]),this.ctx.stroke(),this.drawArrowhead(h[0],h[1],l,a)}this.ctx.restore()}calculateAutoScale(t,e){let i=t.map((r,s)=>Math.sqrt(r*r+e[s]*e[s])),n=Math.max(...i);return n>0?n/30:1}drawArrowhead(t,e,i,n){let r=Math.atan2(e-i[1],t-i[0]);this.ctx.beginPath(),this.ctx.moveTo(t,e),this.ctx.lineTo(t-n*Math.cos(r-Math.PI/6),e-n*Math.sin(r-Math.PI/6)),this.ctx.lineTo(t-n*Math.cos(r+Math.PI/6),e-n*Math.sin(r+Math.PI/6)),this.ctx.closePath(),this.ctx.fill()}};var L=class{constructor(t,e){this.ctx=t;this.getPlotArea=e}drawTitle(t){this.ctx.save(),this.ctx.font="bold 16px sans-serif",this.ctx.fillStyle="#333",this.ctx.textAlign="center",this.ctx.fillText(t,this.getPlotArea().left+this.getPlotArea().width/2,25),this.ctx.restore()}drawAxisLabels(t,e){this.ctx.save(),this.ctx.fillStyle="#333",this.ctx.font="14px sans-serif",t&&(this.ctx.textAlign="center",this.ctx.fillText(t,this.getPlotArea().left+this.getPlotArea().width/2,this.getPlotArea().bottom+40)),e&&(this.ctx.save(),this.ctx.textAlign="center",this.ctx.translate(25,this.getPlotArea().top+this.getPlotArea().height/2),this.ctx.rotate(-Math.PI/2),this.ctx.fillText(e,0,0),this.ctx.restore()),this.ctx.restore()}drawLegend(t,e="top-right"){if(t.length===0)return;this.ctx.save(),this.ctx.font="12px sans-serif";let i=20,n=10,r=30,c=Math.max(...t.map(d=>this.ctx.measureText(d.label).width))+r+n*3,a=t.length*i+n*2,o,l,h=10;switch(e){case"top-right":o=this.getPlotArea().right-c-h,l=this.getPlotArea().top+h;break;case"top-left":o=this.getPlotArea().left+h,l=this.getPlotArea().top+h;break;case"bottom-right":o=this.getPlotArea().right-c-h,l=this.getPlotArea().bottom-a-h;break;case"bottom-left":o=this.getPlotArea().left+h,l=this.getPlotArea().bottom-a-h;break;default:o=this.getPlotArea().right-c-h,l=this.getPlotArea().top+h}this.ctx.fillStyle="rgba(255, 255, 255, 0.95)",this.ctx.strokeStyle="#ccc",this.ctx.lineWidth=1,this.ctx.fillRect(o,l,c,a),this.ctx.strokeRect(o,l,c,a),t.forEach((d,f)=>{let x=l+n+f*i+i/2;this.ctx.strokeStyle=d.color,this.ctx.lineWidth=d.lineStyle?.width||2,d.lineStyle?.dash?this.ctx.setLineDash(d.lineStyle.dash):this.ctx.setLineDash([]),this.ctx.beginPath(),this.ctx.moveTo(o+n,x),this.ctx.lineTo(o+n+r,x),this.ctx.stroke(),this.ctx.fillStyle="#333",this.ctx.setLineDash([]),this.ctx.fillText(d.label,o+n+r+10,x+4)}),this.ctx.restore()}};var T=class{constructor(t,e,i){this.ctx=t;this.width=e;this.height=i;this.bounds=new k(e,i),this.axisRenderer=new E(t,()=>this.bounds.getViewBounds(),(n,r)=>this.bounds.toCanvas(n,r),()=>this.bounds.getPlotArea()),this.data=new z(t,(n,r)=>this.bounds.toCanvas(n,r),()=>this.bounds.getPlotArea()),this.labels=new L(t,()=>this.bounds.getPlotArea())}plot(t,e,i={}){return this.clear(),this.bounds.updateDataBounds(t,e),i.autoScale!==!1&&this.bounds.autoScale(),i.aspectRatio==="equal"?this.bounds.adjustAspectRatio("equal"):this.bounds.adjustAspectRatio("auto"),this.axisRenderer.drawGrid(i),this.axisRenderer.drawAxes(i.xLabel,i.yLabel,i),this.data.plot(t,e,i),i.title&&this.labels.drawTitle(i.title),this.labels.drawAxisLabels(i.xLabel,i.yLabel),this}plotMultiple(t,e={}){this.clear();let i=[],n=[];return t.forEach(r=>{i.push(...r.x),n.push(...r.y)}),this.bounds.updateDataBounds(i,n),e.autoScale!==!1&&this.bounds.autoScale(),e.aspectRatio==="equal"?this.bounds.adjustAspectRatio("equal"):this.bounds.adjustAspectRatio("auto"),this.axisRenderer.drawGrid(e),this.axisRenderer.drawAxes(e.xLabel,e.yLabel,e),t.forEach((r,s)=>{this.data.plot(r.x,r.y,{...e,lineColor:r.color||y.getColorByIndex(s)})}),e.title&&this.labels.drawTitle(e.title),this.labels.drawAxisLabels(e.xLabel,e.yLabel),this}drawVectors(t,e,i,n,r={}){return this.data.drawVectors(t,e,i,n,r),this}addLegend(t,e="top-right"){this.labels.drawLegend(t,e)}clear(){this.ctx.fillStyle="#f8f9fa",this.ctx.fillRect(0,0,this.width,this.height)}setBounds(t){this.bounds.setViewBounds(t)}getPlotArea(){return this.bounds.getPlotArea()}drawGrid(t={}){this.axisRenderer.drawGrid(t)}drawAxis(t={}){this.axisRenderer.drawAxes(t.x,t.y,t)}setBoundsWithAuto(t,e){t.x&&Array.isArray(t.x)?this.setBounds(t):e&&this.setBounds(e)}setBoundsWithAutoAndAspectRatio(t,e){t.x&&Array.isArray(t.x)?this.setBounds(t):e&&(this.setBounds(e),this.bounds.adjustAspectRatio("equal"))}createDrawContext(){let t=this;return{plot:(e,i,n={})=>{t.data.plot(e,i,n)},line:(e,i,n={})=>{let[r,s]=t.bounds.toCanvas(e[0],e[1]),[c,a]=t.bounds.toCanvas(i[0],i[1]);t.ctx.beginPath(),t.ctx.moveTo(r,s),t.ctx.lineTo(c,a),t.ctx.strokeStyle=n.color||"#2563eb",t.ctx.lineWidth=n.width||1,n.dash?t.ctx.setLineDash(n.dash):t.ctx.setLineDash([]),t.ctx.stroke()},circle:(e,i,n={})=>{let[r,s]=t.bounds.toCanvas(e[0],e[1]),c=t.bounds.getViewBounds(),a=t.bounds.getPlotArea(),o=c.x[1]-c.x[0],l=a.width/o,h=i*l;t.ctx.beginPath(),t.ctx.arc(r,s,h,0,2*Math.PI),n.fill&&(t.ctx.fillStyle=n.fill,t.ctx.fill()),n.stroke&&(t.ctx.strokeStyle=n.stroke,t.ctx.lineWidth=n.width||1,t.ctx.stroke())},arrow:(e,i,n={})=>{let[r,s]=t.bounds.toCanvas(e[0],e[1]),[c,a]=t.bounds.toCanvas(i[0],i[1]),o=n.headSize||10;t.ctx.beginPath(),t.ctx.moveTo(r,s),t.ctx.lineTo(c,a),t.ctx.strokeStyle=n.color||"#2563eb",t.ctx.lineWidth=n.width||2,t.ctx.stroke();let l=Math.atan2(a-s,c-r);t.ctx.beginPath(),t.ctx.moveTo(c,a),t.ctx.lineTo(c-o*Math.cos(l-Math.PI/6),a-o*Math.sin(l-Math.PI/6)),t.ctx.moveTo(c,a),t.ctx.lineTo(c-o*Math.cos(l+Math.PI/6),a-o*Math.sin(l+Math.PI/6)),t.ctx.stroke()},text:(e,i,n={})=>{let[r,s]=t.bounds.toCanvas(e[0],e[1]);t.ctx.font=`${n.size||14}px ${n.font||"system-ui"}`,t.ctx.fillStyle=n.color||"#1f2937",t.ctx.fillText(i,r,s)}}}debugInfo(){return{viewBounds:this.bounds.getViewBounds(),plotArea:this.bounds.getPlotArea(),dataBounds:this.bounds.dataBounds}}};var w=class{constructor(t,e=800,i=600,n){this.container=t,this.log=n,this.targetWidth=e,this.targetHeight=i,this.canvas=this.createCanvas(e,i),this.renderer=new T(this.canvas.getContext("2d"),this.canvas.width,this.canvas.height),this.setupResizeObserver()}createCanvas(t,e){let i=document.createElement("div");i.innerHTML=`<canvas width="${t}" height="${e}"></canvas>`;let n=i.firstChild;return n.style&&(n.style.width="100%",n.style.height="100%",n.style.display="block"),this.container.appendChild(n),n}setupResizeObserver(){typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(t=>{for(let e of t){let{width:i,height:n}=e.contentRect;(i!==this.targetWidth||n!==this.targetHeight)&&this.updateCanvasSize(i,n)}}),this.resizeObserver.observe(this.container))}updateCanvasSize(t,e){this.canvas.width=Math.floor(t),this.canvas.height=Math.floor(e),this.targetWidth=Math.floor(t),this.targetHeight=Math.floor(e),this.renderer=new T(this.canvas.getContext("2d"),this.canvas.width,this.canvas.height),this.currentData&&this.renderInternal(this.currentData)}renderInternal(t){let e=t.layers||[];t.viewDescriptor&&t.viewDescriptor.layers&&(e=t.viewDescriptor.layers),this.renderer.clear();let i=e.find(a=>a.type==="bounds");if(i&&i.bounds){console.log("Found explicit bounds:",JSON.stringify(i.bounds));let a=this.calculateBoundsFromTimeline(t.timeline),l=e.find(h=>h.type==="axis")?.options?.aspectRatio==="equal";console.log("Has aspectRatio equal:",l),l?this.renderer.setBoundsWithAutoAndAspectRatio(i.bounds,a):this.renderer.setBoundsWithAuto(i.bounds,a)}else{console.log("No explicit bounds found, using auto bounds");let a=this.calculateBoundsFromTimeline(t.timeline,e);this.renderer.setBounds(a)}let n={grid:1,axis:2,plot:3},r=e.filter(a=>a.type!=="bounds").sort((a,o)=>(n[a.type]||999)-(n[o.type]||999)),s=[],c=[];if(r.forEach((a,o)=>{switch(a.type){case"grid":this.renderer.drawGrid(a.options||{});break;case"axis":this.renderer.drawAxis(a.options||{});break;case"plot":if(a.selector){a.options?.label&&s.push({label:a.options.label,color:a.options.color||"#2563eb",lineStyle:{width:a.options.lineWidth||2,dash:a.options.dash||[]}});let l=this.extractPlotData(t.timeline,a);l&&c.push({x:l.xValues,y:l.yValues,color:a.options?.color})}break;case"scene":a.draw&&this.renderScene(t.timeline,a);break;default:break}}),c.length>0){let a={},o=r.find(l=>l.type==="axis");o&&(a=o.options||{}),this.renderer.plotMultiple(c,{...t.options,aspectRatio:a.aspectRatio,autoScale:!1})}s.length>0&&this.renderer.addLegend(s,"top-right")}render(t){t.timeline&&(this.currentData=t,this.renderInternal(t))}extractPlotData(t,e){let{selector:i}=e,n=!1;try{let s={x:0,y:0},c=b.parseAndCreateFunction(["s"],i)(s);n=Array.isArray(c)&&c.length===2}catch{n=!1}let r;try{r=b.parseAndCreateFunction(["s"],i)}catch(s){return this.log("\u26A0\uFE0F Failed to compile selector:",s),null}if(n){let c=t.times.map((l,h)=>{let d=Object.keys(t.states).reduce((f,x)=>(f[x]=t.states[x][h],f),{});return r(d)}).filter(l=>Array.isArray(l)&&l.length===2&&typeof l[0]=="number"&&typeof l[1]=="number"),a=c.map(l=>l[0]),o=c.map(l=>l[1]);return{xValues:a,yValues:o}}else{let s=t.times.map((c,a)=>{let o=Object.keys(t.states).reduce((l,h)=>(l[h]=t.states[h][a],l),{});return r(o)});return{xValues:t.times,yValues:s}}}renderPlot(t,e){let{selector:i,options:n={}}=e,r=!1;try{let c={x:0,y:0},a=b.parseAndCreateFunction(["s"],i)(c);r=Array.isArray(a)&&a.length===2}catch{r=!1}let s;try{s=b.parseAndCreateFunction(["s"],i),this.log("\u2705 selector created successfully")}catch(c){this.log("\u26A0\uFE0F Failed to compile selector:",c),s=a=>0}if(r){let a=t.times.map((h,d)=>{let f=Object.keys(t.states).reduce((x,p)=>(x[p]=t.states[p][d],x),{});return s(f)}).filter(h=>Array.isArray(h)&&h.length===2&&typeof h[0]=="number"&&typeof h[1]=="number"),o=a.map(h=>h[0]),l=a.map(h=>h[1]);this.renderer.plot(o,l,n)}else{let c=t.times.map((a,o)=>{let l=Object.keys(t.states).reduce((h,d)=>(h[d]=t.states[d][o],h),{});return s(l)});this.renderer.plot(t.times,c,n)}}renderScene(t,e){let{draw:i}=e;if(!i)return;let n;try{n=b.parseAndCreateFunction(["ctx","state"],i)}catch(r){this.log("\u26A0\uFE0F Failed to compile scene function:",r);return}t.times.forEach((r,s)=>{let c=Object.keys(t.states).reduce((a,o)=>(a[o]=t.states[o][s],a),{});try{n(this.renderer.createDrawContext(),c)}catch(a){this.log("\u26A0\uFE0F Error in scene function:",a)}})}renderExplore(t,e){this.currentTimeline=e,this.render({type:"view",timeline:e,layers:t.layers,options:t.options,viewDescriptor:t.viewDescriptor})}calculateBoundsFromTimeline(t,e){let i=1/0,n=-1/0,r=1/0,s=-1/0;if(e){let o=e.filter(l=>l.type==="plot"&&l.selector);for(let l of o)try{let h=b.parseAndCreateFunction(["s"],l.selector),f=h({x:0,y:0});if(Array.isArray(f)&&f.length===2){let p=t.times.map((m,v)=>{let O=Object.keys(t.states).reduce((C,S)=>(C[S]=t.states[S][v],C),{});return h(O)}).filter(m=>Array.isArray(m)&&m.length===2&&typeof m[0]=="number"&&typeof m[1]=="number");for(let m of p)i=Math.min(i,m[0]),n=Math.max(n,m[0]),r=Math.min(r,m[1]),s=Math.max(s,m[1])}else{let p=t.times.map((m,v)=>{let O=Object.keys(t.states).reduce((C,S)=>(C[S]=t.states[S][v],C),{});return h(O)}).filter(m=>typeof m=="number");i=Math.min(i,...t.times),n=Math.max(n,...t.times),r=Math.min(r,...p),s=Math.max(s,...p)}}catch(h){this.log("\u26A0\uFE0F Failed to analyze selector for bounds:",h)}}i===1/0&&t.times&&(i=Math.min(...t.times),n=Math.max(...t.times)),i===1/0&&(i=0),n===-1/0&&(n=10),r===1/0&&(r=-10),s===-1/0&&(s=10);let c=(n-i)*.1||1,a=(s-r)*.1||1;return{x:[i-c,n+c],y:[r-a,s+a]}}};function g(u,t={},...e){let i=document.createElement(u);return Object.entries(t).forEach(([n,r])=>{n==="className"?i.className=r:n.startsWith("data-")?i.setAttribute(n,String(r)):n in i?i[n]=r:i.setAttribute(n,String(r))}),e.flat().forEach(n=>{typeof n=="string"?i.appendChild(document.createTextNode(n)):n instanceof HTMLElement&&i.appendChild(n)}),i}var V=(u={},...t)=>g("div",u,...t),j=(u={},...t)=>g("span",u,...t),F=(u={})=>g("input",u),H=(u={},...t)=>g("label",u,...t);function A(u,t){let e=`input-${t.id}`,i=`val-${t.id}`,n=j({className:"value-display",id:i},typeof t.value=="number"?t.value.toFixed(2):String(t.value)),r=F({type:"range",id:e,min:String(t.control.min),max:String(t.control.max),step:String(t.control.step||.01),value:String(t.value),"data-slider-id":t.id});r.addEventListener("input",a=>{let o=parseFloat(a.target.value);n.textContent=o.toFixed(2),t.onChange&&t.onChange(t.id,o)});let s=H({htmlFor:e},t.control.label),c=V({className:"control-group"},s,r,n);return u.appendChild(c),r}function M(u,t){let e=`input-${t.id}`,i=F({type:"checkbox",id:e,checked:t.value||!1,"data-checkbox-id":t.id});i.addEventListener("change",s=>{let c=s.target.checked;t.onChange&&t.onChange(t.id,c)});let n=H({htmlFor:e},t.control.label),r=V({className:"control-group"},n,i);return u.appendChild(r),i}var I=class{constructor(t){this.layers=[];this.timeline=t}scene(t){return this.layers.push({type:"scene",draw:this.serializeFunction(t)}),this}plot(t,e={}){let i=this.detectParametricSelector(t);return this.layers.push({type:"plot",selector:this.serializeFunction(t),parametric:i,options:{color:"#2563eb",lineWidth:2,fill:!1,dash:[],label:"",alpha:1,...e}}),this}vector(t,e,i={}){return this.layers.push({type:"vector",at:this.serializeFunction(t),dir:this.serializeFunction(e),options:{color:"#0ff",scale:1,width:2,...i}}),this}bounds(t){return this.layers.push({type:"bounds",bounds:t}),this}grid(t={}){return this.layers.push({type:"grid",options:t}),this}axis(t={}){return this.layers.push({type:"axis",options:t}),this}getLayers(){return[...this.layers]}getTimeline(){return this.timeline}setTimeline(t){this.timeline=t}serializeFunction(t){return t.toString()}detectParametricSelector(t){try{let i=t({x:1,y:2,z:3});return Array.isArray(i)&&i.length===2}catch{return!1}}toDescriptor(){return{timeline:{times:this.timeline?.times||[],states:this.timeline?.states||{}},layers:this.layers}}executeWithTimeline(t){let e=this.timeline;this.timeline=t;let i=this.toDescriptor();return this.timeline=e,i}};function P(u){return new I(u)}typeof globalThis<"u"&&(globalThis.CalcPlotComponents={createSlider:A,createCheckbox:M,view:P});function $(u,t,e,i){i(" Creating controls for:",Object.keys(u.params));let n=g("div",{style:"padding: 10px; border-bottom: 1px solid #ccc;"});t.appendChild(n),Object.entries(u.params).forEach(([r,s])=>{if(s.type==="slider"){let c=window.CalcPlotComponents.createSlider;c?c(n,{id:r,control:s,value:s.default,onChange:(a,o)=>{e()}}):i("\u274C createSlider not available")}else if(s.type==="checkbox"){let c=window.CalcPlotComponents.createCheckbox;c?c(n,{id:r,control:s,value:s.default,onChange:(a,o)=>{i(`\u2611\uFE0F Checkbox ${a} changed to ${o}`),e()}}):i("\u274C createCheckbox not available")}})}function W(u,t,e,i){let n=g("div",{style:"display: flex; width: 100%; height: 100%;"});return u.appendChild(n),n}function N(u,t,e,i,n){let r={columns:u.length,rows:1,gaps:10};return u.map(s=>{let c=g("div",{style:"flex: 1; width: 0; height: 100%;"});return t.appendChild(c),new w(c,e/r.columns,i/r.rows,n)})}function q(u,t,e,i,n,r){let s={columns:t.length,rows:1,gaps:10};t.forEach((c,a)=>{let o;if(c.layers&&Array.isArray(c.layers))o={timeline:{times:e.times,states:e.states},layers:c.layers};else throw new Error("Invalid view configuration: expected layers array");u[a].render({type:"view",timeline:e,layers:o.layers,width:n/s.columns,height:r/s.rows})})}function G(u,t,e){e(" Initializing explore mode...");try{let l=function(){let h={};Object.entries(u.params).forEach(([d,f])=>{let x=document.getElementById(`input-${d}`);x?h[d]=parseFloat(x.value):h[d]=f.default});try{let d=new R(e),x=d.parseInitialFunction(u.initial)(h),p=d.simulateTrajectory(u,x,h);if(r)q(o,n,p,h,s,c);else{let m=n[0];if(m){let v;if(m.layers&&Array.isArray(m.layers))v={timeline:{times:p.times,states:p.states},layers:m.layers};else throw new Error("Invalid view configuration: expected layers array");o[0].render({type:"view",timeline:p,layers:v.layers,width:s,height:c})}}}catch(d){e("\u274C Error in simulation:",d.message)}};var i=l;let n=u.views||[],r=n.length>1,s=u.width||800,c=u.height||600;u.params&&$(u,t,l,e);let a=r?W(t,s,c,10):t,o=r?N(n,a,s,c,e):[new w(a,s,c,e)];l(),e(`\u2705 ${r?"Multi-view":"Single"} explore mode initialized`)}catch(n){e("\u274C Error in explore initialization:",n.message)}}function U(u,t,e){e("\u{1F4CA} Initializing show mode...");try{let i=u.views||[];if(i.length>1){let r=u.layout||{columns:i.length,rows:1,gaps:10},s=u.width||800,c=u.height||600,a=g("div",{style:`display: flex; flex-wrap: wrap; gap: ${r.gaps}px; width: ${s}px; height: ${c}px;`});t.appendChild(a),i.forEach(o=>{let l=g("div",{style:"flex: 1 1 calc(50% - 5px); min-width: 300px; height: calc(50% - 5px);"});a.appendChild(l),new w(l,o.width||s/r.columns,o.height||c/r.rows,e).render(o)}),e("\u2705 Multi-view show mode initialized")}else{let r=i[0];r&&new w(t,r.width||800,r.height||600,e).render(r),e("\u2705 Show mode initialized")}}catch(i){e("\u274C Error in show initialization:",i.message)}}function Y(u,t,e){e("\u{1F4CA} Initializing compare mode...");try{new w(t,u.width||800,u.height||600,e).render(u),e("\u2705 Compare mode initialized")}catch(i){e("\u274C Error in compare initialization:",i.message)}}function B(u,t,e){let i=e||function(...r){console.log("[calcplot]",...r)};i("\u{1F680} Starting CalcPlot...");let n=t||window.calcPlotData;if(!n){i("\u274C No calcplot data found");return}if(!u){i("\u274C No container provided - visualization skipped");return}i("\u{1F4E6} Data received:",n.type),i("\u{1F4E6} Using container:",u.id||"unnamed"),n.type==="explore"?G(n,u,i):n.type==="show"?U(n,u,i):n.type==="compare"?Y(n,u,i):i("\u274C Unknown data type:",n.type)}typeof globalThis<"u"&&(globalThis.CalcPlotComponents={initializeClient:B,createSlider:A,createCheckbox:M,view:P});typeof globalThis<"u"&&(globalThis.CalcPlotClient={initializeClient:B,createCheckbox:M,createSlider:A,view:P});})();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/runtime/serialization.ts", "../src/runtime/client/SimulationEngine.ts", "../src/ui/CanvasRenderer.ts", "../src/runtime/client/ViewRenderer.ts", "../src/utils/html-tag.ts", "../src/ui/components/Slider.ts", "../src/ui/components/Checkbox.ts", "../src/ui/ViewBuilder.ts", "../src/runtime/client/init.ts", "../src/runtime/client/index.ts", "../src/runtime/client-bundle.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * CalcPlot API Serialization\n * Handles serialization/deserialization of models, params, functions, and timelines\n */\n\nexport interface SerializedModel {\n state: Record<string, number>;\n params: Record<string, number>;\n derivatives: Record<string, string>;\n events?: Record<string, string>;\n}\n\nexport interface SerializedParams {\n [key: string]: {\n type: string;\n min: number;\n max: number;\n default: number;\n label: string;\n step: number;\n };\n}\n\nexport interface SerializedTimeline {\n times: number[];\n states: Record<string, number[]>;\n}\n\n/**\n * Function serialization utilities\n */\nexport class FunctionSerializer {\n /**\n * Parse function string and extract the body\n * Handles various formats:\n * - \"(p)=>{ return p.x; }\" \u2192 \"return p.x;\"\n * - \"(s)=>s.vx\" \u2192 \"return s.vx\"\n * - \"s=>s.vx\" \u2192 \"return s.vx\"\n * - \"function(p){ return p.x; }\" \u2192 \"return p.x;\"\n */\n static parseFunction(fnStr: string): string {\n const trimmed = fnStr.trim();\n\n // If it's an arrow function wrapped in parentheses with block body\n const arrowMatch = trimmed.match(/^\\(([^)]+)\\)\\s*=>\\s*\\{([\\s\\S]*)\\}$/);\n if (arrowMatch) {\n return arrowMatch[2].trim();\n }\n\n // If it's a simple arrow function without parentheses with block body\n const simpleArrowBlockMatch = trimmed.match(/^(\\w+)\\s*=>\\s*\\{([\\s\\S]*)\\}$/);\n if (simpleArrowBlockMatch) {\n return simpleArrowBlockMatch[2].trim();\n }\n\n // If it's an arrow function wrapped in parentheses with expression body\n const arrowExprMatch = trimmed.match(/^\\(([^)]+)\\)\\s*=>\\s*(.+)$/s);\n if (arrowExprMatch) {\n return `return ${arrowExprMatch[2].trim()}`;\n }\n\n // If it's a simple arrow function without parentheses and without block\n const simpleArrowMatch = trimmed.match(/^(\\w+)\\s*=>\\s*(.+)$/s);\n if (simpleArrowMatch) {\n return `return ${simpleArrowMatch[2].trim()}`;\n }\n\n // If it's a regular function, extract the body\n const functionMatch = trimmed.match(/^function\\s*\\([^)]*\\)\\s*\\{([\\s\\S]*)\\}$/);\n if (functionMatch) {\n return functionMatch[1].trim();\n }\n\n // Otherwise return as is (might be a simple expression)\n return trimmed;\n }\n\n /**\n * Create function from parsed string\n */\n static createFunction(params: string[], body: string): (...args: any[]) => any {\n return new Function(...params, body) as (...args: any[]) => any;\n }\n\n /**\n * Parse and create function in one step\n */\n static parseAndCreateFunction(params: string[], fnStr: string): (...args: any[]) => any {\n const parsedBody = this.parseFunction(fnStr);\n return this.createFunction(params, parsedBody);\n }\n}\n\n/**\n * Serialize model for HTML embedding\n */\nexport function serializeModel(model: any): SerializedModel {\n return {\n state: model.state,\n params: model.params,\n derivatives: serializeFunctions(model.derivatives),\n events: model.events ? serializeFunctions(model.events) : undefined\n };\n}\n\n/**\n * Serialize parameters (sliders) for HTML embedding\n */\nexport function serializeParams(params: Record<string, any>): SerializedParams {\n const serialized: SerializedParams = {};\n for (const [key, control] of Object.entries(params)) {\n serialized[key] = {\n type: control.type || 'slider',\n min: control.min,\n max: control.max,\n default: control.default,\n label: control.label || key,\n step: control.step || 0.01\n };\n }\n return serialized;\n}\n\n/**\n * Serialize timeline for HTML embedding\n */\nexport function serializeTimeline(timeline: any): SerializedTimeline {\n return {\n times: timeline.times,\n states: timeline.states\n };\n}\n\n/**\n * Deserialize parameters from sliders to values\n */\nexport function deserializeParams(serializedParams: SerializedParams): Record<string, number> {\n const params: Record<string, number> = {};\n for (const [key, control] of Object.entries(serializedParams)) {\n params[key] = control.default;\n }\n return params;\n}\n\n/**\n * Deserialize functions from strings\n */\nexport function deserializeFunctions(\n serialized: Record<string, string>\n): Record<string, (...args: any[]) => any> {\n const functions: Record<string, (...args: any[]) => any> = {};\n for (const [key, fnStr] of Object.entries(serialized)) {\n try {\n // Handle different function formats\n if (fnStr.includes('=>')) {\n // Arrow function - use as is\n functions[key] = eval(`(${fnStr})`);\n } else if (fnStr.startsWith('function')) {\n // Regular function declaration - use as is\n functions[key] = eval(`(${fnStr})`);\n } else {\n // Simple expression - wrap in return statement\n functions[key] = eval(`(state, params) => ${fnStr}`);\n }\n } catch (e) {\n console.error('Error deserializing function', key, e);\n // Fallback: simple identity function\n functions[key] = () => 0;\n }\n }\n return functions;\n}\n\n/**\n * Helper: serialize object with functions\n */\nfunction serializeFunctions(obj: any): Record<string, string> {\n const serialized: Record<string, string> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'function') {\n serialized[key] = value.toString();\n } else if (typeof value === 'object' && value !== null) {\n serialized[key] = JSON.stringify(value);\n } else {\n serialized[key] = String(value);\n }\n }\n return serialized;\n}\n", "/**\n * Client-side simulation engine for interactive explore mode\n * Uses core simulation logic but adapted for client-side\n */\n\nimport { FunctionSerializer } from '../serialization';\n\nexport interface SimulationData {\n model: any;\n params: any;\n derivatives: Record<string, string>;\n options: any;\n}\n\nexport class SimulationEngine {\n private log: (...args: any[]) => void;\n\n constructor(log: (...args: any[]) => void) {\n this.log = log;\n }\n\n simulateTrajectory(data: SimulationData, initialState: any, params: any): any {\n // Validate initialState and merge model params with explore params\n if (!initialState || typeof initialState !== 'object') {\n throw new Error(\n `Invalid initialState: expected object, got ${typeof initialState}. Value: ${initialState}`\n );\n }\n\n // Merge model params with explore params for complete parameter set\n const modelParams = data.model?.params || {};\n const exploreParams = params || {};\n const allParams = { ...modelParams, ...exploreParams };\n\n const { dt = 0.01, maxTime = 10 } = data.options || {};\n const times = [];\n const states: Record<string, number[]> = {};\n\n // Initialize states object with all state variables\n Object.keys(initialState).forEach((key) => {\n states[key] = [];\n });\n\n let state = { ...initialState };\n let t = 0;\n\n // Parse derivative functions from model\n const derivatives = data.model?.derivatives || data.derivatives;\n if (!derivatives) {\n throw new Error('No derivatives found in data.model.derivatives or data.derivatives');\n }\n\n const derivativeFns: Record<string, Function> = {};\n Object.entries(derivatives).forEach(([key, fn]) => {\n derivativeFns[key] = FunctionSerializer.parseAndCreateFunction(['s', 'p'], fn as string);\n });\n\n while (t <= maxTime && state.y >= 0) {\n times.push(t);\n\n // Store current state\n Object.keys(state).forEach((key) => {\n states[key].push(state[key]);\n });\n\n // Calculate derivatives\n const derivatives2: Record<string, number> = {};\n Object.entries(derivativeFns).forEach(([key, fn]) => {\n derivatives2[key] = fn(state, allParams);\n });\n\n // Update state\n Object.keys(state).forEach((key) => {\n if (derivatives2[key] !== undefined) {\n state[key] += derivatives2[key] * dt;\n }\n });\n\n t += dt;\n }\n\n return { times, states };\n }\n\n parseInitialFunction(initial: string): Function {\n try {\n const fn = FunctionSerializer.parseAndCreateFunction(['p'], initial);\n return fn;\n } catch (error) {\n console.error('\u274C parseInitialFunction error:', error);\n throw error;\n }\n }\n}\n", "/**\n * Canvas drawing context with coordinate transformation and advanced rendering\n */\n\nimport { DrawContext } from './ViewBuilder';\n\nexport interface Bounds {\n x: [number, number];\n y: [number, number];\n}\n\nexport interface BoundsInput {\n x?: [number, number] | 'auto';\n y?: [number, number] | 'auto';\n}\n\nexport interface GridOptions {\n color?: string;\n alpha?: number;\n major?: boolean;\n minor?: boolean;\n}\n\nexport interface AxisOptions {\n x?: string;\n y?: string;\n color?: string;\n showTicks?: boolean;\n showLabels?: boolean;\n}\n\nexport interface Transform {\n scale: number;\n offsetX: number;\n offsetY: number;\n}\n\nexport class CanvasRenderer {\n private ctx: CanvasRenderingContext2D;\n private bounds: Bounds;\n private width: number;\n private height: number;\n private margin = 50; // Space for axes and labels\n\n constructor(ctx: CanvasRenderingContext2D, width: number, height: number) {\n this.ctx = ctx;\n this.width = width;\n this.height = height;\n\n // Default bounds\n this.bounds = {\n x: [-10, 10],\n y: [-10, 10]\n };\n }\n\n /**\n * Set bounds for coordinate system\n */\n setBounds(bounds: Bounds): void {\n this.bounds = bounds;\n }\n\n /**\n * Set bounds with auto support (for mixed bounds)\n */\n setBoundsWithAuto(bounds: BoundsInput, dataBounds?: Bounds): void {\n const finalBounds: Bounds = {\n x: bounds.x === 'auto' && dataBounds ? dataBounds.x : (bounds.x as [number, number]),\n y: bounds.y === 'auto' && dataBounds ? dataBounds.y : (bounds.y as [number, number])\n };\n this.bounds = finalBounds;\n }\n\n /**\n * Convert mathematical coordinates to canvas coordinates\n */\n private toCanvas(x: number, y: number): [number, number] {\n const [xMin, xMax] = this.bounds.x;\n const [yMin, yMax] = this.bounds.y;\n\n // X: from margin to width-margin\n const sx = this.margin + ((x - xMin) / (xMax - xMin)) * (this.width - 2 * this.margin);\n\n // Y: from height-margin to margin (inverted)\n const sy =\n this.height - this.margin - ((y - yMin) / (yMax - yMin)) * (this.height - 2 * this.margin);\n\n return [sx, sy];\n }\n\n /**\n * Convert screen coordinates back to mathematical coordinates\n */\n toScreen(x: number, y: number): [number, number] {\n const [xMin, xMax] = this.bounds.x;\n const [yMin, yMax] = this.bounds.y;\n\n const mx = xMin + ((x - this.margin) / (this.width - 2 * this.margin)) * (xMax - xMin);\n const my =\n yMin + ((this.height - this.margin - y) / (this.height - 2 * this.margin)) * (yMax - yMin);\n\n return [mx, my];\n }\n\n /**\n * Calculate \"nice\" step for axis divisions\n */\n private calculateNiceStep(range: number, targetSteps: number): number {\n const rawStep = range / targetSteps;\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n\n // Round to 1, 2, 5 or 10\n let niceNormalized;\n if (normalized < 1.5) niceNormalized = 1;\n else if (normalized < 3) niceNormalized = 2;\n else if (normalized < 7) niceNormalized = 5;\n else niceNormalized = 10;\n\n return niceNormalized * magnitude;\n }\n\n /**\n * Format numbers for axis labels\n */\n private formatNumber(n: number): string {\n // Remove insignificant zeros\n if (Math.abs(n) < 0.01 || Math.abs(n) > 1000) {\n return n.toExponential(1);\n }\n return n.toFixed(2).replace(/\\.?0+$/, '');\n }\n\n /**\n * Draw grid with nice divisions\n */\n grid(options: GridOptions = {}): void {\n const { color = '#333', alpha = 0.2, major = true, minor = false } = options;\n\n this.ctx.save();\n this.ctx.strokeStyle = color;\n this.ctx.lineWidth = 1;\n this.ctx.globalAlpha = alpha;\n\n const [xMin, xMax] = this.bounds.x;\n const [yMin, yMax] = this.bounds.y;\n\n // Calculate nice intervals\n const xStep = this.calculateNiceStep(xMax - xMin, 5);\n const yStep = this.calculateNiceStep(yMax - yMin, 5);\n\n // Vertical lines\n const xStart = Math.ceil(xMin / xStep) * xStep;\n for (let x = xStart; x <= xMax; x += xStep) {\n const [sx, sy0] = this.toCanvas(x, yMin);\n const [, sy1] = this.toCanvas(x, yMax);\n\n this.ctx.beginPath();\n this.ctx.moveTo(sx, sy0);\n this.ctx.lineTo(sx, sy1);\n this.ctx.stroke();\n }\n\n // Horizontal lines\n const yStart = Math.ceil(yMin / yStep) * yStep;\n for (let y = yStart; y <= yMax; y += yStep) {\n const [sx0, sy] = this.toCanvas(xMin, y);\n const [sx1] = this.toCanvas(xMax, y);\n\n this.ctx.beginPath();\n this.ctx.moveTo(sx0, sy);\n this.ctx.lineTo(sx1, sy);\n this.ctx.stroke();\n }\n\n this.ctx.restore();\n }\n\n /**\n * Draw axes with ticks and labels\n */\n axis(options: AxisOptions = {}): void {\n const { x: xLabel, y: yLabel, color = '#666', showTicks = true, showLabels = true } = options;\n\n this.ctx.save();\n this.ctx.strokeStyle = color;\n this.ctx.fillStyle = color;\n this.ctx.lineWidth = 2;\n this.ctx.font = '12px sans-serif';\n\n const [xMin, xMax] = this.bounds.x;\n const [yMin, yMax] = this.bounds.y;\n\n // X axis\n const [x0, yAxis] = this.toCanvas(xMin, 0);\n const [x1] = this.toCanvas(xMax, 0);\n\n this.ctx.beginPath();\n this.ctx.moveTo(x0, yAxis);\n this.ctx.lineTo(x1, yAxis);\n this.ctx.stroke();\n\n // Y axis\n const [xAxis, y0] = this.toCanvas(0, yMin);\n const [, y1] = this.toCanvas(0, yMax);\n\n this.ctx.beginPath();\n this.ctx.moveTo(xAxis, y0);\n this.ctx.lineTo(xAxis, y1);\n this.ctx.stroke();\n\n if (showTicks || showLabels) {\n const xStep = this.calculateNiceStep(xMax - xMin, 5);\n const yStep = this.calculateNiceStep(yMax - yMin, 5);\n\n // X ticks and labels\n const xStart = Math.ceil(xMin / xStep) * xStep;\n for (let x = xStart; x <= xMax; x += xStep) {\n const [sx, sy] = this.toCanvas(x, 0);\n\n if (showTicks) {\n this.ctx.beginPath();\n this.ctx.moveTo(sx, sy - 5);\n this.ctx.lineTo(sx, sy + 5);\n this.ctx.stroke();\n }\n\n if (showLabels && x !== 0) {\n this.ctx.fillText(this.formatNumber(x), sx - 10, sy + 20);\n }\n }\n\n // Y ticks and labels\n const yStart = Math.ceil(yMin / yStep) * yStep;\n for (let y = yStart; y <= yMax; y += yStep) {\n const [sx, sy] = this.toCanvas(0, y);\n\n if (showTicks) {\n this.ctx.beginPath();\n this.ctx.moveTo(sx - 5, sy);\n this.ctx.lineTo(sx + 5, sy);\n this.ctx.stroke();\n }\n\n if (showLabels && y !== 0) {\n this.ctx.fillText(this.formatNumber(y), sx - 35, sy + 4);\n }\n }\n }\n\n // Axis labels\n if (xLabel) {\n this.ctx.fillText(xLabel, this.width - this.margin + 10, yAxis + 4);\n }\n if (yLabel) {\n this.ctx.save();\n this.ctx.translate(xAxis - 4, this.margin - 10);\n this.ctx.rotate(-Math.PI / 2);\n this.ctx.fillText(yLabel, 0, 0);\n this.ctx.restore();\n }\n\n this.ctx.restore();\n }\n\n /**\n * Clear canvas\n */\n clear(): void {\n this.ctx.clearRect(0, 0, this.width, this.height);\n this.ctx.fillStyle = '#f8f9fa';\n this.ctx.fillRect(0, 0, this.width, this.height);\n }\n\n /**\n * Create draw context with coordinate transformation\n */\n createDrawContext(): DrawContext {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n return {\n line: (from: [number, number], to: [number, number], options = {}) => {\n const [x1, y1] = self.toCanvas(from[0], from[1]);\n const [x2, y2] = self.toCanvas(to[0], to[1]);\n\n self.ctx.beginPath();\n self.ctx.moveTo(x1, y1);\n self.ctx.lineTo(x2, y2);\n self.ctx.strokeStyle = options.color || '#2563eb';\n self.ctx.lineWidth = options.width || 1;\n\n if (options.dash) {\n self.ctx.setLineDash(options.dash);\n } else {\n self.ctx.setLineDash([]);\n }\n\n self.ctx.stroke();\n },\n\n circle: (center: [number, number], radius: number, options = {}) => {\n const [cx, cy] = self.toCanvas(center[0], center[1]);\n const r = radius * self.calculateScale();\n\n self.ctx.beginPath();\n self.ctx.arc(cx, cy, r, 0, 2 * Math.PI);\n\n if (options.fill) {\n self.ctx.fillStyle = options.fill;\n self.ctx.fill();\n }\n\n if (options.stroke) {\n self.ctx.strokeStyle = options.stroke;\n self.ctx.lineWidth = options.width || 1;\n self.ctx.stroke();\n }\n },\n\n arrow: (from: [number, number], to: [number, number], options = {}) => {\n const [x1, y1] = self.toCanvas(from[0], from[1]);\n const [x2, y2] = self.toCanvas(to[0], to[1]);\n const headSize = options.headSize || 10;\n\n // Draw line\n self.ctx.beginPath();\n self.ctx.moveTo(x1, y1);\n self.ctx.lineTo(x2, y2);\n self.ctx.strokeStyle = options.color || '#2563eb';\n self.ctx.lineWidth = options.width || 2;\n self.ctx.stroke();\n\n // Draw arrowhead\n const angle = Math.atan2(y2 - y1, x2 - x1);\n self.ctx.beginPath();\n self.ctx.moveTo(x2, y2);\n self.ctx.lineTo(\n x2 - headSize * Math.cos(angle - Math.PI / 6),\n y2 - headSize * Math.sin(angle - Math.PI / 6)\n );\n self.ctx.moveTo(x2, y2);\n self.ctx.lineTo(\n x2 - headSize * Math.cos(angle + Math.PI / 6),\n y2 - headSize * Math.sin(angle + Math.PI / 6)\n );\n self.ctx.stroke();\n },\n\n text: (pos: [number, number], text: string, options = {}) => {\n const [x, y] = self.toCanvas(pos[0], pos[1]);\n self.ctx.font = `${options.size || 14}px ${options.font || 'system-ui'}`;\n self.ctx.fillStyle = options.color || '#1f2937';\n self.ctx.fillText(text, x, y);\n },\n\n plot: (xValues: number[], yValues: number[], options = {}) => {\n if (xValues.length !== yValues.length || xValues.length === 0) {\n return;\n }\n\n // Filter out invalid values\n const validYValues = yValues.filter((v) => typeof v === 'number' && !isNaN(v));\n if (validYValues.length === 0) {\n return;\n }\n\n self.ctx.beginPath();\n self.ctx.strokeStyle = options.color || '#000';\n self.ctx.lineWidth = options.lineWidth || 2;\n\n // Draw lines using bounds-based coordinates\n for (let i = 0; i < xValues.length; i++) {\n const yVal = yValues[i];\n if (typeof yVal !== 'number' || isNaN(yVal)) {\n continue; // Skip invalid points\n }\n\n const [x, y] = self.toCanvas(xValues[i], yVal);\n\n if (i === 0) {\n self.ctx.moveTo(x, y);\n } else {\n self.ctx.lineTo(x, y);\n }\n }\n\n self.ctx.stroke();\n }\n };\n }\n\n /**\n * Calculate current scale for transformations\n */\n private calculateScale(): number {\n const [xMin, xMax] = this.bounds.x;\n return (this.width - 2 * this.margin) / (xMax - xMin);\n }\n\n /**\n * Get current bounds\n */\n getBounds(): Bounds {\n return { ...this.bounds };\n }\n\n /**\n * Fluent API method for chaining\n */\n setBoundsFluent(bounds: BoundsInput): CanvasRenderer {\n this.setBoundsWithAuto(bounds);\n return this;\n }\n\n /**\n * Fluent API method for grid\n */\n gridFluent(options: GridOptions = {}): CanvasRenderer {\n this.grid(options);\n return this;\n }\n\n /**\n * Fluent API method for axis\n */\n axisFluent(options: AxisOptions = {}): CanvasRenderer {\n this.axis(options);\n return this;\n }\n}\n", "/**\n * View Renderer - handles canvas creation and rendering\n */\n\nimport { Bounds, CanvasRenderer } from '../../ui/CanvasRenderer';\nimport { FunctionSerializer } from '../serialization';\n\nexport interface VisualizationData {\n type: 'view' | 'explore';\n timeline?: any;\n layers?: any;\n params?: any;\n viewDescriptor?: any; // Add viewDescriptor with layers\n options?: any;\n width?: number;\n height?: number;\n}\n\nexport class ViewRenderer {\n private container: HTMLElement;\n private canvas: HTMLCanvasElement;\n private renderer: CanvasRenderer;\n private log: (...args: any[]) => void;\n private resizeObserver?: ResizeObserver;\n private targetWidth: number;\n private targetHeight: number;\n private currentData?: VisualizationData;\n private currentTimeline?: any;\n\n constructor(\n container: HTMLElement,\n width: number = 800,\n height: number = 600,\n log: (...args: any[]) => void\n ) {\n this.container = container;\n this.log = log;\n this.targetWidth = width;\n this.targetHeight = height;\n this.canvas = this.createCanvas(width, height);\n this.renderer = new CanvasRenderer(\n this.canvas.getContext('2d')!,\n this.canvas.width,\n this.canvas.height\n );\n this.setupResizeObserver();\n }\n\n /**\n * Create and append canvas to container\n */\n private createCanvas(width: number, height: number): HTMLCanvasElement {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = `<canvas width=\"${width}\" height=\"${height}\"></canvas>`;\n const canvas = tempDiv.firstChild as HTMLCanvasElement;\n\n // Make canvas responsive - check if style exists (for test environments)\n if (canvas.style) {\n canvas.style.width = '100%';\n canvas.style.height = '100%';\n canvas.style.display = 'block';\n }\n\n this.container.appendChild(canvas);\n\n return canvas;\n }\n\n /**\n * Setup ResizeObserver to handle container size changes\n */\n private setupResizeObserver(): void {\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n\n // Only update if size actually changed and not already updating\n if (width !== this.targetWidth || height !== this.targetHeight) {\n this.updateCanvasSize(width, height);\n }\n }\n });\n this.resizeObserver.observe(this.container);\n }\n }\n\n /**\n * Update canvas size based on container dimensions\n */\n private updateCanvasSize(containerWidth: number, containerHeight: number): void {\n // Use actual container dimensions instead of target dimensions\n this.canvas.width = Math.floor(containerWidth);\n this.canvas.height = Math.floor(containerHeight);\n this.targetWidth = Math.floor(containerWidth);\n this.targetHeight = Math.floor(containerHeight);\n this.renderer = new CanvasRenderer(\n this.canvas.getContext(\"2d\")!,\n this.canvas.width,\n this.canvas.height\n );\n if (this.currentData) {\n this.renderInternal(this.currentData);\n }\n }\n\n /**\n * Internal render method without saving data\n */\n private renderInternal(data: VisualizationData): void {\n let layers = data.layers || [];\n if (data.viewDescriptor && data.viewDescriptor.layers) {\n layers = data.viewDescriptor.layers;\n }\n\n this.renderer.clear();\n const bounds = this.calculateBoundsFromTimeline(data.timeline, layers);\n this.renderer.setBounds(bounds);\n const drawCtx = this.renderer.createDrawContext();\n\n // Sort layers by priority: bounds > grid > axis > plot\n const layerPriority: Record<string, number> = {\n bounds: 1,\n grid: 2,\n axis: 3,\n plot: 4\n };\n\n const sortedLayers = [...layers].sort(\n (a, b) => (layerPriority[a.type] || 999) - (layerPriority[b.type] || 999)\n );\n\n sortedLayers.forEach((layer, index) => {\n switch (layer.type) {\n case 'bounds':\n if (layer.bounds) {\n const timelineBounds = this.calculateBoundsFromTimeline(data.timeline);\n this.renderer.setBoundsWithAuto(layer.bounds, timelineBounds);\n }\n break;\n case 'grid':\n this.renderer.grid(layer.options || {});\n break;\n case 'axis':\n this.renderer.axis(layer.options || {});\n break;\n case 'plot':\n if (layer.selector) {\n this.renderPlot(drawCtx, data.timeline, layer);\n }\n break;\n case 'scene':\n if (layer.draw) {\n this.renderScene(drawCtx, data.timeline, layer);\n }\n break;\n default:\n break;\n }\n });\n }\n\n /**\n * Main rendering method\n */\n render(data: VisualizationData): void {\n if (!data.timeline) {\n return;\n }\n\n // Save current data for resize handling\n this.currentData = data;\n\n // Use internal render method\n this.renderInternal(data);\n }\n\n private renderPlot(drawCtx: any, timeline: any, layer: any): void {\n const { selector, options = {} } = layer;\n\n // Determine if this is a parametric plot by checking the selector\n let isParametric = false;\n try {\n const testState = { x: 0, y: 0 };\n const result = FunctionSerializer.parseAndCreateFunction(['s'], selector)(testState);\n isParametric = Array.isArray(result) && result.length === 2;\n } catch (e) {\n isParametric = false;\n }\n\n // Create function from selector string\n let selectFn: (s: any) => any;\n try {\n selectFn = FunctionSerializer.parseAndCreateFunction(['s'], selector) as (s: any) => any;\n this.log('\u2705 selector created successfully');\n } catch (e) {\n this.log('\u26A0\uFE0F Failed to compile selector:', e);\n selectFn = (s: any) => 0;\n }\n\n if (isParametric) {\n // Extract x,y pairs for parametric plot\n const points = timeline.times.map((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n return selectFn(state);\n });\n\n const validPoints = points.filter(\n (p) =>\n Array.isArray(p) && p.length === 2 && typeof p[0] === 'number' && typeof p[1] === 'number'\n );\n\n const xValues = validPoints.map((p) => p[0]);\n const yValues = validPoints.map((p) => p[1]);\n\n drawCtx.plot(xValues, yValues, options);\n } else {\n // Extract y values for regular plot\n const yValues = timeline.times.map((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n return selectFn(state);\n });\n\n drawCtx.plot(timeline.times, yValues, options);\n }\n }\n\n private renderScene(drawCtx: any, timeline: any, layer: any): void {\n const { draw } = layer;\n\n if (!draw) {\n return;\n }\n\n let drawFn: (ctx: any, state: any) => void;\n try {\n drawFn = FunctionSerializer.parseAndCreateFunction(['ctx', 'state'], draw) as (\n ctx: any,\n state: any\n ) => void;\n } catch (e) {\n this.log('\u26A0\uFE0F Failed to compile scene function:', e);\n return;\n }\n\n timeline.times.forEach((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n\n try {\n drawFn(drawCtx, state);\n } catch (e) {\n this.log('\u26A0\uFE0F Error in scene function:', e);\n }\n });\n }\n\n renderExplore(data: VisualizationData, timeline: any): void {\n // Save timeline for resize handling\n this.currentTimeline = timeline;\n\n this.render({\n type: 'view',\n timeline: timeline,\n layers: data.layers,\n options: data.options,\n viewDescriptor: data.viewDescriptor\n });\n }\n\n /**\n * Calculate bounds from timeline data\n */\n private calculateBoundsFromTimeline(timeline: any, layers?: any[]): Bounds {\n let xMin = Infinity,\n xMax = -Infinity;\n let yMin = Infinity,\n yMax = -Infinity;\n\n // First try to find bounds from selectors in plot layers\n if (layers) {\n const plotLayers = layers.filter(layer => layer.type === 'plot' && layer.selector);\n \n for (const layer of plotLayers) {\n try {\n const selectFn = FunctionSerializer.parseAndCreateFunction(['s'], layer.selector);\n \n // Test if selector is parametric\n const testState = { x: 0, y: 0 };\n const result = selectFn(testState);\n const isParametric = Array.isArray(result) && result.length === 2;\n \n if (isParametric) {\n // Extract all points from timeline\n const points = timeline.times.map((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n return selectFn(state);\n }).filter(p => Array.isArray(p) && p.length === 2 && typeof p[0] === 'number' && typeof p[1] === 'number');\n \n // Update bounds from points\n for (const point of points) {\n xMin = Math.min(xMin, point[0]);\n xMax = Math.max(xMax, point[0]);\n yMin = Math.min(yMin, point[1]);\n yMax = Math.max(yMax, point[1]);\n }\n } else {\n // For non-parametric plots, use time as x and selector result as y\n const yValues = timeline.times.map((_: any, i: number) => {\n const state = Object.keys(timeline.states).reduce((acc: any, key: string) => {\n acc[key] = timeline.states[key][i];\n return acc;\n }, {});\n return selectFn(state);\n }).filter(v => typeof v === 'number');\n \n xMin = Math.min(xMin, ...timeline.times);\n xMax = Math.max(xMax, ...timeline.times);\n yMin = Math.min(yMin, ...yValues);\n yMax = Math.max(yMax, ...yValues);\n }\n } catch (e) {\n // If selector analysis fails, fall back to key-based analysis\n this.log('\u26A0\uFE0F Failed to analyze selector for bounds:', e);\n }\n }\n }\n \n // Fallback: use time for x-axis if bounds not found from selectors\n if (xMin === Infinity && timeline.times) {\n xMin = Math.min(...timeline.times);\n xMax = Math.max(...timeline.times);\n }\n\n // Default values if still not found\n if (xMin === Infinity) xMin = 0;\n if (xMax === -Infinity) xMax = 10;\n if (yMin === Infinity) yMin = -10;\n if (yMax === -Infinity) yMax = 10;\n\n const xPadding = (xMax - xMin) * 0.1 || 1;\n const yPadding = (yMax - yMin) * 0.1 || 1;\n\n return {\n x: [xMin - xPadding, xMax + xPadding],\n y: [yMin - yPadding, yMax + yPadding]\n };\n }\n}\n", "/**\n * HTML tag builder for component-based architecture\n */\n\nexport interface HtmlAttrs {\n [key: string]: any;\n}\n\n// DOM element creation functions\nexport function createElement(\n tag: string,\n attrs: HtmlAttrs = {},\n ...children: (HTMLElement | string)[]\n): HTMLElement {\n const element = document.createElement(tag);\n\n // Set attributes\n Object.entries(attrs).forEach(([key, val]) => {\n if (key === 'className') {\n element.className = val;\n } else if (key.startsWith('data-')) {\n element.setAttribute(key, String(val));\n } else if (key in element) {\n (element as any)[key] = val;\n } else {\n element.setAttribute(key, String(val));\n }\n });\n\n // Append children\n children.flat().forEach((child) => {\n if (typeof child === 'string') {\n element.appendChild(document.createTextNode(child));\n } else if (child instanceof HTMLElement) {\n element.appendChild(child);\n }\n });\n\n return element;\n}\n\n// Common shortcuts for DOM elements\nexport const div = (attrs: HtmlAttrs = {}, ...children: (HTMLElement | string)[]) =>\n createElement('div', attrs, ...children);\nexport const span = (attrs: HtmlAttrs = {}, ...children: (HTMLElement | string)[]) =>\n createElement('span', attrs, ...children);\nexport const input = (attrs: HtmlAttrs = {}) => createElement('input', attrs);\nexport const label = (attrs: HtmlAttrs = {}, ...children: (HTMLElement | string)[]) =>\n createElement('label', attrs, ...children);\nexport const button = (attrs: HtmlAttrs = {}, ...children: (HTMLElement | string)[]) =>\n createElement('button', attrs, ...children);\nexport const canvas = (attrs: HtmlAttrs = {}) => createElement('canvas', attrs);\n\n// HTML string generation function (for compatibility)\nexport function h(tag: string, attrs: HtmlAttrs = {}, ...children: any[]): string {\n const attrStr = Object.entries(attrs)\n .filter(([_, val]) => val !== undefined && val !== null && val !== false)\n .map(([key, val]) => {\n const attrName = key === 'className' ? 'class' : key;\n const attrValue = typeof val === 'boolean' ? '' : `=\"${val}\"`;\n return `${attrName}${attrValue}`;\n })\n .join(' ');\n\n const childrenStr = children\n .flat()\n .filter((child) => child !== null && child !== undefined && child !== false)\n .map((child) => (typeof child === 'string' ? child : String(child)))\n .join('');\n\n return `<${tag}${attrStr ? ' ' + attrStr : ''}>${childrenStr}</${tag}>`;\n}\n\n// Common shortcuts for HTML strings\nexport const divStr = (attrs: HtmlAttrs = {}, ...children: any[]) => h('div', attrs, ...children);\nexport const spanStr = (attrs: HtmlAttrs = {}, ...children: any[]) => h('span', attrs, ...children);\nexport const inputStr = (attrs: HtmlAttrs = {}) => h('input', attrs);\nexport const labelStr = (attrs: HtmlAttrs = {}, ...children: any[]) =>\n h('label', attrs, ...children);\nexport const buttonStr = (attrs: HtmlAttrs = {}, ...children: any[]) =>\n h('button', attrs, ...children);\nexport const canvasStr = (attrs: HtmlAttrs = {}) => h('canvas', attrs);\nexport const style = (content: string) => h('style', {}, content);\nexport const script = (content: string, attrs: HtmlAttrs = {}) => h('script', attrs, content);\n", "/**\n * Slider component for parameter controls\n */\n\nimport { div, input, label, span } from '../../utils/html-tag';\nimport { Control } from '../controls';\n\nexport interface SliderProps {\n id: string;\n control: Control;\n value?: number | boolean;\n onChange?: (id: string, value: number | boolean) => void;\n}\n\n/**\n * Create slider element with event listener\n */\nexport function createSlider(container: HTMLElement, props: SliderProps): HTMLInputElement {\n const inputId = `input-${props.id}`;\n const valueId = `val-${props.id}`;\n\n // Create value display\n const valueDisplay = span(\n {\n className: 'value-display',\n id: valueId\n },\n typeof props.value === 'number' ? props.value.toFixed(2) : String(props.value)\n );\n\n // Create input\n const inputElement = input({\n type: 'range',\n id: inputId,\n min: String(props.control.min),\n max: String(props.control.max),\n step: String(props.control.step || 0.01),\n value: String(props.value),\n 'data-slider-id': props.id\n }) as HTMLInputElement;\n\n // Add event listener\n inputElement.addEventListener('input', (e) => {\n const value = parseFloat((e.target as HTMLInputElement).value);\n\n // Update value display\n valueDisplay.textContent = value.toFixed(2);\n\n // Call onChange callback\n if (props.onChange) {\n props.onChange(props.id, value);\n }\n });\n\n // Create label\n const labelElement = label({ htmlFor: inputId }, props.control.label);\n\n // Create control group\n const controlGroup = div(\n { className: 'control-group' },\n labelElement,\n inputElement,\n valueDisplay\n );\n container.appendChild(controlGroup);\n\n return inputElement;\n}\n", "/**\n * Checkbox component for boolean parameters\n */\n\nimport { div, input, label } from '../../utils/html-tag';\nimport { Control } from '../controls';\n\nexport interface CheckboxProps {\n id: string;\n control: Control;\n value?: boolean;\n onChange?: (id: string, value: boolean) => void;\n}\n\n/**\n * Create checkbox element with event listener\n */\nexport function createCheckbox(container: HTMLElement, props: CheckboxProps): HTMLInputElement {\n const inputId = `input-${props.id}`;\n\n // Create input\n const inputElement = input({\n type: 'checkbox',\n id: inputId,\n checked: props.value || false,\n 'data-checkbox-id': props.id\n }) as HTMLInputElement;\n\n // Add event listener\n inputElement.addEventListener('change', (e) => {\n const checked = (e.target as HTMLInputElement).checked;\n\n // Call onChange callback\n if (props.onChange) {\n props.onChange(props.id, checked);\n }\n });\n\n // Create label\n const labelElement = label({ htmlFor: inputId }, props.control.label);\n\n // Create control group\n const controlGroup = div({ className: 'control-group' }, labelElement, inputElement);\n container.appendChild(controlGroup);\n\n return inputElement;\n}\n", "/**\n * Chainable API for building visualizations\n */\n\nimport { State, Timeline } from '../core/ivp';\n\nexport interface GridOptions {\n color?: string;\n alpha?: number;\n spacing?: number;\n}\n\nexport interface PlotOptions {\n color?: string;\n lineWidth?: number;\n dash?: number[];\n label?: string;\n}\n\nexport interface VectorOptions {\n color?: string;\n label?: string;\n scale?: number;\n width?: number;\n}\n\nexport interface SceneFunction {\n (ctx: DrawContext, state: State): void;\n}\n\nexport interface SelectorFunction {\n (state: State): number | [number, number];\n}\n\nexport interface VectorFunction {\n (state: State): [number, number];\n}\n\nexport interface DrawContext {\n line: (\n from: [number, number],\n to: [number, number],\n options?: { width?: number; color?: string; dash?: number[] }\n ) => void;\n circle: (\n center: [number, number],\n radius: number,\n options?: { fill?: string; stroke?: string; width?: number }\n ) => void;\n arrow: (\n from: [number, number],\n to: [number, number],\n options?: { width?: number; color?: string; headSize?: number }\n ) => void;\n text: (\n pos: [number, number],\n text: string,\n options?: { color?: string; size?: number; font?: string }\n ) => void;\n plot: (xValues: number[], yValues: number[], options?: PlotOptions) => void;\n}\n\nexport interface Layer {\n type: 'grid' | 'scene' | 'plot' | 'vector' | 'bounds' | 'axis';\n options?: any;\n draw?: string; // serialized function\n selector?: string; // serialized function\n at?: string; // serialized function\n dir?: string; // serialized function\n bounds?: { x?: [number, number] | 'auto'; y?: [number, number] | 'auto' };\n parametric?: boolean; // true for [x, y] plots\n}\n\nexport class ViewBuilder {\n private layers: Layer[] = [];\n private timeline?: Timeline;\n\n constructor(timeline?: Timeline) {\n this.timeline = timeline;\n }\n\n /**\n * Add custom scene drawing layer\n */\n scene(drawFn: SceneFunction): ViewBuilder {\n this.layers.push({\n type: 'scene',\n draw: this.serializeFunction(drawFn)\n });\n return this;\n }\n\n /**\n * Add plot layer\n */\n plot(selector: SelectorFunction, options: PlotOptions = {}): ViewBuilder {\n // Detect if selector is parametric (returns [x, y]) by testing it\n const isParametric = this.detectParametricSelector(selector);\n\n this.layers.push({\n type: 'plot',\n selector: this.serializeFunction(selector),\n parametric: isParametric,\n options: {\n color: '#2563eb',\n lineWidth: 2,\n fill: false,\n dash: [],\n label: '',\n alpha: 1,\n ...options\n }\n });\n return this;\n }\n\n /**\n * Add vector layer\n */\n vector(at: VectorFunction, dir: VectorFunction, options: VectorOptions = {}): ViewBuilder {\n this.layers.push({\n type: 'vector',\n at: this.serializeFunction(at),\n dir: this.serializeFunction(dir),\n options: {\n color: '#0ff',\n scale: 1,\n width: 2,\n ...options\n }\n });\n return this;\n }\n\n /**\n * Set bounds for coordinate system\n */\n bounds(bounds: { x?: [number, number] | 'auto'; y?: [number, number] | 'auto' }): ViewBuilder {\n this.layers.push({\n type: 'bounds',\n bounds: bounds\n });\n return this;\n }\n\n /**\n * Add grid layer\n */\n grid(options: any = {}): ViewBuilder {\n this.layers.push({\n type: 'grid',\n options: options\n });\n return this;\n }\n\n /**\n * Add axis layer\n */\n axis(options: any = {}): ViewBuilder {\n this.layers.push({\n type: 'axis',\n options: options\n });\n return this;\n }\n\n /**\n * Get all layers\n */\n getLayers(): Layer[] {\n return [...this.layers];\n }\n\n /**\n * Get timeline\n */\n getTimeline(): Timeline | undefined {\n return this.timeline;\n }\n\n /**\n * Set timeline (for when timeline is provided later)\n */\n setTimeline(timeline: Timeline): void {\n this.timeline = timeline;\n }\n\n /**\n * Serialize function or selector for HTML embedding\n */\n private serializeFunction(fn: (...args: any[]) => any): string {\n return fn.toString();\n }\n\n /**\n * Detect if selector function is parametric (returns [x, y])\n */\n private detectParametricSelector(selector: SelectorFunction): boolean {\n try {\n // Test with sample state to see if function returns array (parametric) or number (scalar)\n const testState = { x: 1, y: 2, z: 3 };\n const result = selector(testState);\n return Array.isArray(result) && result.length === 2;\n } catch {\n // If we can't determine, assume non-parametric\n return false;\n }\n }\n\n /**\n * Convert to ViewDescriptor for HTML rendering\n */\n toDescriptor(): {\n timeline: { times: number[]; states: Record<string, number[]> };\n layers: Layer[];\n } {\n return {\n timeline: {\n times: this.timeline?.times || [],\n states: this.timeline?.states || {}\n },\n layers: this.layers\n };\n }\n\n /**\n * Execute with timeline and return descriptor\n */\n executeWithTimeline(timeline: Timeline): {\n timeline: { times: number[]; states: Record<string, number[]> };\n layers: Layer[];\n } {\n const tempTimeline = this.timeline;\n this.timeline = timeline;\n const descriptor = this.toDescriptor();\n this.timeline = tempTimeline;\n return descriptor;\n }\n}\n\n/**\n * Main view function - now timeline-agnostic\n */\nexport function view(timeline?: Timeline): ViewBuilder {\n return new ViewBuilder(timeline);\n}\n", "/**\n * CalcPlot Client Initialization\n * Handles setup and initialization of visualizations\n */\n\nimport { SimulationEngine } from './SimulationEngine';\nimport { ViewRenderer } from './ViewRenderer';\nimport { createSlider } from '../../ui/components/Slider';\nimport { createCheckbox } from '../../ui/components/Checkbox';\nimport { createElement } from '../../utils/html-tag';\nimport { view } from '../../ui/ViewBuilder';\n\n// Make components available globally for client\nif (typeof globalThis !== 'undefined') {\n (globalThis as any).CalcPlotComponents = {\n createSlider: createSlider,\n createCheckbox: createCheckbox,\n view: view\n };\n}\n\n// Create controls for explore mode\nfunction createControls(\n data: any,\n container: HTMLElement,\n updateSimulation: () => void,\n log: (...args: any[]) => void\n): void {\n log(' Creating controls for:', Object.keys(data.params));\n const controlsDiv = createElement('div', {\n style: 'padding: 10px; border-bottom: 1px solid #ccc;'\n });\n container.appendChild(controlsDiv);\n\n Object.entries(data.params).forEach(([key, param]: [string, any]) => {\n if (param.type === 'slider') {\n const createSlider = (window as any).CalcPlotComponents.createSlider;\n if (createSlider) {\n createSlider(controlsDiv, {\n id: key,\n control: param,\n value: param.default, // Add initial value\n onChange: (id: string, value: number) => {\n updateSimulation();\n }\n });\n } else {\n log('\u274C createSlider not available');\n }\n } else if (param.type === 'checkbox') {\n const createCheckbox = (window as any).CalcPlotComponents.createCheckbox;\n if (createCheckbox) {\n createCheckbox(controlsDiv, {\n id: key,\n control: param,\n value: param.default,\n onChange: (id: string, value: boolean) => {\n log(`\u2611\uFE0F Checkbox ${id} changed to ${value}`);\n updateSimulation();\n }\n });\n } else {\n log('\u274C createCheckbox not available');\n }\n }\n });\n}\n\n// Create container wrapper for multiple views\nfunction createWrapper(container: HTMLElement, width: number, height: number, gaps: number): HTMLElement {\n const wrapper = createElement('div', {\n style: `display: flex; width: 100%; height: 100%;`\n });\n container.appendChild(wrapper);\n return wrapper;\n}\n\n// Initialize multiple views in container\nfunction initializeViews(views: any[], container: HTMLElement, width: number, height: number, log: (...args: any[]) => void): ViewRenderer[] {\n const layout = { columns: views.length, rows: 1, gaps: 10 };\n\n return views.map((viewData: any) => {\n const viewContainer = createElement('div', {\n style: `flex: 1; width: 0; height: 100%;`\n });\n container.appendChild(viewContainer);\n\n return new ViewRenderer(\n viewContainer,\n width / layout.columns,\n height / layout.rows,\n log\n );\n });\n}\n\n// Update all views with new data\nfunction updateViews(renderers: ViewRenderer[], views: any[], timeline: any, params: any, width: number, height: number): void {\n const layout = { columns: views.length, rows: 1, gaps: 10 };\n\n views.forEach((viewData: any, index: number) => {\n let descriptor;\n \n // Handle ViewBuilder layers\n if (viewData.layers && Array.isArray(viewData.layers)) {\n descriptor = {\n timeline: {\n times: timeline.times,\n states: timeline.states\n },\n layers: viewData.layers\n };\n } else {\n throw new Error('Invalid view configuration: expected layers array');\n }\n\n renderers[index].render({\n type: 'view',\n timeline,\n layers: descriptor.layers,\n width: width / layout.columns,\n height: height / layout.rows\n });\n });\n}\n\n// Initialize explore mode with controls and simulation\nfunction initializeExplore(data: any, container: HTMLElement, log: (...args: any[]) => void): void {\n log(' Initializing explore mode...');\n\n try {\n const views = data.views || [];\n const isMultiView = views.length > 1;\n const containerWidth = data.width || 800;\n const containerHeight = data.height || 600;\n\n // Create controls\n if (data.params) {\n createControls(data, container, updateSimulation, log);\n }\n\n const canvasContainer = isMultiView ? createWrapper(container, containerWidth, containerHeight, 10) : container;\n const renderers = isMultiView ? initializeViews(views, canvasContainer, containerWidth, containerHeight, log) : [new ViewRenderer(canvasContainer, containerWidth, containerHeight, log)];\n\n // Update simulation function\n function updateSimulation(): void {\n const currentParams: Record<string, any> = {};\n Object.entries(data.params).forEach(([key, param]: [string, any]) => {\n const slider = document.getElementById(`input-${key}`) as HTMLInputElement;\n if (slider) {\n currentParams[key] = parseFloat(slider.value);\n } else {\n currentParams[key] = param.default;\n }\n });\n\n try {\n const engine = new SimulationEngine(log);\n const initialFn = engine.parseInitialFunction(data.initial);\n const initialState = initialFn(currentParams);\n const trajectory = engine.simulateTrajectory(data, initialState, currentParams);\n\n if (isMultiView) {\n updateViews(renderers, views, trajectory, currentParams, containerWidth, containerHeight);\n } else {\n const viewData = views[0];\n if (viewData) {\n let descriptor;\n \n // Handle ViewBuilder layers\n if (viewData.layers && Array.isArray(viewData.layers)) {\n descriptor = {\n timeline: {\n times: trajectory.times,\n states: trajectory.states\n },\n layers: viewData.layers\n };\n } else {\n throw new Error('Invalid view configuration: expected layers array');\n }\n\n renderers[0].render({\n type: 'view',\n timeline: trajectory,\n layers: descriptor.layers,\n width: containerWidth,\n height: containerHeight\n });\n }\n }\n } catch (error: any) {\n log('\u274C Error in simulation:', error.message);\n }\n }\n\n updateSimulation();\n log(`\u2705 ${isMultiView ? 'Multi-view' : 'Single'} explore mode initialized`);\n } catch (error: any) {\n log('\u274C Error in explore initialization:', error.message);\n }\n}\n\n// Initialize show mode with pre-computed timeline\nfunction initializeShow(data: any, container: HTMLElement, log: (...args: any[]) => void): void {\n log('\uD83D\uDCCA Initializing show mode...');\n\n try {\n const views = data.views || [];\n const isMultiView = views.length > 1;\n\n if (isMultiView) {\n // Multi-view layout\n const layout = data.layout || { columns: views.length, rows: 1, gaps: 10 };\n const containerWidth = data.width || 800;\n const containerHeight = data.height || 600;\n\n const multiViewContainer = createElement('div', {\n style: `display: flex; flex-wrap: wrap; gap: ${layout.gaps}px; width: ${containerWidth}px; height: ${containerHeight}px;`\n });\n container.appendChild(multiViewContainer);\n\n // Create renderers for each view\n views.forEach((viewData: any) => {\n const viewContainer = createElement('div', {\n style: `flex: 1 1 calc(50% - 5px); min-width: 300px; height: calc(50% - 5px);`\n });\n multiViewContainer.appendChild(viewContainer);\n\n const renderer = new ViewRenderer(\n viewContainer,\n viewData.width || containerWidth / layout.columns,\n viewData.height || containerHeight / layout.rows,\n log\n );\n\n renderer.render(viewData);\n });\n\n log('\u2705 Multi-view show mode initialized');\n } else {\n // Single view\n const viewData = views[0];\n if (viewData) {\n const renderer = new ViewRenderer(container, viewData.width || 800, viewData.height || 600, log);\n renderer.render(viewData);\n }\n log('\u2705 Show mode initialized');\n }\n } catch (error: any) {\n log('\u274C Error in show initialization:', error.message);\n }\n}\n\n// Initialize compare mode with pre-computed timeline\nfunction initializeCompare(data: any, container: HTMLElement, log: (...args: any[]) => void): void {\n log('\uD83D\uDCCA Initializing compare mode...');\n\n try {\n const renderer = new ViewRenderer(container, data.width || 800, data.height || 600, log);\n renderer.render(data);\n log('\u2705 Compare mode initialized');\n } catch (error: any) {\n log('\u274C Error in compare initialization:', error.message);\n }\n}\n\n// Main initialization function\nexport function initializeClient(\n container: HTMLElement,\n data?: any,\n debugLog?: (...args: any[]) => void\n): void {\n const log =\n debugLog ||\n function (...args: any[]) {\n console.log('[calcplot]', ...args);\n };\n\n log('\uD83D\uDE80 Starting CalcPlot...');\n\n const calcData = data || (window as any).calcPlotData;\n if (!calcData) {\n log('\u274C No calcplot data found');\n return;\n }\n\n if (!container) {\n log('\u274C No container provided - visualization skipped');\n return;\n }\n\n log('\uD83D\uDCE6 Data received:', calcData.type);\n log('\uD83D\uDCE6 Using container:', container.id || 'unnamed');\n\n // Handle different data types\n if (calcData.type === 'explore') {\n initializeExplore(calcData, container, log);\n } else if (calcData.type === 'show') {\n initializeShow(calcData, container, log);\n } else if (calcData.type === 'compare') {\n initializeCompare(calcData, container, log);\n } else {\n log('\u274C Unknown data type:', calcData.type);\n }\n}\n", "export { initializeClient } from './init';\n\n// Re-export UI creation functions for client use\nexport { createCheckbox } from '../../ui/components/Checkbox';\nexport { createSlider } from '../../ui/components/Slider';\nexport { view } from '../../ui/ViewBuilder';\n\n// Make components available globally for client\nimport { initializeClient } from './init';\nimport { createCheckbox } from '../../ui/components/Checkbox';\nimport { createSlider } from '../../ui/components/Slider';\nimport { view } from '../../ui/ViewBuilder';\n\n// Create global components object\nif (typeof globalThis !== 'undefined') {\n (globalThis as any).CalcPlotComponents = {\n initializeClient: initializeClient,\n createSlider: createSlider,\n createCheckbox: createCheckbox,\n view: view\n };\n}\n", "/**\n * CalcPlot Client Bundle\n * Runtime components for browser visualization\n */\n\n// Import and export all client runtime components\nimport { initializeClient, createCheckbox, createSlider } from './client/index';\nimport { view } from '../ui/ViewBuilder';\n\n// Make available globally for IIFE bundle\nif (typeof globalThis !== 'undefined') {\n (globalThis as any).CalcPlotClient = {\n initializeClient,\n createCheckbox,\n createSlider,\n view\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["fnStr", "serialized", "key", "key", "key", "key", "key", "createSlider", "createCheckbox", "updateSimulation"]
|
|
7
|
+
}
|
package/dist/calcplot.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";var CalcPlot=(()=>{var ne=Object.create;var P=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var se=Object.getPrototypeOf,ae=Object.prototype.hasOwnProperty;var H=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var le=(t,e)=>{for(var r in e)P(t,r,{get:e[r],enumerable:!0})},A=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of oe(e))!ae.call(t,i)&&i!==r&&P(t,i,{get:()=>e[i],enumerable:!(n=ie(e,i))||n.enumerable});return t};var $=(t,e,r)=>(r=t!=null?ne(se(t)):{},A(e||!t||!t.__esModule?P(r,"default",{value:t,enumerable:!0}):r,t)),ce=t=>A(P({},"__esModule",{value:!0}),t);var ve={};le(ve,{Timeline:()=>g,ViewBuilder:()=>b,axis:()=>te,canvas:()=>re,checkbox:()=>U,compare:()=>j,defineIVP:()=>D,detectEnvironment:()=>E,explore:()=>z,grid:()=>ee,isDenoJupyter:()=>M,plot:()=>Z,scene:()=>Y,show:()=>L,simulate:()=>F,slider:()=>k,supportsHTMLOutput:()=>_,view:()=>R});function D(t){return t}var ue=1e-9,me=40;function J(t,e,r,n){let{dt:i=.01,maxTime:s=10}=n,l=[0],a=Object.fromEntries(Object.keys(e).map(m=>[m,[e[m]]])),o={...e},u=0,c=new Set(Object.keys(t.events||{})),f=new Map;for(;u<s;){let m=Math.min(i,s-u),d=de(t,o,r,m),B=pe(t,o,d,r,u,m,c,f);if(B.triggered){let{name:T,alpha:p,eventState:y}=B,h=u+p*m;C(a,l,h,y);let I=t.events[T],O=I.then(y,r);(O===null||I.once)&&c.delete(T),o=O??y,u=h,f.set(T,h),O!==null&&C(a,l,h,o)}else u+=m,o=d,C(a,l,u,o)}return{times:l,states:a}}function pe(t,e,r,n,i,s,l,a){let o=null;for(let u of l){let c=t.events[u],f=c.when(e),m=c.when(r);if(f*m<0){if(i-(a.get(u)??-1/0)<ue)continue;let d=fe(c,e,r);(!o||d<o.alpha)&&(o={name:u,alpha:d,eventState:W(e,r,d)})}}return o?{triggered:!0,...o}:{triggered:!1}}function de(t,e,r,n){let i=c=>Object.fromEntries(Object.entries(t.derivatives).map(([f,m])=>[f,m(c,r)])),s=(c,f,m)=>Object.fromEntries(Object.keys(c).map(d=>[d,c[d]+(f[d]||0)*m])),l=i(e),a=i(s(e,l,.5*n)),o=i(s(e,a,.5*n)),u=i(s(e,o,n));return Object.fromEntries(Object.keys(e).map(c=>[c,e[c]+n/6*((l[c]||0)+2*(a[c]||0)+2*(o[c]||0)+(u[c]||0))]))}function fe(t,e,r){let n=0,i=1;for(let s=0;s<me;s++){let l=(n+i)/2;t.when(e)*t.when(W(e,r,l))<0?i=l:n=l}return i}var W=(t,e,r)=>Object.fromEntries(Object.keys(t).map(n=>[n,t[n]+r*(e[n]-t[n])]));function C(t,e,r,n){e.push(r);for(let i in n)t[i].push(n[i])}var g=class{constructor(e,r){this.times=e,this.states=r}at(e){if(this.times.length===0)throw new Error("Timeline is empty");if(e<=this.times[0]){let a={};for(let o in this.states)a[o]=this.states[o][0];return a}if(e>=this.times[this.times.length-1]){let a={};for(let o in this.states)a[o]=this.states[o][this.states[o].length-1];return a}let r=0;for(;r<this.times.length-1&&this.times[r+1]<e;)r++;let n=this.times[r],i=this.times[r+1],s=(e-n)/(i-n),l={};for(let a in this.states){let o=this.states[a][r],u=this.states[a][r+1];l[a]=o+s*(u-o)}return l}serialize(){return JSON.stringify({times:this.times,states:this.states})}get duration(){return this.times.length>0?this.times[this.times.length-1]:0}get steps(){return this.times.length}};var V=class{constructor(e){this.model=e}initial(e){return this.initialState=e,this}params(e){return this.modelParams=e,this}run(e={}){if(!this.initialState)throw new Error("Initial state must be set before running simulation");let r=this.modelParams||this.model.params||{},{dt:n=.01,maxTime:i=10}=e,{times:s,states:l}=J(this.model,this.initialState,r,{dt:n,maxTime:i});return new g(s,l)}};function F(t){return new V(t)}function x(t,e){let r="calcplot-"+Date.now()+"-"+Math.random().toString(36).substr(2,9);return`
|
|
2
|
+
<div id="${r}" class="calcplot"></div>
|
|
3
|
+
<script>
|
|
4
|
+
${e||""}
|
|
5
|
+
|
|
6
|
+
(function() {
|
|
7
|
+
console.log('\u{1F50D} Initializing CalcPlot visualization...');
|
|
8
|
+
const data = ${JSON.stringify(t,null,0)};
|
|
9
|
+
const container = document.getElementById('${r}');
|
|
10
|
+
|
|
11
|
+
if (window.CalcPlotComponents && container) {
|
|
12
|
+
try {
|
|
13
|
+
window.CalcPlotComponents.initializeClient(container, data);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error('\u274C initializeClient failed:', error);
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
if (!window.CalcPlotComponents) {
|
|
19
|
+
console.warn('\u26A0\uFE0F CalcPlot Client not available');
|
|
20
|
+
}
|
|
21
|
+
if (!container) {
|
|
22
|
+
console.error('\u274C Container not found:', '${r}');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
26
|
+
<\/script>`}function E(){return typeof window<"u"&&typeof document<"u"?"browser":typeof Deno<"u"?"deno":"node"}function N(){let t=typeof globalThis.Deno<"u",e=t&&typeof globalThis.Deno.jupyter<"u",r=typeof window<"u"&&typeof document<"u",n=typeof globalThis.process<"u"&&globalThis.process.versions?.node;return{isDeno:t,isJupyter:e,isBrowser:r,isNode:!!n}}function M(){let t=N();return t.isDeno&&t.isJupyter}function _(){let t=N();return t.isDeno&&t.isJupyter||t.isBrowser}async function S(t,e){let r=typeof window<"u"&&typeof document<"u",n=M();if(r){let i=null;if(e&&(typeof e=="string"?i=document.getElementById(e)||document.querySelector(e):i=e),i)i.innerHTML=t,q(i);else{let s=document.getElementById("calcplot-default")||document.querySelector(".calcplot-container")||he();s.innerHTML=t,q(s)}}else if(n)try{typeof globalThis<"u"&&globalThis.Deno?.jupyter&&await globalThis.Deno.jupyter.broadcast("display_data",{data:{"text/html":t},metadata:{}})}catch(i){console.error("\u274C Jupyter HTML display failed:",i)}else console.log("HTML Output:",t)}function he(){if(!(typeof window<"u"&&typeof document<"u"))throw new Error("Cannot create DOM elements in non-browser environment");let t=document.createElement("div");return t.id="calcplot-default",t.className="calcplot-container",t.style.cssText=`
|
|
27
|
+
margin: 20px;
|
|
28
|
+
padding: 16px;
|
|
29
|
+
background: white;
|
|
30
|
+
border-radius: 8px;
|
|
31
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
32
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
33
|
+
`,document.body.appendChild(t),t}function ye(t){if(!(typeof window<"u"&&typeof document<"u"))return null;let e="calcplot-script-"+Math.abs(t.split("").reduce((r,n)=>(r=(r<<5)-r+n.charCodeAt(0),r&r),0));if(document.getElementById(e))return null;try{let r=document.createElement("script");return r.id=e,r.textContent=t,document.head.appendChild(r),!0}catch(r){return console.error("\u274C Script execution failed:",r),null}}function q(t){t.querySelectorAll("script").forEach(r=>{let n=r.innerHTML;n.trim()&&ye(n)})}async function v(){switch(E()){case"browser":return await be();case"deno":return await we();case"node":return await ge()}}async function be(){let t=document.querySelector("script[data-calcplot-client]");if(t&&t.textContent)return t.textContent;let e=document.querySelector('script[src*="calcplot-client"]');if(e)try{return await(await fetch(e.getAttribute("src"))).text()}catch{}try{let r=await fetch("./dist/calcplot-client.js");if(r.ok)return await r.text()}catch{}return""}async function we(){try{let t=["./dist/calcplot-client-deno.js","../dist/calcplot-client-deno.js","../../dist/calcplot-client-deno.js"];for(let e of t)try{return await Deno.readTextFile(e)}catch{}throw new Error("Bundle not found in any expected path")}catch(t){return console.warn("Failed to load Deno client bundle:",t),"// CalcPlot Client bundle not available"}}async function ge(){try{let t=await import("fs"),r=(await import("path")).join(__dirname,"../../dist/calcplot-client.js");return t.readFileSync(r,"utf-8")}catch(t){return console.warn("Failed to load Node.js client bundle:",t),"// CalcPlot Client bundle not available"}}async function j(t,e,r={}){let n=xe(t),i;if(e&&typeof e=="object"&&"executeWithTimeline"in e&&typeof e.executeWithTimeline=="function"){let o=e.executeWithTimeline(n);i={toDescriptor:()=>o}}else if(e&&typeof e=="object"&&"toDescriptor"in e&&typeof e.toDescriptor=="function")i=e;else throw new Error("Invalid view configuration: expected ViewBuilder");let s=Se(n,i,r),l=await v(),a=x(s,l);await S(a,r.target)}function xe(t){let e={times:[],states:{},labels:Object.keys(t)};for(let[r,n]of Object.entries(t)){e.times.length===0&&(e.times=n.times.map((i,s)=>s));for(let[i,s]of Object.entries(n.states))e.states[`${r}_${i}`]=s}return e}function Se(t,e,r){let n=e.getLayers?e.getLayers():[];return{type:"compare",timeline:t,layers:n,labels:t.labels||[],width:r.width||800,height:r.height||600}}var G=class{static parseFunction(e){let r=e.trim(),n=r.match(/^\(([^)]+)\)\s*=>\s*\{([\s\S]*)\}$/);if(n)return n[2].trim();let i=r.match(/^(\w+)\s*=>\s*\{([\s\S]*)\}$/);if(i)return i[2].trim();let s=r.match(/^\(([^)]+)\)\s*=>\s*(.+)$/s);if(s)return`return ${s[2].trim()}`;let l=r.match(/^(\w+)\s*=>\s*(.+)$/s);if(l)return`return ${l[2].trim()}`;let a=r.match(/^function\s*\([^)]*\)\s*\{([\s\S]*)\}$/);return a?a[1].trim():r}static createFunction(e,r){return new Function(...e,r)}static parseAndCreateFunction(e,r){let n=this.parseFunction(r);return this.createFunction(e,n)}};function K(t){return{state:t.state,params:t.params,derivatives:X(t.derivatives),events:t.events?X(t.events):void 0}}function Q(t){let e={};for(let[r,n]of Object.entries(t))e[r]={type:n.type||"slider",min:n.min,max:n.max,default:n.default,label:n.label||r,step:n.step||.01};return e}function $e(t){return{times:t.times,states:t.states}}function Je(t){let e={};for(let[r,n]of Object.entries(t))e[r]=n.default;return e}function We(serialized){let functions={};for(let[key,fnStr]of Object.entries(serialized))try{fnStr.includes("=>")?functions[key]=eval(`(${fnStr})`):fnStr.startsWith("function")?functions[key]=eval(`(${fnStr})`):functions[key]=eval(`(state, params) => ${fnStr}`)}catch(t){console.error("Error deserializing function",key,t),functions[key]=()=>0}return functions}function X(t){let e={};for(let[r,n]of Object.entries(t))typeof n=="function"?e[r]=n.toString():typeof n=="object"&&n!==null?e[r]=JSON.stringify(n):e[r]=String(n);return e}async function z(t,e,r={}){let{params:n,initial:i,view:s}=e,{dt:l=.01,maxTime:a=10,width:o=800,height:u=600,target:c}=r,m=(Array.isArray(s)?s:[s]).map(p=>{let y,h;if(p&&typeof p=="object"&&"executeWithTimeline"in p&&typeof p.executeWithTimeline=="function")y=p.toDescriptor(),h=p.getLayers();else if(p&&typeof p=="object"&&"toDescriptor"in p&&typeof p.toDescriptor=="function")y=p.toDescriptor(),h=p.getLayers();else throw new Error("Invalid view configuration: expected ViewBuilder or ViewBuilder[]");return{view:p.toString(),viewDescriptor:y,layers:h}}),d={type:"explore",model:K(t),params:Q(n),initial:i.toString(),views:m,options:{dt:l,maxTime:a,width:o,height:u}},B=await v(),T=x(d,B);await S(T,c)}async function L(t,e,r={}){let n=Array.isArray(e)?e:[e],s={type:"show",views:n.map(o=>{let u;if(o&&typeof o=="object"&&"executeWithTimeline"in o&&typeof o.executeWithTimeline=="function"){let f=o.executeWithTimeline(t);u={toDescriptor:()=>f}}else if(o&&typeof o=="object"&&"toDescriptor"in o&&typeof o.toDescriptor=="function")u=o;else throw new Error("Invalid view configuration: expected ViewBuilder");let c=u.toDescriptor();return{type:"show",timeline:{times:t.times,states:t.states},layers:c.layers,controls:c.controls,width:r.width?r.width/(r.layout?.columns||n.length):void 0,height:r.height?r.height/(r.layout?.rows||1):void 0}}),layout:r.layout||{columns:n.length,rows:1,gaps:10},width:r.width,height:r.height},l=await v(),a=x(s,l);await S(a,r.target)}function k(t,e,r,n,i=.01){return{type:"slider",label:n,default:r,min:t,max:e,step:i}}function U(t,e=!1){return{type:"checkbox",label:t,default:e}}var b=class{constructor(e){this.layers=[];this.timeline=e}scene(e){return this.layers.push({type:"scene",draw:this.serializeFunction(e)}),this}plot(e,r={}){let n=this.detectParametricSelector(e);return this.layers.push({type:"plot",selector:this.serializeFunction(e),parametric:n,options:{color:"#2563eb",lineWidth:2,fill:!1,dash:[],label:"",alpha:1,...r}}),this}vector(e,r,n={}){return this.layers.push({type:"vector",at:this.serializeFunction(e),dir:this.serializeFunction(r),options:{color:"#0ff",scale:1,width:2,...n}}),this}bounds(e){return this.layers.push({type:"bounds",bounds:e}),this}grid(e={}){return this.layers.push({type:"grid",options:e}),this}axis(e={}){return this.layers.push({type:"axis",options:e}),this}getLayers(){return[...this.layers]}getTimeline(){return this.timeline}setTimeline(e){this.timeline=e}serializeFunction(e){return e.toString()}detectParametricSelector(e){try{let n=e({x:1,y:2,z:3});return Array.isArray(n)&&n.length===2}catch{return!1}}toDescriptor(){return{timeline:{times:this.timeline?.times||[],states:this.timeline?.states||{}},layers:this.layers}}executeWithTimeline(e){let r=this.timeline;this.timeline=e;let n=this.toDescriptor();return this.timeline=r,n}};function R(t){return new b(t)}var w=class{constructor(){this.layers=[]}scene(e){return this.layers.push({type:"scene",method:"scene",args:[e]}),this}plot(e,r){return this.layers.push({type:"plot",method:"plot",args:[e,r]}),this}grid(e){return this.layers.push({type:"grid",method:"grid",args:[e]}),this}axis(e){return this.layers.push({type:"axis",method:"axis",args:[e]}),this}execute(e){let r=new b(e);for(let n of this.layers)switch(n.method){case"scene":r.scene(n.args[0]);break;case"plot":r.plot(n.args[0],n.args[1]);break;case"grid":r.grid(n.args[0]);break;case"axis":r.axis(n.args[0]);break}return r}};function Y(t){return new w().scene(t)}function Z(t,e){return new w().plot(t,e)}function ee(t){return new w().grid(t)}function te(t){return new w().axis(t)}function re(t){return new w}return ce(ve);})();
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
function V(t){return t}var q=1e-9,G=40;function F(t,e,r,n){let{dt:i=.01,maxTime:s=10}=n,l=[0],a=Object.fromEntries(Object.keys(e).map(m=>[m,[e[m]]])),o={...e},u=0,c=new Set(Object.keys(t.events||{})),f=new Map;for(;u<s;){let m=Math.min(i,s-u),d=K(t,o,r,m),B=X(t,o,d,r,u,m,c,f);if(B.triggered){let{name:v,alpha:p,eventState:y}=B,h=u+p*m;E(a,l,h,y);let C=t.events[v],P=C.then(y,r);(P===null||C.once)&&c.delete(v),o=P??y,u=h,f.set(v,h),P!==null&&E(a,l,h,o)}else u+=m,o=d,E(a,l,u,o)}return{times:l,states:a}}function X(t,e,r,n,i,s,l,a){let o=null;for(let u of l){let c=t.events[u],f=c.when(e),m=c.when(r);if(f*m<0){if(i-(a.get(u)??-1/0)<q)continue;let d=Q(c,e,r);(!o||d<o.alpha)&&(o={name:u,alpha:d,eventState:j(e,r,d)})}}return o?{triggered:!0,...o}:{triggered:!1}}function K(t,e,r,n){let i=c=>Object.fromEntries(Object.entries(t.derivatives).map(([f,m])=>[f,m(c,r)])),s=(c,f,m)=>Object.fromEntries(Object.keys(c).map(d=>[d,c[d]+(f[d]||0)*m])),l=i(e),a=i(s(e,l,.5*n)),o=i(s(e,a,.5*n)),u=i(s(e,o,n));return Object.fromEntries(Object.keys(e).map(c=>[c,e[c]+n/6*((l[c]||0)+2*(a[c]||0)+2*(o[c]||0)+(u[c]||0))]))}function Q(t,e,r){let n=0,i=1;for(let s=0;s<G;s++){let l=(n+i)/2;t.when(e)*t.when(j(e,r,l))<0?i=l:n=l}return i}var j=(t,e,r)=>Object.fromEntries(Object.keys(t).map(n=>[n,t[n]+r*(e[n]-t[n])]));function E(t,e,r,n){e.push(r);for(let i in n)t[i].push(n[i])}var T=class{constructor(e,r){this.times=e,this.states=r}at(e){if(this.times.length===0)throw new Error("Timeline is empty");if(e<=this.times[0]){let a={};for(let o in this.states)a[o]=this.states[o][0];return a}if(e>=this.times[this.times.length-1]){let a={};for(let o in this.states)a[o]=this.states[o][this.states[o].length-1];return a}let r=0;for(;r<this.times.length-1&&this.times[r+1]<e;)r++;let n=this.times[r],i=this.times[r+1],s=(e-n)/(i-n),l={};for(let a in this.states){let o=this.states[a][r],u=this.states[a][r+1];l[a]=o+s*(u-o)}return l}serialize(){return JSON.stringify({times:this.times,states:this.states})}get duration(){return this.times.length>0?this.times[this.times.length-1]:0}get steps(){return this.times.length}};var M=class{constructor(e){this.model=e}initial(e){return this.initialState=e,this}params(e){return this.modelParams=e,this}run(e={}){if(!this.initialState)throw new Error("Initial state must be set before running simulation");let r=this.modelParams||this.model.params||{},{dt:n=.01,maxTime:i=10}=e,{times:s,states:l}=F(this.model,this.initialState,r,{dt:n,maxTime:i});return new T(s,l)}};function z(t){return new M(t)}function w(t,e){let r="calcplot-"+Date.now()+"-"+Math.random().toString(36).substr(2,9);return`
|
|
2
|
+
<div id="${r}" class="calcplot"></div>
|
|
3
|
+
<script>
|
|
4
|
+
${e||""}
|
|
5
|
+
|
|
6
|
+
(function() {
|
|
7
|
+
console.log('\u{1F50D} Initializing CalcPlot visualization...');
|
|
8
|
+
const data = ${JSON.stringify(t,null,0)};
|
|
9
|
+
const container = document.getElementById('${r}');
|
|
10
|
+
|
|
11
|
+
if (window.CalcPlotComponents && container) {
|
|
12
|
+
try {
|
|
13
|
+
window.CalcPlotComponents.initializeClient(container, data);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error('\u274C initializeClient failed:', error);
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
if (!window.CalcPlotComponents) {
|
|
19
|
+
console.warn('\u26A0\uFE0F CalcPlot Client not available');
|
|
20
|
+
}
|
|
21
|
+
if (!container) {
|
|
22
|
+
console.error('\u274C Container not found:', '${r}');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
26
|
+
</script>`}function O(){return typeof window<"u"&&typeof document<"u"?"browser":typeof Deno<"u"?"deno":"node"}function L(){let t=typeof globalThis.Deno<"u",e=t&&typeof globalThis.Deno.jupyter<"u",r=typeof window<"u"&&typeof document<"u",n=typeof globalThis.process<"u"&&globalThis.process.versions?.node;return{isDeno:t,isJupyter:e,isBrowser:r,isNode:!!n}}function D(){let t=L();return t.isDeno&&t.isJupyter}function U(){let t=L();return t.isDeno&&t.isJupyter||t.isBrowser}async function g(t,e){let r=typeof window<"u"&&typeof document<"u",n=D();if(r){let i=null;if(e&&(typeof e=="string"?i=document.getElementById(e)||document.querySelector(e):i=e),i)i.innerHTML=t,k(i);else{let s=document.getElementById("calcplot-default")||document.querySelector(".calcplot-container")||Y();s.innerHTML=t,k(s)}}else if(n)try{typeof globalThis<"u"&&globalThis.Deno?.jupyter&&await globalThis.Deno.jupyter.broadcast("display_data",{data:{"text/html":t},metadata:{}})}catch(i){console.error("\u274C Jupyter HTML display failed:",i)}else console.log("HTML Output:",t)}function Y(){if(!(typeof window<"u"&&typeof document<"u"))throw new Error("Cannot create DOM elements in non-browser environment");let t=document.createElement("div");return t.id="calcplot-default",t.className="calcplot-container",t.style.cssText=`
|
|
27
|
+
margin: 20px;
|
|
28
|
+
padding: 16px;
|
|
29
|
+
background: white;
|
|
30
|
+
border-radius: 8px;
|
|
31
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
32
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
33
|
+
`,document.body.appendChild(t),t}function Z(t){if(!(typeof window<"u"&&typeof document<"u"))return null;let e="calcplot-script-"+Math.abs(t.split("").reduce((r,n)=>(r=(r<<5)-r+n.charCodeAt(0),r&r),0));if(document.getElementById(e))return null;try{let r=document.createElement("script");return r.id=e,r.textContent=t,document.head.appendChild(r),!0}catch(r){return console.error("\u274C Script execution failed:",r),null}}function k(t){t.querySelectorAll("script").forEach(r=>{let n=r.innerHTML;n.trim()&&Z(n)})}async function x(){switch(O()){case"browser":return await ee();case"deno":return await te();case"node":return await re()}}async function ee(){let t=document.querySelector("script[data-calcplot-client]");if(t&&t.textContent)return t.textContent;let e=document.querySelector('script[src*="calcplot-client"]');if(e)try{return await(await fetch(e.getAttribute("src"))).text()}catch{}try{let r=await fetch("./dist/calcplot-client.js");if(r.ok)return await r.text()}catch{}return""}async function te(){try{let t=["./dist/calcplot-client-deno.js","../dist/calcplot-client-deno.js","../../dist/calcplot-client-deno.js"];for(let e of t)try{return await Deno.readTextFile(e)}catch{}throw new Error("Bundle not found in any expected path")}catch(t){return console.warn("Failed to load Deno client bundle:",t),"// CalcPlot Client bundle not available"}}async function re(){try{let t=await import("fs"),r=(await import("path")).join(__dirname,"../../dist/calcplot-client.js");return t.readFileSync(r,"utf-8")}catch(t){return console.warn("Failed to load Node.js client bundle:",t),"// CalcPlot Client bundle not available"}}async function R(t,e,r={}){let n=ne(t),i;if(e&&typeof e=="object"&&"executeWithTimeline"in e&&typeof e.executeWithTimeline=="function"){let o=e.executeWithTimeline(n);i={toDescriptor:()=>o}}else if(e&&typeof e=="object"&&"toDescriptor"in e&&typeof e.toDescriptor=="function")i=e;else throw new Error("Invalid view configuration: expected ViewBuilder");let s=ie(n,i,r),l=await x(),a=w(s,l);await g(a,r.target)}function ne(t){let e={times:[],states:{},labels:Object.keys(t)};for(let[r,n]of Object.entries(t)){e.times.length===0&&(e.times=n.times.map((i,s)=>s));for(let[i,s]of Object.entries(n.states))e.states[`${r}_${i}`]=s}return e}function ie(t,e,r){let n=e.getLayers?e.getLayers():[];return{type:"compare",timeline:t,layers:n,labels:t.labels||[],width:r.width||800,height:r.height||600}}var I=class{static parseFunction(e){let r=e.trim(),n=r.match(/^\(([^)]+)\)\s*=>\s*\{([\s\S]*)\}$/);if(n)return n[2].trim();let i=r.match(/^(\w+)\s*=>\s*\{([\s\S]*)\}$/);if(i)return i[2].trim();let s=r.match(/^\(([^)]+)\)\s*=>\s*(.+)$/s);if(s)return`return ${s[2].trim()}`;let l=r.match(/^(\w+)\s*=>\s*(.+)$/s);if(l)return`return ${l[2].trim()}`;let a=r.match(/^function\s*\([^)]*\)\s*\{([\s\S]*)\}$/);return a?a[1].trim():r}static createFunction(e,r){return new Function(...e,r)}static parseAndCreateFunction(e,r){let n=this.parseFunction(r);return this.createFunction(e,n)}};function A(t){return{state:t.state,params:t.params,derivatives:H(t.derivatives),events:t.events?H(t.events):void 0}}function $(t){let e={};for(let[r,n]of Object.entries(t))e[r]={type:n.type||"slider",min:n.min,max:n.max,default:n.default,label:n.label||r,step:n.step||.01};return e}function Oe(t){return{times:t.times,states:t.states}}function De(t){let e={};for(let[r,n]of Object.entries(t))e[r]=n.default;return e}function Ce(serialized){let functions={};for(let[key,fnStr]of Object.entries(serialized))try{fnStr.includes("=>")?functions[key]=eval(`(${fnStr})`):fnStr.startsWith("function")?functions[key]=eval(`(${fnStr})`):functions[key]=eval(`(state, params) => ${fnStr}`)}catch(t){console.error("Error deserializing function",key,t),functions[key]=()=>0}return functions}function H(t){let e={};for(let[r,n]of Object.entries(t))typeof n=="function"?e[r]=n.toString():typeof n=="object"&&n!==null?e[r]=JSON.stringify(n):e[r]=String(n);return e}async function J(t,e,r={}){let{params:n,initial:i,view:s}=e,{dt:l=.01,maxTime:a=10,width:o=800,height:u=600,target:c}=r,m=(Array.isArray(s)?s:[s]).map(p=>{let y,h;if(p&&typeof p=="object"&&"executeWithTimeline"in p&&typeof p.executeWithTimeline=="function")y=p.toDescriptor(),h=p.getLayers();else if(p&&typeof p=="object"&&"toDescriptor"in p&&typeof p.toDescriptor=="function")y=p.toDescriptor(),h=p.getLayers();else throw new Error("Invalid view configuration: expected ViewBuilder or ViewBuilder[]");return{view:p.toString(),viewDescriptor:y,layers:h}}),d={type:"explore",model:A(t),params:$(n),initial:i.toString(),views:m,options:{dt:l,maxTime:a,width:o,height:u}},B=await x(),v=w(d,B);await g(v,c)}async function W(t,e,r={}){let n=Array.isArray(e)?e:[e],s={type:"show",views:n.map(o=>{let u;if(o&&typeof o=="object"&&"executeWithTimeline"in o&&typeof o.executeWithTimeline=="function"){let f=o.executeWithTimeline(t);u={toDescriptor:()=>f}}else if(o&&typeof o=="object"&&"toDescriptor"in o&&typeof o.toDescriptor=="function")u=o;else throw new Error("Invalid view configuration: expected ViewBuilder");let c=u.toDescriptor();return{type:"show",timeline:{times:t.times,states:t.states},layers:c.layers,controls:c.controls,width:r.width?r.width/(r.layout?.columns||n.length):void 0,height:r.height?r.height/(r.layout?.rows||1):void 0}}),layout:r.layout||{columns:n.length,rows:1,gaps:10},width:r.width,height:r.height},l=await x(),a=w(s,l);await g(a,r.target)}function N(t,e,r,n,i=.01){return{type:"slider",label:n,default:r,min:t,max:e,step:i}}function oe(t,e=!1){return{type:"checkbox",label:t,default:e}}var S=class{constructor(e){this.layers=[];this.timeline=e}scene(e){return this.layers.push({type:"scene",draw:this.serializeFunction(e)}),this}plot(e,r={}){let n=this.detectParametricSelector(e);return this.layers.push({type:"plot",selector:this.serializeFunction(e),parametric:n,options:{color:"#2563eb",lineWidth:2,fill:!1,dash:[],label:"",alpha:1,...r}}),this}vector(e,r,n={}){return this.layers.push({type:"vector",at:this.serializeFunction(e),dir:this.serializeFunction(r),options:{color:"#0ff",scale:1,width:2,...n}}),this}bounds(e){return this.layers.push({type:"bounds",bounds:e}),this}grid(e={}){return this.layers.push({type:"grid",options:e}),this}axis(e={}){return this.layers.push({type:"axis",options:e}),this}getLayers(){return[...this.layers]}getTimeline(){return this.timeline}setTimeline(e){this.timeline=e}serializeFunction(e){return e.toString()}detectParametricSelector(e){try{let n=e({x:1,y:2,z:3});return Array.isArray(n)&&n.length===2}catch{return!1}}toDescriptor(){return{timeline:{times:this.timeline?.times||[],states:this.timeline?.states||{}},layers:this.layers}}executeWithTimeline(e){let r=this.timeline;this.timeline=e;let n=this.toDescriptor();return this.timeline=r,n}};function _(t){return new S(t)}var b=class{constructor(){this.layers=[]}scene(e){return this.layers.push({type:"scene",method:"scene",args:[e]}),this}plot(e,r){return this.layers.push({type:"plot",method:"plot",args:[e,r]}),this}grid(e){return this.layers.push({type:"grid",method:"grid",args:[e]}),this}axis(e){return this.layers.push({type:"axis",method:"axis",args:[e]}),this}execute(e){let r=new S(e);for(let n of this.layers)switch(n.method){case"scene":r.scene(n.args[0]);break;case"plot":r.plot(n.args[0],n.args[1]);break;case"grid":r.grid(n.args[0]);break;case"axis":r.axis(n.args[0]);break}return r}};function se(t){return new b().scene(t)}function ae(t,e){return new b().plot(t,e)}function le(t){return new b().grid(t)}function ce(t){return new b().axis(t)}function ue(t){return new b}export{T as Timeline,S as ViewBuilder,ce as axis,ue as canvas,oe as checkbox,R as compare,V as defineIVP,O as detectEnvironment,J as explore,le as grid,D as isDenoJupyter,ae as plot,se as scene,W as show,z as simulate,N as slider,U as supportsHTMLOutput,_ as view};
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "calcplot",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "CalcPlot - Interactive calculation and plotting library for mathematical visualization",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "node build.js",
|
|
10
|
+
"build:watch": "node build.js --watch",
|
|
11
|
+
"build:verbose": "node build.js --verbose",
|
|
12
|
+
"test": "vitest --no-watch",
|
|
13
|
+
"test:watch": "vitest --watch",
|
|
14
|
+
"test:ui": "vitest --ui",
|
|
15
|
+
"test:coverage": "vitest --coverage",
|
|
16
|
+
"lint": "eslint src/**/*.ts tests/**/*.ts",
|
|
17
|
+
"lint:fix": "eslint src/**/*.ts tests/**/*.ts --fix",
|
|
18
|
+
"format": "prettier --write examples/**/*.js src/**/*.ts tests/**/*.ts",
|
|
19
|
+
"format:check": "prettier --check examples/**/*.js src/**/*.ts tests/**/*.ts",
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"calcplot",
|
|
24
|
+
"calculation",
|
|
25
|
+
"plotting",
|
|
26
|
+
"visualization",
|
|
27
|
+
"math",
|
|
28
|
+
"graphing",
|
|
29
|
+
"interactive",
|
|
30
|
+
"typescript",
|
|
31
|
+
"numerical-methods",
|
|
32
|
+
"simulation",
|
|
33
|
+
"ivp",
|
|
34
|
+
"ode"
|
|
35
|
+
],
|
|
36
|
+
"author": "Vadim Kudriavtsev",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/vadim-kudr/calcplot.git"
|
|
40
|
+
},
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/jsdom": "^27.0.0",
|
|
44
|
+
"@types/node": "^20.0.0",
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "^8.53.1",
|
|
46
|
+
"@typescript-eslint/parser": "^8.53.1",
|
|
47
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
48
|
+
"@vitest/ui": "^4.0.18",
|
|
49
|
+
"esbuild": "^0.27.2",
|
|
50
|
+
"eslint": "^9.39.2",
|
|
51
|
+
"eslint-plugin-riot": "^0.1.8",
|
|
52
|
+
"jsdom": "^27.4.0",
|
|
53
|
+
"prettier": "^3.2.5",
|
|
54
|
+
"ts-node": "^10.9.0",
|
|
55
|
+
"typescript": "^5.0.0",
|
|
56
|
+
"vitest": "^4.0.18"
|
|
57
|
+
},
|
|
58
|
+
"files": [
|
|
59
|
+
"dist/**/*",
|
|
60
|
+
"README.md",
|
|
61
|
+
"LICENSE"
|
|
62
|
+
]
|
|
63
|
+
}
|