Security News
Introducing the Socket Python SDK
The initial version of the Socket Python SDK is now on PyPI, enabling developers to more easily interact with the Socket REST API in Python projects.
A tiny reactive user interface library.
Observables
and Promises
. Just put them where they need to be displayed and, when they update, your UI will be refreshed for you.4kB
gziped.npm install evolui rxjs
To jump to the code, visite the example
folder.
import html, { render } from 'evolui'
const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
render(
html`
<p>
Hello, ${delay(1000).then(() => 'World!')}
</p>
`,
document.querySelector('#mount')
)
import html, { render } from 'evolui'
import { interval } from 'rxjs'
import { take, map } from 'rxjs/operators'
render(
html`
<p>
Hello, ${interval(1000).pipe(
take(4),
map(index => ['.', '..', '...', 'World!'][index])
)}
</p>
`,
document.querySelector('#mount')
)
import html, { render } from 'evolui'
import { createState } from 'evolui/extra'
const Counter = () => {
const state = createState({ count: 0 })
return html`
<div>
count: ${state.count}
<button onClick=${() => state.count.set(c => c - 1)}>-</div>
<button onClick=${() => state.count.set(c => c + 1)}>+</div>
</div>
`
}
render(html`<${Counter} />`, document.querySelector('#mount'))
The main goal of evolui is to make dealing with observables as easy as dealing with regular values.
Observables are a great way to represent values that change over time. The hard part though is combining them. This is where evolui comes in handy. It understands any combination of Array
s, Promise
s and Observable
s, so you never have to worry about the way you should combine them before putting them inside your template.
import html from 'evolui'
import { from } from 'rxjs'
import { startWith } from 'rxjs/operators'
const getCharacterName = id =>
fetch(`https://swapi.co/api/people/${id}`)
.then(res => res.json())
.then(character => character.name)
html`
<div>
${'' /* this will return an array of observables. */}
${'' /* Don't panic! evolui understands that as well */}
${[1, 2, 3].map(
id => html`
<h1>
${from(getCharacterName(id)).pipe(startWith('Loading...'))}
</h1>
`
)}
</div>
`
Evolui lets you organize your code in components.
Components are defined as a simple function of Observable Props -> Observable VirtualDOM
:
import html, { render } from 'evolui'
import { createState } from 'evolui/extra'
import { map } from 'rxjs/operators'
const Button = props$ =>
props$.pipe(
map(
({ text, onClick }) => html`
<button class="Button" onClick=${onClick}>
${text}
</button>
`
)
)
const App = () => {
const state = createState({ count: 0 })
return html`
<div>
<${Button}
text="-"
onClick=${() => state.count.set(c => c - 1)}
/>
count: ${state.count}
<${Button}
text="+"
onClick=${() => state.count.set(c => c + 1)}
/>
</div>
`
}
render(html`<${App} />`, document.querySelector('#mount'))
Components can have children 👍
import html, { render } from 'evolui'
import { map } from 'rxjs/operators'
const CrazyLayout = map(({ children }) => html`<div>${children}</div>`)
render(
html`
<${CrazyLayout}>
<p>I'm the content</p>
</${CrazyLayout}>
`,
document.querySelector('#mount')
)
evolui/extra
exports a spring animation helper called ease
.
ease: (stiffness: number, damping: number, id: string?) => Observable<number> => Observable<number>
You just have to pipe any of your observables to ease(<stiffness>, <damping>)
to make it animated.
If you are interested in using this feature separately, check out rx-ease
import html, { render } from 'evolui'
import { ease } from 'evolui/extra'
import { fromEvent } from 'rxjs'
import { map, startWith } from 'rxjs/operators'
const stiffness = 120
const damping = 20
const style$ = fromEvent(window, 'click').pipe(
map(() => ({ x: e.clientX, y: e.clientY })),
startWith({ x: 0, y: 0 }),
ease({
x: [stiffness, damping],
y: [stiffness, damping],
}),
map({ x, y }) => ({
transform: `translate(${x}px,${y}px)`
})
)
render(
html`
<div
class="circle"
style="${style$}"
/>
`,
document.querySelector('#mount')
)
For single values, you can pass the stiffness
and damping
directly
import html, { render } from 'evolui'
import { ease } from 'evolui/extra'
import { interval } from 'rxjs'
import { map } from 'rxjs/operators'
render(
html`
<div style="width: ${interval(1000).pipe(
map(i => i * 50),
ease(120, 20)
)}px" />
`,
document.querySelector('#mount')
)
import { text } from 'evolui'
const style$ = text`
position: absolute;
transform: translate(${x$}px, ${y$}px);
`
import html from 'evolui'
const App = () => html`
<div style="${style$};" />
`
import { render } from 'evolui'
render(html`<${App} />`, document.querySelector('#mount'))
import { ease } from 'evolui/extra'
import { interval } from 'rxjs'
interval(1000).pipe(
ease(120, 20),
subscribe(x => console.log(x)) // every values will be interpolated
)
Create an object of mutable reactive values.
Each key on your initial state will be transformed into a stream, with a special set
method on it.
set
can take either a value or a mapper function.
import html, { render } from 'evolui'
import { createState } from 'evolui/extra'
const state = createState({ count: 0 })
console.log(state.count)
// => Observable.of(0)
const reset = () => state.count.set(0)
const add1 = () => state.count.set(c => c + 1)
render(
html`
<div>
count: ${state.count}
<button onClick=${reset}>reset</button>
<button onClick=${add1}>+</button>
</div>
`,
document.querySelector('#mount')
)
import { all } from 'evolui/extra'
const z$ = all([x$, y$]).map(([x, y]) => x + y)
html`
<div
mount="${el => console.log('mounted!', el)}"
update="${el => console.log('updated', el)}"
unmount="${el => console.log('will unmount!', el)}" />
`
If you find this interesting and you want to contribute, don't hesitate to open an issue or to reach me out on twitter @GabrielVergnaud!
FAQs
Observable powered templates for asynchronous UIs
The npm package evolui receives a total of 58 weekly downloads. As such, evolui popularity was classified as not popular.
We found that evolui demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The initial version of the Socket Python SDK is now on PyPI, enabling developers to more easily interact with the Socket REST API in Python projects.
Security News
Floating dependency ranges in npm can introduce instability and security risks into your project by allowing unverified or incompatible versions to be installed automatically, leading to unpredictable behavior and potential conflicts.
Security News
A new Rust RFC proposes "Trusted Publishing" for Crates.io, introducing short-lived access tokens via OIDC to improve security and reduce risks associated with long-lived API tokens.