dxinteractive / dendriform Goto Github PK
View Code? Open in Web Editor NEWBuild performant, reactive data-editing UIs for React.js. Succinct code, observable state, undo & redo included!
License: MIT License
Build performant, reactive data-editing UIs for React.js. Succinct code, observable state, undo & redo included!
License: MIT License
New data type that can lazily derive, async, for heavy operations.
value
returns a promise and accessing it kicks off the lazy derivationuseValue()
hook, it will kicks off its lazy derivation againuseValue()
hook - it may even want to pass through something that its subscribed to (e.g. image rendering that builds up over time) or keep its old value until the new one is done deriving.const nameForm = new Dendriform('cool');
const ageForm = new Dendriform(12);
const picture = new LazyDeriver(async () => {
coolCanvas.text('name', nameForm.value);
coolCanvas.text('age', ageForm.value);
return await coolCanvas.render();
}, [nameForm, ageForm]);
button.onClick(() => {
document.appendChild(await picture.value);
});
// react
function Compy() {
const picture = useLazyDeriver(async () => {
coolCanvas.text('name', nameForm.value);
coolCanvas.text('age', ageForm.value);
return await coolCanvas.render();
}, [nameForm, ageForm]);
const pictureInverted = useLazyDeriver(async () => {
return await picture.invert();
}, [picture]);
return <div>{pictureInverted.useValue()}</div>;
}
Be able to make forms that test potential changes with a function, and do not accept changes if that test fails. Also don't allow changes to go through if derived functions fail too. Might involve an internal revert function that can be called on all derived things.
This could allow for a generalised "collection of items whose ids refer to specific other items lifespans" construct
Async buffering is an API nicety, but the timing issues it causes aren't worth the hassle.
Right now if two changes can squeeze in rapid succession before a setTimeout(..., 0)
can fire, then dendriform may push out an update that is stale compared to any state hooks that are tracking the same data in real time. This isn't the worst thing but can cause unavoidable cursor jumping if values are bound onto text inputs, and maybe worse.
.set()
not async by removing the setTimeout()
batch()
and flush()
methods, and If someone wants to call 2 set()
in a row they must call batch()
first and finish with flush()
. In dev mode we can warn if 2 sets get called too fast (less than setImmediate), and if flush isn't called fast enough (more than setImmediate)Perhaps onDerive is good enough for this?
Relies on #20
It can be useful for a set to pass along additional information in a set()
so that onChange
handlers can conditionally behave in a different way.
If any state is related to other state's lifespans, then we'll need to be able to know when a particular item in a dendriform tree is deleted.
// proposal
import {array} from 'dendriform';
// changes to
import {array} from 'dendriform/array';
Wouldn't require a breaking change.
When sync
is used, people shouldn't also use onDerive()
between the same forms, but making people do this is a tough ask, especially if different parts of a system may be deriving to each other. Instead make Dendriform have a register of sync groups, which sync
can add to, and check which members of each have synced after deriving is complete, and throw no-change's in the others.
Instead of
const [value, setValue] = form.useValue();
it will be cleaner in most cases to have
const value = form.useValue();
// to set, call form.set();
because it avoids going form.useValue()[0]
to do one-liners, reduces the API size (setValue and form.set are identical), and reduce confusion (setValue doesnt need to be used via a hook, but value does in order to receive updates)
const form = new Dendriform({foo: 123}):
form.onDerive(value => {
// works, value is {foo: 123}
});
form.branch('foo').onDerive(value => {
// doesn't work, value is {foo: 123} but should be 123
});
Haven't hit this in the wild yet.
Quite a lot of potential crossover with #73.
Add something like form.readonly()
that returns the same form but where .set()
is disabled. This'll allow the observable abilities of forms to be spread around an app while also being able to whitelist where the forms value can be updated from.
Because form.buffer()
and form.done()
aren't global, and they rely on callAllChangeCallbacks()
not being called in order to buffer changes.
Make it rely on focus to the correct demo too
Allows debouncing to be used anywhere a .set()
can take place. Perhaps as form.set("new", 200)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.