Dyo is a JavaScript library for building user interfaces.

Overview

Dyo

Dyo

A JavaScript library for building user interfaces.

Coverage Size Licence NPM

Installation

  • Use a Direct Download: <script src=dyo.js></script>
  • Use a CDN: <script src=unpkg.com/dyo></script>
  • Use NPM: npm install dyo --save

Documentation

Documentation can be find on the website.

See the Getting Started page for a quick overview.

The documentation is divided into several sections:

You can improve it by sending pull requests to this repository.

Examples

Several examples can be found on the website. Here's one to get started:

import {h, render} from 'dyo'

function Example (props) {
	return h('h1', {}, 'Hello ', props.name)
}

render(h(Example, {name: 'World'}), 'body')

This will render a heading element with the text content "Hello World" into the specified target(the body element).

Comparison

The library is much alike React, so it's only natural that a comparison of the differences is in order; Which if successful might manage to highlight why it exists.

Re-parenting

The Portal component supports string selectors as targets. This presents an array of different possibilities with regards to isomorphic target references.

function Example (props) {
	return h(Portal, {target: 'main'}, 'Hello')
}

render(h(Example), 'body')

In addition to this – re-parenting is baked into portals. That is when a portals container is changed, instead of unmounting its contents and re-mounting them to the newly designated container we can instead move its contents without replaying destruction unmount operations that may discard valuable interface and component state.

In co-ordination with custom renderers, portals afford the opportunity to create atomic branch specific custom renderers. Imagine isolated declarative canvas renderers within a document renderer.

Promises

Promises(or thenables) are first class values. This affords authors the ability to render promises, directly await promises within effects and events, and delay unmounting.

render(props => Promise.resolve('Hello'), 'body')

function Example (props) {
	useEffect(async () => {
		// out of band updates in here
		// are also batched
		return async () => {
			// delays unmount until the animation
			// has completed
			return props.current.animate({}).finished
		}
	})
}

Callbacks

In an async world, public interfaces like render are not guaranteed to complete synchronously if a subtree happens to have async dependencies within it. A consequence of this will see more use cases for the optional callback arguments that this function accepts – in much the same way authors are afforded the ability to await on this central routine.

await render(props => Promise.resolve('Hello'), 'body')
Resources

In addition to other hooks, a resource allocation hook that can be used to fetch and cache resources.

function Example (props) {
	const resource = useResource(props => fetch('https://reqres.in/api/users'))
	return h('pre', {}, JSON.stringify(resource))
}
Async Server Rendering

Server side rendering supports the plethora of async primitives supported.

import {http} from 'http'
import {h, render, useResource} from 'dyo'

function Example (props) {
	const resource = useResource(props => fetch('https://reqres.in/api/users'))
	return h('pre', {}, JSON.stringify(resource))
}

http.createServer((request, response) => {
	return render(h('html', {}, h(Example)), response)
}).listen(8080)

License

Dyo is MIT licensed.

