Changed from RitzRuntime.loadComponent() (doesn't exist) to
new RitzLoader().load() (correct API).
Also updated DOM element IDs:
- #root → #app (RitzLoader default)
- Added #status div for load status messages
- Added styling for status indicator
Should now load properly in browser.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created a new example that demonstrates what we need for proper string/type support:
**TextInput Example (currently a counter):**
- Initially tried to build reactive text input
- Exposed 5 critical limitations:
1. String signals stored as i32 (should be i8*)
2. F-string interpolation incomplete (f"Count: {count}" → "0")
3. No oninput event (only onclick supported)
4. No event value passing (can't get input.value)
5. No string operations (len, concat, etc.)
**Quick Fix Applied:**
- Added type coercion in _emit_signal_globals()
- String signals default to i32 0 (temporary)
- Bool signals convert True/False to 1/0
- Example now uses counter to demonstrate reactive updates
**TYPE_SYSTEM_ROADMAP.md:**
Complete implementation plan for proper type support:
- Phase 1: Type hints extraction (already works!)
- Phase 2: Typed signals (i32, i8*, i1)
- Phase 3: String interpolation in text nodes
- Phase 4: Generalized event system
- Phase 5: Component parameter type checking
- Phase 6: Delegate/callback types
This example will drive the type system implementation. Once complete,
text input will work with proper string signals and reactive updates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Bug Fixes:**
- Fixed duplicate js_append_child calls causing DOM element re-insertion
- Elements were being appended twice: once by self-append logic, once by parent loop
- This was breaking CSS transitions on vertical tabs (elements moved in DOM)
- Removed self-append logic from _emit_with() and _emit_yield_component()
**Refactoring:**
- Created reusable HTab and VTab components for horizontal/vertical tabs
- Reduced repetitive tab code from 9 lines per tab to 1 line
- Improved code maintainability and reusability
- WASM bundle size reduced from 5987 bytes to 4690 bytes (22% reduction!)
**Result:**
- CSS transitions now work smoothly on vertical tabs ✓
- All 55 tests passing ✓
- Cleaner, more composable tab components ✓
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Features:
- Track attributes that depend on signals (ternary expressions)
- Store element references in globals for reactive attributes
- Re-evaluate and update only changed attributes when signals change
- Similar to reactive conditionals but for attributes
Performance:
- Minimal DOM updates - only changed attributes are updated
- No full re-renders, no virtual DOM diffing
- Direct attribute updates via js_set_attribute
Example:
class_='tab active' if tab_index == 0 else 'tab'
When tab_index changes, only the class attribute updates.
Implementation:
- Collection phase: scan for attributes with signal dependencies
- Render phase: store element references to globals
- Signal update: re-evaluate expression and update attribute
All tests passing (55 passed, 2 skipped)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Component render functions return i32 (root element) instead of void
- Nested components (yield SomeComponent()) now work correctly
- Added main() entry point that calls top-level component and sets root
- Updated runtime to call main() instead of render_ComponentName()
Note: Active state in ternary expressions still needs reactive updates
This commit fixes the nested component rendering issue
All tests passing (51 passed, 2 skipped)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes:
- Lambda functions now correctly pass arguments to handlers
- Function parameters properly emitted in LLVM IR
- Event handlers defined with parameter lists
New feature - Ternary expressions:
- Support Python ternary syntax (x if cond else y) in props
- Eliminates repetitive if/else blocks for active states
- Before: 6 lines per tab button
- After: 1 line with ternary expression
Example:
class_='tab active' if active else 'tab'
All tests passing (51 passed, 2 skipped)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements efficient reactive conditionals that pre-render branches once
and swap DOM nodes without recreation, enabling fast switching with
thousands of elements.
Key Fixes:
- Runtime now calls reevaluate_conditional_*() on signal changes
- Match/case swap logic uses phi nodes to load correct old case
- Previously hardcoded case_0 as old value, causing accumulation
- Branch render functions now wrap all content in container div
Implementation:
- Pre-render both if/else branches at init
- Store roots in globals (@cond_N_then_root, @cond_N_else_root)
- On signal change, swap DOM nodes via js_replace_at_marker()
- Match statements use switch/phi pattern to select old case
Tests:
- Added test_reactive_conditionals.py (5 new tests)
- Updated test_llvm_codegen_conditional.py for reactive infrastructure
- All 35 tests passing
Performance: No re-rendering on switches, perfect for dynamic content.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Critical change that makes conditionals reactive:
- Added signal_conditional_deps map to track dependencies
- Added _extract_signals_from_expr() to find signals in expressions
- Populate dependency map during _collect_conditionals()
- Replace TODO comments in signal setters with reevaluate calls
How it works:
1. During collection, analyze if/match test/subject expressions
2. Extract all signal names referenced in conditions
3. Build map: signal_name -> [conditional_ids that use it]
4. When signal is updated (assign/augassign), call reevaluate for each dependent conditional
Example: set_tab_0() now:
store i32 0, i32* @signal_Tabs_tab_index
call void @reevaluate_conditional_4()
call void @reevaluate_conditional_5()
call void @reevaluate_conditional_6()
call void @reevaluate_conditional_7()
This makes tabs fully interactive!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implemented _emit_match_reactive() to generate init/reevaluate functions
- Modified _emit_match() to create markers and call init functions
- Init function pre-renders all cases and uses switch to insert active one
- Reevaluate function checks if subject changed and swaps DOM
Match init function:
- Calls _render_cond_X_case_Y() for each case
- Stores all case roots in globals
- Evaluates subject with switch instruction
- Inserts matching case at marker position
Fallback to _emit_match_static() if not collected.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Modified _emit_if() to:
- Create marker node via js_create_marker()
- Append marker to parent element
- Store marker ID in global
- Call _init_conditional_X() to render and insert active branch
Branch render functions work correctly:
- Build element tree locally
- Return root element ID
- Called by init function to pre-render all branches
Fallback to _emit_if_static() if conditional not collected.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add parent_element_stack to track nesting context
- Elements inside if/match branches append to parent
- Fixes: Li elements inside if statements now append to Ul parent
- Tabs now render visibly!
- TODO: Fix duplicate appends
- All tests passing (30/30)
- Add _emit_match() using LLVM switch instruction
- Handle value patterns and wildcard (case _:) patterns
- Each case gets its own basic block with branch to end
- Wildcard case becomes default label in switch
- All tests passing (30/30)
- Tabs.wasm size: 1908 → 3185 bytes
- Handle 'assign' type statements in _emit_handler_statement()
- Evaluate value expression and store to signal global
- Enables patterns like: setting_tab = 0
- All tests passing (30/30)