Brynja is a virtual DOM implementation with a declarative chaining based javascript API.
- It's small. Less than 4kb gzipped.
- It requires NO transpilation, everything runs as is in the browser.
- Everything is 100% typed and ready for Typescript!
NPM:
CDN:
<script src="https://cdn.jsdelivr.net/npm/brynja/cdn/brynja.js"></script>
See upgrading guide
Please ⭐️ this repository!
- Hello World: https://jsfiddle.net/olian04/kcfserx5/216/
- Counting: https://jsfiddle.net/hrnxq01d/4/
- Table generation: https://jsfiddle.net/yvmaue6x/1/
- Probabilistic Propagation: https://jsfiddle.net/ebh7z13y/4/
- Interpolation animation: https://jsfiddle.net/t2zrf61o/2/
- Aim trainer game: https://jsfiddle.net/olian04/fxz53wcy/240/
- With html-router: https://jsfiddle.net/ao941b5r/1/
- With simply-reactive: https://jsfiddle.net/rb4xc25f/47/
You can setup brynja in one of two ways.
The default render method expects a dom element with id 'root' to exsist.
import { render } from 'brynja';
render(_=>_
.child('p', _=>_
.text('Hello World!')
)
);
import { Renderer } from 'brynja';
const { render } = new Renderer({
rootElement: document.getElementById('root')
});
render(_=>_
.child('p', _=>_
.text('Hello World!')
)
);
In brynja, method that are exposed on the chaining api is referred to as operations and are divided into 4 categories; Nesting operations, Mutating operations, Control flow operations, and Effect free operations.
Nesting operations are used to append children to the current vdom node.
render(_=>_
.child('div', _=>_
.text('Hello World!')
)
);
<div><!--Root-->
<div>
Hello World!
</div>
</div>
render(_=>_
.children('div', 3, (_, i)=>_
.text(i)
)
.children('div', ['a', 'b', 'c'], (_, item)=>_
.text(item)
)
);
<div><!--Root-->
<div>0</div>
<div>1</div>
<div>2</div>
<div>a</div>
<div>b</div>
<div>c</div>
</div>
Mutating operations are used for adding and modifying data on the current vdom node.
render(_=>_
.child('div', _=>_
.id('foo')
)
);
<div><!--Root-->
<div id="foo"></div>
</div>
render(_=>_
.child('div', _=>_
.class('foo', 'bar')
.class('biz')
)
);
<div><!--Root-->
<div class="foo bar biz"></div>
</div>
render(_=>_
.child('div', _=>_
.name('foo')
)
);
<div><!--Root-->
<div name="foo"></div>
</div>
render(_=>_
.child('div', _=>_
.value('foo')
)
);
<div><!--Root-->
<div value="foo"></div>
</div>
render(_=>_
.child('div', _=>_
.text('Foo')
)
);
<div><!--Root-->
<div>Foo</div>
</div>
render(_=>_
.child('div', _=>_
.prop('foo', 'bar')
)
);
<div><!--Root-->
<div foo="bar"></div>
</div>
render(_=>_
.child('div', _=>_
.on('click', e => console.log(e))
)
);
<div><!--Root-->
<div><!-- The dom element has the onClick event registered --></div>
</div>
render(_=>_
.child('div', _=>_
.text('Hello')
.style({
background: 'blue',
':hover': {
background: 'red'
}
})
)
);
<div><!--Root-->
<div class="brynja-k8xf37">Hello</div>
<style>
.brynja-k8xf37 {
background: blue;
}
.brynja-k8xf37:hover {
background: red;
}
</style>
</div>
Control flow operations are used for conditional rendering.
render(_=>_
.when(true, _=>_
.child('h1', _=>_)
)
.when(false, _=>_
.child('h1', _=>_)
,_=>_
.child('h2', _=>_)
)
);
<div><!--Root-->
<h1><!-- First when: true --></h1>
<h2><!-- Second when: false --></h2>
</div>
render(_=>_
.while(i => i < 3, (_, i)=>_
.child('div', _=>_
.text(i)
)
)
);
<div><!--Root-->
<div>0</div>
<div>1</div>
<div>2</div>
</div>
import { createComponent } from 'brynja';
const Image = createComponent((width, height, src) => _=>_
.child('img', _=>_
.prop('width', width)
.prop('height', heigh)
.prop('src', src)
.prop('alt', src.substring(src.lastIndexOf('/'), src.lastIndexOf('.')))
)
);
render(_=>_
.do(
Image(64, 64, '/assets/logo_small.png'),
Image(192, 192, '/assets/logo_medium.png')
)
);
<div><!--Root-->
<img src="/assets/logo_small.png" height="64" width="64" alt="logo_small">
<img src="/assets/logo_medium.png" height="192" width="192" alt="logo_medium">
</div>
When using Effect free operations you can be sure that no changes will be made in either the dom nor the vdom.
Peek at the current vdom node.
render(_=>_
.peek(console.log)
);
> { tag: 'div', value: null, text: '', events: {}, props: {}, children: [] }
Licensed under MIT. See LICENSE.