Comparing version 0.3.8 to 0.4.0
# Changelog | ||
## 0.4.0 - 2019-02-16 | ||
- Rename API to create__ to be semantically correct | ||
- Added implicit event delegation | ||
## 0.3.8 - 2019-01-31 | ||
@@ -4,0 +8,0 @@ - Add support for HyperScript |
@@ -125,3 +125,3 @@ import S from 's-js'; | ||
function useState(state = {}) { | ||
function createState(state = {}) { | ||
state = unwrap(state); | ||
@@ -228,3 +228,3 @@ const wrappedState = wrap(state); | ||
function useSignal(value, comparator) { | ||
function createSignal(value, comparator) { | ||
const d = S.makeDataNode(value); | ||
@@ -248,5 +248,5 @@ let setter; | ||
function useMemo(fn, seed) { return S(fn, seed); } | ||
function createMemo(fn, seed) { return S(fn, seed); } | ||
function useEffect(fn, deps, defer) { | ||
function createEffect(fn, deps, defer) { | ||
if (!deps) return S.makeComputationNode(fn); | ||
@@ -256,26 +256,4 @@ S.on(deps, fn, undefined, defer); | ||
// export observable | ||
function observable(input) { | ||
if (Symbol.observable in input) return input[Symbol.observable](); | ||
return { | ||
subscribe(observer) { | ||
if (!(observer instanceof Object) || observer == null) { | ||
throw new TypeError('Expected the observer to be an object.'); | ||
} | ||
observer = observer.next || observer; | ||
let complete = false; | ||
S.on(input, function next() { | ||
if (complete) return; | ||
observer(input()); | ||
}); | ||
return { | ||
unsubscribe() { complete = true; } | ||
}; | ||
}, | ||
[Symbol.observable]() { return this; } | ||
}; | ||
} | ||
const { root: createRoot, cleanup: onCleanup, sample, freeze } = S; | ||
const { root, cleanup: useCleanup, sample, freeze } = S; | ||
export { root, useCleanup, sample, freeze, useState, unwrap, reconcile, useSignal, useMemo, useEffect, observable }; | ||
export { createRoot, onCleanup, sample, freeze, createState, unwrap, reconcile, createSignal, createMemo, createEffect }; |
# API | ||
### `root(disposer => <code>)` | ||
### `createRoot(disposer => <code>)` | ||
Creates a new non-tracked context that doesn't auto-dispose. All Solid code should be wrapped in one of these top level as they ensure that all memory/computations are freed up. | ||
### `useState(initValue): [state, setState]` | ||
### `createState(initValue): [state, setState]` | ||
Creates a new State object and setState pair that can be used to maintain your componenents state. | ||
### `useEffect(() => <code>, dependencies, defer)` | ||
### `createEffect(() => <code>, dependencies, defer)` | ||
Creates a new effect that automatically tracks dependencies. The 2nd optional argument is an explicit array of dependencies. The 3rd optional argument is whether to defer initial execution of the effect until a value has changed (this only works with explicit dependencies). | ||
### `useSignal(initialValue, comparatorFn): [getValueFn, setValueFn]` | ||
### `createSignal(initialValue, comparatorFn): [getValueFn, setValueFn]` | ||
Creates a new signal that can be used for reactive tracking. By default signals always notify on setting a value. However a comparator can be passed in to indicate whether the values should be considered equal and listeners not notified. | ||
### `useMemo(prev => <code>, initialValue): getValueFn` | ||
### `createMemo(prev => <code>, initialValue): getValueFn` | ||
Creates a readonly signal that recalculates it's value whenever the executed codes dependencies update. | ||
### `useCleanup(() => <code>)` | ||
### `onCleanup(() => <code>)` | ||
@@ -25,0 +25,0 @@ Registers a cleanup method that performs that executes on disposal or recalculation of the current context. |
@@ -18,3 +18,3 @@ # Rendering | ||
on_____ properties get added (addEventListener) as event handlers on the element. If the event handler has more than one argument, the second argument will be the model property or (nearest parent's). The 3rd will be a similarly attributed action property to different events of the same type (like 2 types of clicks). This is useful to automatically handle event delegation without any special syntax, methods, or synthetics. | ||
on_____ properties get added (addEventListener) as event handlers on the element. Camel Case events will be delegated by default and the second argument will be the model property or (nearest parent's). Use all lowercase for directly bound events. | ||
@@ -30,5 +30,5 @@ ## Control Flow | ||
<div>{( user.firstName )}</div> | ||
<$ when={ user.stars > 100 }>{ | ||
() => <div>Verified</div> | ||
}</$> | ||
<$ when={ user.stars > 100 }> | ||
<div>Verified</div> | ||
</$> | ||
</li> | ||
@@ -35,0 +35,0 @@ }</$> |
@@ -8,8 +8,8 @@ # Signals | ||
```js | ||
import { useSignal, useCleanup } from 'solid-js'; | ||
import { createSignal, onCleanup } from 'solid-js'; | ||
function useTick(delay) { | ||
const [getCount, setCount] = useSignal(0); | ||
const [getCount, setCount] = createSignal(0); | ||
handle = setInterval(() => setCount(getCount() + 1), delay); | ||
useCleanup(() => clearInterval(handle)); | ||
onCleanup(() => clearInterval(handle)); | ||
return getCount; | ||
@@ -30,7 +30,7 @@ } | ||
```js | ||
import { useState, useEffect } from 'solid-js'; | ||
import { createState, createEffect } from 'solid-js'; | ||
const [state, setState] = useState({count: 1}); | ||
const [state, setState] = createState({count: 1}); | ||
useEffect(() => console.log(state.count)); | ||
createEffect(() => console.log(state.count)); | ||
setState({count: state.count + 1}); | ||
@@ -55,7 +55,7 @@ | ||
// redux | ||
const [getAction, dispatch] = useSignal(), | ||
getStore = useMemo(state => reducer(state, getAction()), {list: []}); | ||
const [getAction, dispatch] = createSignal(), | ||
getStore = createMemo(state => reducer(state, getAction()), {list: []}); | ||
// subscribe and dispatch | ||
useEffect(() => console.log(getStore().list)); | ||
createEffect(() => console.log(getStore().list)); | ||
dispatch({type: 'LIST/ADD', payload: {id: 1, title: 'New Value'}}); | ||
@@ -70,6 +70,6 @@ ``` | ||
```jsx | ||
import { useSignal } from 'solid-js' | ||
import { createRoot, createSignal } from 'solid-js' | ||
root(() => { | ||
const [getSeconds, setSeconds] = useSignal(0); | ||
createRoot(() => { | ||
const [getSeconds, setSeconds] = createSignal(0); | ||
div = <div>Number of seconds elapsed: {( getSeconds() )}</div> | ||
@@ -89,5 +89,5 @@ | ||
const useReducer = (reducer, init) => { | ||
const [state, setState] = useState(init), | ||
[getAction, dispatch] = useSignal(); | ||
useEffect((prevState = init) => { | ||
const [state, setState] = createState(init), | ||
[getAction, dispatch] = createSignal(); | ||
createEffect((prevState = init) => { | ||
let action, next; | ||
@@ -98,3 +98,3 @@ if (!(action = getAction())) return prevState; | ||
return next; | ||
}) | ||
}, [ getAction ]) | ||
return [state, dispatch]; | ||
@@ -110,2 +110,2 @@ } | ||
Observables can work well with Signals as being a source that feeds data into them. Like State, Observables are another tool that allow more control in a specific aspect of your application. Where State is valuable for reconciling multiple Signals together into a serializable structure to keep managing Component or Storage code simple, Observables are useful for transforming Async data pipelines like handling Data Communication services. | ||
Observables can work well with Signals as being a source that feeds data into them. Like State, Observables are another tool that allow more control in a specific aspect of your application. Where State is valuable for reconciling multiple Signals together into a serializable structure to keep managing Component or Store code simple, Observables are useful for transforming Async data pipelines like handling Data Communication services. |
@@ -7,3 +7,3 @@ # State | ||
### useState(object) | ||
### createState(object) | ||
@@ -10,0 +10,0 @@ Initializes with object value and returns an array where the first index is the state object and the second is the setState method. |
@@ -131,3 +131,3 @@ 'use strict'; | ||
function useState(state = {}) { | ||
function createState(state = {}) { | ||
state = unwrap(state); | ||
@@ -234,3 +234,3 @@ const wrappedState = wrap(state); | ||
function useSignal(value, comparator) { | ||
function createSignal(value, comparator) { | ||
const d = S.makeDataNode(value); | ||
@@ -254,5 +254,5 @@ let setter; | ||
function useMemo(fn, seed) { return S(fn, seed); } | ||
function createMemo(fn, seed) { return S(fn, seed); } | ||
function useEffect(fn, deps, defer) { | ||
function createEffect(fn, deps, defer) { | ||
if (!deps) return S.makeComputationNode(fn); | ||
@@ -262,36 +262,13 @@ S.on(deps, fn, undefined, defer); | ||
// export observable | ||
function observable(input) { | ||
if (Symbol.observable in input) return input[Symbol.observable](); | ||
return { | ||
subscribe(observer) { | ||
if (!(observer instanceof Object) || observer == null) { | ||
throw new TypeError('Expected the observer to be an object.'); | ||
} | ||
observer = observer.next || observer; | ||
let complete = false; | ||
S.on(input, function next() { | ||
if (complete) return; | ||
observer(input()); | ||
}); | ||
return { | ||
unsubscribe() { complete = true; } | ||
}; | ||
}, | ||
[Symbol.observable]() { return this; } | ||
}; | ||
} | ||
const { root: createRoot, cleanup: onCleanup, sample, freeze } = S; | ||
const { root, cleanup: useCleanup, sample, freeze } = S; | ||
exports.root = root; | ||
exports.useCleanup = useCleanup; | ||
exports.createRoot = createRoot; | ||
exports.onCleanup = onCleanup; | ||
exports.sample = sample; | ||
exports.freeze = freeze; | ||
exports.useState = useState; | ||
exports.createState = createState; | ||
exports.unwrap = unwrap; | ||
exports.reconcile = reconcile; | ||
exports.useSignal = useSignal; | ||
exports.useMemo = useMemo; | ||
exports.useEffect = useEffect; | ||
exports.observable = observable; | ||
exports.createSignal = createSignal; | ||
exports.createMemo = createMemo; | ||
exports.createEffect = createEffect; |
{ | ||
"name": "solid-js", | ||
"description": "A declarative JavaScript library for building user interfaces.", | ||
"version": "0.3.8", | ||
"version": "0.4.0", | ||
"author": "Ryan Carniato", | ||
@@ -23,6 +23,6 @@ "license": "MIT", | ||
"peerDependencies": { | ||
"babel-plugin-jsx-dom-expressions": ">=0.3.10 < 0.4.0" | ||
"babel-plugin-jsx-dom-expressions": "0.4.x" | ||
}, | ||
"devDependencies": { | ||
"jest": "~23.6.0", | ||
"jest": "~24.1.0", | ||
"rollup": "^1.1.0", | ||
@@ -29,0 +29,0 @@ "rollup-plugin-node-resolve": "^4.0.0" |
@@ -8,5 +8,7 @@ # Solid.js | ||
* JSX precompilation with support for standard JSX features and W3C Web Components | ||
* Webcomponent friendly implicit event delegation | ||
* Declarative data | ||
* Data behavior is part of the declaration | ||
* No need for lifecycle functions, and the large chains of conditionals they bring. | ||
* Power of Hooks with no Hook Rules. | ||
* ES6 Proxies to keep data access simple and POJO like | ||
@@ -21,3 +23,3 @@ * Expandable custom operators and binding directives. | ||
```jsx | ||
import { root } from 'solid-js' | ||
import { createRoot } from 'solid-js' | ||
@@ -30,3 +32,3 @@ const MyComponent = props => | ||
root(() => mountEl.appendChild(<MyComponent name='Taylor' />)); | ||
createRoot(() => mountEl.appendChild(<MyComponent name='Taylor' />)); | ||
``` | ||
@@ -45,10 +47,10 @@ | ||
```jsx | ||
import { root, useState } from 'solid-js' | ||
import { createRoot, createState, onCleanup } from 'solid-js' | ||
const CountingComponent = () => { | ||
const [state, setState] = useState({counter: 0}), | ||
const [state, setState] = createState({counter: 0}), | ||
interval = setInterval(() => setState({ | ||
counter: state.counter + 1 | ||
}), 1000); | ||
useCleanup(() => clearInterval(interval)); | ||
onCleanup(() => clearInterval(interval)); | ||
@@ -62,3 +64,3 @@ return <div>{(state.counter)}</div> | ||
```js | ||
const [state, setState] = useState({ | ||
const [state, setState] = createState({ | ||
user: { | ||
@@ -75,3 +77,3 @@ firstName: 'John' | ||
```js | ||
const [state, setState] = useState({counter: 0}); | ||
const [state, setState] = createState({counter: 0}); | ||
setState('counter', c => c + 1); | ||
@@ -85,3 +87,3 @@ ``` | ||
```js | ||
useEffect(() => setState({ | ||
createEffect(() => setState({ | ||
displayName: `${state.user.firstName} ${state.user.lastName}` | ||
@@ -99,3 +101,3 @@ })); | ||
const unsubscribe = store.subscribe(({ todos }) => setState(reconcile('todos', todos))); | ||
useCleanup(() => unsubscribe()); | ||
onCleanup(() => unsubscribe()); | ||
``` | ||
@@ -126,2 +128,3 @@ | ||
``` | ||
With HyperScript it is possible to map to element functions or even tagged template literals which offer many different development experiences. See examples below. | ||
@@ -135,8 +138,8 @@ ## Components | ||
```jsx | ||
import { useState, root } from 'solid-js' | ||
import { createState, createRoot } from 'solid-js' | ||
class Component extends HTMLElement { | ||
constructor () { | ||
const [state, setState] = useState({}), | ||
[props, __setProps] = useState({}); | ||
const [state, setState] = createState({}), | ||
[props, __setProps] = createState({}); | ||
Object.assign(this, {state, setState, props, __setProps}); | ||
@@ -147,3 +150,3 @@ } | ||
this.attachShadow({mode: 'open'}); | ||
root(() => this.shadowRoot.appendChild(this.render()); | ||
createRoot(() => this.shadowRoot.appendChild(this.render()); | ||
} | ||
@@ -212,2 +215,3 @@ | ||
* [Simple Todos HyperScript](https://codepen.io/ryansolid/pen/WPGobB?editors=0010) on CodePen | ||
* [Simple Todos Template Literals](https://codepen.io/ryansolid/pen/GzQNWB?editors=0010) on CodePen | ||
* [TodoMVC](https://github.com/ryansolid/solid-todomvc) Classic TodoMVC example | ||
@@ -214,0 +218,0 @@ * [WebComponent Todos](https://github.com/shprink/web-components-todo/tree/master/solid) Showing off Solid with Web Components |
@@ -1,2 +0,2 @@ | ||
const { root, useState, useSignal, useEffect, reconcile } = require('../lib/solid'); | ||
const { createRoot, createState, createSignal, createEffect, reconcile } = require('../lib/solid'); | ||
@@ -6,8 +6,8 @@ describe('setState', () => { | ||
test('Track a state change', () => { | ||
root(() => { | ||
var [state, setState] = useState({data: 2}), | ||
createRoot(() => { | ||
var [state, setState] = createState({data: 2}), | ||
executionCount = 0; | ||
expect.assertions(2); | ||
useEffect(() => { | ||
createEffect(() => { | ||
if (executionCount === 0) | ||
@@ -30,8 +30,8 @@ expect(state.data).toBe(2); | ||
test('Track a nested state change', () => { | ||
root(() => { | ||
var [state, setState] = useState({user: {firstName: 'John', lastName: 'Smith'}}), | ||
createRoot(() => { | ||
var [state, setState] = createState({user: {firstName: 'John', lastName: 'Smith'}}), | ||
executionCount = 0; | ||
expect.assertions(2); | ||
useEffect(() => { | ||
createEffect(() => { | ||
if (executionCount === 0) | ||
@@ -57,8 +57,8 @@ expect(state.user.firstName).toBe('John'); | ||
test('Track a state reconcile', () => { | ||
root(() => { | ||
var [state, setState] = useState({ data: 2, missing: 'soon' }), | ||
createRoot(() => { | ||
var [state, setState] = createState({ data: 2, missing: 'soon' }), | ||
executionCount = 0; | ||
expect.assertions(4); | ||
useEffect(() => { | ||
createEffect(() => { | ||
if (executionCount === 0) { | ||
@@ -81,9 +81,9 @@ expect(state.data).toBe(2); | ||
describe('useEffect', () => { | ||
describe('createEffect', () => { | ||
test('Setting state from signal', () => { | ||
root(() => { | ||
var [ getData, setData ] = useSignal('init'), | ||
[ state, setState ] = useState({}); | ||
useEffect(() => setState('data', getData())); | ||
createRoot(() => { | ||
var [ getData, setData ] = createSignal('init'), | ||
[ state, setState ] = createState({}); | ||
createEffect(() => setState('data', getData())); | ||
setData('signal') | ||
@@ -95,6 +95,6 @@ expect(state.data).toBe('signal'); | ||
test('Select Promise', (done) => { | ||
root(async () => { | ||
createRoot(async () => { | ||
var p = new Promise(resolve => { setTimeout(resolve, 20, 'promised'); }), | ||
[ state, setState ] = useState({}); | ||
useEffect(() => p.then(v => setState('data', v))); | ||
[ state, setState ] = createState({}); | ||
createEffect(() => p.then(v => setState('data', v))); | ||
await p; | ||
@@ -101,0 +101,0 @@ expect(state.data).toBe('promised'); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
224
52788
654