Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/rozek/reactive-scriptable-components

light-weight reactive scriptable web components
https://github.com/rozek/reactive-scriptable-components

custom-elements htm hyperactiv preact reactive scriptable web-components

Last synced: 15 days ago
JSON representation

light-weight reactive scriptable web components

Awesome Lists containing this project

README

        

# reactive-scriptable-components (RSC) #

light-weight reactive scriptable web components

> **Warning**: this framework is currently under active development - consider it as incomplete pre-alpha software: anything may change, some changes _may_ even break existing applications (although I don't _expect_ many of them). **Thus, please stay tuned and come back here from time to time to see if there is a (well-documented) version that you may safely use...**

The idea behind this framework is to allow for the rapid development of small reactive web applications. To give you an idea of what these web apps could look like, consider the following example (which implements a simple calculator that converts temperatures between °Celsius and °Fahrenheit, see [live demo](https://rozek.github.io/reactive-scriptable-components/examples/Temperature-Converter.html)):

![Screenshot of the Temperature Converter Example](TemperatureConverter-Screenshot.png)

```html

Temperature Converter

°Celsius:

°Fahrenheit:


const observed = Object.assign(this.observed,{
Celsius:0,
Fahrenheit:0
})

reactively(() => observed.Fahrenheit = observed.Celsius * 9/5 + 32)
reactively(() => observed.Celsius = 5/9 * (observed.Fahrenheit-32))


```

The example basically consists of two number input controls, a bit of visual "decoration" and some "business logic".

What makes it interesting is how the logic works:

* `$$value` attributes make the number input controls "reactive" (in both directions), i.e., user input changes the specified variable and variable changes will be reflected in the UI - and, yes, the circularity of the dependencies shown above causes no problem
* every "reactive scriptable component" (which is a standard [web component](https://developer.mozilla.org/en-US/docs/Web/API/Web_components)) may contain its own `observed` and `unobserved` (state) variables - in this trivial example, only the applet itself provides some "state", whereas the input controls do not
* whenever an `observed` variable is changed, all functions using that variable may be `reactively` recalculated - in this example, changes of the `Celsius` variable will recompute the `Fahrenheit` variable and vice-versa - and the `$value` reactivity will automatically update the number input fields.

This approach allows to write simple web applications within minutes - the author uses it for his computer science lectures at [Stuttgart University of Applied Sciences](https://www.hft-stuttgart.com/) in order to demonstrate various concepts and algorithms or give students the possibility to practice what they learned. You probably won't use "reactive-scriptable-components" to implement the next office package, but simple tools can be written with very little effort and in a way that may easily be understood even by inexperienced or casual programmers.

**NPM users**: please consider the [Github README](https://github.com/rozek/reactive-scriptable-components) for the latest description of this package (as updating the docs would otherwise always require a new NPM package version)

> Just a small note: if you like this module and plan to use it, consider "starring" this repository (you will find the "Star" button on the top right of this page), so that I know which of my repositories to take most care of.

## Features ##

"reactive-scriptable-components" offer the following fundamental features:

- **Script Attributes**
(small) scripts may be directly provided as an HTML attribute of a component - this keeps a component and it's functionality together
- **Script Elements**
(larger) scripts may be provided as a `` element within the component they belong to - e.g., below all other inner HTML elements. This approach keeps the internal structure of an RSC component visible and still allows a component and its code to be kept close together
- **Delegated Scripts**
if you want to separate the "look" from its "feel", you may provide "delegated scripts" (``) for components that can be identified by a CSS selector (e.g., `#id`, `.class`, `[attr="value"]` etc.)
- **Behaviour Scripts**
if you have multiple RSC components that share the same functionality, you may define a "behaviour" and provide the shared code in a separate `` element. If there are both a behaviour and a component script for a given RSC component, the behaviour script is executed before the component script.
- **Observed and Unobserved Variables**
RSC components usually have to store some values they need for their operation. For that purpose, RSC provides both an `observed` and an `unobserved` data structure for every component which can be freely used as required. "Observed" entries may then be used to trigger "reactive functions" or update "reactive attributes" whenever their values change
- **Reactive Functions**
"reactive functions" (defined using `reactively(() => ...)`) are functions that will be automatically invoked whenever any of the observed(!) values they use internally have changed
- **Reactive Attributes**
"reactive attributes" have names starting with one or two dollar signs (e.g., `$value` or `$$value`) and establish a "reactive binding" between a reactive variable of the component itself (`observed.value` in this example) and another reactive variable in an outer RSC component - both a reference to that outer component and the path to the other reactive variable have to be specified in the attribute itself
- **Event Handlers as Function Calls**
sometimes, RSC components do not directly change other (reactive) variables but initiate an activity - to support such use cases, RSC components may trigger events or handle them. In contrast to DOM events, however, RSC events may be used like function calls, i.e., it is allowed to provide arbitrary arguments and possible to wait for a result from event handling
- **Error Indicators**
often, it is difficult to recognize and track errors which occured in behaviour or component scripts, or during event handling. For that reason, RSC marks faulty components with an "error indicator": just click on such an indicator to reveal details about the detected error

## Built-in Controls ##

![Screenshot of built-in native HTML Controls](nativeControls-Screenshot.png)

## Browser Requirements (and Polyfills) ##

RSC is based on relatively modern web technologies which _should_ already be available in most browsers out-of-the-box - but for those that lack these features (particularily Safari versions < 16.4 or devices with iOS versions < 16.4), polyfills have been included in the examples to plug these holes:

- [Import Maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) (see [availability across browsers](https://caniuse.com/mdn-html_elements_script_type_importmap))
for a polyfill see [https://github.com/guybedford/es-module-shims](https://github.com/guybedford/es-module-shims)
- [Custom Elements v1](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements) (see [availability across browsers](https://caniuse.com/?search=Custom%20Elements))
for a polyfill see [https://github.com/webcomponents/webcomponentsjs](https://github.com/webcomponents/webcomponentsjs)

## Inlined Dependencies ##

"reactive-scriptable-components" are based on the following (brilliant!) libraries and packages:

* [HTM (Hyperscript Tagged Markup)](https://github.com/developit/htm) - for easy HTML markup using JavaScript template strings,
* [PREACT](https://github.com/preactjs/preact) - from which its efficient and light-weight DOM diffing is used, and
* [Hyperactiv](https://github.com/elbywan/hyperactiv) - a light-weight reactive library which even handles circular dependencies

All these dependencies have been bundled into a single module for faster loading and a predictable user experience.

> Nota bene: while it may be advisable to [know how to use HTM](https://github.com/developit/htm?tab=readme-ov-file#syntax-like-jsx-but-also-lit), there is no immediate need to learn any of the above to write an RSC application.

The final distributables were built using the marvellous [microbundle](https://github.com/developit/microbundle).

## Installation ##

In order to avoid initial flashing of "custom Elements" (aka "Web Components") you should always add the following lines at the beginning of the `