Skip to content

Commit

Permalink
Merge pull request #111 from funkia/new-component-function
Browse files Browse the repository at this point in the history
New component function, refactor TodoMVC
  • Loading branch information
paldepind authored Aug 24, 2019
2 parents 68f6039 + b907935 commit f651b1c
Show file tree
Hide file tree
Showing 15 changed files with 603 additions and 699 deletions.
56 changes: 22 additions & 34 deletions examples/counters/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
import { Behavior, combine, stepper, Stream } from "@funkia/hareactive";
import { Behavior, stepper, Stream } from "@funkia/hareactive";
import { go } from "@funkia/jabz";
import { elements, fgo, modelView, runComponent } from "../../../src";
import { elements, fgo, runComponent, view, component } from "../../../src";
import { main1 } from "./version1";
import { main2 } from "./version2";
import { main3 } from "./version3";
import { counterList as main4 } from "./version4";
import { main4 } from "./version4";

const { button, div } = elements;

const numberToApp = {
"1": main1,
"2": main2,
"3": main3,
"4": main4
};
const numberToApp = { "1": main1, "2": main2, "3": main3, "4": main4 };

type AppId = keyof (typeof numberToApp);

function selectorButton(n: AppId, selected: Behavior<AppId>) {
return button(
{
class: ["btn btn-default", { active: selected.map((m) => n === m) }]
},
`Version ${n}`
).map(({ click }) => ({
select: click.mapTo(n)
}));
}
const selectorButton = (n: AppId, selected: Behavior<AppId>) =>
view(
button(
{
class: ["btn btn-default", { active: selected.map((m) => n === m) }]
},
`Version ${n}`
).output((o) => ({ selectVersion: o.click.mapTo(n).log(n) }))
);

type FromView = {
selectVersion: Stream<AppId>;
Expand All @@ -36,26 +30,20 @@ type FromModel = {
selected: Behavior<AppId>;
};

const versionSelector = modelView<FromModel, FromView>(
const versionSelector = component<FromView, FromModel>(
fgo(function*({ selectVersion }) {
const selected = yield stepper("1", selectVersion);
return { selected };
}),
({ selected }) =>
div({ class: "btn-group" }, [
selectorButton("1", selected).output({ select1: "select" }),
selectorButton("2", selected).output({ select2: "select" }),
selectorButton("3", selected).output({ select3: "select" }),
selectorButton("4", selected).output({ select4: "select" })
])
.map((o) => ({
selectVersion: combine(o.select1, o.select2, o.select3, o.select4)
}))
.output({ selectVersion: "selectVersion" })
return div({ class: "btn-group" }, [
selectorButton("1", selected).output({ selectVersion: "selectVersion" }),
selectorButton("2", selected).output({ selectVersion: "selectVersion" }),
selectorButton("3", selected).output({ selectVersion: "selectVersion" }),
selectorButton("4", selected).output({ selectVersion: "selectVersion" })
]).result({ selected });
})
);

const main = go(function*() {
const { selected } = yield versionSelector();
const { selected } = yield versionSelector.output({ selected: "selected" });
const currentApp = selected.map((n: AppId) => numberToApp[n]);
yield div(currentApp);
return {};
Expand Down
55 changes: 23 additions & 32 deletions examples/counters/src/version2.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,32 @@
import { Behavior, accum, Stream, combine } from "@funkia/hareactive";
import { elements, modelView, fgo } from "../../../src";
import { elements, fgo, component } from "../../../src";
const { div, button } = elements;

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

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

const counterModel = fgo(function*({
incrementClick,
decrementClick
}: CounterModelInput) {
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);
return { count };
});

const counterView = ({ count }: CounterViewInput) =>
div([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").output({
incrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, " - ").output({
decrementClick: "click"
})
]);
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 = modelView(counterModel, counterView);
return div([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").output({
incrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, " - ").output({
decrementClick: "click"
})
]);
})
);

export const main2 = counter();
export const main2 = counter;
108 changes: 44 additions & 64 deletions examples/counters/src/version3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import {
Behavior,
combine,
map,
Now,
accum,
scan,
Stream
} from "@funkia/hareactive";

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

const add = (n: number, m: number) => n + m;
Expand All @@ -19,76 +18,57 @@ type CounterModelInput = {
decrementClick: Stream<any>;
};

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

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

const counterModel = fgo(function*({
incrementClick,
decrementClick
}: CounterModelInput): ModelReturn<CounterViewInput> {
const increment = incrementClick.mapTo(1);
const decrement = decrementClick.mapTo(-1);
const count = yield accum(add, 0, combine(increment, decrement));
return { count };
});
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));

const counterView = ({ count }: CounterViewInput) =>
div([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").output({
incrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, " - ").output({
decrementClick: "click"
return div([
"Counter ",
count,
" ",
button({ class: "btn btn-default" }, " + ").output({
incrementClick: "click"
}),
" ",
button({ class: "btn btn-default" }, " - ").output({
decrementClick: "click"
})
]).result({ count });
})
]);

const counter = modelView(counterModel, counterView);

type ViewInput = {
counterIds: Behavior<number[]>;
sum: Behavior<number>;
};
);

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

const counterListModel = fgo(function*({
addCounter,
listOut
}: ModelInput): Iterator<Now<any>> {
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 { counterIds };
});

const counterListView = ({ sum, counterIds }: ViewInput) => [
h1("Counters"),
button({ class: "btn btn-primary" }, "Add counter").output({
addCounter: "click"
}),
br,
ul(list(counter, counterIds).output((o) => ({ listOut: o })))
];

const counterList = modelView(counterListModel, counterListView);
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").output({
addCounter: "click"
}),
br,
ul(list(counter, counterIds))
];
})
);

export const main3 = counterList();
export const main3 = counterList;
Loading

0 comments on commit f651b1c

Please sign in to comment.