Skip to content

Commit

Permalink
component function passes start as parameter, update examples accordi…
Browse files Browse the repository at this point in the history
…ngly
  • Loading branch information
paldepind committed Aug 28, 2019
1 parent 9ce9121 commit d8fc066
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 387 deletions.
34 changes: 15 additions & 19 deletions examples/counters/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,30 @@ const selectorButton = (n: AppId, selected: Behavior<AppId>) =>
class: ["btn btn-default", { active: selected.map((m) => n === m) }]
},
`Version ${n}`
).use((o) => ({ selectVersion: o.click.mapTo(n).log(n) }))
).use((o) => ({ selectVersion: o.click.mapTo(n) }))
);

type FromView = {
type On = {
selectVersion: Stream<AppId>;
};

type FromModel = {
selected: Behavior<AppId>;
};

const versionSelector = component<FromView, FromModel>(
fgo(function*({ selectVersion }) {
const selected = yield stepper("1", selectVersion);
return div({ class: "btn-group" }, [
selectorButton("1", selected).use({ selectVersion: "selectVersion" }),
selectorButton("2", selected).use({ selectVersion: "selectVersion" }),
selectorButton("3", selected).use({ selectVersion: "selectVersion" }),
selectorButton("4", selected).use({ selectVersion: "selectVersion" })
]).output({ selected });
})
);

const main = go(function*() {
const { selected } = yield versionSelector.use({ selected: "selected" });
const currentApp = selected.map((n: AppId) => numberToApp[n]);
yield div(currentApp);
return {};
const versionSelector = component<On, FromModel>((on, start) => {
const selected = start(stepper("1", on.selectVersion));
return div({ class: "btn-group" }, [
selectorButton("1", selected).use({ selectVersion: "selectVersion" }),
selectorButton("2", selected).use({ selectVersion: "selectVersion" }),
selectorButton("3", selected).use({ selectVersion: "selectVersion" }),
selectorButton("4", selected).use({ selectVersion: "selectVersion" })
]).output({ selected });
});

const main = component<FromModel>((on) => {
const currentApp = on.selected.map((n: AppId) => numberToApp[n]);
return [versionSelector.use({ selected: "selected" }), div(currentApp)];
});

runComponent("#mount", main);
42 changes: 20 additions & 22 deletions examples/counters/src/version2.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,30 @@
import { Behavior, accum, Stream, combine } from "@funkia/hareactive";
import { elements, fgo, component } from "../../../src";
import { accum, Stream, combine } from "@funkia/hareactive";
import { elements, component } from "../../../src";
const { div, button } = elements;

type On = {
incrementClick: Stream<any>;
decrementClick: Stream<any>;
};

const counter = component<On>(
fgo(function*({ incrementClick, decrementClick }) {
const increment = incrementClick.mapTo(1);
const decrement = decrementClick.mapTo(-1);
const changes = combine(increment, decrement);
const count = yield accum((n, m) => n + m, 0, changes);
const counter = component<On>((on, start) => {
const increment = on.incrementClick.mapTo(1);
const decrement = on.decrementClick.mapTo(-1);
const changes = combine(increment, decrement);
const count = start(accum((n, m) => n + m, 0, changes));

return div([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").use({
incrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, " - ").use({
decrementClick: "click"
})
]);
})
);
return div([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").use({
incrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, " - ").use({
decrementClick: "click"
})
]);
});

export const main2 = counter;
92 changes: 37 additions & 55 deletions examples/counters/src/version3.ts
Original file line number Diff line number Diff line change
@@ -1,74 +1,56 @@
import {
Behavior,
combine,
map,
accum,
scan,
Stream
} from "@funkia/hareactive";
import { Behavior, map, accum, scan, Stream } from "@funkia/hareactive";

import { elements, fgo, list, component } from "../../../src";
const { br, div, button, h1, ul } = elements;
import { elements, list, component } from "../../../src";
const { br, li, button, h1, ul } = elements;

const add = (n: number, m: number) => n + m;
const apply = <A, B>(f: (a: A) => B, a: A) => f(a);

type CounterModelInput = {
incrementClick: Stream<any>;
decrementClick: Stream<any>;
type CounterOn = {
delta: Stream<number>;
};

type CounterOutput = {
count: Behavior<number>;
};

const counter = () =>
component<CounterModelInput, CounterOutput>(
fgo(function*(on) {
const increment = on.incrementClick.mapTo(1);
const decrement = on.decrementClick.mapTo(-1);
const count = yield accum(add, 0, combine(increment, decrement));

return div([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").use({
incrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, " - ").use({
decrementClick: "click"
})
]).output({ count });
})
);
component<CounterOn, CounterOutput>((on, start) => {
const count = start(accum(add, 0, on.delta));

return li([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").use((o) => ({
delta: o.click.mapTo(1)
})),
" ",
button({ class: "btn btn-default" }, " - ").use((o) => ({
delta: o.click.mapTo(-1)
}))
]).output({ count });
});

type ListOn = {
addCounter: Stream<Event>;
};

