Comparing version 2.4.1 to 2.4.2
{ | ||
"name": "literaljs", | ||
"version": "2.4.1", | ||
"version": "2.4.2", | ||
"description": "~1kb JavaScript library for building user interfaces.", | ||
@@ -5,0 +5,0 @@ "main": "build/index.js", |
460
README.md
@@ -0,5 +1,12 @@ | ||
<p align="center"> | ||
<img src="literalJS.png" alt="LiteralJS Logo"> | ||
</p> | ||
--- | ||
# LiteralJS | ||
### ~1kb JavaScript library for building user interfaces. | ||
### Links | ||
- **Documentation**: https://literaljs.com | ||
```js | ||
@@ -20,452 +27,1 @@ $ microbundle | ||
- **One Global Store**: One source of truth which makes other state management libraries less of a need. | ||
### Documentation Index | ||
- [Features](#features) | ||
- [Getting Started](#getting-started) | ||
- [Install LiteralJS](#install) | ||
- [How to use JSX in LiteralJS?](#using-jsx) | ||
- [JSX Markup Syntax](#jsx-markup-syntax) | ||
- [Object Markup Syntax](#object-markup-syntax) | ||
- [Lifecycle Events](#lifecycle-events) | ||
#### API Functions | ||
- [component](#component) | ||
- [props](#component-props) | ||
- [methods](#component-methods) | ||
- [getState](#methods-getState) | ||
- [setState](#methods-setState) | ||
- [render](#component-render) | ||
- [state](#state) | ||
- [getState](#getstate) | ||
- [setState](#setstate) | ||
- [props](#props) | ||
- [methods](#methods) | ||
- [render](#render) | ||
- [h](#h) | ||
## [Getting Started](#getting-started) | ||
The easiest way of getting started is by cloning the LiteralJS starter application located here: | ||
- [LiteralJS Starter Application](https://github.com/Mikeysax/LiteralJS-Starter) | ||
Once you clone the project, you `cd` to the directory and run the following commands: | ||
```js | ||
$ npm install | ||
$ npm run dev | ||
// OR | ||
$ yarn | ||
$ yarn dev | ||
``` | ||
This command is setup to launch a browser window and you should see a landing page. The project is also partially setup to deploy to Netlify if you want. Just make sure to use the `build-netlify` command in the Netlify dashboard and set the deploy folder to `dist`. | ||
#### [Install](#install) | ||
``` | ||
$ npm install literaljs | ||
``` | ||
``` | ||
$ yarn add literaljs | ||
``` | ||
### Import | ||
```js | ||
const Literal = require('literaljs'); | ||
// OR | ||
import Literal from 'literaljs'; | ||
// OR | ||
import { component, render, h } from 'literaljs'; | ||
``` | ||
### ES6 Examples | ||
You can use 3 types of markup in the render! | ||
#### JSX | ||
- [How to use JSX in LiteralJS?](#using-jsx) | ||
```jsx | ||
const Foo = component({ | ||
render: ({ state, getState, setState }) => ( | ||
<div class='container'> | ||
This is the Count: {state.count} | ||
<button events={{ click: () => setState({ count: getState().count + 1 }) }}> | ||
Click Me! | ||
</button> | ||
</div> | ||
) | ||
}); | ||
render(foo, 'app', { count: 0 }); | ||
``` | ||
#### Hyper Script | ||
```js | ||
const Foo = component({ | ||
render: ({ state, getState, setState }) => | ||
h('div', { | ||
class: 'container', | ||
text: `This is the Count: ${state.count}` | ||
}, | ||
h('button', { | ||
events: { click: () => setState({ count: getState().count + 1 }) } | ||
}) | ||
); | ||
}); | ||
render(foo, 'app', { count: 0 }); | ||
``` | ||
#### Objects | ||
```js | ||
const Foo = component({ | ||
render: ({ state, getState, setState }) => ({ | ||
element: 'div', | ||
class: 'container', | ||
text: `This is the Count: ${state.count}`, | ||
children: [ | ||
{ | ||
element: 'button', | ||
text: 'Click Me!', | ||
events: { click: () => setState({ count: getState().count + 1 }) } | ||
} | ||
] | ||
}) | ||
}); | ||
render(foo, 'app', { count: 0 }); | ||
``` | ||
## component | ||
The `component` function accepts objects with the following keys: | ||
- [props](#component-props) | ||
- [methods](#component-methods) | ||
- [render](#component-render) | ||
### [component `props`](#component-props) | ||
The `props` of a `component` is an object which can be passed with anything that is normally valid in a JavaScript Object. This can include any data or functions. | ||
The only component that can not recieve `props` is the root component that is passed to the `Literal.render` function. | ||
**Example:** | ||
```jsx | ||
const Bar = component({ | ||
render: ({ props }) => ( | ||
<p>Total: {props.total}</p> | ||
) | ||
}); | ||
const Foo = component({ | ||
render: () => ( | ||
<div>{Bar({ total: 9 })}</div> | ||
) | ||
}); | ||
``` | ||
### [component `methods`](#component-methods) | ||
The `methods` key of a `component` will accept a function which returns an object of other functions. Within the `methods`, you also have access to a `component`s `getState` and `setState` functions which can be used accordingly. You also, have access to created methods directly within the `render` function. | ||
#### [getState](#methods-getState) | ||
`getState` is a function which is accessible as a property of the `methods` function. | ||
Using the `getState` function will pull the latest state objecty of your application. Once used, the specific state keys are accessible via dot notation. | ||
#### [setState](#methods-setState) | ||
`setState` is a function which is accessible as a property of the `methods` function. | ||
Using the `setState` function will cause the application state to update and diffing to occur. | ||
**Example:** | ||
```jsx | ||
component({ | ||
methods: ({ getState, setState }) => ({ | ||
increase: () => setState({ count: getState().count + 1 }) | ||
}), | ||
render: ({ state, methods: { increase }}) => ( | ||
<button events={{ click: increase }}> | ||
Current Count: {state.count} | ||
</button> | ||
) | ||
}); | ||
``` | ||
### [component `render`](#component-render) | ||
The `render` key of a `component` accepts a function that returns an JavaScript Object. | ||
- [Properties](#properties) | ||
#### [JSX Markup Syntax](#jsx-markup-syntax) | ||
JSX in LiteralJS has some differentiation when it comes to other implementations like JSX in React. | ||
The biggest differentiator in syntax from React JSX is that the `class` attribute is acceptable on JSX elements and `events` are passed as either an Array or Objects or a single Object. | ||
Event Objects need a key which is a DOM event name and function as a value. The events in LiteralJS are [explained here](#events). | ||
Anything can be considered acceptable as attributes and any keys that work with [LiteralJS Object Markup Syntax](#object-markup-syntax) also work in LiteralJS JSX markup. | ||
Example Of Single Event: | ||
```jsx | ||
component({ | ||
methods: ({ getState, setState }) => ({ | ||
increase: () => setState({ count: getState().count + 1 }) | ||
}), | ||
render: ({ state, methods: { increase }}) => ( | ||
<button events={{ click: () => increase() }}> | ||
Current Count: {state.count} | ||
</button> | ||
) | ||
}); | ||
``` | ||
Example Of Multiple Events: | ||
```jsx | ||
component({ | ||
methods: ({ getState, setState }) => ({ | ||
increase: () => setState({ count: getState().count + 1 }) | ||
}), | ||
render: ({ state, methods: { increase }}) => ( | ||
<button | ||
events={{ | ||
mounted: () => console.log('Button Mounted'), | ||
click: () => increase() | ||
}} | ||
> | ||
Current Count: {state.count} | ||
</button> | ||
) | ||
}); | ||
``` | ||
#### [Object Markup Syntax](#object-markup-syntax) | ||
Object Markup is currently written with Objects with the following specified keys or strings and more not listed: | ||
- [`element`](#element-key)* | ||
- [`text`](#text-key) | ||
- [`class`](#class-key) | ||
- [`id`](#id-key) | ||
- [`children`](#children-key) | ||
- [`events`](#events-key) | ||
- [`lifecycle events`](#lifecyle-events) | ||
\* = Required Key | ||
#### element Key | ||
The `element` key in the `render` function markup is the HTML node tag name as a `String`. For example, an `element` with the value | ||
The `element` key is **required** when generating a new DOM node. | ||
Example: | ||
```js | ||
component({ | ||
render: () => ({ | ||
element: 'div', | ||
}) | ||
}); | ||
// Outputs: <div></div> | ||
``` | ||
#### text Key | ||
The `text` key in the `render` function markup accepts a String an will generate a text inside the element. | ||
Example: | ||
```js | ||
component({ | ||
render: () => ({ | ||
element: 'div', | ||
text: 'Hello World!' | ||
}) | ||
}); | ||
// Outputs: <div>Hello World!</div> | ||
``` | ||
You can also include regular strings as children to create text nodes. | ||
Example: | ||
```js | ||
component({ | ||
render: () => ({ | ||
element: 'div', | ||
children: ['Hello World!'] | ||
}) | ||
}); | ||
// Outputs: <div>Hello World!</div> | ||
``` | ||
#### class Key | ||
The `class` key in the `render` function markup is the HTML node class name as a `String`. | ||
Example: | ||
```js | ||
component({ | ||
render: () => ({ | ||
element: 'div', | ||
class: 'title' | ||
}) | ||
}); | ||
// Outputs: <div class="title"></div> | ||
``` | ||
#### id Key | ||
The `id` key in the `render` function markup is the HTML node class name as a `String`. | ||
Example: | ||
```js | ||
component({ | ||
render: () => ({ | ||
element: 'div', | ||
id: '2' | ||
}) | ||
}); | ||
// Outputs: <div id="2"></div> | ||
``` | ||
#### children Key | ||
The `children` key in the `render` function markup represet the `childNodes` of a given `element` or DOM Node. This key only accepts an Array of Objects or Strings. Each Object or in this Array can be another Object that represents a new DOM Node. You can also use Strings to represet Text nodes. | ||
Example: | ||
```js | ||
component({ | ||
render: () => ({ | ||
element: 'div', | ||
children: [ | ||
'Count: ', | ||
{ | ||
element: 'span' | ||
text: '0' | ||
} | ||
] | ||
}) | ||
}); | ||
// Outputs: <div>Count: <span>0</span></div> | ||
``` | ||
#### [Events Key](#events) | ||
The `events` key in the `render` function markup accepts either an Object. | ||
An event object consists of the `key` of the event name and the `value` of a function to trigger: | ||
- Key: Event Name | ||
- Value: Function To Trigger | ||
Example: | ||
```js | ||
// An Array Of Events | ||
component({ | ||
render: () => ({ | ||
element: 'button', | ||
text: 'Click Me!', | ||
events: { click: () => console.log('Hello World!') } | ||
}) | ||
}); | ||
// Output in Console: Hello World! | ||
``` | ||
#### [Lifecycle Events](#lifecycle-events) | ||
Besides the common event handlers like `click`, there are two lifecycle events that `LiteralJS` includes that can be attached to any DOM node. | ||
To do so, just name the `type` value `unmounted`, `updated`, or `mounted` to trigger functions when a DOM node is first placed in the DOM or removed from the DOM. | ||
**Example:** | ||
Example: | ||
```js | ||
component({ | ||
render: () => ({ | ||
element: 'div', | ||
text: 'I have a life!', | ||
events: { | ||
mounted: () => console.log('I\'m on the page!'), | ||
updated: () => console.log('I\'m updated!'), | ||
unmounted: () => console.log('I\'m off the page!') | ||
} | ||
}) | ||
}); | ||
``` | ||
#### Other Keys Not Listed | ||
Other typical keys are also accepted in a DOM object, such as `data`, `href`, and other custom keys depending on the `element`. | ||
#### Properties | ||
Within the `render` function of a component, you have access to other functions and objects: | ||
- [state](#state) | ||
- [getState](#getstate) | ||
- [setState](#setstate) | ||
- [props](#props) | ||
- [methods](#methods) | ||
### `state` (Object) | ||
The `state` property is an Object of the current state and should only be used within markup and not functions or events. | ||
### `getState` (Function -> Object) | ||
The `getState` function of the `component`s `render` method will allow you to access the global store of your application within functions and events. | ||
### `setState` (Function) | ||
The `setState` function of the `component`s `render` method accepts an object which will allow you to set new values for particular pieces of state in the global store | ||
### `props` (Object) | ||
The `props` object of the `component`s `render method can contain any number of data types and functions. The only `component` that cannot contain `props` is the root `component` that is passed to the `Literal.render` method. | ||
### `methods` (Object -> Functions) | ||
The `methods` object allow you to access other functions defined directly in the `component`. You can use this as a way to organize other pieces of logic and keep the `render` function much cleaner. | ||
## render (Function) | ||
The `Literal.render` function is responsible for parsing the AST that is provided with `component`s, injecting the generated markup into the specific DOM node, diffing any new changes based on state, and setting the default application state. | ||
The `Literal.render` function can accept 3 arguments, one of which is optional. | ||
- The root `component`. | ||
- The String `id` of the DOM node to inject generated markup with. | ||
- (Optional) The default state as an Object. | ||
**Example:** | ||
```js | ||
Literal.render(component, 'app', { count: 0 }); | ||
// or | ||
render(component, 'app'); | ||
``` | ||
## h | ||
The `Literal.h` function will generate specific LiteralJS Object Syntax. | ||
### [Using JSX](#using-jsx) | ||
If you want to use JSX, you can import the `Literal.h` function and install the [JSX transform plugin](https://babeljs.io/docs/plugins/transform-react-jsx) and add the pragma option to your `.babelrc` file. | ||
In `.babelrc`: | ||
``` | ||
{ | ||
"plugins": [["transform-react-jsx", { "pragma": "h" }]] | ||
} | ||
``` | ||
Some text editors and linters might also require the following at the top of the file to recognize that the file is using JSX: | ||
```js | ||
/** @jsx h */ | ||
``` | ||
14
212141
27