diff --git a/training-data/code-patterns-frontend-&-creative.jsonl b/training-data/code-patterns-frontend-&-creative.jsonl new file mode 100644 index 00000000..107dd01f --- /dev/null +++ b/training-data/code-patterns-frontend-&-creative.jsonl @@ -0,0 +1,1000 @@ +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#ff6b6b', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.03;\n cube.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 0} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n scene.fog = new THREE.Fog('#4ecdc4', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 1} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 12, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.05,\n y: (Math.random() - 0.5) * 0.05,\n z: (Math.random() - 0.5) * 0.05\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#6c5ce7', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 2} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#96ceb4');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#45b7d1', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#fab1a0',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 3} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#45b7d1' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 4} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#45b7d1', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#a29bfe' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.1;\n torus.rotation.y += 0.1 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 5} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 6} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #00b894;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 7} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 8} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 9} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 10} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 11} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 12} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 13} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 14} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #e84393; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 15} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 16} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#45b7d1';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 17} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 18} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$200px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 19} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#6c5ce7';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 20} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 21} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 22} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#4ecdc4');\n// renderer.registerTile(1, '#dfe6e9');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 23} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 15,\n speed = 0.01,\n life = 1.0,\n colors = ['#4ecdc4', '#e84393', '#0984e3'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#ffeaa7', '#fd79a8', '#e17055'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 24} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#00cec9', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.015;\n cube.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 25} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n scene.fog = new THREE.Fog('#fab1a0', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 26} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 12, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.02,\n y: (Math.random() - 0.5) * 0.02,\n z: (Math.random() - 0.5) * 0.02\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#fd79a8', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 27} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#ff6b6b');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#6c5ce7', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#96ceb4',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 28} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#55efc4' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 29} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#ffeaa7', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00b894' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.02;\n torus.rotation.y += 0.02 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 30} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 31} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #74b9ff;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 32} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 33} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 34} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 35} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 36} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 37} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 38} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 39} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #ff6b6b; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 40} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 41} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#fdcb6e';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 42} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 43} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$100%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 44} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#a29bfe';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 45} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 46} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 47} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#e84393');\n// renderer.registerTile(1, '#6c5ce7');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 48} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 12,\n speed = 0.02,\n life = 1.0,\n colors = ['#74b9ff', '#e84393', '#45b7d1'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#a29bfe', '#00b894', '#6c5ce7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 49} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#ffeaa7', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.03;\n cube.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 50} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#74b9ff');\n scene.fog = new THREE.Fog('#74b9ff', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 51} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 10, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.005,\n y: (Math.random() - 0.5) * 0.005,\n z: (Math.random() - 0.5) * 0.005\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#ff6b6b', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 52} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#fdcb6e');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#0984e3', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#ff6b6b',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 53} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#ff6b6b' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 54} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#74b9ff', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#fd79a8' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.015;\n torus.rotation.y += 0.015 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 55} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 56} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fd79a8;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 57} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 58} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 59} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 60} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 61} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 62} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 63} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 64} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #0984e3; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 65} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 66} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00b894';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 67} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 68} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$250px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 69} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#e17055';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 70} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 71} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 72} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fdcb6e');\n// renderer.registerTile(1, '#e17055');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 73} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 20,\n speed = 0.01,\n life = 1.0,\n colors = ['#6c5ce7', '#0984e3', '#e17055'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#dfe6e9', '#a29bfe', '#dfe6e9'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 74} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#a29bfe', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.01;\n cube.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 75} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n scene.fog = new THREE.Fog('#96ceb4', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 76} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 20, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.03,\n y: (Math.random() - 0.5) * 0.03,\n z: (Math.random() - 0.5) * 0.03\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#e17055', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 77} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#6c5ce7');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#45b7d1', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#4ecdc4',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 78} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ff6b6b');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#00b894' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 79} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#45b7d1', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#0984e3' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.05;\n torus.rotation.y += 0.05 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 80} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 81} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fab1a0;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 82} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 83} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 84} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 85} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 86} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 87} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 88} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 89} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #00cec9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 90} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 91} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#0984e3';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 92} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 93} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$250px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 94} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fab1a0';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 95} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 96} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 97} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fab1a0');\n// renderer.registerTile(1, '#00b894');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 98} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 5,\n speed = 0.03,\n life = 1.0,\n colors = ['#4ecdc4', '#e17055', '#6c5ce7'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#a29bfe', '#fd79a8', '#00b894'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 99} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#55efc4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.03;\n cube.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 100} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e84393');\n scene.fog = new THREE.Fog('#e84393', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 101} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 15, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.015,\n y: (Math.random() - 0.5) * 0.015,\n z: (Math.random() - 0.5) * 0.015\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#45b7d1', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 102} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#00b894');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#e84393', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#96ceb4',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 103} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#ff6b6b' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 104} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#ffeaa7', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#4ecdc4' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.01;\n torus.rotation.y += 0.01 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 105} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 106} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(50%, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #4ecdc4;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 107} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 108} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 109} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 110} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 111} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 112} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 113} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 114} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #00cec9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 115} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 116} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00b894';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 117} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 118} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$80vh`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 119} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#96ceb4';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 120} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 121} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 122} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#dfe6e9');\n// renderer.registerTile(1, '#55efc4');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 123} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 12,\n speed = 0.1,\n life = 1.0,\n colors = ['#fd79a8', '#00cec9', '#96ceb4'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#00b894', '#6c5ce7', '#fdcb6e'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 124} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#55efc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fdcb6e', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.005;\n cube.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 125} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n scene.fog = new THREE.Fog('#4ecdc4', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 126} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 10, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.005,\n y: (Math.random() - 0.5) * 0.005,\n z: (Math.random() - 0.5) * 0.005\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#0984e3', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 127} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#fab1a0');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#4ecdc4', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#fdcb6e',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 128} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#96ceb4' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 129} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#a29bfe', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#fdcb6e' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.01;\n torus.rotation.y += 0.01 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 130} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 131} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #a29bfe;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 132} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 133} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 134} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 135} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 136} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 137} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 138} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 139} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fab1a0; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 140} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 141} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#a29bfe';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 142} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 143} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$250px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 144} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#6c5ce7';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 145} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 146} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 147} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#4ecdc4');\n// renderer.registerTile(1, '#fab1a0');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 148} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.015,\n life = 1.0,\n colors = ['#ffeaa7', '#0984e3', '#6c5ce7'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#96ceb4', '#74b9ff', '#ffeaa7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 149} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ff6b6b');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#45b7d1', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.005;\n cube.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 150} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n scene.fog = new THREE.Fog('#e17055', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 151} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 20, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.02,\n y: (Math.random() - 0.5) * 0.02,\n z: (Math.random() - 0.5) * 0.02\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#e17055', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 152} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#45b7d1');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#00cec9', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#e84393',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 153} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#55efc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#00b894' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 154} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#55efc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#e84393', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#74b9ff' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.03;\n torus.rotation.y += 0.03 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 155} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 156} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(50%, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #e84393;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 157} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 158} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 159} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 160} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 161} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 162} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 163} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 164} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #00cec9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 165} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 166} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#45b7d1';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 167} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 168} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$400px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 169} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#74b9ff';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 170} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 171} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 172} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#00cec9');\n// renderer.registerTile(1, '#dfe6e9');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 173} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 12,\n speed = 0.1,\n life = 1.0,\n colors = ['#e17055', '#0984e3', '#a29bfe'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#00b894', '#fd79a8', '#fdcb6e'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 174} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#e17055', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.02;\n cube.rotation.y += 0.02;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 175} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fd79a8');\n scene.fog = new THREE.Fog('#fd79a8', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 176} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 12, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.01,\n y: (Math.random() - 0.5) * 0.01,\n z: (Math.random() - 0.5) * 0.01\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#e84393', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 177} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#96ceb4');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#4ecdc4', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#e17055',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.02;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 178} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#dfe6e9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#0984e3' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 179} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#fd79a8', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#55efc4' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.1;\n torus.rotation.y += 0.1 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 180} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 181} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #e84393;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 182} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 183} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 184} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 185} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 186} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 187} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 188} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 189} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #dfe6e9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 190} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 191} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#55efc4';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 192} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 193} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$50%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 194} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#4ecdc4';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 195} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 196} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 197} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#96ceb4');\n// renderer.registerTile(1, '#74b9ff');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 198} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 12,\n speed = 0.03,\n life = 1.0,\n colors = ['#dfe6e9', '#ff6b6b', '#74b9ff'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#00b894', '#fd79a8', '#96ceb4'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 199} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fd79a8', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.015;\n cube.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 200} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n scene.fog = new THREE.Fog('#fab1a0', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 201} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 15, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.05,\n y: (Math.random() - 0.5) * 0.05,\n z: (Math.random() - 0.5) * 0.05\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#00b894', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 202} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#6c5ce7');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#e17055', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 203} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#a29bfe' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 204} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#45b7d1', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00cec9' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.01;\n torus.rotation.y += 0.01 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 205} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 206} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #4ecdc4;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 207} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 208} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 209} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 210} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 211} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 212} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 213} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 214} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #a29bfe; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 215} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 216} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00cec9';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 217} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 218} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$200px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 219} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#00b894';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 220} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 221} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 222} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#6c5ce7');\n// renderer.registerTile(1, '#96ceb4');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 223} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 8,\n speed = 0.05,\n life = 1.0,\n colors = ['#fd79a8', '#74b9ff', '#a29bfe'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#ff6b6b', '#00b894', '#e84393'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 224} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#a29bfe', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.05;\n cube.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 225} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#55efc4');\n scene.fog = new THREE.Fog('#55efc4', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 226} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 8, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.01,\n y: (Math.random() - 0.5) * 0.01,\n z: (Math.random() - 0.5) * 0.01\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#ff6b6b', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 227} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#55efc4');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#4ecdc4', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#0984e3',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 228} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e84393');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#e17055' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 229} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#fd79a8', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00cec9' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.015;\n torus.rotation.y += 0.015 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 230} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 231} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fab1a0;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 232} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 233} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 234} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 235} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 236} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 237} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 238} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 239} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #dfe6e9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 240} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 241} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#fab1a0';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 242} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 243} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$80vh`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 244} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fdcb6e';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 245} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 246} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 247} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fdcb6e');\n// renderer.registerTile(1, '#0984e3');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 248} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 3,\n speed = 0.005,\n life = 1.0,\n colors = ['#55efc4', '#45b7d1', '#96ceb4'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#6c5ce7', '#0984e3', '#fab1a0'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 249} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#55efc4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.005;\n cube.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 250} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ff6b6b');\n scene.fog = new THREE.Fog('#ff6b6b', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 251} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 12, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.01,\n y: (Math.random() - 0.5) * 0.01,\n z: (Math.random() - 0.5) * 0.01\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#00cec9', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 252} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#ffeaa7');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#55efc4', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#e17055',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 253} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#6c5ce7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#6c5ce7' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 254} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#dfe6e9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#a29bfe', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00cec9' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.05;\n torus.rotation.y += 0.05 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 255} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 256} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fd79a8;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 257} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 258} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 259} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 260} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 261} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 262} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 263} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 264} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #e84393; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 265} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 266} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#45b7d1';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 267} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 268} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$100%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 269} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#74b9ff';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 270} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 271} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 272} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#e17055');\n// renderer.registerTile(1, '#74b9ff');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 273} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 20,\n speed = 0.01,\n life = 1.0,\n colors = ['#fd79a8', '#ffeaa7', '#e17055'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#6c5ce7', '#ff6b6b', '#96ceb4'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 274} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#dfe6e9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#00b894', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.01;\n cube.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 275} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n scene.fog = new THREE.Fog('#e17055', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 276} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 5, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.015,\n y: (Math.random() - 0.5) * 0.015,\n z: (Math.random() - 0.5) * 0.015\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#00cec9', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 277} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#45b7d1');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#a29bfe', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#fab1a0',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 278} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#ffeaa7' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 279} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#fdcb6e', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#6c5ce7' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.02;\n torus.rotation.y += 0.02 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 280} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 281} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #00cec9;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 282} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 283} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 284} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 285} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 286} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 287} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 288} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 289} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fdcb6e; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 290} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 291} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#4ecdc4';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 292} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 293} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$200px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 294} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#e84393';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 295} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 296} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 297} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#ffeaa7');\n// renderer.registerTile(1, '#00b894');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 298} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 8,\n speed = 0.1,\n life = 1.0,\n colors = ['#a29bfe', '#e17055', '#00b894'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#00cec9', '#ffeaa7', '#fab1a0'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 299} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#74b9ff');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fab1a0', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.02;\n cube.rotation.y += 0.02;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 300} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n scene.fog = new THREE.Fog('#ffeaa7', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 301} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 12, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.02,\n y: (Math.random() - 0.5) * 0.02,\n z: (Math.random() - 0.5) * 0.02\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#e17055', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 302} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#ffeaa7');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#45b7d1', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#a29bfe',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 303} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#6c5ce7' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 304} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#a29bfe', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#ffeaa7' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.03;\n torus.rotation.y += 0.03 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 305} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 306} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(60vw, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fdcb6e;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 307} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 308} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 309} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 310} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 311} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 312} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 313} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 314} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #ff6b6b; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 315} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 316} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#74b9ff';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 317} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 318} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$80vh`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 319} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#dfe6e9';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 320} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 321} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 322} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#ff6b6b');\n// renderer.registerTile(1, '#74b9ff');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 323} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 20,\n speed = 0.005,\n life = 1.0,\n colors = ['#dfe6e9', '#4ecdc4', '#96ceb4'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#74b9ff', '#0984e3', '#ff6b6b'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 324} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#74b9ff');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fd79a8', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.03;\n cube.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 325} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n scene.fog = new THREE.Fog('#96ceb4', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 326} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 8, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.02,\n y: (Math.random() - 0.5) * 0.02,\n z: (Math.random() - 0.5) * 0.02\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#e17055', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 327} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#96ceb4');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#e17055', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#fab1a0',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 328} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#55efc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#dfe6e9' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 329} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#96ceb4', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#45b7d1' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.1;\n torus.rotation.y += 0.1 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 330} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 331} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #00cec9;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 332} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 333} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 334} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 335} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 336} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 337} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 338} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 339} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #00cec9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 340} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 341} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#55efc4';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 342} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 343} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$50%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 344} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fdcb6e';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 345} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 346} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 347} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#45b7d1');\n// renderer.registerTile(1, '#74b9ff');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 348} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.03,\n life = 1.0,\n colors = ['#e17055', '#00b894', '#fdcb6e'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#4ecdc4', '#fab1a0', '#74b9ff'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 349} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fab1a0', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.05;\n cube.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 350} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n scene.fog = new THREE.Fog('#00cec9', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 351} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 10, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.05,\n y: (Math.random() - 0.5) * 0.05,\n z: (Math.random() - 0.5) * 0.05\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#dfe6e9', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 352} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#55efc4');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#00b894', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#e17055',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 353} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#00cec9' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 354} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#74b9ff', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#dfe6e9' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.03;\n torus.rotation.y += 0.03 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 355} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 356} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fab1a0;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 357} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 358} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 359} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 360} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 361} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 362} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 363} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 364} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #0984e3; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 365} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 366} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#0984e3';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 367} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 368} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$300px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 369} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#55efc4';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 370} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 371} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 372} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fdcb6e');\n// renderer.registerTile(1, '#6c5ce7');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 373} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 3,\n speed = 0.02,\n life = 1.0,\n colors = ['#ff6b6b', '#dfe6e9', '#0984e3'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#fdcb6e', '#a29bfe', '#0984e3'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 374} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#dfe6e9', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.05;\n cube.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 375} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e84393');\n scene.fog = new THREE.Fog('#e84393', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 376} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 20, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.1,\n y: (Math.random() - 0.5) * 0.1,\n z: (Math.random() - 0.5) * 0.1\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#96ceb4', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 377} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#e17055');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#00cec9', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#e84393',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 378} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#74b9ff');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#e84393' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 379} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ff6b6b');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#74b9ff', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#55efc4' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.005;\n torus.rotation.y += 0.005 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 380} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 381} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fd79a8;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 382} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 383} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 384} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 385} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 386} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 387} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 388} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 389} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #a29bfe; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 390} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 391} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#e17055';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 392} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 393} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$100%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 394} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#dfe6e9';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 395} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 396} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 397} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#00b894');\n// renderer.registerTile(1, '#e84393');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 398} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 3,\n speed = 0.015,\n life = 1.0,\n colors = ['#45b7d1', '#fd79a8', '#00cec9'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#fd79a8', '#74b9ff', '#00cec9'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 399} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#96ceb4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.03;\n cube.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 400} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#74b9ff');\n scene.fog = new THREE.Fog('#74b9ff', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 401} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 15, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.1,\n y: (Math.random() - 0.5) * 0.1,\n z: (Math.random() - 0.5) * 0.1\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#fdcb6e', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 402} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#e84393');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#ff6b6b', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#45b7d1',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 403} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#6c5ce7' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 404} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#e84393', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#e17055' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.03;\n torus.rotation.y += 0.03 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 405} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 406} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100%, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #00cec9;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 407} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 408} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 409} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 410} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 411} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 412} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 413} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 414} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #00cec9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 415} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 416} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#0984e3';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 417} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 418} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$60vw`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 419} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#0984e3';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 420} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 421} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 422} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#ffeaa7');\n// renderer.registerTile(1, '#dfe6e9');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 423} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 12,\n speed = 0.03,\n life = 1.0,\n colors = ['#45b7d1', '#fd79a8', '#6c5ce7'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#dfe6e9', '#00cec9', '#fab1a0'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 424} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#0984e3', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.015;\n cube.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 425} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#74b9ff');\n scene.fog = new THREE.Fog('#74b9ff', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 426} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 5, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.015,\n y: (Math.random() - 0.5) * 0.015,\n z: (Math.random() - 0.5) * 0.015\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#96ceb4', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 427} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#e84393');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#ff6b6b', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#fdcb6e',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 428} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#fab1a0' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 429} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#45b7d1');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#e17055', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#e84393' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.01;\n torus.rotation.y += 0.01 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 430} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 431} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #55efc4;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 432} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 433} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 434} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 435} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 436} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 437} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 438} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 439} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fd79a8; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 440} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 441} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#a29bfe';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 442} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 443} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$300px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 444} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#dfe6e9';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 445} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 446} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 447} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#4ecdc4');\n// renderer.registerTile(1, '#00cec9');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 448} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 10,\n speed = 0.01,\n life = 1.0,\n colors = ['#fab1a0', '#96ceb4', '#74b9ff'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#96ceb4', '#00cec9', '#6c5ce7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 449} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#55efc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#00b894', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.05;\n cube.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 450} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n scene.fog = new THREE.Fog('#0984e3', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 451} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 20, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.1,\n y: (Math.random() - 0.5) * 0.1,\n z: (Math.random() - 0.5) * 0.1\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#a29bfe', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 452} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#0984e3');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#ff6b6b', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 453} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e84393');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#4ecdc4' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 454} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#6c5ce7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#74b9ff', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00b894' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.005;\n torus.rotation.y += 0.005 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 455} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 456} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #6c5ce7;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 457} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 458} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 459} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 460} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 461} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 462} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 463} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 464} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #55efc4; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 465} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 466} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#e84393';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 467} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 468} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$200px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 469} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fd79a8';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 470} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 471} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 472} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fab1a0');\n// renderer.registerTile(1, '#45b7d1');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 473} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.02,\n life = 1.0,\n colors = ['#96ceb4', '#00cec9', '#fd79a8'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#a29bfe', '#fab1a0', '#6c5ce7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 474} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fab1a0', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.03;\n cube.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 475} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fd79a8');\n scene.fog = new THREE.Fog('#fd79a8', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 476} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 50, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.005,\n y: (Math.random() - 0.5) * 0.005,\n z: (Math.random() - 0.5) * 0.005\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#96ceb4', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 477} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#a29bfe');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#dfe6e9', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#0984e3',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 478} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e84393');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#96ceb4' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 479} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#55efc4', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#ffeaa7' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.03;\n torus.rotation.y += 0.03 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 480} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 481} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #6c5ce7;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 482} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 483} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 484} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 485} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 486} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 487} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 488} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 489} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fdcb6e; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 490} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 491} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#e84393';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 492} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 493} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$300px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 494} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#e17055';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 495} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 496} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 497} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#74b9ff');\n// renderer.registerTile(1, '#e84393');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 498} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 5,\n speed = 0.05,\n life = 1.0,\n colors = ['#0984e3', '#4ecdc4', '#fab1a0'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#a29bfe', '#fdcb6e', '#e17055'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 499} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00b894');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#45b7d1', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.015;\n cube.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 500} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n scene.fog = new THREE.Fog('#fab1a0', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 501} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 15, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.05,\n y: (Math.random() - 0.5) * 0.05,\n z: (Math.random() - 0.5) * 0.05\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#45b7d1', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 502} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#ff6b6b');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#e17055', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 503} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fd79a8');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#55efc4' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 504} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#e17055', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#6c5ce7' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.02;\n torus.rotation.y += 0.02 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 505} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 506} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #e17055;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 507} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 508} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 509} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 510} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 511} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 512} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 513} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 514} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #ff6b6b; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 515} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 516} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#55efc4';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 517} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 518} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$400px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 519} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fab1a0';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 520} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 521} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 522} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#00cec9');\n// renderer.registerTile(1, '#ffeaa7');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 523} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 10,\n speed = 0.005,\n life = 1.0,\n colors = ['#6c5ce7', '#45b7d1', '#00b894'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#fdcb6e', '#74b9ff', '#6c5ce7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 524} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#74b9ff');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#dfe6e9', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.03;\n cube.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 525} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n scene.fog = new THREE.Fog('#00cec9', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 526} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 50, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.03,\n y: (Math.random() - 0.5) * 0.03,\n z: (Math.random() - 0.5) * 0.03\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#dfe6e9', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 527} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#ffeaa7');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#fd79a8', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#ff6b6b',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 528} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#fd79a8' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 529} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#dfe6e9', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#ffeaa7' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.01;\n torus.rotation.y += 0.01 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 530} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 531} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(80vh, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #55efc4;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 532} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 533} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 534} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 535} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 536} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 537} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 538} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 539} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #6c5ce7; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 540} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 541} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#dfe6e9';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 542} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 543} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$250px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 544} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#74b9ff';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 545} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 546} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 547} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#96ceb4');\n// renderer.registerTile(1, '#00b894');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 548} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 12,\n speed = 0.01,\n life = 1.0,\n colors = ['#74b9ff', '#6c5ce7', '#4ecdc4'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#00b894', '#ffeaa7', '#e17055'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 549} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#ff6b6b', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.1;\n cube.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 550} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#dfe6e9');\n scene.fog = new THREE.Fog('#dfe6e9', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 551} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 10, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.1,\n y: (Math.random() - 0.5) * 0.1,\n z: (Math.random() - 0.5) * 0.1\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#96ceb4', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 552} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#55efc4');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#fab1a0', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 553} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#45b7d1');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#0984e3' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 554} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#96ceb4', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#fab1a0' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.005;\n torus.rotation.y += 0.005 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 555} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 556} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fdcb6e;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 557} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 558} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 559} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 560} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 561} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 562} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 563} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 564} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fdcb6e; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 565} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 566} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#a29bfe';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 567} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 568} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$100px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 569} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#74b9ff';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 570} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 571} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 572} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#ffeaa7');\n// renderer.registerTile(1, '#6c5ce7');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 573} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.02,\n life = 1.0,\n colors = ['#dfe6e9', '#fd79a8', '#55efc4'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#45b7d1', '#ffeaa7', '#ffeaa7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 574} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#00b894', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.1;\n cube.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 575} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n scene.fog = new THREE.Fog('#fab1a0', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 576} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 15, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.005,\n y: (Math.random() - 0.5) * 0.005,\n z: (Math.random() - 0.5) * 0.005\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#74b9ff', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 577} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#00b894');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#00b894', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#96ceb4',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 578} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#dfe6e9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#74b9ff' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 579} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#96ceb4', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#6c5ce7' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.05;\n torus.rotation.y += 0.05 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 580} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 581} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #dfe6e9;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 582} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 583} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 584} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 585} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 586} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 587} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 588} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 589} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fd79a8; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 590} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 591} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#e84393';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 592} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 593} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$300px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 594} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#6c5ce7';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 595} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 596} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 597} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#a29bfe');\n// renderer.registerTile(1, '#4ecdc4');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 598} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.1,\n life = 1.0,\n colors = ['#ffeaa7', '#fd79a8', '#e84393'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#ff6b6b', '#ff6b6b', '#dfe6e9'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 599} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00b894');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#00cec9', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.005;\n cube.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 600} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n scene.fog = new THREE.Fog('#e17055', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 601} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 3, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.05,\n y: (Math.random() - 0.5) * 0.05,\n z: (Math.random() - 0.5) * 0.05\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#00cec9', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 602} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#0984e3');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#0984e3', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 603} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00b894');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#74b9ff' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 604} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#96ceb4', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#45b7d1' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.005;\n torus.rotation.y += 0.005 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 605} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 606} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #45b7d1;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 607} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 608} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 609} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 610} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 611} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 612} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 613} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 614} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #ffeaa7; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 615} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 616} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00cec9';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 617} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 618} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$250px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 619} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#55efc4';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 620} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 621} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 622} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fdcb6e');\n// renderer.registerTile(1, '#e84393');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 623} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 15,\n speed = 0.005,\n life = 1.0,\n colors = ['#74b9ff', '#0984e3', '#6c5ce7'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#ff6b6b', '#a29bfe', '#00cec9'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 624} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#6c5ce7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#e17055', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.02;\n cube.rotation.y += 0.02;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 625} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n scene.fog = new THREE.Fog('#ffeaa7', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 626} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 12, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.1,\n y: (Math.random() - 0.5) * 0.1,\n z: (Math.random() - 0.5) * 0.1\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#a29bfe', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 627} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#e84393');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#4ecdc4', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#74b9ff',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 628} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ff6b6b');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#fab1a0' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 629} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#0984e3', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#e17055' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.015;\n torus.rotation.y += 0.015 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 630} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 631} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(50%, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #74b9ff;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 632} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 633} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 634} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 635} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 636} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 637} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 638} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 639} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #dfe6e9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 640} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 641} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#74b9ff';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 642} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 643} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$80vh`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 644} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#00cec9';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 645} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 646} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 647} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#dfe6e9');\n// renderer.registerTile(1, '#e17055');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 648} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 3,\n speed = 0.01,\n life = 1.0,\n colors = ['#0984e3', '#fdcb6e', '#4ecdc4'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#fd79a8', '#ffeaa7', '#45b7d1'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 649} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fd79a8');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#96ceb4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.1;\n cube.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 650} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n scene.fog = new THREE.Fog('#e17055', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 651} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 10, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.02,\n y: (Math.random() - 0.5) * 0.02,\n z: (Math.random() - 0.5) * 0.02\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#ffeaa7', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 652} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#ff6b6b');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#00cec9', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#fd79a8',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.02;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 653} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#55efc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#dfe6e9' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 654} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#a29bfe', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#fdcb6e' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.1;\n torus.rotation.y += 0.1 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 655} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 656} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100%, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #e17055;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 657} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 658} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 659} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 660} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 661} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 662} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 663} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 664} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fdcb6e; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 665} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 666} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#e84393';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 667} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 668} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$80vh`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 669} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#a29bfe';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 670} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 671} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 672} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#74b9ff');\n// renderer.registerTile(1, '#0984e3');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 673} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 12,\n speed = 0.01,\n life = 1.0,\n colors = ['#fab1a0', '#a29bfe', '#45b7d1'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#0984e3', '#45b7d1', '#e84393'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 674} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#74b9ff', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.1;\n cube.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 675} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n scene.fog = new THREE.Fog('#e17055', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 676} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 8, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.015,\n y: (Math.random() - 0.5) * 0.015,\n z: (Math.random() - 0.5) * 0.015\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#6c5ce7', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 677} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#00b894');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#e84393', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#fdcb6e',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 678} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#ffeaa7' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 679} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#dfe6e9', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00b894' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.1;\n torus.rotation.y += 0.1 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 680} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 681} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #00b894;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 682} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 683} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 684} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 685} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 686} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 687} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 688} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 689} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #6c5ce7; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 690} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 691} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#ff6b6b';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 692} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 693} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$80vh`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 694} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#55efc4';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 695} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 696} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 697} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fd79a8');\n// renderer.registerTile(1, '#fd79a8');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 698} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 12,\n speed = 0.01,\n life = 1.0,\n colors = ['#00b894', '#a29bfe', '#6c5ce7'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#e17055', '#fd79a8', '#fdcb6e'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 699} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#a29bfe');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#55efc4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.02;\n cube.rotation.y += 0.02;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 700} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n scene.fog = new THREE.Fog('#fdcb6e', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 701} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 20, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.05,\n y: (Math.random() - 0.5) * 0.05,\n z: (Math.random() - 0.5) * 0.05\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#ff6b6b', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 702} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#dfe6e9');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#00b894', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 703} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#00b894' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 704} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00b894');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#00b894', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00cec9' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.05;\n torus.rotation.y += 0.05 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 705} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 706} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #96ceb4;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 707} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 708} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 709} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 710} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 711} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 712} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 713} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 714} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #00cec9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 715} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 716} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00cec9';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 717} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 718} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$100%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 719} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#96ceb4';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 720} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 721} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 722} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fab1a0');\n// renderer.registerTile(1, '#e17055');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 723} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 10,\n speed = 0.015,\n life = 1.0,\n colors = ['#45b7d1', '#e17055', '#6c5ce7'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#fd79a8', '#0984e3', '#ffeaa7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 724} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#0984e3', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.02;\n cube.rotation.y += 0.02;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 725} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#6c5ce7');\n scene.fog = new THREE.Fog('#6c5ce7', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 726} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 50, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.1,\n y: (Math.random() - 0.5) * 0.1,\n z: (Math.random() - 0.5) * 0.1\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#0984e3', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 727} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#4ecdc4');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#00cec9', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#ff6b6b',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 728} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#0984e3' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 729} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#55efc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#6c5ce7', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#a29bfe' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.005;\n torus.rotation.y += 0.005 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 730} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 731} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fd79a8;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 732} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 733} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 734} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 735} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 736} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 737} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 738} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 739} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fdcb6e; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 740} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 741} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00cec9';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 742} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 743} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$250px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 744} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fd79a8';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 745} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 746} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 747} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#e17055');\n// renderer.registerTile(1, '#e17055');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 748} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 20,\n speed = 0.015,\n life = 1.0,\n colors = ['#45b7d1', '#e84393', '#4ecdc4'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#55efc4', '#6c5ce7', '#96ceb4'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 749} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#ffeaa7', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.05;\n cube.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 750} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00b894');\n scene.fog = new THREE.Fog('#00b894', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 751} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 10, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.01,\n y: (Math.random() - 0.5) * 0.01,\n z: (Math.random() - 0.5) * 0.01\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#6c5ce7', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 752} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#dfe6e9');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#e84393', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#55efc4',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 753} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#ffeaa7' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 754} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#fdcb6e', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#4ecdc4' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.02;\n torus.rotation.y += 0.02 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 755} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 756} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #ffeaa7;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 757} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 758} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 759} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 760} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 761} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 762} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 763} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 764} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fdcb6e; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 765} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 766} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#a29bfe';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 767} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 768} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$300px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 769} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fab1a0';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 770} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 771} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 772} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#ffeaa7');\n// renderer.registerTile(1, '#ff6b6b');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 773} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 20,\n speed = 0.015,\n life = 1.0,\n colors = ['#55efc4', '#fab1a0', '#dfe6e9'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#e84393', '#ff6b6b', '#6c5ce7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 774} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ff6b6b');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#96ceb4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.01;\n cube.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 775} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fd79a8');\n scene.fog = new THREE.Fog('#fd79a8', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 776} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 12, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.015,\n y: (Math.random() - 0.5) * 0.015,\n z: (Math.random() - 0.5) * 0.015\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#ff6b6b', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 777} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#e84393');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#fd79a8', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 778} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00cec9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#00b894' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 779} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#4ecdc4', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#74b9ff' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.01;\n torus.rotation.y += 0.01 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 780} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 781} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #45b7d1;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 782} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 783} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 784} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 785} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 786} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 787} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 788} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 789} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #4ecdc4; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 790} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 791} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#fdcb6e';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 792} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 793} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$50%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 794} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fab1a0';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 795} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 796} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 797} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#00b894');\n// renderer.registerTile(1, '#96ceb4');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 798} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 20,\n speed = 0.005,\n life = 1.0,\n colors = ['#45b7d1', '#96ceb4', '#ffeaa7'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#6c5ce7', '#a29bfe', '#55efc4'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 799} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ffeaa7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fd79a8', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.05;\n cube.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 800} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e84393');\n scene.fog = new THREE.Fog('#e84393', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 801} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 20, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.02,\n y: (Math.random() - 0.5) * 0.02,\n z: (Math.random() - 0.5) * 0.02\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#45b7d1', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 802} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#00cec9');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#6c5ce7', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.005;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 803} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#4ecdc4' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 804} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#fab1a0', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#dfe6e9' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.01;\n torus.rotation.y += 0.01 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 805} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 806} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100%, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fdcb6e;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 807} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 808} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 809} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 810} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 811} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 812} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 813} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 814} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #e84393; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 815} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 816} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#45b7d1';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 817} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 818} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$60vw`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 819} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#45b7d1';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 820} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 821} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 822} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#dfe6e9');\n// renderer.registerTile(1, '#fdcb6e');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 823} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 5,\n speed = 0.05,\n life = 1.0,\n colors = ['#fd79a8', '#0984e3', '#fdcb6e'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#4ecdc4', '#a29bfe', '#dfe6e9'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 824} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e84393');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#96ceb4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.015;\n cube.rotation.y += 0.015;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 825} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00b894');\n scene.fog = new THREE.Fog('#00b894', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 826} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 8, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.03,\n y: (Math.random() - 0.5) * 0.03,\n z: (Math.random() - 0.5) * 0.03\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#fab1a0', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 827} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#6c5ce7');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#45b7d1', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#45b7d1',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 828} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#dfe6e9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#dfe6e9' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 829} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#45b7d1');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#ff6b6b', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00b894' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.02;\n torus.rotation.y += 0.02 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 830} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 831} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #fd79a8;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 832} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 833} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 834} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 835} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 836} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 837} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 838} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 839} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #4ecdc4; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 840} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 841} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#74b9ff';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 842} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 843} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$250px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 844} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fd79a8';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 845} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 846} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 847} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#00b894');\n// renderer.registerTile(1, '#fab1a0');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 848} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 15,\n speed = 0.015,\n life = 1.0,\n colors = ['#0984e3', '#fab1a0', '#fdcb6e'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#0984e3', '#fd79a8', '#ffeaa7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 849} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#55efc4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.1;\n cube.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 850} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fd79a8');\n scene.fog = new THREE.Fog('#fd79a8', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 851} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 8, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.03,\n y: (Math.random() - 0.5) * 0.03,\n z: (Math.random() - 0.5) * 0.03\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#a29bfe', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 852} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#00b894');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#a29bfe', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 853} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#dfe6e9' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 854} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#55efc4', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#ffeaa7' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.03;\n torus.rotation.y += 0.03 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 855} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 856} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(50%, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #dfe6e9;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 857} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 858} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 859} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 860} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 861} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 862} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 863} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 864} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #ff6b6b; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 865} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 866} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#ffeaa7';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 867} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 868} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$100%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 869} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#45b7d1';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 870} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 871} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 872} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#fdcb6e');\n// renderer.registerTile(1, '#74b9ff');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 873} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.1,\n life = 1.0,\n colors = ['#ffeaa7', '#e17055', '#e84393'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#e84393', '#6c5ce7', '#74b9ff'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 874} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#74b9ff', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.05;\n cube.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 875} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fab1a0');\n scene.fog = new THREE.Fog('#fab1a0', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 876} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 20, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.05,\n y: (Math.random() - 0.5) * 0.05,\n z: (Math.random() - 0.5) * 0.05\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#e17055', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 877} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#fab1a0');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#45b7d1', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#00cec9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 878} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#4ecdc4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#e17055' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 879} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fd79a8');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#fd79a8', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#ff6b6b' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.03;\n torus.rotation.y += 0.03 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 880} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 881} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #a29bfe;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 882} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 883} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 884} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 885} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 886} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 887} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 888} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 889} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #e84393; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 890} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 891} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00b894';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 892} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 893} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$200px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 894} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#45b7d1';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 895} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 896} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 897} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#e84393');\n// renderer.registerTile(1, '#e84393');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 898} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 10,\n speed = 0.03,\n life = 1.0,\n colors = ['#fdcb6e', '#6c5ce7', '#dfe6e9'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#ffeaa7', '#fab1a0', '#00b894'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 899} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#6c5ce7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#55efc4', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.1;\n cube.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 900} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n scene.fog = new THREE.Fog('#fdcb6e', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 901} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 8, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.03,\n y: (Math.random() - 0.5) * 0.03,\n z: (Math.random() - 0.5) * 0.03\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#e17055', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 902} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#fab1a0');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#ff6b6b', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#fd79a8',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 903} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#6c5ce7');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#dfe6e9' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 904} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#0984e3', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#fab1a0' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.05;\n torus.rotation.y += 0.05 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 905} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 906} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #6c5ce7;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 907} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 908} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 909} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 910} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 911} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 912} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 913} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 914} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #ff6b6b; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 915} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 916} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00cec9';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 917} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 918} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$100px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 919} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#00b894';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 920} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 921} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 922} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#55efc4');\n// renderer.registerTile(1, '#55efc4');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 923} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.02,\n life = 1.0,\n colors = ['#96ceb4', '#45b7d1', '#74b9ff'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#96ceb4', '#ffeaa7', '#96ceb4'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 924} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#0984e3', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.01;\n cube.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 925} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e84393');\n scene.fog = new THREE.Fog('#e84393', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 926} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 10, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.015,\n y: (Math.random() - 0.5) * 0.015,\n z: (Math.random() - 0.5) * 0.015\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#00b894', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 927} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#dfe6e9');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#6c5ce7', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#00cec9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.1;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 928} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#dfe6e9');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#fd79a8' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 929} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#00b894');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#e84393', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#96ceb4' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.005;\n torus.rotation.y += 0.005 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 930} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 931} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #55efc4;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 932} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 933} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 934} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 935} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 936} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 937} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 938} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 939} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #fd79a8; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 940} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 941} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#00cec9';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 942} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 943} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$200px`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 944} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#fdcb6e';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 945} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 946} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 947} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#74b9ff');\n// renderer.registerTile(1, '#ffeaa7');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 948} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.005,\n life = 1.0,\n colors = ['#e84393', '#a29bfe', '#fab1a0'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#ffeaa7', '#a29bfe', '#fab1a0'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 949} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#45b7d1');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fdcb6e', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.03;\n cube.rotation.y += 0.03;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 950} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fd79a8');\n scene.fog = new THREE.Fog('#fd79a8', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 951} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 10, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.02,\n y: (Math.random() - 0.5) * 0.02,\n z: (Math.random() - 0.5) * 0.02\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#6c5ce7', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 952} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#ffeaa7');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#fab1a0', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#ff6b6b',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 953} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#ff6b6b');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#ffeaa7' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 954} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#ffeaa7', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#00cec9' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.1;\n torus.rotation.y += 0.1 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 955} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 956} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100%, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #6c5ce7;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 957} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 958} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 959} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 960} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 961} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 962} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 963} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 964} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #4ecdc4; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 965} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 966} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#e17055';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 967} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 968} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$80vh`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 969} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#00b894';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 970} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 971} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 972} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#96ceb4');\n// renderer.registerTile(1, '#e17055');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 973} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 50,\n speed = 0.015,\n life = 1.0,\n colors = ['#96ceb4', '#45b7d1', '#dfe6e9'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#45b7d1', '#55efc4', '#6c5ce7'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 974} +{"problem": "Create a Three.js scene with a rotating colored cube", "solution": "import * as THREE from 'three';\n\nfunction createCubeScene(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found: ' + containerId);\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#96ceb4');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BoxGeometry(1, 1, 1);\n const material = new THREE.MeshStandardMaterial({ color: '#fab1a0', roughness: 0.3, metalness: 0.1 });\n const cube = new THREE.Mesh(geometry, material);\n scene.add(cube);\n\n const light = new THREE.DirectionalLight(0xffffff, 1);\n light.position.set(5, 5, 5);\n scene.add(light);\n scene.add(new THREE.AmbientLight(0x404040));\n\n function animate() {\n requestAnimationFrame(animate);\n cube.rotation.x += 0.01;\n cube.rotation.y += 0.01;\n renderer.render(scene, camera);\n }\n animate();\n\n window.addEventListener('resize', () => {\n camera.aspect = container.clientWidth / container.clientHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(container.clientWidth, container.clientHeight);\n });\n\n return { scene, camera, renderer, cube };\n}\n\n// Usage: createCubeScene();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 975} +{"problem": "Load a GLTF 3D model in Three.js with orbit controls", "solution": "import * as THREE from 'three';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\n\nasync function loadModel(url, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#0984e3');\n scene.fog = new THREE.Fog('#0984e3', 10, 50);\n\n const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100);\n camera.position.set(0, 2, 5);\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.shadowMap.enabled = true;\n container.appendChild(renderer.domElement);\n\n const controls = new OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n\n scene.add(new THREE.AmbientLight(0xffffff, 0.5));\n const dirLight = new THREE.DirectionalLight(0xffffff, 1);\n dirLight.position.set(5, 10, 7);\n dirLight.castShadow = true;\n scene.add(dirLight);\n\n const loader = new GLTFLoader();\n try {\n const gltf = await loader.loadAsync(url);\n const model = gltf.scene;\n model.traverse(child => { if (child.isMesh) child.castShadow = true; });\n scene.add(model);\n } catch (err) {\n console.error('Failed to load model:', err);\n throw err;\n }\n\n function animate() {\n requestAnimationFrame(animate);\n controls.update();\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, controls };\n}\n\n// Usage: loadModel('/models/character.glb');", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 976} +{"problem": "Create a particle system in Three.js with random motion", "solution": "import * as THREE from 'three';\n\nfunction createParticles(count = 3, containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 30;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(count * 3);\n const velocities = [];\n\n for (let i = 0; i < count; i++) {\n positions[i * 3] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 1] = (Math.random() - 0.5) * 50;\n positions[i * 3 + 2] = (Math.random() - 0.5) * 50;\n velocities.push({\n x: (Math.random() - 0.5) * 0.02,\n y: (Math.random() - 0.5) * 0.02,\n z: (Math.random() - 0.5) * 0.02\n });\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n const material = new THREE.PointsMaterial({ color: '#fab1a0', size: 0.5, transparent: true, opacity: 0.8 });\n const particles = new THREE.Points(geometry, material);\n scene.add(particles);\n\n function animate() {\n requestAnimationFrame(animate);\n const pos = geometry.attributes.position.array;\n for (let i = 0; i < count; i++) {\n pos[i * 3] += velocities[i].x;\n pos[i * 3 + 1] += velocities[i].y;\n pos[i * 3 + 2] += velocities[i].z;\n if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1;\n if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1;\n if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1;\n }\n geometry.attributes.position.needsUpdate = true;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, particles, renderer };\n}\n\n// Usage: createParticles(200);", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 977} +{"problem": "Create a reflective sphere with environment mapping in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createReflectiveSphere(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 3;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n renderer.toneMapping = THREE.ACESFilmicToneMapping;\n container.appendChild(renderer.domElement);\n\n const pmremGenerator = new THREE.PMREMGenerator(renderer);\n const envScene = new THREE.Scene();\n envScene.background = new THREE.Color('#00b894');\n envScene.add(new THREE.Mesh(\n new THREE.SphereGeometry(10, 32, 32),\n new THREE.MeshBasicMaterial({ color: '#00b894', side: THREE.BackSide })\n ));\n const envMap = pmremGenerator.fromScene(envScene).texture;\n\n const geometry = new THREE.SphereGeometry(1, 64, 64);\n const material = new THREE.MeshPhysicalMaterial({\n color: '#dfe6e9',\n metalness: 1.0,\n roughness: 0.1,\n envMap,\n envMapIntensity: 1.0\n });\n const sphere = new THREE.Mesh(geometry, material);\n scene.add(sphere);\n\n function animate() {\n requestAnimationFrame(animate);\n sphere.rotation.y += 0.05;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, sphere, renderer };\n}\n\n// Usage: createReflectiveSphere();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 978} +{"problem": "Build a Three.js first-person camera controller with WASD movement", "solution": "import * as THREE from 'three';\n\nfunction createFPSController(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#fdcb6e');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.y = 1.7;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n // Floor\n const floor = new THREE.Mesh(\n new THREE.PlaneGeometry(50, 50),\n new THREE.MeshStandardMaterial({ color: '#00cec9' })\n );\n floor.rotation.x = -Math.PI / 2;\n floor.receiveShadow = true;\n scene.add(floor);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);\n dirLight.position.set(5, 10, 5);\n scene.add(dirLight);\n\n const keys = { w: false, a: false, s: false, d: false };\n const velocity = new THREE.Vector3();\n const direction = new THREE.Vector3();\n\n document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; });\n document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; });\n\n container.addEventListener('click', () => container.requestPointerLock());\n document.addEventListener('mousemove', (e) => {\n if (document.pointerLockElement === container) {\n camera.rotation.y -= e.movementX * 0.002;\n camera.rotation.x -= e.movementY * 0.002;\n camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));\n }\n });\n\n const clock = new THREE.Clock();\n function animate() {\n requestAnimationFrame(animate);\n const delta = clock.getDelta();\n velocity.x -= velocity.x * 10 * delta;\n velocity.z -= velocity.z * 10 * delta;\n direction.z = Number(keys.w) - Number(keys.s);\n direction.x = Number(keys.a) - Number(keys.d);\n direction.normalize();\n if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta;\n if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta;\n camera.translateX(-velocity.x * delta);\n camera.translateZ(-velocity.z * delta);\n camera.position.y = 1.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, camera, renderer };\n}\n\n// Usage: createFPSController();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 979} +{"problem": "Create an animated torus knot with wireframe overlay in Three.js", "solution": "import * as THREE from 'three';\n\nfunction createTorusKnot(containerId = 'canvas-container') {\n const container = document.getElementById(containerId);\n if (!container) throw new Error('Container not found');\n\n const scene = new THREE.Scene();\n scene.background = new THREE.Color('#e17055');\n\n const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);\n camera.position.z = 5;\n\n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(container.clientWidth, container.clientHeight);\n container.appendChild(renderer.domElement);\n\n const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);\n const material = new THREE.MeshStandardMaterial({ color: '#dfe6e9', roughness: 0.4, metalness: 0.3 });\n const torus = new THREE.Mesh(geometry, material);\n scene.add(torus);\n\n const wireGeo = new THREE.WireframeGeometry(geometry);\n const wireMat = new THREE.LineBasicMaterial({ color: '#fd79a8' });\n const wireframe = new THREE.LineSegments(wireGeo, wireMat);\n torus.add(wireframe);\n\n scene.add(new THREE.AmbientLight(0x404040));\n const pointLight = new THREE.PointLight(0xffffff, 1, 100);\n pointLight.position.set(2, 3, 4);\n scene.add(pointLight);\n\n function animate() {\n requestAnimationFrame(animate);\n torus.rotation.x += 0.1;\n torus.rotation.y += 0.1 * 0.7;\n renderer.render(scene, camera);\n }\n animate();\n\n return { scene, torus, renderer };\n}\n\n// Usage: createTorusKnot();", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 980} +{"problem": "Raycast from mouse to detect 3D object clicks in Three.js", "solution": "import * as THREE from 'three';\n\nfunction setupRaycasting(scene, camera, renderer, onIntersect) {\n const raycaster = new THREE.Raycaster();\n const mouse = new THREE.Vector2();\n\n renderer.domElement.addEventListener('click', (event) => {\n const rect = renderer.domElement.getBoundingClientRect();\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;\n\n raycaster.setFromCamera(mouse, camera);\n const intersects = raycaster.intersectObjects(scene.children, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0];\n console.log('Clicked:', hit.object.name || hit.object.uuid);\n if (typeof onIntersect === 'function') onIntersect(hit);\n }\n });\n}\n\n// Usage example:\n// const mesh = new THREE.Mesh(geometry, material);\n// mesh.name = 'clickable-box';\n// scene.add(mesh);\n// setupRaycasting(scene, camera, renderer, (hit) => {\n// hit.object.material.color.setHex(Math.random() * 0xffffff);\n// });", "domain": "threejs", "language": "javascript", "tags": ["frontend", "threejs", "webgl"], "variant": 981} +{"problem": "Build a responsive CSS grid layout with auto-fit columns", "solution": "/* Responsive grid layout */\n.grid-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(60vw, 1fr));\n gap: 1.5rem;\n padding: 2rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.grid-item {\n background: #ffeaa7;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.grid-item:hover {\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.15);\n}\n\n@media (max-width: 600px) {\n .grid-container {\n grid-template-columns: 1fr;\n padding: 1rem;\n }\n}", "domain": "html-css-js", "language": "css", "tags": ["frontend", "css", "dom"], "variant": 982} +{"problem": "Create a sticky navigation bar that changes style on scroll", "solution": "/* Sticky nav styles */\n.nav-bar {\n position: sticky;\n top: 0;\n z-index: 1000;\n background: transparent;\n padding: 1rem 2rem;\n transition: background 0.3s ease, box-shadow 0.3s ease;\n}\n\n.nav-bar.scrolled {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n/* JavaScript */\nfunction initStickyNav(navSelector = '.nav-bar') {\n const nav = document.querySelector(navSelector);\n if (!nav) throw new Error('Nav element not found');\n\n function onScroll() {\n if (window.scrollY > 50) {\n nav.classList.add('scrolled');\n } else {\n nav.classList.remove('scrolled');\n }\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n onScroll(); // Initialize state\n return nav;\n}\n\n// Usage: initStickyNav();", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 983} +{"problem": "Implement debounced search input with fetch API", "solution": "async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) {\n const input = document.querySelector(inputSelector);\n if (!input) throw new Error('Input element not found');\n\n let timeoutId = null;\n let controller = null;\n\n input.addEventListener('input', (e) => {\n const query = e.target.value.trim();\n clearTimeout(timeoutId);\n if (controller) controller.abort();\n\n if (!query) {\n renderFn([]);\n return;\n }\n\n timeoutId = setTimeout(async () => {\n controller = new AbortController();\n try {\n const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, {\n signal: controller.signal\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json();\n renderFn(data);\n } catch (err) {\n if (err.name !== 'AbortError') {\n console.error('Search failed:', err);\n renderFn([], err);\n }\n }\n }, delay);\n });\n}\n\n// Usage:\n// debouncedSearch('#search', '/api/search', (results, err) => {\n// if (err) return showError(err);\n// updateDOM(results);\n// });", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 984} +{"problem": "Create a CSS-only modal with backdrop blur and focus trap", "solution": "/* Modal styles */\n.modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.modal-overlay.active {\n opacity: 1;\n visibility: visible;\n}\n\n.modal-content {\n background: white;\n border-radius: 16px;\n padding: 2rem;\n max-width: 500px;\n width: 90%;\n transform: scale(0.9);\n transition: transform 0.3s ease;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n}\n\n.modal-overlay.active .modal-content {\n transform: scale(1);\n}\n\n/* JavaScript for focus trap and keyboard */\nfunction initModal(triggerSelector, modalSelector) {\n const trigger = document.querySelector(triggerSelector);\n const modal = document.querySelector(modalSelector);\n if (!trigger || !modal) throw new Error('Modal elements not found');\n\n const content = modal.querySelector('.modal-content');\n const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])');\n\n function open() {\n modal.classList.add('active');\n (focusables[0] || content).focus();\n document.addEventListener('keydown', onKey);\n }\n\n function close() {\n modal.classList.remove('active');\n document.removeEventListener('keydown', onKey);\n trigger.focus();\n }\n\n function onKey(e) {\n if (e.key === 'Escape') close();\n if (e.key === 'Tab' && focusables.length > 0) {\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n trigger.addEventListener('click', open);\n modal.addEventListener('click', (e) => { if (e.target === modal) close(); });\n\n return { open, close };\n}\n\n// Usage: initModal('#open-modal', '#my-modal');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 985} +{"problem": "Build a custom dropdown select with keyboard navigation", "solution": "function createCustomSelect(selectElement) {\n if (!(selectElement instanceof HTMLSelectElement)) {\n throw new TypeError('Expected HTMLSelectElement');\n }\n\n const wrapper = document.createElement('div');\n wrapper.className = 'custom-select';\n wrapper.style.position = 'relative';\n wrapper.style.width = selectElement.offsetWidth + 'px';\n\n const trigger = document.createElement('button');\n trigger.type = 'button';\n trigger.className = 'select-trigger';\n trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...';\n trigger.setAttribute('aria-haspopup', 'listbox');\n\n const list = document.createElement('ul');\n list.className = 'select-options';\n list.setAttribute('role', 'listbox');\n list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;';\n\n Array.from(selectElement.options).forEach((opt, i) => {\n const li = document.createElement('li');\n li.textContent = opt.text;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(opt.selected));\n li.dataset.value = opt.value;\n li.style.padding = '0.5rem 1rem';\n li.style.cursor = 'pointer';\n li.addEventListener('click', () => {\n selectElement.value = opt.value;\n trigger.textContent = opt.text;\n close();\n selectElement.dispatchEvent(new Event('change'));\n });\n list.appendChild(li);\n });\n\n wrapper.appendChild(trigger);\n wrapper.appendChild(list);\n selectElement.style.display = 'none';\n selectElement.parentNode.insertBefore(wrapper, selectElement);\n\n let activeIndex = -1;\n function open() {\n list.style.display = 'block';\n trigger.setAttribute('aria-expanded', 'true');\n activeIndex = Array.from(selectElement.options).findIndex(o => o.selected);\n }\n function close() {\n list.style.display = 'none';\n trigger.setAttribute('aria-expanded', 'false');\n }\n\n trigger.addEventListener('click', () => {\n list.style.display === 'block' ? close() : open();\n });\n\n document.addEventListener('click', (e) => {\n if (!wrapper.contains(e.target)) close();\n });\n\n trigger.addEventListener('keydown', (e) => {\n const items = list.querySelectorAll('li');\n if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); }\n if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); }\n if (e.key === 'Escape') close();\n });\n\n return wrapper;\n}\n\n// Usage: createCustomSelect(document.getElementById('my-select'));", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 986} +{"problem": "Implement smooth scroll-to-section with intersection observer highlighting", "solution": "function initScrollSpy(navSelector, sectionSelector, options = {}) {\n const navLinks = document.querySelectorAll(`${navSelector} a[href^=\"#\"]`);\n const sections = document.querySelectorAll(sectionSelector);\n if (!navLinks.length || !sections.length) {\n console.warn('Scroll spy: no nav links or sections found');\n return;\n }\n\n const offset = options.offset || 80;\n\n // Smooth scroll on click\n navLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n const targetId = link.getAttribute('href').slice(1);\n const target = document.getElementById(targetId);\n if (target) {\n window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' });\n }\n });\n });\n\n // Intersection observer for active state\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n navLinks.forEach(l => l.classList.remove('active'));\n const active = document.querySelector(`${navSelector} a[href=\"#${entry.target.id}\"]`);\n if (active) active.classList.add('active');\n }\n });\n }, { rootMargin: `-${offset}px 0px -60% 0px` });\n\n sections.forEach(section => observer.observe(section));\n return observer;\n}\n\n// Usage: initScrollSpy('.side-nav', 'section[data-section]');", "domain": "html-css-js", "language": "javascript", "tags": ["frontend", "css", "dom"], "variant": 987} +{"problem": "Create a draggable range slider with real-time value display", "solution": "function createRangeSlider(container, options = {}) {\n const { min = 0, max = 100, step = 1, value = 50, onChange } = options;\n container = typeof container === 'string' ? document.querySelector(container) : container;\n if (!container) throw new Error('Slider container not found');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'range-slider';\n wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = min;\n input.max = max;\n input.step = step;\n input.value = value;\n input.style.flex = '1';\n\n const valueDisplay = document.createElement('span');\n valueDisplay.className = 'slider-value';\n valueDisplay.textContent = value;\n valueDisplay.style.minWidth = '3ch';\n valueDisplay.style.textAlign = 'right';\n valueDisplay.style.fontVariantNumeric = 'tabular-nums';\n\n input.addEventListener('input', (e) => {\n valueDisplay.textContent = e.target.value;\n if (typeof onChange === 'function') onChange(Number(e.target.value));\n });\n\n wrapper.appendChild(input);\n wrapper.appendChild(valueDisplay);\n container.appendChild(wrapper);\n\n return { input, valueDisplay, getValue: () => Number(input.value) };\n}\n\n// Usage:\n// createRangeSlider('#slider-box', {\n// min: 0, max: 255, value: 128,\n// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; }\n// });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 988} +{"problem": "Build a color picker canvas with eyedropper and palette export", "solution": "function createColorPicker(canvasId, exportBtnId) {\n const canvas = document.getElementById(canvasId);\n const exportBtn = document.getElementById(exportBtnId);\n if (!canvas || !exportBtn) throw new Error('Color picker elements not found');\n\n const ctx = canvas.getContext('2d', { willReadFrequently: true });\n let isDragging = false;\n const palette = new Set();\n\n // Draw a hue-saturation gradient\n function drawGradient() {\n const w = canvas.width;\n const h = canvas.height;\n for (let x = 0; x < w; x++) {\n const hue = (x / w) * 360;\n const grad = ctx.createLinearGradient(0, 0, 0, h);\n grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`);\n grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`);\n ctx.fillStyle = grad;\n ctx.fillRect(x, 0, 1, h);\n }\n }\n drawGradient();\n\n function pickColor(x, y) {\n const pixel = ctx.getImageData(x, y, 1, 1).data;\n const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join('');\n return hex;\n }\n\n function handleMove(e) {\n const rect = canvas.getBoundingClientRect();\n const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1);\n const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1);\n const color = pickColor(x, y);\n canvas.style.cursor = 'crosshair';\n if (isDragging) {\n palette.add(color);\n canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } }));\n }\n return color;\n }\n\n canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); });\n canvas.addEventListener('mousemove', handleMove);\n canvas.addEventListener('mouseup', () => { isDragging = false; });\n canvas.addEventListener('mouseleave', () => { isDragging = false; });\n\n exportBtn.addEventListener('click', () => {\n const colors = Array.from(palette);\n const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'palette.json';\n a.click();\n URL.revokeObjectURL(url);\n });\n\n return { canvas, palette, pickColor };\n}\n\n// Usage: createColorPicker('picker-canvas', 'export-btn');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 989} +{"problem": "Create a live code preview playground with iframe sandbox", "solution": "function createCodePlayground(containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Playground container not found');\n\n container.innerHTML = `\n
\n
\n \n \n \n \n
\n \n \n
\n `;\n\n const editor = container.querySelector('.editor');\n const preview = container.querySelector('.preview');\n const files = { html: '

Hello World

', css: 'h1 { color: #00cec9; }', js: 'console.log(\"ready\");' };\n let currentLang = 'html';\n\n editor.value = files.html;\n\n container.querySelectorAll('button[data-lang]').forEach(btn => {\n btn.addEventListener('click', () => {\n files[currentLang] = editor.value;\n currentLang = btn.dataset.lang;\n editor.value = files[currentLang];\n });\n });\n\n container.querySelector('button[data-action=\"run\"]').addEventListener('click', () => {\n files[currentLang] = editor.value;\n const doc = `\n \n \n \n ${files.html}\n \n `;\n preview.srcdoc = doc;\n });\n\n return { editor, preview, getFiles: () => ({ ...files }) };\n}\n\n// Usage: createCodePlayground('#playground');", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 990} +{"problem": "Build a resizable split-pane layout with drag handle", "solution": "function createSplitPane(containerSelector, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Split pane container not found');\n\n const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options;\n const isHorizontal = direction === 'horizontal';\n\n container.style.display = 'flex';\n container.style.flexDirection = isHorizontal ? 'row' : 'column';\n container.style.height = '100%';\n container.style.overflow = 'hidden';\n\n const pane1 = document.createElement('div');\n pane1.className = 'pane pane-1';\n pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`;\n pane1.style.overflow = 'auto';\n pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n const handle = document.createElement('div');\n handle.className = 'split-handle';\n handle.style.flex = '0 0 8px';\n handle.style.background = '#e0e0e0';\n handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n handle.style.userSelect = 'none';\n\n const pane2 = document.createElement('div');\n pane2.className = 'pane pane-2';\n pane2.style.flex = '1 1 auto';\n pane2.style.overflow = 'auto';\n pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto';\n pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto';\n\n container.appendChild(pane1);\n container.appendChild(handle);\n container.appendChild(pane2);\n\n let isDragging = false;\n const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n handle.addEventListener('mousedown', (e) => {\n isDragging = true;\n document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n });\n\n document.addEventListener('mousemove', (e) => {\n if (!isDragging) return;\n const rect = container.getBoundingClientRect();\n const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top;\n const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp];\n pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`;\n });\n\n document.addEventListener('mouseup', () => {\n isDragging = false;\n document.body.style.cursor = '';\n });\n\n return { pane1, pane2, handle };\n}\n\n// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });", "domain": "playground", "language": "javascript", "tags": ["frontend", "ui", "interactive"], "variant": 991} +{"problem": "Implement a masonry image grid with lazy loading and lightbox", "solution": "function createMasonryGallery(containerSelector, imageUrls) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Gallery container not found');\n\n container.style.columnCount = '3';\n container.style.columnGap = '1rem';\n\n if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array');\n\n // Lightbox overlay\n const lightbox = document.createElement('div');\n lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;';\n const img = document.createElement('img');\n img.style.maxWidth = '90vw';\n img.style.maxHeight = '90vh';\n img.style.objectFit = 'contain';\n lightbox.appendChild(img);\n lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; });\n document.body.appendChild(lightbox);\n\n imageUrls.forEach((src, i) => {\n const wrapper = document.createElement('div');\n wrapper.style.breakInside = 'avoid';\n wrapper.style.marginBottom = '1rem';\n\n const image = document.createElement('img');\n image.dataset.src = src;\n image.alt = `Gallery image ${i + 1}`;\n image.style.width = '100%';\n image.style.borderRadius = '8px';\n image.style.display = 'block';\n image.style.background = '#a29bfe';\n image.style.minHeight = '150px';\n\n image.addEventListener('click', () => {\n img.src = src;\n lightbox.style.display = 'flex';\n });\n\n wrapper.appendChild(image);\n container.appendChild(wrapper);\n });\n\n // Lazy loading\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && entry.target.dataset.src) {\n entry.target.src = entry.target.dataset.src;\n delete entry.target.dataset.src;\n observer.unobserve(entry.target);\n }\n });\n }, { rootMargin: '200px' });\n\n container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));\n return { container, lightbox, observer };\n}\n\n// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 992} +{"problem": "Create an image carousel with touch swipe and keyboard controls", "solution": "function createCarousel(containerSelector, slides) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Carousel container not found');\n if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required');\n\n let current = 0;\n\n container.innerHTML = `\n
\n
\n \n \n
\n
\n `;\n\n const track = container.querySelector('.track');\n const indicators = container.querySelector('.indicators');\n\n slides.forEach((slide, i) => {\n const div = document.createElement('div');\n div.style.minWidth = '100%';\n div.innerHTML = slide;\n track.appendChild(div);\n\n const dot = document.createElement('button');\n dot.style.width = '10px';\n dot.style.height = '10px';\n dot.style.borderRadius = '50%';\n dot.style.border = 'none';\n dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)';\n dot.addEventListener('click', () => goTo(i));\n indicators.appendChild(dot);\n });\n\n function goTo(index) {\n current = ((index % slides.length) + slides.length) % slides.length;\n track.style.transform = `translateX(-${current * 100}%)`;\n Array.from(indicators.children).forEach((dot, i) => {\n dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)';\n });\n }\n\n container.querySelector('.prev').addEventListener('click', () => goTo(current - 1));\n container.querySelector('.next').addEventListener('click', () => goTo(current + 1));\n\n // Touch swipe\n let startX = 0;\n container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; });\n container.addEventListener('touchend', (e) => {\n const diff = startX - e.changedTouches[0].clientX;\n if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1));\n });\n\n // Keyboard\n container.setAttribute('tabindex', '0');\n container.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowLeft') goTo(current - 1);\n if (e.key === 'ArrowRight') goTo(current + 1);\n });\n\n return { goTo, getCurrent: () => current };\n}\n\n// Usage: createCarousel('#carousel', ['', '']);", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 993} +{"problem": "Build an infinite scroll image feed with skeleton placeholders", "solution": "function createInfiniteFeed(containerSelector, fetchPage, options = {}) {\n const container = document.querySelector(containerSelector);\n if (!container) throw new Error('Feed container not found');\n if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function');\n\n const { pageSize = 20, threshold = 300 } = options;\n let page = 1;\n let isLoading = false;\n let hasMore = true;\n\n function createSkeletons(count) {\n const frag = document.createDocumentFragment();\n for (let i = 0; i < count; i++) {\n const div = document.createElement('div');\n div.className = 'skeleton';\n div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;';\n frag.appendChild(div);\n }\n return frag;\n }\n\n // Add shimmer keyframes if not present\n if (!document.getElementById('skeleton-styles')) {\n const style = document.createElement('style');\n style.id = 'skeleton-styles';\n style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }';\n document.head.appendChild(style);\n }\n\n async function loadMore() {\n if (isLoading || !hasMore) return;\n isLoading = true;\n const skeletons = createSkeletons(pageSize);\n container.appendChild(skeletons);\n\n try {\n const items = await fetchPage(page, pageSize);\n skeletons.remove();\n if (!items || items.length === 0) {\n hasMore = false;\n return;\n }\n items.forEach(item => container.appendChild(item));\n page++;\n } catch (err) {\n console.error('Feed load error:', err);\n skeletons.remove();\n } finally {\n isLoading = false;\n }\n }\n\n const sentinel = document.createElement('div');\n sentinel.style.height = '1px';\n container.appendChild(sentinel);\n\n const observer = new IntersectionObserver((entries) => {\n if (entries[0].isIntersecting) loadMore();\n }, { rootMargin: `${threshold}px` });\n observer.observe(sentinel);\n\n loadMore();\n return { loadMore, observer };\n}\n\n// Usage:\n// createInfiniteFeed('#feed', async (page, size) => {\n// const res = await fetch(`/api/images?page=${page}&size=$50%`);\n// const data = await res.json();\n// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; });\n// });", "domain": "gallery", "language": "javascript", "tags": ["frontend", "images", "performance"], "variant": 994} +{"problem": "Create a 2D canvas game loop with delta-time physics", "solution": "class GameEngine {\n constructor(canvasId, options = {}) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found: ' + canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.entities = [];\n this.lastTime = 0;\n this.running = false;\n this.fps = 60;\n\n this.canvas.width = options.width || 800;\n this.canvas.height = options.height || 600;\n this.canvas.style.background = options.bg || '#ffeaa7';\n }\n\n addEntity(entity) {\n if (!entity.update || !entity.draw) {\n throw new TypeError('Entity must have update(dt) and draw(ctx) methods');\n }\n this.entities.push(entity);\n return this;\n }\n\n start() {\n this.running = true;\n requestAnimationFrame((t) => this.loop(t));\n }\n\n stop() {\n this.running = false;\n }\n\n loop(timestamp) {\n if (!this.running) return;\n const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta\n this.lastTime = timestamp;\n\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n for (const entity of this.entities) {\n entity.update(dt, this.canvas.width, this.canvas.height);\n entity.draw(this.ctx);\n }\n\n requestAnimationFrame((t) => this.loop(t));\n }\n}\n\n// Usage:\n// const engine = new GameEngine('game-canvas', { width: 800, height: 600 });\n// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 });\n// engine.start();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 995} +{"problem": "Implement AABB collision detection for rectangular game entities", "solution": "function checkAABBCollision(a, b) {\n if (!a || !b) throw new Error('Both entities required for collision check');\n return (\n a.x < b.x + b.width &&\n a.x + a.width > b.x &&\n a.y < b.y + b.height &&\n a.y + a.height > b.y\n );\n}\n\nfunction resolveAABBOverlap(a, b) {\n const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n\n if (overlapX < overlapY) {\n const dir = a.x < b.x ? -1 : 1;\n a.x += (overlapX / 2) * dir;\n b.x -= (overlapX / 2) * dir;\n } else {\n const dir = a.y < b.y ? -1 : 1;\n a.y += (overlapY / 2) * dir;\n b.y -= (overlapY / 2) * dir;\n }\n}\n\nclass PhysicsWorld {\n constructor() {\n this.bodies = [];\n }\n\n add(body) {\n if (typeof body.x !== 'number' || typeof body.y !== 'number') {\n throw new TypeError('Body must have numeric x and y properties');\n }\n this.bodies.push(body);\n }\n\n step() {\n for (let i = 0; i < this.bodies.length; i++) {\n for (let j = i + 1; j < this.bodies.length; j++) {\n if (checkAABBCollision(this.bodies[i], this.bodies[j])) {\n resolveAABBOverlap(this.bodies[i], this.bodies[j]);\n if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]);\n if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]);\n }\n }\n }\n }\n}\n\n// Usage:\n// const world = new PhysicsWorld();\n// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } });\n// world.step();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 996} +{"problem": "Build a sprite animation system with frame clipping and playback controls", "solution": "class SpriteAnimator {\n constructor(image, frameWidth, frameHeight, frameCount) {\n if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement');\n this.image = image;\n this.frameWidth = frameWidth;\n this.frameHeight = frameHeight;\n this.frameCount = frameCount;\n this.currentFrame = 0;\n this.elapsed = 0;\n this.fps = 10;\n this.playing = true;\n this.loop = true;\n }\n\n update(dt) {\n if (!this.playing) return;\n this.elapsed += dt;\n const frameDuration = 1 / this.fps;\n if (this.elapsed >= frameDuration) {\n this.elapsed -= frameDuration;\n this.currentFrame++;\n if (this.currentFrame >= this.frameCount) {\n if (this.loop) this.currentFrame = 0;\n else { this.currentFrame = this.frameCount - 1; this.playing = false; }\n }\n }\n }\n\n draw(ctx, x, y, options = {}) {\n const sx = (this.currentFrame * this.frameWidth) % this.image.width;\n const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight;\n const scale = options.scale || 1;\n ctx.drawImage(\n this.image,\n sx, sy, this.frameWidth, this.frameHeight,\n x, y, this.frameWidth * scale, this.frameHeight * scale\n );\n }\n\n play() { this.playing = true; }\n pause() { this.playing = false; }\n reset() { this.currentFrame = 0; this.elapsed = 0; }\n setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); }\n}\n\n// Usage:\n// const img = new Image();\n// img.src = '/sprites/player.png';\n// img.onload = () => {\n// const anim = new SpriteAnimator(img, 32, 32, 8);\n// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100);\n// };", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 997} +{"problem": "Implement a tilemap renderer with camera scrolling and culling", "solution": "class TilemapRenderer {\n constructor(canvasId, tileSize = 32) {\n this.canvas = document.getElementById(canvasId);\n if (!this.canvas) throw new Error('Canvas not found');\n this.ctx = this.canvas.getContext('2d');\n this.tileSize = tileSize;\n this.camera = { x: 0, y: 0 };\n this.tiles = []; // 2D array of tile IDs\n this.tileset = new Map(); // ID -> color or image\n }\n\n loadMap(tiles) {\n if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) {\n throw new TypeError('tiles must be a 2D array');\n }\n this.tiles = tiles;\n }\n\n registerTile(id, renderable) {\n this.tileset.set(id, renderable);\n }\n\n setCamera(x, y) {\n this.camera.x = x;\n this.camera.y = y;\n }\n\n render() {\n const cols = Math.ceil(this.canvas.width / this.tileSize) + 1;\n const rows = Math.ceil(this.canvas.height / this.tileSize) + 1;\n const startCol = Math.floor(this.camera.x / this.tileSize);\n const startRow = Math.floor(this.camera.y / this.tileSize);\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tileRow = startRow + r;\n const tileCol = startCol + c;\n if (tileRow < 0 || tileRow >= this.tiles.length) continue;\n if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue;\n\n const tileId = this.tiles[tileRow][tileCol];\n const screenX = c * this.tileSize - (this.camera.x % this.tileSize);\n const screenY = r * this.tileSize - (this.camera.y % this.tileSize);\n\n const renderable = this.tileset.get(tileId);\n if (typeof renderable === 'string') {\n this.ctx.fillStyle = renderable;\n this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize);\n } else if (renderable instanceof HTMLImageElement) {\n this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize);\n }\n }\n }\n }\n}\n\n// Usage:\n// const renderer = new TilemapRenderer('game-canvas', 32);\n// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]);\n// renderer.registerTile(0, '#e17055');\n// renderer.registerTile(1, '#00b894');\n// renderer.setCamera(100, 50);\n// renderer.render();", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 998} +{"problem": "Create a particle explosion effect on canvas for game feedback", "solution": "class ParticleSystem {\n constructor() {\n this.particles = [];\n }\n\n emit(x, y, options = {}) {\n const {\n count = 20,\n speed = 0.02,\n life = 1.0,\n colors = ['#fab1a0', '#74b9ff', '#6c5ce7'],\n size = 4,\n gravity = 200\n } = options;\n\n for (let i = 0; i < count; i++) {\n const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;\n const velocity = speed * (0.5 + Math.random() * 0.5);\n this.particles.push({\n x, y,\n vx: Math.cos(angle) * velocity,\n vy: Math.sin(angle) * velocity,\n life,\n maxLife: life,\n color: colors[Math.floor(Math.random() * colors.length)],\n size: size * (0.5 + Math.random()),\n gravity\n });\n }\n }\n\n update(dt) {\n for (let i = this.particles.length - 1; i >= 0; i--) {\n const p = this.particles[i];\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n p.vy += p.gravity * dt;\n p.life -= dt;\n if (p.life <= 0) this.particles.splice(i, 1);\n }\n }\n\n draw(ctx) {\n for (const p of this.particles) {\n const alpha = Math.max(0, p.life / p.maxLife);\n ctx.globalAlpha = alpha;\n ctx.fillStyle = p.color;\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n}\n\n// Usage:\n// const particles = new ParticleSystem();\n// particles.emit(400, 300, { count: 30, speed: 150, colors: ['#0984e3', '#ff6b6b', '#fdcb6e'] });\n// // In game loop: particles.update(dt); particles.draw(ctx);", "domain": "games", "language": "javascript", "tags": ["frontend", "canvas", "game-dev"], "variant": 999} diff --git a/training/scripts/generate_code_patterns_frontend.py b/training/scripts/generate_code_patterns_frontend.py new file mode 100755 index 00000000..94cae47d --- /dev/null +++ b/training/scripts/generate_code_patterns_frontend.py @@ -0,0 +1,1575 @@ +#!/usr/bin/env python3 +""" +generate_code_patterns_frontend.py — Generate 1K problem→solution training pairs +for frontend & creative code (Three.js, HTML/CSS/JS, playground UI, gallery, games). + +Usage: + python3 training/scripts/generate_code_patterns_frontend.py + python3 training/scripts/generate_code_patterns_frontend.py --count 1000 --output training-data/code-patterns-frontend-&-creative.jsonl +""" + +import argparse +import json +import random +import sys +from pathlib import Path + +random.seed(42) + +# ── Variation pools ── +COLORS = ["#ff6b6b", "#4ecdc4", "#45b7d1", "#96ceb4", "#ffeaa7", "#dfe6e9", + "#fd79a8", "#a29bfe", "#00b894", "#e17055", "#74b9ff", "#55efc4", + "#fab1a0", "#fdcb6e", "#6c5ce7", "#0984e3", "#00cec9", "#e84393"] + +NAMES = ["hero", "scene", "viewer", "canvas", "stage", "world", "panel", "card", + "grid", "list", "item", "box", "circle", "shape", "model", "sprite", + "player", "enemy", "obstacle", "target", "button", "slider", "menu"] + +ADJECTIVES = ["dynamic", "interactive", "responsive", "animated", "stylish", + "minimal", "modern", "elegant", "bold", "soft", "vibrant", "dark"] + +SIZES = ["100px", "200px", "300px", "50%", "100%", "80vh", "60vw", "400px", "250px"] + +SPEEDS = [0.01, 0.02, 0.05, 0.1, 0.005, 0.03, 0.015] + +COUNTS = [3, 5, 8, 10, 12, 15, 20, 50] + + +def pick(pool, rng=random): + return rng.choice(pool) + + +def picks(pool, k, rng=random): + return rng.sample(pool, k=min(k, len(pool))) + + +# ── Domain: Three.js ── +def threejs_templates(): + t = [] + t.append(( + "Create a Three.js scene with a rotating colored cube", + '''import * as THREE from 'three'; + +function createCubeScene(containerId = 'canvas-container') { + const container = document.getElementById(containerId); + if (!container) throw new Error('Container not found: ' + containerId); + + const scene = new THREE.Scene(); + scene.background = new THREE.Color('{color1}'); + + const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000); + camera.position.z = 5; + + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(container.clientWidth, container.clientHeight); + renderer.setPixelRatio(window.devicePixelRatio); + container.appendChild(renderer.domElement); + + const geometry = new THREE.BoxGeometry(1, 1, 1); + const material = new THREE.MeshStandardMaterial({ color: '{color2}', roughness: 0.3, metalness: 0.1 }); + const cube = new THREE.Mesh(geometry, material); + scene.add(cube); + + const light = new THREE.DirectionalLight(0xffffff, 1); + light.position.set(5, 5, 5); + scene.add(light); + scene.add(new THREE.AmbientLight(0x404040)); + + function animate() { + requestAnimationFrame(animate); + cube.rotation.x += {speed}; + cube.rotation.y += {speed}; + renderer.render(scene, camera); + } + animate(); + + window.addEventListener('resize', () => { + camera.aspect = container.clientWidth / container.clientHeight; + camera.updateProjectionMatrix(); + renderer.setSize(container.clientWidth, container.clientHeight); + }); + + return { scene, camera, renderer, cube }; +} + +// Usage: createCubeScene();''' + )) + t.append(( + "Load a GLTF 3D model in Three.js with orbit controls", + '''import * as THREE from 'three'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; + +async function loadModel(url, containerId = 'canvas-container') { + const container = document.getElementById(containerId); + if (!container) throw new Error('Container not found'); + + const scene = new THREE.Scene(); + scene.background = new THREE.Color('{color1}'); + scene.fog = new THREE.Fog('{color1}', 10, 50); + + const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 100); + camera.position.set(0, 2, 5); + + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(container.clientWidth, container.clientHeight); + renderer.shadowMap.enabled = true; + container.appendChild(renderer.domElement); + + const controls = new OrbitControls(camera, renderer.domElement); + controls.enableDamping = true; + controls.dampingFactor = 0.05; + + scene.add(new THREE.AmbientLight(0xffffff, 0.5)); + const dirLight = new THREE.DirectionalLight(0xffffff, 1); + dirLight.position.set(5, 10, 7); + dirLight.castShadow = true; + scene.add(dirLight); + + const loader = new GLTFLoader(); + try { + const gltf = await loader.loadAsync(url); + const model = gltf.scene; + model.traverse(child => { if (child.isMesh) child.castShadow = true; }); + scene.add(model); + } catch (err) { + console.error('Failed to load model:', err); + throw err; + } + + function animate() { + requestAnimationFrame(animate); + controls.update(); + renderer.render(scene, camera); + } + animate(); + + return { scene, camera, controls }; +} + +// Usage: loadModel('/models/character.glb');''' + )) + t.append(( + "Create a particle system in Three.js with random motion", + '''import * as THREE from 'three'; + +function createParticles(count = {count}, containerId = 'canvas-container') { + const container = document.getElementById(containerId); + if (!container) throw new Error('Container not found'); + + const scene = new THREE.Scene(); + const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000); + camera.position.z = 30; + + const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); + renderer.setSize(container.clientWidth, container.clientHeight); + container.appendChild(renderer.domElement); + + const geometry = new THREE.BufferGeometry(); + const positions = new Float32Array(count * 3); + const velocities = []; + + for (let i = 0; i < count; i++) { + positions[i * 3] = (Math.random() - 0.5) * 50; + positions[i * 3 + 1] = (Math.random() - 0.5) * 50; + positions[i * 3 + 2] = (Math.random() - 0.5) * 50; + velocities.push({ + x: (Math.random() - 0.5) * {speed}, + y: (Math.random() - 0.5) * {speed}, + z: (Math.random() - 0.5) * {speed} + }); + } + + geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); + const material = new THREE.PointsMaterial({ color: '{color2}', size: 0.5, transparent: true, opacity: 0.8 }); + const particles = new THREE.Points(geometry, material); + scene.add(particles); + + function animate() { + requestAnimationFrame(animate); + const pos = geometry.attributes.position.array; + for (let i = 0; i < count; i++) { + pos[i * 3] += velocities[i].x; + pos[i * 3 + 1] += velocities[i].y; + pos[i * 3 + 2] += velocities[i].z; + if (Math.abs(pos[i * 3]) > 25) velocities[i].x *= -1; + if (Math.abs(pos[i * 3 + 1]) > 25) velocities[i].y *= -1; + if (Math.abs(pos[i * 3 + 2]) > 25) velocities[i].z *= -1; + } + geometry.attributes.position.needsUpdate = true; + renderer.render(scene, camera); + } + animate(); + + return { scene, particles, renderer }; +} + +// Usage: createParticles(200);''' + )) + t.append(( + "Create a reflective sphere with environment mapping in Three.js", + '''import * as THREE from 'three'; + +function createReflectiveSphere(containerId = 'canvas-container') { + const container = document.getElementById(containerId); + if (!container) throw new Error('Container not found'); + + const scene = new THREE.Scene(); + const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000); + camera.position.z = 3; + + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(container.clientWidth, container.clientHeight); + renderer.toneMapping = THREE.ACESFilmicToneMapping; + container.appendChild(renderer.domElement); + + const pmremGenerator = new THREE.PMREMGenerator(renderer); + const envScene = new THREE.Scene(); + envScene.background = new THREE.Color('{color1}'); + envScene.add(new THREE.Mesh( + new THREE.SphereGeometry(10, 32, 32), + new THREE.MeshBasicMaterial({ color: '{color2}', side: THREE.BackSide }) + )); + const envMap = pmremGenerator.fromScene(envScene).texture; + + const geometry = new THREE.SphereGeometry(1, 64, 64); + const material = new THREE.MeshPhysicalMaterial({ + color: '{color3}', + metalness: 1.0, + roughness: 0.1, + envMap, + envMapIntensity: 1.0 + }); + const sphere = new THREE.Mesh(geometry, material); + scene.add(sphere); + + function animate() { + requestAnimationFrame(animate); + sphere.rotation.y += {speed}; + renderer.render(scene, camera); + } + animate(); + + return { scene, sphere, renderer }; +} + +// Usage: createReflectiveSphere();''' + )) + t.append(( + "Build a Three.js first-person camera controller with WASD movement", + '''import * as THREE from 'three'; + +function createFPSController(containerId = 'canvas-container') { + const container = document.getElementById(containerId); + if (!container) throw new Error('Container not found'); + + const scene = new THREE.Scene(); + scene.background = new THREE.Color('{color1}'); + + const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000); + camera.position.y = 1.7; + + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(container.clientWidth, container.clientHeight); + container.appendChild(renderer.domElement); + + // Floor + const floor = new THREE.Mesh( + new THREE.PlaneGeometry(50, 50), + new THREE.MeshStandardMaterial({ color: '{color2}' }) + ); + floor.rotation.x = -Math.PI / 2; + floor.receiveShadow = true; + scene.add(floor); + + scene.add(new THREE.AmbientLight(0x404040)); + const dirLight = new THREE.DirectionalLight(0xffffff, 0.8); + dirLight.position.set(5, 10, 5); + scene.add(dirLight); + + const keys = { w: false, a: false, s: false, d: false }; + const velocity = new THREE.Vector3(); + const direction = new THREE.Vector3(); + + document.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = true; }); + document.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key.toLowerCase())) keys[e.key.toLowerCase()] = false; }); + + container.addEventListener('click', () => container.requestPointerLock()); + document.addEventListener('mousemove', (e) => { + if (document.pointerLockElement === container) { + camera.rotation.y -= e.movementX * 0.002; + camera.rotation.x -= e.movementY * 0.002; + camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x)); + } + }); + + const clock = new THREE.Clock(); + function animate() { + requestAnimationFrame(animate); + const delta = clock.getDelta(); + velocity.x -= velocity.x * 10 * delta; + velocity.z -= velocity.z * 10 * delta; + direction.z = Number(keys.w) - Number(keys.s); + direction.x = Number(keys.a) - Number(keys.d); + direction.normalize(); + if (keys.w || keys.s) velocity.z -= direction.z * 40 * delta; + if (keys.a || keys.d) velocity.x -= direction.x * 40 * delta; + camera.translateX(-velocity.x * delta); + camera.translateZ(-velocity.z * delta); + camera.position.y = 1.7; + renderer.render(scene, camera); + } + animate(); + + return { scene, camera, renderer }; +} + +// Usage: createFPSController();''' + )) + t.append(( + "Create an animated torus knot with wireframe overlay in Three.js", + '''import * as THREE from 'three'; + +function createTorusKnot(containerId = 'canvas-container') { + const container = document.getElementById(containerId); + if (!container) throw new Error('Container not found'); + + const scene = new THREE.Scene(); + scene.background = new THREE.Color('{color1}'); + + const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000); + camera.position.z = 5; + + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(container.clientWidth, container.clientHeight); + container.appendChild(renderer.domElement); + + const geometry = new THREE.TorusKnotGeometry(1, 0.3, 100, 16); + const material = new THREE.MeshStandardMaterial({ color: '{color2}', roughness: 0.4, metalness: 0.3 }); + const torus = new THREE.Mesh(geometry, material); + scene.add(torus); + + const wireGeo = new THREE.WireframeGeometry(geometry); + const wireMat = new THREE.LineBasicMaterial({ color: '{color3}' }); + const wireframe = new THREE.LineSegments(wireGeo, wireMat); + torus.add(wireframe); + + scene.add(new THREE.AmbientLight(0x404040)); + const pointLight = new THREE.PointLight(0xffffff, 1, 100); + pointLight.position.set(2, 3, 4); + scene.add(pointLight); + + function animate() { + requestAnimationFrame(animate); + torus.rotation.x += {speed}; + torus.rotation.y += {speed} * 0.7; + renderer.render(scene, camera); + } + animate(); + + return { scene, torus, renderer }; +} + +// Usage: createTorusKnot();''' + )) + t.append(( + "Raycast from mouse to detect 3D object clicks in Three.js", + '''import * as THREE from 'three'; + +function setupRaycasting(scene, camera, renderer, onIntersect) { + const raycaster = new THREE.Raycaster(); + const mouse = new THREE.Vector2(); + + renderer.domElement.addEventListener('click', (event) => { + const rect = renderer.domElement.getBoundingClientRect(); + mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + + raycaster.setFromCamera(mouse, camera); + const intersects = raycaster.intersectObjects(scene.children, true); + + if (intersects.length > 0) { + const hit = intersects[0]; + console.log('Clicked:', hit.object.name || hit.object.uuid); + if (typeof onIntersect === 'function') onIntersect(hit); + } + }); +} + +// Usage example: +// const mesh = new THREE.Mesh(geometry, material); +// mesh.name = 'clickable-box'; +// scene.add(mesh); +// setupRaycasting(scene, camera, renderer, (hit) => { +// hit.object.material.color.setHex(Math.random() * 0xffffff); +// });''' + )) + return t + + +# ── Domain: HTML/CSS/JS ── +def htmlcss_templates(): + t = [] + t.append(( + "Build a responsive CSS grid layout with auto-fit columns", + '''/* Responsive grid layout */ +.grid-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax({size}, 1fr)); + gap: 1.5rem; + padding: 2rem; + max-width: 1200px; + margin: 0 auto; +} + +.grid-item { + background: {color1}; + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 4px 6px rgba(0,0,0,0.1); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.grid-item:hover { + transform: translateY(-4px); + box-shadow: 0 12px 24px rgba(0,0,0,0.15); +} + +@media (max-width: 600px) { + .grid-container { + grid-template-columns: 1fr; + padding: 1rem; + } +}''' + )) + t.append(( + "Create a sticky navigation bar that changes style on scroll", + '''/* Sticky nav styles */ +.nav-bar { + position: sticky; + top: 0; + z-index: 1000; + background: transparent; + padding: 1rem 2rem; + transition: background 0.3s ease, box-shadow 0.3s ease; +} + +.nav-bar.scrolled { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + box-shadow: 0 2px 10px rgba(0,0,0,0.1); +} + +/* JavaScript */ +function initStickyNav(navSelector = '.nav-bar') { + const nav = document.querySelector(navSelector); + if (!nav) throw new Error('Nav element not found'); + + function onScroll() { + if (window.scrollY > 50) { + nav.classList.add('scrolled'); + } else { + nav.classList.remove('scrolled'); + } + } + + window.addEventListener('scroll', onScroll, { passive: true }); + onScroll(); // Initialize state + return nav; +} + +// Usage: initStickyNav();''' + )) + t.append(( + "Implement debounced search input with fetch API", + '''async function debouncedSearch(inputSelector, endpoint, renderFn, delay = 300) { + const input = document.querySelector(inputSelector); + if (!input) throw new Error('Input element not found'); + + let timeoutId = null; + let controller = null; + + input.addEventListener('input', (e) => { + const query = e.target.value.trim(); + clearTimeout(timeoutId); + if (controller) controller.abort(); + + if (!query) { + renderFn([]); + return; + } + + timeoutId = setTimeout(async () => { + controller = new AbortController(); + try { + const res = await fetch(`${endpoint}?q=${encodeURIComponent(query)}`, { + signal: controller.signal + }); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const data = await res.json(); + renderFn(data); + } catch (err) { + if (err.name !== 'AbortError') { + console.error('Search failed:', err); + renderFn([], err); + } + } + }, delay); + }); +} + +// Usage: +// debouncedSearch('#search', '/api/search', (results, err) => { +// if (err) return showError(err); +// updateDOM(results); +// });''' + )) + t.append(( + "Create a CSS-only modal with backdrop blur and focus trap", + '''/* Modal styles */ +.modal-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease, visibility 0.3s ease; +} + +.modal-overlay.active { + opacity: 1; + visibility: visible; +} + +.modal-content { + background: white; + border-radius: 16px; + padding: 2rem; + max-width: 500px; + width: 90%; + transform: scale(0.9); + transition: transform 0.3s ease; + box-shadow: 0 20px 60px rgba(0,0,0,0.3); +} + +.modal-overlay.active .modal-content { + transform: scale(1); +} + +/* JavaScript for focus trap and keyboard */ +function initModal(triggerSelector, modalSelector) { + const trigger = document.querySelector(triggerSelector); + const modal = document.querySelector(modalSelector); + if (!trigger || !modal) throw new Error('Modal elements not found'); + + const content = modal.querySelector('.modal-content'); + const focusables = content.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); + + function open() { + modal.classList.add('active'); + (focusables[0] || content).focus(); + document.addEventListener('keydown', onKey); + } + + function close() { + modal.classList.remove('active'); + document.removeEventListener('keydown', onKey); + trigger.focus(); + } + + function onKey(e) { + if (e.key === 'Escape') close(); + if (e.key === 'Tab' && focusables.length > 0) { + const first = focusables[0]; + const last = focusables[focusables.length - 1]; + if (e.shiftKey && document.activeElement === first) { + e.preventDefault(); + last.focus(); + } else if (!e.shiftKey && document.activeElement === last) { + e.preventDefault(); + first.focus(); + } + } + } + + trigger.addEventListener('click', open); + modal.addEventListener('click', (e) => { if (e.target === modal) close(); }); + + return { open, close }; +} + +// Usage: initModal('#open-modal', '#my-modal');''' + )) + t.append(( + "Build a custom dropdown select with keyboard navigation", + '''function createCustomSelect(selectElement) { + if (!(selectElement instanceof HTMLSelectElement)) { + throw new TypeError('Expected HTMLSelectElement'); + } + + const wrapper = document.createElement('div'); + wrapper.className = 'custom-select'; + wrapper.style.position = 'relative'; + wrapper.style.width = selectElement.offsetWidth + 'px'; + + const trigger = document.createElement('button'); + trigger.type = 'button'; + trigger.className = 'select-trigger'; + trigger.textContent = selectElement.options[selectElement.selectedIndex]?.text || 'Select...'; + trigger.setAttribute('aria-haspopup', 'listbox'); + + const list = document.createElement('ul'); + list.className = 'select-options'; + list.setAttribute('role', 'listbox'); + list.style.cssText = 'position:absolute;top:100%;left:0;right:0;max-height:200px;overflow:auto;list-style:none;margin:0;padding:0;border:1px solid #ccc;background:#fff;z-index:100;display:none;'; + + Array.from(selectElement.options).forEach((opt, i) => { + const li = document.createElement('li'); + li.textContent = opt.text; + li.setAttribute('role', 'option'); + li.setAttribute('aria-selected', String(opt.selected)); + li.dataset.value = opt.value; + li.style.padding = '0.5rem 1rem'; + li.style.cursor = 'pointer'; + li.addEventListener('click', () => { + selectElement.value = opt.value; + trigger.textContent = opt.text; + close(); + selectElement.dispatchEvent(new Event('change')); + }); + list.appendChild(li); + }); + + wrapper.appendChild(trigger); + wrapper.appendChild(list); + selectElement.style.display = 'none'; + selectElement.parentNode.insertBefore(wrapper, selectElement); + + let activeIndex = -1; + function open() { + list.style.display = 'block'; + trigger.setAttribute('aria-expanded', 'true'); + activeIndex = Array.from(selectElement.options).findIndex(o => o.selected); + } + function close() { + list.style.display = 'none'; + trigger.setAttribute('aria-expanded', 'false'); + } + + trigger.addEventListener('click', () => { + list.style.display === 'block' ? close() : open(); + }); + + document.addEventListener('click', (e) => { + if (!wrapper.contains(e.target)) close(); + }); + + trigger.addEventListener('keydown', (e) => { + const items = list.querySelectorAll('li'); + if (e.key === 'ArrowDown') { open(); activeIndex = Math.min(activeIndex + 1, items.length - 1); items[activeIndex]?.focus(); e.preventDefault(); } + if (e.key === 'ArrowUp') { open(); activeIndex = Math.max(activeIndex - 1, 0); items[activeIndex]?.focus(); e.preventDefault(); } + if (e.key === 'Enter' || e.key === ' ') { if (list.style.display === 'block' && items[activeIndex]) items[activeIndex].click(); else open(); e.preventDefault(); } + if (e.key === 'Escape') close(); + }); + + return wrapper; +} + +// Usage: createCustomSelect(document.getElementById('my-select'));''' + )) + t.append(( + "Implement smooth scroll-to-section with intersection observer highlighting", + '''function initScrollSpy(navSelector, sectionSelector, options = {}) { + const navLinks = document.querySelectorAll(`${navSelector} a[href^="#"]`); + const sections = document.querySelectorAll(sectionSelector); + if (!navLinks.length || !sections.length) { + console.warn('Scroll spy: no nav links or sections found'); + return; + } + + const offset = options.offset || 80; + + // Smooth scroll on click + navLinks.forEach(link => { + link.addEventListener('click', (e) => { + e.preventDefault(); + const targetId = link.getAttribute('href').slice(1); + const target = document.getElementById(targetId); + if (target) { + window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' }); + } + }); + }); + + // Intersection observer for active state + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + navLinks.forEach(l => l.classList.remove('active')); + const active = document.querySelector(`${navSelector} a[href="#${entry.target.id}"]`); + if (active) active.classList.add('active'); + } + }); + }, { rootMargin: `-${offset}px 0px -60% 0px` }); + + sections.forEach(section => observer.observe(section)); + return observer; +} + +// Usage: initScrollSpy('.side-nav', 'section[data-section]');''' + )) + return t + + +# ── Domain: Playground UI ── +def playground_templates(): + t = [] + t.append(( + "Create a draggable range slider with real-time value display", + '''function createRangeSlider(container, options = {}) { + const { min = 0, max = 100, step = 1, value = 50, onChange } = options; + container = typeof container === 'string' ? document.querySelector(container) : container; + if (!container) throw new Error('Slider container not found'); + + const wrapper = document.createElement('div'); + wrapper.className = 'range-slider'; + wrapper.style.cssText = 'display:flex;align-items:center;gap:1rem;font-family:sans-serif;'; + + const input = document.createElement('input'); + input.type = 'range'; + input.min = min; + input.max = max; + input.step = step; + input.value = value; + input.style.flex = '1'; + + const valueDisplay = document.createElement('span'); + valueDisplay.className = 'slider-value'; + valueDisplay.textContent = value; + valueDisplay.style.minWidth = '3ch'; + valueDisplay.style.textAlign = 'right'; + valueDisplay.style.fontVariantNumeric = 'tabular-nums'; + + input.addEventListener('input', (e) => { + valueDisplay.textContent = e.target.value; + if (typeof onChange === 'function') onChange(Number(e.target.value)); + }); + + wrapper.appendChild(input); + wrapper.appendChild(valueDisplay); + container.appendChild(wrapper); + + return { input, valueDisplay, getValue: () => Number(input.value) }; +} + +// Usage: +// createRangeSlider('#slider-box', { +// min: 0, max: 255, value: 128, +// onChange: (v) => { document.body.style.background = `rgb(${v},${v},${v})`; } +// });''' + )) + t.append(( + "Build a color picker canvas with eyedropper and palette export", + '''function createColorPicker(canvasId, exportBtnId) { + const canvas = document.getElementById(canvasId); + const exportBtn = document.getElementById(exportBtnId); + if (!canvas || !exportBtn) throw new Error('Color picker elements not found'); + + const ctx = canvas.getContext('2d', { willReadFrequently: true }); + let isDragging = false; + const palette = new Set(); + + // Draw a hue-saturation gradient + function drawGradient() { + const w = canvas.width; + const h = canvas.height; + for (let x = 0; x < w; x++) { + const hue = (x / w) * 360; + const grad = ctx.createLinearGradient(0, 0, 0, h); + grad.addColorStop(0, `hsl(${hue}, 100%, 50%)`); + grad.addColorStop(1, `hsl(${hue}, 100%, 0%)`); + ctx.fillStyle = grad; + ctx.fillRect(x, 0, 1, h); + } + } + drawGradient(); + + function pickColor(x, y) { + const pixel = ctx.getImageData(x, y, 1, 1).data; + const hex = '#' + [pixel[0], pixel[1], pixel[2]].map(c => c.toString(16).padStart(2, '0')).join(''); + return hex; + } + + function handleMove(e) { + const rect = canvas.getBoundingClientRect(); + const x = Math.min(Math.max(e.clientX - rect.left, 0), canvas.width - 1); + const y = Math.min(Math.max(e.clientY - rect.top, 0), canvas.height - 1); + const color = pickColor(x, y); + canvas.style.cursor = 'crosshair'; + if (isDragging) { + palette.add(color); + canvas.dispatchEvent(new CustomEvent('colorpicked', { detail: { color, x, y } })); + } + return color; + } + + canvas.addEventListener('mousedown', (e) => { isDragging = true; handleMove(e); }); + canvas.addEventListener('mousemove', handleMove); + canvas.addEventListener('mouseup', () => { isDragging = false; }); + canvas.addEventListener('mouseleave', () => { isDragging = false; }); + + exportBtn.addEventListener('click', () => { + const colors = Array.from(palette); + const blob = new Blob([JSON.stringify(colors, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'palette.json'; + a.click(); + URL.revokeObjectURL(url); + }); + + return { canvas, palette, pickColor }; +} + +// Usage: createColorPicker('picker-canvas', 'export-btn');''' + )) + t.append(( + "Create a live code preview playground with iframe sandbox", + '''function createCodePlayground(containerSelector) { + const container = document.querySelector(containerSelector); + if (!container) throw new Error('Playground container not found'); + + container.innerHTML = ` +
+
+ + + + +
+ + +
+ `; + + const editor = container.querySelector('.editor'); + const preview = container.querySelector('.preview'); + const files = { html: '

Hello World

', css: 'h1 { color: {color1}; }', js: 'console.log("ready");' }; + let currentLang = 'html'; + + editor.value = files.html; + + container.querySelectorAll('button[data-lang]').forEach(btn => { + btn.addEventListener('click', () => { + files[currentLang] = editor.value; + currentLang = btn.dataset.lang; + editor.value = files[currentLang]; + }); + }); + + container.querySelector('button[data-action="run"]').addEventListener('click', () => { + files[currentLang] = editor.value; + const doc = ` + + + + ${files.html} + + `; + preview.srcdoc = doc; + }); + + return { editor, preview, getFiles: () => ({ ...files }) }; +} + +// Usage: createCodePlayground('#playground');''' + )) + t.append(( + "Build a resizable split-pane layout with drag handle", + '''function createSplitPane(containerSelector, options = {}) { + const container = document.querySelector(containerSelector); + if (!container) throw new Error('Split pane container not found'); + + const { direction = 'horizontal', initialRatio = 0.5, minSize = 100 } = options; + const isHorizontal = direction === 'horizontal'; + + container.style.display = 'flex'; + container.style.flexDirection = isHorizontal ? 'row' : 'column'; + container.style.height = '100%'; + container.style.overflow = 'hidden'; + + const pane1 = document.createElement('div'); + pane1.className = 'pane pane-1'; + pane1.style.flex = `0 0 calc(${initialRatio * 100}% - 4px)`; + pane1.style.overflow = 'auto'; + pane1.style.minWidth = isHorizontal ? minSize + 'px' : 'auto'; + pane1.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto'; + + const handle = document.createElement('div'); + handle.className = 'split-handle'; + handle.style.flex = '0 0 8px'; + handle.style.background = '#e0e0e0'; + handle.style.cursor = isHorizontal ? 'col-resize' : 'row-resize'; + handle.style.userSelect = 'none'; + + const pane2 = document.createElement('div'); + pane2.className = 'pane pane-2'; + pane2.style.flex = '1 1 auto'; + pane2.style.overflow = 'auto'; + pane2.style.minWidth = isHorizontal ? minSize + 'px' : 'auto'; + pane2.style.minHeight = !isHorizontal ? minSize + 'px' : 'auto'; + + container.appendChild(pane1); + container.appendChild(handle); + container.appendChild(pane2); + + let isDragging = false; + const sizeProp = isHorizontal ? 'clientWidth' : 'clientHeight'; + + handle.addEventListener('mousedown', (e) => { + isDragging = true; + document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize'; + }); + + document.addEventListener('mousemove', (e) => { + if (!isDragging) return; + const rect = container.getBoundingClientRect(); + const pos = isHorizontal ? e.clientX - rect.left : e.clientY - rect.top; + const ratio = Math.max(minSize, Math.min(pos, rect[sizeProp] - minSize)) / rect[sizeProp]; + pane1.style.flex = `0 0 calc(${ratio * 100}% - 4px)`; + }); + + document.addEventListener('mouseup', () => { + isDragging = false; + document.body.style.cursor = ''; + }); + + return { pane1, pane2, handle }; +} + +// Usage: createSplitPane('#editor-layout', { direction: 'horizontal', initialRatio: 0.4 });''' + )) + return t + + +# ── Domain: Gallery ── +def gallery_templates(): + t = [] + t.append(( + "Implement a masonry image grid with lazy loading and lightbox", + '''function createMasonryGallery(containerSelector, imageUrls) { + const container = document.querySelector(containerSelector); + if (!container) throw new Error('Gallery container not found'); + + container.style.columnCount = '3'; + container.style.columnGap = '1rem'; + + if (!Array.isArray(imageUrls)) throw new TypeError('imageUrls must be an array'); + + // Lightbox overlay + const lightbox = document.createElement('div'); + lightbox.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.9);display:none;align-items:center;justify-content:center;z-index:1000;'; + const img = document.createElement('img'); + img.style.maxWidth = '90vw'; + img.style.maxHeight = '90vh'; + img.style.objectFit = 'contain'; + lightbox.appendChild(img); + lightbox.addEventListener('click', () => { lightbox.style.display = 'none'; }); + document.body.appendChild(lightbox); + + imageUrls.forEach((src, i) => { + const wrapper = document.createElement('div'); + wrapper.style.breakInside = 'avoid'; + wrapper.style.marginBottom = '1rem'; + + const image = document.createElement('img'); + image.dataset.src = src; + image.alt = `Gallery image ${i + 1}`; + image.style.width = '100%'; + image.style.borderRadius = '8px'; + image.style.display = 'block'; + image.style.background = '{color1}'; + image.style.minHeight = '150px'; + + image.addEventListener('click', () => { + img.src = src; + lightbox.style.display = 'flex'; + }); + + wrapper.appendChild(image); + container.appendChild(wrapper); + }); + + // Lazy loading + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting && entry.target.dataset.src) { + entry.target.src = entry.target.dataset.src; + delete entry.target.dataset.src; + observer.unobserve(entry.target); + } + }); + }, { rootMargin: '200px' }); + + container.querySelectorAll('img[data-src]').forEach(img => observer.observe(img)); + return { container, lightbox, observer }; +} + +// Usage: createMasonryGallery('#gallery', ['/img/1.jpg', '/img/2.jpg']);''' + )) + t.append(( + "Create an image carousel with touch swipe and keyboard controls", + '''function createCarousel(containerSelector, slides) { + const container = document.querySelector(containerSelector); + if (!container) throw new Error('Carousel container not found'); + if (!Array.isArray(slides) || slides.length === 0) throw new Error('Slides array required'); + + let current = 0; + + container.innerHTML = ` + + `; + + const track = container.querySelector('.track'); + const indicators = container.querySelector('.indicators'); + + slides.forEach((slide, i) => { + const div = document.createElement('div'); + div.style.minWidth = '100%'; + div.innerHTML = slide; + track.appendChild(div); + + const dot = document.createElement('button'); + dot.style.width = '10px'; + dot.style.height = '10px'; + dot.style.borderRadius = '50%'; + dot.style.border = 'none'; + dot.style.background = i === 0 ? '#fff' : 'rgba(255,255,255,0.4)'; + dot.addEventListener('click', () => goTo(i)); + indicators.appendChild(dot); + }); + + function goTo(index) { + current = ((index % slides.length) + slides.length) % slides.length; + track.style.transform = `translateX(-${current * 100}%)`; + Array.from(indicators.children).forEach((dot, i) => { + dot.style.background = i === current ? '#fff' : 'rgba(255,255,255,0.4)'; + }); + } + + container.querySelector('.prev').addEventListener('click', () => goTo(current - 1)); + container.querySelector('.next').addEventListener('click', () => goTo(current + 1)); + + // Touch swipe + let startX = 0; + container.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; }); + container.addEventListener('touchend', (e) => { + const diff = startX - e.changedTouches[0].clientX; + if (Math.abs(diff) > 50) goTo(current + (diff > 0 ? 1 : -1)); + }); + + // Keyboard + container.setAttribute('tabindex', '0'); + container.addEventListener('keydown', (e) => { + if (e.key === 'ArrowLeft') goTo(current - 1); + if (e.key === 'ArrowRight') goTo(current + 1); + }); + + return { goTo, getCurrent: () => current }; +} + +// Usage: createCarousel('#carousel', ['', '']);''' + )) + t.append(( + "Build an infinite scroll image feed with skeleton placeholders", + '''function createInfiniteFeed(containerSelector, fetchPage, options = {}) { + const container = document.querySelector(containerSelector); + if (!container) throw new Error('Feed container not found'); + if (typeof fetchPage !== 'function') throw new TypeError('fetchPage must be a function'); + + const { pageSize = 20, threshold = 300 } = options; + let page = 1; + let isLoading = false; + let hasMore = true; + + function createSkeletons(count) { + const frag = document.createDocumentFragment(); + for (let i = 0; i < count; i++) { + const div = document.createElement('div'); + div.className = 'skeleton'; + div.style.cssText = 'height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:8px;'; + frag.appendChild(div); + } + return frag; + } + + // Add shimmer keyframes if not present + if (!document.getElementById('skeleton-styles')) { + const style = document.createElement('style'); + style.id = 'skeleton-styles'; + style.textContent = '@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }'; + document.head.appendChild(style); + } + + async function loadMore() { + if (isLoading || !hasMore) return; + isLoading = true; + const skeletons = createSkeletons(pageSize); + container.appendChild(skeletons); + + try { + const items = await fetchPage(page, pageSize); + skeletons.remove(); + if (!items || items.length === 0) { + hasMore = false; + return; + } + items.forEach(item => container.appendChild(item)); + page++; + } catch (err) { + console.error('Feed load error:', err); + skeletons.remove(); + } finally { + isLoading = false; + } + } + + const sentinel = document.createElement('div'); + sentinel.style.height = '1px'; + container.appendChild(sentinel); + + const observer = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting) loadMore(); + }, { rootMargin: `${threshold}px` }); + observer.observe(sentinel); + + loadMore(); + return { loadMore, observer }; +} + +// Usage: +// createInfiniteFeed('#feed', async (page, size) => { +// const res = await fetch(`/api/images?page=${page}&size=${size}`); +// const data = await res.json(); +// return data.map(url => { const img = document.createElement('img'); img.src = url; return img; }); +// });''' + )) + return t + + +# ── Domain: Games ── +def game_templates(): + t = [] + t.append(( + "Create a 2D canvas game loop with delta-time physics", + '''class GameEngine { + constructor(canvasId, options = {}) { + this.canvas = document.getElementById(canvasId); + if (!this.canvas) throw new Error('Canvas not found: ' + canvasId); + this.ctx = this.canvas.getContext('2d'); + this.entities = []; + this.lastTime = 0; + this.running = false; + this.fps = 60; + + this.canvas.width = options.width || 800; + this.canvas.height = options.height || 600; + this.canvas.style.background = options.bg || '{color1}'; + } + + addEntity(entity) { + if (!entity.update || !entity.draw) { + throw new TypeError('Entity must have update(dt) and draw(ctx) methods'); + } + this.entities.push(entity); + return this; + } + + start() { + this.running = true; + requestAnimationFrame((t) => this.loop(t)); + } + + stop() { + this.running = false; + } + + loop(timestamp) { + if (!this.running) return; + const dt = Math.min((timestamp - this.lastTime) / 1000, 0.05); // Cap delta + this.lastTime = timestamp; + + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + + for (const entity of this.entities) { + entity.update(dt, this.canvas.width, this.canvas.height); + entity.draw(this.ctx); + } + + requestAnimationFrame((t) => this.loop(t)); + } +} + +// Usage: +// const engine = new GameEngine('game-canvas', { width: 800, height: 600 }); +// engine.addEntity({ update(dt, w, h) { this.x += 100 * dt; }, draw(ctx) { ctx.fillRect(this.x, 100, 20, 20); }, x: 0 }); +// engine.start();''' + )) + t.append(( + "Implement AABB collision detection for rectangular game entities", + '''function checkAABBCollision(a, b) { + if (!a || !b) throw new Error('Both entities required for collision check'); + return ( + a.x < b.x + b.width && + a.x + a.width > b.x && + a.y < b.y + b.height && + a.y + a.height > b.y + ); +} + +function resolveAABBOverlap(a, b) { + const overlapX = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x); + const overlapY = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y); + + if (overlapX < overlapY) { + const dir = a.x < b.x ? -1 : 1; + a.x += (overlapX / 2) * dir; + b.x -= (overlapX / 2) * dir; + } else { + const dir = a.y < b.y ? -1 : 1; + a.y += (overlapY / 2) * dir; + b.y -= (overlapY / 2) * dir; + } +} + +class PhysicsWorld { + constructor() { + this.bodies = []; + } + + add(body) { + if (typeof body.x !== 'number' || typeof body.y !== 'number') { + throw new TypeError('Body must have numeric x and y properties'); + } + this.bodies.push(body); + } + + step() { + for (let i = 0; i < this.bodies.length; i++) { + for (let j = i + 1; j < this.bodies.length; j++) { + if (checkAABBCollision(this.bodies[i], this.bodies[j])) { + resolveAABBOverlap(this.bodies[i], this.bodies[j]); + if (this.bodies[i].onCollision) this.bodies[i].onCollision(this.bodies[j]); + if (this.bodies[j].onCollision) this.bodies[j].onCollision(this.bodies[i]); + } + } + } + } +} + +// Usage: +// const world = new PhysicsWorld(); +// world.add({ x: 0, y: 0, width: 32, height: 32, onCollision(other) { console.log('hit!'); } }); +// world.step();''' + )) + t.append(( + "Build a sprite animation system with frame clipping and playback controls", + '''class SpriteAnimator { + constructor(image, frameWidth, frameHeight, frameCount) { + if (!(image instanceof HTMLImageElement)) throw new TypeError('Expected HTMLImageElement'); + this.image = image; + this.frameWidth = frameWidth; + this.frameHeight = frameHeight; + this.frameCount = frameCount; + this.currentFrame = 0; + this.elapsed = 0; + this.fps = 10; + this.playing = true; + this.loop = true; + } + + update(dt) { + if (!this.playing) return; + this.elapsed += dt; + const frameDuration = 1 / this.fps; + if (this.elapsed >= frameDuration) { + this.elapsed -= frameDuration; + this.currentFrame++; + if (this.currentFrame >= this.frameCount) { + if (this.loop) this.currentFrame = 0; + else { this.currentFrame = this.frameCount - 1; this.playing = false; } + } + } + } + + draw(ctx, x, y, options = {}) { + const sx = (this.currentFrame * this.frameWidth) % this.image.width; + const sy = Math.floor((this.currentFrame * this.frameWidth) / this.image.width) * this.frameHeight; + const scale = options.scale || 1; + ctx.drawImage( + this.image, + sx, sy, this.frameWidth, this.frameHeight, + x, y, this.frameWidth * scale, this.frameHeight * scale + ); + } + + play() { this.playing = true; } + pause() { this.playing = false; } + reset() { this.currentFrame = 0; this.elapsed = 0; } + setFrame(index) { this.currentFrame = Math.max(0, Math.min(index, this.frameCount - 1)); } +} + +// Usage: +// const img = new Image(); +// img.src = '/sprites/player.png'; +// img.onload = () => { +// const anim = new SpriteAnimator(img, 32, 32, 8); +// // In game loop: anim.update(dt); anim.draw(ctx, 100, 100); +// };''' + )) + t.append(( + "Implement a tilemap renderer with camera scrolling and culling", + '''class TilemapRenderer { + constructor(canvasId, tileSize = 32) { + this.canvas = document.getElementById(canvasId); + if (!this.canvas) throw new Error('Canvas not found'); + this.ctx = this.canvas.getContext('2d'); + this.tileSize = tileSize; + this.camera = { x: 0, y: 0 }; + this.tiles = []; // 2D array of tile IDs + this.tileset = new Map(); // ID -> color or image + } + + loadMap(tiles) { + if (!Array.isArray(tiles) || !tiles.every(row => Array.isArray(row))) { + throw new TypeError('tiles must be a 2D array'); + } + this.tiles = tiles; + } + + registerTile(id, renderable) { + this.tileset.set(id, renderable); + } + + setCamera(x, y) { + this.camera.x = x; + this.camera.y = y; + } + + render() { + const cols = Math.ceil(this.canvas.width / this.tileSize) + 1; + const rows = Math.ceil(this.canvas.height / this.tileSize) + 1; + const startCol = Math.floor(this.camera.x / this.tileSize); + const startRow = Math.floor(this.camera.y / this.tileSize); + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + const tileRow = startRow + r; + const tileCol = startCol + c; + if (tileRow < 0 || tileRow >= this.tiles.length) continue; + if (tileCol < 0 || tileCol >= this.tiles[tileRow].length) continue; + + const tileId = this.tiles[tileRow][tileCol]; + const screenX = c * this.tileSize - (this.camera.x % this.tileSize); + const screenY = r * this.tileSize - (this.camera.y % this.tileSize); + + const renderable = this.tileset.get(tileId); + if (typeof renderable === 'string') { + this.ctx.fillStyle = renderable; + this.ctx.fillRect(screenX, screenY, this.tileSize, this.tileSize); + } else if (renderable instanceof HTMLImageElement) { + this.ctx.drawImage(renderable, screenX, screenY, this.tileSize, this.tileSize); + } + } + } + } +} + +// Usage: +// const renderer = new TilemapRenderer('game-canvas', 32); +// renderer.loadMap([[0,0,1],[0,1,1],[1,1,1]]); +// renderer.registerTile(0, '{color1}'); +// renderer.registerTile(1, '{color2}'); +// renderer.setCamera(100, 50); +// renderer.render();''' + )) + t.append(( + "Create a particle explosion effect on canvas for game feedback", + '''class ParticleSystem { + constructor() { + this.particles = []; + } + + emit(x, y, options = {}) { + const { + count = {count}, + speed = {speed}, + life = 1.0, + colors = {colors}, + size = 4, + gravity = 200 + } = options; + + for (let i = 0; i < count; i++) { + const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5; + const velocity = speed * (0.5 + Math.random() * 0.5); + this.particles.push({ + x, y, + vx: Math.cos(angle) * velocity, + vy: Math.sin(angle) * velocity, + life, + maxLife: life, + color: colors[Math.floor(Math.random() * colors.length)], + size: size * (0.5 + Math.random()), + gravity + }); + } + } + + update(dt) { + for (let i = this.particles.length - 1; i >= 0; i--) { + const p = this.particles[i]; + p.x += p.vx * dt; + p.y += p.vy * dt; + p.vy += p.gravity * dt; + p.life -= dt; + if (p.life <= 0) this.particles.splice(i, 1); + } + } + + draw(ctx) { + for (const p of this.particles) { + const alpha = Math.max(0, p.life / p.maxLife); + ctx.globalAlpha = alpha; + ctx.fillStyle = p.color; + ctx.beginPath(); + ctx.arc(p.x, p.y, p.size * alpha, 0, Math.PI * 2); + ctx.fill(); + } + ctx.globalAlpha = 1; + } +} + +// Usage: +// const particles = new ParticleSystem(); +// particles.emit(400, 300, { count: 30, speed: 150, colors: ['{color1}', '{color2}', '{color3}'] }); +// // In game loop: particles.update(dt); particles.draw(ctx);''' + )) + return t + + +# ── Generator ── +def generate(count=1000): + rng = random.Random(42) + templates = ( + threejs_templates() + + htmlcss_templates() + + playground_templates() + + gallery_templates() + + game_templates() + ) + + entries = [] + tpl_idx = 0 + variant = 0 + + while len(entries) < count: + problem_template, solution_template = templates[tpl_idx % len(templates)] + tpl_idx += 1 + + color1 = pick(COLORS, rng) + color2 = pick(COLORS, rng) + color3 = pick(COLORS, rng) + name = pick(NAMES, rng) + adj = pick(ADJECTIVES, rng) + size = pick(SIZES, rng) + speed = pick(SPEEDS, rng) + cnt = pick(COUNTS, rng) + + problem = problem_template.replace('{name}', name).replace('{adj}', adj) + solution = (solution_template + .replace('{color1}', color1) + .replace('{color2}', color2) + .replace('{color3}', color3) + .replace('{name}', name) + .replace('{adj}', adj) + .replace('{size}', size) + .replace('{speed}', str(speed)) + .replace('{count}', str(cnt)) + .replace('{colors}', str(picks(COLORS, 3, rng)))) + + # Determine domain from template source + domain = 'threejs' + lang = 'javascript' + tags = ['frontend'] + if problem_template in [p for p, _ in htmlcss_templates()]: + domain = 'html-css-js' + lang = 'css' if problem_template.startswith('Build a responsive CSS') or 'grid' in problem_template else 'javascript' + tags = ['frontend', 'css', 'dom'] + elif problem_template in [p for p, _ in playground_templates()]: + domain = 'playground' + tags = ['frontend', 'ui', 'interactive'] + elif problem_template in [p for p, _ in gallery_templates()]: + domain = 'gallery' + tags = ['frontend', 'images', 'performance'] + elif problem_template in [p for p, _ in game_templates()]: + domain = 'games' + tags = ['frontend', 'canvas', 'game-dev'] + + if 'three.js' in problem.lower(): + domain = 'threejs' + tags = ['frontend', 'threejs', 'webgl'] + + entries.append({ + 'problem': problem, + 'solution': solution, + 'domain': domain, + 'language': lang, + 'tags': tags, + 'variant': variant + }) + variant += 1 + + return entries + + +def main(): + parser = argparse.ArgumentParser(description='Generate frontend code pattern training pairs') + parser.add_argument('--count', type=int, default=1000, help='Number of pairs to generate') + parser.add_argument('--output', type=str, default='training-data/code-patterns-frontend-&-creative.jsonl') + parser.add_argument('--seed', type=int, default=42, help='Random seed') + args = parser.parse_args() + + random.seed(args.seed) + entries = generate(args.count) + + out_path = Path(args.output) + out_path.parent.mkdir(parents=True, exist_ok=True) + + with open(out_path, 'w', encoding='utf-8') as f: + for entry in entries: + f.write(json.dumps(entry, ensure_ascii=False) + '\n') + + print(f'Generated {len(entries)} code pattern pairs → {out_path}') + print(f'Size: {out_path.stat().st_size / 1024:.1f} KB') + + # Print domain distribution + from collections import Counter + dist = Counter(e['domain'] for e in entries) + print('Domain distribution:') + for d, c in sorted(dist.items()): + print(f' {d}: {c}') + + +if __name__ == '__main__': + main()