npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@orby/core

v0.1.7

Published

Orby is a small experiment of functional components based on virtual-dom.

Downloads

39

Readme

Orby is a small and minimalist library to create modern interfaces based on JSX, Virtual-Dom and Functions.

Index

  1. Motivation
  2. JSX
  3. Component
    1. Properties of the component
    2. Control of component status
    3. Control of the context of the component
  4. Lifecycle
    1. onCreate
    2. onCreated
    3. onRemove
    4. onRemoved
    5. onUpdate
    6. onUpdated
  5. Hooks
    1. useState
    2. useEffect
    3. useReducer
    4. useContext
    5. useMemo
  6. Special properties
    1. key
    2. scoped
    3. context
  7. createContext
  8. Examples
  9. Utils

Motivation

Simplify the creation and maintenance of components, limiting its scope only functions, avoiding the use of classes, with the aim of simplifying the learning curve centered only on the use of functions, life cycle associated with nodes, hooks and Jsx.

Another motivation is the use of shadow-dom, as part of the process of detecting changes. Example of this is the creation of a component with style scope thanks to the use of shadow-dom, please see the following example and note the definition of the property scoped.

function Button(props){
    return <div scoped>
        <style>{`
            :host{
                padding : .5rem 1rem;
                border:none;
                background:black;
                color:white
            }
        `}</style>   
        {props.children}
    </div>
}

The <Button/> component will be isolated in the Dom tree, this will define a closed scope of css styles.

JSX

JSX is defined as an extension of the JavaScript syntax, this allows to maintain a readable union between HTML and JS, and then be used for example in the manipulation of nodes, assignment of events, mutation of attributes and more.

When working with Orby, please consider the following differences with other libraries, such as React, in:

Without fragment support, Orby's components are more attached to the definition of a tree always maintaining a root node, this is how it is expressed in the Lifecycle.

Component

The functional Orbison components and you can manipulate the state of the nodes either through the Lifecycle associated with the virtual-dom or through the use of hooks.

Properties of the component

Like any functional component, the first argument of the component will always be its properties.

export function	Button(props){
    return <button onclick={props.click}>{props.children}</button>
}

The design pattern of purely functional components does not change if you were only limited to the use of Props.

Control of the context of the component

The context allows you to share a defined object at a higher level, it will be very useful if you look for interaction between 2 components.

export function	Button(props,context){
    return <button>{context.message}</button>
}

Another important point is that context management can be defined by using the context property external to the component.

import {h,render} from "@orby/core";
import App from "./app";

render(
    <App context={{message:"hi! Orby"}}/>,
    document.querySelector("#app")
);

Lifecycle

The life cycle manifests itself on the virtual-dom in the creation, updating and elimination of the nodes, this is similar to how it operates in Hyperapp.

export function Button(){
    return <button onCreate={handlerWithCreate}>Hi! Orby</button>
}

The DIFF process will invoke the onCreate properties only when the <button/>node is created in the dom tree. You can add the life cycle properties to the nodes you deem convenient.

onCreate

The onCreate property is invoked when the node is added in the dom tree.

export function Button(){
    return <button onCreate={(target:HTMLElement)=>{
    	/**algorithm**/
	}}>Hi! Orby</button>
}

onCreated

The onCreated property is invoked after the node was added to the dom tree and propagated the changes to its children.

export function Button(){
    return <button onCreated={(target:HTMLElement)=>{
    	/**algorithm**/
	}}>Hi! Orby</button>
}

onRemove

The onRemove property is invoked when removing the node from the dom tree.

export function Button(){
    return <button onRemove={(target:HTMLElement)=>{
    	/**algorithm**/
	}}>Hi! Orby</button>
}

onRemoved

The onRemoved property is invoked after removing the node from the dom tree and propagating the changes to its children.

export function Button(){
    return <button onRemoved={(target:HTMLElement)=>{
    	/**algorithm**/
	}}>Hi! Orby</button>
}

onUpdate

The onUpdate property is invoked before propagating from the node of the dom tree. returnfalse to avoid such propagation

export function Button(){
    return <button onUpdate={(target:HTMLElement, prevProps:Object, nextProps:Object)=>{
    	/**algorithm**/
	}}>Hi! Orby</button>
}

onUpdated

The onUpdated property is invoked after propagating from the node of the dom tree.

export function Button(){
    return <button onUpdated={(target:HTMLElement)=>{
    	/**algorithm**/
	}}>Hi! Orby</button>
}

Hooks

Hooks are a powerful way to extend the behavior of a functional component created with Orby, this is a small implementation based on the React Hooks, consider also knowing the benefits of this pattern and rules associated with the use of Hooks

¿Why hooks?

Hooks are a powerful way to separate logic from the functional component, you can create custom effects that are linked to the component only with the invocation, it is such a link that these effects manage to control the state of the component without the need to know the same component.

useState

It allows using a state and associating it with the component, by default the components in Orby do not have status since they are functions, if you require a component that can manipulate changes based on a state you can use useState within the component as many times as you deem appropriate. useState append the status control only when it is invoked within the component

Unlike useState of React, this returns in the array a 3 argument, this one has the purpose of obtaining the state in asynchronous behaviors, its use is optional.

import {h,useState} from "@orby/core";
export function Button(){
    let [state,useState] = useState();
}

