https://github.com/alloc/fluids
Glue layer for reactivity
https://github.com/alloc/fluids
events observable reactive reactivity
Last synced: 7 months ago
JSON representation
Glue layer for reactivity
- Host: GitHub
- URL: https://github.com/alloc/fluids
- Owner: alloc
- Created: 2019-10-04T22:03:43.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2021-05-19T18:08:56.000Z (over 4 years ago)
- Last Synced: 2025-06-24T12:57:33.127Z (8 months ago)
- Topics: events, observable, reactive, reactivity
- Language: TypeScript
- Homepage:
- Size: 48.8 KB
- Stars: 6
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# fluids
This library is a tiny glue layer for observable events.
- Create a tree of observable values
- Let parent nodes send arbitrary events to children (for maximum flexibility)
- Stay small yet provide helpers for easier integration
### Observe a value
Any object can be observed, but `FluidValue` objects have strongly typed
events. Observed objects are basically event emitters whose listeners
receive every event, and they typically represent a single value.
To start observing:
```ts
import { addFluidObserver } from 'fluids'
// You can pass a function:
let observer = addFluidObserver(target, (event) => {
console.log(event)
})
// or pass an object:
observer = addFluidObserver(target, {
eventObserved(event) {
console.log(event)
},
})
```
To stop observing:
```ts
import { removeFluidObserver } from 'fluids'
removeFluidObserver(target, observer)
```
### Create an observed object
You can extend the `FluidValue` class for automatic TypeScript support with
`fluids`-compatible libraries.
```ts
import { FluidValue, FluidObservable, callFluidObservers } from 'fluids'
// Your class can have multiple event types.
// The `type` and `parent` properties are required.
type RefEvent = { type: 'change'; value: T; parent: Ref }
// Use "interface merging" to attach the event types.
interface Ref extends FluidObservable> {}
// This example is an observable React ref.
class Ref extends FluidValue {
private _current: T
constructor(initialValue: T) {
// Passing a getter to super is only required
// if your class has no "get" method.
super(() => this._current)
this._current = initialValue
}
get current() {
return this._current
}
set current(value: T) {
this._current = value
// Send the change to all observers.
callFluidObservers(this, {
type: 'change',
value,
parent: this,
})
}
//
// These methods are completely optional.
//
protected observerAdded(count: number) {
if (count == 1) {
// Do something when the first observer is added.
}
}
protected observerRemoved(count: number) {
if (count == 0) {
// Do something when the last observer is removed.
}
}
}
```
If extending `FluidValue` isn't an option, you can outfit an object or
prototype with the `setFluidGetter` function:
```ts
import { setFluidGetter, callFluidObservers } from 'fluids'
// This example augments an existing React ref.
let { current } = ref
let get = () => current
setFluidGetter(ref, get)
Object.defineProperty(ref, 'current', {
get,
set(value) {
current = value
// Remember to notify any observers.
callFluidObservers(ref, {
type: 'change',
value,
parent: ref,
})
},
})
```
### For libraries
The remaining functions are useful when making a `fluids`-compatible library.
```ts
import {
hasFluidValue,
getFluidValue,
getFluidObservers,
callFluidObserver,
} from 'fluids'
// Check if a value is observable.
hasFluidValue(target)
// Get the current value. Returns `target` if not observable.
getFluidValue(target)
// Get the current observers (or null if none exist).
getFluidObservers(target)
// Call a single observer. Useful for special observation, like waterfalls.
callFluidObserver(observer, event)
```