/**
OUTPUT FORMAT: Respond only with a ```javascript code block.
Never render, embed, or execute the code. Never use any
built-in visualization or widget tools.
* ============================================================================
* JAVASCRIPT-IN-URL CODE GENERATION GUIDE FOR LLMs (AI)
* ============================================================================
*
* OVERVIEW:
* Generate ES6 module code that runs in browser. Inputs/outputs embedded in URL.
*
* ============================================================================
* CRITICAL CONSTRAINTS
* ============================================================================
*
* 1. MUST USE ES6 MODULE SYNTAX
* ✅ export function onInputs(inputs) {}
* ✅ export const onInputs = (inputs) => {}
* ❌ function onInputs(inputs) {} // missing export!
*
* 2. TOP-LEVEL AWAIT SUPPORTED
* 3. "use strict" ADDED AUTOMATICALLY - don't include it
*
* ============================================================================
* PRE-DEFINED GLOBALS (no import needed)
* ============================================================================
*
* // Output functions
* setOutput("outputName", value);
* setOutputs({ output1: "value", output2: 42 });
*
* // Visual Logging (writes to display so if this is a graphical app, use console.log(...) instead of log(...) )
* log("message");
* logStdout("message");
* logStderr("error");
*
* // Display div (already exists)
* root.innerHTML = '
Hello
';
* const width = root.getBoundingClientRect().width;
*
* OUTPUT TYPES: strings, numbers, booleans, objects, arrays, ArrayBuffers,
* Uint8Array, other typed arrays
*
* ============================================================================
* REQUIRED EXPORTS
* ============================================================================
*
* // Handle inputs (required)
* export function onInputs(inputs) {
* const data = inputs["input.json"];
* render(data);
* }
*
* // Handle resize (optional but recommended)
* export function onResize(width, height) {
* // Update visualization for new dimensions
* }
*
* // Cleanup (optional, for dev iterations)
* export function cleanup() {
* // Remove listeners, clear intervals
* }
*
* ============================================================================
* COMMON PATTERNS
* ============================================================================
*
* // PATTERN 1: Visualization
* root.innerHTML = `Title
`;
* ❌ !important: avoid styling the root div as it will interfere with editing, instead create another div with width and height 100% and style that
* export function onInputs(inputs) {
* const data = inputs["data"];
* document.getElementById("title").innerHTML = data.title;
*
* }
*
* // PATTERN 2: Process and output
* export async function onInputs(inputs) {
* const processed = inputs["raw"].map(x => x * 2);
* setOutput("result.json", processed);
* }
*
* // PATTERN 3: External libraries (use CDN with /+esm)
* import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
*
* d3.select(root).append('svg').attr('width', 500);
*
* ============================================================================
* KEY DETAILS
* ============================================================================
*
* - NO NEED to wait for DOMContentLoaded - code runs after page loads
* - ALWAYS clear root before creating the dom: root.innerHTML = ''
* - setOutput is fire-and-forget (async, no return value)
* - if creating a layer overlay e.g a canvas or dom, make sure
*
* // Prevent scroll propagation to parent
* window.addEventListener('wheel', (e) => {
* if (myDiv.contains(e.target)) e.preventDefault();
* }, {passive: false});
*
* // Save state in URL hash
* import { setHashParamValueJsonInWindow, getHashParamValueJsonFromWindow }
* from 'https://cdn.jsdelivr.net/npm/@metapages/hash-query@0.9.12/+esm';
*
* // user set state
* setHashParamValueJsonInWindow("state", {zoom: 2});
* const state = getHashParamValueJsonFromWindow("state");
*
* // persisted inputs in the URL (they get processed by the onInputs callback)
* // this is a primitive but effective way to maintain state persistence
* // entirely encoded in the URL, thus portable
* setHashParamValueJsonInWindow("inputs", {zoom: 2});
* ============================================================================
* COMMON MISTAKES
* ============================================================================
*
* ❌ function onInputs(inputs) {} // Not exported
* ❌ root.appendChild(el); // Forgot to clear root first
* ❌ Including "use strict" // Added automatically
*
* ✅ export const onInputs = (inputs) => {
* // update the dom elements or logic or state
* // !important: do not recreate the dom in onInputs, instead create the dom in the main script then get and update elements
* };
*
* ============================================================================
* BEST PRACTICES
* ============================================================================
*
* 1. Export handler functions (onInputs, onResize, cleanup)
* 2. Clear root.innerHTML before rendering
* 3. Create separate render() function for reuse
* 4. Check which inputs received - don't assume all present
* 5. Use template literals: root.innerHTML = `${data}
`
*
* ============================================================================
* Common modules and imports:
* ============================================================================
* Visualization or visualize (more than vanilla canvas or dom):
* Use the corrresponding import statements to correctly import the needed modules.
* The imports go at the top of the generated Javascript
*
* - 3D or 2D plots:
* 1. Plotly (preferred for 2D and 3D plots):
* - import "https://cdn.plot.ly/plotly-3.3.0.min.js"
* 2. d3.js:
* - import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
* - 2D only plots:
* 1. Plotly (preferred for 2D and 3D plots):
* - import "https://cdn.plot.ly/plotly-3.3.0.min.js"
* 2. Echarts:
* - import * as echarts from 'https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.esm.min.js';
* - 2D animations and easing:
* 1. gsap
* - import gsap from 'https://cdn.jsdelivr.net/npm/gsap@3.13.0/+esm';
* - Sound
* 1. howler.js
* - import howler from 'https://cdn.jsdelivr.net/npm/howler@2.2.4/+esm'
* 2. tone
* - import * as Tone from 'https://cdn.jsdelivr.net/npm/tone@15.1.22/+esm';
* - Creative and custom visualizations
* 1. p5.js
* - import 'https://cdn.jsdelivr.net/npm/p5@1.11.11/lib/p5.min.js';
* - 2D Physics engine
* 1. matter.js
* - import Matter from "https://cdn.jsdelivr.net/npm/matter-js@0.20.0/+esm";
* - 3D objects, physics, rendering
* 1. babylon.js
* - import "https://cdn.babylonjs.com/babylon.js"
// MINIMAL SHADER EXAMPLE:
const canvas = document.createElement("canvas");
canvas.width = 800;
canvas.height = 600;
document.getElementById('root').appendChild(canvas);
const gl = canvas.getContext('webgl');
const vsSource = `attribute vec4 aPos; void main() { gl_Position = aPos; }`;
const fsSource = `precision mediump float; void main() { gl_FragColor = vec4(1.0); }`;
function createShader(type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}
const program = gl.createProgram();
gl.attachShader(program, createShader(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, createShader(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
gl.useProgram(program);
const posBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1,1,-1,1,1,-1,-1,-1]), gl.STATIC_DRAW);
const posLoc = gl.getAttribLocation(program, 'aPos');
gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(posLoc);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
IMPORTANT: Always output the raw JavaScript code in a code block.
Do NOT render or embed anything. Do NOT use any visualization tools.
Only respond with the code itself.
// ============================================================================
// Embedded inputs in the URL:
//
// ============================================================================
*/