Reactive front end framework, with an integrated state management system.
The purpose of Cascade is to make it simple and fast to build advanced user interfaces that are data driven, generative and reactive.
Unlike most reactive UI frameworks, Cascade renders directly onto a live target in one pass - reading and writing the real DOM in tree order - rather than building an abstract tree first and reconciling it separately. All while still ensuring minimal changes to the DOM upon change.
Signals are great for building reactive systems, and they come in many forms and shapes, such as properties of MobX observables or Vue property values. But the problem with signals is: there is usually only one signal per object and per property.
This means that with signals you are forced to build an explicit dependency graph, storing intermediary values as their own signals.
But this is not how rendering and document transformation is normally done! When rendering, and when transforming documents, there is a sequence of operations that transform the same object.
Temporal signals allow us to build a pipeline of readers and writers of data that manipulate the same data objects. They each operate within their own time frame, only invalidating other readers downstream in the pipeline.
Where signals introduce the space dimension for observation, temporal signals also introduce the time dimension for observation.
In a small form: three readers and writers of the same object, in a pipeline, at three fixed times. The first capitalizes the heading's text and the second doubles its size - each by writing the very property it reads - and the third sees the result. Change one property, and only the steps that read it along the way run again: two of the three, never all of them.
With ordinary signals - one value per property - a step can't tell its input from its own output. Reading back the size it just doubled, it would either set itself off again, doubling over and over (MobX, for one, gives up after 100 rounds), or, where a reaction can't trigger itself, the original size would be lost for good, and the next time the step runs it doubles its own result. The way around it is a signal of its own for every intermediate value - an explicit dependency graph, built by hand.
import getWorld from "@liquefy/cascade.reactive";
const { observable, repeat } = getWorld({ timeLevels: 3 });
const heading = observable({ text: "hello world", size: 16 });
// Time 0: capitalizes the text - writing the very property it reads.
repeat(() => { heading.text = heading.text.toUpperCase(); }, { time: 0 });
// Time 1: headings are twice the size - the same, for the size.
repeat(() => { heading.size = heading.size * 2; }, { time: 1 });
// Time 2: sees the heading as times 0 and 1 left it.
repeat(() => console.log(heading.text, heading.size + "px"), { time: 2 });
// HELLO WORLD 32px
heading.text = "temporal signals";
// TEMPORAL SIGNALS 32px - times 0 and 2 run again,
// time 1 doesn't: it never read the text.
heading.size = 20;
// TEMPORAL SIGNALS 40px - times 1 and 2 run again, time 0 doesn't.
// Time 1 reads the new 20, not its own 32: no doubling twice.In Cascade this mechanism is used to define a reactive order of rendering, so that a parent can render before its children, measure its bounds, and pass the bounds on to its children for programmatic reactive layout. So temporal signals are used in Cascade to build a reactive front end framework with unprecedented precision.
But the real use case where temporal signals shine is when building WYSIWYG word processors and other document editors, which temporal signals are especially engineered for.
Name another reactive front end framework where animating an entire form can be reduced down to a one-liner. This becomes possible because of sub-frame render precision and temporal reactivity that can do complex FLIP-animation setup in the middle of a render cycle.

Components can override either build() or render(). 'Build components' just build children and let them do all work. 'Render components' however interact directly with the render target and give direct render instructions. Both see the render context - what the components around them provide - which holds only timeless values: build components see the final value of every property.
Cascade offers opportunities and features, with as few requirements as possible. There are multiple ways to do the same thing in this framework, and everyone can find a style of development that fits them. For example:
React and Cascade are very different, there is some React DNA in Cascade - the author of Cascade was a huge fan of React from its very start.
Similarities
Differences
Cascade is what you would get if you took all the capabilities of React and MobX, added temporal signals, and mixed it all together. It can do everything those systems can do - but with temporal signals and sub-frame precision, it takes it to the next level.
This demo is a work in progress.