Note that useState returns an array, which you can use with Destructuring assignment to associate A variable, useState also supports a first argument that defines the initial state.

import {h,useState} from "@orby/core";

export function Button(){
    let [count,setCount] = useState(0);
}

if this first argument is a function, it is executed only when initializing the state of the component.

import {h,useState} from "@orby/core";
function createState(){
    return {data:[]};
}
export function Button(){
    let [state,useState] = useState(createState);
}

useEffect

It allows the execution of a function so many times the component is executed, this function is executed after the rendering process associated with patching the changes of the node.

It is easier to understand the execution of useEffect by associating it with the life cycle methods of virtual-dom onCreated and onUpdated and onRemove.

import {h,useEffect} from "@orby/core";

export function Button(){
    const [count, setCount] = useState(0);
    useEffect(()=>{
       document.title = `clicked ${count}`;
    });
    return <button onClick={()=>setCount(count+1)}>increment</button>;
}

If you try to assimilate the execution of the event onRemove of the virtual-dom within useEffect, the function associated with useEffect must return a function.

export function Button(props,context){
 	const [count, setCount] = useState(0);
    useEffect(()=>{
       document.title = `clicked ${count}`;
        return ()=>{
            document.title = `component remove`;
        }
    });
    return <button onClick={()=>setCount(count+1)}>increment</button>;   
}

useEffect also receives a second argument, this gives the ability to limit the execution of the effect only to the changes associated with the second argument. The following example shows how to limit the execution of the effect only to a first instance.

export function Button(props,context){
 	useEffect(()=>{
       console.log("component created")
        return ()=>{
            console.log("component remove")
        }
    },[true]);
    return <button onClick={()=>setCount(count+1)}>increment</button>;   
}

useReducer

small implementation use React

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'reset':
      return {count: action.payload};
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      // A reducer must always return a valid state.
      // Alternatively you can throw an error if an invalid action is dispatched.
      return state;
  }
}

function Counter({initialCount}) {
  const [state, dispatch] = useReducer(
    reducer,
    initialState,
    {type: 'reset', payload: initialCount},
  );

  return (
    <div>
      Count: {state.count}
      <button
        onClick={() => dispatch({type: 'reset', payload: initialCount})}>
        Reset
      </button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </div>
  );
}

useContext

It allows to recover the context of the component, unlike React's useContext, it returns the whole context if it does not have an argument.


const context = useContext(Context);

Context is the return of the createContext instance, this homologous behavior of React.createContext.

useMemo

allows to memorize the return of a callback, each time the second argument changes.

const list = useMemo(()=>{
    let list =[];
    for(let i=0;i<1000;i++){
        list.push(i);
    }
    return list;
},[1000]);

this function is executed in second instance only if the values given in the second argument of useMemo are disintos to the previous one.

Special properties

key

It allows to define the identifier on the virtual-dom, to link it to a previous state, regardless of its order. The use of keys allows for example:

  1. Maintain an associative state of virtual-dom and a node indifferent to its order.
  2. Reduce the amount of manipulations associated with sun.

scoped

the scoped property allows to enable the use of shadow-dom on the node, when defining scoped as true, the DIFF process will understand that the nodes will be mounted in the shadowRoot of the node.

export function Button(props){
    return <div scoped>
        <style>{`:host{background:crimson}`}</style>	
        {props.children}
    </div>
}

context

The context property allows you to add new properties to the context.

<ParentComponent context={{title:"Hi! Orby"}}>
    <ChildComponent></ChildComponent>
</ParentComponent>

The example component ChildComponent can make use of the context defined in a superior way. Note that it is not necessary to enter the component to create contexts.

createContext

This function allows you to create contexts that already reserve a namespace.

Default contexts in Orby

Orby by default allows to generate contexts in a simple way but this forces the child node to know the name of the property to access it and this can generate conflict.

import {h,render} from "@orby/core";

function Title(props,context){
    return <h1>{context.myTitleContext}</h1>
}

render(
    <Title context={{myTitleContext:"hello"}}/>,
    document.body
)

context with createContext

Through createContext, you ensure that the name of the property is stored only within the createContext instance, reducing the possibility of name conflict.

import {h, createContext} from "@orby/core";

let Context = createContext({title:"hello"});

function Title(props,context){
    return <h1>
        <Context.Consumer>
            {(data)=>data.title}
        </Context.Consumer>
    </h1>
}

render(
    <Context.Provider>
        <Title/>
    </Context.Provider>,
    document.body
)

consume context with useContext

By giving useContext the context instance this returns the value of the property associated with the reservation and name of the context

import {h,useContext,createContext} from "@orby/core";

let Context = createContext({title:"hello"});

function Title(props,context){
    let data = useContext(Context);
    return <h1>
        {data.title}
    </h1>
}

render(
    <Context.Provider>
        <Title/>
    </Context.Provider>,
    document.body
)

Examples

| Title | Description | link | |---------|------------------------------|------------------------------------------------| | Counter | shows the use of useState | 🔗 link | | Counter with Reducer | shows the use of useState| 🔗 link | | Hooks Router | show how to use useRouter and useRedirect| 🔗 link |

Utilities

| Title | Description | Repo | |---------|-----------------------------------------------------|------------------------------------------------| | Router | Manage your routes in a simple and declarative way | 🔗 link |