From f03bd92d84f4f49ef89533bb6612ae7693286a80 Mon Sep 17 00:00:00 2001 From: Richard Ward Date: Tue, 30 Dec 2025 23:31:12 +0000 Subject: [PATCH] code: tsx,storybook,src (1 files) --- storybook/src/components/registry.tsx | 172 ++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/storybook/src/components/registry.tsx b/storybook/src/components/registry.tsx index 5f4efb3c5..419465bea 100644 --- a/storybook/src/components/registry.tsx +++ b/storybook/src/components/registry.tsx @@ -882,6 +882,178 @@ export const Pagination: React.FC ) +/** + * LuaScriptViewer - Shows Lua utility scripts with code and execution + */ +export const LuaScriptViewer: React.FC = ({ scriptFile, scriptName, description, category, packageId }) => { + const [code, setCode] = React.useState(null) + const [result, setResult] = React.useState(null) + const [error, setError] = React.useState(null) + const [testInput, setTestInput] = React.useState('1735570800000') // Default timestamp + const [loading, setLoading] = React.useState(true) + + React.useEffect(() => { + async function loadScript() { + if (!scriptFile) return + + // Try to find the package from the current URL or context + const pkgId = packageId || window.location.hash.match(/packageId=([^&]+)/)?.[1] || + window.location.pathname.split('/').find(p => p.includes('_')) || + 'irc_webchat' // Fallback + + try { + const response = await fetch(`/packages/${pkgId}/seed/scripts/${scriptFile}`) + if (response.ok) { + const luaCode = await response.text() + setCode(luaCode) + } else { + setError(`Failed to load: ${response.statusText}`) + } + } catch (err) { + setError(String(err)) + } + setLoading(false) + } + loadScript() + }, [scriptFile, packageId]) + + const runScript = async () => { + if (!code) return + setError(null) + setResult(null) + + try { + // Dynamically import fengari + const fengari = await import('fengari-web') + const { lua, lauxlib, lualib, to_luastring, to_jsstring } = fengari + + const L = lauxlib.luaL_newstate() + lualib.luaL_openlibs(L) + + // Load the script + const loadResult = lauxlib.luaL_loadstring(L, to_luastring(code)) + if (loadResult !== lua.LUA_OK) { + setError(`Load error: ${to_jsstring(lua.lua_tostring(L, -1))}`) + lua.lua_close(L) + return + } + + // Execute to get the function + const execResult = lua.lua_pcall(L, 0, 1, 0) + if (execResult !== lua.LUA_OK) { + setError(`Exec error: ${to_jsstring(lua.lua_tostring(L, -1))}`) + lua.lua_close(L) + return + } + + // Check return type + const returnType = lua.lua_type(L, -1) + + if (returnType === lua.LUA_TFUNCTION) { + // Call the function with test input + const input = parseFloat(testInput) || testInput + if (typeof input === 'number') { + lua.lua_pushnumber(L, input) + } else { + lua.lua_pushstring(L, to_luastring(input)) + } + + const callResult = lua.lua_pcall(L, 1, 1, 0) + if (callResult !== lua.LUA_OK) { + setError(`Call error: ${to_jsstring(lua.lua_tostring(L, -1))}`) + lua.lua_close(L) + return + } + + // Get result + const resultType = lua.lua_type(L, -1) + if (resultType === lua.LUA_TSTRING) { + setResult(to_jsstring(lua.lua_tostring(L, -1))) + } else if (resultType === lua.LUA_TNUMBER) { + setResult(String(lua.lua_tonumber(L, -1))) + } else if (resultType === lua.LUA_TBOOLEAN) { + setResult(lua.lua_toboolean(L, -1) ? 'true' : 'false') + } else { + const typeNames = ['nil', 'boolean', 'lightuserdata', 'number', 'string', 'table', 'function', 'userdata', 'thread'] + setResult(`[${typeNames[resultType] || 'unknown'}]`) + } + } else { + const typeNames = ['nil', 'boolean', 'lightuserdata', 'number', 'string', 'table', 'function', 'userdata', 'thread'] + setResult(`Script returned: ${typeNames[returnType] || 'unknown'}`) + } + + lua.lua_close(L) + } catch (err) { + setError(String(err)) + } + } + + if (loading) { + return
Loading script...
+ } + + return ( +
+ {/* Header */} +
+

+ 📜 {scriptName || scriptFile} +

+

{description}

+ {category && Category: {category}} +
+ + {/* Code viewer */} +
+
Lua Code
+
+          {code || 'No code loaded'}
+        
+
+ + {/* Test runner */} +
+
Test Execution
+
+ + setTestInput(e.target.value)} + className="flex-1 px-3 py-2 border rounded text-sm" + placeholder="Enter test input..." + /> + +
+ + {error && ( +
+ {error} +
+ )} + + {result && ( +
+ Result: + {result} +
+ )} +
+
+ ) +} + /** * Component Registry - maps Lua type names to React components */