Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/raycar5/valv

A tiny but powerful web framework built on top of lit-html and rxjs
https://github.com/raycar5/valv

framework lit-html rxjs typescript web

Last synced: about 2 months ago
JSON representation

A tiny but powerful web framework built on top of lit-html and rxjs

Awesome Lists containing this project

README

        

# | Valv |

A tiny but powerful web framework built on top of [lit-html](https://github.com/Polymer/lit-html) and [rxjs](https://github.com/ReactiveX/rxjs)

## [Demo](https://valv-hn.firebaseapp.com/top/1) ([Source](https://github.com/raycar5/valv-hn))

## Features

- Easy ui design and composition thanks to lit-html
- Powerful state management thanks to rxjs
- Fast! (no traversing trees to see what changed)
- SPA router in the box
- 100% Web component compatible
- Nice api for web animations
- Tiny (10KB gzipped)

## Naming

Due to the extensive use of rx in this library I've opted for the following naming convention for the frequently used types:

- Observables: observable\$
- Subjects: \$subject\$
- Observers: \$observer

## Guide

Valv is all about controlling the flow of streams, whenever an event happens, it gets put into an observable and the job of the application is to build a pipeline with rxjs that turns that event into a UI update.

**It is an absolute requirement that you understand rxjs in order to use this framework, so please read the documentation at [ReactiveX](http://reactivex.io/intro.html) if you haven't done so.**

Valv has 2 main parts, Widgets and Blocs:

### Widgets

A widget is a function that takes context, some props and returns a lit-html TemplateResult, it is wrapped in the `Widget` function for convinience.

```typescript
interface MyWidgetProps {
text: string;
}
const MyWidgetDefaultProps = { text: 'HelloWorld' };
const MyWidget = Widget((context, { text }: MyWidgetProps = MyWidgetDefaultProps) =>
html`

${text}

`;
);
```

Rendering a widget is easy!

```typescript
render(MyWidget(context), document.getElementById('body'));
```

Widgets are composable.

```typescript
// Props can have any type you want
const BoldWidget = Widget(
(context, widget: Widget) =>
html`
${widget(context)}
`
);
```

### Blocs

A Bloc is any class that uses observers as input and observables as output, the framework does not enforce this, you can put any class you like into a BlocRepo but hopefully after this guide you'll see it's a good way to structure your code.

```typescript
class MyBloc {
public readonly input: Observer; // We don't care about input values, just that the event happened
public readonly output: Observable;

// All the pipes are plugged together in the constructor
constructor() {
const subject = new Subject();
const input = subject; // We only expose the Observer side of the subject
const output = subject.pipe(map((x, index) => index)); // Number will increase as events come through the input
}
}
```

Widgets access blocs through the bloc repository or BlocRepo.
The code below displays a button and a number that increases every time you press the button.

```typescript
const context = new Context(); // Context right now only contains the BlocRepo but might include more information in the future
context.blocs.register(MyBloc);
context.blocs.register(MyParameterizedBloc, new MyParameterizedBloc(32)); // You can also provide an instance

const MyWidget = Widget(context => {
const myBloc = context.blocs.of(MyBloc);
return html`
${awaito(myBloc.output)}
`;
});
```

## awaito

But wait what is that function `awaito`?

It stands for await observable and it's the main tool that Valv provides, it takes an observable of anything that can be rendered in lit-html (text,numbers,TemplateResults) and whenever the observable emits a new value, the previous dom gets replaced with the new one.

It also provides a convinient map function as a second parameter if you want to construct the UI at the call site.

```typescript
awaito(
numberObservable,
number =>
html`
${number}
`
);
```

## Todo

- A lot of Documentation
- SSR
- PWA facilities
- more fancy animation stuff

### Made with [typescript-library-starter](https://github.com/alexjoverm/typescript-library-starter)