diff --git a/examples/showcase.html b/examples/showcase.html new file mode 100644 index 0000000..a7981f0 --- /dev/null +++ b/examples/showcase.html @@ -0,0 +1,1202 @@ + + + +
+ + +Five capabilities that exist nowhere else — not in React, Svelte, Solid, Vue, or any other framework. Each + one is novel. Together, they're a paradigm shift.
+In every other framework, signals are invisible to the type system. You can pass a + signal where a plain value is expected and it silently breaks. DreamStack catches this at + compile time.
+// The compiler KNOWS these are reactive +let count = 0 // → Signal<Int> +let name = "Ada" // → Signal<String> +let doubled = count * 2 // → Derived<Int> +let hot = count > 10 // → Derived<Bool> + +// ✅ Type-safe: compiler verifies deps +// ✅ Auto-tracks what to re-render +// ✅ Zero accidental subscriptions+
// TypeScript can't tell these apart: +const [count, setCount] = useState(0) +// count is... number? Signal? Who knows? + +// This compiles but SILENTLY BREAKS: +function add(a: number, b: number) { + return a + b +} +add(count, 5) // ← loses reactivity! +// No framework catches this at compile time+
React has useEffect (untyped, untestable). DreamStack has algebraic effects — declare + what side-effects a function may perform, and the compiler enforces that every effect is + handled. Swap handlers for testing without touching business logic.
+// Declare what effects exist +effect Http.get(url: String): Response +effect Time.delay(ms: Int): () + +// Use them — the TYPE tracks it +let search = (q) -> { + perform Time.delay(250) + perform Http.get("/api?q=" ++ q) +} +// search : (String) -> Response ! Http, Time + +// In production: +handle { Http.get(u) -> fetch(u) } + +// In tests — SAME code, DIFFERENT handler: +handle { Http.get(u) -> mock_data }+
// Effects are opaque and untraceable +useEffect(() => { + fetch('/api') // ← hidden side-effect + .then(r => r.json()) + .then(setData) +}, [query]) + +// Questions no framework can answer: +// • What effects does this component perform? +// • Are all effects cleaned up? +// • Can I swap fetch for a mock? +// • Will this work without network? +// +// Answer: 🤷 good luck+
In other frameworks, spring animations are separate from state. In DreamStack, a spring + IS a signal — set its target and every derived value, every view binding, every layout constraint + updates automatically through the reactive graph. Physics and reactivity are one system.
+// A spring IS a signal — same API, same graph +let sidebar_w = spring( + target: 240, + stiffness: 170, + damping: 26 +) // → Spring<Float> (is-a Signal<Float>) + +// Derived values track spring physics! +let main_w = 1000 - sidebar_w +// main_w smoothly animates as sidebar springs + +// Layout constraints + springs = magic +view main = row [ + panel { width: sidebar_w } // springs! + panel { width: main_w } // auto-follows! +] + +on toggle -> sidebar_w.target = 64 +// Everything animates. Zero manual work.+
// Animation is separate from state +const [sidebar, api] = useSpring({ + width: expanded ? 240 : 64 +}) + +// Want main panel to follow? Manual math: +const main = sidebar.width.to( + w => 1000 - w +) // ← manual interpolation per value + +// Want derived-of-derived? More manual work. +// Want 5 things to follow? 5× manual. +// Physics never feeds back into the +// reactive graph. Two separate worlds. +// +// Spring ≠ Signal. They can't talk.+
In React/Solid, dependencies are discovered at runtime. DreamStack's compiler statically + analyzes the entire signal dependency graph before a single line runs. Dead signals get eliminated. + Over-subscription is impossible.
+// The compiler produces this at BUILD TIME: +Signal Graph { + count: Source(Int) → [doubled, is_hot, view] + doubled: Derived(Int) ← [count] + is_hot: Derived(Bool) ← [count] + + // Dead signal detection: + ⚠ unused_var: Source(String) — DEAD, eliminated + + // Optimal subscription plan: + view.main subscribes to: [count, doubled, is_hot] + // NOT to unused_var — zero wasted work +}+
// Dependency discovery happens AT RUNTIME +// The compiler has NO IDEA what subscribes to what + +useEffect(() => { + // React: "I'll figure it out when it runs" + // Missing dep? Silent stale closure bug. + // Extra dep? Runs too often. + setDoubled(count * 2) +}, [count]) // ← YOU must list deps manually + +// In Solid: auto-tracking is runtime-only. +// Unused signals still exist in memory. +// Over-subscription? No compiler to warn you.+
CSS was designed for documents, not UIs. DreamStack uses a Cassowary constraint solver —
+ the same algorithm Apple uses for Auto Layout. Declare relationships between elements, and the solver
+ finds the solution. No flex-grow: 1; min-width: 0; overflow: hidden nightmares.
// Declare relationships. Solver does the math. +constraint sidebar.width == 200 @ Strong +constraint sidebar.width >= 64 @ Required +constraint main.x == sidebar.x + sidebar.width +constraint main.x + main.width == 1000 + +// The solver guarantees: +// • sidebar = 200, main = 800 (normal) +// • sidebar = 64, main = 936 (collapsed) +// • NEVER sidebar = -1 or main = NaN + +// Bonus: constraint + spring = animated layout +constraint sidebar.width == sidebar_spring +// Physics drives layout. Solver maintains truth.+
/* Hope and pray this works: */ +.sidebar { + width: 200px; + min-width: 64px; + flex-shrink: 0; + transition: width 0.3s; +} +.main { + flex: 1; + min-width: 0; /* ← the classic hack */ + overflow: hidden; /* ← another hack */ +} + +/* What if sidebar + main > viewport? */ +/* What if content pushes sidebar wider? */ +/* What if animation causes flash of wrong layout? */ +/* CSS: ¯\_(ツ)_/¯ */+
Five capabilities. Zero competitors have all five. Most have zero.
+| Capability | +DreamStack | +React | +Svelte 5 | +Solid | +Vue | +
|---|---|---|---|---|---|
| Signals in the type system | +✓ | +✕ | +✕ | +✕ | +✕ | +
| Algebraic effects (testable side-effects) | +✓ | +✕ | +✕ | +✕ | +✕ | +
| Springs are signals (unified graph) | +✓ | +✕ | +✕ | +✕ | +✕ | +
| Compile-time dependency graph | +✓ | +✕ | +~ | +✕ | +✕ | +
| Constraint-based layout (Cassowary) | +✓ | +✕ | +✕ | +✕ | +✕ | +
| Score | +5/5 | +0/5 | +~0.5/5 | +0/5 | +0/5 | +