Repository navigation
Expand file tree
/
Copy pathindex.js
More file actions
127 lines (112 loc) · 3.42 KB
/
Copy pathindex.js
File metadata and controls
127 lines (112 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// @flow
import React from 'react'
import * as status from './status'
import { type Status } from './status'
export type Form<+T> = {
+initialStatus: Status<T>,
render(report: Status<T> => void): React$Element<any>
}
export function pure<A>(value: A): Form<A> {
return {
initialStatus: status.pure(value),
render: report => React.createElement(() => null)
}
}
export function map<A, B>(form: Form<A>, f: A => B): Form<B> {
return {
initialStatus: status.map(form.initialStatus, f),
render: report => form.render(s => report(status.map(s, f)))
}
}
export function filter<A>(form: Form<A>, predicate: A => bool): Form<A> {
return {
initialStatus: status.filter(form.initialStatus, predicate),
render: report => form.render(s => report(status.filter(s, predicate)))
}
}
export function optional<A>(form: Form<A>): Form<A | void> {
return {
initialStatus: status.optional(form.initialStatus),
render: report => form.render(s => report(status.optional(s)))
}
}
export function maybe<A>(form: Form<A>): Form<?A> {
return {
initialStatus: status.maybe(form.initialStatus),
render: report => form.render(s => report(status.maybe(s)))
}
}
export function array<Forms: Array<Form<any>>>(forms: Forms): Form<$TupleMap<Forms, <T>(Form<T>) => T>> {
return {
initialStatus: status.array(forms.map(f => f.initialStatus)),
render: report => <Ortharray forms={forms} report={report} />
}
}
export function object<Forms: { [name: string]: Form<any> }>(forms: Forms): Form<$ObjMap<Forms, <T>(Form<T>) => T>> {
return {
initialStatus: status.object(objectMap(forms, f => f.initialStatus)),
render: report => <Orthobject forms={forms} report={report} />
}
}
type ArrayProps<S> = {
forms: $TupleMap<S, <T>(T) => Form<T>>,
report: Status<S> => void
}
class Ortharray<S: Array<any>> extends React.Component<void, ArrayProps<S>, void> {
statuses: $TupleMap<S, <T>(T) => Status<T>>
constructor(props: ArrayProps<S>) {
super(props)
this.statuses = props.forms.map(f => f.initialStatus)
}
render() {
return <div>{
this.props.forms.map((form, idx) =>
React.cloneElement(form.render(this.report(idx)), { key: idx }))
}</div>
}
report = (idx: number) => (s: Status<any>) => {
this.statuses[idx] = s
this.props.report(status.array(this.statuses))
}
componentWillReceiveProps(props) {
this.statuses = props.forms.map(f => f.initialStatus)
}
}
type ObjectProps<S> = {
forms: $ObjMap<S, <T>(T) => Form<T>>,
report: Status<S> => void
}
class Orthobject<S: { [name: string]: any }> extends React.Component<void, ObjectProps<S>, void> {
statuses: $ObjMap<S, <T>(T) => Status<T>>
constructor(props: ObjectProps<S>) {
super(props)
this.statuses = objectMap(props.forms, f => f.initialStatus)
}
render() {
return <div>{
kvs(this.props.forms).map(([name, form]) =>
React.cloneElement(form.render(this.report(name)), { key: name }))
}</div>
}
report = (name: string) => (s: Status<any>) => {
this.statuses[name] = s
this.props.report(status.object(this.statuses))
}
componentWillReceiveProps(props) {
this.statuses = objectMap(props.forms, f => f.initialStatus)
}
}
function kvs(map) {
const result = []
for (const k in map) {
result.push([k, map[k]])
}
return result
}
function objectMap(obj, f): any {
const result = {}
for (const key in obj) {
result[key] = f(obj[key])
}
return result
}