const counterList = component<ListOn>(
fgo(function*({ addCounter }) {
const nextId: Stream<number> = yield scan(add, 2, addCounter.mapTo(1));
const appendCounterFn = map(
(id) => (ids: number[]) => ids.concat([id]),
nextId
);
const counterIds = yield accum<(a: number[]) => number[], number[]>(
apply,
[0],
appendCounterFn
);
return [
h1("Counters"),
button({ class: "btn btn-primary" }, "Add counter").use({
addCounter: "click"
}),
br,
ul(list(counter, counterIds))
];
})
);
const counterList = component<ListOn>(({ addCounter }, start) => {
const nextId = start(scan(add, 2, addCounter.mapTo(1)));
const appendCounterFn = map(
(id) => (ids: number[]) => ids.concat([id]),
nextId
);
const counterIds = start(accum(apply, [0], appendCounterFn));
return [
h1("Counters"),
button({ class: "btn btn-primary" }, "Add counter").use({
addCounter: "click"
}),
br,
ul(list(counter, counterIds))
];
});

export const main3 = counterList;
118 changes: 52 additions & 66 deletions examples/counters/src/version4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
moment
} from "@funkia/hareactive";

import { list, elements, fgo, component } from "../../../src";
import { list, elements, component } from "../../../src";
const { ul, li, p, br, button, h1 } = elements;

const add = (n: number, m: number) => n + m;
Expand All @@ -21,8 +21,7 @@ const apply = <A>(f: (a: A) => A, a: A) => f(a);
type Id = number;

type CounterModelInput = {
incrementClick: Stream<any>;
decrementClick: Stream<any>;
delta: Stream<number>;
deleteClick: Stream<any>;
};

Expand All @@ -32,75 +31,62 @@ type CounterOutput = {
};

const counter = (id: Id) =>
component<CounterModelInput>(
fgo(function*({ incrementClick, decrementClick, deleteClick }) {
const increment = incrementClick.mapTo(1);
const decrement = decrementClick.mapTo(-1);
const deleteS = deleteClick.mapTo(id);
const count = yield accum(add, 0, combine(increment, decrement));
component<CounterModelInput, CounterOutput>((on, start) => {
const deleteS = on.deleteClick.mapTo(id);
const count = start(accum(add, 0, on.delta));

return li([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").use({
incrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, " - ").use({
decrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, "x").use({
deleteClick: "click"
})
]).output({ count, deleteS });
})
);
return li([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").use((o) => ({
delta: o.click.mapTo(1)
})),
" ",
button({ class: "btn btn-default" }, " - ").use((o) => ({
delta: o.click.mapTo(-1)
})),
" ",
button({ class: "btn btn-default" }, "x").use({
deleteClick: "click"
})
]).output({ count, deleteS });
});

type ToModel = {
addCounter: Stream<Event>;
listOut: Behavior<CounterOutput[]>;
};

const counterList = component<ToModel>(
fgo(function*({ addCounter, listOut }) {
const removeIdB = listOut.map((l) =>
l.length > 0 ? combine(...l.map((o) => o.deleteS)) : <Stream<number>>empty
);
const sum = moment((at) =>
at(listOut)
.map((t) => at(t.count))
.reduce(add, 0)
);
const removeCounterIdFn = shiftCurrent(removeIdB).map(
(id) => (arr: number[]) => arr.filter((i) => i !== id)
);
const nextId: Stream<number> = yield scan(add, 2, addCounter.mapTo(1));
const appendCounterFn = map(
(id) => (ids: Id[]) => ids.concat([id]),
nextId
);
const modifications = combine(appendCounterFn, removeCounterIdFn);
const counterIds: Behavior<number[]> = yield accum(
apply,
[0, 1, 2],
modifications
);
return [
h1("Counters"),
p(["Sum ", sum]),
button({ class: "btn btn-primary" }, "Add counter").use({
addCounter: "click"
}),
br,
ul(
list((n) => counter(n).use((o) => o), counterIds).use((o) => ({
listOut: o
}))
)
];
})
);
const counterList = component<ToModel>((on, start) => {
const removeIdB = on.listOut.map((l) =>
l.length > 0 ? combine(...l.map((o) => o.deleteS)) : <Stream<number>>empty
);
const sum = moment((at) =>
at(on.listOut)
.map((t) => at(t.count))
.reduce(add, 0)
);
const removeCounterIdFn = shiftCurrent(removeIdB).map(
(id) => (arr: number[]) => arr.filter((i) => i !== id)
);
const nextId = start(scan(add, 2, on.addCounter.mapTo(1)));
const appendCounterFn = map((id) => (ids: Id[]) => ids.concat([id]), nextId);
const modifications = combine(appendCounterFn, removeCounterIdFn);
const counterIds = start(accum(apply, [0, 1, 2], modifications));
return [
h1("Counters"),
p(["Sum ", sum]),
button({ class: "btn btn-primary" }, "Add counter").use({
addCounter: "click"
}),
br,
ul(
list((n) => counter(n).use((o) => o), counterIds).use((o) => ({
listOut: o
}))
)
];
});

export const main4 = counterList;
Loading

0 comments on commit d8fc066

Please sign in to comment.