frameworks
This commit is contained in:
commit
02e1011284
2 changed files with 767 additions and 0 deletions
639
framework.js
Normal file
639
framework.js
Normal file
|
@ -0,0 +1,639 @@
|
||||||
|
/**
|
||||||
|
* @class Represents a dynamic attribute or element
|
||||||
|
*/
|
||||||
|
class Dynamic {
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {() => any} callback
|
||||||
|
*/
|
||||||
|
constructor(callback) {
|
||||||
|
this.callback = callback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Represents a variable state
|
||||||
|
*/
|
||||||
|
class State {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {any} defaultValue
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
constructor(defaultValue = undefined) {
|
||||||
|
/**
|
||||||
|
* @type {any}
|
||||||
|
* @public
|
||||||
|
* The value of this state
|
||||||
|
*/
|
||||||
|
this.value = defaultValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Renderable[]}
|
||||||
|
* @protected
|
||||||
|
* The renderable linked to this state
|
||||||
|
*/
|
||||||
|
this.renderables = []
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Renderable} renderable
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
addRenderable(renderable) {
|
||||||
|
this.renderables.push(renderable)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the value of the state
|
||||||
|
* @param {any} newValue
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
update(newValue) {
|
||||||
|
this.value = newValue
|
||||||
|
for (const renderable of this.renderables) {
|
||||||
|
renderable.render()
|
||||||
|
renderable.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {String}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
toString() {
|
||||||
|
return this.value.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Represents a rendererable component or html element
|
||||||
|
*/
|
||||||
|
class Renderable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {Renderable[]} children
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
constructor(children) {
|
||||||
|
|
||||||
|
if (!children)
|
||||||
|
children = []
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent renderable of this renderable
|
||||||
|
* @type {HTMLElement | DocumentFragment}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.parentRenderable = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The element that is currently in the dom
|
||||||
|
* @type {HTMLElement | DocumentFragment}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.domElement = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The element from the most recent render
|
||||||
|
* @type {HTMLElement | DocumentFragment}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.renderedElement = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The elements children
|
||||||
|
* @type {Renderable[]}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.children = children
|
||||||
|
|
||||||
|
for (const child of this.children) {
|
||||||
|
if (child instanceof App) {
|
||||||
|
throw new Error('App must be at root of component tree')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
/* Render all children */
|
||||||
|
for (const child of this.children) {
|
||||||
|
child.render()
|
||||||
|
child.parentRenderable = this
|
||||||
|
child.domElement = child.renderedElement
|
||||||
|
this.renderedElement.appendChild(child.renderedElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
this.domElement.replaceWith(this.renderedElement)
|
||||||
|
this.domElement = this.renderedElement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Representsa HTML Element
|
||||||
|
*/
|
||||||
|
class Element extends Renderable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @protected
|
||||||
|
* @param {String} type
|
||||||
|
* @param {any} attrs
|
||||||
|
* @param {Renderable[]} children
|
||||||
|
*/
|
||||||
|
constructor(type, attrs, children) {
|
||||||
|
|
||||||
|
// call parent constructor
|
||||||
|
super(children)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The element type
|
||||||
|
* @type {String}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.type = type
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The element attributes
|
||||||
|
* @type {any}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.attrs = attrs
|
||||||
|
|
||||||
|
if (this.attrs['signals']) {
|
||||||
|
for (const signal of this.attrs['signals']) {
|
||||||
|
signal.addRenderable(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
|
||||||
|
let el;
|
||||||
|
|
||||||
|
if (this.type == 'path' || this.type == 'g' || this.type == 'svg') {
|
||||||
|
let svgns = "http://www.w3.org/2000/svg";
|
||||||
|
el = document.createElementNS(svgns, this.type);
|
||||||
|
} else {
|
||||||
|
el = document.createElement(this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in this.attrs) {
|
||||||
|
|
||||||
|
let val = this.attrs[key]
|
||||||
|
|
||||||
|
if (key == 'signals') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val instanceof Dynamic)
|
||||||
|
val = val.callback()
|
||||||
|
|
||||||
|
if (key.startsWith("on")) {
|
||||||
|
el[key] = val
|
||||||
|
} else {
|
||||||
|
el.setAttribute(key, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.renderedElement = el
|
||||||
|
|
||||||
|
super.render()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Represents raw content to be added to HTML
|
||||||
|
*/
|
||||||
|
class Content extends Renderable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {() => any} callback
|
||||||
|
* @param {State[]} states
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
constructor(callback, states) {
|
||||||
|
|
||||||
|
super([])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {() => any}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.callback = callback
|
||||||
|
|
||||||
|
for (const state of states) {
|
||||||
|
state.addRenderable(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
this.renderedElement = document
|
||||||
|
.createRange()
|
||||||
|
.createContextualFragment(this.callback())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
this.parentRenderable.render()
|
||||||
|
this.parentRenderable.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectableRenderable extends Renderable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
constructor () {
|
||||||
|
super([])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Renderable}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.selectedElement = null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
this.selectedElement.render()
|
||||||
|
this.renderedElement = this.selectedElement.renderedElement
|
||||||
|
this.selectedElement.parentRenderable = this.parentRenderable
|
||||||
|
super.render()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var routerCallbacks = []
|
||||||
|
export var routeSignal = state(document.location.pathname.toString())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Represends a page router
|
||||||
|
*/
|
||||||
|
class Router extends SelectableRenderable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {(string) => Renderable} callback
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
constructor (callback) {
|
||||||
|
|
||||||
|
super()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {(string) => Renderable}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.callback = callback
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.location = document.location.pathname.toString()
|
||||||
|
|
||||||
|
routerCallbacks.push(() => {
|
||||||
|
this.location = document.location.pathname.toString()
|
||||||
|
this.render()
|
||||||
|
this.update()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
super.selectedElement = this.callback(this.location.toString())
|
||||||
|
super.render()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Represends a component switch
|
||||||
|
*/
|
||||||
|
class Conditional extends SelectableRenderable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {() => any} conditional
|
||||||
|
* @param {{[key: any]: Renderable}} cases
|
||||||
|
* @param {State[]} states
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
constructor (conditional, cases, states) {
|
||||||
|
|
||||||
|
super()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.conditional = conditional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.cases = cases
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.states = states
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
let value = this.conditional()
|
||||||
|
|
||||||
|
this.renderedElement = null
|
||||||
|
|
||||||
|
for (const [key, element] of Object.entries(this.routes)) {
|
||||||
|
if (key === value) {
|
||||||
|
super.selectedElement = element
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.render()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class App extends Renderable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {Renderable} container
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
constructor(container) {
|
||||||
|
super([])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Renderable}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.container = container
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the app into the DOM
|
||||||
|
* @param {HTMLElement} parent - the parent element to place the app
|
||||||
|
* @public
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
render(parent) {
|
||||||
|
|
||||||
|
this.container.render()
|
||||||
|
this.container.parentRenderable = parent
|
||||||
|
|
||||||
|
if (this.container.domElement)
|
||||||
|
this.container.domElement.remove()
|
||||||
|
|
||||||
|
this.container.domElement = this.container.renderedElement
|
||||||
|
|
||||||
|
parent.appendChild(this.container.domElement)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
update() { /* empty */ }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {App}
|
||||||
|
* @param {Renderable} container
|
||||||
|
*/
|
||||||
|
export function app(container) {
|
||||||
|
return new App(container)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Dynamic}
|
||||||
|
* @param {() => any} callback
|
||||||
|
*/
|
||||||
|
export function dynamic(callback) {
|
||||||
|
return new Dynamic(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {State}
|
||||||
|
* @param {any} defaultValue
|
||||||
|
*/
|
||||||
|
export function state(defaultValue) {
|
||||||
|
return new State(defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {() => string} callback
|
||||||
|
* @param {...State} states
|
||||||
|
* @returns {Content}
|
||||||
|
*/
|
||||||
|
export function content(callback, ...states) {
|
||||||
|
return new Content(callback, states)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {(string) => Renderable} callback
|
||||||
|
* @returns {Router}
|
||||||
|
*/
|
||||||
|
export function router(callback) {
|
||||||
|
return new Router(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {() => any} conditional
|
||||||
|
* @param {{[key: any]: Renderable}} cases
|
||||||
|
* @param {...State} states
|
||||||
|
* @returns {Conditional}
|
||||||
|
*/
|
||||||
|
export function conditional(conditional, cases, ...states) {
|
||||||
|
return new Conditional(conditional, cases, states)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function backLocation() {
|
||||||
|
window.history.back()
|
||||||
|
routeSignal.update(document.location.pathname.toString())
|
||||||
|
for (const callback of routerCallbacks)
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function forwardLocation() {
|
||||||
|
window.history.forward()
|
||||||
|
routeSignal.update(document.location.pathname.toString())
|
||||||
|
for (const callback of routerCallbacks)
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function pushLocation(newLocation) {
|
||||||
|
window.history.pushState({}, '', newLocation)
|
||||||
|
routeSignal.update(document.location.pathname.toString())
|
||||||
|
for (const callback of routerCallbacks)
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function replaceLocation(newLocation) {
|
||||||
|
window.history.replaceState({}, '', newLocation)
|
||||||
|
routeSignal.update(document.location.pathname.toString())
|
||||||
|
for (const callback of routerCallbacks)
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML paragraph
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function p(attrs, ...children) {
|
||||||
|
return new Element("p", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML span
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function span(attrs, ...children) {
|
||||||
|
return new Element("span", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML div
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function div(attrs, ...children) {
|
||||||
|
return new Element("div", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML anchor
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function a(attrs, ...children) {
|
||||||
|
return new Element("a", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML icon
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function i(attrs, ...children) {
|
||||||
|
return new Element("i", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML form
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function form(attrs, ...children) {
|
||||||
|
return new Element("form", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML img
|
||||||
|
* @param {String} alt - the alt tag
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function img(alt, attrs, children) {
|
||||||
|
attrs['onerror'] = (event) => event.target.remove()
|
||||||
|
attrs['alt'] = alt
|
||||||
|
return new Element("img", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML input
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function input(attrs, ...children) {
|
||||||
|
return new Element("input", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML button
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function button(attrs, ...children) {
|
||||||
|
return new Element("button", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML path
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function path(attrs, ...children) {
|
||||||
|
return new Element("path", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML g tah
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function g(attrs, ...children) {
|
||||||
|
return new Element("g", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML svg
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function svg(attrs, ...children) {
|
||||||
|
return new Element("svg", attrs, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HTML text area
|
||||||
|
* @param {{[key: string]: any}} attrs - a map of the HTML attributes
|
||||||
|
* @param {Renderable[]} children - the elements children
|
||||||
|
*/
|
||||||
|
export function textarea(attrs, ...children) {
|
||||||
|
return new Element("textarea", attrs, children)
|
||||||
|
}
|
128
readme.md
Normal file
128
readme.md
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
## framework
|
||||||
|
another js framework
|
||||||
|
|
||||||
|
### components
|
||||||
|
|
||||||
|
there are 5 major components for this framework
|
||||||
|
|
||||||
|
#### element
|
||||||
|
|
||||||
|
The most basic component. An `element` represends any HTMLElement.
|
||||||
|
These can be created with any of the functions named after their html functions, i.e. `a`, `div`, `textarea`, etc. Elements can hold other elements, contents, and routers as children.
|
||||||
|
|
||||||
|
To make a component, (most) require 2 paramaters. First, its attributes, and second its children.
|
||||||
|
|
||||||
|
```js
|
||||||
|
# Usage
|
||||||
|
# element(attrs, ...children)
|
||||||
|
|
||||||
|
div({
|
||||||
|
style: 'background-color: red;'
|
||||||
|
},
|
||||||
|
a({ href: 'google.com'})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### content
|
||||||
|
|
||||||
|
The content type is how you add dynamic strings and insert content into the dom.
|
||||||
|
You cannot just add text as a child directly to any element, it must be wrapped in a
|
||||||
|
content tag.
|
||||||
|
|
||||||
|
The content tag tags a single callback that returns a string. Its called on every render.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Usage
|
||||||
|
// content(callback, ...states)
|
||||||
|
|
||||||
|
content(() => 'Hello world!')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### state
|
||||||
|
|
||||||
|
State is how you create signals and store variables a reactive way. When a state object is updated,
|
||||||
|
it causes every content and element its attached to, to update.
|
||||||
|
|
||||||
|
It takes one argument, the default value of the state;
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Usage
|
||||||
|
// state(defaultValue)
|
||||||
|
|
||||||
|
let test = state('test')
|
||||||
|
test.value // get value
|
||||||
|
test.update('test2') // update value
|
||||||
|
```
|
||||||
|
|
||||||
|
Also you need to attach the state object to any element or content that uses it. Otherwise they wont update when changed. To do this add them to the `signals` attribute on any `element`, or pass them in after the callback in any `content`.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Usage
|
||||||
|
|
||||||
|
content(() => `${test.value}`, test);
|
||||||
|
|
||||||
|
// or
|
||||||
|
|
||||||
|
div({
|
||||||
|
signals: [test],
|
||||||
|
style: `background-color: ${test.value}`
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### router
|
||||||
|
|
||||||
|
The router is what allows you to switch between pages reactivly based on the location.
|
||||||
|
|
||||||
|
To change location use the following functions
|
||||||
|
|
||||||
|
```js
|
||||||
|
backLocation() // go back
|
||||||
|
forwardLocation() // go forward
|
||||||
|
|
||||||
|
pushLocation('/newPath') // append location to history, and goto newPath
|
||||||
|
replaceLocation('/newPath') // replace location in history, and goto newPath
|
||||||
|
```
|
||||||
|
|
||||||
|
To create a router you must pass in a callback that takes in the current location, and returns either a element, content, or another router. Routers will auto update on location change.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Usage
|
||||||
|
// router(callback)
|
||||||
|
|
||||||
|
const component() => {
|
||||||
|
return div({}, content(() => 'hello world!'))
|
||||||
|
}
|
||||||
|
|
||||||
|
const notFound() => {
|
||||||
|
return div({}, content(() => 'not found :('))
|
||||||
|
}
|
||||||
|
|
||||||
|
router((path) => {
|
||||||
|
switch(path) {
|
||||||
|
case: '/secret':
|
||||||
|
return component()
|
||||||
|
default:
|
||||||
|
retrun notFound()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### app
|
||||||
|
|
||||||
|
The final type is the App. This is the highest component in the component tree, and requires a signle router, element, or content to manage at the top of the tree.
|
||||||
|
|
||||||
|
You are only allowed to make a single app, since they arent gurenteed to work with multiple.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Usage
|
||||||
|
// app(root)
|
||||||
|
|
||||||
|
let mySite = app(router((path) => { /* ... */ }))
|
||||||
|
mySite.render(document.body)
|
||||||
|
```
|
||||||
|
|
||||||
|
### todo
|
||||||
|
|
||||||
|
- page titles
|
||||||
|
- component arrays
|
||||||
|
- likly other things
|
Loading…
Reference in a new issue