fix: component prop signal wrapping + import demo

- emit_component_decl now wraps props in signal-like accessors
- Props use { get value() { return props.X; } } pattern
- Missing props default to empty string instead of null
- Added examples/import-demo.ds demonstrating 3-component import
- Zero console errors when rendering imported Card, Badge, Button
This commit is contained in:
enzotar 2026-02-26 15:46:55 -08:00
parent 8a318e380e
commit 55dc24eecc
2 changed files with 27 additions and 2 deletions

View file

@ -466,9 +466,14 @@ impl JsEmitter {
fn emit_component_decl(&mut self, comp: &ComponentDecl, graph: &SignalGraph) { fn emit_component_decl(&mut self, comp: &ComponentDecl, graph: &SignalGraph) {
self.emit_line(&format!("function DS_{}(props) {{", comp.name)); self.emit_line(&format!("function DS_{}(props) {{", comp.name));
self.indent += 1; self.indent += 1;
// Destructure props into local variables // Destructure props into local signal-compatible variables
// Props may be raw values or signals — wrap in a signal-like accessor
for p in &comp.props { for p in &comp.props {
self.emit_line(&format!("const {} = props.{} !== undefined ? props.{} : null;", p.name, p.name, p.name)); // Create a signal-like wrapper: if prop is already a signal, use it; otherwise wrap
self.emit_line(&format!(
"const {} = (props.{} !== undefined && props.{} !== null) ? (typeof props.{} === 'object' && 'value' in props.{} ? props.{} : {{ get value() {{ return props.{}; }} }}) : {{ get value() {{ return \"\"; }} }};",
p.name, p.name, p.name, p.name, p.name, p.name, p.name
));
} }
let root_id = self.emit_view_expr(&comp.body, graph); let root_id = self.emit_view_expr(&comp.body, graph);
self.emit_line(&format!("return {};", root_id)); self.emit_line(&format!("return {};", root_id));

20
examples/import-demo.ds Normal file
View file

@ -0,0 +1,20 @@
-- DreamStack Import Demo
-- Demonstrates component imports from registry
import { Button } from "../registry/components/button"
import { Card } from "../registry/components/card"
import { Badge } from "../registry/components/badge"
let count = 0
view main = column [
text "🧩 Component Composition" { variant: "title" }
text "Imported 3 components from registry" { variant: "subtitle" }
Card { title: "Counter Card" }
Badge { label: "imported", variant: "success" }
Button { label: "Click me", variant: "primary" }
text "Count: {count}"
button "+1" { click: count += 1, variant: "primary" }
]