Compare commits
31 Commits
4065e17208
...
1.1.5
| Author | SHA1 | Date | |
|---|---|---|---|
| ad774185c2 | |||
| c513a54717 | |||
| 7e53db5785 | |||
| f463dec7f1 | |||
| 7f55ae0d4e | |||
| 6f52c56857 | |||
| cfdcdf1def | |||
| f8cdfe131f | |||
| 95f85aedaa | |||
| 5c7cf36cf3 | |||
| 2a84086828 | |||
| 1dcdc17436 | |||
| 466e95cb14 | |||
| 7ef7c44cf7 | |||
| bf31d5371e | |||
| fc4e96ab37 | |||
| 7af635a19b | |||
| 665dd28f93 | |||
| e026dcdb15 | |||
| 2102e9c8cf | |||
| 020299f82a | |||
| bac3b409d2 | |||
| 442f6055f6 | |||
| bd96c56445 | |||
| 9978667571 | |||
| 66173ac4f7 | |||
| 85fbdce1d5 | |||
| 4ad844468f | |||
| 2db58bec9e | |||
| 9df6a82f91 | |||
| a60c0a0657 |
16
.gitea/workflows/pull_request_change.yaml
Normal file
16
.gitea/workflows/pull_request_change.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
name: Pull request change
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "**"
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: debian-bullseye
|
||||
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: verify version
|
||||
uses: https://git.thorup.us/actions/version_verify@v1
|
||||
20
.gitea/workflows/push_to_main.yaml
Normal file
20
.gitea/workflows/push_to_main.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Push to main
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: debian-bullseye
|
||||
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: version tag
|
||||
uses: https://git.thorup.us/actions/version_tag@v1
|
||||
- name: npm publish
|
||||
uses: https://git.thorup.us/actions/npm_publish@v1
|
||||
with:
|
||||
npm_repo_key: ${{ secrets.NPM_REPO_KEY }}
|
||||
npm_repo_domain: ${{ vars.NPM_REPO_DOMAIN }}
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
@@ -1,3 +1,3 @@
|
||||
# interactor
|
||||
|
||||
cross-element communications and state management utility.
|
||||
Cross-element communications and state management utility.
|
||||
81
interactor.js
Normal file
81
interactor.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Stream } from "@brycethorup/stream";
|
||||
|
||||
export class Interactor {
|
||||
#actions = new Stream();
|
||||
#reactions = new Stream();
|
||||
#latestReaction;
|
||||
#latestReactions = {};
|
||||
|
||||
constructor(initialReaction = new Reaction()) {
|
||||
this.#actions.listen((action) => {
|
||||
let funcRef = `_handle${action.constructor.name}`;
|
||||
if (!this[funcRef])
|
||||
throw `${this.constructor.name} does not have a handler defined for the action "${action.constructor.name}". Create one by adding a function definition named "${funcRef}" in the ${this.constructor.name} class.`;
|
||||
this[funcRef](action);
|
||||
});
|
||||
this._react(initialReaction);
|
||||
}
|
||||
|
||||
act(action) {
|
||||
if (!(action instanceof Action)) throw "invalid action";
|
||||
this.#actions.add(action);
|
||||
}
|
||||
|
||||
observe(reactionHandler, provideLatestReaction = true) {
|
||||
if (provideLatestReaction) reactionHandler(this.#latestReaction);
|
||||
let listener = (reaction) => {
|
||||
if (!(reaction instanceof Reaction)) throw "invalid reaction";
|
||||
reactionHandler(reaction);
|
||||
};
|
||||
this.#reactions.listen(listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
ignore(listener) {
|
||||
this.#reactions.ignore(listener);
|
||||
}
|
||||
|
||||
_react(reaction) {
|
||||
if (!(reaction instanceof Reaction)) throw "invalid reaction";
|
||||
let latest = this.#latestReactions[reaction.constructor.name];
|
||||
if (!reaction.equals(latest)) {
|
||||
this.#latestReaction = reaction;
|
||||
this.#latestReactions[reaction.constructor.name] = reaction;
|
||||
this.#reactions.add(reaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Action {}
|
||||
|
||||
export class ActionBundle {
|
||||
add(action) {
|
||||
if (!(action.prototype instanceof Action)) {
|
||||
throw "Only classes extended by `Action` can be added to a `ActionBundle`";
|
||||
}
|
||||
let actionName = action.name;
|
||||
this[`#${actionName}`] = action;
|
||||
Object.defineProperty(this, actionName, {
|
||||
get: () => this[`#${actionName}`],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class Reaction {
|
||||
equals(reaction) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class ReactionBundle {
|
||||
add(reaction) {
|
||||
if (!(reaction.prototype instanceof Reaction)) {
|
||||
throw "Only classes extended by `Reaction` can be added to a `ReactionBundle`";
|
||||
}
|
||||
let reactionName = reaction.name;
|
||||
this[`#${reactionName}`] = reaction;
|
||||
Object.defineProperty(this, reactionName, {
|
||||
get: () => this[`#${reactionName}`],
|
||||
});
|
||||
}
|
||||
}
|
||||
20
package-lock.json
generated
Normal file
20
package-lock.json
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "interactor",
|
||||
"version": "1.0.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "interactor",
|
||||
"version": "1.0.4",
|
||||
"dependencies": {
|
||||
"stream": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://git.thorup.us/api/packages/bryce/npm/stream/-/1.0.0/stream-1.0.0.tgz",
|
||||
"integrity": "sha512-JGDjmgbnZcPCiQUxsboU7UufAryyivajDR3sCD790N/xfGpzlfl7OpPXf7EodDc43ojE+8dU8c3MOGbsH/Er4g=="
|
||||
}
|
||||
}
|
||||
}
|
||||
11
package.json
Normal file
11
package.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@brycethorup/interactor",
|
||||
"version": "1.1.5",
|
||||
"description": "Cross-element communications and state management utility.",
|
||||
"author": "Bryce Thorup",
|
||||
"type": "module",
|
||||
"main": "interactor.js",
|
||||
"dependencies": {
|
||||
"@brycethorup/stream": "^1.0.1"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user