Skip to content

Commit

Permalink
expose only the react-like Signal type
Browse files Browse the repository at this point in the history
  • Loading branch information
AlessioCoser committed Mar 23, 2024
1 parent 20c841a commit 971d389
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 28 deletions.
37 changes: 24 additions & 13 deletions dev/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { Button, Div, H2 } from '../src/dom'
import { Children, Component } from '../src/dom/types';
import { effect, signal } from '../src/reactivity'
import { Accessor } from '../src/reactivity/types';
import { Button, Div, H2 } from "../src/dom";
import { Children, Component } from "../src/dom/types";
import { derive, effect, signal } from "../src/reactivity";
import { Accessor } from "../src/reactivity/types";

type ButtonProps = {
size: Accessor<number>;
onButtonClick: () => void;
children: Children
children: Children;
};
const MyButton: Component<ButtonProps> = ({ size, onButtonClick, children }) => {
const MyButton: Component<ButtonProps> = ({
size,
onButtonClick,
children,
}) => {
const [isLoading, setIsLoading] = signal(false);
const fontSize = () => `${size()}em`;
const fontSize = derive<string>("1em", () => `${size()}em`);

const onclick = async () => {
return new Promise((resolve) => {
Expand All @@ -23,7 +27,12 @@ const MyButton: Component<ButtonProps> = ({ size, onButtonClick, children }) =>
});
};

return Button({ style: {fontSize}, disabled: isLoading, onclick, children })
return Button({
style: { fontSize },
disabled: isLoading,
onclick,
children,
});
};

const App = () => {
Expand All @@ -37,12 +46,14 @@ const App = () => {
setSize(size() + 1);
};

return Div({ children: [
H2({ children: () => `Size ${size()}`}),
MyButton({ onButtonClick, size, children: () => `button ${text()}`})
]})
return Div({
children: [
H2({ children: () => `Size ${size()}` }),
MyButton({ onButtonClick, size, children: () => `button ${text()}` }),
],
});
};

// no need to use magic stuff to attach components to the dom,
// we always return a DOM Element from our components
document.body.appendChild(App());
document.body.appendChild(App());
4 changes: 2 additions & 2 deletions src/reactivity/effect.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Signal, Subscriber } from "./types";
import { _Signal, Subscriber } from "./types";
import { subscriptions } from "./subscriptions";

export function effect(fn: () => void) {
return _createEffect(fn);
}
export function _createEffect(
fn: () => void,
derived: Signal<any> | null = null
derived: _Signal<any> | null = null
) {
const running: Subscriber = {
derived,
Expand Down
10 changes: 5 additions & 5 deletions src/reactivity/signal.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { Signal, Accessor, Setter } from "./types";
import { Signal, _Signal } from "./types";
import { subscriptions } from "./subscriptions";

export function signal<T>(initial: T): [Accessor<T>, Setter<T>] {
export function signal<T>(initial: T): Signal<T> {
const s = _createSignal(initial);
return [s.get.bind(s), s.set.bind(s)];
}
export function _createSignal<T>(initial: T): Signal<T> {
export function _createSignal<T>(initial: T): _Signal<T> {
let _value: T = initial;

return {
get(this: Signal<T>) {
get(this: _Signal<T>) {
subscriptions.subscribeTo(this);
return _value;
},
set(this: Signal<T>, value: T) {
set(this: _Signal<T>, value: T) {
_value = value;
subscriptions.executeAllSubscriptionsTo(this);
},
Expand Down
5 changes: 3 additions & 2 deletions src/reactivity/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export type Derivation<T> = (previous: T) => Exclude<T, void>;
export type Accessor<T> = () => T;
export type Setter<T> = (value: T) => void;
export type Signal<T> = { get: Accessor<T>; set: Setter<T> };
export type Subscriber = { derived: Signal<any> | null, execute: () => void };
export type _Signal<T> = { get: Accessor<T>; set: Setter<T> };
export type Signal<T> = [Accessor<T>, Setter<T>];
export type Subscriber = { derived: _Signal<any> | null; execute: () => void };
12 changes: 6 additions & 6 deletions src/reactivity/utils/Subscriptions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Tree } from "./Tree";
import { TreeSet } from "./TreeSet";
import { Subscriber, Signal } from "../types";
import { Subscriber, _Signal } from "../types";

export class Subscriptions {
private currentSubscriber: Subscriber | null = null;
private derivations = new Tree<Signal<any>, Signal<any>>();
private subscriptions = new Tree<Signal<any>, Subscriber>();
private derivations = new Tree<_Signal<any>, _Signal<any>>();
private subscriptions = new Tree<_Signal<any>, Subscriber>();

run(subscriber: Subscriber, fn: () => void): void {
this.currentSubscriber = subscriber;
Expand All @@ -16,7 +16,7 @@ export class Subscriptions {
}
}

subscribeTo(signal: Signal<any>): void {
subscribeTo(signal: _Signal<any>): void {
const subscriber = this.currentSubscriber;
if (!signal || !subscriber || signal === subscriber.derived) {
return;
Expand All @@ -25,11 +25,11 @@ export class Subscriptions {
this.derivations.addTo(signal, subscriber.derived);
}

executeAllSubscriptionsTo(signal: Signal<any> | null) {
executeAllSubscriptionsTo(signal: _Signal<any> | null) {
this._subscriptionsTo(signal).forEach((subscriber) => subscriber.execute());
}

private _subscriptionsTo(signal: Signal<any> | null): TreeSet<Subscriber> {
private _subscriptionsTo(signal: _Signal<any> | null): TreeSet<Subscriber> {
if (!signal) {
return new TreeSet();
}
Expand Down

0 comments on commit 971d389

Please sign in to comment.