Comments
  • DIO 8

    DIO 8

    Ready for the most part, mostly tweaking the level of abstractions to allow for a clean transition into the 2-phase commit->flush approach for the next minor release before/when react fiber(async mode) is released and cooperative scheduling is proven a necessary abstraction.

    Currently the infrastructure looks like reconcile -> commit -> renderer. The transition would make it look like reconcile -> commit ... [DOM/Native...]renderer(commits).

    opened by thysultan 196
  • RFC: Hooks

    RFC: Hooks

    Similar to React Hooks. RFC discussion.

    The differences being

    1. The use of a single setter/getter stream instead of a tuple. So value = use(value) instead of [value, setValue] = use(value). This allows us to use live values to avoid the age old problem of stale data. That is value() would always return the current value.
    2. The unification of hooks and effects into a single use API. i.e use(value) and use(value, callback) instead of useState and useEffect.
    3. Support for unmount animations as can be archived with componentWillUnmount. Without which hooks wouldn't have full feature parity with lifecycle methods.
    4. ...and passing [dependencies], props, state, context to the effect callback to effectively avoid being tied to closures.

    An example of the aforementioned might look like the following:

    import {h, use, render} from 'dyo'
    
    function Counter (props, {refs, value = use(0)}, context) {
    	try {
    		return h('div', {ref: refs},
    			h('button', {onClick: e => value(value + 1)}, '+'),
    			h('button', {onClick: e => value(value - 1)}, '-'),
    			h('h1', {}, value)
    		)
    	} finally {
    		useAnimation(value)
    	}
    }
    
    function useAnimation (value) {
    	return use([value], ([value], props, {refs}, context) => {
    		return () => {
    			return refs.current.animate([], {}).finished
    		}
    	})
    }
    

    Point 3 arises the question of how do we handle the case when multiple effects try to register unmount animations: Do we 1. Register all the animations? or 2. Register the last animation?

    opened by thysultan 59
  • Why not making it compatible with React.js?

    Why not making it compatible with React.js?

    Hi, I find it interesting that I can use the same code with React, Preact and Inferno by simply importing the equivalent h, render and Component from them. I'd love to be able to do the same with Dio.js, but it seems Dio's API is not compatible. For example, inside a component's render I'd have access to the props with this.this.props instead of this.props. Wouldn't you be interested in keeping the same compatibility layer in the basic API, just like Preact and Inferno do? This way, authors of React-like application can easily switch their VDOM implementation and compare them.

    opened by rosenfeld 51
  • Are there any plans to support defaultValue in form elements?

    Are there any plans to support defaultValue in form elements?

    React supports the defaultValue option for several form elements, which is often used with uncontrolled components: https://reactjs.org/docs/uncontrolled-components.html

    Is Dio.js going to support those as well?

    opened by rosenfeld 42
  • Adding support for prop validation (aka

    Adding support for prop validation (aka "propTypes") to DIO

    As discussed in #71 it would be nice if DIO had support for propTypes validation, as React has. In the next release of DIO there will be separated packages for DEVELOPMENT and PRODUCTION (as in React), see #72. So it's possible to add propTypes validation to DIO that will only be performed in DEVELOPMENT mode and NOT in PRODUCTION.

    Task description:

    • Add propTypes and contextTypes validation support for DIO component classes and DIO stateless functional components (no need to implement support for "childContextTypes").
    • Add propTypes validation for ContextProviders (=> new context API)
    • Make sure that the above mentioned changes have the same API and behavior as in React, and also make sure that all the changes for the propType validation logic are not included in DIO's PRODUCTION packages.
    opened by mcjazzyfunky 23
  • 9.0.0

    9.0.0

    This adds the new context api, improves some implementation details and makes changes that would make it easier to implement https://github.com/thysultan/dio.js/issues/51.

    The current commit includes changes that make Error Boundaries more inline with https://github.com/thysultan/dio.js/issues/50

    There are still some tests that fail/skipped, namely, the Factory test, but that is intentional because i'm still figuring out if any other config hooks need to change.

    opened by thysultan 21
  • Enhance build scripts to produce development and production packages

    Enhance build scripts to produce development and production packages

    Description: As discussed in #71 it would be nice if the DIO build scripts produced both development and production artifacts for the usual DIO packages. This would allow (for future DIO versions) additional checks and validations in development mode to increase the overall development experience, while those additional checks and validations would not be applied in production mode (for performance reasons). This is similar to React, where you find two packages "react.development.js" and "react.production.min.js".

    Task: Enhance DIO's build scripts to produce packages for development and production. Find some way to allow code blocks to be removed for the production artifacts.

    opened by mcjazzyfunky 20
  • Discussion about props validation

    Discussion about props validation

    The following is just meant to be (hopefully) base of a discussion - not a feature request yet.

    DIO does not provide a feature to validate the component props (known as "propTypes" in react-development). I really can understand that this is not implemented in DIO. Nevertheless - especially if you do not use TypeScript - the development experience would be highly increased if you had some kind of props validation in your development environment. Of course programmers can write their own Component extension that adds that validation if they want - using super constructor and componentWillReceiveProps to add the props validation features. But whatever they do, it will not result in the same programming experience that they would have with React (there will be some annoying additional boilerblate code and error messages will not show the path within the component tree etc.).

    Frankly, I personally do not like the way the whole component metadata has to be declared in React, especially the propsType API - what about the following simple non-React-conform solution:

    DIO's Component class povides a static class methods validateProps(props: PropsType): Error | Error[] | null (the base implementation returns null) that will be called before each constructor call and before each invocation of componentWillReceiveProps. If it returns an error or an array of errors those errors will be printed out on console using console.error or console.warn (whatever you like) on DEV, including information about the concreate node in the component tree =>that's all. In PRODUCTION the validateProps class method will just be ignored.

    As static class methods will be inherited to subclasses and the corresponding (sub)class (aka. constructor) can be accessed via this inside of a static class method, all programmers could (optionally) implement/use the validation system of their choice.

    Oh BTW: Since a couple of weeks, React's context providers can also have prop validation. That also should be added as suggested above.

    opened by mcjazzyfunky 18
  • Better support for custom elements (additional issue)

    Better support for custom elements (additional issue)

    The only JSX based UI library that I know, where the following custom element topic is working fine, is "Crank.js", but I think this could also work with "Dyo" by only changing one line of code (at least I'm claiming it, have not really tested), plus unit tests of course.

    Please check the following simple counter demo written with Crank.js: https://codesandbox.io/s/crank-webcomponents-demo-forked-kldle?file=/src/index.tsx

    The important parts are:

    1. In line 16 of file index.tsx you find the following: <demo-counter label="Sheep count" onCountChange={onCountChange} /> This is 100% type safe! Especially the onCountChange stuff is 100% type safe!

    2. In file demo-counter.ts you find the type definition and implementation of custom element demo-counter. This type definition there is completely framework agnostic! For the implementation of that custom element an experimental webcomponent library is used, but this is not important here - please just ignore it.

    Now please check the Dyo version (is working properly): https://codesandbox.io/s/dyo-webcomponents-demo-forked-u7ek6?file=/src/index.tsx

    The important parts are:

    1. In line 15 of file index.tsx you find the following line: <demo-counter label="Sheep count" oncount-change={onCountChange} /> While that label="Sheep count" stuff is type safe, that oncount-change=... stuff is NOT (you do not get a compile error in this example due to the hyphen in oncount-change but nevertheless it's not type safe (and if the event type would be only change instead of count-change you would indeed get a compile time error). FYI: this demo-counter component supports both a count-change event and an onCountChange property, but in Dyo, if a property starts with on always addEventListener is used independent whether there's a corresponding property or not.

    2. File demo-counter.ts is exactly the same as in the Crank version - still the type definition for that custom element is framework agnostic.

    This is how this issue could be fixed in Dyo (at least I think so): For each event normal DOM elements have also a corresponding "onevent" property. So you can either use myButton.addEventListener('change', ...) or myButton.onchange = .... A well implemented custom element should do the same IMHO with each supported event.

    If in the following line https://github.com/dyo/dyo/blob/2f1f48008ad485a31471b77c327bae5ec2e4887d/src/Interface.js#L205

    if (valid(name)) was replaced by if (valid(name) && !(name in instance)) then in the Dyo demo the line <demo-counter label="Sheep count" oncount-change={onCountChange} /> could be replaced with <demo-counter label="Sheep count" onCountChange={onCountChange} /> and everything would be nice and type safe also in Dyo.

    @thysultan What do you think?

    opened by mcjazzyfunky 16
  • The form attribute shouldn't be assigned to the input when its value is undefined

    The form attribute shouldn't be assigned to the input when its value is undefined

    I'm closing #67 in favor of this more easily reproducible issue:

    https://codesandbox.io/s/q360k5oj14

    You can see that Dio.js behaves differently from React by toggling the imports.

    opened by rosenfeld 16
  • Better support for custom elements

    Better support for custom elements

    Dyo's support for custom elements could actually be a bit better.

    Please have a look at the following demo: https://codesandbox.io/s/hopeful-sound-l3bvo?file=/src/index.js

    You find there two custom elements <custom-element ...> and <haunted-custom-element ...>. While the first one is implemented without using a special library, the second one is using the "haunted" web component library. It's important to know that "haunted" uses a proxy to handle the custom element's properties (no special setter or getter property functions are used).

    The demo uses Preact and I would say this is working as expected: It seems that if Preact finds a defined property it will use this property for setting the new value otherwise it will use setAttribute. As "Haunted" uses a proxy instead of explicitly defined props the Preact's heuristic fails. But I think that's not Preact fault, using a proxy for the custom elements may just not be the best solution.

    If you switch the demo to "Dyo" then the output is quite different: It seems that only setAttribute is used in this demo.

    Any chance that this could be enhanced some day (I don't think that this is urgent)?

    opened by mcjazzyfunky 15
  • next

    next

    exploring the next version of dyo

    • smaller
    • faster
    • better

    This is just the code that's been sitting on my computer, very much a WIP.

    • possible explorations: everything in a worker(maybe).
    opened by thysultan 0
  • Is it really a good idea to support generator function components and iterators/generators as virtual node in general?

    Is it really a good idea to support generator function components and iterators/generators as virtual node in general?

    This is just to open a discussion about the question whether Dyo should really continue to support generator function components and generators (aka. iterators) as children in general.

    For this issue, let's define an Iterable as an object that has a special property [Symbol.iterator] whose value is a function that returns something that we call Iterator and that satisfies the corresponding ECMAScript iterator protocol (I think we all know the nature of that protocol).

    It's important to know that ECMAScript iterators themselves have a property [Symbol.iterator] whose value is a function that returns an iterator (each time the same (= identical) iterator will be returned!). That makes a iterator look and behave like a iterable (for example it can be used in a for-of loop). But there's an important difference between ECMAScript iterators and "normal" ECMAScript iterables: An iterator can only be traversed once ... while "normal" ECMAScript iterables can be traversed multiple times (virtually infinite times).

    Dyo supports iterables as children (which is a really great feature and shall not be changed). As Dyo currently traverse those iterable children only once it's not a problem that Dyo treats children that are iterators the same way as if they were "normal" iterables. Therefore without any special logic, Dyo out of the box supports iterators as children as well.

    Let's assume somewhere in future Dyo will be splitted into a DEV and a PRODUCTION package to allow additional checks on DEV system like some kind of uniqueness check for keys. Or maybe a future Dyo will allow its API to be intercepted, similar to what you can do in Preact with this options object and someone wants to add some React-like prop-types validation in userland. In all such cases, children which are iterators will cause a lot of trouble as soon as the children need to be traversed twice and not just once. Some special userland extensions will not even be possible to be implemented because of that iterator issue.

    If Dyo did not allow iterators as children in the first place, nobody would really miss that "feature" (would anyone?) and the win would be that there will be no trouble with iterators any longer and things would be better prepared for future extensions.

    Here are a few example of iterators as children which currently are supported by Dyo but should not be supported in Dyo any longer in my opinon:

    function* MyComponent() {
      yield 1
      yield 2
      yield 3
    }
    

    This behaves exactly the same as the following

    function* gimmeOneTwoThree() {
      yield 1
      yield 2
      yield 3
    }
    
    function MyComponent2() {
      return gimmeOneTwoThree()
    }
    

    Which behaves similar to:

    function* gimmeOneTwoThree() {
      yield 1
      yield 2
      yield 3
    }
    
    function MyComponent3() {
      const oneTwoThree = gimmeOneTwoThree()
    
      return <>{oneTwoThree}</>
    }
    

    Even if this looks quite unusual, the following example is currently working and should also be working in future, as the component returns an iterable, not an iterator, and therefore will never cause trouble:

    function MyComponent4() {
      return {
        *[Symbol.iterator]() {
          yield 1
          yield 2
          yield 3
        }
      }
    }
    
    opened by mcjazzyfunky 16
Owner
Dyo
Dyo is a JavaScript library for building user interfaces.
Dyo
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
A library of high-quality primitives that help you build accessible user interfaces with SolidJS.

Solid Aria A library of high-quality primitives that help you build accessible user interfaces with SolidJS. Primitives @solid-aria/primitives - Expor

SolidJS Community 205 Jan 7, 2023
Absolutely minimal view layer for building web interfaces.

Superfine Superfine is a minimal view layer for building web interfaces. Think Hyperapp without the framework—no state machines, effects, or subscript

Jorge Bucaran 1.6k Dec 29, 2022
Types generator will help user to create TS types from JSON. Just paste your single object JSON the Types generator will auto-generate the interfaces for you. You can give a name for the root object

Types generator Types generator is a utility tool that will help User to create TS Interfaces from JSON. All you have to do is paste your single objec

Vineeth.TR 16 Dec 6, 2022
Million is a lightweight (<1kb) Virtual DOM. It's really fast and makes it easy to create user interfaces.

?? Watch Video ?? Read the docs ?? Join our Discord What is Million? Million is a lightweight (<1kb) Virtual DOM. It's really fast and makes it easy t

Derek Jones 5 Aug 24, 2022
AweSome Book App displays the book details entered by user and saves the information in Local storage. User can add and remove a book title/author to the library and from the library.

Awesome Book App with ES6 Used npm init -y command to create package.json file. Created the entry point for the JavaScript code called index.js Create

Krishna Prasad Acharya 8 Aug 15, 2022
A lightweight (<1Kb) JavaScript package to facilitate a11y-compliant tabbed interfaces

A11y Tabs A lightweight (<1Kb) JavaScript package to facilitate a11y-compliant tabbed interfaces. Documentation ↗ Demo on Codepen ↗ Features: Support

null 5 Nov 20, 2022
A monorepo for comma.ai web interfaces and packages

comma webapps This mono-repository contains the web applications and packages for the web UIs of comma.ai Contributing Just pick something and work on

null 5 Sep 27, 2022
Generated TypeScript interfaces for Aptos Move.

Aptos Framework TypeScript SDK Generated TypeScript interfaces for Aptos Move. This contains types for: AptosFramework MoveNursery MoveStdlib Releases

Aptosis 7 Aug 25, 2022
This project is built with JavaScript, Webpack, HTML & CSS, Leaderboard api. When user clicks on Refresh button it hits the api and responds with the data, The user can also post data to the api

leaderboad Description the project. this project is about the leaderboad i did during Microverse to build a website for adding Data to the API and fet

Emmanuel Moombe 4 May 30, 2022
Satyam Sharma 3 Jul 8, 2022
Remix enables you to build fantastic user experiences for the web and feel happy with the code that got you there. In this workshop, we'll look at some more advanced use cases when building Remix applications.

?? Advanced Remix Workshop Remix enables you to build fantastic user experiences for the web and feel happy with the code that got you there. In this

Frontend Masters 167 Dec 9, 2022
Grayce Muthui 8 Jun 16, 2022
This project is a user friendly project that provides the accurate constellation name of the user

OVERVIEW: This is a group project by certain members of the 100Devs community. Contributors Lee Gill | GitHub: LeeGee64 | Twitter: @LeeGee64 | LinkedI

Lee Gill 5 Jun 15, 2022
A live instant messaging app that translates user messages into the other user's preferred language.

BabelFish Description BabelFish is an interactive multi-person chat app with built in live translation. It is created using the MERN stack (MongoDB, E

Jamel 3 Jul 18, 2022