Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jahilldev/hypnode
Generate HTML node trees from JSX or direct function calls
https://github.com/jahilldev/hypnode
architecture components es6 javascript jsx lightweight micro-framework react-alternative server-side-rendering typescript webcomponents
Last synced: 2 months ago
JSON representation
Generate HTML node trees from JSX or direct function calls
- Host: GitHub
- URL: https://github.com/jahilldev/hypnode
- Owner: jahilldev
- Created: 2019-11-29T13:39:57.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T13:47:04.000Z (almost 2 years ago)
- Last Synced: 2024-10-06T11:59:02.503Z (3 months ago)
- Topics: architecture, components, es6, javascript, jsx, lightweight, micro-framework, react-alternative, server-side-rendering, typescript, webcomponents
- Language: TypeScript
- Size: 1.31 MB
- Stars: 6
- Watchers: 2
- Forks: 0
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
A super fast, lightweight (roughly **1kb** gzipped) and reactive series of utility functions, used to build HTML node trees and stateful functional components. Can be used either directly via the `h` function, or from transpiled `JSX`.
Due to it's size, `hypnode` is a useful companion utility for writing _WebComponents_, simplifying `HTML` structures, element references and state management. See section entitled "WebComponents" for an example, [click to jump there](#webcomponents).
# Getting Started
To install `hypnode`, you can use one of the following in your project:
`yarn add hypnode` or `npm install hypnode`
`hypode` can be used in one of two ways, either as a target for `JSX` transpilation, or directly using the exposed `h` function. It's exported as ES6, so if you need to support older environments, you'll need to transpile down to ES5 in your build tasks.
The `h` function can be imported in one of the following ways:
```javascript
import { h } from 'hypnode';
``````javascript
const { h } = require('hypnode');
```# Direct Usage
Once imported, use the function to generate your tree of DOM Nodes. The function takes 3 arguments, the last two of which are optional:
```
h([type]: string | Function, [attributes]?: object, [children]?: array[]);
```## Simple Example
The code below:
```javascript
import { h, render } from 'hypnode';/*[...]*/
const result = render(
h('div', { title: 'A DIV!' }, [
h('h1', { class: 'title' }, 'Hypnode'),
h('p', { id: 'text'}, 'My text value'),
)
);console.log(result.outerHTML);
```Will produce the following:
```html
Hypnode
My text value
```# JSX Elements
`hypnode` can be used with `JSX` to provide a more familiar API when building DOM structures. This will need a transpilation step, see below for examples.
## TypeScript
Transpilation of `JSX` is provided out of the box by custom factories (TypeScript 1.8+), to apply this, add the following to your `tsconfig.json` file:
```json
"compilerOptions": {
"jsx": "react",
"jsxFactory": "h",
/*[...]*/
}
```This tells the TypeScript compiler to convert all `JSX` elements into function calls, in this case using our exported `h` function. You'll still need to import the `h` function in every file where you're using `JSX`.
To apply the correct types, all files that contain `JSX` must have the extension `.tsx`.
## Simple Example
The code below:
```javascript
import { h, render } from 'hypnode';/*[...]*/
const root = document.getElementId('root');
const result = render(
);root.appendChild(result);
```Will produce the following:
```html
```# Rendering
As the `render()` function exported by `hypnode` returns a fully formed `HTMLElement`, you can handle it's output easily using native `DOM` API's like `root.appendChild` or `root.replaceChild`. There is, however, an optional secondary argument that can handle this for you, e.g:
```javascript
const result = h('div', { class: 'wrapper' }, 'Lorem ipsum');/*[...]*/
render(result, document.getElementById('root'));
```or, with `JSX`:
```javascript
const result =Lorem ipsum;/*[...]*/
render(result, document.getElementById('root'));
```# Event Binding
`hypnode` provides a set of properties for you to apply DOM events. All native events are supported, formatted in camelCase and prefixed with `on`. For example:
```javascript
h('a', { onClick: (ev) => console.log(ev) }, 'Click Here');
```or, with `JSX`:
```javascript
console.log(ev)} />
```# Element References
If you need access to a particular node in your tree, use the `ref` property. For example:
```javascript
let myElement;/*[...]*/
h('div', { id: 'container' }, [
h('p', { ref: (el) => (myElement = el) }, 'Lorem ipsum dolor sit amet, consectetur'),
]);
```or with `JSX`:
```javascript
let myElement;/*[...]*/
;
```# Components
`hypnode` can be used to create re-usable, functional components, below is a simple example:
```javascript
import { h, render } from 'hypnode';/*[...]*/
function Button({ className = '', children }) {
return h('a', { class: `button ${className}` }, children);
}/*[...]*/
const button = h(Button, { className: 'big' }, buttonText));
render(button, document.getElementById('root'))
```or with `JSX`:
```javascript
import { h, render } from 'hypnode';/*[...]*/
function Button({ className = '', children }) {
return {children};
}/*[...]*/
const button = Click here;
render(button, document.getElementById('root'));
```## WebComponents
Creating and managing complex HTML structures using _WebComponents_ can become tricky as their size increases. `hypnode` simplifies this by incorporating a familiar component and state pattern into your custom elements. You can find more info on _WebComponents_ [here](https://www.webcomponents.org/introduction). As `hypnode` is fast and lightweight, _WebComponents_ can be more easily shared between projects without significant dependency overhead.
A quick example can be found below:
```javascript
// myComponent.tsx (TypeScript + JSX)import { h, render, useState, State } from 'hypnode';
/*[...]*/
class MyComponent extends HTMLElement {
private state: State;public connectedCallback() {
const Button = () => this.renderButton();this.appendChild(render());
}private renderButton = () => {
const [counter] = (this.state = useState(0));return (
Counter: {counter}
Click Here
);
}private onClick = (ev: Event) => {
const [counter, setState] = this.state;setState(counter + 1);
}
}
```# State
`hypnode` exposes a simple, declarative hook to provide state into your functional application.
First, you'll need to import the hook function:
```javascript
import { h, useState } from 'hypnode';
```Once imported, you can initialize a state registry in your components by doing the following:
```javascript
const [state, setState] = useState(([value]: any));
```The `useState` function takes a single argument, the initial value you wish to assign to the state. This can be anything, a primitive or something more complex like an object. For example:
```javascript
function Button({ buttonText }) {
const [state, setState] = useState(10);return h('button', { onClick: () => setState(state + 1) }, `${buttonText}: ${state}`);
}
```You provide mutations to your state via the `setState` function, this accepts a _new_ value you wish to assign. Whenever this function is called, the component will be re-rendered with the replaced state value.
# Effects
`hypnode` exports a simple effect hook, `useEffect`. This takes a callback as it's only argument which will be called on "mount". You can optionally return another function from it that will be called on "un-mount". The lifecycle of this function works in a similar way to React's hook by the same name.
See example below:
```javascript
import { h, useEffect } from 'hypnode';/*[...]*/
function Banner({ children }) {
useEffect(() => {
console.log('onMount');return () => console.log('onUnMount (optional)');
});return h('div', { class: 'banner' }, children);
}
```# Server Side Rendering
`hypnode` provides a Virtual `DOM` representation for server side rendering (universal rendering). You can use this output to generate a complete `HTML` representation of your app. A prebuilt utility that can convert this into an `HTML` string can be found here: [`hypnode-server`](https://github.com/jhdevuk/hypnode-server)
# TypeScript
This utility was created with TypeScript and comes pre-bundled with a definition file.