@dreamfusion/pollen
v2.0.0
Published
A modern reactive framework for building connections between JavaScript objects and the DOM
Downloads
5
Maintainers
Readme
Pollen 2.0 🌸
Pollen is a lightweight, modern reactive framework for building explicit connections between JavaScript objects and the DOM. It provides a powerful, signal-based reactive core while maintaining a simple, intuitive API for data binding and state management.
Originally conceived in 2014, Pollen 2.0 is a complete rewrite that embraces modern JavaScript, TypeScript, and the emerging Signals standard. It preserves the original library's core concept of a "connectable" web, but with a high-performance, fine-grained reactive engine under the hood.
Core Concepts
Signals: The heart of Pollen's reactivity. A
Signalis a reactive value container. When its value changes, it automatically notifies anything that depends on it.Pollination: The process of making an object reactive.
pollinate()takes a plain JavaScript object and endows it with reactive capabilities, including a unique ID and a set of connectablenodes.Nodes: A
Nodeis a reactive endpoint on a pollinated object. It can be a simple value (a Signal), a derived value (a Computed), or have custom getter/setter logic.Connections: The magic of Pollen. A
Connectionis an explicit, reactive link between two nodes. When the source node's value changes, the target node's value is automatically updated.
Features
- Fine-Grained Reactivity: Powered by a Signal-based core for optimal performance.
- Explicit Connections: A clear and declarative API for creating data flows.
- TypeScript First: Full static typing for a robust developer experience.
- DOM Integration: Easily bind reactive state to DOM elements and attributes.
- Extensible Factory: A system for creating reusable, pre-pollinated components.
- Zero Dependencies: A lean core with no external runtime dependencies.
Installation
Install Pollen 2.0 from the npm registry:
# Using npm
npm install @dreamfusion/pollen
# Using pnpm
pnpm add @dreamfusion/pollenQuick Start
Here's a simple example of a reactive counter connected to the DOM.
<div id="app">
<h1>Count: <span id="display">0</span></h1>
<button id="increment">+1</button>
</div>
<script type="module">
import Pollen from '@dreamfusion/pollen';
// 1. Create a reactive object with a 'value' node
const counter = Pollen.pollinate({ value: 0 }, {
value: { get: () => counter.value, set: (v) => counter.value = v }
});
// 2. Pollinate the DOM element
const display = Pollen.pollinateDOM(document.getElementById('display'));
// 3. Connect the counter's value to the display's text content
Pollen.connect(counter, 'value', display, 'textContent');
// 4. Add an event listener to update the counter
document.getElementById('increment').addEventListener('click', () => {
Pollen.setNode(counter, 'value', counter.value + 1);
});
</script>API Reference
Core Reactivity
These are the low-level primitives that power Pollen.
| Function | Description |
| --- | --- |
| signal(initialValue) | Creates a new Signal (a reactive value). |
| computed(fn) | Creates a Computed signal whose value is derived from other signals. |
| effect(fn) | Creates a reactive computation that runs whenever its dependencies change. |
Pollination
pollinate(obj, nodeDefinitions) is the primary way to make an object reactive.
import { pollinate, getNode, setNode } from '@dreamfusion/pollen';
let myValue = 10;
const myObject = pollinate({}, {
value: {
type: 'number',
label: 'My Value',
get: () => myValue,
set: (v: number) => { myValue = v; }
},
doubled: {
type: 'number',
label: 'Doubled Value',
compute: () => myValue * 2
}
});
console.log(getNode(myObject, 'doubled')); // 20
setNode(myObject, 'value', 20);
console.log(getNode(myObject, 'doubled')); // 40Connections
Create reactive links between nodes.
import { connect, from } from '@dreamfusion/pollen';
// Standard API
connect(sourceObj, 'sourceNode', targetObj, 'targetNode');
// Fluent API
from(sourceObj, 'sourceNode').to(targetObj, 'targetNode');
// With a value transformer
from(sourceObj, 'sourceNode')
.transform(value => value.toUpperCase())
.to(targetObj, 'targetNode');DOM Integration
Pollen provides helpers for working with the DOM.
| Function | Description |
| --- | --- |
| pollinateDOM(element) | Makes a DOM element reactive, creating nodes for its attributes. |
| $(selector) | Queries a single element and pollinates it. |
| $$ (selector) | Queries multiple elements and pollinates them. |
| bind(element, prop, fn) | Creates a one-way binding from a signal to a DOM property. |
| on(element, event, handler) | Attaches an event listener. |
Example:
import { $, on, signal } from '@dreamfusion/pollen';
const name = signal('World');
const heading = $('#greeting');
// Bind the signal to the element's text content
bind(heading.element, 'textContent', () => `Hello, ${name.get()}!`);
// Update the signal on button click
on($('#my-button').element, 'click', () => {
name.set('Pollen 2.0');
});Factory
The factory provides pre-built, reusable components.
import { factory, connect } from '@dreamfusion/pollen';
const counter = factory.make('logic.counter');
const display = pollinateDOM(document.getElementById('display'));
connect(counter, 'value', display, 'textContent');Available Components:
logic.counter: An incremental counter.logic.calculator: A basic arithmetic calculator.logic.store: A simple value store.logic.gate: A data flow gate.logic.ticker: A periodic timer.logic.comparator: Compares two values.
Examples
Explore these live examples to see Pollen 2.0 in action:
- Counter: A simple counter built with the factory.
- Calculator: A multi-connection calculator.
- Form Binding: Demonstrates two-way data binding with a form.
To run the examples, clone the repository and open the HTML files in your browser.
Building from Source
If you'd like to contribute to Pollen or build it from source, follow these steps:
Clone the repository:
git clone https://github.com/bentrain/pollen.git cd pollen/pollen2Install dependencies:
pnpm installRun the development server:
pnpm devRun tests:
pnpm testBuild the library:
pnpm build
License
Pollen 2.0 is open-source software licensed under the MIT License.
