jaml-ui 0.25.2 → 0.25.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ui-5cBy3zAm.js","names":[],"sources":["../../src/ui/hooks.ts","../../src/ui/sprites.tsx","../../src/ui/jimboText.tsx","../../src/ui/panel.tsx","../../src/ui/jimboTabs.tsx","../../src/ui/JimboFloating.tsx","../../src/ui/JimboToggleList.tsx","../../src/ui/JimboBadge.tsx","../../src/ui/jimboFlankNav.tsx","../../src/ui/jimboFilterBar.tsx","../../src/ui/footer.tsx","../../src/ui/jimboBackground.tsx","../../src/ui/jimboTooltip.tsx","../../src/ui/codeBlock.tsx","../../src/ui/jimboApp.tsx","../../src/ui/jimboSectionHeader.tsx","../../src/ui/jimboInfoCard.tsx","../../src/ui/showcase.tsx","../../src/ui/jimboCopyRow.tsx","../../src/ui/jimboWordmark.tsx","../../src/ui/jimboStatGrid.tsx","../../src/ui/jimboInset.tsx","../../src/ui/JimboIconButton.tsx","../../src/ui/JimboInputModal.tsx","../../src/ui/JimboSelect.tsx","../../src/ui/PanelSplitter.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react'\r\nimport { JamlVisualClause, JamlVisualFilter, JamlZone } from '../components/JamlIdeVisual.js'\r\nimport { JIMBO_ANIMATIONS } from './tokens.js'\r\nimport { Layer } from '../render/Layer.js'\r\nimport { SPRITE_SHEETS } from '../sprites/spriteData.js'\r\n\r\nfunction loadImage(url: string): Promise<HTMLImageElement | null> {\r\n return new Promise((resolve) => {\r\n const image = new window.Image()\r\n image.addEventListener('load', () => resolve(image))\r\n image.addEventListener('error', () => resolve(null))\r\n image.src = url\r\n })\r\n}\r\n\r\nfunction renderImage(\r\n canvas: HTMLCanvasElement,\r\n context: CanvasRenderingContext2D,\r\n image: HTMLImageElement,\r\n layer: Layer,\r\n timestamp?: number,\r\n) {\r\n if (!image || !layer || !layer?.pos) return 0\r\n const cardWidth = image.width / layer.columns\r\n const cardHeight = image.height / layer.rows\r\n const canvasStyle = canvas.style\r\n\r\n if (layer.order === 0) {\r\n canvas.width = cardWidth\r\n canvas.height = cardHeight\r\n canvasStyle.width = `${cardWidth}px`\r\n canvasStyle.height = `${cardHeight}px`\r\n }\r\n\r\n canvasStyle.imageRendering = 'pixelated'\r\n context.imageSmoothingEnabled = true\r\n\r\n context.save()\r\n\r\n if (layer.animated && timestamp) {\r\n const elapsed = timestamp\r\n const yOffset = Math.sin(elapsed / 1000) * 3\r\n const xOffset = Math.sin(elapsed / 1500) * 1.5\r\n context.globalAlpha = 0.65 + (Math.sin(elapsed / 2000) + 1) * 0.075\r\n context.translate(xOffset, yOffset)\r\n }\r\n\r\n context.drawImage(image, layer.pos.x * cardWidth, layer.pos.y * cardHeight, cardWidth, cardHeight, 0, 0, canvas.width, canvas.height)\r\n context.restore()\r\n\r\n return cardWidth / cardHeight\r\n}\r\n\r\n/**\r\n * Sway animation for Balatro-style UI elements.\r\n */\r\nexport function useSway(active: boolean) {\r\n const ref = useRef<HTMLDivElement>(null)\r\n\r\n useEffect(() => {\r\n if (!active || !ref.current) return\r\n let frame: number\r\n const start = Date.now()\r\n const el = ref.current\r\n const tick = () => {\r\n const t = ((Date.now() - start) % JIMBO_ANIMATIONS.SWAY_DURATION) / JIMBO_ANIMATIONS.SWAY_DURATION * Math.PI * 2\r\n el.style.transform = `translate(${Math.sin(t) * JIMBO_ANIMATIONS.SWAY_AMOUNT * 0.3}px, ${Math.sin(t * 0.8) * JIMBO_ANIMATIONS.SWAY_AMOUNT}px)`\r\n frame = requestAnimationFrame(tick)\r\n }\r\n frame = requestAnimationFrame(tick)\r\n return () => {\r\n cancelAnimationFrame(frame)\r\n if (el) el.style.transform = ''\r\n }\r\n }, [active])\r\n\r\n return ref\r\n}\r\n\r\n/**\r\n * Handles delayed visibility for transitions (e.g. modals).\r\n */\r\nexport function useDelayedVisibility(open: boolean, delay: number) {\r\n const [visible, setVisible] = useState(open)\r\n const [opacity, setOpacity] = useState(open ? 1 : 0)\r\n const [prevOpen, setPrevOpen] = useState(open)\r\n\r\n if (open !== prevOpen) {\r\n setPrevOpen(open)\r\n if (open) {\r\n setVisible(true)\r\n } else {\r\n setOpacity(0)\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n if (open) {\r\n const frame = requestAnimationFrame(() => setOpacity(1))\r\n return () => cancelAnimationFrame(frame)\r\n } else {\r\n const t = setTimeout(() => setVisible(false), delay)\r\n return () => clearTimeout(t)\r\n }\r\n }, [open, delay])\r\n\r\n return { visible, opacity }\r\n}\r\n\r\n/**\r\n * Hook for the Balatro hypnotic swirl background.\r\n * Manages WebGL context, shader compilation, and animation loop.\r\n */\r\nexport function useBalatroBackground() {\r\n const canvasRef = useRef<HTMLCanvasElement>(null)\r\n\r\n useEffect(() => {\r\n const canvas = canvasRef.current\r\n if (!canvas) return\r\n\r\n const gl = canvas.getContext('webgl')\r\n if (!gl) return\r\n\r\n const vsSource = `\r\n attribute vec2 position;\r\n void main() {\r\n gl_Position = vec4(position, 0.0, 1.0);\r\n }\r\n `\r\n\r\n const fsSource = `\r\n precision mediump float;\r\n\r\n uniform float u_time;\r\n uniform vec2 u_resolution;\r\n\r\n const float SPIN_ROTATION = -2.0;\r\n const float SPIN_SPEED = 4.5;\r\n const vec4 COLOUR_1 = vec4(1.0, 0.2, 0.2, 1.0);\r\n const vec4 COLOUR_2 = vec4(0.0, 0.5, 1.0, 1.0);\r\n const vec4 COLOUR_3 = vec4(0.05, 0.08, 0.1, 1.0);\r\n const float CONTRAST = 4.5;\r\n const float LIGTHING = 0.5;\r\n const float SPIN_AMOUNT = 0.35;\r\n const float PIXEL_FILTER = 1024.0;\r\n const float PI = 3.14159265359;\r\n\r\n void main() {\r\n vec2 screenSize = u_resolution;\r\n float pixel_size = length(screenSize.xy) / PIXEL_FILTER;\r\n vec2 uv = (floor(gl_FragCoord.xy*(1.0/pixel_size))*pixel_size - 0.5*screenSize.xy)/length(screenSize.xy);\r\n float uv_len = length(uv);\r\n\r\n float speed = (SPIN_ROTATION * 0.2) + 302.2;\r\n float new_pixel_angle = atan(uv.y, uv.x) + speed - 20.0*(1.0*SPIN_AMOUNT*uv_len + (1.0 - 1.0*SPIN_AMOUNT));\r\n\r\n vec2 mid = (screenSize.xy/length(screenSize.xy))/2.0;\r\n uv = (vec2((uv_len * cos(new_pixel_angle) + mid.x), (uv_len * sin(new_pixel_angle) + mid.y)) - mid);\r\n\r\n uv *= 30.0;\r\n speed = u_time * SPIN_SPEED;\r\n vec2 uv2 = vec2(uv.x, uv.y);\r\n\r\n for(int i=0; i < 5; i++) {\r\n uv2 += sin(max(uv.x, uv.y)) + uv;\r\n uv += 0.5*vec2(cos(5.1123314 + 0.353*uv2.y + speed*0.131121), sin(uv2.x - 0.113*speed));\r\n uv -= 1.0*cos(uv.x + uv.y) - 1.0*sin(uv.x*0.711 - uv.y);\r\n }\r\n\r\n float contrast_mod = (0.25*CONTRAST + 0.5*SPIN_AMOUNT + 1.2);\r\n float paint_res = min(2.0, max(0.0, length(uv)*(0.035)*contrast_mod));\r\n float c1p = max(0.0, 1.0 - contrast_mod*abs(1.0 - paint_res));\r\n float c2p = max(0.0, 1.0 - contrast_mod*abs(paint_res));\r\n float c3p = 1.0 - min(1.0, c1p + c2p);\r\n float light = (LIGTHING - 0.2)*max(c1p*5.0 - 4.0, 0.0) + LIGTHING*max(c2p*5.0 - 4.0, 0.0);\r\n\r\n vec4 finalCol = (0.3/CONTRAST)*COLOUR_1 + (1.0 - 0.3/CONTRAST)*(COLOUR_1*c1p + COLOUR_2*c2p + vec4(c3p*COLOUR_3.rgb, c3p*COLOUR_1.a)) + light;\r\n\r\n gl_FragColor = finalCol;\r\n }\r\n `\r\n\r\n const createShader = (type: number, source: string) => {\r\n const shader = gl.createShader(type)\r\n if (!shader) return null\r\n gl.shaderSource(shader, source)\r\n gl.compileShader(shader)\r\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\r\n console.error('[JimboBackground] shader compile error:', gl.getShaderInfoLog(shader))\r\n gl.deleteShader(shader)\r\n return null\r\n }\r\n return shader\r\n }\r\n\r\n const vertexShader = createShader(gl.VERTEX_SHADER, vsSource)\r\n const fragmentShader = createShader(gl.FRAGMENT_SHADER, fsSource)\r\n if (!vertexShader || !fragmentShader) return\r\n\r\n const program = gl.createProgram()\r\n if (!program) return\r\n gl.attachShader(program, vertexShader)\r\n gl.attachShader(program, fragmentShader)\r\n gl.linkProgram(program)\r\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\r\n console.error('[JimboBackground] program link error:', gl.getProgramInfoLog(program))\r\n return\r\n }\r\n\r\n gl.useProgram(program)\r\n\r\n const positionBuffer = gl.createBuffer()\r\n gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)\r\n gl.bufferData(\r\n gl.ARRAY_BUFFER,\r\n new Float32Array([\r\n -1.0, -1.0, 1.0, -1.0, -1.0, 1.0,\r\n -1.0, 1.0, 1.0, -1.0, 1.0, 1.0,\r\n ]),\r\n gl.STATIC_DRAW,\r\n )\r\n\r\n const positionLocation = gl.getAttribLocation(program, 'position')\r\n gl.enableVertexAttribArray(positionLocation)\r\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0)\r\n\r\n const timeLocation = gl.getUniformLocation(program, 'u_time')\r\n const resolutionLocation = gl.getUniformLocation(program, 'u_resolution')\r\n\r\n const startTime = Date.now()\r\n let animationFrameId: number\r\n\r\n const render = () => {\r\n const displayWidth = canvas.clientWidth\r\n const displayHeight = canvas.clientHeight\r\n if (canvas.width !== displayWidth || canvas.height !== displayHeight) {\r\n canvas.width = displayWidth\r\n canvas.height = displayHeight\r\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight)\r\n }\r\n\r\n const currentTime = (Date.now() - startTime) / 1000.0\r\n gl.uniform1f(timeLocation, currentTime)\r\n gl.uniform2f(resolutionLocation, canvas.width, canvas.height)\r\n\r\n gl.drawArrays(gl.TRIANGLES, 0, 6)\r\n animationFrameId = requestAnimationFrame(render)\r\n }\r\n\r\n render()\r\n\r\n return () => {\r\n cancelAnimationFrame(animationFrameId)\r\n gl.deleteProgram(program)\r\n gl.deleteShader(vertexShader)\r\n gl.deleteShader(fragmentShader)\r\n gl.deleteBuffer(positionBuffer)\r\n }\r\n }, [])\r\n\r\n return canvasRef\r\n}\r\n\r\nexport type JimboTooltipMode = 'snap' | 'mouse'\r\nexport type JimboTooltipPlacement = 'top' | 'bottom' | 'auto'\r\n\r\n/**\r\n * Hook for managing JimboTooltip state and positioning.\r\n */\r\nexport function useJimboTooltip({\r\n mode = 'snap',\r\n placement = 'auto',\r\n delay = 80,\r\n disabled = false,\r\n}: {\r\n mode?: JimboTooltipMode\r\n placement?: JimboTooltipPlacement\r\n delay?: number\r\n disabled?: boolean\r\n}) {\r\n const [visible, setVisible] = useState(false)\r\n const [pos, setPos] = useState<{ left: number; top: number; align: 'top' | 'bottom' } | null>(null)\r\n const targetRef = useRef<HTMLElement | null>(null)\r\n const tooltipRef = useRef<HTMLDivElement | null>(null)\r\n const delayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\r\n\r\n const show = useCallback(() => {\r\n if (disabled) return\r\n if (delayTimerRef.current) clearTimeout(delayTimerRef.current)\r\n delayTimerRef.current = setTimeout(() => setVisible(true), delay)\r\n }, [disabled, delay])\r\n\r\n const hide = useCallback(() => {\r\n if (delayTimerRef.current) clearTimeout(delayTimerRef.current)\r\n setVisible(false)\r\n setPos(null)\r\n }, [])\r\n\r\n const computeSnapPos = useCallback(() => {\r\n const el = targetRef.current\r\n const tip = tooltipRef.current\r\n if (!el || !tip) return\r\n const rect = el.getBoundingClientRect()\r\n const tipRect = tip.getBoundingClientRect()\r\n const roomAbove = rect.top\r\n const align: 'top' | 'bottom' =\r\n placement === 'top' ? 'top'\r\n : placement === 'bottom' ? 'bottom'\r\n : roomAbove >= tipRect.height + 12 ? 'top' : 'bottom'\r\n\r\n const left = rect.left + rect.width / 2 - tipRect.width / 2\r\n const top = align === 'top' ? rect.top - tipRect.height - 8 : rect.bottom + 8\r\n setPos({\r\n left: Math.max(8, Math.min(window.innerWidth - tipRect.width - 8, left)),\r\n top,\r\n align\r\n })\r\n }, [placement])\r\n\r\n useEffect(() => {\r\n if (!visible || mode !== 'snap') return\r\n const raf = requestAnimationFrame(computeSnapPos)\r\n window.addEventListener('resize', computeSnapPos)\r\n window.addEventListener('scroll', computeSnapPos, true)\r\n return () => {\r\n cancelAnimationFrame(raf)\r\n window.removeEventListener('resize', computeSnapPos)\r\n window.removeEventListener('scroll', computeSnapPos, true)\r\n }\r\n }, [visible, mode, computeSnapPos])\r\n\r\n useEffect(() => () => {\r\n if (delayTimerRef.current) clearTimeout(delayTimerRef.current)\r\n }, [])\r\n\r\n const handleMouseMove = useCallback((e: React.MouseEvent | React.PointerEvent) => {\r\n if (mode !== 'mouse') return\r\n setPos({ left: e.clientX + 12, top: e.clientY + 16, align: 'bottom' })\r\n }, [mode])\r\n\r\n return {\r\n visible,\r\n pos,\r\n targetRef,\r\n tooltipRef,\r\n show,\r\n hide,\r\n handleMouseMove,\r\n }\r\n}\r\n\r\n/**\r\n * Hook for managing the JamlCardRenderer logic.\r\n */\r\nexport function useJamlCardRenderer({\r\n layers,\r\n invert = false,\r\n hoverTilt = false,\r\n}: {\r\n layers: Layer[]\r\n invert?: boolean\r\n hoverTilt?: boolean\r\n}) {\r\n const canvasRef = useRef<HTMLCanvasElement>(null)\r\n const imageCacheRef = useRef<Map<string, HTMLImageElement>>(new Map())\r\n const [ratio, setRatio] = useState(3 / 4)\r\n const [, forceUpdate] = useState(0)\r\n const animationFrameRef = useRef<number | null>(null)\r\n const [elapsed, setElapsed] = useState(0)\r\n const [isHovered, setIsHovered] = useState(false)\r\n const [transform, setTransform] = useState('none')\r\n\r\n const hasAnimatedLayer = layers?.some((layer) => layer.animated)\r\n\r\n // Preload all known sheets once\r\n useEffect(() => {\r\n let cancelled = false\r\n const imageCache = imageCacheRef.current\r\n const preload = async () => {\r\n const urls = Array.from(new Set(Object.values(SPRITE_SHEETS).map((sheet) => sheet.src)))\r\n const images = await Promise.all(urls.map((url) => loadImage(url)))\r\n if (cancelled) return\r\n images.forEach((image, index) => {\r\n if (image) imageCache.set(urls[index], image)\r\n })\r\n forceUpdate((prev) => prev + 1)\r\n }\r\n\r\n preload().catch((err) => console.error('[JamlCardRenderer]', err))\r\n\r\n return () => {\r\n cancelled = true\r\n imageCache.clear()\r\n }\r\n }, [])\r\n\r\n // Animation loop for animated layers\r\n useEffect(() => {\r\n if (!hasAnimatedLayer) return\r\n\r\n let startTime: number\r\n const animate = (timestamp: number) => {\r\n if (!startTime) startTime = timestamp\r\n const now = timestamp - startTime\r\n if (!animationFrameRef.current || timestamp - 100 > animationFrameRef.current) {\r\n animationFrameRef.current = timestamp\r\n setElapsed(now)\r\n }\r\n animationFrameRef.current = requestAnimationFrame(animate)\r\n }\r\n\r\n animationFrameRef.current = requestAnimationFrame(animate)\r\n return () => {\r\n if (animationFrameRef.current) cancelAnimationFrame(animationFrameRef.current)\r\n }\r\n }, [hasAnimatedLayer])\r\n\r\n // Core drawing logic\r\n useEffect(() => {\r\n const canvas = canvasRef.current\r\n if (!canvas || !layers || layers.length === 0) return\r\n const context = canvas.getContext('2d')\r\n if (!context) return\r\n let cancelled = false\r\n\r\n context.clearRect(0, 0, canvas.width, canvas.height)\r\n ;[...layers]\r\n .sort((a, b) => a.order - b.order)\r\n .forEach((layer) => {\r\n if (imageCacheRef.current.has(layer.source)) {\r\n const image = imageCacheRef.current.get(layer.source)\r\n if (!image) return\r\n const imageRatio = renderImage(canvas, context, image, layer, hasAnimatedLayer ? elapsed : undefined)\r\n if (layer.order === 0) setRatio(imageRatio)\r\n return\r\n }\r\n loadImage(layer.source).then((img) => {\r\n if (cancelled || !img) return\r\n const imageRatio = renderImage(canvas, context, img, layer, hasAnimatedLayer ? elapsed : undefined)\r\n imageCacheRef.current.set(layer.source, img)\r\n if (layer.order === 0) setRatio(imageRatio)\r\n forceUpdate((prev) => prev + 1)\r\n })\r\n })\r\n\r\n canvas.style.filter = invert ? 'invert(0.94)' : 'none'\r\n return () => { cancelled = true }\r\n }, [layers, elapsed, invert, hasAnimatedLayer])\r\n\r\n const onPointerEnter = (event: React.PointerEvent) => {\r\n if (!hoverTilt || event.pointerType === 'touch') return\r\n setIsHovered(true)\r\n }\r\n\r\n const onPointerLeave = () => {\r\n if (!hoverTilt) return\r\n setIsHovered(false)\r\n setTransform('none')\r\n }\r\n\r\n const onPointerMove = (event: React.PointerEvent<HTMLDivElement>) => {\r\n if (!hoverTilt || event.pointerType === 'touch') return\r\n const rect = event.currentTarget.getBoundingClientRect()\r\n const x = event.clientX - rect.left\r\n const y = event.clientY - rect.top\r\n const rotateY = (x / rect.width) * 12 - 6\r\n const rotateX = (y / rect.height) * -16 + 8\r\n const juiceScale = 1.05\r\n const juiceY = -2 // slight move up\r\n setTransform(`perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(${juiceScale}) translateY(${juiceY}px)`)\r\n }\r\n\r\n const containerStyle: React.CSSProperties = {\r\n aspectRatio: String(ratio),\r\n width: '100%',\r\n display: 'flex',\r\n perspective: hoverTilt ? '1000px' : undefined,\r\n userSelect: 'none',\r\n WebkitUserSelect: 'none',\r\n }\r\n\r\n const canvasStyle: React.CSSProperties = {\r\n transition: hoverTilt && !isHovered ? 'transform 0.4s ease, box-shadow 0.4s ease-out' : 'transform 0.1s ease-out',\r\n transform: hoverTilt ? (isHovered ? transform : 'none') : undefined,\r\n transformStyle: hoverTilt ? 'preserve-3d' : undefined,\r\n transformOrigin: hoverTilt ? 'center center' : undefined,\r\n borderRadius: '6px',\r\n boxShadow: hoverTilt && isHovered ? '0 2px 12px rgba(0,0,0,0.3)' : '0 2px 8px rgba(0,0,0,0.2)',\r\n imageRendering: 'pixelated',\r\n pointerEvents: 'none',\r\n }\r\n\r\n return {\r\n canvasRef,\r\n containerStyle,\r\n canvasStyle,\r\n handlers: {\r\n onPointerEnter: hoverTilt ? onPointerEnter : undefined,\r\n onPointerLeave: hoverTilt ? onPointerLeave : undefined,\r\n onPointerMove: hoverTilt ? onPointerMove : undefined,\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Tracks which 'ante' section is currently most visible in a scrollable container.\r\n * Used in JamlAnalyzerFullscreen and AnalyzerExplorer.\r\n */\r\nexport function useAnteTracker(antes: { ante: number }[], options: { threshold?: number[] } = {}) {\r\n const [currentAnte, setCurrentAnte] = useState(antes[0]?.ante ?? 0)\r\n const [prevFirstAnte, setPrevFirstAnte] = useState(antes[0]?.ante)\r\n const scrollRef = useRef<HTMLDivElement>(null)\r\n const anteRefs = useRef<Map<number, HTMLElement>>(new Map())\r\n\r\n if (antes[0]?.ante !== prevFirstAnte) {\r\n setPrevFirstAnte(antes[0]?.ante)\r\n if (antes.length > 0) {\r\n setCurrentAnte(antes[0].ante)\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n const root = scrollRef.current\r\n if (!root || antes.length === 0) return\r\n\r\n const observer = new IntersectionObserver(\r\n (entries) => {\r\n // Find the entry with the highest intersection ratio\r\n const mostVisible = entries\r\n .filter((e) => e.isIntersecting)\r\n .sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0]\r\n\r\n if (mostVisible) {\r\n const ante = Number((mostVisible.target as HTMLElement).dataset.ante)\r\n if (!Number.isNaN(ante)) {\r\n setCurrentAnte(ante)\r\n }\r\n }\r\n },\r\n {\r\n root,\r\n threshold: options.threshold ?? [0.4, 0.6, 0.8],\r\n }\r\n )\r\n\r\n anteRefs.current.forEach((el) => observer.observe(el))\r\n\r\n return () => observer.disconnect()\r\n }, [antes, options.threshold])\r\n\r\n const scrollToAnte = useCallback((ante: number) => {\r\n const el = anteRefs.current.get(ante)\r\n if (el) {\r\n el.scrollIntoView({ behavior: 'smooth', block: 'start' })\r\n }\r\n }, [])\r\n\r\n const registerAnteRef = useCallback((ante: number, el: HTMLElement | null) => {\r\n if (el) {\r\n anteRefs.current.set(ante, el)\r\n } else {\r\n anteRefs.current.delete(ante)\r\n }\r\n }, [])\r\n\r\n return {\r\n currentAnte,\r\n scrollRef,\r\n scrollToAnte,\r\n registerAnteRef,\r\n }\r\n}\r\n\r\nexport interface DragState {\r\n clause: JamlVisualClause\r\n fromZone: JamlZone\r\n x: number\r\n y: number\r\n offX: number\r\n offY: number\r\n}\r\n\r\ninterface PendingDragState {\r\n clause: JamlVisualClause\r\n fromZone: JamlZone\r\n x: number\r\n y: number\r\n offX: number\r\n offY: number\r\n}\r\n\r\n/**\r\n * Manages drag-and-drop state for the Jaml IDE visual filter editor.\r\n */\r\nexport function useJamlIdeDrag(\r\n filter: JamlVisualFilter,\r\n onChange: (filter: JamlVisualFilter) => void,\r\n rootRef: React.RefObject<HTMLDivElement | null>\r\n) {\r\n const [drag, setDrag] = useState<DragState | null>(null)\r\n const [pendingDrag, setPendingDrag] = useState<PendingDragState | null>(null)\r\n const [hoverZone, setHoverZone] = useState<string | null>(null)\r\n\r\n const onDragStart = useCallback(\r\n (e: React.MouseEvent | React.TouchEvent, clause: JamlVisualClause, fromZone: JamlZone) => {\r\n const t = 'touches' in e ? e.touches[0] : e\r\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\r\n setPendingDrag({\r\n clause,\r\n fromZone,\r\n x: t.clientX,\r\n y: t.clientY,\r\n offX: t.clientX - rect.left,\r\n offY: t.clientY - rect.top,\r\n })\r\n setHoverZone(null)\r\n },\r\n []\r\n )\r\n\r\n useEffect(() => {\r\n if (!pendingDrag && !drag) return\r\n\r\n const move = (e: MouseEvent | TouchEvent) => {\r\n const touchEvent = 'touches' in e ? (e as TouchEvent) : null\r\n const t = touchEvent ? touchEvent.touches[0] : (e as MouseEvent)\r\n if (!t) return\r\n\r\n let activeDrag = drag\r\n\r\n if (!activeDrag && pendingDrag) {\r\n const dx = t.clientX - pendingDrag.x\r\n const dy = t.clientY - pendingDrag.y\r\n if (Math.hypot(dx, dy) < 8) return\r\n activeDrag = {\r\n ...pendingDrag,\r\n x: t.clientX,\r\n y: t.clientY,\r\n }\r\n setPendingDrag(null)\r\n setDrag(activeDrag)\r\n } else if (activeDrag) {\r\n activeDrag = { ...activeDrag, x: t.clientX, y: t.clientY }\r\n setDrag(activeDrag)\r\n }\r\n\r\n if (!activeDrag) return\r\n if (touchEvent?.cancelable) touchEvent.preventDefault()\r\n\r\n const rails = rootRef.current?.querySelectorAll('[data-zone]') ?? []\r\n let found: string | null = null\r\n for (const r of rails) {\r\n const rc = r.getBoundingClientRect()\r\n if (t.clientX >= rc.left && t.clientX <= rc.right && t.clientY >= rc.top && t.clientY <= rc.bottom) {\r\n found = r.getAttribute('data-zone')\r\n break\r\n }\r\n }\r\n setHoverZone(found)\r\n }\r\n\r\n const up = () => {\r\n if (drag && hoverZone && hoverZone !== drag.fromZone) {\r\n const to = hoverZone as JamlZone\r\n onChange({\r\n ...filter,\r\n [drag.fromZone]: filter[drag.fromZone].filter((c) => c.id !== drag.clause.id),\r\n [to]: [...filter[to], { ...drag.clause }],\r\n })\r\n }\r\n setPendingDrag(null)\r\n setDrag(null)\r\n setHoverZone(null)\r\n }\r\n\r\n window.addEventListener('mousemove', move)\r\n window.addEventListener('mouseup', up)\r\n window.addEventListener('touchmove', move, { passive: false })\r\n window.addEventListener('touchend', up)\r\n\r\n return () => {\r\n window.removeEventListener('mousemove', move)\r\n window.removeEventListener('mouseup', up)\r\n window.removeEventListener('touchmove', move)\r\n window.removeEventListener('touchend', up)\r\n }\r\n }, [pendingDrag, drag, hoverZone, filter, onChange, rootRef])\r\n\r\n return {\r\n drag,\r\n hoverZone,\r\n onDragStart,\r\n }\r\n}\r\n\r\n/**\r\n * Provides a magnetic 3D tilt effect for DOM elements, replicating the 'juice' of Balatro cards.\r\n * Ensures the hit-detection area remains stable by separating container events from the transformed style.\r\n */\r\nexport function useDOMMagneticTilt(enabled: boolean = true) {\r\n const [isHovered, setIsHovered] = useState(false)\r\n const [transform, setTransform] = useState('none')\r\n\r\n const onPointerEnter = (event: React.PointerEvent) => {\r\n if (!enabled || event.pointerType === 'touch') return\r\n setIsHovered(true)\r\n }\r\n\r\n const onPointerLeave = () => {\r\n if (!enabled) return\r\n setIsHovered(false)\r\n setTransform('none')\r\n }\r\n\r\n const onPointerMove = (event: React.PointerEvent) => {\r\n if (!enabled || event.pointerType === 'touch') return\r\n const rect = event.currentTarget.getBoundingClientRect()\r\n const x = event.clientX - rect.left\r\n const y = event.clientY - rect.top\r\n const rotateY = (x / rect.width) * 12 - 6\r\n const rotateX = (y / rect.height) * -16 + 8\r\n const juiceScale = 1.05\r\n const juiceY = -2 // slight move up\r\n setTransform(`perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(${juiceScale}) translateY(${juiceY}px)`)\r\n }\r\n\r\n const handlers = {\r\n onPointerEnter: enabled ? onPointerEnter : undefined,\r\n onPointerLeave: enabled ? onPointerLeave : undefined,\r\n onPointerMove: enabled ? onPointerMove : undefined,\r\n }\r\n\r\n const tiltStyle: React.CSSProperties = {\r\n transition: enabled && !isHovered ? 'transform 0.4s ease, box-shadow 0.4s ease-out' : 'transform 0.1s ease-out',\r\n transform: enabled ? (isHovered ? transform : 'none') : undefined,\r\n transformStyle: enabled ? 'preserve-3d' : undefined,\r\n transformOrigin: enabled ? 'center center' : undefined,\r\n willChange: enabled ? 'transform' : undefined,\r\n pointerEvents: enabled ? 'none' : undefined,\r\n }\r\n\r\n return { handlers, tiltStyle, isHovered }\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\nimport { resolveJamlAssetUrl } from '../assets.js'\r\nimport { getSpriteData, getMysterySprite, SHEET_META, type SpriteSheetType } from '../sprites/spriteMapper.js'\r\n\r\nexport interface JimboSpriteProps {\r\n name: string\r\n sheet?: SpriteSheetType\r\n width?: number\r\n height?: number\r\n style?: React.CSSProperties\r\n}\r\n\r\nexport function JimboSprite({ name, sheet, width = 40, height, style }: JimboSpriteProps) {\r\n const sprite = getSpriteData(name)\r\n const resolvedSheet: SpriteSheetType = sheet ?? sprite?.type ?? 'Jokers'\r\n const meta = SHEET_META[resolvedSheet]\r\n const mystery = getMysterySprite(resolvedSheet)\r\n const pos = sprite?.pos ?? mystery.pos\r\n \r\n let defaultH = width;\r\n if ([\"Jokers\", \"Tarots\", \"Vouchers\", \"Boosters\", \"Decks\", \"Enhancers\", \"Editions\"].includes(resolvedSheet)) {\r\n defaultH = Math.round((width * 95) / 71);\r\n }\r\n const h = height ?? defaultH;\r\n\r\n if (!meta) return null\r\n\r\n const bgW = width * meta.cols\r\n const bgH = h * meta.rows\r\n const bgX = -(pos.x * width)\r\n const bgY = -(pos.y * h)\r\n\r\n return (\r\n <div style={{\r\n width, height: h, flexShrink: 0,\r\n backgroundImage: `url(${resolveJamlAssetUrl(meta.assetKey)})`,\r\n backgroundSize: `${bgW}px ${bgH}px`,\r\n backgroundPosition: `${bgX}px ${bgY}px`,\r\n backgroundRepeat: 'no-repeat',\r\n imageRendering: 'pixelated',\r\n ...style,\r\n }} />\r\n )\r\n}\r\n\r\nexport interface StakeSpriteProps {\r\n stake: string\r\n width?: number\r\n height?: number\r\n style?: React.CSSProperties\r\n}\r\n\r\nconst STAKE_MAP: string[] = [\"White\", \"Red\", \"Green\", \"Black\", \"Blue\", \"Purple\", \"Orange\", \"Gold\"]\r\n\r\nexport function StakeSprite({ stake, width = 29, height, style }: StakeSpriteProps) {\r\n const index = STAKE_MAP.indexOf(stake.replace(\" Stake\", \"\"))\r\n const idx = index >= 0 ? index : 0\r\n const x = idx % 5\r\n const y = Math.floor(idx / 5)\r\n const h = height ?? width\r\n const bgW = width * 5\r\n const bgH = h * 2\r\n\r\n return (\r\n <div style={{\r\n width, height: h, flexShrink: 0,\r\n backgroundImage: `url(${resolveJamlAssetUrl('stakes')})`,\r\n backgroundSize: `${bgW}px ${bgH}px`,\r\n backgroundPosition: `-${x * width}px -${y * h}px`,\r\n backgroundRepeat: 'no-repeat',\r\n imageRendering: 'pixelated',\r\n ...style,\r\n }} />\r\n )\r\n}\r\n\r\nexport interface DeckSpriteProps {\r\n deck: string\r\n width?: number\r\n height?: number\r\n style?: React.CSSProperties\r\n}\r\n\r\nconst DECK_ROWS: Record<string, number> = {\r\n Red: 0,\r\n Blue: 1,\r\n Yellow: 2,\r\n Green: 3,\r\n Black: 0,\r\n Magic: 1,\r\n Nebula: 2,\r\n Ghost: 3,\r\n}\r\n\r\nexport function DeckSprite({ deck, width = 71, height, style }: DeckSpriteProps) {\r\n const baseDeck = deck.replace(\" Deck\", \"\")\r\n const y = DECK_ROWS[baseDeck] ?? 0\r\n const x = 12\r\n const h = height ?? (width * 95 / 71)\r\n const bgW = width * 13\r\n const bgH = h * 4\r\n\r\n return (\r\n <div style={{\r\n width, height: h, flexShrink: 0,\r\n backgroundImage: `url(${resolveJamlAssetUrl('deck')})`,\r\n backgroundSize: `${bgW}px ${bgH}px`,\r\n backgroundPosition: `-${x * width}px -${y * h}px`,\r\n backgroundRepeat: 'no-repeat',\r\n imageRendering: 'pixelated',\r\n ...style,\r\n }} />\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\n\r\nexport type JimboTextTone =\r\n | 'default'\r\n | 'mult'\r\n | 'chips'\r\n | 'gold'\r\n | 'green'\r\n | 'red'\r\n | 'blue'\r\n | 'orange'\r\n | 'purple'\r\n | 'grey'\r\n | 'white'\r\n\r\nexport type JimboTextSize = 'micro' | 'label' | 'xs' | 'body' | 'sm' | 'md' | 'heading' | 'lg' | 'xl' | 'display'\r\n\r\nexport interface JimboTextProps extends React.HTMLAttributes<HTMLElement> {\r\n tone?: JimboTextTone\r\n size?: JimboTextSize\r\n /** Canonical Balatro drop shadow (1px right, 1px down, ${BLACK}cc). Default true. */\r\n shadow?: boolean\r\n /** Uppercase + spacing — Balatro button/pill label treatment. Default false. */\r\n uppercase?: boolean\r\n /** Wiggle effect for text characters. Default false. */\r\n dance?: boolean\r\n /** Letter-spacing override; defaults depend on uppercase prop. */\r\n letterSpacing?: number | string\r\n as?: 'span' | 'p' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label'\r\n children?: React.ReactNode\r\n}\r\n\r\n/**\r\n * Canonical pixel-font text wrapper. Uses `m6x11plus` as its family and\r\n * applies the authentic Balatro drop shadow by default. Prefer this over\r\n * hand-rolling `fontFamily: 'm6x11plus, monospace'` + `textShadow` strings\r\n * throughout consumers — it keeps the styling drift-free.\r\n *\r\n * Requires `import 'jaml-ui/fonts.css'` somewhere in the consumer bundle\r\n * so the @font-face declaration lands (font is base64-embedded, no\r\n * runtime fetch).\r\n */\r\nexport function JimboText({\r\n tone = 'default',\r\n size = 'md',\r\n shadow = true,\r\n uppercase = false,\r\n dance = false,\r\n letterSpacing,\r\n as: Tag = 'span',\r\n className = '',\r\n style,\r\n children,\r\n ...rest\r\n}: JimboTextProps) {\r\n const sizeClass = `j-text--${size}`\r\n const toneClass = `j-text--${tone}`\r\n const shadowClass = shadow ? '' : 'j-text--no-shadow'\r\n const upperClass = uppercase ? 'j-text--upper' : ''\r\n const danceClass = dance ? 'j-text--dance-container' : ''\r\n\r\n const inlineStyle: React.CSSProperties = {}\r\n if (letterSpacing != null) {\r\n inlineStyle.letterSpacing = letterSpacing\r\n } else if (uppercase && letterSpacing == null) {\r\n inlineStyle.letterSpacing = 2\r\n }\r\n if (style) Object.assign(inlineStyle, style)\r\n\r\n let content = children\r\n if (dance && typeof children === 'string') {\r\n content = children.split('').map((char, i) => (\r\n <span\r\n key={i}\r\n className=\"j-font-dance-char\"\r\n style={{ animationDelay: `${i * -0.15}s` }}\r\n >\r\n {char === ' ' ? '\\u00A0' : char}\r\n </span>\r\n ))\r\n }\r\n\r\n return (\r\n <Tag\r\n className={`j-text ${sizeClass} ${toneClass} ${shadowClass} ${upperClass} ${danceClass} ${className}`.trim()}\r\n style={Object.keys(inlineStyle).length > 0 ? inlineStyle : undefined}\r\n {...rest}\r\n >\r\n {content}\r\n </Tag>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React, { memo } from 'react'\r\nimport { useSway } from './hooks.js'\r\nimport { JimboText, type JimboTextSize } from './jimboText.js'\r\n\r\n// ─── Panel ───────────────────────────────────────────────────────────────────\r\n\r\nexport interface JimboPanelProps extends React.HTMLAttributes<HTMLDivElement> {\r\n sway?: boolean\r\n onBack?: () => void\r\n hideBack?: boolean\r\n}\r\nexport const JimboPanel = memo(({\r\n children, className = '', sway = false, onBack, hideBack = false, style, ...props\r\n}: JimboPanelProps) => {\r\n const panelRef = useSway(sway)\r\n\r\n return (\r\n <div\r\n ref={panelRef}\r\n className={`j-panel ${className}`}\r\n style={style}\r\n {...props}\r\n >\r\n <div className=\"j-panel__body\">{children}</div>\r\n {onBack && !hideBack && (\r\n <div className=\"j-panel__back\">\r\n <JimboBackButton onClick={onBack} />\r\n </div>\r\n )}\r\n </div>\r\n )\r\n})\r\nJimboPanel.displayName = 'JimboPanel'\r\n\r\nexport type JimboInnerPanelProps = React.HTMLAttributes<HTMLDivElement>;\r\n\r\nexport const JimboInnerPanel = memo(({ children, className = '', style, ...props }: JimboInnerPanelProps) => (\r\n <div\r\n className={`j-inner-panel ${className}`}\r\n style={style}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n))\r\nJimboInnerPanel.displayName = 'JimboInnerPanel'\r\n\r\n// ─── JimboButton ──────────────────────────────────────────────────────────────\r\n// Canonical flat 2D Balatro-style button.\r\n// Tones are purely CSS-driven via j-btn--{tone} classes in jimbo.css.\r\n// No JS color maps. No TONE_PAIRS. Respect the design tokens.\r\n\r\nexport type JimboTone = 'orange' | 'red' | 'blue' | 'green' | 'tarot' | 'planet' | 'spectral' | 'grey'\r\n\r\nexport interface JimboButtonProps {\r\n tone?: JimboTone\r\n size?: 'xs' | 'sm' | 'md' | 'lg'\r\n fullWidth?: boolean\r\n disabled?: boolean\r\n uppercase?: boolean\r\n onClick?: () => void\r\n style?: React.CSSProperties\r\n className?: string\r\n children?: React.ReactNode\r\n}\r\n\r\nexport function JimboButton({\r\n tone = 'orange', size = 'md', fullWidth = false, disabled = false, uppercase = false, onClick, style, className = '', children,\r\n}: JimboButtonProps) {\r\n const textSize: JimboTextSize = size === 'xs' ? 'xs' : size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'md'\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className={`j-btn j-btn--${tone} j-btn--${size} ${fullWidth ? 'j-btn--full' : ''} ${disabled ? 'j-btn--disabled' : ''} ${className}`}\r\n disabled={disabled}\r\n onClick={onClick}\r\n style={style}\r\n >\r\n <div className=\"j-btn__face\">\r\n <JimboText size={textSize} uppercase={uppercase}>{children}</JimboText>\r\n </div>\r\n </button>\r\n )\r\n}\r\n\r\nexport function JimboBackButton({ onClick }: { onClick?: () => void }) {\r\n return (\r\n <div className=\"j-flex j-justify-center j-w-full\" style={{ padding: '4px 0' }}>\r\n <JimboButton tone=\"orange\" size=\"md\" fullWidth onClick={onClick} className=\"j-back-btn\">Back</JimboButton>\r\n </div>\r\n )\r\n}\r\n\r\n// ─── Modal ───────────────────────────────────────────────────────────────────\r\n\r\nexport interface JimboModalProps {\r\n children: React.ReactNode\r\n open: boolean\r\n onClose: () => void\r\n title?: string\r\n className?: string\r\n showBack?: boolean\r\n}\r\n\r\nexport function JimboModal({ children, open, onClose, title, className, showBack = true }: JimboModalProps) {\r\n if (!open) return null\r\n\r\n return (\r\n <div className=\"j-modal-overlay\">\r\n <JimboPanel\r\n onBack={showBack ? onClose : undefined}\r\n className={`j-modal ${className ?? ''}`}\r\n >\r\n {title && <JimboText as=\"h2\" size=\"lg\" className=\"j-modal__title\">{title}</JimboText>}\r\n {children}\r\n </JimboPanel>\r\n </div>\r\n )\r\n}\r\n","'use client'\n\nimport * as React from 'react'\nimport { JimboText } from './jimboText.js'\n\nexport interface JimboTabItem {\n id: string\n label: string\n}\n\nexport interface JimboTabsProps {\n tabs: JimboTabItem[]\n activeTab: string\n onTabChange: (tabId: string) => void\n className?: string\n style?: React.CSSProperties\n}\n\n/**\n * Horizontal tab navigation with bouncing triangle indicator on the active\n * tab. Triangle attaches to each button and animates only on the active one.\n */\nexport function JimboTabs({ tabs, activeTab, onTabChange, className = '', style }: JimboTabsProps) {\n return (\n <div className={`j-tabs ${className}`} style={style}>\n {tabs.map((tab) => (\n <TabButton\n key={tab.id}\n label={tab.label}\n active={activeTab === tab.id}\n onClick={() => onTabChange(tab.id)}\n />\n ))}\n </div>\n )\n}\n\nfunction TabButton({ label, active, onClick }: { label: string; active: boolean; onClick: () => void }) {\n return (\n <div className=\"j-tab\" data-active={active}>\n <div\n className=\"j-tab__indicator\"\n data-active={active}\n aria-hidden\n >\n <svg width={14} height={10} viewBox=\"0 0 14 10\">\n <polygon points=\"7,10 0,0 14,0\" />\n </svg>\n </div>\n <button\n type=\"button\"\n className=\"j-tab__btn\"\n data-active={active}\n onClick={onClick}\n >\n <JimboText size=\"sm\" tone=\"default\">{label}</JimboText>\n </button>\n </div>\n )\n}\n\n/**\n * Vertical tab strip — rotated labels (writing-mode) for space efficiency.\n */\nexport function JimboVerticalTabs({ tabs, activeTab, onTabChange, className = '', style }: JimboTabsProps) {\n return (\n <div className={`j-vtabs ${className}`} style={style}>\n {tabs.map((tab) => {\n const isActive = activeTab === tab.id\n return (\n <button\n key={tab.id}\n type=\"button\"\n className=\"j-vtab\"\n data-active={isActive}\n onClick={() => onTabChange(tab.id)}\n >\n <JimboText size=\"sm\" tone={isActive ? 'default' : 'grey'}>{tab.label}</JimboText>\n </button>\n )\n })}\n </div>\n )\n}\n","import React from 'react'\r\n\r\nexport interface JimboFloatingProps {\r\n anchor?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center'\r\n offset?: number\r\n zIndex?: number\r\n children: React.ReactNode\r\n}\r\n\r\nexport function JimboFloating({ anchor = 'top-right', offset = 12, zIndex = 20, children }: JimboFloatingProps) {\r\n const pos: React.CSSProperties = { position: 'absolute', zIndex };\r\n\r\n if (anchor.includes('top')) pos.top = offset;\r\n if (anchor.includes('bottom')) pos.bottom = offset;\r\n\r\n if (anchor.includes('left')) pos.left = offset;\r\n if (anchor.includes('right')) pos.right = offset;\r\n if (anchor.includes('center')) {\r\n pos.left = '50%';\r\n pos.transform = 'translateX(-50%)';\r\n }\r\n\r\n return (\r\n <div style={pos}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n","import React from 'react'\r\nimport { JimboPanel } from './panel.js'\r\n\r\nexport interface ToggleItem {\r\n id: string;\r\n label: string;\r\n on: boolean;\r\n}\r\n\r\nexport interface JimboToggleListProps {\r\n items: ToggleItem[];\r\n onToggle: (id: string) => void;\r\n title?: string;\r\n}\r\n\r\nexport function JimboToggleList({ items, onToggle, title }: JimboToggleListProps) {\r\n return (\r\n <JimboPanel>\r\n <div className=\"j-toggle-list\">\r\n {title && <div className=\"j-toggle-list__title\">{title}</div>}\r\n {items.map(item => (\r\n <button\r\n key={item.id}\r\n type=\"button\"\r\n className=\"j-toggle-item\"\r\n onClick={() => onToggle(item.id)}\r\n >\r\n <div className=\"j-toggle-check\" data-on={item.on} />\r\n {item.label}\r\n </button>\r\n ))}\r\n </div>\r\n </JimboPanel>\r\n )\r\n}\r\n","import React from 'react'\r\n\r\nexport type JimboBadgeTone = 'dark' | 'blue' | 'red' | 'green' | 'gold' | 'grey' | 'orange' | 'purple'\r\n\r\nexport interface JimboBadgeProps {\r\n size?: 'sm' | 'md'\r\n tone?: JimboBadgeTone\r\n children: React.ReactNode\r\n className?: string\r\n}\r\n\r\n/**\r\n * Small colored label pill. Matches Balatro's in-game tag/rarity badges.\r\n * All styling via jimbo.css `.j-badge` classes.\r\n */\r\nexport function JimboBadge({ size = 'sm', tone = 'dark', className, children }: JimboBadgeProps) {\r\n return (\r\n <span className={`j-badge j-badge--${size} j-badge--${tone} ${className ?? ''}`}>\r\n {children}\r\n </span>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\n\r\nexport interface JimboFlankNavProps {\r\n onPrev: () => void\r\n onNext: () => void\r\n canPrev?: boolean\r\n canNext?: boolean\r\n prevLabel?: string\r\n nextLabel?: string\r\n children: React.ReactNode\r\n className?: string\r\n style?: React.CSSProperties\r\n}\r\n\r\n/**\r\n * Prev/next navigation with flanking buttons around a central stage.\r\n * No hardcoded labels, no lucide dep (inline chevron SVGs).\r\n */\r\nexport function JimboFlankNav({\r\n onPrev,\r\n onNext,\r\n canPrev = true,\r\n canNext = true,\r\n prevLabel = 'Previous',\r\n nextLabel = 'Next',\r\n children,\r\n className = '',\r\n style,\r\n}: JimboFlankNavProps) {\r\n return (\r\n <div className={`j-flank ${className}`} style={style}>\r\n <NavButton direction=\"left\" onClick={onPrev} disabled={!canPrev} aria-label={prevLabel} />\r\n <div className=\"j-flank__content\">{children}</div>\r\n <NavButton direction=\"right\" onClick={onNext} disabled={!canNext} aria-label={nextLabel} />\r\n </div>\r\n )\r\n}\r\n\r\nfunction NavButton({\r\n direction,\r\n onClick,\r\n disabled,\r\n 'aria-label': ariaLabel,\r\n}: {\r\n direction: 'left' | 'right'\r\n onClick: () => void\r\n disabled: boolean\r\n 'aria-label': string\r\n}) {\r\n const [pressed, setPressed] = React.useState(false)\r\n return (\r\n <button\r\n type=\"button\"\r\n className=\"j-flank__btn\"\r\n data-pressed={pressed && !disabled}\r\n onClick={onClick}\r\n disabled={disabled}\r\n aria-label={ariaLabel}\r\n title={ariaLabel}\r\n onMouseDown={() => !disabled && setPressed(true)}\r\n onMouseUp={() => setPressed(false)}\r\n onMouseLeave={() => setPressed(false)}\r\n onTouchStart={() => !disabled && setPressed(true)}\r\n onTouchEnd={() => setPressed(false)}\r\n >\r\n <ChevronSvg direction={direction} />\r\n </button>\r\n )\r\n}\r\n\r\nfunction ChevronSvg({ direction }: { direction: 'left' | 'right' }) {\r\n const points = direction === 'left' ? '18,4 8,14 18,24' : '10,4 20,14 10,24'\r\n return (\r\n <svg width={28} height={28} viewBox=\"0 0 28 28\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\r\n <polyline points={points} />\r\n </svg>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\nimport { JimboText } from './jimboText.js'\r\n\r\nexport interface JimboFilterSortOption {\r\n value: string\r\n label: string\r\n}\r\n\r\nexport interface JimboFilterBarProps {\r\n search?: string\r\n onSearchChange?: (query: string) => void\r\n searchPlaceholder?: string\r\n searchLabel?: string\r\n\r\n sort?: string\r\n onSortChange?: (value: string) => void\r\n sortLabel?: string\r\n sortOptions?: JimboFilterSortOption[]\r\n\r\n className?: string\r\n style?: React.CSSProperties\r\n}\r\n\r\n/**\r\n * Generic Balatro-styled filter row: search input with floating pill label\r\n * + optional sort dropdown with floating pill label.\r\n */\r\nexport function JimboFilterBar({\r\n search,\r\n onSearchChange,\r\n searchPlaceholder = 'Search...',\r\n searchLabel = 'Search',\r\n sort,\r\n onSortChange,\r\n sortLabel = 'Sort By',\r\n sortOptions,\r\n className = '',\r\n style,\r\n}: JimboFilterBarProps) {\r\n return (\r\n <div className={`j-filter-bar ${className}`} style={style}>\r\n {onSearchChange ? (\r\n <div className=\"j-filter-bar__field\">\r\n <div className=\"j-filter-bar__pill\">\r\n <JimboText size=\"xs\">{searchLabel}</JimboText>\r\n </div>\r\n <div className=\"j-relative\">\r\n <div className=\"j-filter-bar__search-icon\">\r\n <SearchIcon />\r\n </div>\r\n <input\r\n type=\"text\"\r\n value={search ?? ''}\r\n onChange={(e) => onSearchChange(e.target.value)}\r\n placeholder={searchPlaceholder}\r\n className=\"j-filter-bar__input\"\r\n />\r\n </div>\r\n </div>\r\n ) : null}\r\n\r\n {sortOptions && onSortChange ? (\r\n <div className=\"j-filter-bar__field\">\r\n <div className=\"j-filter-bar__pill\">\r\n <JimboText size=\"xs\">{sortLabel}</JimboText>\r\n </div>\r\n <div className=\"j-relative\">\r\n <select\r\n value={sort ?? sortOptions[0]?.value}\r\n onChange={(e) => onSortChange(e.target.value)}\r\n className=\"j-filter-bar__select\"\r\n >\r\n {sortOptions.map((opt) => (\r\n <option key={opt.value} value={opt.value}>{opt.label}</option>\r\n ))}\r\n </select>\r\n <div className=\"j-filter-bar__sort-icon\">\r\n <SortIcon />\r\n </div>\r\n </div>\r\n </div>\r\n ) : null}\r\n </div>\r\n )\r\n}\r\n\r\nfunction SearchIcon() {\r\n return (\r\n <svg width={24} height={24} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={3} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\r\n <circle cx={11} cy={11} r={8} />\r\n <line x1={21} y1={21} x2={16.65} y2={16.65} />\r\n </svg>\r\n )\r\n}\r\n\r\nfunction SortIcon() {\r\n return (\r\n <svg width={20} height={20} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\r\n <polyline points=\"7 4 7 20\" />\r\n <polyline points=\"3 8 7 4 11 8\" />\r\n <polyline points=\"17 20 17 4\" />\r\n <polyline points=\"21 16 17 20 13 16\" />\r\n </svg>\r\n )\r\n}\r\n","'use client'\n\nimport React from 'react'\n\nconst SUITS = [\n { char: '♥️', kf: 'jaml-heart' },\n { char: '♠️', kf: 'jaml-spade' },\n { char: '♦️', kf: 'jaml-diamond' },\n { char: '♣️', kf: 'jaml-club' },\n] as const\n\nexport interface JimboBalatroFooterProps {\n className?: string\n}\n\n/**\n * Attribution footer with animated suit cycle.\n * Always rendered — required attribution for using Balatro art.\n */\nexport function JimboBalatroFooter({ className = '' }: JimboBalatroFooterProps) {\n return (\n <div className={`j-footer ${className}`}>\n <div className=\"j-footer__bar\">\n <p className=\"j-footer__text\">\n <span>Not affiliated with LocalThunk or PlayStack •{' '}</span>\n <a\n href=\"https://store.steampowered.com/app/2379780/Balatro/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"j-footer__link\"\n >\n BUY BALATRO\n </a>\n <span>{' '}• Created with{' '}</span>\n <span className=\"j-footer__suits\">\n <span className=\"j-footer__suit-stage\">\n {SUITS.map(({ char, kf }) => (\n <span key={char} className=\"j-footer__suit-char\" style={{ animationName: kf }}>\n {char}\n </span>\n ))}\n </span>{' '}\n for the Balatro community\n </span>\n </p>\n </div>\n <style>{`\n @keyframes jaml-heart { 0%{opacity:0;transform:scale(1)} 1%{opacity:1;transform:scale(1.45)} 3.5%{opacity:1;transform:scale(1)} 61.5%{opacity:1;transform:scale(1)} 62%{opacity:0} 100%{opacity:0} }\n @keyframes jaml-spade { 0%,61.5%{opacity:0} 62%{opacity:1;transform:scale(1.45)} 64.5%{opacity:1;transform:scale(1)} 71.5%{opacity:1} 72%{opacity:0} 100%{opacity:0} }\n @keyframes jaml-diamond { 0%,71.5%{opacity:0} 72%{opacity:1;transform:scale(1.45)} 74.5%{opacity:1;transform:scale(1)} 81.5%{opacity:1} 82%{opacity:0} 100%{opacity:0} }\n @keyframes jaml-club { 0%,81.5%{opacity:0} 82%{opacity:1;transform:scale(1.45)} 84.5%{opacity:1;transform:scale(1)} 95%{opacity:1} 96%{opacity:0} 100%{opacity:0} }\n `}</style>\n </div>\n )\n}\n","import React from 'react'\nimport { useBalatroBackground } from './hooks.js'\nimport { JimboBalatroFooter } from './footer.js'\n\n/**\n * Fullscreen WebGL CRT/spin background — the authentic Balatro hypnotic\n * swirl, pixelated and animated. Also renders the attribution footer at the\n * bottom of the viewport (position: fixed) so it is always present and no\n * consumer can accidentally omit it.\n *\n * Drop it once at the root of your page:\n *\n * <JimboBackground />\n * <YourAppContent />\n *\n * Resizes automatically. Disposes the animation frame + shader on unmount.\n */\nexport function JimboBackground() {\n const canvasRef = useBalatroBackground()\n\n return (\n <>\n <canvas\n ref={canvasRef}\n aria-hidden\n style={{\n position: 'fixed',\n inset: 0,\n width: '100%',\n height: '100%',\n zIndex: -10,\n pointerEvents: 'none',\n }}\n />\n <JimboBalatroFooter />\n </>\n )\n}\n","import React, { useCallback } from 'react'\r\nimport { useJimboTooltip, type JimboTooltipMode, type JimboTooltipPlacement } from './hooks.js'\r\n\r\nexport interface JimboTooltipProps {\r\n /** Content rendered inside the tooltip panel. Typically a card's ability text, joker description, etc. */\r\n content: React.ReactNode\r\n /** The target element the tooltip anchors to. */\r\n children: React.ReactElement\r\n /** `snap` (default): tooltip sits above/below the target's bounding rect.\r\n * `mouse`: tooltip follows the mouse position while hovering. */\r\n mode?: JimboTooltipMode\r\n /** Only used in `snap` mode. Default `auto` picks top if there's room, else bottom. */\r\n placement?: JimboTooltipPlacement\r\n /** Hover delay in ms before the tooltip appears. Default 80. */\r\n delay?: number\r\n /** Max width of the tooltip panel (px). Default 280. */\r\n maxWidth?: number\r\n /** Disable the tooltip entirely (e.g. when the target is disabled). */\r\n disabled?: boolean\r\n}\r\n\r\nfunction assignRef<T>(ref: React.Ref<T> | undefined | null, value: T) {\r\n if (typeof ref === 'function') ref(value)\r\n else if (ref && typeof ref === 'object') {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n (ref as any).current = value\r\n }\r\n}\r\n\r\n/**\r\n * Canonical Balatro-style tooltip: dark panel, silver border, pixel font.\r\n * Wrap any target to get a hover/focus popover.\r\n */\r\nexport function JimboTooltip({\r\n content,\r\n children,\r\n mode = 'snap',\r\n placement = 'auto',\r\n delay = 80,\r\n maxWidth = 280,\r\n disabled = false,\r\n}: JimboTooltipProps) {\r\n const {\r\n visible,\r\n pos,\r\n targetRef,\r\n tooltipRef,\r\n show,\r\n hide,\r\n handleMouseMove,\r\n } = useJimboTooltip({ mode, placement, delay, disabled })\r\n\r\n const child = React.Children.only(children) as React.ReactElement<{\r\n ref?: React.Ref<HTMLElement>\r\n onMouseEnter?: (e: React.MouseEvent) => void\r\n onMouseLeave?: (e: React.MouseEvent) => void\r\n onFocus?: (e: React.FocusEvent) => void\r\n onBlur?: (e: React.FocusEvent) => void\r\n onMouseMove?: (e: React.MouseEvent) => void\r\n }>\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const childRef = (child as any).ref\r\n const refHandler = useCallback((node: HTMLElement | null) => {\r\n targetRef.current = node\r\n assignRef(childRef, node)\r\n }, [childRef, targetRef])\r\n\r\n const wrapped = React.cloneElement(child, {\r\n ref: refHandler,\r\n onMouseEnter: (e: React.MouseEvent) => { show(); child.props.onMouseEnter?.(e) },\r\n onMouseLeave: (e: React.MouseEvent) => { hide(); child.props.onMouseLeave?.(e) },\r\n onFocus: (e: React.FocusEvent) => { show(); child.props.onFocus?.(e) },\r\n onBlur: (e: React.FocusEvent) => { hide(); child.props.onBlur?.(e) },\r\n onMouseMove: (e: React.MouseEvent) => { handleMouseMove(e); child.props.onMouseMove?.(e) },\r\n })\r\n\r\n return (\r\n <>\r\n {wrapped}\r\n {visible ? (\r\n <div\r\n ref={tooltipRef}\r\n role=\"tooltip\"\r\n className=\"j-tooltip\"\r\n style={{\r\n left: pos?.left ?? -9999,\r\n top: pos?.top ?? -9999,\r\n maxWidth,\r\n opacity: pos ? 1 : 0,\r\n }}\r\n >\r\n {content}\r\n </div>\r\n ) : null}\r\n </>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React, { useState } from 'react'\r\n\r\nexport interface JimboCodeBlockProps {\r\n code: string\r\n language?: string\r\n filename?: string\r\n className?: string\r\n}\r\n\r\nexport function JimboCodeBlock({ code, language, filename, className = '' }: JimboCodeBlockProps) {\r\n const [copied, setCopied] = useState(false)\r\n\r\n const copy = () => {\r\n void navigator.clipboard.writeText(code)\r\n setCopied(true)\r\n setTimeout(() => setCopied(false), 2000)\r\n }\r\n\r\n return (\r\n <div className={`j-code-block ${className}`}>\r\n <div className=\"j-code-block__header\">\r\n <div className=\"j-code-block__meta\">\r\n {filename && <span className=\"j-code-block__filename\">{filename}</span>}\r\n {language && <span className=\"j-code-block__lang\">{language}</span>}\r\n </div>\r\n <button\r\n onClick={copy}\r\n title=\"Copy\"\r\n className=\"j-code-block__copy\"\r\n data-copied={copied}\r\n >\r\n {copied\r\n ? <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>\r\n : <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>\r\n }\r\n </button>\r\n </div>\r\n <pre className=\"j-code-block__pre\">\r\n <code>{code}</code>\r\n </pre>\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\n// ─── App Shell ──────────────────────────────────────────────────────────────\r\n// Mobile-first 320px layout container. This is the DEFAULT layout for ALL\r\n// Jimbo UI screens — not just the \"demo\".\r\n//\r\n// Add `fluid` prop to unlock for MCP / desktop contexts (j-app--fluid).\r\n// In fluid mode the container stretches to fill its parent (up to 750px)\r\n// and container queries in jimbo.css activate \"cozy\" overrides at 401px+.\r\n\r\nexport interface JimboAppProps extends React.HTMLAttributes<HTMLDivElement> {\r\n children: React.ReactNode\r\n /** Unlock width/height for MCP inline or desktop use. Default: false (320×568 locked). */\r\n fluid?: boolean\r\n}\r\n\r\n/** Standard mobile-first app shell. 320px locked, or fluid for MCP/desktop. */\r\nexport function JimboApp({ children, fluid, className = '', ...props }: JimboAppProps) {\r\n const classes = `j-app${fluid ? ' j-app--fluid' : ''} ${className}`.trim()\r\n return (\r\n <div className={classes} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n\r\n/** Scrollable content area inside JimboApp. Hidden scrollbar, snap-friendly. */\r\nexport function JimboAppScroll({ children, className = '', ...props }: Omit<JimboAppProps, 'fluid'>) {\r\n return (\r\n <div className={`j-app__scroll ${className}`} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n\r\n/** Sticky bottom action area inside JimboApp. Thumb zone. */\r\nexport function JimboAppFooter({ children, className = '', ...props }: Omit<JimboAppProps, 'fluid'>) {\r\n return (\r\n <div className={`j-app__footer ${className}`} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport type JimboSectionTone = 'red' | 'blue' | 'green' | 'gold' | 'orange' | 'purple'\r\n\r\nexport interface JimboSectionHeaderProps {\r\n label: string\r\n tone?: JimboSectionTone\r\n className?: string\r\n}\r\n\r\n/**\r\n * Colored tag + horizontal rule — reusable section divider.\r\n * All styling via jimbo.css `.j-section-header` classes + tone utilities.\r\n */\r\nexport function JimboSectionHeader({ label, tone = 'blue', className = '' }: JimboSectionHeaderProps) {\r\n return (\r\n <div className={`j-section-header ${className}`}>\r\n <div className={`j-section-header__tag j-bg--${tone}`}>{label}</div>\r\n <div className={`j-section-header__rule j-bg--${tone}`} />\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport type JimboInfoCardTone = 'red' | 'blue' | 'green' | 'gold' | 'orange' | 'purple'\r\n\r\nexport interface JimboInfoCardProps extends React.HTMLAttributes<HTMLDivElement> {\r\n tone?: JimboInfoCardTone\r\n children: React.ReactNode\r\n}\r\n\r\n/**\r\n * Generic clickable row card — used for filter lists, seed lists, etc.\r\n * Border color set via tone. All styling via jimbo.css `.j-info-card`.\r\n */\r\nexport function JimboInfoCard({ tone, children, className = '', ...props }: JimboInfoCardProps) {\r\n const borderClass = tone ? `j-border--${tone}` : ''\r\n return (\r\n <div className={`j-info-card ${borderClass} ${className}`} style={tone ? { borderColor: undefined } : undefined} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n\r\n/** Main body area inside an InfoCard (flex: 1, overflow-safe). */\r\nexport function JimboInfoCardBody({ children, className = '' }: { children: React.ReactNode; className?: string }) {\r\n return <div className={`j-info-card__body ${className}`}>{children}</div>\r\n}\r\n\r\n/** Title line inside an InfoCard body. */\r\nexport function JimboInfoCardTitle({ children, className = '' }: { children: React.ReactNode; className?: string }) {\r\n return <div className={`j-info-card__title ${className}`}>{children}</div>\r\n}\r\n\r\n/** Subtitle line inside an InfoCard body. */\r\nexport function JimboInfoCardSub({ children, className = '' }: { children: React.ReactNode; className?: string }) {\r\n return <div className={`j-info-card__sub ${className}`}>{children}</div>\r\n}\r\n\r\n/** Right-side aside area inside an InfoCard. */\r\nexport function JimboInfoCardAside({ children, className = '' }: { children: React.ReactNode; className?: string }) {\r\n return <div className={`j-info-card__aside ${className}`}>{children}</div>\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\nimport { JimboButton } from './panel.js'\r\nimport { JimboSprite } from './sprites.js'\r\nimport { JimboText } from './jimboText.js'\r\nimport { JimboApp, JimboAppFooter } from './jimboApp.js'\r\nimport { JimboBalatroFooter } from './footer.js'\r\nimport { JimboSectionHeader, type JimboSectionTone } from './jimboSectionHeader.js'\r\nimport { JimboInfoCard, JimboInfoCardBody, JimboInfoCardTitle, JimboInfoCardSub, JimboInfoCardAside } from './jimboInfoCard.js'\r\n\r\nexport interface ShowcaseFilter {\r\n name: string\r\n author: string\r\n hits: string\r\n tone: JimboSectionTone\r\n sample: string[]\r\n}\r\n\r\nexport interface ShowcaseRecentFind {\r\n seed: string\r\n filterName: string\r\n score: number\r\n}\r\n\r\nexport interface ShowcaseLiveStats {\r\n searched: string\r\n matches: string\r\n speed: string\r\n}\r\n\r\nexport interface ShowcaseMcpInfo {\r\n runtime: string\r\n engine: string\r\n features: string\r\n}\r\n\r\nexport interface ShowcaseProps {\r\n title?: string\r\n subtitle?: string\r\n hotFilters?: ShowcaseFilter[]\r\n recentFinds?: ShowcaseRecentFind[]\r\n mcpInfo?: ShowcaseMcpInfo\r\n onNewSearch?: () => void\r\n onBrowseFilters?: () => void\r\n onFilterClick?: (filter: ShowcaseFilter, index: number) => void\r\n}\r\n\r\n/**\r\n * Landing/showcase screen — 320×568, NO SCROLL.\r\n * Every pixel accounted for. No flex stretching. No gaps.\r\n */\r\nexport function Showcase({\r\n title = 'Balatro',\r\n subtitle = 'Seed Curator',\r\n hotFilters = [],\r\n recentFinds = [],\r\n mcpInfo,\r\n onNewSearch,\r\n onBrowseFilters,\r\n onFilterClick,\r\n}: ShowcaseProps) {\r\n return (\r\n <JimboApp>\r\n {/* Content — no flex-grow, no dead space, footer follows naturally */}\r\n <div style={{ padding: '12px 12px 8px', display: 'flex', flexDirection: 'column', gap: 6 }}>\r\n {/* Compact title */}\r\n <div className=\"j-text-center\">\r\n <JimboText size=\"lg\" tone=\"gold\">{title}</JimboText>\r\n <JimboText size=\"micro\" tone=\"grey\" style={{ letterSpacing: 3 }}>{subtitle}</JimboText>\r\n </div>\r\n\r\n {/* Engine strip — single line */}\r\n {mcpInfo && (\r\n <div className=\"j-flex j-justify-between\" style={{\r\n padding: '3px 8px',\r\n background: 'var(--j-dark-grey)', borderRadius: 4,\r\n border: '1px solid var(--j-panel-edge)',\r\n }}>\r\n <JimboText size=\"micro\" tone=\"purple\">{mcpInfo.engine}</JimboText>\r\n <JimboText size=\"micro\" tone=\"grey\">{mcpInfo.features}</JimboText>\r\n </div>\r\n )}\r\n\r\n {/* Hot Filters */}\r\n {hotFilters.length > 0 && (\r\n <>\r\n <JimboSectionHeader label=\"Filters\" tone=\"blue\" />\r\n <div className=\"j-flex-col\" style={{ gap: 4 }}>\r\n {hotFilters.slice(0, 4).map((f, i) => (\r\n <JimboInfoCard\r\n key={i}\r\n tone={f.tone}\r\n onClick={() => onFilterClick?.(f, i)}\r\n style={{ cursor: onFilterClick ? 'pointer' : undefined }}\r\n >\r\n <div className=\"j-flex j-gap-xs\">\r\n {f.sample.slice(0, 2).map((name, j) => (\r\n <div key={j} style={{ width: 22, height: 28, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <JimboSprite name={name} width={20} />\r\n </div>\r\n ))}\r\n </div>\r\n <JimboInfoCardBody>\r\n <JimboInfoCardTitle>{f.name}</JimboInfoCardTitle>\r\n <JimboInfoCardSub>by {f.author}</JimboInfoCardSub>\r\n </JimboInfoCardBody>\r\n <JimboInfoCardAside>\r\n <JimboText size=\"xs\" tone={f.tone === 'gold' ? 'gold' : f.tone}>{f.hits}</JimboText>\r\n </JimboInfoCardAside>\r\n </JimboInfoCard>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* Recent finds — compact */}\r\n {recentFinds.length > 0 && (\r\n <>\r\n <JimboSectionHeader label=\"Recent\" tone=\"green\" />\r\n <div style={{ lineHeight: 1.5 }}>\r\n {recentFinds.slice(0, 3).map((r, i) => (\r\n <div key={i} className=\"j-flex j-gap-sm\">\r\n <JimboText size=\"micro\" tone=\"gold\">{r.seed}</JimboText>\r\n <JimboText size=\"micro\" tone=\"grey\">{r.filterName}</JimboText>\r\n {r.score > 0 && <JimboText size=\"micro\" tone=\"green\">+{r.score}</JimboText>}\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n <JimboAppFooter>\r\n <JimboButton tone=\"green\" fullWidth size=\"lg\" onClick={onNewSearch}>New Search</JimboButton>\r\n <JimboButton tone=\"blue\" fullWidth size=\"lg\" onClick={onBrowseFilters}>Browse Filters</JimboButton>\r\n </JimboAppFooter>\r\n <JimboBalatroFooter />\r\n </JimboApp>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React, { useState } from 'react'\r\nimport { JimboText } from './jimboText.js'\r\n\r\nexport interface JimboCopyRowProps {\r\n value: string\r\n label?: string\r\n}\r\n\r\n/**\r\n * Inline copy-to-clipboard row with label + value + button.\r\n * All styling via jimbo.css `.j-copy-row` classes.\r\n */\r\nexport function JimboCopyRow({ value, label }: JimboCopyRowProps) {\r\n const [copied, setCopied] = useState(false)\r\n\r\n function copy() {\r\n navigator.clipboard.writeText(value).then(() => {\r\n setCopied(true)\r\n setTimeout(() => setCopied(false), 1500)\r\n })\r\n }\r\n\r\n return (\r\n <div className=\"j-copy-row\">\r\n {label && (\r\n <JimboText size=\"xs\" tone=\"grey\" className=\"j-copy-row__label\">\r\n {label}\r\n </JimboText>\r\n )}\r\n <div className=\"j-copy-row__field\">\r\n <div className=\"j-copy-row__value\">\r\n <JimboText size=\"sm\">{value}</JimboText>\r\n </div>\r\n <button\r\n type=\"button\"\r\n className=\"j-copy-row__btn\"\r\n data-copied={copied}\r\n onClick={copy}\r\n >\r\n {copied ? 'Copied' : 'Copy'}\r\n </button>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport interface JimboWordmarkProps {\r\n title: string\r\n subtitle?: string\r\n className?: string\r\n}\r\n\r\n/**\r\n * Title + subtitle hero block. Gold title, grey subtitle.\r\n * All styling via jimbo.css `.j-wordmark` classes.\r\n */\r\nexport function JimboWordmark({ title, subtitle, className = '' }: JimboWordmarkProps) {\r\n return (\r\n <div className={`j-wordmark ${className}`}>\r\n <div className=\"j-wordmark__title\">{title}</div>\r\n {subtitle && <div className=\"j-wordmark__sub\">{subtitle}</div>}\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport interface JimboStatItem {\r\n value: string | number\r\n label: string\r\n}\r\n\r\nexport interface JimboStatGridProps extends React.HTMLAttributes<HTMLDivElement> {\r\n items: JimboStatItem[]\r\n}\r\n\r\n/**\r\n * 3-column stat bar — value on top, label below.\r\n * All styling via jimbo.css `.j-stat-grid` classes.\r\n */\r\nexport function JimboStatGrid({ items, className = '', ...props }: JimboStatGridProps) {\r\n return (\r\n <div className={`j-stat-grid ${className}`} {...props}>\r\n {items.map((item) => (\r\n <div key={item.label}>\r\n <div className=\"j-stat-grid__value\">{item.value}</div>\r\n <div className=\"j-stat-grid__label\">{item.label}</div>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport interface JimboInsetProps extends React.HTMLAttributes<HTMLDivElement> {\r\n children: React.ReactNode\r\n}\r\n\r\n/**\r\n * Dark recessed content area — for log output, recent finds, etc.\r\n * All styling via jimbo.css `.j-inset` class.\r\n */\r\nexport function JimboInset({ children, className = '', ...props }: JimboInsetProps) {\r\n return (\r\n <div className={`j-inset ${className}`} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n","// PORTABLE — intended for jaml-ui/src/ui/jimboIconButton.tsx\r\n// On paste, replace `from 'jaml-ui'` with `from './tokens.js'`.\r\n\"use client\";\r\n\r\nimport { JimboColorOption } from \"./tokens.js\";\r\nimport type React from \"react\";\r\nimport { useState } from \"react\";\r\n\r\nconst C = JimboColorOption;\r\n\r\nexport interface JimboIconButtonProps {\r\n \"aria-label\"?: string;\r\n children: React.ReactNode;\r\n disabled?: boolean;\r\n onClick?: () => void;\r\n size?: \"sm\" | \"md\";\r\n title?: string;\r\n}\r\n\r\nexport function JimboIconButton({\r\n onClick,\r\n title,\r\n \"aria-label\": ariaLabel,\r\n disabled = false,\r\n size = \"md\",\r\n children,\r\n}: JimboIconButtonProps) {\r\n const [hover, setHover] = useState(false);\r\n const side = size === \"sm\" ? 26 : 30;\r\n\r\n return (\r\n <button\r\n aria-label={ariaLabel ?? title}\r\n disabled={disabled}\r\n onClick={() => !disabled && onClick?.()}\r\n onMouseEnter={() => setHover(true)}\r\n onMouseLeave={() => setHover(false)}\r\n style={{\r\n width: side,\r\n height: side,\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n background: hover && !disabled ? C.DARK_GREY : C.DARKEST,\r\n color: C.WHITE,\r\n border: `1px solid ${C.PANEL_EDGE}`,\r\n borderRadius: 4,\r\n cursor: disabled ? \"not-allowed\" : \"pointer\",\r\n opacity: disabled ? 0.55 : 1,\r\n padding: 0,\r\n fontSize: 14,\r\n lineHeight: 1,\r\n transition: \"background 80ms ease\",\r\n }}\r\n title={title}\r\n type=\"button\"\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n","// PORTABLE — intended for jaml-ui/src/ui/jimboInputModal.tsx\r\n// On paste, replace `from 'jaml-ui'` with `from './panel.js'`/`./tokens.js` as appropriate.\r\n\"use client\";\r\n\r\nimport { JimboButton, JimboModal } from \"./panel.js\";\r\nimport { JimboColorOption } from \"./tokens.js\";\r\nimport { JimboText } from \"./jimboText.js\";\r\nimport { useEffect, useRef, useState } from \"react\";\r\n\r\nconst C = JimboColorOption;\r\n\r\nexport interface JimboInputModalProps {\r\n cancelLabel?: string;\r\n confirmLabel?: string;\r\n initialValue?: string;\r\n message?: string;\r\n onCancel: () => void;\r\n onConfirm: (value: string) => void;\r\n open: boolean;\r\n placeholder?: string;\r\n title: string;\r\n validate?: (value: string) => string | null;\r\n}\r\n\r\nexport function JimboInputModal({\r\n open,\r\n title,\r\n message,\r\n placeholder,\r\n initialValue = \"\",\r\n confirmLabel = \"Confirm\",\r\n cancelLabel = \"Cancel\",\r\n validate,\r\n onConfirm,\r\n onCancel,\r\n}: JimboInputModalProps) {\r\n const [value, setValue] = useState(initialValue);\r\n const [error, setError] = useState<string | null>(null);\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n\r\n const [prevOpen, setPrevOpen] = useState(open);\r\n\r\n if (open !== prevOpen) {\r\n setPrevOpen(open);\r\n if (open) {\r\n setValue(initialValue);\r\n setError(null);\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n if (open) {\r\n const t = setTimeout(() => inputRef.current?.focus(), 30);\r\n return () => clearTimeout(t);\r\n }\r\n }, [open]);\r\n\r\n function submit() {\r\n const err = validate?.(value) ?? null;\r\n if (err) {\r\n setError(err);\r\n return;\r\n }\r\n onConfirm(value);\r\n }\r\n\r\n return (\r\n <JimboModal onClose={onCancel} open={open} title={title}>\r\n {message && (\r\n <JimboText\r\n size=\"sm\"\r\n style={{ display: \"block\", marginBottom: 8 }}\r\n tone=\"grey\"\r\n >\r\n {message}\r\n </JimboText>\r\n )}\r\n <input\r\n aria-invalid={error ? \"true\" : \"false\"}\r\n onChange={(e) => {\r\n setValue(e.target.value);\r\n if (error) {\r\n setError(null);\r\n }\r\n }}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\") {\r\n submit();\r\n }\r\n if (e.key === \"Escape\") {\r\n onCancel();\r\n }\r\n }}\r\n placeholder={placeholder}\r\n ref={inputRef}\r\n style={{\r\n width: \"100%\",\r\n padding: \"8px 10px\",\r\n background: C.DARKEST,\r\n color: C.WHITE,\r\n border: `1px solid ${error ? C.RED : C.PANEL_EDGE}`,\r\n borderRadius: 4,\r\n fontSize: 13,\r\n fontFamily: \"m6x11plus, monospace\",\r\n letterSpacing: 1,\r\n outline: \"none\",\r\n boxSizing: \"border-box\",\r\n }}\r\n type=\"text\"\r\n value={value}\r\n />\r\n {error && (\r\n <JimboText\r\n size=\"sm\"\r\n style={{ display: \"block\", marginTop: 6 }}\r\n tone=\"red\"\r\n >\r\n {error}\r\n </JimboText>\r\n )}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n justifyContent: \"flex-end\",\r\n gap: 8,\r\n marginTop: 14,\r\n }}\r\n >\r\n <JimboButton onClick={onCancel} size=\"sm\" tone=\"red\">\r\n {cancelLabel}\r\n </JimboButton>\r\n <JimboButton onClick={submit} size=\"sm\" tone=\"blue\">\r\n {confirmLabel}\r\n </JimboButton>\r\n </div>\r\n </JimboModal>\r\n );\r\n}\r\n","// PORTABLE — intended for jaml-ui/src/ui/jimboSelect.tsx\r\n// On paste, replace `from 'jaml-ui'` with `from './tokens.js'`.\r\n\"use client\";\r\n\r\nimport { JimboColorOption } from \"./tokens.js\";\r\nimport type React from \"react\";\r\n\r\nconst C = JimboColorOption;\r\n\r\nexport interface JimboSelectOption {\r\n disabled?: boolean;\r\n label?: string;\r\n value: string;\r\n}\r\n\r\nexport interface JimboSelectProps {\r\n \"aria-label\"?: string;\r\n disabled?: boolean;\r\n fullWidth?: boolean;\r\n onChange: (value: string) => void;\r\n options: JimboSelectOption[] | string[];\r\n placeholder?: string;\r\n size?: \"sm\" | \"md\";\r\n style?: React.CSSProperties;\r\n value: string;\r\n}\r\n\r\nexport function JimboSelect({\r\n value,\r\n options,\r\n onChange,\r\n placeholder,\r\n disabled = false,\r\n fullWidth = true,\r\n size = \"md\",\r\n style,\r\n \"aria-label\": ariaLabel,\r\n}: JimboSelectProps) {\r\n let normalized: JimboSelectOption[];\r\n if (options.length === 0) {\r\n normalized = [];\r\n } else if (typeof options[0] === \"string\") {\r\n normalized = (options as string[]).map((v) => ({ value: v }));\r\n } else {\r\n normalized = options as JimboSelectOption[];\r\n }\r\n\r\n const pad = size === \"sm\" ? \"4px 8px\" : \"6px 10px\";\r\n const fontSize = size === \"sm\" ? 11 : 12;\r\n\r\n return (\r\n <select\r\n aria-label={ariaLabel}\r\n disabled={disabled}\r\n onChange={(e) => onChange(e.target.value)}\r\n style={{\r\n width: fullWidth ? \"100%\" : undefined,\r\n padding: pad,\r\n background: C.DARKEST,\r\n color: C.WHITE,\r\n border: `1px solid ${C.PANEL_EDGE}`,\r\n borderRadius: 4,\r\n fontSize,\r\n fontFamily: \"m6x11plus, monospace\",\r\n cursor: disabled ? \"not-allowed\" : \"pointer\",\r\n opacity: disabled ? 0.55 : 1,\r\n appearance: \"none\",\r\n backgroundImage:\r\n \"linear-gradient(45deg, transparent 50%, \" +\r\n C.GOLD_TEXT +\r\n \" 50%), linear-gradient(135deg, \" +\r\n C.GOLD_TEXT +\r\n \" 50%, transparent 50%)\",\r\n backgroundPosition: \"calc(100% - 12px) 50%, calc(100% - 7px) 50%\",\r\n backgroundSize: \"5px 5px, 5px 5px\",\r\n backgroundRepeat: \"no-repeat\",\r\n paddingRight: 22,\r\n ...style,\r\n }}\r\n value={value}\r\n >\r\n {placeholder !== undefined && (\r\n <option disabled value=\"\">\r\n {placeholder}\r\n </option>\r\n )}\r\n {normalized.map((opt) => (\r\n <option disabled={opt.disabled} key={opt.value} value={opt.value}>\r\n {opt.label ?? opt.value}\r\n </option>\r\n ))}\r\n </select>\r\n );\r\n}\r\n","// PORTABLE — intended for jaml-ui/src/ui/panelSplitter.tsx\r\n// On paste, replace `from 'jaml-ui'` with `from './tokens.js'`.\r\n\"use client\";\r\n\r\nimport { JimboColorOption } from \"./tokens.js\";\r\nimport { useCallback, useEffect, useRef, useLayoutEffect } from \"react\";\r\n\r\nconst C = JimboColorOption;\r\n\r\nexport interface PanelSplitterProps {\r\n \"aria-label\"?: string;\r\n onDrag: (delta: number) => void;\r\n onKeyAdjust?: (delta: number) => void;\r\n orientation?: \"vertical\" | \"horizontal\";\r\n}\r\n\r\nexport function PanelSplitter({\r\n orientation = \"vertical\",\r\n onDrag,\r\n onKeyAdjust,\r\n \"aria-label\": ariaLabel,\r\n}: PanelSplitterProps) {\r\n const draggingRef = useRef(false);\r\n const lastRef = useRef(0);\r\n const onDragRef = useRef(onDrag);\r\n useLayoutEffect(() => {\r\n onDragRef.current = onDrag;\r\n });\r\n\r\n const handlePointerDown = useCallback(\r\n (e: React.PointerEvent<HTMLElement>) => {\r\n e.preventDefault();\r\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\r\n draggingRef.current = true;\r\n lastRef.current = orientation === \"vertical\" ? e.clientX : e.clientY;\r\n },\r\n [orientation]\r\n );\r\n\r\n useEffect(() => {\r\n function move(e: PointerEvent) {\r\n if (!draggingRef.current) {\r\n return;\r\n }\r\n const cur = orientation === \"vertical\" ? e.clientX : e.clientY;\r\n const delta = cur - lastRef.current;\r\n if (delta !== 0) {\r\n lastRef.current = cur;\r\n onDragRef.current(delta);\r\n }\r\n }\r\n function up() {\r\n draggingRef.current = false;\r\n }\r\n window.addEventListener(\"pointermove\", move);\r\n window.addEventListener(\"pointerup\", up);\r\n window.addEventListener(\"pointercancel\", up);\r\n return () => {\r\n window.removeEventListener(\"pointermove\", move);\r\n window.removeEventListener(\"pointerup\", up);\r\n window.removeEventListener(\"pointercancel\", up);\r\n };\r\n }, [orientation]);\r\n\r\n const step = 16;\r\n const isVertical = orientation === \"vertical\";\r\n\r\n return (\r\n <button\r\n aria-label={ariaLabel ?? \"Resize panel\"}\r\n onKeyDown={(e) => {\r\n if (!onKeyAdjust) {\r\n return;\r\n }\r\n if (isVertical && e.key === \"ArrowLeft\") {\r\n onKeyAdjust(-step);\r\n }\r\n if (isVertical && e.key === \"ArrowRight\") {\r\n onKeyAdjust(step);\r\n }\r\n if (!isVertical && e.key === \"ArrowUp\") {\r\n onKeyAdjust(-step);\r\n }\r\n if (!isVertical && e.key === \"ArrowDown\") {\r\n onKeyAdjust(step);\r\n }\r\n }}\r\n onPointerDown={handlePointerDown}\r\n style={{\r\n all: \"unset\",\r\n display: \"block\",\r\n flex: \"0 0 auto\",\r\n width: isVertical ? 6 : undefined,\r\n height: isVertical ? undefined : 6,\r\n cursor: isVertical ? \"col-resize\" : \"row-resize\",\r\n background: C.PANEL_EDGE,\r\n borderLeft: isVertical ? `1px solid ${C.BLACK}` : undefined,\r\n borderRight: isVertical ? `1px solid ${C.BLACK}` : undefined,\r\n borderTop: isVertical ? undefined : `1px solid ${C.BLACK}`,\r\n borderBottom: isVertical ? undefined : `1px solid ${C.BLACK}`,\r\n touchAction: \"none\",\r\n userSelect: \"none\",\r\n }}\r\n type=\"button\"\r\n />\r\n );\r\n}\r\n"],"mappings":";;;;;;AAMA,SAAS,EAAU,GAA+C;CAChE,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAM,IAAQ,IAAI,OAAO,OAAO;EAGhC,AAFA,EAAM,iBAAiB,cAAc,EAAQ,EAAM,CAAC,EACpD,EAAM,iBAAiB,eAAe,EAAQ,KAAK,CAAC,EACpD,EAAM,MAAM;GACZ;;AAGJ,SAAS,EACP,GACA,GACA,GACA,GACA,GACA;CACA,IAAI,CAAC,KAAS,CAAC,KAAS,CAAC,GAAO,KAAK,OAAO;CAC5C,IAAM,IAAY,EAAM,QAAQ,EAAM,SAChC,IAAa,EAAM,SAAS,EAAM,MAClC,IAAc,EAAO;CAc3B,IAZI,EAAM,UAAU,MAClB,EAAO,QAAQ,GACf,EAAO,SAAS,GAChB,EAAY,QAAQ,GAAG,EAAU,KACjC,EAAY,SAAS,GAAG,EAAW,MAGrC,EAAY,iBAAiB,aAC7B,EAAQ,wBAAwB,IAEhC,EAAQ,MAAM,EAEV,EAAM,YAAY,GAAW;EAC/B,IAAM,IAAU,GACV,IAAU,KAAK,IAAI,IAAU,IAAK,GAAG,GACrC,IAAU,KAAK,IAAI,IAAU,KAAK,GAAG;EAE3C,AADA,EAAQ,cAAc,OAAQ,KAAK,IAAI,IAAU,IAAK,GAAG,KAAK,MAC9D,EAAQ,UAAU,GAAS,EAAQ;;CAMrC,OAHA,EAAQ,UAAU,GAAO,EAAM,IAAI,IAAI,GAAW,EAAM,IAAI,IAAI,GAAY,GAAW,GAAY,GAAG,GAAG,EAAO,OAAO,EAAO,OAAO,EACrI,EAAQ,SAAS,EAEV,IAAY;;AAMrB,SAAgB,EAAQ,GAAiB;CACvC,IAAM,IAAM,EAAuB,KAAK;CAmBxC,OAjBA,QAAgB;EACd,IAAI,CAAC,KAAU,CAAC,EAAI,SAAS;EAC7B,IAAI,GACE,IAAQ,KAAK,KAAK,EAClB,IAAK,EAAI,SACT,UAAa;GACjB,IAAM,KAAM,KAAK,KAAK,GAAG,KAAS,EAAiB,gBAAiB,EAAiB,gBAAgB,KAAK,KAAK;GAE/G,AADA,EAAG,MAAM,YAAY,aAAa,KAAK,IAAI,EAAE,GAAG,EAAiB,cAAc,GAAI,MAAM,KAAK,IAAI,IAAI,GAAI,GAAG,EAAiB,YAAY,MAC1I,IAAQ,sBAAsB,EAAK;;EAGrC,OADA,IAAQ,sBAAsB,EAAK,QACtB;GAEX,AADA,qBAAqB,EAAM,EACvB,MAAI,EAAG,MAAM,YAAY;;IAE9B,CAAC,EAAO,CAAC,EAEL;;AAqCT,SAAgB,IAAuB;CACrC,IAAM,IAAY,EAA0B,KAAK;CAkJjD,OAhJA,QAAgB;EACd,IAAM,IAAS,EAAU;EACzB,IAAI,CAAC,GAAQ;EAEb,IAAM,IAAK,EAAO,WAAW,QAAQ;EACrC,IAAI,CAAC,GAAI;EAET,IA2DM,KAAgB,GAAc,MAAmB;GACrD,IAAM,IAAS,EAAG,aAAa,EAAK;GASpC,OARK,KACL,EAAG,aAAa,GAAQ,EAAO,EAC/B,EAAG,cAAc,EAAO,EACnB,EAAG,mBAAmB,GAAQ,EAAG,eAAe,GAK9C,KAJL,QAAQ,MAAM,2CAA2C,EAAG,iBAAiB,EAAO,CAAC,EACrF,EAAG,aAAa,EAAO,EAChB,SANW;KAWhB,IAAe,EAAa,EAAG,eAAe,wHAAS,EACvD,IAAiB,EAAa,EAAG,iBAAiB,6nEAAS;EACjE,IAAI,CAAC,KAAgB,CAAC,GAAgB;EAEtC,IAAM,IAAU,EAAG,eAAe;EAClC,IAAI,CAAC,GAAS;EAId,IAHA,EAAG,aAAa,GAAS,EAAa,EACtC,EAAG,aAAa,GAAS,EAAe,EACxC,EAAG,YAAY,EAAQ,EACnB,CAAC,EAAG,oBAAoB,GAAS,EAAG,YAAY,EAAE;GACpD,QAAQ,MAAM,yCAAyC,EAAG,kBAAkB,EAAQ,CAAC;GACrF;;EAGF,EAAG,WAAW,EAAQ;EAEtB,IAAM,IAAiB,EAAG,cAAc;EAExC,AADA,EAAG,WAAW,EAAG,cAAc,EAAe,EAC9C,EAAG,WACD,EAAG,cACH,IAAI,aAAa;GACf;GAAM;GAAM;GAAK;GAAM;GAAM;GAC7B;GAAM;GAAK;GAAK;GAAM;GAAK;GAC5B,CAAC,EACF,EAAG,YACJ;EAED,IAAM,IAAmB,EAAG,kBAAkB,GAAS,WAAW;EAElE,AADA,EAAG,wBAAwB,EAAiB,EAC5C,EAAG,oBAAoB,GAAkB,GAAG,EAAG,OAAO,IAAO,GAAG,EAAE;EAElE,IAAM,IAAe,EAAG,mBAAmB,GAAS,SAAS,EACvD,IAAqB,EAAG,mBAAmB,GAAS,eAAe,EAEnE,IAAY,KAAK,KAAK,EACxB,GAEE,UAAe;GACnB,IAAM,IAAe,EAAO,aACtB,IAAgB,EAAO;GAC7B,CAAI,EAAO,UAAU,KAAgB,EAAO,WAAW,OACrD,EAAO,QAAQ,GACf,EAAO,SAAS,GAChB,EAAG,SAAS,GAAG,GAAG,EAAG,oBAAoB,EAAG,oBAAoB;GAGlE,IAAM,KAAe,KAAK,KAAK,GAAG,KAAa;GAK/C,AAJA,EAAG,UAAU,GAAc,EAAY,EACvC,EAAG,UAAU,GAAoB,EAAO,OAAO,EAAO,OAAO,EAE7D,EAAG,WAAW,EAAG,WAAW,GAAG,EAAE,EACjC,IAAmB,sBAAsB,EAAO;;EAKlD,OAFA,GAAQ,QAEK;GAKX,AAJA,qBAAqB,EAAiB,EACtC,EAAG,cAAc,EAAQ,EACzB,EAAG,aAAa,EAAa,EAC7B,EAAG,aAAa,EAAe,EAC/B,EAAG,aAAa,EAAe;;IAEhC,EAAE,CAAC,EAEC;;AAST,SAAgB,EAAgB,EAC9B,UAAO,QACP,eAAY,QACZ,WAAQ,IACR,cAAW,MAMV;CACD,IAAM,CAAC,GAAS,KAAc,EAAS,GAAM,EACvC,CAAC,GAAK,KAAU,EAAwE,KAAK,EAC7F,IAAY,EAA2B,KAAK,EAC5C,IAAa,EAA8B,KAAK,EAChD,IAAgB,EAA6C,KAAK,EAElE,IAAO,QAAkB;EACzB,MACA,EAAc,WAAS,aAAa,EAAc,QAAQ,EAC9D,EAAc,UAAU,iBAAiB,EAAW,GAAK,EAAE,EAAM;IAChE,CAAC,GAAU,EAAM,CAAC,EAEf,IAAO,QAAkB;EAG7B,AAFI,EAAc,WAAS,aAAa,EAAc,QAAQ,EAC9D,EAAW,GAAM,EACjB,EAAO,KAAK;IACX,EAAE,CAAC,EAEA,IAAiB,QAAkB;EACvC,IAAM,IAAK,EAAU,SACf,IAAM,EAAW;EACvB,IAAI,CAAC,KAAM,CAAC,GAAK;EACjB,IAAM,IAAO,EAAG,uBAAuB,EACjC,IAAU,EAAI,uBAAuB,EACrC,IAAY,EAAK,KACjB,IACJ,MAAc,QAAQ,QAClB,MAAc,WAAW,WACvB,KAAa,EAAQ,SAAS,KAAK,QAAQ,UAE7C,IAAO,EAAK,OAAO,EAAK,QAAQ,IAAI,EAAQ,QAAQ,GACpD,IAAM,MAAU,QAAQ,EAAK,MAAM,EAAQ,SAAS,IAAI,EAAK,SAAS;EAC5E,EAAO;GACL,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,aAAa,EAAQ,QAAQ,GAAG,EAAK,CAAC;GACxE;GACA;GACD,CAAC;IACD,CAAC,EAAU,CAAC;CAuBf,OArBA,QAAgB;EACd,IAAI,CAAC,KAAW,MAAS,QAAQ;EACjC,IAAM,IAAM,sBAAsB,EAAe;EAGjD,OAFA,OAAO,iBAAiB,UAAU,EAAe,EACjD,OAAO,iBAAiB,UAAU,GAAgB,GAAK,QAC1C;GAGX,AAFA,qBAAqB,EAAI,EACzB,OAAO,oBAAoB,UAAU,EAAe,EACpD,OAAO,oBAAoB,UAAU,GAAgB,GAAK;;IAE3D;EAAC;EAAS;EAAM;EAAe,CAAC,EAEnC,cAAsB;EACpB,AAAI,EAAc,WAAS,aAAa,EAAc,QAAQ;IAC7D,EAAE,CAAC,EAOC;EACL;EACA;EACA;EACA;EACA;EACA;EACA,iBAZsB,GAAa,MAA6C;GAC5E,MAAS,WACb,EAAO;IAAE,MAAM,EAAE,UAAU;IAAI,KAAK,EAAE,UAAU;IAAI,OAAO;IAAU,CAAC;KACrE,CAAC,EAAK,CASP;EACD;;AAMH,SAAgB,EAAoB,EAClC,WACA,YAAS,IACT,eAAY,MAKX;CACD,IAAM,IAAY,EAA0B,KAAK,EAC3C,IAAgB,kBAAsC,IAAI,KAAK,CAAC,EAChE,CAAC,GAAO,KAAY,EAAS,IAAI,EAAE,EACnC,GAAG,KAAe,EAAS,EAAE,EAC7B,IAAoB,EAAsB,KAAK,EAC/C,CAAC,GAAS,KAAc,EAAS,EAAE,EACnC,CAAC,GAAW,KAAgB,EAAS,GAAM,EAC3C,CAAC,GAAW,KAAgB,EAAS,OAAO,EAE5C,IAAmB,GAAQ,MAAM,MAAU,EAAM,SAAS;CAwHhE,OArHA,QAAgB;EACd,IAAI,IAAY,IACV,IAAa,EAAc;EAajC,QAFA,YAV4B;GAC1B,IAAM,IAAO,MAAM,KAAK,IAAI,IAAI,OAAO,OAAO,EAAc,CAAC,KAAK,MAAU,EAAM,IAAI,CAAC,CAAC,EAClF,IAAS,MAAM,QAAQ,IAAI,EAAK,KAAK,MAAQ,EAAU,EAAI,CAAC,CAAC;GAC/D,MACJ,EAAO,SAAS,GAAO,MAAU;IAC/B,AAAI,KAAO,EAAW,IAAI,EAAK,IAAQ,EAAM;KAC7C,EACF,GAAa,MAAS,IAAO,EAAE;MAGxB,CAAC,OAAO,MAAQ,QAAQ,MAAM,sBAAsB,EAAI,CAAC,QAErD;GAEX,AADA,IAAY,IACZ,EAAW,OAAO;;IAEnB,EAAE,CAAC,EAGN,QAAgB;EACd,IAAI,CAAC,GAAkB;EAEvB,IAAI,GACE,KAAW,MAAsB;GACrC,AAAgB,MAAY;GAC5B,IAAM,IAAM,IAAY;GAKxB,CAJI,CAAC,EAAkB,WAAW,IAAY,MAAM,EAAkB,aACpE,EAAkB,UAAU,GAC5B,EAAW,EAAI,GAEjB,EAAkB,UAAU,sBAAsB,EAAQ;;EAI5D,OADA,EAAkB,UAAU,sBAAsB,EAAQ,QAC7C;GACX,AAAI,EAAkB,WAAS,qBAAqB,EAAkB,QAAQ;;IAE/E,CAAC,EAAiB,CAAC,EAGtB,QAAgB;EACd,IAAM,IAAS,EAAU;EACzB,IAAI,CAAC,KAAU,CAAC,KAAU,EAAO,WAAW,GAAG;EAC/C,IAAM,IAAU,EAAO,WAAW,KAAK;EACvC,IAAI,CAAC,GAAS;EACd,IAAI,IAAY;EAuBhB,OArBA,EAAQ,UAAU,GAAG,GAAG,EAAO,OAAO,EAAO,OAAO,EACjD,CAAC,GAAG,EAAO,CACT,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,SAAS,MAAU;GAClB,IAAI,EAAc,QAAQ,IAAI,EAAM,OAAO,EAAE;IAC3C,IAAM,IAAQ,EAAc,QAAQ,IAAI,EAAM,OAAO;IACrD,IAAI,CAAC,GAAO;IACZ,IAAM,IAAa,EAAY,GAAQ,GAAS,GAAO,GAAO,IAAmB,IAAU,KAAA,EAAU;IACrG,AAAI,EAAM,UAAU,KAAG,EAAS,EAAW;IAC3C;;GAEF,EAAU,EAAM,OAAO,CAAC,MAAM,MAAQ;IACpC,IAAI,KAAa,CAAC,GAAK;IACvB,IAAM,IAAa,EAAY,GAAQ,GAAS,GAAK,GAAO,IAAmB,IAAU,KAAA,EAAU;IAGnG,AAFA,EAAc,QAAQ,IAAI,EAAM,QAAQ,EAAI,EACxC,EAAM,UAAU,KAAG,EAAS,EAAW,EAC3C,GAAa,MAAS,IAAO,EAAE;KAC/B;IACF,EAEN,EAAO,MAAM,SAAS,IAAS,iBAAiB,cACnC;GAAE,IAAY;;IAC1B;EAAC;EAAQ;EAAS;EAAQ;EAAiB,CAAC,EA6CxC;EACL;EACA,gBAAA;GArBA,aAAa,OAAO,EAAM;GAC1B,OAAO;GACP,SAAS;GACT,aAAa,IAAY,WAAW,KAAA;GACpC,YAAY;GACZ,kBAAkB;GAgBlB;EACA,aAAA;GAbA,YAAY,KAAa,CAAC,IAAY,kDAAkD;GACxF,WAAW,IAAa,IAAY,IAAY,SAAU,KAAA;GAC1D,gBAAgB,IAAY,gBAAgB,KAAA;GAC5C,iBAAiB,IAAY,kBAAkB,KAAA;GAC/C,cAAc;GACd,WAAW,KAAa,IAAY,+BAA+B;GACnE,gBAAgB;GAChB,eAAe;GAMf;EACA,UAAU;GACR,gBAAgB,KAhDI,MAA8B;IAChD,CAAC,KAAa,EAAM,gBAAgB,WACxC,EAAa,GAAK;OA8C6B,KAAA;GAC7C,gBAAgB,UA5CS;IACtB,MACL,EAAa,GAAM,EACnB,EAAa,OAAO;OAyC2B,KAAA;GAC7C,eAAe,KAvCI,MAA8C;IACnE,IAAI,CAAC,KAAa,EAAM,gBAAgB,SAAS;IACjD,IAAM,IAAO,EAAM,cAAc,uBAAuB,EAClD,IAAI,EAAM,UAAU,EAAK,MACzB,IAAI,EAAM,UAAU,EAAK,KACzB,IAAW,IAAI,EAAK,QAAS,KAAK;IAIxC,EAAa,+BAHI,IAAI,EAAK,SAAU,MAAM,EAGU,eAAe,EAAQ,mCAAmD;OA8BjF,KAAA;GAC5C;EACF;;AAOH,SAAgB,EAAe,GAA2B,IAAoC,EAAE,EAAE;CAChG,IAAM,CAAC,GAAa,KAAkB,EAAS,EAAM,IAAI,QAAQ,EAAE,EAC7D,CAAC,GAAe,KAAoB,EAAS,EAAM,IAAI,KAAK,EAC5D,IAAY,EAAuB,KAAK,EACxC,IAAW,kBAAiC,IAAI,KAAK,CAAC;CAqD5D,OAnDI,EAAM,IAAI,SAAS,MACrB,EAAiB,EAAM,IAAI,KAAK,EAC5B,EAAM,SAAS,KACjB,EAAe,EAAM,GAAG,KAAK,GAIjC,QAAgB;EACd,IAAM,IAAO,EAAU;EACvB,IAAI,CAAC,KAAQ,EAAM,WAAW,GAAG;EAEjC,IAAM,IAAW,IAAI,sBAClB,MAAY;GAEX,IAAM,IAAc,EACjB,QAAQ,MAAM,EAAE,eAAe,CAC/B,MAAM,GAAG,MAAM,EAAE,oBAAoB,EAAE,kBAAkB,CAAC;GAE7D,IAAI,GAAa;IACf,IAAM,IAAO,OAAQ,EAAY,OAAuB,QAAQ,KAAK;IACrE,AAAK,OAAO,MAAM,EAAK,IACrB,EAAe,EAAK;;KAI1B;GACE;GACA,WAAW,EAAQ,aAAa;IAAC;IAAK;IAAK;IAAI;GAChD,CACF;EAID,OAFA,EAAS,QAAQ,SAAS,MAAO,EAAS,QAAQ,EAAG,CAAC,QAEzC,EAAS,YAAY;IACjC,CAAC,GAAO,EAAQ,UAAU,CAAC,EAiBvB;EACL;EACA;EACA,cAlBmB,GAAa,MAAiB;GACjD,IAAM,IAAK,EAAS,QAAQ,IAAI,EAAK;GACrC,AAAI,KACF,EAAG,eAAe;IAAE,UAAU;IAAU,OAAO;IAAS,CAAC;KAE1D,EAAE,CAaH;EACA,iBAZsB,GAAa,GAAc,MAA2B;GAC5E,AAAI,IACF,EAAS,QAAQ,IAAI,GAAM,EAAG,GAE9B,EAAS,QAAQ,OAAO,EAAK;KAE9B,EAAE,CAMH;EACD;;AAwBH,SAAgB,GACd,GACA,GACA,GACA;CACA,IAAM,CAAC,GAAM,KAAW,EAA2B,KAAK,EAClD,CAAC,GAAa,KAAkB,EAAkC,KAAK,EACvE,CAAC,GAAW,KAAgB,EAAwB,KAAK,EAEzD,IAAc,GACjB,GAAwC,GAA0B,MAAuB;EACxF,IAAM,IAAI,aAAa,IAAI,EAAE,QAAQ,KAAK,GACpC,IAAQ,EAAE,cAA8B,uBAAuB;EASrE,AARA,EAAe;GACb;GACA;GACA,GAAG,EAAE;GACL,GAAG,EAAE;GACL,MAAM,EAAE,UAAU,EAAK;GACvB,MAAM,EAAE,UAAU,EAAK;GACxB,CAAC,EACF,EAAa,KAAK;IAEpB,EAAE,CACH;CAsED,OApEA,QAAgB;EACd,IAAI,CAAC,KAAe,CAAC,GAAM;EAE3B,IAAM,KAAQ,MAA+B;GAC3C,IAAM,IAAa,aAAa,IAAK,IAAmB,MAClD,IAAI,IAAa,EAAW,QAAQ,KAAM;GAChD,IAAI,CAAC,GAAG;GAER,IAAI,IAAa;GAEjB,IAAI,CAAC,KAAc,GAAa;IAC9B,IAAM,IAAK,EAAE,UAAU,EAAY,GAC7B,IAAK,EAAE,UAAU,EAAY;IACnC,IAAI,KAAK,MAAM,GAAI,EAAG,GAAG,GAAG;IAO5B,AANA,IAAa;KACX,GAAG;KACH,GAAG,EAAE;KACL,GAAG,EAAE;KACN,EACD,EAAe,KAAK,EACpB,EAAQ,EAAW;UACd,AAAI,MACT,IAAa;IAAE,GAAG;IAAY,GAAG,EAAE;IAAS,GAAG,EAAE;IAAS,EAC1D,EAAQ,EAAW;GAGrB,IAAI,CAAC,GAAY;GACjB,AAAI,GAAY,cAAY,EAAW,gBAAgB;GAEvD,IAAM,IAAQ,EAAQ,SAAS,iBAAiB,cAAc,IAAI,EAAE,EAChE,IAAuB;GAC3B,KAAK,IAAM,KAAK,GAAO;IACrB,IAAM,IAAK,EAAE,uBAAuB;IACpC,IAAI,EAAE,WAAW,EAAG,QAAQ,EAAE,WAAW,EAAG,SAAS,EAAE,WAAW,EAAG,OAAO,EAAE,WAAW,EAAG,QAAQ;KAClG,IAAQ,EAAE,aAAa,YAAY;KACnC;;;GAGJ,EAAa,EAAM;KAGf,UAAW;GACf,IAAI,KAAQ,KAAa,MAAc,EAAK,UAAU;IACpD,IAAM,IAAK;IACX,EAAS;KACP,GAAG;MACF,EAAK,WAAW,EAAO,EAAK,UAAU,QAAQ,MAAM,EAAE,OAAO,EAAK,OAAO,GAAG;MAC5E,IAAK,CAAC,GAAG,EAAO,IAAK,EAAE,GAAG,EAAK,QAAQ,CAAC;KAC1C,CAAC;;GAIJ,AAFA,EAAe,KAAK,EACpB,EAAQ,KAAK,EACb,EAAa,KAAK;;EAQpB,OALA,OAAO,iBAAiB,aAAa,EAAK,EAC1C,OAAO,iBAAiB,WAAW,EAAG,EACtC,OAAO,iBAAiB,aAAa,GAAM,EAAE,SAAS,IAAO,CAAC,EAC9D,OAAO,iBAAiB,YAAY,EAAG,QAE1B;GAIX,AAHA,OAAO,oBAAoB,aAAa,EAAK,EAC7C,OAAO,oBAAoB,WAAW,EAAG,EACzC,OAAO,oBAAoB,aAAa,EAAK,EAC7C,OAAO,oBAAoB,YAAY,EAAG;;IAE3C;EAAC;EAAa;EAAM;EAAW;EAAQ;EAAU;EAAQ,CAAC,EAEtD;EACL;EACA;EACA;EACD;;;;ACtqBH,SAAgB,EAAY,EAAE,SAAM,UAAO,WAAQ,IAAI,WAAQ,YAA2B;CACxF,IAAM,IAAS,EAAc,EAAK,EAC5B,IAAiC,KAAS,GAAQ,QAAQ,UAC1D,IAAO,EAAW,IAClB,IAAU,EAAiB,EAAc,EACzC,IAAM,GAAQ,OAAO,EAAQ,KAE/B,IAAW;CACf,AAAI;EAAC;EAAU;EAAU;EAAY;EAAY;EAAS;EAAa;EAAW,CAAC,SAAS,EAAc,KACxG,IAAW,KAAK,MAAO,IAAQ,KAAM,GAAG;CAE1C,IAAM,IAAI,KAAU;CAEpB,IAAI,CAAC,GAAM,OAAO;CAElB,IAAM,IAAM,IAAQ,EAAK,MACnB,IAAM,IAAI,EAAK,MACf,IAAM,EAAE,EAAI,IAAI,IAChB,IAAM,EAAE,EAAI,IAAI;CAEtB,OACE,kBAAC,OAAD,EAAK,OAAO;EACV;EAAO,QAAQ;EAAG,YAAY;EAC9B,iBAAiB,OAAO,EAAoB,EAAK,SAAS,CAAC;EAC3D,gBAAgB,GAAG,EAAI,KAAK,EAAI;EAChC,oBAAoB,GAAG,EAAI,KAAK,EAAI;EACpC,kBAAkB;EAClB,gBAAgB;EAChB,GAAG;EACJ,EAAI,CAAA;;AAWT,IAAM,KAAsB;CAAC;CAAS;CAAO;CAAS;CAAS;CAAQ;CAAU;CAAU;CAAO;AAElG,SAAgB,GAAY,EAAE,UAAO,WAAQ,IAAI,WAAQ,YAA2B;CAClF,IAAM,IAAQ,GAAU,QAAQ,EAAM,QAAQ,UAAU,GAAG,CAAC,EACtD,IAAM,KAAS,IAAI,IAAQ,GAC3B,IAAI,IAAM,GACV,IAAI,KAAK,MAAM,IAAM,EAAE,EACvB,IAAI,KAAU,GACd,IAAM,IAAQ,GACd,IAAM,IAAI;CAEhB,OACE,kBAAC,OAAD,EAAK,OAAO;EACV;EAAO,QAAQ;EAAG,YAAY;EAC9B,iBAAiB,OAAO,EAAoB,SAAS,CAAC;EACtD,gBAAgB,GAAG,EAAI,KAAK,EAAI;EAChC,oBAAoB,IAAI,IAAI,EAAM,MAAM,IAAI,EAAE;EAC9C,kBAAkB;EAClB,gBAAgB;EAChB,GAAG;EACJ,EAAI,CAAA;;AAWT,IAAM,KAAoC;CACxC,KAAK;CACL,MAAM;CACN,QAAQ;CACR,OAAO;CACP,OAAO;CACP,OAAO;CACP,QAAQ;CACR,OAAO;CACR;AAED,SAAgB,GAAW,EAAE,SAAM,WAAQ,IAAI,WAAQ,YAA0B;CAE/E,IAAM,IAAI,GADO,EAAK,QAAQ,SAAS,GACnB,KAAa,GAE3B,IAAI,KAAW,IAAQ,KAAK,IAC5B,IAAM,IAAQ,IACd,IAAM,IAAI;CAEhB,OACE,kBAAC,OAAD,EAAK,OAAO;EACV;EAAO,QAAQ;EAAG,YAAY;EAC9B,iBAAiB,OAAO,EAAoB,OAAO,CAAC;EACpD,gBAAgB,GAAG,EAAI,KAAK,EAAI;EAChC,oBAAoB,IAAI,KAAI,EAAM,MAAM,IAAI,EAAE;EAC9C,kBAAkB;EAClB,gBAAgB;EAChB,GAAG;EACJ,EAAI,CAAA;;;;ACpET,SAAgB,EAAU,EACxB,UAAO,WACP,UAAO,MACP,YAAS,IACT,eAAY,IACZ,WAAQ,IACR,kBACA,IAAI,IAAM,QACV,eAAY,IACZ,UACA,aACA,GAAG,KACc;CACjB,IAAM,IAAY,WAAW,KACvB,IAAY,WAAW,KACvB,IAAc,IAAS,KAAK,qBAC5B,IAAa,IAAY,kBAAkB,IAC3C,IAAa,IAAQ,4BAA4B,IAEjD,IAAmC,EAAE;CAM3C,AALI,KAAiB,OAEV,KAAa,KAAiB,SACvC,EAAY,gBAAgB,KAF5B,EAAY,gBAAgB,GAI1B,KAAO,OAAO,OAAO,GAAa,EAAM;CAE5C,IAAI,IAAU;CAad,OAZI,KAAS,OAAO,KAAa,aAC/B,IAAU,EAAS,MAAM,GAAG,CAAC,KAAK,GAAM,MACtC,kBAAC,QAAD;EAEE,WAAU;EACV,OAAO,EAAE,gBAAgB,GAAG,IAAI,KAAM,IAAI;YAEzC,MAAS,MAAM,SAAW;EACtB,EALA,EAKA,CACP,GAIF,kBAAC,GAAD;EACE,WAAW,UAAU,EAAU,GAAG,EAAU,GAAG,EAAY,GAAG,EAAW,GAAG,EAAW,GAAG,IAAY,MAAM;EAC5G,OAAO,OAAO,KAAK,EAAY,CAAC,SAAS,IAAI,IAAc,KAAA;EAC3D,GAAI;YAEH;EACG,CAAA;;;;AC/EV,IAAa,IAAa,GAAM,EAC9B,aAAU,eAAY,IAAI,UAAO,IAAO,WAAQ,cAAW,IAAO,UAAO,GAAG,QAK1E,kBAAC,OAAD;CACE,KAJa,EAAQ,EAIhB;CACL,WAAW,WAAW;CACf;CACP,GAAI;WAJN,CAME,kBAAC,OAAD;EAAK,WAAU;EAAiB;EAAe,CAAA,EAC9C,KAAU,CAAC,KACV,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAiB,SAAS,GAAU,CAAA;EAChC,CAAA,CAEJ;GAER;AACF,EAAW,cAAc;AAIzB,IAAa,IAAkB,GAAM,EAAE,aAAU,eAAY,IAAI,UAAO,GAAG,QACzE,kBAAC,OAAD;CACE,WAAW,iBAAiB;CACrB;CACP,GAAI;CAEH;CACG,CAAA,CACN;AACF,EAAgB,cAAc;AAqB9B,SAAgB,EAAY,EAC1B,UAAO,UAAU,UAAO,MAAM,eAAY,IAAO,cAAW,IAAO,eAAY,IAAO,YAAS,UAAO,eAAY,IAAI,eACnG;CACnB,IAAM,IAA0B,MAAS,OAAO,OAAO,MAAS,OAAO,OAAO,MAAS,OAAO,OAAO;CAErG,OACE,kBAAC,UAAD;EACE,MAAK;EACL,WAAW,gBAAgB,EAAK,UAAU,EAAK,GAAG,IAAY,gBAAgB,GAAG,GAAG,IAAW,oBAAoB,GAAG,GAAG;EAC/G;EACD;EACF;YAEP,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD;IAAW,MAAM;IAAqB;IAAY;IAAqB,CAAA;GACnE,CAAA;EACC,CAAA;;AAIb,SAAgB,EAAgB,EAAE,cAAqC;CACrE,OACE,kBAAC,OAAD;EAAK,WAAU;EAAmC,OAAO,EAAE,SAAS,SAAS;YAC3E,kBAAC,GAAD;GAAa,MAAK;GAAS,MAAK;GAAK,WAAA;GAAmB;GAAS,WAAU;aAAa;GAAkB,CAAA;EACtG,CAAA;;AAeV,SAAgB,EAAW,EAAE,aAAU,SAAM,YAAS,UAAO,cAAW,cAAW,MAAyB;CAG1G,OAFK,IAGH,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GACE,QAAQ,IAAW,IAAU,KAAA;GAC7B,WAAW,WAAW,KAAa;aAFrC,CAIG,KAAS,kBAAC,GAAD;IAAW,IAAG;IAAK,MAAK;IAAK,WAAU;cAAkB;IAAkB,CAAA,EACpF,EACU;;EACT,CAAA,GAXU;;;;ACtFpB,SAAgB,GAAU,EAAE,SAAM,cAAW,gBAAa,eAAY,IAAI,YAAyB;CACjG,OACE,kBAAC,OAAD;EAAK,WAAW,UAAU;EAAoB;YAC3C,EAAK,KAAK,MACT,kBAAC,IAAD;GAEE,OAAO,EAAI;GACX,QAAQ,MAAc,EAAI;GAC1B,eAAe,EAAY,EAAI,GAAG;GAClC,EAJK,EAAI,GAIT,CACF;EACE,CAAA;;AAIV,SAAS,GAAU,EAAE,UAAO,WAAQ,cAAoE;CACtG,OACE,kBAAC,OAAD;EAAK,WAAU;EAAQ,eAAa;YAApC,CACE,kBAAC,OAAD;GACE,WAAU;GACV,eAAa;GACb,eAAA;aAEA,kBAAC,OAAD;IAAK,OAAO;IAAI,QAAQ;IAAI,SAAQ;cAClC,kBAAC,WAAD,EAAS,QAAO,iBAAkB,CAAA;IAC9B,CAAA;GACF,CAAA,EACN,kBAAC,UAAD;GACE,MAAK;GACL,WAAU;GACV,eAAa;GACJ;aAET,kBAAC,GAAD;IAAW,MAAK;IAAK,MAAK;cAAW;IAAkB,CAAA;GAChD,CAAA,CACL;;;AAOV,SAAgB,GAAkB,EAAE,SAAM,cAAW,gBAAa,eAAY,IAAI,YAAyB;CACzG,OACE,kBAAC,OAAD;EAAK,WAAW,WAAW;EAAoB;YAC5C,EAAK,KAAK,MAAQ;GACjB,IAAM,IAAW,MAAc,EAAI;GACnC,OACE,kBAAC,UAAD;IAEE,MAAK;IACL,WAAU;IACV,eAAa;IACb,eAAe,EAAY,EAAI,GAAG;cAElC,kBAAC,GAAD;KAAW,MAAK;KAAK,MAAM,IAAW,YAAY;eAAS,EAAI;KAAkB,CAAA;IAC1E,EAPF,EAAI,GAOF;IAEX;EACE,CAAA;;;;ACxEV,SAAgB,GAAc,EAAE,YAAS,aAAa,YAAS,IAAI,YAAS,IAAI,eAAgC;CAC9G,IAAM,IAA2B;EAAE,UAAU;EAAY;EAAQ;CAYjE,OAVI,EAAO,SAAS,MAAM,KAAE,EAAI,MAAM,IAClC,EAAO,SAAS,SAAS,KAAE,EAAI,SAAS,IAExC,EAAO,SAAS,OAAO,KAAE,EAAI,OAAO,IACpC,EAAO,SAAS,QAAQ,KAAE,EAAI,QAAQ,IACtC,EAAO,SAAS,SAAS,KAC3B,EAAI,OAAO,OACX,EAAI,YAAY,qBAIhB,kBAAC,OAAD;EAAK,OAAO;EACT;EACG,CAAA;;;;ACVV,SAAgB,GAAgB,EAAE,UAAO,aAAU,YAA+B;CAChF,OACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,KAAS,kBAAC,OAAD;GAAK,WAAU;aAAwB;GAAY,CAAA,EAC5D,EAAM,KAAI,MACT,kBAAC,UAAD;GAEE,MAAK;GACL,WAAU;GACV,eAAe,EAAS,EAAK,GAAG;aAJlC,CAME,kBAAC,OAAD;IAAK,WAAU;IAAiB,WAAS,EAAK;IAAM,CAAA,EACnD,EAAK,MACC;KAPF,EAAK,GAOH,CACT,CACE;KACK,CAAA;;;;ACjBjB,SAAgB,GAAW,EAAE,UAAO,MAAM,UAAO,QAAQ,cAAW,eAA6B;CAC/F,OACE,kBAAC,QAAD;EAAM,WAAW,oBAAoB,EAAK,YAAY,EAAK,GAAG,KAAa;EACxE;EACI,CAAA;;;;ACEX,SAAgB,GAAc,EAC5B,WACA,WACA,aAAU,IACV,aAAU,IACV,eAAY,YACZ,eAAY,QACZ,aACA,eAAY,IACZ,YACqB;CACrB,OACE,kBAAC,OAAD;EAAK,WAAW,WAAW;EAAoB;YAA/C;GACE,kBAAC,GAAD;IAAW,WAAU;IAAQ,SAAS;IAAQ,UAAU,CAAC;IAAS,cAAY;IAAa,CAAA;GAC3F,kBAAC,OAAD;IAAK,WAAU;IAAoB;IAAe,CAAA;GAClD,kBAAC,GAAD;IAAW,WAAU;IAAQ,SAAS;IAAQ,UAAU,CAAC;IAAS,cAAY;IAAa,CAAA;GACvF;;;AAIV,SAAS,EAAU,EACjB,cACA,YACA,aACA,cAAc,KAMb;CACD,IAAM,CAAC,GAAS,KAAc,EAAM,SAAS,GAAM;CACnD,OACE,kBAAC,UAAD;EACE,MAAK;EACL,WAAU;EACV,gBAAc,KAAW,CAAC;EACjB;EACC;EACV,cAAY;EACZ,OAAO;EACP,mBAAmB,CAAC,KAAY,EAAW,GAAK;EAChD,iBAAiB,EAAW,GAAM;EAClC,oBAAoB,EAAW,GAAM;EACrC,oBAAoB,CAAC,KAAY,EAAW,GAAK;EACjD,kBAAkB,EAAW,GAAM;YAEnC,kBAAC,IAAD,EAAuB,cAAa,CAAA;EAC7B,CAAA;;AAIb,SAAS,GAAW,EAAE,gBAA8C;CAElE,OACE,kBAAC,OAAD;EAAK,OAAO;EAAI,QAAQ;EAAI,SAAQ;EAAY,MAAK;EAAO,QAAO;EAAe,aAAa;EAAG,eAAc;EAAQ,gBAAe;EAAQ,eAAA;YAC7I,kBAAC,YAAD,EAAkB,QAHP,MAAc,SAAS,oBAAoB,oBAG1B,CAAA;EACxB,CAAA;;;;ACjDV,SAAgB,EAAe,EAC7B,WACA,mBACA,uBAAoB,aACpB,iBAAc,UACd,SACA,iBACA,eAAY,WACZ,gBACA,eAAY,IACZ,YACsB;CACtB,OACE,kBAAC,OAAD;EAAK,WAAW,gBAAgB;EAAoB;YAApD,CACG,IACC,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAW,MAAK;eAAM;KAAwB,CAAA;IAC1C,CAAA,EACN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD,EAAc,CAAA;KACV,CAAA,EACN,kBAAC,SAAD;KACE,MAAK;KACL,OAAO,KAAU;KACjB,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;KAC/C,aAAa;KACb,WAAU;KACV,CAAA,CACE;MACF;OACJ,MAEH,KAAe,IACd,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAW,MAAK;eAAM;KAAsB,CAAA;IACxC,CAAA,EACN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,UAAD;KACE,OAAO,KAAQ,EAAY,IAAI;KAC/B,WAAW,MAAM,EAAa,EAAE,OAAO,MAAM;KAC7C,WAAU;eAET,EAAY,KAAK,MAChB,kBAAC,UAAD;MAAwB,OAAO,EAAI;gBAAQ,EAAI;MAAe,EAAjD,EAAI,MAA6C,CAC9D;KACK,CAAA,EACT,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD,EAAY,CAAA;KACR,CAAA,CACF;MACF;OACJ,KACA;;;AAIV,SAAS,IAAa;CACpB,OACE,kBAAC,OAAD;EAAK,OAAO;EAAI,QAAQ;EAAI,SAAQ;EAAY,MAAK;EAAO,QAAO;EAAe,aAAa;EAAG,eAAc;EAAQ,gBAAe;EAAQ,eAAA;YAA/I,CACE,kBAAC,UAAD;GAAQ,IAAI;GAAI,IAAI;GAAI,GAAG;GAAK,CAAA,EAChC,kBAAC,QAAD;GAAM,IAAI;GAAI,IAAI;GAAI,IAAI;GAAO,IAAI;GAAS,CAAA,CAC1C;;;AAIV,SAAS,IAAW;CAClB,OACE,kBAAC,OAAD;EAAK,OAAO;EAAI,QAAQ;EAAI,SAAQ;EAAY,MAAK;EAAO,QAAO;EAAe,aAAa;EAAK,eAAc;EAAQ,gBAAe;EAAQ,eAAA;YAAjJ;GACE,kBAAC,YAAD,EAAU,QAAO,YAAa,CAAA;GAC9B,kBAAC,YAAD,EAAU,QAAO,gBAAiB,CAAA;GAClC,kBAAC,YAAD,EAAU,QAAO,cAAe,CAAA;GAChC,kBAAC,YAAD,EAAU,QAAO,qBAAsB,CAAA;GACnC;;;;;ACpGV,IAAM,IAAQ;CACZ;EAAE,MAAM;EAAM,IAAI;EAAc;CAChC;EAAE,MAAM;EAAM,IAAI;EAAc;CAChC;EAAE,MAAM;EAAM,IAAI;EAAgB;CAClC;EAAE,MAAM;EAAM,IAAI;EAAa;CAChC;AAUD,SAAgB,EAAmB,EAAE,eAAY,MAA+B;CAC9E,OACE,kBAAC,OAAD;EAAK,WAAW,YAAY;YAA5B,CACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,KAAD;IAAG,WAAU;cAAb;KACE,kBAAC,QAAD,EAAA,UAAA,CAAM,iDAA8C,IAAW,EAAA,CAAA;KAC/D,kBAAC,KAAD;MACI,MAAK;MACL,QAAO;MACP,KAAI;MACJ,WAAU;gBACb;MAEG,CAAA;KACJ,kBAAC,QAAD,EAAA,UAAA;MAAO;MAAI;MAAe;MAAW,EAAA,CAAA;KACrC,kBAAC,QAAD;MAAM,WAAU;gBAAhB;OACE,kBAAC,QAAD;QAAM,WAAU;kBACb,EAAM,KAAK,EAAE,SAAM,YAClB,kBAAC,QAAD;SAAiB,WAAU;SAAsB,OAAO,EAAE,eAAe,GAAI;mBAC1E;SACI,EAFI,EAEJ,CACP;QACG,CAAA;OAAC;OAAI;OAEP;;KACL;;GACA,CAAA,EACN,kBAAC,SAAD,EAAA,UAAQ,ivBAKE,CAAA,CACN;;;;;ACnCV,SAAgB,IAAkB;CAGhC,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;EACE,KALY,GAKP;EACL,eAAA;EACA,OAAO;GACL,UAAU;GACV,OAAO;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,eAAe;GAChB;EACD,CAAA,EACF,kBAAC,GAAD,EAAsB,CAAA,CACrB,EAAA,CAAA;;;;ACdP,SAAS,EAAa,GAAsC,GAAU;CACpE,AAAI,OAAO,KAAQ,aAAY,EAAI,EAAM,GAChC,KAAO,OAAO,KAAQ,aAE7B,EAAa,UAAU;;AAQ3B,SAAgB,EAAa,EAC3B,YACA,aACA,UAAO,QACP,eAAY,QACZ,WAAQ,IACR,cAAW,KACX,cAAW,MACS;CACpB,IAAM,EACJ,YACA,QACA,cACA,eACA,SACA,SACA,uBACE,EAAgB;EAAE;EAAM;EAAW;EAAO;EAAU,CAAC,EAEnD,IAAQ,EAAM,SAAS,KAAK,EAAS,EAUrC,IAAY,EAAc,KAC1B,IAAa,GAAa,MAA6B;EAE3D,AADA,EAAU,UAAU,GACpB,EAAU,GAAU,EAAK;IACxB,CAAC,GAAU,EAAU,CAAC;CAWzB,OACE,kBAAA,GAAA,EAAA,UAAA,CAVc,EAAM,aAAa,GAAO;EACxC,KAAK;EACL,eAAe,MAAwB;GAAU,AAAR,GAAM,EAAE,EAAM,MAAM,eAAe,EAAE;;EAC9E,eAAe,MAAwB;GAAU,AAAR,GAAM,EAAE,EAAM,MAAM,eAAe,EAAE;;EAC9E,UAAe,MAAwB;GAAU,AAAR,GAAM,EAAE,EAAM,MAAM,UAAU,EAAE;;EACzE,SAAe,MAAwB;GAAU,AAAR,GAAM,EAAE,EAAM,MAAM,SAAS,EAAE;;EACxE,cAAe,MAAwB;GAAsB,AAApB,EAAgB,EAAE,EAAE,EAAM,MAAM,cAAc,EAAE;;EAC1F,CAII,EACA,IACC,kBAAC,OAAD;EACE,KAAK;EACL,MAAK;EACL,WAAU;EACV,OAAO;GACL,MAAM,GAAK,QAAQ;GACnB,KAAK,GAAK,OAAO;GACjB;GACA,SAAS;GACV;YAEA;EACG,CAAA,GACJ,KACH,EAAA,CAAA;;;;ACpFP,SAAgB,EAAe,EAAE,SAAM,aAAU,aAAU,eAAY,MAA2B;CAChG,IAAM,CAAC,GAAQ,KAAa,EAAS,GAAM;CAQ3C,OACE,kBAAC,OAAD;EAAK,WAAW,gBAAgB;YAAhC,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KAAY,kBAAC,QAAD;KAAM,WAAU;eAA0B;KAAgB,CAAA,EACtE,KAAY,kBAAC,QAAD;KAAM,WAAU;eAAsB;KAAgB,CAAA,CAC/D;OACN,kBAAC,UAAD;IACE,eAdW;KAGjB,AAFA,UAAe,UAAU,UAAU,EAAK,EACxC,EAAU,GAAK,EACf,iBAAiB,EAAU,GAAM,EAAE,IAAK;;IAYlC,OAAM;IACN,WAAU;IACV,eAAa;cAEZ,IACG,kBAAC,OAAD;KAAK,OAAM;KAAK,QAAO;KAAK,SAAQ;KAAY,MAAK;KAAO,QAAO;KAAe,aAAY;KAAM,eAAc;KAAQ,gBAAe;eAAQ,kBAAC,YAAD,EAAU,QAAO,kBAAkB,CAAA;KAAM,CAAA,GAC1L,kBAAC,OAAD;KAAK,OAAM;KAAK,QAAO;KAAK,SAAQ;KAAY,MAAK;KAAO,QAAO;KAAe,aAAY;KAAI,eAAc;KAAQ,gBAAe;eAAvI,CAA+I,kBAAC,QAAD;MAAM,GAAE;MAAI,GAAE;MAAI,OAAM;MAAK,QAAO;MAAK,IAAG;MAAK,CAAA,EAAA,kBAAC,QAAD,EAAM,GAAE,2DAA2D,CAAA,CAAM;;IAEtQ,CAAA,CACL;MACN,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,QAAD,EAAA,UAAO,GAAY,CAAA;GACf,CAAA,CACF;;;;;ACvBV,SAAgB,EAAS,EAAE,aAAU,UAAO,eAAY,IAAI,GAAG,KAAwB;CAErF,OACE,kBAAC,OAAD;EAAK,WAFS,QAAQ,IAAQ,kBAAkB,GAAG,GAAG,IAAY,MAElD;EAAS,GAAI;EAC1B;EACG,CAAA;;AAKV,SAAgB,GAAe,EAAE,aAAU,eAAY,IAAI,GAAG,KAAuC;CACnG,OACE,kBAAC,OAAD;EAAK,WAAW,iBAAiB;EAAa,GAAI;EAC/C;EACG,CAAA;;AAKV,SAAgB,EAAe,EAAE,aAAU,eAAY,IAAI,GAAG,KAAuC;CACnG,OACE,kBAAC,OAAD;EAAK,WAAW,iBAAiB;EAAa,GAAI;EAC/C;EACG,CAAA;;;;AC1BV,SAAgB,EAAmB,EAAE,UAAO,UAAO,QAAQ,eAAY,MAA+B;CACpG,OACE,kBAAC,OAAD;EAAK,WAAW,oBAAoB;YAApC,CACE,kBAAC,OAAD;GAAK,WAAW,+BAA+B;aAAS;GAAY,CAAA,EACpE,kBAAC,OAAD,EAAK,WAAW,gCAAgC,KAAU,CAAA,CACtD;;;;;ACNV,SAAgB,EAAc,EAAE,SAAM,aAAU,eAAY,IAAI,GAAG,KAA6B;CAE9F,OACE,kBAAC,OAAD;EAAK,WAAW,eAFE,IAAO,aAAa,MAAS,GAEJ,GAAG;EAAa,OAAO,IAAO,EAAE,aAAa,KAAA,GAAW,GAAG,KAAA;EAAW,GAAI;EAClH;EACG,CAAA;;AAKV,SAAgB,EAAkB,EAAE,aAAU,eAAY,MAAyD;CACjH,OAAO,kBAAC,OAAD;EAAK,WAAW,qBAAqB;EAAc;EAAe,CAAA;;AAI3E,SAAgB,EAAmB,EAAE,aAAU,eAAY,MAAyD;CAClH,OAAO,kBAAC,OAAD;EAAK,WAAW,sBAAsB;EAAc;EAAe,CAAA;;AAI5E,SAAgB,EAAiB,EAAE,aAAU,eAAY,MAAyD;CAChH,OAAO,kBAAC,OAAD;EAAK,WAAW,oBAAoB;EAAc;EAAe,CAAA;;AAI1E,SAAgB,EAAmB,EAAE,aAAU,eAAY,MAAyD;CAClH,OAAO,kBAAC,OAAD;EAAK,WAAW,sBAAsB;EAAc;EAAe,CAAA;;;;ACW5E,SAAgB,GAAS,EACvB,WAAQ,WACR,cAAW,gBACX,gBAAa,EAAE,EACf,iBAAc,EAAE,EAChB,YACA,gBACA,oBACA,oBACgB;CAChB,OACE,kBAAC,GAAD,EAAA,UAAA;EAEE,kBAAC,OAAD;GAAK,OAAO;IAAE,SAAS;IAAiB,SAAS;IAAQ,eAAe;IAAU,KAAK;IAAG;aAA1F;IAEE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAW,MAAK;MAAK,MAAK;gBAAQ;MAAkB,CAAA,EACpD,kBAAC,GAAD;MAAW,MAAK;MAAQ,MAAK;MAAO,OAAO,EAAE,eAAe,GAAG;gBAAG;MAAqB,CAAA,CACnF;;IAGL,KACC,kBAAC,OAAD;KAAK,WAAU;KAA2B,OAAO;MAC/C,SAAS;MACT,YAAY;MAAsB,cAAc;MAChD,QAAQ;MACT;eAJD,CAKE,kBAAC,GAAD;MAAW,MAAK;MAAQ,MAAK;gBAAU,EAAQ;MAAmB,CAAA,EAClE,kBAAC,GAAD;MAAW,MAAK;MAAQ,MAAK;gBAAQ,EAAQ;MAAqB,CAAA,CAC9D;;IAIP,EAAW,SAAS,KACnB,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;KAAoB,OAAM;KAAU,MAAK;KAAS,CAAA,EAClD,kBAAC,OAAD;KAAK,WAAU;KAAa,OAAO,EAAE,KAAK,GAAG;eAC1C,EAAW,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG,MAC9B,kBAAC,GAAD;MAEE,MAAM,EAAE;MACR,eAAe,IAAgB,GAAG,EAAE;MACpC,OAAO,EAAE,QAAQ,IAAgB,YAAY,KAAA,GAAW;gBAJ1D;OAME,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAE,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK,GAAM,MAC/B,kBAAC,OAAD;SAAa,OAAO;UAAE,OAAO;UAAI,QAAQ;UAAI,SAAS;UAAQ,YAAY;UAAU,gBAAgB;UAAU;mBAC5G,kBAAC,GAAD;UAAmB;UAAM,OAAO;UAAM,CAAA;SAClC,EAFI,EAEJ,CACN;QACE,CAAA;OACN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAqB,EAAE,MAA0B,CAAA,EACjD,kBAAC,GAAD,EAAA,UAAA,CAAkB,OAAI,EAAE,OAA0B,EAAA,CAAA,CAChC,EAAA,CAAA;OACpB,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;QAAW,MAAK;QAAK,MAAM,EAAE,SAAS,SAAS,SAAS,EAAE;kBAAO,EAAE;QAAiB,CAAA,EACjE,CAAA;OACP;QAnBT,EAmBS,CAChB;KACE,CAAA,CACL,EAAA,CAAA;IAIJ,EAAY,SAAS,KACpB,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;KAAoB,OAAM;KAAS,MAAK;KAAU,CAAA,EAClD,kBAAC,OAAD;KAAK,OAAO,EAAE,YAAY,KAAK;eAC5B,EAAY,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG,MAC/B,kBAAC,OAAD;MAAa,WAAU;gBAAvB;OACE,kBAAC,GAAD;QAAW,MAAK;QAAQ,MAAK;kBAAQ,EAAE;QAAiB,CAAA;OACxD,kBAAC,GAAD;QAAW,MAAK;QAAQ,MAAK;kBAAQ,EAAE;QAAuB,CAAA;OAC7D,EAAE,QAAQ,KAAK,kBAAC,GAAD;QAAW,MAAK;QAAQ,MAAK;kBAA7B,CAAqC,KAAE,EAAE,MAAkB;;OACvE;QAJI,EAIJ,CACN;KACE,CAAA,CACL,EAAA,CAAA;IAED;;EAEN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GAAa,MAAK;GAAQ,WAAA;GAAU,MAAK;GAAK,SAAS;aAAa;GAAwB,CAAA,EAC5F,kBAAC,GAAD;GAAa,MAAK;GAAQ,WAAA;GAAU,MAAK;GAAK,SAAS;aAAiB;GAA4B,CAAA,CACrF,EAAA,CAAA;EACjB,kBAAC,GAAD,EAAsB,CAAA;EACb,EAAA,CAAA;;;;AC5Hf,SAAgB,GAAa,EAAE,UAAO,YAA4B;CAChE,IAAM,CAAC,GAAQ,KAAa,EAAS,GAAM;CAE3C,SAAS,IAAO;EACd,UAAU,UAAU,UAAU,EAAM,CAAC,WAAW;GAE9C,AADA,EAAU,GAAK,EACf,iBAAiB,EAAU,GAAM,EAAE,KAAK;IACxC;;CAGJ,OACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,KACC,kBAAC,GAAD;GAAW,MAAK;GAAK,MAAK;GAAO,WAAU;aACxC;GACS,CAAA,EAEd,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAW,MAAK;eAAM;KAAkB,CAAA;IACpC,CAAA,EACN,kBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,eAAa;IACb,SAAS;cAER,IAAS,WAAW;IACd,CAAA,CACL;KACF;;;;;AC9BV,SAAgB,GAAc,EAAE,UAAO,aAAU,eAAY,MAA0B;CACrF,OACE,kBAAC,OAAD;EAAK,WAAW,cAAc;YAA9B,CACE,kBAAC,OAAD;GAAK,WAAU;aAAqB;GAAY,CAAA,EAC/C,KAAY,kBAAC,OAAD;GAAK,WAAU;aAAmB;GAAe,CAAA,CAC1D;;;;;ACFV,SAAgB,GAAc,EAAE,UAAO,eAAY,IAAI,GAAG,KAA6B;CACrF,OACE,kBAAC,OAAD;EAAK,WAAW,eAAe;EAAa,GAAI;YAC7C,EAAM,KAAK,MACV,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;GAAK,WAAU;aAAsB,EAAK;GAAY,CAAA,EACtD,kBAAC,OAAD;GAAK,WAAU;aAAsB,EAAK;GAAY,CAAA,CAClD,EAAA,EAHI,EAAK,MAGT,CACN;EACE,CAAA;;;;ACdV,SAAgB,EAAW,EAAE,aAAU,eAAY,IAAI,GAAG,KAA0B;CAClF,OACE,kBAAC,OAAD;EAAK,WAAW,WAAW;EAAa,GAAI;EACzC;EACG,CAAA;;;;ACRV,IAAM,IAAI;AAWV,SAAgB,GAAgB,EAC9B,YACA,UACA,cAAc,GACd,cAAW,IACX,UAAO,MACP,eACuB;CACvB,IAAM,CAAC,GAAO,KAAY,EAAS,GAAM,EACnC,IAAO,MAAS,OAAO,KAAK;CAElC,OACE,kBAAC,UAAD;EACE,cAAY,KAAa;EACf;EACV,eAAe,CAAC,KAAY,KAAW;EACvC,oBAAoB,EAAS,GAAK;EAClC,oBAAoB,EAAS,GAAM;EACnC,OAAO;GACL,OAAO;GACP,QAAQ;GACR,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,YAAY,KAAS,CAAC,IAAW,EAAE,YAAY,EAAE;GACjD,OAAO,EAAE;GACT,QAAQ,aAAa,EAAE;GACvB,cAAc;GACd,QAAQ,IAAW,gBAAgB;GACnC,SAAS,IAAW,MAAO;GAC3B,SAAS;GACT,UAAU;GACV,YAAY;GACZ,YAAY;GACb;EACM;EACP,MAAK;EAEJ;EACM,CAAA;;;;ACjDb,IAAM,IAAI;AAeV,SAAgB,GAAgB,EAC9B,SACA,UACA,YACA,gBACA,kBAAe,IACf,kBAAe,WACf,iBAAc,UACd,aACA,cACA,eACuB;CACvB,IAAM,CAAC,GAAO,KAAY,EAAS,EAAa,EAC1C,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,IAAW,EAAgC,KAAK,EAEhD,CAAC,GAAU,KAAe,EAAS,EAAK;CAU9C,AARI,MAAS,MACX,EAAY,EAAK,EACb,MACF,EAAS,EAAa,EACtB,EAAS,KAAK,IAIlB,QAAgB;EACd,IAAI,GAAM;GACR,IAAM,IAAI,iBAAiB,EAAS,SAAS,OAAO,EAAE,GAAG;GACzD,aAAa,aAAa,EAAE;;IAE7B,CAAC,EAAK,CAAC;CAEV,SAAS,IAAS;EAChB,IAAM,IAAM,IAAW,EAAM,IAAI;EACjC,IAAI,GAAK;GACP,EAAS,EAAI;GACb;;EAEF,EAAU,EAAM;;CAGlB,OACE,kBAAC,GAAD;EAAY,SAAS;EAAgB;EAAa;YAAlD;GACG,KACC,kBAAC,GAAD;IACE,MAAK;IACL,OAAO;KAAE,SAAS;KAAS,cAAc;KAAG;IAC5C,MAAK;cAEJ;IACS,CAAA;GAEd,kBAAC,SAAD;IACE,gBAAc,IAAQ,SAAS;IAC/B,WAAW,MAAM;KAEf,AADA,EAAS,EAAE,OAAO,MAAM,EACpB,KACF,EAAS,KAAK;;IAGlB,YAAY,MAAM;KAIhB,AAHI,EAAE,QAAQ,WACZ,GAAQ,EAEN,EAAE,QAAQ,YACZ,GAAU;;IAGD;IACb,KAAK;IACL,OAAO;KACL,OAAO;KACP,SAAS;KACT,YAAY,EAAE;KACd,OAAO,EAAE;KACT,QAAQ,aAAa,IAAQ,EAAE,MAAM,EAAE;KACvC,cAAc;KACd,UAAU;KACV,YAAY;KACZ,eAAe;KACf,SAAS;KACT,WAAW;KACZ;IACD,MAAK;IACE;IACP,CAAA;GACD,KACC,kBAAC,GAAD;IACE,MAAK;IACL,OAAO;KAAE,SAAS;KAAS,WAAW;KAAG;IACzC,MAAK;cAEJ;IACS,CAAA;GAEd,kBAAC,OAAD;IACE,OAAO;KACL,SAAS;KACT,gBAAgB;KAChB,KAAK;KACL,WAAW;KACZ;cANH,CAQE,kBAAC,GAAD;KAAa,SAAS;KAAU,MAAK;KAAK,MAAK;eAC5C;KACW,CAAA,EACd,kBAAC,GAAD;KAAa,SAAS;KAAQ,MAAK;KAAK,MAAK;eAC1C;KACW,CAAA,CACV;;GACK;;;;;AChIjB,IAAM,IAAI;AAoBV,SAAgB,GAAY,EAC1B,UACA,YACA,aACA,gBACA,cAAW,IACX,eAAY,IACZ,UAAO,MACP,UACA,cAAc,KACK;CACnB,IAAI;CACJ,AAKE,IALE,EAAQ,WAAW,IACR,EAAE,GACN,OAAO,EAAQ,MAAO,WACjB,EAAqB,KAAK,OAAO,EAAE,OAAO,GAAG,EAAE,GAEhD;CAGf,IAAM,IAAM,MAAS,OAAO,YAAY,YAClC,IAAW,MAAS,OAAO,KAAK;CAEtC,OACE,kBAAC,UAAD;EACE,cAAY;EACF;EACV,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;EACzC,OAAO;GACL,OAAO,IAAY,SAAS,KAAA;GAC5B,SAAS;GACT,YAAY,EAAE;GACd,OAAO,EAAE;GACT,QAAQ,aAAa,EAAE;GACvB,cAAc;GACd;GACA,YAAY;GACZ,QAAQ,IAAW,gBAAgB;GACnC,SAAS,IAAW,MAAO;GAC3B,YAAY;GACZ,iBACE,6CACA,EAAE,YACF,oCACA,EAAE,YACF;GACF,oBAAoB;GACpB,gBAAgB;GAChB,kBAAkB;GAClB,cAAc;GACd,GAAG;GACJ;EACM;YA5BT,CA8BG,MAAgB,KAAA,KACf,kBAAC,UAAD;GAAQ,UAAA;GAAS,OAAM;aACpB;GACM,CAAA,EAEV,EAAW,KAAK,MACf,kBAAC,UAAD;GAAQ,UAAU,EAAI;GAA0B,OAAO,EAAI;aACxD,EAAI,SAAS,EAAI;GACX,EAF4B,EAAI,MAEhC,CACT,CACK;;;;;ACpFb,IAAM,IAAI;AASV,SAAgB,GAAc,EAC5B,iBAAc,YACd,WACA,gBACA,cAAc,KACO;CACrB,IAAM,IAAc,EAAO,GAAM,EAC3B,IAAU,EAAO,EAAE,EACnB,IAAY,EAAO,EAAO;CAChC,QAAsB;EACpB,EAAU,UAAU;GACpB;CAEF,IAAM,IAAoB,GACvB,MAAuC;EAItC,AAHA,EAAE,gBAAgB,EAClB,EAAG,OAAuB,kBAAkB,EAAE,UAAU,EACxD,EAAY,UAAU,IACtB,EAAQ,UAAU,MAAgB,aAAa,EAAE,UAAU,EAAE;IAE/D,CAAC,EAAY,CACd;CAED,QAAgB;EACd,SAAS,EAAK,GAAiB;GAC7B,IAAI,CAAC,EAAY,SACf;GAEF,IAAM,IAAM,MAAgB,aAAa,EAAE,UAAU,EAAE,SACjD,IAAQ,IAAM,EAAQ;GAC5B,AAAI,MAAU,MACZ,EAAQ,UAAU,GAClB,EAAU,QAAQ,EAAM;;EAG5B,SAAS,IAAK;GACZ,EAAY,UAAU;;EAKxB,OAHA,OAAO,iBAAiB,eAAe,EAAK,EAC5C,OAAO,iBAAiB,aAAa,EAAG,EACxC,OAAO,iBAAiB,iBAAiB,EAAG,QAC/B;GAGX,AAFA,OAAO,oBAAoB,eAAe,EAAK,EAC/C,OAAO,oBAAoB,aAAa,EAAG,EAC3C,OAAO,oBAAoB,iBAAiB,EAAG;;IAEhD,CAAC,EAAY,CAAC;CAEjB,IACM,IAAa,MAAgB;CAEnC,OACE,kBAAC,UAAD;EACE,cAAY,KAAa;EACzB,YAAY,MAAM;GACX,MAGD,KAAc,EAAE,QAAQ,eAC1B,EAAY,IAAM,EAEhB,KAAc,EAAE,QAAQ,gBAC1B,EAAY,GAAK,EAEf,CAAC,KAAc,EAAE,QAAQ,aAC3B,EAAY,IAAM,EAEhB,CAAC,KAAc,EAAE,QAAQ,eAC3B,EAAY,GAAK;;EAGrB,eAAe;EACf,OAAO;GACL,KAAK;GACL,SAAS;GACT,MAAM;GACN,OAAO,IAAa,IAAI,KAAA;GACxB,QAAQ,IAAa,KAAA,IAAY;GACjC,QAAQ,IAAa,eAAe;GACpC,YAAY,EAAE;GACd,YAAY,IAAa,aAAa,EAAE,UAAU,KAAA;GAClD,aAAa,IAAa,aAAa,EAAE,UAAU,KAAA;GACnD,WAAW,IAAa,KAAA,IAAY,aAAa,EAAE;GACnD,cAAc,IAAa,KAAA,IAAY,aAAa,EAAE;GACtD,aAAa;GACb,YAAY;GACb;EACD,MAAK;EACL,CAAA"}
1
+ {"version":3,"file":"ui-BRMCKSX4.js","names":[],"sources":["../../src/ui/hooks.ts","../../src/ui/sprites.tsx","../../src/ui/jimboText.tsx","../../src/ui/panel.tsx","../../src/ui/jimboTabs.tsx","../../src/ui/jimboFlankNav.tsx","../../src/ui/JimboFloating.tsx","../../src/ui/JimboToggleList.tsx","../../src/ui/JimboBadge.tsx","../../src/ui/jimboFilterBar.tsx","../../src/ui/footer.tsx","../../src/ui/jimboBackground.tsx","../../src/ui/jimboTooltip.tsx","../../src/ui/codeBlock.tsx","../../src/ui/jimboApp.tsx","../../src/ui/jimboSectionHeader.tsx","../../src/ui/jimboInfoCard.tsx","../../src/ui/showcase.tsx","../../src/ui/jimboCopyRow.tsx","../../src/ui/jimboWordmark.tsx","../../src/ui/jimboStatGrid.tsx","../../src/ui/jimboInset.tsx","../../src/ui/JimboIconButton.tsx","../../src/ui/JimboInputModal.tsx","../../src/ui/JimboSelect.tsx","../../src/ui/PanelSplitter.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react'\r\nimport { JamlVisualClause, JamlVisualFilter, JamlZone } from '../components/JamlIdeVisual.js'\r\nimport { JIMBO_ANIMATIONS } from './tokens.js'\r\nimport { Layer } from '../render/Layer.js'\r\nimport { SPRITE_SHEETS } from '../sprites/spriteData.js'\r\n\r\nfunction loadImage(url: string): Promise<HTMLImageElement | null> {\r\n return new Promise((resolve) => {\r\n const image = new window.Image()\r\n image.addEventListener('load', () => resolve(image))\r\n image.addEventListener('error', () => resolve(null))\r\n image.src = url\r\n })\r\n}\r\n\r\nfunction renderImage(\r\n canvas: HTMLCanvasElement,\r\n context: CanvasRenderingContext2D,\r\n image: HTMLImageElement,\r\n layer: Layer,\r\n timestamp?: number,\r\n) {\r\n if (!image || !layer || !layer?.pos) return 0\r\n const cardWidth = image.width / layer.columns\r\n const cardHeight = image.height / layer.rows\r\n const canvasStyle = canvas.style\r\n\r\n if (layer.order === 0) {\r\n canvas.width = cardWidth\r\n canvas.height = cardHeight\r\n canvasStyle.width = `${cardWidth}px`\r\n canvasStyle.height = `${cardHeight}px`\r\n }\r\n\r\n canvasStyle.imageRendering = 'pixelated'\r\n context.imageSmoothingEnabled = true\r\n\r\n context.save()\r\n\r\n if (layer.animated && timestamp) {\r\n const elapsed = timestamp\r\n const yOffset = Math.sin(elapsed / 1000) * 3\r\n const xOffset = Math.sin(elapsed / 1500) * 1.5\r\n context.globalAlpha = 0.65 + (Math.sin(elapsed / 2000) + 1) * 0.075\r\n context.translate(xOffset, yOffset)\r\n }\r\n\r\n context.drawImage(image, layer.pos.x * cardWidth, layer.pos.y * cardHeight, cardWidth, cardHeight, 0, 0, canvas.width, canvas.height)\r\n context.restore()\r\n\r\n return cardWidth / cardHeight\r\n}\r\n\r\n/**\r\n * Sway animation for Balatro-style UI elements.\r\n */\r\nexport function useSway(active: boolean) {\r\n const ref = useRef<HTMLDivElement>(null)\r\n\r\n useEffect(() => {\r\n if (!active || !ref.current) return\r\n let frame: number\r\n const start = Date.now()\r\n const el = ref.current\r\n const tick = () => {\r\n const t = ((Date.now() - start) % JIMBO_ANIMATIONS.SWAY_DURATION) / JIMBO_ANIMATIONS.SWAY_DURATION * Math.PI * 2\r\n el.style.transform = `translate(${Math.sin(t) * JIMBO_ANIMATIONS.SWAY_AMOUNT * 0.3}px, ${Math.sin(t * 0.8) * JIMBO_ANIMATIONS.SWAY_AMOUNT}px)`\r\n frame = requestAnimationFrame(tick)\r\n }\r\n frame = requestAnimationFrame(tick)\r\n return () => {\r\n cancelAnimationFrame(frame)\r\n if (el) el.style.transform = ''\r\n }\r\n }, [active])\r\n\r\n return ref\r\n}\r\n\r\n/**\r\n * Handles delayed visibility for transitions (e.g. modals).\r\n */\r\nexport function useDelayedVisibility(open: boolean, delay: number) {\r\n const [visible, setVisible] = useState(open)\r\n const [opacity, setOpacity] = useState(open ? 1 : 0)\r\n const [prevOpen, setPrevOpen] = useState(open)\r\n\r\n if (open !== prevOpen) {\r\n setPrevOpen(open)\r\n if (open) {\r\n setVisible(true)\r\n } else {\r\n setOpacity(0)\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n if (open) {\r\n const frame = requestAnimationFrame(() => setOpacity(1))\r\n return () => cancelAnimationFrame(frame)\r\n } else {\r\n const t = setTimeout(() => setVisible(false), delay)\r\n return () => clearTimeout(t)\r\n }\r\n }, [open, delay])\r\n\r\n return { visible, opacity }\r\n}\r\n\r\n/**\r\n * Hook for the Balatro hypnotic swirl background.\r\n * Manages WebGL context, shader compilation, and animation loop.\r\n */\r\nexport function useBalatroBackground() {\r\n const canvasRef = useRef<HTMLCanvasElement>(null)\r\n\r\n useEffect(() => {\r\n const canvas = canvasRef.current\r\n if (!canvas) return\r\n\r\n const gl = canvas.getContext('webgl')\r\n if (!gl) return\r\n\r\n const vsSource = `\r\n attribute vec2 position;\r\n void main() {\r\n gl_Position = vec4(position, 0.0, 1.0);\r\n }\r\n `\r\n\r\n const fsSource = `\r\n precision mediump float;\r\n\r\n uniform float u_time;\r\n uniform vec2 u_resolution;\r\n\r\n const float SPIN_ROTATION = -2.0;\r\n const float SPIN_SPEED = 4.5;\r\n const vec4 COLOUR_1 = vec4(1.0, 0.2, 0.2, 1.0);\r\n const vec4 COLOUR_2 = vec4(0.0, 0.5, 1.0, 1.0);\r\n const vec4 COLOUR_3 = vec4(0.05, 0.08, 0.1, 1.0);\r\n const float CONTRAST = 4.5;\r\n const float LIGTHING = 0.5;\r\n const float SPIN_AMOUNT = 0.35;\r\n const float PIXEL_FILTER = 1024.0;\r\n const float PI = 3.14159265359;\r\n\r\n void main() {\r\n vec2 screenSize = u_resolution;\r\n float pixel_size = length(screenSize.xy) / PIXEL_FILTER;\r\n vec2 uv = (floor(gl_FragCoord.xy*(1.0/pixel_size))*pixel_size - 0.5*screenSize.xy)/length(screenSize.xy);\r\n float uv_len = length(uv);\r\n\r\n float speed = (SPIN_ROTATION * 0.2) + 302.2;\r\n float new_pixel_angle = atan(uv.y, uv.x) + speed - 20.0*(1.0*SPIN_AMOUNT*uv_len + (1.0 - 1.0*SPIN_AMOUNT));\r\n\r\n vec2 mid = (screenSize.xy/length(screenSize.xy))/2.0;\r\n uv = (vec2((uv_len * cos(new_pixel_angle) + mid.x), (uv_len * sin(new_pixel_angle) + mid.y)) - mid);\r\n\r\n uv *= 30.0;\r\n speed = u_time * SPIN_SPEED;\r\n vec2 uv2 = vec2(uv.x, uv.y);\r\n\r\n for(int i=0; i < 5; i++) {\r\n uv2 += sin(max(uv.x, uv.y)) + uv;\r\n uv += 0.5*vec2(cos(5.1123314 + 0.353*uv2.y + speed*0.131121), sin(uv2.x - 0.113*speed));\r\n uv -= 1.0*cos(uv.x + uv.y) - 1.0*sin(uv.x*0.711 - uv.y);\r\n }\r\n\r\n float contrast_mod = (0.25*CONTRAST + 0.5*SPIN_AMOUNT + 1.2);\r\n float paint_res = min(2.0, max(0.0, length(uv)*(0.035)*contrast_mod));\r\n float c1p = max(0.0, 1.0 - contrast_mod*abs(1.0 - paint_res));\r\n float c2p = max(0.0, 1.0 - contrast_mod*abs(paint_res));\r\n float c3p = 1.0 - min(1.0, c1p + c2p);\r\n float light = (LIGTHING - 0.2)*max(c1p*5.0 - 4.0, 0.0) + LIGTHING*max(c2p*5.0 - 4.0, 0.0);\r\n\r\n vec4 finalCol = (0.3/CONTRAST)*COLOUR_1 + (1.0 - 0.3/CONTRAST)*(COLOUR_1*c1p + COLOUR_2*c2p + vec4(c3p*COLOUR_3.rgb, c3p*COLOUR_1.a)) + light;\r\n\r\n gl_FragColor = finalCol;\r\n }\r\n `\r\n\r\n const createShader = (type: number, source: string) => {\r\n const shader = gl.createShader(type)\r\n if (!shader) return null\r\n gl.shaderSource(shader, source)\r\n gl.compileShader(shader)\r\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\r\n console.error('[JimboBackground] shader compile error:', gl.getShaderInfoLog(shader))\r\n gl.deleteShader(shader)\r\n return null\r\n }\r\n return shader\r\n }\r\n\r\n const vertexShader = createShader(gl.VERTEX_SHADER, vsSource)\r\n const fragmentShader = createShader(gl.FRAGMENT_SHADER, fsSource)\r\n if (!vertexShader || !fragmentShader) return\r\n\r\n const program = gl.createProgram()\r\n if (!program) return\r\n gl.attachShader(program, vertexShader)\r\n gl.attachShader(program, fragmentShader)\r\n gl.linkProgram(program)\r\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\r\n console.error('[JimboBackground] program link error:', gl.getProgramInfoLog(program))\r\n return\r\n }\r\n\r\n gl.useProgram(program)\r\n\r\n const positionBuffer = gl.createBuffer()\r\n gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)\r\n gl.bufferData(\r\n gl.ARRAY_BUFFER,\r\n new Float32Array([\r\n -1.0, -1.0, 1.0, -1.0, -1.0, 1.0,\r\n -1.0, 1.0, 1.0, -1.0, 1.0, 1.0,\r\n ]),\r\n gl.STATIC_DRAW,\r\n )\r\n\r\n const positionLocation = gl.getAttribLocation(program, 'position')\r\n gl.enableVertexAttribArray(positionLocation)\r\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0)\r\n\r\n const timeLocation = gl.getUniformLocation(program, 'u_time')\r\n const resolutionLocation = gl.getUniformLocation(program, 'u_resolution')\r\n\r\n const startTime = Date.now()\r\n let animationFrameId: number\r\n\r\n const render = () => {\r\n const displayWidth = canvas.clientWidth\r\n const displayHeight = canvas.clientHeight\r\n if (canvas.width !== displayWidth || canvas.height !== displayHeight) {\r\n canvas.width = displayWidth\r\n canvas.height = displayHeight\r\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight)\r\n }\r\n\r\n const currentTime = (Date.now() - startTime) / 1000.0\r\n gl.uniform1f(timeLocation, currentTime)\r\n gl.uniform2f(resolutionLocation, canvas.width, canvas.height)\r\n\r\n gl.drawArrays(gl.TRIANGLES, 0, 6)\r\n animationFrameId = requestAnimationFrame(render)\r\n }\r\n\r\n render()\r\n\r\n return () => {\r\n cancelAnimationFrame(animationFrameId)\r\n gl.deleteProgram(program)\r\n gl.deleteShader(vertexShader)\r\n gl.deleteShader(fragmentShader)\r\n gl.deleteBuffer(positionBuffer)\r\n }\r\n }, [])\r\n\r\n return canvasRef\r\n}\r\n\r\nexport type JimboTooltipMode = 'snap' | 'mouse'\r\nexport type JimboTooltipPlacement = 'top' | 'bottom' | 'auto'\r\n\r\n/**\r\n * Hook for managing JimboTooltip state and positioning.\r\n */\r\nexport function useJimboTooltip({\r\n mode = 'snap',\r\n placement = 'auto',\r\n delay = 80,\r\n disabled = false,\r\n}: {\r\n mode?: JimboTooltipMode\r\n placement?: JimboTooltipPlacement\r\n delay?: number\r\n disabled?: boolean\r\n}) {\r\n const [visible, setVisible] = useState(false)\r\n const [pos, setPos] = useState<{ left: number; top: number; align: 'top' | 'bottom' } | null>(null)\r\n const targetRef = useRef<HTMLElement | null>(null)\r\n const tooltipRef = useRef<HTMLDivElement | null>(null)\r\n const delayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\r\n\r\n const show = useCallback(() => {\r\n if (disabled) return\r\n if (delayTimerRef.current) clearTimeout(delayTimerRef.current)\r\n delayTimerRef.current = setTimeout(() => setVisible(true), delay)\r\n }, [disabled, delay])\r\n\r\n const hide = useCallback(() => {\r\n if (delayTimerRef.current) clearTimeout(delayTimerRef.current)\r\n setVisible(false)\r\n setPos(null)\r\n }, [])\r\n\r\n const computeSnapPos = useCallback(() => {\r\n const el = targetRef.current\r\n const tip = tooltipRef.current\r\n if (!el || !tip) return\r\n const rect = el.getBoundingClientRect()\r\n const tipRect = tip.getBoundingClientRect()\r\n const roomAbove = rect.top\r\n const align: 'top' | 'bottom' =\r\n placement === 'top' ? 'top'\r\n : placement === 'bottom' ? 'bottom'\r\n : roomAbove >= tipRect.height + 12 ? 'top' : 'bottom'\r\n\r\n const left = rect.left + rect.width / 2 - tipRect.width / 2\r\n const top = align === 'top' ? rect.top - tipRect.height - 8 : rect.bottom + 8\r\n setPos({\r\n left: Math.max(8, Math.min(window.innerWidth - tipRect.width - 8, left)),\r\n top,\r\n align\r\n })\r\n }, [placement])\r\n\r\n useEffect(() => {\r\n if (!visible || mode !== 'snap') return\r\n const raf = requestAnimationFrame(computeSnapPos)\r\n window.addEventListener('resize', computeSnapPos)\r\n window.addEventListener('scroll', computeSnapPos, true)\r\n return () => {\r\n cancelAnimationFrame(raf)\r\n window.removeEventListener('resize', computeSnapPos)\r\n window.removeEventListener('scroll', computeSnapPos, true)\r\n }\r\n }, [visible, mode, computeSnapPos])\r\n\r\n useEffect(() => () => {\r\n if (delayTimerRef.current) clearTimeout(delayTimerRef.current)\r\n }, [])\r\n\r\n const handleMouseMove = useCallback((e: React.MouseEvent | React.PointerEvent) => {\r\n if (mode !== 'mouse') return\r\n setPos({ left: e.clientX + 12, top: e.clientY + 16, align: 'bottom' })\r\n }, [mode])\r\n\r\n return {\r\n visible,\r\n pos,\r\n targetRef,\r\n tooltipRef,\r\n show,\r\n hide,\r\n handleMouseMove,\r\n }\r\n}\r\n\r\n/**\r\n * Hook for managing the JamlCardRenderer logic.\r\n */\r\nexport function useJamlCardRenderer({\r\n layers,\r\n invert = false,\r\n hoverTilt = false,\r\n}: {\r\n layers: Layer[]\r\n invert?: boolean\r\n hoverTilt?: boolean\r\n}) {\r\n const canvasRef = useRef<HTMLCanvasElement>(null)\r\n const imageCacheRef = useRef<Map<string, HTMLImageElement>>(new Map())\r\n const [ratio, setRatio] = useState(3 / 4)\r\n const [, forceUpdate] = useState(0)\r\n const animationFrameRef = useRef<number | null>(null)\r\n const [elapsed, setElapsed] = useState(0)\r\n const [isHovered, setIsHovered] = useState(false)\r\n const [transform, setTransform] = useState('none')\r\n\r\n const hasAnimatedLayer = layers?.some((layer) => layer.animated)\r\n\r\n // Preload all known sheets once\r\n useEffect(() => {\r\n let cancelled = false\r\n const imageCache = imageCacheRef.current\r\n const preload = async () => {\r\n const urls = Array.from(new Set(Object.values(SPRITE_SHEETS).map((sheet) => sheet.src)))\r\n const images = await Promise.all(urls.map((url) => loadImage(url)))\r\n if (cancelled) return\r\n images.forEach((image, index) => {\r\n if (image) imageCache.set(urls[index], image)\r\n })\r\n forceUpdate((prev) => prev + 1)\r\n }\r\n\r\n preload().catch((err) => console.error('[JamlCardRenderer]', err))\r\n\r\n return () => {\r\n cancelled = true\r\n imageCache.clear()\r\n }\r\n }, [])\r\n\r\n // Animation loop for animated layers\r\n useEffect(() => {\r\n if (!hasAnimatedLayer) return\r\n\r\n let startTime: number\r\n const animate = (timestamp: number) => {\r\n if (!startTime) startTime = timestamp\r\n const now = timestamp - startTime\r\n if (!animationFrameRef.current || timestamp - 100 > animationFrameRef.current) {\r\n animationFrameRef.current = timestamp\r\n setElapsed(now)\r\n }\r\n animationFrameRef.current = requestAnimationFrame(animate)\r\n }\r\n\r\n animationFrameRef.current = requestAnimationFrame(animate)\r\n return () => {\r\n if (animationFrameRef.current) cancelAnimationFrame(animationFrameRef.current)\r\n }\r\n }, [hasAnimatedLayer])\r\n\r\n // Core drawing logic\r\n useEffect(() => {\r\n const canvas = canvasRef.current\r\n if (!canvas || !layers || layers.length === 0) return\r\n const context = canvas.getContext('2d')\r\n if (!context) return\r\n let cancelled = false\r\n\r\n context.clearRect(0, 0, canvas.width, canvas.height)\r\n ;[...layers]\r\n .sort((a, b) => a.order - b.order)\r\n .forEach((layer) => {\r\n if (imageCacheRef.current.has(layer.source)) {\r\n const image = imageCacheRef.current.get(layer.source)\r\n if (!image) return\r\n const imageRatio = renderImage(canvas, context, image, layer, hasAnimatedLayer ? elapsed : undefined)\r\n if (layer.order === 0) setRatio(imageRatio)\r\n return\r\n }\r\n loadImage(layer.source).then((img) => {\r\n if (cancelled || !img) return\r\n const imageRatio = renderImage(canvas, context, img, layer, hasAnimatedLayer ? elapsed : undefined)\r\n imageCacheRef.current.set(layer.source, img)\r\n if (layer.order === 0) setRatio(imageRatio)\r\n forceUpdate((prev) => prev + 1)\r\n })\r\n })\r\n\r\n canvas.style.filter = invert ? 'invert(0.94)' : 'none'\r\n return () => { cancelled = true }\r\n }, [layers, elapsed, invert, hasAnimatedLayer])\r\n\r\n const onPointerEnter = (event: React.PointerEvent) => {\r\n if (!hoverTilt || event.pointerType === 'touch') return\r\n setIsHovered(true)\r\n }\r\n\r\n const onPointerLeave = () => {\r\n if (!hoverTilt) return\r\n setIsHovered(false)\r\n setTransform('none')\r\n }\r\n\r\n const onPointerMove = (event: React.PointerEvent<HTMLDivElement>) => {\r\n if (!hoverTilt || event.pointerType === 'touch') return\r\n const rect = event.currentTarget.getBoundingClientRect()\r\n const x = event.clientX - rect.left\r\n const y = event.clientY - rect.top\r\n const rotateY = (x / rect.width) * 12 - 6\r\n const rotateX = (y / rect.height) * -16 + 8\r\n const juiceScale = 1.05\r\n const juiceY = -2 // slight move up\r\n setTransform(`perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(${juiceScale}) translateY(${juiceY}px)`)\r\n }\r\n\r\n const containerStyle: React.CSSProperties = {\r\n aspectRatio: String(ratio),\r\n width: '100%',\r\n display: 'flex',\r\n perspective: hoverTilt ? '1000px' : undefined,\r\n userSelect: 'none',\r\n WebkitUserSelect: 'none',\r\n }\r\n\r\n const canvasStyle: React.CSSProperties = {\r\n transition: hoverTilt && !isHovered ? 'transform 0.4s ease, box-shadow 0.4s ease-out' : 'transform 0.1s ease-out',\r\n transform: hoverTilt ? (isHovered ? transform : 'none') : undefined,\r\n transformStyle: hoverTilt ? 'preserve-3d' : undefined,\r\n transformOrigin: hoverTilt ? 'center center' : undefined,\r\n borderRadius: '6px',\r\n boxShadow: hoverTilt && isHovered ? '0 2px 12px rgba(0,0,0,0.3)' : '0 2px 8px rgba(0,0,0,0.2)',\r\n imageRendering: 'pixelated',\r\n pointerEvents: 'none',\r\n }\r\n\r\n return {\r\n canvasRef,\r\n containerStyle,\r\n canvasStyle,\r\n handlers: {\r\n onPointerEnter: hoverTilt ? onPointerEnter : undefined,\r\n onPointerLeave: hoverTilt ? onPointerLeave : undefined,\r\n onPointerMove: hoverTilt ? onPointerMove : undefined,\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Tracks which 'ante' section is currently most visible in a scrollable container.\r\n * Used in JamlAnalyzerFullscreen and AnalyzerExplorer.\r\n */\r\nexport function useAnteTracker(antes: { ante: number }[], options: { threshold?: number[] } = {}) {\r\n const [currentAnte, setCurrentAnte] = useState(antes[0]?.ante ?? 0)\r\n const [prevFirstAnte, setPrevFirstAnte] = useState(antes[0]?.ante)\r\n const scrollRef = useRef<HTMLDivElement>(null)\r\n const anteRefs = useRef<Map<number, HTMLElement>>(new Map())\r\n\r\n if (antes[0]?.ante !== prevFirstAnte) {\r\n setPrevFirstAnte(antes[0]?.ante)\r\n if (antes.length > 0) {\r\n setCurrentAnte(antes[0].ante)\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n const root = scrollRef.current\r\n if (!root || antes.length === 0) return\r\n\r\n const observer = new IntersectionObserver(\r\n (entries) => {\r\n // Find the entry with the highest intersection ratio\r\n const mostVisible = entries\r\n .filter((e) => e.isIntersecting)\r\n .sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0]\r\n\r\n if (mostVisible) {\r\n const ante = Number((mostVisible.target as HTMLElement).dataset.ante)\r\n if (!Number.isNaN(ante)) {\r\n setCurrentAnte(ante)\r\n }\r\n }\r\n },\r\n {\r\n root,\r\n threshold: options.threshold ?? [0.4, 0.6, 0.8],\r\n }\r\n )\r\n\r\n anteRefs.current.forEach((el) => observer.observe(el))\r\n\r\n return () => observer.disconnect()\r\n }, [antes, options.threshold])\r\n\r\n const scrollToAnte = useCallback((ante: number) => {\r\n const el = anteRefs.current.get(ante)\r\n if (el) {\r\n el.scrollIntoView({ behavior: 'smooth', block: 'start' })\r\n }\r\n }, [])\r\n\r\n const registerAnteRef = useCallback((ante: number, el: HTMLElement | null) => {\r\n if (el) {\r\n anteRefs.current.set(ante, el)\r\n } else {\r\n anteRefs.current.delete(ante)\r\n }\r\n }, [])\r\n\r\n return {\r\n currentAnte,\r\n scrollRef,\r\n scrollToAnte,\r\n registerAnteRef,\r\n }\r\n}\r\n\r\nexport interface DragState {\r\n clause: JamlVisualClause\r\n fromZone: JamlZone\r\n x: number\r\n y: number\r\n offX: number\r\n offY: number\r\n}\r\n\r\ninterface PendingDragState {\r\n clause: JamlVisualClause\r\n fromZone: JamlZone\r\n x: number\r\n y: number\r\n offX: number\r\n offY: number\r\n}\r\n\r\n/**\r\n * Manages drag-and-drop state for the Jaml IDE visual filter editor.\r\n */\r\nexport function useJamlIdeDrag(\r\n filter: JamlVisualFilter,\r\n onChange: (filter: JamlVisualFilter) => void,\r\n rootRef: React.RefObject<HTMLDivElement | null>\r\n) {\r\n const [drag, setDrag] = useState<DragState | null>(null)\r\n const [pendingDrag, setPendingDrag] = useState<PendingDragState | null>(null)\r\n const [hoverZone, setHoverZone] = useState<string | null>(null)\r\n\r\n const onDragStart = useCallback(\r\n (e: React.MouseEvent | React.TouchEvent, clause: JamlVisualClause, fromZone: JamlZone) => {\r\n const t = 'touches' in e ? e.touches[0] : e\r\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\r\n setPendingDrag({\r\n clause,\r\n fromZone,\r\n x: t.clientX,\r\n y: t.clientY,\r\n offX: t.clientX - rect.left,\r\n offY: t.clientY - rect.top,\r\n })\r\n setHoverZone(null)\r\n },\r\n []\r\n )\r\n\r\n useEffect(() => {\r\n if (!pendingDrag && !drag) return\r\n\r\n const move = (e: MouseEvent | TouchEvent) => {\r\n const touchEvent = 'touches' in e ? (e as TouchEvent) : null\r\n const t = touchEvent ? touchEvent.touches[0] : (e as MouseEvent)\r\n if (!t) return\r\n\r\n let activeDrag = drag\r\n\r\n if (!activeDrag && pendingDrag) {\r\n const dx = t.clientX - pendingDrag.x\r\n const dy = t.clientY - pendingDrag.y\r\n if (Math.hypot(dx, dy) < 8) return\r\n activeDrag = {\r\n ...pendingDrag,\r\n x: t.clientX,\r\n y: t.clientY,\r\n }\r\n setPendingDrag(null)\r\n setDrag(activeDrag)\r\n } else if (activeDrag) {\r\n activeDrag = { ...activeDrag, x: t.clientX, y: t.clientY }\r\n setDrag(activeDrag)\r\n }\r\n\r\n if (!activeDrag) return\r\n if (touchEvent?.cancelable) touchEvent.preventDefault()\r\n\r\n const rails = rootRef.current?.querySelectorAll('[data-zone]') ?? []\r\n let found: string | null = null\r\n for (const r of rails) {\r\n const rc = r.getBoundingClientRect()\r\n if (t.clientX >= rc.left && t.clientX <= rc.right && t.clientY >= rc.top && t.clientY <= rc.bottom) {\r\n found = r.getAttribute('data-zone')\r\n break\r\n }\r\n }\r\n setHoverZone(found)\r\n }\r\n\r\n const up = () => {\r\n if (drag && hoverZone && hoverZone !== drag.fromZone) {\r\n const to = hoverZone as JamlZone\r\n onChange({\r\n ...filter,\r\n [drag.fromZone]: filter[drag.fromZone].filter((c) => c.id !== drag.clause.id),\r\n [to]: [...filter[to], { ...drag.clause }],\r\n })\r\n }\r\n setPendingDrag(null)\r\n setDrag(null)\r\n setHoverZone(null)\r\n }\r\n\r\n window.addEventListener('mousemove', move)\r\n window.addEventListener('mouseup', up)\r\n window.addEventListener('touchmove', move, { passive: false })\r\n window.addEventListener('touchend', up)\r\n\r\n return () => {\r\n window.removeEventListener('mousemove', move)\r\n window.removeEventListener('mouseup', up)\r\n window.removeEventListener('touchmove', move)\r\n window.removeEventListener('touchend', up)\r\n }\r\n }, [pendingDrag, drag, hoverZone, filter, onChange, rootRef])\r\n\r\n return {\r\n drag,\r\n hoverZone,\r\n onDragStart,\r\n }\r\n}\r\n\r\n/**\r\n * Provides a magnetic 3D tilt effect for DOM elements, replicating the 'juice' of Balatro cards.\r\n * Ensures the hit-detection area remains stable by separating container events from the transformed style.\r\n */\r\nexport function useDOMMagneticTilt(enabled: boolean = true) {\r\n const [isHovered, setIsHovered] = useState(false)\r\n const [transform, setTransform] = useState('none')\r\n\r\n const onPointerEnter = (event: React.PointerEvent) => {\r\n if (!enabled || event.pointerType === 'touch') return\r\n setIsHovered(true)\r\n }\r\n\r\n const onPointerLeave = () => {\r\n if (!enabled) return\r\n setIsHovered(false)\r\n setTransform('none')\r\n }\r\n\r\n const onPointerMove = (event: React.PointerEvent) => {\r\n if (!enabled || event.pointerType === 'touch') return\r\n const rect = event.currentTarget.getBoundingClientRect()\r\n const x = event.clientX - rect.left\r\n const y = event.clientY - rect.top\r\n const rotateY = (x / rect.width) * 12 - 6\r\n const rotateX = (y / rect.height) * -16 + 8\r\n const juiceScale = 1.05\r\n const juiceY = -2 // slight move up\r\n setTransform(`perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(${juiceScale}) translateY(${juiceY}px)`)\r\n }\r\n\r\n const handlers = {\r\n onPointerEnter: enabled ? onPointerEnter : undefined,\r\n onPointerLeave: enabled ? onPointerLeave : undefined,\r\n onPointerMove: enabled ? onPointerMove : undefined,\r\n }\r\n\r\n const tiltStyle: React.CSSProperties = {\r\n transition: enabled && !isHovered ? 'transform 0.4s ease, box-shadow 0.4s ease-out' : 'transform 0.1s ease-out',\r\n transform: enabled ? (isHovered ? transform : 'none') : undefined,\r\n transformStyle: enabled ? 'preserve-3d' : undefined,\r\n transformOrigin: enabled ? 'center center' : undefined,\r\n willChange: enabled ? 'transform' : undefined,\r\n pointerEvents: enabled ? 'none' : undefined,\r\n }\r\n\r\n return { handlers, tiltStyle, isHovered }\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\nimport { resolveJamlAssetUrl } from '../assets.js'\r\nimport { getSpriteData, getMysterySprite, SHEET_META, type SpriteSheetType } from '../sprites/spriteMapper.js'\r\n\r\nexport interface JimboSpriteProps {\r\n name: string\r\n sheet?: SpriteSheetType\r\n width?: number\r\n height?: number\r\n style?: React.CSSProperties\r\n}\r\n\r\nexport function JimboSprite({ name, sheet, width = 40, height, style }: JimboSpriteProps) {\r\n const sprite = getSpriteData(name)\r\n const resolvedSheet: SpriteSheetType = sheet ?? sprite?.type ?? 'Jokers'\r\n const meta = SHEET_META[resolvedSheet]\r\n const mystery = getMysterySprite(resolvedSheet)\r\n const pos = sprite?.pos ?? mystery.pos\r\n \r\n let defaultH = width;\r\n if ([\"Jokers\", \"Tarots\", \"Vouchers\", \"Boosters\", \"Decks\", \"Enhancers\", \"Editions\"].includes(resolvedSheet)) {\r\n defaultH = Math.round((width * 95) / 71);\r\n }\r\n const h = height ?? defaultH;\r\n\r\n if (!meta) return null\r\n\r\n const bgW = width * meta.cols\r\n const bgH = h * meta.rows\r\n const bgX = -(pos.x * width)\r\n const bgY = -(pos.y * h)\r\n\r\n return (\r\n <div style={{\r\n width, height: h, flexShrink: 0,\r\n backgroundImage: `url(${resolveJamlAssetUrl(meta.assetKey)})`,\r\n backgroundSize: `${bgW}px ${bgH}px`,\r\n backgroundPosition: `${bgX}px ${bgY}px`,\r\n backgroundRepeat: 'no-repeat',\r\n imageRendering: 'pixelated',\r\n ...style,\r\n }} />\r\n )\r\n}\r\n\r\nexport interface StakeSpriteProps {\r\n stake: string\r\n width?: number\r\n height?: number\r\n style?: React.CSSProperties\r\n}\r\n\r\nconst STAKE_MAP: string[] = [\"White\", \"Red\", \"Green\", \"Black\", \"Blue\", \"Purple\", \"Orange\", \"Gold\"]\r\n\r\nexport function StakeSprite({ stake, width = 29, height, style }: StakeSpriteProps) {\r\n const index = STAKE_MAP.indexOf(stake.replace(\" Stake\", \"\"))\r\n const idx = index >= 0 ? index : 0\r\n const x = idx % 5\r\n const y = Math.floor(idx / 5)\r\n const h = height ?? width\r\n const bgW = width * 5\r\n const bgH = h * 2\r\n\r\n return (\r\n <div style={{\r\n width, height: h, flexShrink: 0,\r\n backgroundImage: `url(${resolveJamlAssetUrl('stakes')})`,\r\n backgroundSize: `${bgW}px ${bgH}px`,\r\n backgroundPosition: `-${x * width}px -${y * h}px`,\r\n backgroundRepeat: 'no-repeat',\r\n imageRendering: 'pixelated',\r\n ...style,\r\n }} />\r\n )\r\n}\r\n\r\nexport interface DeckSpriteProps {\r\n deck: string\r\n width?: number\r\n height?: number\r\n style?: React.CSSProperties\r\n}\r\n\r\nconst DECK_ROWS: Record<string, number> = {\r\n Red: 0,\r\n Blue: 1,\r\n Yellow: 2,\r\n Green: 3,\r\n Black: 0,\r\n Magic: 1,\r\n Nebula: 2,\r\n Ghost: 3,\r\n}\r\n\r\nexport function DeckSprite({ deck, width = 71, height, style }: DeckSpriteProps) {\r\n const baseDeck = deck.replace(\" Deck\", \"\")\r\n const y = DECK_ROWS[baseDeck] ?? 0\r\n const x = 12\r\n const h = height ?? (width * 95 / 71)\r\n const bgW = width * 13\r\n const bgH = h * 4\r\n\r\n return (\r\n <div style={{\r\n width, height: h, flexShrink: 0,\r\n backgroundImage: `url(${resolveJamlAssetUrl('deck')})`,\r\n backgroundSize: `${bgW}px ${bgH}px`,\r\n backgroundPosition: `-${x * width}px -${y * h}px`,\r\n backgroundRepeat: 'no-repeat',\r\n imageRendering: 'pixelated',\r\n ...style,\r\n }} />\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\n\r\nexport type JimboTextTone =\r\n | 'default'\r\n | 'mult'\r\n | 'chips'\r\n | 'gold'\r\n | 'green'\r\n | 'red'\r\n | 'blue'\r\n | 'orange'\r\n | 'purple'\r\n | 'grey'\r\n | 'white'\r\n\r\nexport type JimboTextSize = 'micro' | 'label' | 'xs' | 'body' | 'sm' | 'md' | 'heading' | 'lg' | 'xl' | 'display'\r\n\r\nexport interface JimboTextProps extends React.HTMLAttributes<HTMLElement> {\r\n tone?: JimboTextTone\r\n size?: JimboTextSize\r\n /** Canonical Balatro drop shadow (1px right, 1px down, ${BLACK}cc). Default true. */\r\n shadow?: boolean\r\n /** Uppercase + spacing — Balatro button/pill label treatment. Default false. */\r\n uppercase?: boolean\r\n /** Wiggle effect for text characters. Default false. */\r\n dance?: boolean\r\n /** Letter-spacing override; defaults depend on uppercase prop. */\r\n letterSpacing?: number | string\r\n as?: 'span' | 'p' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label'\r\n children?: React.ReactNode\r\n}\r\n\r\n/**\r\n * Canonical pixel-font text wrapper. Uses `m6x11plus` as its family and\r\n * applies the authentic Balatro drop shadow by default. Prefer this over\r\n * hand-rolling `fontFamily: 'm6x11plus, monospace'` + `textShadow` strings\r\n * throughout consumers — it keeps the styling drift-free.\r\n *\r\n * Requires `import 'jaml-ui/fonts.css'` somewhere in the consumer bundle\r\n * so the @font-face declaration lands (font is base64-embedded, no\r\n * runtime fetch).\r\n */\r\nexport function JimboText({\r\n tone = 'default',\r\n size = 'md',\r\n shadow = true,\r\n uppercase = false,\r\n dance = false,\r\n letterSpacing,\r\n as: Tag = 'span',\r\n className = '',\r\n style,\r\n children,\r\n ...rest\r\n}: JimboTextProps) {\r\n const sizeClass = `j-text--${size}`\r\n const toneClass = `j-text--${tone}`\r\n const shadowClass = shadow ? '' : 'j-text--no-shadow'\r\n const upperClass = uppercase ? 'j-text--upper' : ''\r\n const danceClass = dance ? 'j-text--dance-container' : ''\r\n\r\n const inlineStyle: React.CSSProperties = {}\r\n if (letterSpacing != null) {\r\n inlineStyle.letterSpacing = letterSpacing\r\n } else if (uppercase && letterSpacing == null) {\r\n inlineStyle.letterSpacing = 2\r\n }\r\n if (style) Object.assign(inlineStyle, style)\r\n\r\n let content = children\r\n if (dance && typeof children === 'string') {\r\n content = children.split('').map((char, i) => (\r\n <span\r\n key={i}\r\n className=\"j-font-dance-char\"\r\n style={{ animationDelay: `${i * -0.15}s` }}\r\n >\r\n {char === ' ' ? '\\u00A0' : char}\r\n </span>\r\n ))\r\n }\r\n\r\n return (\r\n <Tag\r\n className={`j-text ${sizeClass} ${toneClass} ${shadowClass} ${upperClass} ${danceClass} ${className}`.trim()}\r\n style={Object.keys(inlineStyle).length > 0 ? inlineStyle : undefined}\r\n {...rest}\r\n >\r\n {content}\r\n </Tag>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React, { memo } from 'react'\r\nimport { useSway } from './hooks.js'\r\nimport { JimboText, type JimboTextSize } from './jimboText.js'\r\n\r\n// ─── Panel ───────────────────────────────────────────────────────────────────\r\n\r\nexport interface JimboPanelProps extends React.HTMLAttributes<HTMLDivElement> {\r\n sway?: boolean\r\n onBack?: () => void\r\n hideBack?: boolean\r\n}\r\nexport const JimboPanel = memo(({\r\n children, className = '', sway = false, onBack, hideBack = false, style, ...props\r\n}: JimboPanelProps) => {\r\n const panelRef = useSway(sway)\r\n\r\n return (\r\n <div\r\n ref={panelRef}\r\n className={`j-panel ${className}`}\r\n style={style}\r\n {...props}\r\n >\r\n <div className=\"j-panel__body\">{children}</div>\r\n {onBack && !hideBack && (\r\n <div className=\"j-panel__back\">\r\n <JimboBackButton onClick={onBack} />\r\n </div>\r\n )}\r\n </div>\r\n )\r\n})\r\nJimboPanel.displayName = 'JimboPanel'\r\n\r\nexport type JimboInnerPanelProps = React.HTMLAttributes<HTMLDivElement>;\r\n\r\nexport const JimboInnerPanel = memo(({ children, className = '', style, ...props }: JimboInnerPanelProps) => (\r\n <div\r\n className={`j-inner-panel ${className}`}\r\n style={style}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n))\r\nJimboInnerPanel.displayName = 'JimboInnerPanel'\r\n\r\n// ─── JimboButton ──────────────────────────────────────────────────────────────\r\n// Canonical flat 2D Balatro-style button.\r\n// Tones are purely CSS-driven via j-btn--{tone} classes in jimbo.css.\r\n// No JS color maps. No TONE_PAIRS. Respect the design tokens.\r\n\r\nexport type JimboTone = 'orange' | 'red' | 'blue' | 'green' | 'tarot' | 'planet' | 'spectral' | 'grey'\r\n\r\nexport interface JimboButtonProps {\r\n tone?: JimboTone\r\n size?: 'xs' | 'sm' | 'md' | 'lg'\r\n fullWidth?: boolean\r\n disabled?: boolean\r\n uppercase?: boolean\r\n onClick?: () => void\r\n style?: React.CSSProperties\r\n className?: string\r\n children?: React.ReactNode\r\n}\r\n\r\nexport function JimboButton({\r\n tone = 'orange', size = 'md', fullWidth = false, disabled = false, uppercase = false, onClick, style, className = '', children,\r\n}: JimboButtonProps) {\r\n const textSize: JimboTextSize = size === 'xs' ? 'xs' : size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'md'\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className={`j-btn j-btn--${tone} j-btn--${size} ${fullWidth ? 'j-btn--full' : ''} ${disabled ? 'j-btn--disabled' : ''} ${className}`}\r\n disabled={disabled}\r\n onClick={onClick}\r\n style={style}\r\n >\r\n <div className=\"j-btn__face\">\r\n <JimboText size={textSize} uppercase={uppercase}>{children}</JimboText>\r\n </div>\r\n </button>\r\n )\r\n}\r\n\r\nexport function JimboBackButton({ onClick }: { onClick?: () => void }) {\r\n return (\r\n <div className=\"j-flex j-justify-center j-w-full\" style={{ padding: '4px 0' }}>\r\n <JimboButton tone=\"orange\" size=\"md\" fullWidth onClick={onClick} className=\"j-back-btn\">Back</JimboButton>\r\n </div>\r\n )\r\n}\r\n\r\n// ─── Modal ───────────────────────────────────────────────────────────────────\r\n\r\nexport interface JimboModalProps {\r\n children: React.ReactNode\r\n open: boolean\r\n onClose: () => void\r\n title?: string\r\n className?: string\r\n showBack?: boolean\r\n}\r\n\r\nexport function JimboModal({ children, open, onClose, title, className, showBack = true }: JimboModalProps) {\r\n if (!open) return null\r\n\r\n return (\r\n <div className=\"j-modal-overlay\">\r\n <JimboPanel\r\n onBack={showBack ? onClose : undefined}\r\n className={`j-modal ${className ?? ''}`}\r\n >\r\n {title && <JimboText as=\"h2\" size=\"lg\" className=\"j-modal__title\">{title}</JimboText>}\r\n {children}\r\n </JimboPanel>\r\n </div>\r\n )\r\n}\r\n","'use client'\n\nimport * as React from 'react'\nimport { JimboText } from './jimboText.js'\n\nexport interface JimboTabItem {\n id: string\n label: string\n}\n\nexport interface JimboTabsProps {\n tabs: JimboTabItem[]\n activeTab: string\n onTabChange: (tabId: string) => void\n className?: string\n style?: React.CSSProperties\n}\n\n/**\n * Horizontal tab navigation with bouncing triangle indicator on the active\n * tab. Triangle attaches to each button and animates only on the active one.\n */\nexport function JimboTabs({ tabs, activeTab, onTabChange, className = '', style }: JimboTabsProps) {\n return (\n <div className={`j-tabs ${className}`} style={style}>\n {tabs.map((tab) => (\n <TabButton\n key={tab.id}\n label={tab.label}\n active={activeTab === tab.id}\n onClick={() => onTabChange(tab.id)}\n />\n ))}\n </div>\n )\n}\n\nfunction TabButton({ label, active, onClick }: { label: string; active: boolean; onClick: () => void }) {\n return (\n <div className=\"j-tab\" data-active={active}>\n <div\n className=\"j-tab__indicator\"\n data-active={active}\n aria-hidden\n >\n <svg width={14} height={10} viewBox=\"0 0 14 10\">\n <polygon points=\"7,10 0,0 14,0\" />\n </svg>\n </div>\n <button\n type=\"button\"\n className=\"j-tab__btn\"\n data-active={active}\n onClick={onClick}\n >\n <JimboText size=\"sm\" tone=\"default\">{label}</JimboText>\n </button>\n </div>\n )\n}\n\n/**\n * Vertical tab strip — rotated labels (writing-mode) for space efficiency.\n */\nexport function JimboVerticalTabs({ tabs, activeTab, onTabChange, className = '', style }: JimboTabsProps) {\n return (\n <div className={`j-vtabs ${className}`} style={style}>\n {tabs.map((tab) => {\n const isActive = activeTab === tab.id\n return (\n <button\n key={tab.id}\n type=\"button\"\n className=\"j-vtab\"\n data-active={isActive}\n onClick={() => onTabChange(tab.id)}\n >\n <JimboText size=\"sm\" tone={isActive ? 'default' : 'grey'}>{tab.label}</JimboText>\n </button>\n )\n })}\n </div>\n )\n}\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\n\r\nexport interface JimboFlankNavProps {\r\n onPrev: () => void\r\n onNext: () => void\r\n canPrev?: boolean\r\n canNext?: boolean\r\n prevLabel?: string\r\n nextLabel?: string\r\n children: React.ReactNode\r\n className?: string\r\n style?: React.CSSProperties\r\n}\r\n\r\n/**\r\n * Prev/next navigation with flanking buttons around a central stage.\r\n * No hardcoded labels, no lucide dep (inline chevron SVGs).\r\n */\r\nexport function JimboFlankNav({\r\n onPrev,\r\n onNext,\r\n canPrev = true,\r\n canNext = true,\r\n prevLabel = 'Previous',\r\n nextLabel = 'Next',\r\n children,\r\n className = '',\r\n style,\r\n}: JimboFlankNavProps) {\r\n return (\r\n <div className={`j-flank ${className}`} style={style}>\r\n <NavButton direction=\"left\" onClick={onPrev} disabled={!canPrev} aria-label={prevLabel} />\r\n <div className=\"j-flank__content\">{children}</div>\r\n <NavButton direction=\"right\" onClick={onNext} disabled={!canNext} aria-label={nextLabel} />\r\n </div>\r\n )\r\n}\r\n\r\nfunction NavButton({\r\n direction,\r\n onClick,\r\n disabled,\r\n 'aria-label': ariaLabel,\r\n}: {\r\n direction: 'left' | 'right'\r\n onClick: () => void\r\n disabled: boolean\r\n 'aria-label': string\r\n}) {\r\n const [pressed, setPressed] = React.useState(false)\r\n return (\r\n <button\r\n type=\"button\"\r\n className=\"j-flank__btn\"\r\n data-pressed={pressed && !disabled}\r\n onClick={onClick}\r\n disabled={disabled}\r\n aria-label={ariaLabel}\r\n title={ariaLabel}\r\n onMouseDown={() => !disabled && setPressed(true)}\r\n onMouseUp={() => setPressed(false)}\r\n onMouseLeave={() => setPressed(false)}\r\n onTouchStart={() => !disabled && setPressed(true)}\r\n onTouchEnd={() => setPressed(false)}\r\n >\r\n <ChevronSvg direction={direction} />\r\n </button>\r\n )\r\n}\r\n\r\nfunction ChevronSvg({ direction }: { direction: 'left' | 'right' }) {\r\n const points = direction === 'left' ? '18,4 8,14 18,24' : '10,4 20,14 10,24'\r\n return (\r\n <svg width={28} height={28} viewBox=\"0 0 28 28\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\r\n <polyline points={points} />\r\n </svg>\r\n )\r\n}\r\n","import React from 'react'\r\n\r\nexport interface JimboFloatingProps {\r\n anchor?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center'\r\n offset?: number\r\n zIndex?: number\r\n children: React.ReactNode\r\n}\r\n\r\nexport function JimboFloating({ anchor = 'top-right', offset = 12, zIndex = 20, children }: JimboFloatingProps) {\r\n const pos: React.CSSProperties = { position: 'absolute', zIndex };\r\n\r\n if (anchor.includes('top')) pos.top = offset;\r\n if (anchor.includes('bottom')) pos.bottom = offset;\r\n\r\n if (anchor.includes('left')) pos.left = offset;\r\n if (anchor.includes('right')) pos.right = offset;\r\n if (anchor.includes('center')) {\r\n pos.left = '50%';\r\n pos.transform = 'translateX(-50%)';\r\n }\r\n\r\n return (\r\n <div style={pos}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n","import React from 'react'\r\nimport { JimboPanel } from './panel.js'\r\n\r\nexport interface ToggleItem {\r\n id: string;\r\n label: string;\r\n on: boolean;\r\n}\r\n\r\nexport interface JimboToggleListProps {\r\n items: ToggleItem[];\r\n onToggle: (id: string) => void;\r\n title?: string;\r\n}\r\n\r\nexport function JimboToggleList({ items, onToggle, title }: JimboToggleListProps) {\r\n return (\r\n <JimboPanel>\r\n <div className=\"j-toggle-list\">\r\n {title && <div className=\"j-toggle-list__title\">{title}</div>}\r\n {items.map(item => (\r\n <button\r\n key={item.id}\r\n type=\"button\"\r\n className=\"j-toggle-item\"\r\n onClick={() => onToggle(item.id)}\r\n >\r\n <div className=\"j-toggle-check\" data-on={item.on} />\r\n {item.label}\r\n </button>\r\n ))}\r\n </div>\r\n </JimboPanel>\r\n )\r\n}\r\n","import React from 'react'\r\n\r\nexport type JimboBadgeTone = 'dark' | 'blue' | 'red' | 'green' | 'gold' | 'grey' | 'orange' | 'purple'\r\n\r\nexport interface JimboBadgeProps {\r\n size?: 'sm' | 'md'\r\n tone?: JimboBadgeTone\r\n children: React.ReactNode\r\n className?: string\r\n}\r\n\r\n/**\r\n * Small colored label pill. Matches Balatro's in-game tag/rarity badges.\r\n * All styling via jimbo.css `.j-badge` classes.\r\n */\r\nexport function JimboBadge({ size = 'sm', tone = 'dark', className, children }: JimboBadgeProps) {\r\n return (\r\n <span className={`j-badge j-badge--${size} j-badge--${tone} ${className ?? ''}`}>\r\n {children}\r\n </span>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\nimport { JimboText } from './jimboText.js'\r\n\r\nexport interface JimboFilterSortOption {\r\n value: string\r\n label: string\r\n}\r\n\r\nexport interface JimboFilterBarProps {\r\n search?: string\r\n onSearchChange?: (query: string) => void\r\n searchPlaceholder?: string\r\n searchLabel?: string\r\n\r\n sort?: string\r\n onSortChange?: (value: string) => void\r\n sortLabel?: string\r\n sortOptions?: JimboFilterSortOption[]\r\n\r\n className?: string\r\n style?: React.CSSProperties\r\n}\r\n\r\n/**\r\n * Generic Balatro-styled filter row: search input with floating pill label\r\n * + optional sort dropdown with floating pill label.\r\n */\r\nexport function JimboFilterBar({\r\n search,\r\n onSearchChange,\r\n searchPlaceholder = 'Search...',\r\n searchLabel = 'Search',\r\n sort,\r\n onSortChange,\r\n sortLabel = 'Sort By',\r\n sortOptions,\r\n className = '',\r\n style,\r\n}: JimboFilterBarProps) {\r\n return (\r\n <div className={`j-filter-bar ${className}`} style={style}>\r\n {onSearchChange ? (\r\n <div className=\"j-filter-bar__field\">\r\n <div className=\"j-filter-bar__pill\">\r\n <JimboText size=\"xs\">{searchLabel}</JimboText>\r\n </div>\r\n <div className=\"j-relative\">\r\n <div className=\"j-filter-bar__search-icon\">\r\n <SearchIcon />\r\n </div>\r\n <input\r\n type=\"text\"\r\n value={search ?? ''}\r\n onChange={(e) => onSearchChange(e.target.value)}\r\n placeholder={searchPlaceholder}\r\n className=\"j-filter-bar__input\"\r\n />\r\n </div>\r\n </div>\r\n ) : null}\r\n\r\n {sortOptions && onSortChange ? (\r\n <div className=\"j-filter-bar__field\">\r\n <div className=\"j-filter-bar__pill\">\r\n <JimboText size=\"xs\">{sortLabel}</JimboText>\r\n </div>\r\n <div className=\"j-relative\">\r\n <select\r\n value={sort ?? sortOptions[0]?.value}\r\n onChange={(e) => onSortChange(e.target.value)}\r\n className=\"j-filter-bar__select\"\r\n >\r\n {sortOptions.map((opt) => (\r\n <option key={opt.value} value={opt.value}>{opt.label}</option>\r\n ))}\r\n </select>\r\n <div className=\"j-filter-bar__sort-icon\">\r\n <SortIcon />\r\n </div>\r\n </div>\r\n </div>\r\n ) : null}\r\n </div>\r\n )\r\n}\r\n\r\nfunction SearchIcon() {\r\n return (\r\n <svg width={24} height={24} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={3} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\r\n <circle cx={11} cy={11} r={8} />\r\n <line x1={21} y1={21} x2={16.65} y2={16.65} />\r\n </svg>\r\n )\r\n}\r\n\r\nfunction SortIcon() {\r\n return (\r\n <svg width={20} height={20} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\r\n <polyline points=\"7 4 7 20\" />\r\n <polyline points=\"3 8 7 4 11 8\" />\r\n <polyline points=\"17 20 17 4\" />\r\n <polyline points=\"21 16 17 20 13 16\" />\r\n </svg>\r\n )\r\n}\r\n","'use client'\n\nimport React from 'react'\n\nconst SUITS = [\n { char: '♥️', kf: 'jaml-heart' },\n { char: '♠️', kf: 'jaml-spade' },\n { char: '♦️', kf: 'jaml-diamond' },\n { char: '♣️', kf: 'jaml-club' },\n] as const\n\nexport interface JimboBalatroFooterProps {\n className?: string\n}\n\n/**\n * Attribution footer with animated suit cycle.\n * Always rendered — required attribution for using Balatro art.\n */\nexport function JimboBalatroFooter({ className = '' }: JimboBalatroFooterProps) {\n return (\n <div className={`j-footer ${className}`}>\n <div className=\"j-footer__bar\">\n <p className=\"j-footer__text\">\n <span>Not affiliated with LocalThunk or PlayStack •{' '}</span>\n <a\n href=\"https://store.steampowered.com/app/2379780/Balatro/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"j-footer__link\"\n >\n BUY BALATRO\n </a>\n <span>{' '}• Created with{' '}</span>\n <span className=\"j-footer__suits\">\n <span className=\"j-footer__suit-stage\">\n {SUITS.map(({ char, kf }) => (\n <span key={char} className=\"j-footer__suit-char\" style={{ animationName: kf }}>\n {char}\n </span>\n ))}\n </span>{' '}\n for the Balatro community\n </span>\n </p>\n </div>\n <style>{`\n @keyframes jaml-heart { 0%{opacity:0;transform:scale(1)} 1%{opacity:1;transform:scale(1.45)} 3.5%{opacity:1;transform:scale(1)} 61.5%{opacity:1;transform:scale(1)} 62%{opacity:0} 100%{opacity:0} }\n @keyframes jaml-spade { 0%,61.5%{opacity:0} 62%{opacity:1;transform:scale(1.45)} 64.5%{opacity:1;transform:scale(1)} 71.5%{opacity:1} 72%{opacity:0} 100%{opacity:0} }\n @keyframes jaml-diamond { 0%,71.5%{opacity:0} 72%{opacity:1;transform:scale(1.45)} 74.5%{opacity:1;transform:scale(1)} 81.5%{opacity:1} 82%{opacity:0} 100%{opacity:0} }\n @keyframes jaml-club { 0%,81.5%{opacity:0} 82%{opacity:1;transform:scale(1.45)} 84.5%{opacity:1;transform:scale(1)} 95%{opacity:1} 96%{opacity:0} 100%{opacity:0} }\n `}</style>\n </div>\n )\n}\n","import React from 'react'\nimport { useBalatroBackground } from './hooks.js'\nimport { JimboBalatroFooter } from './footer.js'\n\n/**\n * Fullscreen WebGL CRT/spin background — the authentic Balatro hypnotic\n * swirl, pixelated and animated. Also renders the attribution footer at the\n * bottom of the viewport (position: fixed) so it is always present and no\n * consumer can accidentally omit it.\n *\n * Drop it once at the root of your page:\n *\n * <JimboBackground />\n * <YourAppContent />\n *\n * Resizes automatically. Disposes the animation frame + shader on unmount.\n */\nexport function JimboBackground() {\n const canvasRef = useBalatroBackground()\n\n return (\n <>\n <canvas\n ref={canvasRef}\n aria-hidden\n style={{\n position: 'fixed',\n inset: 0,\n width: '100%',\n height: '100%',\n zIndex: -10,\n pointerEvents: 'none',\n }}\n />\n <JimboBalatroFooter />\n </>\n )\n}\n","import React, { useCallback } from 'react'\r\nimport { useJimboTooltip, type JimboTooltipMode, type JimboTooltipPlacement } from './hooks.js'\r\n\r\nexport interface JimboTooltipProps {\r\n /** Content rendered inside the tooltip panel. Typically a card's ability text, joker description, etc. */\r\n content: React.ReactNode\r\n /** The target element the tooltip anchors to. */\r\n children: React.ReactElement\r\n /** `snap` (default): tooltip sits above/below the target's bounding rect.\r\n * `mouse`: tooltip follows the mouse position while hovering. */\r\n mode?: JimboTooltipMode\r\n /** Only used in `snap` mode. Default `auto` picks top if there's room, else bottom. */\r\n placement?: JimboTooltipPlacement\r\n /** Hover delay in ms before the tooltip appears. Default 80. */\r\n delay?: number\r\n /** Max width of the tooltip panel (px). Default 280. */\r\n maxWidth?: number\r\n /** Disable the tooltip entirely (e.g. when the target is disabled). */\r\n disabled?: boolean\r\n}\r\n\r\nfunction assignRef<T>(ref: React.Ref<T> | undefined | null, value: T) {\r\n if (typeof ref === 'function') ref(value)\r\n else if (ref && typeof ref === 'object') {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n (ref as any).current = value\r\n }\r\n}\r\n\r\n/**\r\n * Canonical Balatro-style tooltip: dark panel, silver border, pixel font.\r\n * Wrap any target to get a hover/focus popover.\r\n */\r\nexport function JimboTooltip({\r\n content,\r\n children,\r\n mode = 'snap',\r\n placement = 'auto',\r\n delay = 80,\r\n maxWidth = 280,\r\n disabled = false,\r\n}: JimboTooltipProps) {\r\n const {\r\n visible,\r\n pos,\r\n targetRef,\r\n tooltipRef,\r\n show,\r\n hide,\r\n handleMouseMove,\r\n } = useJimboTooltip({ mode, placement, delay, disabled })\r\n\r\n const child = React.Children.only(children) as React.ReactElement<{\r\n ref?: React.Ref<HTMLElement>\r\n onMouseEnter?: (e: React.MouseEvent) => void\r\n onMouseLeave?: (e: React.MouseEvent) => void\r\n onFocus?: (e: React.FocusEvent) => void\r\n onBlur?: (e: React.FocusEvent) => void\r\n onMouseMove?: (e: React.MouseEvent) => void\r\n }>\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const childRef = (child as any).ref\r\n const refHandler = useCallback((node: HTMLElement | null) => {\r\n targetRef.current = node\r\n assignRef(childRef, node)\r\n }, [childRef, targetRef])\r\n\r\n const wrapped = React.cloneElement(child, {\r\n ref: refHandler,\r\n onMouseEnter: (e: React.MouseEvent) => { show(); child.props.onMouseEnter?.(e) },\r\n onMouseLeave: (e: React.MouseEvent) => { hide(); child.props.onMouseLeave?.(e) },\r\n onFocus: (e: React.FocusEvent) => { show(); child.props.onFocus?.(e) },\r\n onBlur: (e: React.FocusEvent) => { hide(); child.props.onBlur?.(e) },\r\n onMouseMove: (e: React.MouseEvent) => { handleMouseMove(e); child.props.onMouseMove?.(e) },\r\n })\r\n\r\n return (\r\n <>\r\n {wrapped}\r\n {visible ? (\r\n <div\r\n ref={tooltipRef}\r\n role=\"tooltip\"\r\n className=\"j-tooltip\"\r\n style={{\r\n left: pos?.left ?? -9999,\r\n top: pos?.top ?? -9999,\r\n maxWidth,\r\n opacity: pos ? 1 : 0,\r\n }}\r\n >\r\n {content}\r\n </div>\r\n ) : null}\r\n </>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React, { useState } from 'react'\r\n\r\nexport interface JimboCodeBlockProps {\r\n code: string\r\n language?: string\r\n filename?: string\r\n className?: string\r\n}\r\n\r\nexport function JimboCodeBlock({ code, language, filename, className = '' }: JimboCodeBlockProps) {\r\n const [copied, setCopied] = useState(false)\r\n\r\n const copy = () => {\r\n void navigator.clipboard.writeText(code)\r\n setCopied(true)\r\n setTimeout(() => setCopied(false), 2000)\r\n }\r\n\r\n return (\r\n <div className={`j-code-block ${className}`}>\r\n <div className=\"j-code-block__header\">\r\n <div className=\"j-code-block__meta\">\r\n {filename && <span className=\"j-code-block__filename\">{filename}</span>}\r\n {language && <span className=\"j-code-block__lang\">{language}</span>}\r\n </div>\r\n <button\r\n onClick={copy}\r\n title=\"Copy\"\r\n className=\"j-code-block__copy\"\r\n data-copied={copied}\r\n >\r\n {copied\r\n ? <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>\r\n : <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>\r\n }\r\n </button>\r\n </div>\r\n <pre className=\"j-code-block__pre\">\r\n <code>{code}</code>\r\n </pre>\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\n// ─── App Shell ──────────────────────────────────────────────────────────────\r\n// Mobile-first 320px layout container. This is the DEFAULT layout for ALL\r\n// Jimbo UI screens — not just the \"demo\".\r\n//\r\n// Add `fluid` prop to unlock for MCP / desktop contexts (j-app--fluid).\r\n// In fluid mode the container stretches to fill its parent (up to 750px)\r\n// and container queries in jimbo.css activate \"cozy\" overrides at 401px+.\r\n\r\nexport interface JimboAppProps extends React.HTMLAttributes<HTMLDivElement> {\r\n children: React.ReactNode\r\n /** Unlock width/height for MCP inline or desktop use. Default: false (320×568 locked). */\r\n fluid?: boolean\r\n}\r\n\r\n/** Standard mobile-first app shell. 320px locked, or fluid for MCP/desktop. */\r\nexport function JimboApp({ children, fluid, className = '', ...props }: JimboAppProps) {\r\n const classes = `j-app${fluid ? ' j-app--fluid' : ''} ${className}`.trim()\r\n return (\r\n <div className={classes} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n\r\n/** Scrollable content area inside JimboApp. Hidden scrollbar, snap-friendly. */\r\nexport function JimboAppScroll({ children, className = '', ...props }: Omit<JimboAppProps, 'fluid'>) {\r\n return (\r\n <div className={`j-app__scroll ${className}`} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n\r\n/** Sticky bottom action area inside JimboApp. Thumb zone. */\r\nexport function JimboAppFooter({ children, className = '', ...props }: Omit<JimboAppProps, 'fluid'>) {\r\n return (\r\n <div className={`j-app__footer ${className}`} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport type JimboSectionTone = 'red' | 'blue' | 'green' | 'gold' | 'orange' | 'purple'\r\n\r\nexport interface JimboSectionHeaderProps {\r\n label: string\r\n tone?: JimboSectionTone\r\n className?: string\r\n}\r\n\r\n/**\r\n * Colored tag + horizontal rule — reusable section divider.\r\n * All styling via jimbo.css `.j-section-header` classes + tone utilities.\r\n */\r\nexport function JimboSectionHeader({ label, tone = 'blue', className = '' }: JimboSectionHeaderProps) {\r\n return (\r\n <div className={`j-section-header ${className}`}>\r\n <div className={`j-section-header__tag j-bg--${tone}`}>{label}</div>\r\n <div className={`j-section-header__rule j-bg--${tone}`} />\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport type JimboInfoCardTone = 'red' | 'blue' | 'green' | 'gold' | 'orange' | 'purple'\r\n\r\nexport interface JimboInfoCardProps extends React.HTMLAttributes<HTMLDivElement> {\r\n tone?: JimboInfoCardTone\r\n children: React.ReactNode\r\n}\r\n\r\n/**\r\n * Generic clickable row card — used for filter lists, seed lists, etc.\r\n * Border color set via tone. All styling via jimbo.css `.j-info-card`.\r\n */\r\nexport function JimboInfoCard({ tone, children, className = '', ...props }: JimboInfoCardProps) {\r\n const borderClass = tone ? `j-border--${tone}` : ''\r\n return (\r\n <div className={`j-info-card ${borderClass} ${className}`} style={tone ? { borderColor: undefined } : undefined} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n\r\n/** Main body area inside an InfoCard (flex: 1, overflow-safe). */\r\nexport function JimboInfoCardBody({ children, className = '' }: { children: React.ReactNode; className?: string }) {\r\n return <div className={`j-info-card__body ${className}`}>{children}</div>\r\n}\r\n\r\n/** Title line inside an InfoCard body. */\r\nexport function JimboInfoCardTitle({ children, className = '' }: { children: React.ReactNode; className?: string }) {\r\n return <div className={`j-info-card__title ${className}`}>{children}</div>\r\n}\r\n\r\n/** Subtitle line inside an InfoCard body. */\r\nexport function JimboInfoCardSub({ children, className = '' }: { children: React.ReactNode; className?: string }) {\r\n return <div className={`j-info-card__sub ${className}`}>{children}</div>\r\n}\r\n\r\n/** Right-side aside area inside an InfoCard. */\r\nexport function JimboInfoCardAside({ children, className = '' }: { children: React.ReactNode; className?: string }) {\r\n return <div className={`j-info-card__aside ${className}`}>{children}</div>\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\nimport { JimboButton } from './panel.js'\r\nimport { JimboSprite } from './sprites.js'\r\nimport { JimboText } from './jimboText.js'\r\nimport { JimboApp, JimboAppFooter } from './jimboApp.js'\r\nimport { JimboBalatroFooter } from './footer.js'\r\nimport { JimboSectionHeader, type JimboSectionTone } from './jimboSectionHeader.js'\r\nimport { JimboInfoCard, JimboInfoCardBody, JimboInfoCardTitle, JimboInfoCardSub, JimboInfoCardAside } from './jimboInfoCard.js'\r\n\r\nexport interface ShowcaseFilter {\r\n name: string\r\n author: string\r\n hits: string\r\n tone: JimboSectionTone\r\n sample: string[]\r\n}\r\n\r\nexport interface ShowcaseRecentFind {\r\n seed: string\r\n filterName: string\r\n score: number\r\n}\r\n\r\nexport interface ShowcaseLiveStats {\r\n searched: string\r\n matches: string\r\n speed: string\r\n}\r\n\r\nexport interface ShowcaseMcpInfo {\r\n runtime: string\r\n engine: string\r\n features: string\r\n}\r\n\r\nexport interface ShowcaseProps {\r\n title?: string\r\n subtitle?: string\r\n hotFilters?: ShowcaseFilter[]\r\n recentFinds?: ShowcaseRecentFind[]\r\n mcpInfo?: ShowcaseMcpInfo\r\n onNewSearch?: () => void\r\n onBrowseFilters?: () => void\r\n onFilterClick?: (filter: ShowcaseFilter, index: number) => void\r\n}\r\n\r\n/**\r\n * Landing/showcase screen — 320×568, NO SCROLL.\r\n * Every pixel accounted for. No flex stretching. No gaps.\r\n */\r\nexport function Showcase({\r\n title = 'Balatro',\r\n subtitle = 'Seed Curator',\r\n hotFilters = [],\r\n recentFinds = [],\r\n mcpInfo,\r\n onNewSearch,\r\n onBrowseFilters,\r\n onFilterClick,\r\n}: ShowcaseProps) {\r\n return (\r\n <JimboApp>\r\n {/* Content — no flex-grow, no dead space, footer follows naturally */}\r\n <div style={{ padding: '12px 12px 8px', display: 'flex', flexDirection: 'column', gap: 6 }}>\r\n {/* Compact title */}\r\n <div className=\"j-text-center\">\r\n <JimboText size=\"lg\" tone=\"gold\">{title}</JimboText>\r\n <JimboText size=\"micro\" tone=\"grey\" style={{ letterSpacing: 3 }}>{subtitle}</JimboText>\r\n </div>\r\n\r\n {/* Engine strip — single line */}\r\n {mcpInfo && (\r\n <div className=\"j-flex j-justify-between\" style={{\r\n padding: '3px 8px',\r\n background: 'var(--j-dark-grey)', borderRadius: 4,\r\n border: '1px solid var(--j-panel-edge)',\r\n }}>\r\n <JimboText size=\"micro\" tone=\"purple\">{mcpInfo.engine}</JimboText>\r\n <JimboText size=\"micro\" tone=\"grey\">{mcpInfo.features}</JimboText>\r\n </div>\r\n )}\r\n\r\n {/* Hot Filters */}\r\n {hotFilters.length > 0 && (\r\n <>\r\n <JimboSectionHeader label=\"Filters\" tone=\"blue\" />\r\n <div className=\"j-flex-col\" style={{ gap: 4 }}>\r\n {hotFilters.slice(0, 4).map((f, i) => (\r\n <JimboInfoCard\r\n key={i}\r\n tone={f.tone}\r\n onClick={() => onFilterClick?.(f, i)}\r\n style={{ cursor: onFilterClick ? 'pointer' : undefined }}\r\n >\r\n <div className=\"j-flex j-gap-xs\">\r\n {f.sample.slice(0, 2).map((name, j) => (\r\n <div key={j} style={{ width: 22, height: 28, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <JimboSprite name={name} width={20} />\r\n </div>\r\n ))}\r\n </div>\r\n <JimboInfoCardBody>\r\n <JimboInfoCardTitle>{f.name}</JimboInfoCardTitle>\r\n <JimboInfoCardSub>by {f.author}</JimboInfoCardSub>\r\n </JimboInfoCardBody>\r\n <JimboInfoCardAside>\r\n <JimboText size=\"xs\" tone={f.tone === 'gold' ? 'gold' : f.tone}>{f.hits}</JimboText>\r\n </JimboInfoCardAside>\r\n </JimboInfoCard>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* Recent finds — compact */}\r\n {recentFinds.length > 0 && (\r\n <>\r\n <JimboSectionHeader label=\"Recent\" tone=\"green\" />\r\n <div style={{ lineHeight: 1.5 }}>\r\n {recentFinds.slice(0, 3).map((r, i) => (\r\n <div key={i} className=\"j-flex j-gap-sm\">\r\n <JimboText size=\"micro\" tone=\"gold\">{r.seed}</JimboText>\r\n <JimboText size=\"micro\" tone=\"grey\">{r.filterName}</JimboText>\r\n {r.score > 0 && <JimboText size=\"micro\" tone=\"green\">+{r.score}</JimboText>}\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n <JimboAppFooter>\r\n <JimboButton tone=\"green\" fullWidth size=\"lg\" onClick={onNewSearch}>New Search</JimboButton>\r\n <JimboButton tone=\"blue\" fullWidth size=\"lg\" onClick={onBrowseFilters}>Browse Filters</JimboButton>\r\n </JimboAppFooter>\r\n <JimboBalatroFooter />\r\n </JimboApp>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React, { useState } from 'react'\r\nimport { JimboText } from './jimboText.js'\r\n\r\nexport interface JimboCopyRowProps {\r\n value: string\r\n label?: string\r\n}\r\n\r\n/**\r\n * Inline copy-to-clipboard row with label + value + button.\r\n * All styling via jimbo.css `.j-copy-row` classes.\r\n */\r\nexport function JimboCopyRow({ value, label }: JimboCopyRowProps) {\r\n const [copied, setCopied] = useState(false)\r\n\r\n function copy() {\r\n navigator.clipboard.writeText(value).then(() => {\r\n setCopied(true)\r\n setTimeout(() => setCopied(false), 1500)\r\n })\r\n }\r\n\r\n return (\r\n <div className=\"j-copy-row\">\r\n {label && (\r\n <JimboText size=\"xs\" tone=\"grey\" className=\"j-copy-row__label\">\r\n {label}\r\n </JimboText>\r\n )}\r\n <div className=\"j-copy-row__field\">\r\n <div className=\"j-copy-row__value\">\r\n <JimboText size=\"sm\">{value}</JimboText>\r\n </div>\r\n <button\r\n type=\"button\"\r\n className=\"j-copy-row__btn\"\r\n data-copied={copied}\r\n onClick={copy}\r\n >\r\n {copied ? 'Copied' : 'Copy'}\r\n </button>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport interface JimboWordmarkProps {\r\n title: string\r\n subtitle?: string\r\n className?: string\r\n}\r\n\r\n/**\r\n * Title + subtitle hero block. Gold title, grey subtitle.\r\n * All styling via jimbo.css `.j-wordmark` classes.\r\n */\r\nexport function JimboWordmark({ title, subtitle, className = '' }: JimboWordmarkProps) {\r\n return (\r\n <div className={`j-wordmark ${className}`}>\r\n <div className=\"j-wordmark__title\">{title}</div>\r\n {subtitle && <div className=\"j-wordmark__sub\">{subtitle}</div>}\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport interface JimboStatItem {\r\n value: string | number\r\n label: string\r\n}\r\n\r\nexport interface JimboStatGridProps extends React.HTMLAttributes<HTMLDivElement> {\r\n items: JimboStatItem[]\r\n}\r\n\r\n/**\r\n * 3-column stat bar — value on top, label below.\r\n * All styling via jimbo.css `.j-stat-grid` classes.\r\n */\r\nexport function JimboStatGrid({ items, className = '', ...props }: JimboStatGridProps) {\r\n return (\r\n <div className={`j-stat-grid ${className}`} {...props}>\r\n {items.map((item) => (\r\n <div key={item.label}>\r\n <div className=\"j-stat-grid__value\">{item.value}</div>\r\n <div className=\"j-stat-grid__label\">{item.label}</div>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n","'use client'\r\n\r\nimport React from 'react'\r\n\r\nexport interface JimboInsetProps extends React.HTMLAttributes<HTMLDivElement> {\r\n children: React.ReactNode\r\n}\r\n\r\n/**\r\n * Dark recessed content area — for log output, recent finds, etc.\r\n * All styling via jimbo.css `.j-inset` class.\r\n */\r\nexport function JimboInset({ children, className = '', ...props }: JimboInsetProps) {\r\n return (\r\n <div className={`j-inset ${className}`} {...props}>\r\n {children}\r\n </div>\r\n )\r\n}\r\n","// PORTABLE — intended for jaml-ui/src/ui/jimboIconButton.tsx\r\n// On paste, replace `from 'jaml-ui'` with `from './tokens.js'`.\r\n\"use client\";\r\n\r\nimport { JimboColorOption } from \"./tokens.js\";\r\nimport type React from \"react\";\r\nimport { useState } from \"react\";\r\n\r\nconst C = JimboColorOption;\r\n\r\nexport interface JimboIconButtonProps {\r\n \"aria-label\"?: string;\r\n children: React.ReactNode;\r\n disabled?: boolean;\r\n onClick?: () => void;\r\n size?: \"sm\" | \"md\";\r\n title?: string;\r\n}\r\n\r\nexport function JimboIconButton({\r\n onClick,\r\n title,\r\n \"aria-label\": ariaLabel,\r\n disabled = false,\r\n size = \"md\",\r\n children,\r\n}: JimboIconButtonProps) {\r\n const [hover, setHover] = useState(false);\r\n const side = size === \"sm\" ? 26 : 30;\r\n\r\n return (\r\n <button\r\n aria-label={ariaLabel ?? title}\r\n disabled={disabled}\r\n onClick={() => !disabled && onClick?.()}\r\n onMouseEnter={() => setHover(true)}\r\n onMouseLeave={() => setHover(false)}\r\n style={{\r\n width: side,\r\n height: side,\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n background: hover && !disabled ? C.DARK_GREY : C.DARKEST,\r\n color: C.WHITE,\r\n border: `1px solid ${C.PANEL_EDGE}`,\r\n borderRadius: 4,\r\n cursor: disabled ? \"not-allowed\" : \"pointer\",\r\n opacity: disabled ? 0.55 : 1,\r\n padding: 0,\r\n fontSize: 14,\r\n lineHeight: 1,\r\n transition: \"background 80ms ease\",\r\n }}\r\n title={title}\r\n type=\"button\"\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n","// PORTABLE — intended for jaml-ui/src/ui/jimboInputModal.tsx\r\n// On paste, replace `from 'jaml-ui'` with `from './panel.js'`/`./tokens.js` as appropriate.\r\n\"use client\";\r\n\r\nimport { JimboButton, JimboModal } from \"./panel.js\";\r\nimport { JimboColorOption } from \"./tokens.js\";\r\nimport { JimboText } from \"./jimboText.js\";\r\nimport { useEffect, useRef, useState } from \"react\";\r\n\r\nconst C = JimboColorOption;\r\n\r\nexport interface JimboInputModalProps {\r\n cancelLabel?: string;\r\n confirmLabel?: string;\r\n initialValue?: string;\r\n message?: string;\r\n onCancel: () => void;\r\n onConfirm: (value: string) => void;\r\n open: boolean;\r\n placeholder?: string;\r\n title: string;\r\n validate?: (value: string) => string | null;\r\n}\r\n\r\nexport function JimboInputModal({\r\n open,\r\n title,\r\n message,\r\n placeholder,\r\n initialValue = \"\",\r\n confirmLabel = \"Confirm\",\r\n cancelLabel = \"Cancel\",\r\n validate,\r\n onConfirm,\r\n onCancel,\r\n}: JimboInputModalProps) {\r\n const [value, setValue] = useState(initialValue);\r\n const [error, setError] = useState<string | null>(null);\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n\r\n const [prevOpen, setPrevOpen] = useState(open);\r\n\r\n if (open !== prevOpen) {\r\n setPrevOpen(open);\r\n if (open) {\r\n setValue(initialValue);\r\n setError(null);\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n if (open) {\r\n const t = setTimeout(() => inputRef.current?.focus(), 30);\r\n return () => clearTimeout(t);\r\n }\r\n }, [open]);\r\n\r\n function submit() {\r\n const err = validate?.(value) ?? null;\r\n if (err) {\r\n setError(err);\r\n return;\r\n }\r\n onConfirm(value);\r\n }\r\n\r\n return (\r\n <JimboModal onClose={onCancel} open={open} title={title}>\r\n {message && (\r\n <JimboText\r\n size=\"sm\"\r\n style={{ display: \"block\", marginBottom: 8 }}\r\n tone=\"grey\"\r\n >\r\n {message}\r\n </JimboText>\r\n )}\r\n <input\r\n aria-invalid={error ? \"true\" : \"false\"}\r\n onChange={(e) => {\r\n setValue(e.target.value);\r\n if (error) {\r\n setError(null);\r\n }\r\n }}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\") {\r\n submit();\r\n }\r\n if (e.key === \"Escape\") {\r\n onCancel();\r\n }\r\n }}\r\n placeholder={placeholder}\r\n ref={inputRef}\r\n style={{\r\n width: \"100%\",\r\n padding: \"8px 10px\",\r\n background: C.DARKEST,\r\n color: C.WHITE,\r\n border: `1px solid ${error ? C.RED : C.PANEL_EDGE}`,\r\n borderRadius: 4,\r\n fontSize: 13,\r\n fontFamily: \"m6x11plus, monospace\",\r\n letterSpacing: 1,\r\n outline: \"none\",\r\n boxSizing: \"border-box\",\r\n }}\r\n type=\"text\"\r\n value={value}\r\n />\r\n {error && (\r\n <JimboText\r\n size=\"sm\"\r\n style={{ display: \"block\", marginTop: 6 }}\r\n tone=\"red\"\r\n >\r\n {error}\r\n </JimboText>\r\n )}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n justifyContent: \"flex-end\",\r\n gap: 8,\r\n marginTop: 14,\r\n }}\r\n >\r\n <JimboButton onClick={onCancel} size=\"sm\" tone=\"red\">\r\n {cancelLabel}\r\n </JimboButton>\r\n <JimboButton onClick={submit} size=\"sm\" tone=\"blue\">\r\n {confirmLabel}\r\n </JimboButton>\r\n </div>\r\n </JimboModal>\r\n );\r\n}\r\n","// PORTABLE — intended for jaml-ui/src/ui/jimboSelect.tsx\r\n// On paste, replace `from 'jaml-ui'` with `from './tokens.js'`.\r\n\"use client\";\r\n\r\nimport { JimboColorOption } from \"./tokens.js\";\r\nimport type React from \"react\";\r\n\r\nconst C = JimboColorOption;\r\n\r\nexport interface JimboSelectOption {\r\n disabled?: boolean;\r\n label?: string;\r\n value: string;\r\n}\r\n\r\nexport interface JimboSelectProps {\r\n \"aria-label\"?: string;\r\n disabled?: boolean;\r\n fullWidth?: boolean;\r\n onChange: (value: string) => void;\r\n options: JimboSelectOption[] | string[];\r\n placeholder?: string;\r\n size?: \"sm\" | \"md\";\r\n style?: React.CSSProperties;\r\n value: string;\r\n}\r\n\r\nexport function JimboSelect({\r\n value,\r\n options,\r\n onChange,\r\n placeholder,\r\n disabled = false,\r\n fullWidth = true,\r\n size = \"md\",\r\n style,\r\n \"aria-label\": ariaLabel,\r\n}: JimboSelectProps) {\r\n let normalized: JimboSelectOption[];\r\n if (options.length === 0) {\r\n normalized = [];\r\n } else if (typeof options[0] === \"string\") {\r\n normalized = (options as string[]).map((v) => ({ value: v }));\r\n } else {\r\n normalized = options as JimboSelectOption[];\r\n }\r\n\r\n const pad = size === \"sm\" ? \"4px 8px\" : \"6px 10px\";\r\n const fontSize = size === \"sm\" ? 11 : 12;\r\n\r\n return (\r\n <select\r\n aria-label={ariaLabel}\r\n disabled={disabled}\r\n onChange={(e) => onChange(e.target.value)}\r\n style={{\r\n width: fullWidth ? \"100%\" : undefined,\r\n padding: pad,\r\n background: C.DARKEST,\r\n color: C.WHITE,\r\n border: `1px solid ${C.PANEL_EDGE}`,\r\n borderRadius: 4,\r\n fontSize,\r\n fontFamily: \"m6x11plus, monospace\",\r\n cursor: disabled ? \"not-allowed\" : \"pointer\",\r\n opacity: disabled ? 0.55 : 1,\r\n appearance: \"none\",\r\n backgroundImage:\r\n \"linear-gradient(45deg, transparent 50%, \" +\r\n C.GOLD_TEXT +\r\n \" 50%), linear-gradient(135deg, \" +\r\n C.GOLD_TEXT +\r\n \" 50%, transparent 50%)\",\r\n backgroundPosition: \"calc(100% - 12px) 50%, calc(100% - 7px) 50%\",\r\n backgroundSize: \"5px 5px, 5px 5px\",\r\n backgroundRepeat: \"no-repeat\",\r\n paddingRight: 22,\r\n ...style,\r\n }}\r\n value={value}\r\n >\r\n {placeholder !== undefined && (\r\n <option disabled value=\"\">\r\n {placeholder}\r\n </option>\r\n )}\r\n {normalized.map((opt) => (\r\n <option disabled={opt.disabled} key={opt.value} value={opt.value}>\r\n {opt.label ?? opt.value}\r\n </option>\r\n ))}\r\n </select>\r\n );\r\n}\r\n","// PORTABLE — intended for jaml-ui/src/ui/panelSplitter.tsx\r\n// On paste, replace `from 'jaml-ui'` with `from './tokens.js'`.\r\n\"use client\";\r\n\r\nimport { JimboColorOption } from \"./tokens.js\";\r\nimport { useCallback, useEffect, useRef, useLayoutEffect } from \"react\";\r\n\r\nconst C = JimboColorOption;\r\n\r\nexport interface PanelSplitterProps {\r\n \"aria-label\"?: string;\r\n onDrag: (delta: number) => void;\r\n onKeyAdjust?: (delta: number) => void;\r\n orientation?: \"vertical\" | \"horizontal\";\r\n}\r\n\r\nexport function PanelSplitter({\r\n orientation = \"vertical\",\r\n onDrag,\r\n onKeyAdjust,\r\n \"aria-label\": ariaLabel,\r\n}: PanelSplitterProps) {\r\n const draggingRef = useRef(false);\r\n const lastRef = useRef(0);\r\n const onDragRef = useRef(onDrag);\r\n useLayoutEffect(() => {\r\n onDragRef.current = onDrag;\r\n });\r\n\r\n const handlePointerDown = useCallback(\r\n (e: React.PointerEvent<HTMLElement>) => {\r\n e.preventDefault();\r\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\r\n draggingRef.current = true;\r\n lastRef.current = orientation === \"vertical\" ? e.clientX : e.clientY;\r\n },\r\n [orientation]\r\n );\r\n\r\n useEffect(() => {\r\n function move(e: PointerEvent) {\r\n if (!draggingRef.current) {\r\n return;\r\n }\r\n const cur = orientation === \"vertical\" ? e.clientX : e.clientY;\r\n const delta = cur - lastRef.current;\r\n if (delta !== 0) {\r\n lastRef.current = cur;\r\n onDragRef.current(delta);\r\n }\r\n }\r\n function up() {\r\n draggingRef.current = false;\r\n }\r\n window.addEventListener(\"pointermove\", move);\r\n window.addEventListener(\"pointerup\", up);\r\n window.addEventListener(\"pointercancel\", up);\r\n return () => {\r\n window.removeEventListener(\"pointermove\", move);\r\n window.removeEventListener(\"pointerup\", up);\r\n window.removeEventListener(\"pointercancel\", up);\r\n };\r\n }, [orientation]);\r\n\r\n const step = 16;\r\n const isVertical = orientation === \"vertical\";\r\n\r\n return (\r\n <button\r\n aria-label={ariaLabel ?? \"Resize panel\"}\r\n onKeyDown={(e) => {\r\n if (!onKeyAdjust) {\r\n return;\r\n }\r\n if (isVertical && e.key === \"ArrowLeft\") {\r\n onKeyAdjust(-step);\r\n }\r\n if (isVertical && e.key === \"ArrowRight\") {\r\n onKeyAdjust(step);\r\n }\r\n if (!isVertical && e.key === \"ArrowUp\") {\r\n onKeyAdjust(-step);\r\n }\r\n if (!isVertical && e.key === \"ArrowDown\") {\r\n onKeyAdjust(step);\r\n }\r\n }}\r\n onPointerDown={handlePointerDown}\r\n style={{\r\n all: \"unset\",\r\n display: \"block\",\r\n flex: \"0 0 auto\",\r\n width: isVertical ? 6 : undefined,\r\n height: isVertical ? undefined : 6,\r\n cursor: isVertical ? \"col-resize\" : \"row-resize\",\r\n background: C.PANEL_EDGE,\r\n borderLeft: isVertical ? `1px solid ${C.BLACK}` : undefined,\r\n borderRight: isVertical ? `1px solid ${C.BLACK}` : undefined,\r\n borderTop: isVertical ? undefined : `1px solid ${C.BLACK}`,\r\n borderBottom: isVertical ? undefined : `1px solid ${C.BLACK}`,\r\n touchAction: \"none\",\r\n userSelect: \"none\",\r\n }}\r\n type=\"button\"\r\n />\r\n );\r\n}\r\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export { JamlAnalyzerFullscreen, type JamlAnalyzerFullscreenProps, } from './com
7
7
  export { ANALYZER_STREAM_META, DEFAULT_ENABLED_STREAMS, type AnalyzerStreamKey, type AnalyzerStreamMeta, } from './hooks/analyzerStreamRegistry.js';
8
8
  export { JamlMapPreview, type JamlMapPreviewProps } from './components/JamlMapPreview.js';
9
9
  export { JamlIde, type JamlIdeProps, type JamlIdeSearchResult, type JamlVisualFilter, type JamlVisualClause, type JamlZone, } from './components/JamlIde.js';
10
+ export { JamlCurator } from './components/JamlCurator.js';
10
11
  export { JamlIdeVisual, type JamlIdeVisualProps, } from './components/JamlIdeVisual.js';
11
12
  export { JamlCodeEditor, type JamlCodeEditorProps, } from './components/JamlCodeEditor.js';
12
13
  export * from './ui.js';