@simten/ui 0.1.6 → 0.1.7

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":"RV32IInstrMemNode.d.ts","sourceRoot":"","sources":["../../src/nodes/RV32IInstrMemNode.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA8C3C,UAAU,sBAAsB;IAC9B,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,sBAAsB,2CAiQ3E"}
1
+ {"version":3,"file":"RV32IInstrMemNode.d.ts","sourceRoot":"","sources":["../../src/nodes/RV32IInstrMemNode.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgD3C,UAAU,sBAAsB;IAC9B,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,sBAAsB,2CAiQ3E"}
@@ -16,14 +16,16 @@ const LANGUAGES = [
16
16
  { value: 'rust', label: 'Rust' },
17
17
  { value: 'asm', label: 'ASM' },
18
18
  ];
19
+ // The compiler links a crt0 that provides `_start` (stack setup) and calls
20
+ // `main` — templates define `main`, not `_start` (which collides at link).
19
21
  const PLACEHOLDER_CODE = {
20
- c: `void _start() {
22
+ c: `void main() {
21
23
  volatile int *uart = (volatile int *)0x80000000;
22
24
  const char *msg = "Hello from C!\\n";
23
25
  while (*msg) *uart = *msg++;
24
26
  while (1);
25
27
  }`,
26
- cpp: `extern "C" void _start() {
28
+ cpp: `extern "C" void main() {
27
29
  volatile int *uart = (volatile int *)0x80000000;
28
30
  const char *msg = "Hello from C++!\\n";
29
31
  while (*msg) *uart = *msg++;
@@ -33,7 +35,7 @@ const PLACEHOLDER_CODE = {
33
35
  #![no_main]
34
36
 
35
37
  #[no_mangle]
36
- pub extern "C" fn _start() -> ! {
38
+ pub extern "C" fn main() -> ! {
37
39
  let uart = 0x80000000 as *mut u32;
38
40
  for &b in b"Hello from Rust!\\n" {
39
41
  unsafe { core::ptr::write_volatile(uart, b as u32); }
@@ -43,9 +45,9 @@ pub extern "C" fn _start() -> ! {
43
45
 
44
46
  #[panic_handler]
45
47
  fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }`,
46
- asm: `.global _start
48
+ asm: `.global main
47
49
  .text
48
- _start:
50
+ main:
49
51
  # Write 'H' to UART
50
52
  li t0, 0x80000000
51
53
  li a0, 72
@@ -1 +1 @@
1
- {"version":3,"file":"RV32IInstrMemNode.js","sourceRoot":"","sources":["../../src/nodes/RV32IInstrMemNode.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * RV32IInstrMemNode Component\n *\n * Renders RV32I instruction memory with:\n * - Drag-and-drop binary file loading\n * - Inline code editor with compile button (calls /api/compile)\n * - Uses onLoadMemory callback to write data via engine.setNode()\n */\n\n\"use client\";\n\nimport React, { useCallback, useState, useRef } from 'react';\nimport { BaseNode, type PortConfig } from './BaseNode';\nimport type { NodeData } from './NodeData';\n\nconst LANGUAGES = [\n { value: 'c', label: 'C' },\n { value: 'cpp', label: 'C++' },\n { value: 'rust', label: 'Rust' },\n { value: 'asm', label: 'ASM' },\n] as const;\n\nconst PLACEHOLDER_CODE: Record<string, string> = {\n c: `void _start() {\n volatile int *uart = (volatile int *)0x80000000;\n const char *msg = \"Hello from C!\\\\n\";\n while (*msg) *uart = *msg++;\n while (1);\n}`,\n cpp: `extern \"C\" void _start() {\n volatile int *uart = (volatile int *)0x80000000;\n const char *msg = \"Hello from C++!\\\\n\";\n while (*msg) *uart = *msg++;\n while (1) {}\n}`,\n rust: `#![no_std]\n#![no_main]\n\n#[no_mangle]\npub extern \"C\" fn _start() -> ! {\n let uart = 0x80000000 as *mut u32;\n for &b in b\"Hello from Rust!\\\\n\" {\n unsafe { core::ptr::write_volatile(uart, b as u32); }\n }\n loop {}\n}\n\n#[panic_handler]\nfn panic(_: &core::panic::PanicInfo) -> ! { loop {} }`,\n asm: `.global _start\n.text\n_start:\n # Write 'H' to UART\n li t0, 0x80000000\n li a0, 72\n sw a0, 0(t0)\n1: j 1b`,\n};\n\ninterface RV32IInstrMemNodeProps {\n data: NodeData;\n selected?: boolean;\n}\n\nexport function RV32IInstrMemNode({ data, selected }: RV32IInstrMemNodeProps) {\n const [isDragOver, setIsDragOver] = useState(false);\n const [showCodeEditor, setShowCodeEditor] = useState(false);\n const [language, setLanguage] = useState<string>('c');\n const [code, setCode] = useState('');\n const [compileStatus, setCompileStatus] = useState<'idle' | 'compiling' | 'success' | 'error'>('idle');\n const [compileError, setCompileError] = useState('');\n const [loadedFilename, setLoadedFilename] = useState<string | null>(null);\n const [loadedSize, setLoadedSize] = useState(0);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const inputPorts: PortConfig[] = data.inputNames.map((name, index) => ({\n name, index, type: 'input',\n }));\n\n const outputPorts: PortConfig[] = data.outputNames.map((name, index) => ({\n name, index, type: 'output',\n }));\n\n const loadBinary = useCallback((binary: Uint8Array, filename: string) => {\n const memoryMap = new Map<number, number>();\n for (let i = 0; i < binary.length; i++) {\n if (binary[i] !== 0) memoryMap.set(i, binary[i]);\n }\n setLoadedFilename(filename);\n setLoadedSize(binary.length);\n data.onLoadMemory?.(memoryMap);\n }, [data.onLoadMemory]);\n\n const handleFileLoad = useCallback(async (file: File) => {\n const buffer = await file.arrayBuffer();\n loadBinary(new Uint8Array(buffer), file.name);\n }, [loadBinary]);\n\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n const file = e.dataTransfer.files[0];\n if (file) handleFileLoad(file);\n }, [handleFileLoad]);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(true);\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n }, []);\n\n const handleClickDropZone = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n fileInputRef.current?.click();\n }, []);\n\n const handleFileInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) handleFileLoad(file);\n e.target.value = '';\n }, [handleFileLoad]);\n\n const handleClear = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n setLoadedFilename(null);\n setLoadedSize(0);\n data.onLoadMemory?.(new Map());\n }, [data.onLoadMemory]);\n\n const handleCompile = useCallback(async () => {\n const sourceCode = code || PLACEHOLDER_CODE[language] || '';\n if (!sourceCode.trim()) return;\n\n setCompileStatus('compiling');\n setCompileError('');\n\n try {\n const resp = await fetch('/api/compile', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ source: sourceCode, language }),\n });\n\n const result = await resp.json() as {\n success: boolean;\n binary?: string;\n stderr?: string;\n error?: string;\n };\n\n if (!result.success) {\n setCompileStatus('error');\n setCompileError(result.stderr || result.error || 'Compilation failed');\n return;\n }\n\n const b64 = result.binary ?? '';\n const raw = atob(b64);\n const binary = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) binary[i] = raw.charCodeAt(i);\n loadBinary(binary, `program.${language}`);\n setCompileStatus('success');\n setTimeout(() => setCompileStatus('idle'), 2000);\n } catch (e) {\n setCompileStatus('error');\n setCompileError(e instanceof Error ? e.message : 'Network error');\n }\n }, [code, language, loadBinary]);\n\n const handleToggleCodeEditor = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n setShowCodeEditor(prev => !prev);\n }, []);\n\n return (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".bin,.elf\"\n onChange={handleFileInputChange}\n className=\"hidden\"\n />\n <BaseNode inputPorts={inputPorts} outputPorts={outputPorts} selected={selected} className=\"min-w-[140px]\" showPortLabels={data.showPortLabels} onPortClick={data.onPortClick} glowUnconnected={data.glowUnconnected}>\n <div className=\"flex flex-col items-center gap-2\">\n {/* Label */}\n <div className=\"px-2 py-1 text-xs font-medium text-[var(--embed-text-primary)]\">\n {data.label || 'InstrMem'}\n </div>\n\n {/* Type badge */}\n <div className=\"px-3 py-2 text-xs font-semibold rounded-md bg-[var(--embed-bg-tertiary)] text-[var(--embed-text-primary)]\">\n IMEM\n </div>\n\n {/* Drop Zone */}\n <div\n className={`\n flex flex-col items-center gap-1 p-2 rounded border-2 border-dashed cursor-pointer transition-all w-full\n ${isDragOver\n ? 'border-blue-500 bg-blue-500/10'\n : loadedFilename\n ? 'border-green-500/50 bg-green-500/10'\n : 'border-[var(--embed-border)] hover:border-blue-400 hover:bg-blue-500/5'\n }\n `}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onClick={handleClickDropZone}\n title={loadedFilename ? 'Click to replace' : 'Drop .bin or click'}\n >\n {loadedFilename ? (\n <>\n <div className=\"text-xs text-green-400 font-medium truncate max-w-[120px]\">\n {loadedFilename}\n </div>\n <div className=\"text-xs text-[var(--embed-text-muted)]\">\n {loadedSize} bytes\n </div>\n <button\n onClick={handleClear}\n className=\"text-xs text-red-400 hover:text-red-300 hover:underline\"\n >\n Clear\n </button>\n </>\n ) : (\n <>\n <div className=\"text-xs text-[var(--embed-text-muted)]\">Drop .bin</div>\n <div className=\"text-xs text-[var(--embed-text-muted)]\">or click</div>\n </>\n )}\n </div>\n\n {/* Code Editor Toggle */}\n <button\n onClick={handleToggleCodeEditor}\n className={`\n w-full px-2 py-1 text-xs rounded transition-colors\n ${showCodeEditor\n ? 'bg-violet-500/20 text-violet-400'\n : 'bg-[var(--embed-bg-tertiary)] text-[var(--embed-text-muted)] hover:bg-violet-500/10 hover:text-violet-400'\n }\n `}\n >\n {showCodeEditor ? 'Hide Code' : 'Code'}\n </button>\n\n {/* Code Editor Panel */}\n {showCodeEditor && (\n <div\n className=\"flex flex-col gap-2 w-full min-w-[280px] nodrag\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* Language Selector */}\n <div className=\"flex gap-1\">\n {LANGUAGES.map(lang => (\n <button\n key={lang.value}\n onClick={() => setLanguage(lang.value)}\n className={`\n px-2 py-0.5 text-xs rounded transition-colors\n ${language === lang.value\n ? 'bg-violet-500/30 text-violet-300'\n : 'bg-[var(--embed-bg-tertiary)] text-[var(--embed-text-muted)] hover:bg-[var(--embed-bg-tertiary)]/80'\n }\n `}\n >\n {lang.label}\n </button>\n ))}\n </div>\n\n {/* Code Input */}\n <textarea\n value={code}\n onChange={(e) => setCode(e.target.value)}\n placeholder={PLACEHOLDER_CODE[language]}\n className=\"w-full h-32 p-2 text-xs font-mono rounded border border-[var(--embed-border)] bg-[var(--embed-bg-code)] text-[var(--embed-text-primary)] resize-y\"\n spellCheck={false}\n />\n\n {/* Compile Button */}\n <button\n onClick={handleCompile}\n disabled={compileStatus === 'compiling'}\n className={`\n w-full px-3 py-1.5 text-xs font-medium rounded transition-colors\n ${compileStatus === 'compiling'\n ? 'bg-[var(--embed-bg-tertiary)] text-[var(--embed-text-muted)] cursor-wait'\n : compileStatus === 'success'\n ? 'bg-green-600 text-white'\n : 'bg-violet-600 hover:bg-violet-500 text-white'\n }\n `}\n >\n {compileStatus === 'compiling' ? 'Compiling...'\n : compileStatus === 'success' ? 'Loaded!'\n : 'Compile & Load'}\n </button>\n\n {/* Error Display */}\n {compileStatus === 'error' && compileError && (\n <div className=\"p-2 text-xs font-mono rounded bg-red-500/10 text-red-400 max-h-24 overflow-y-auto whitespace-pre-wrap\">\n {compileError}\n </div>\n )}\n </div>\n )}\n </div>\n </BaseNode>\n </>\n );\n}\n"]}
1
+ {"version":3,"file":"RV32IInstrMemNode.js","sourceRoot":"","sources":["../../src/nodes/RV32IInstrMemNode.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * RV32IInstrMemNode Component\n *\n * Renders RV32I instruction memory with:\n * - Drag-and-drop binary file loading\n * - Inline code editor with compile button (calls /api/compile)\n * - Uses onLoadMemory callback to write data via engine.setNode()\n */\n\n\"use client\";\n\nimport React, { useCallback, useState, useRef } from 'react';\nimport { BaseNode, type PortConfig } from './BaseNode';\nimport type { NodeData } from './NodeData';\n\nconst LANGUAGES = [\n { value: 'c', label: 'C' },\n { value: 'cpp', label: 'C++' },\n { value: 'rust', label: 'Rust' },\n { value: 'asm', label: 'ASM' },\n] as const;\n\n// The compiler links a crt0 that provides `_start` (stack setup) and calls\n// `main` — templates define `main`, not `_start` (which collides at link).\nconst PLACEHOLDER_CODE: Record<string, string> = {\n c: `void main() {\n volatile int *uart = (volatile int *)0x80000000;\n const char *msg = \"Hello from C!\\\\n\";\n while (*msg) *uart = *msg++;\n while (1);\n}`,\n cpp: `extern \"C\" void main() {\n volatile int *uart = (volatile int *)0x80000000;\n const char *msg = \"Hello from C++!\\\\n\";\n while (*msg) *uart = *msg++;\n while (1) {}\n}`,\n rust: `#![no_std]\n#![no_main]\n\n#[no_mangle]\npub extern \"C\" fn main() -> ! {\n let uart = 0x80000000 as *mut u32;\n for &b in b\"Hello from Rust!\\\\n\" {\n unsafe { core::ptr::write_volatile(uart, b as u32); }\n }\n loop {}\n}\n\n#[panic_handler]\nfn panic(_: &core::panic::PanicInfo) -> ! { loop {} }`,\n asm: `.global main\n.text\nmain:\n # Write 'H' to UART\n li t0, 0x80000000\n li a0, 72\n sw a0, 0(t0)\n1: j 1b`,\n};\n\ninterface RV32IInstrMemNodeProps {\n data: NodeData;\n selected?: boolean;\n}\n\nexport function RV32IInstrMemNode({ data, selected }: RV32IInstrMemNodeProps) {\n const [isDragOver, setIsDragOver] = useState(false);\n const [showCodeEditor, setShowCodeEditor] = useState(false);\n const [language, setLanguage] = useState<string>('c');\n const [code, setCode] = useState('');\n const [compileStatus, setCompileStatus] = useState<'idle' | 'compiling' | 'success' | 'error'>('idle');\n const [compileError, setCompileError] = useState('');\n const [loadedFilename, setLoadedFilename] = useState<string | null>(null);\n const [loadedSize, setLoadedSize] = useState(0);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const inputPorts: PortConfig[] = data.inputNames.map((name, index) => ({\n name, index, type: 'input',\n }));\n\n const outputPorts: PortConfig[] = data.outputNames.map((name, index) => ({\n name, index, type: 'output',\n }));\n\n const loadBinary = useCallback((binary: Uint8Array, filename: string) => {\n const memoryMap = new Map<number, number>();\n for (let i = 0; i < binary.length; i++) {\n if (binary[i] !== 0) memoryMap.set(i, binary[i]);\n }\n setLoadedFilename(filename);\n setLoadedSize(binary.length);\n data.onLoadMemory?.(memoryMap);\n }, [data.onLoadMemory]);\n\n const handleFileLoad = useCallback(async (file: File) => {\n const buffer = await file.arrayBuffer();\n loadBinary(new Uint8Array(buffer), file.name);\n }, [loadBinary]);\n\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n const file = e.dataTransfer.files[0];\n if (file) handleFileLoad(file);\n }, [handleFileLoad]);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(true);\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n }, []);\n\n const handleClickDropZone = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n fileInputRef.current?.click();\n }, []);\n\n const handleFileInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) handleFileLoad(file);\n e.target.value = '';\n }, [handleFileLoad]);\n\n const handleClear = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n setLoadedFilename(null);\n setLoadedSize(0);\n data.onLoadMemory?.(new Map());\n }, [data.onLoadMemory]);\n\n const handleCompile = useCallback(async () => {\n const sourceCode = code || PLACEHOLDER_CODE[language] || '';\n if (!sourceCode.trim()) return;\n\n setCompileStatus('compiling');\n setCompileError('');\n\n try {\n const resp = await fetch('/api/compile', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ source: sourceCode, language }),\n });\n\n const result = await resp.json() as {\n success: boolean;\n binary?: string;\n stderr?: string;\n error?: string;\n };\n\n if (!result.success) {\n setCompileStatus('error');\n setCompileError(result.stderr || result.error || 'Compilation failed');\n return;\n }\n\n const b64 = result.binary ?? '';\n const raw = atob(b64);\n const binary = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) binary[i] = raw.charCodeAt(i);\n loadBinary(binary, `program.${language}`);\n setCompileStatus('success');\n setTimeout(() => setCompileStatus('idle'), 2000);\n } catch (e) {\n setCompileStatus('error');\n setCompileError(e instanceof Error ? e.message : 'Network error');\n }\n }, [code, language, loadBinary]);\n\n const handleToggleCodeEditor = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n setShowCodeEditor(prev => !prev);\n }, []);\n\n return (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".bin,.elf\"\n onChange={handleFileInputChange}\n className=\"hidden\"\n />\n <BaseNode inputPorts={inputPorts} outputPorts={outputPorts} selected={selected} className=\"min-w-[140px]\" showPortLabels={data.showPortLabels} onPortClick={data.onPortClick} glowUnconnected={data.glowUnconnected}>\n <div className=\"flex flex-col items-center gap-2\">\n {/* Label */}\n <div className=\"px-2 py-1 text-xs font-medium text-[var(--embed-text-primary)]\">\n {data.label || 'InstrMem'}\n </div>\n\n {/* Type badge */}\n <div className=\"px-3 py-2 text-xs font-semibold rounded-md bg-[var(--embed-bg-tertiary)] text-[var(--embed-text-primary)]\">\n IMEM\n </div>\n\n {/* Drop Zone */}\n <div\n className={`\n flex flex-col items-center gap-1 p-2 rounded border-2 border-dashed cursor-pointer transition-all w-full\n ${isDragOver\n ? 'border-blue-500 bg-blue-500/10'\n : loadedFilename\n ? 'border-green-500/50 bg-green-500/10'\n : 'border-[var(--embed-border)] hover:border-blue-400 hover:bg-blue-500/5'\n }\n `}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onClick={handleClickDropZone}\n title={loadedFilename ? 'Click to replace' : 'Drop .bin or click'}\n >\n {loadedFilename ? (\n <>\n <div className=\"text-xs text-green-400 font-medium truncate max-w-[120px]\">\n {loadedFilename}\n </div>\n <div className=\"text-xs text-[var(--embed-text-muted)]\">\n {loadedSize} bytes\n </div>\n <button\n onClick={handleClear}\n className=\"text-xs text-red-400 hover:text-red-300 hover:underline\"\n >\n Clear\n </button>\n </>\n ) : (\n <>\n <div className=\"text-xs text-[var(--embed-text-muted)]\">Drop .bin</div>\n <div className=\"text-xs text-[var(--embed-text-muted)]\">or click</div>\n </>\n )}\n </div>\n\n {/* Code Editor Toggle */}\n <button\n onClick={handleToggleCodeEditor}\n className={`\n w-full px-2 py-1 text-xs rounded transition-colors\n ${showCodeEditor\n ? 'bg-violet-500/20 text-violet-400'\n : 'bg-[var(--embed-bg-tertiary)] text-[var(--embed-text-muted)] hover:bg-violet-500/10 hover:text-violet-400'\n }\n `}\n >\n {showCodeEditor ? 'Hide Code' : 'Code'}\n </button>\n\n {/* Code Editor Panel */}\n {showCodeEditor && (\n <div\n className=\"flex flex-col gap-2 w-full min-w-[280px] nodrag\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* Language Selector */}\n <div className=\"flex gap-1\">\n {LANGUAGES.map(lang => (\n <button\n key={lang.value}\n onClick={() => setLanguage(lang.value)}\n className={`\n px-2 py-0.5 text-xs rounded transition-colors\n ${language === lang.value\n ? 'bg-violet-500/30 text-violet-300'\n : 'bg-[var(--embed-bg-tertiary)] text-[var(--embed-text-muted)] hover:bg-[var(--embed-bg-tertiary)]/80'\n }\n `}\n >\n {lang.label}\n </button>\n ))}\n </div>\n\n {/* Code Input */}\n <textarea\n value={code}\n onChange={(e) => setCode(e.target.value)}\n placeholder={PLACEHOLDER_CODE[language]}\n className=\"w-full h-32 p-2 text-xs font-mono rounded border border-[var(--embed-border)] bg-[var(--embed-bg-code)] text-[var(--embed-text-primary)] resize-y\"\n spellCheck={false}\n />\n\n {/* Compile Button */}\n <button\n onClick={handleCompile}\n disabled={compileStatus === 'compiling'}\n className={`\n w-full px-3 py-1.5 text-xs font-medium rounded transition-colors\n ${compileStatus === 'compiling'\n ? 'bg-[var(--embed-bg-tertiary)] text-[var(--embed-text-muted)] cursor-wait'\n : compileStatus === 'success'\n ? 'bg-green-600 text-white'\n : 'bg-violet-600 hover:bg-violet-500 text-white'\n }\n `}\n >\n {compileStatus === 'compiling' ? 'Compiling...'\n : compileStatus === 'success' ? 'Loaded!'\n : 'Compile & Load'}\n </button>\n\n {/* Error Display */}\n {compileStatus === 'error' && compileError && (\n <div className=\"p-2 text-xs font-mono rounded bg-red-500/10 text-red-400 max-h-24 overflow-y-auto whitespace-pre-wrap\">\n {compileError}\n </div>\n )}\n </div>\n )}\n </div>\n </BaseNode>\n </>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simten/ui",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Canvas, editor, and waveform React components for Simten. Built on React Flow with dagre layout and Zustand stores.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Charles Harris",
@@ -88,7 +88,7 @@
88
88
  "radix-ui": "^1.4.3",
89
89
  "tailwind-merge": "^3.4.0",
90
90
  "zustand": "^5.0.10",
91
- "@simten/core": "0.3.0"
91
+ "@simten/core": "0.4.0"
92
92
  },
93
93
  "peerDependencies": {
94
94
  "react": "^18.0.0 || ^19.0.0",