Source file vue_component.ml
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
open Js_of_ocaml
open Js
open Mjs
(** ml types *)
type js_type =
| JString of string
| JObject of any
| JNumber of float
| JBoolean of bool
| JArray of any list
type prop_object = {
pr_default : js_type;
pr_required : bool option;
pr_validator : (string -> bool) option;
}
type prop_options =
| PrType of js_type
| PrTypeArray of js_type list
| PrObj of prop_object
type props_options = PrsArray of string list | PrsObj of (string * prop_options) list
module Internal = struct
class type prop_object_js = object
method type_ : (js_string t -> any t) callback readonly_prop
method default : any optdef readonly_prop
method required : bool t optdef readonly_prop
method validator : (js_string t -> bool t) callback optdef readonly_prop
end
class type ['data, 'all] component_arg = object
method template : js_string t optdef readonly_prop
method props : any optdef readonly_prop
method data : ('all t, unit -> 'data t) meth_callback optdef readonly_prop
method render : ('all t, any -> any) meth_callback optdef readonly_prop
method computed : ('all t, unit -> any optdef) meth_callback table optdef readonly_prop
method watch : ('all t, any -> any -> any) meth_callback table optdef readonly_prop
method methods : any table optdef readonly_prop
method mixins : any js_array t optdef readonly_prop
method extends : any optdef readonly_prop
method mounted : ('all t, unit) meth_callback optdef readonly_prop
method name : js_string t optdef readonly_prop
method components : ('data, 'all) component_arg t table optdef readonly_prop
end
type 'all vue_output = 'all t
class type ['data, 'all] vue_object = object
method component : js_string t -> ('data, 'all) component_arg t optdef -> 'all vue_output meth
method component_extend : js_string t -> ('data, 'all) component_arg t optdef -> 'all vue_output constr meth
end
let js_type_cs : (js_type -> (js_string t -> Unsafe.any t) callback) = function
| JString _ -> wrap_callback @@ Unsafe.global##_String
| JObject _ -> wrap_callback @@ Unsafe.global##_Object
| JNumber _ -> wrap_callback @@ Unsafe.global##_Number
| JBoolean _ -> wrap_callback @@ Unsafe.global##_Boolean
| JArray _ -> wrap_callback @@ Unsafe.global##_Array
let js_prop_obj {pr_default; pr_required; pr_validator} : prop_object_js t =
let default = match pr_default with
| JString s -> def @@ to_any (string s)
| JNumber f -> def @@ to_any (number_of_float f)
| JBoolean b -> def @@ to_any (bool b)
| JObject o -> def @@ to_any (wrap_callback (fun () -> o))
| JArray a -> def @@ to_any (wrap_callback (fun () -> of_list a)) in
object%js
val type_ = js_type_cs pr_default
val default = default
val required = optdef bool pr_required
val validator = optdef (fun v -> wrap_callback (fun s -> bool (v (to_string s)))) pr_validator
end
let make_prop = function
| PrType s -> to_any @@ js_type_cs s
| PrTypeArray a -> to_any @@ of_listf js_type_cs a
| PrObj o -> to_any @@ js_prop_obj o
let make_props = function
| PrsObj l ->
to_any @@ Table.make @@ List.map (fun (name, pr) -> name, make_prop pr) l
| PrsArray l ->
to_any (of_listf string l)
type ('data, 'all) component_args = {
template : string option;
props : props_options option;
data : ('all t -> 'data t) option ;
render : ('all t -> any -> any) option;
computed : ('all t -> any optdef) table_cons option;
watch : ('all t -> any -> any -> any) table_cons option;
methods : any table_cons option;
mixins : any list option;
extends : any option;
mounted : ('all t -> unit) option;
name : string option;
components : (top, top) component_arg t table_cons
}
let make_arg c : ('data, 'all) component_arg t =
object%js
val template = optdef string c.template
val props = optdef make_props c.props
val data = optdef (fun f -> wrap_meth_callback (fun d () -> f d)) c.data
val render = optdef wrap_meth_callback c.render
val computed = optdef (to_tablef (fun f -> wrap_meth_callback (fun d () -> f d))) c.computed
val watch = optdef (to_tablef wrap_meth_callback) c.watch
val methods = optdef to_table c.methods
val mixins = optdef of_list c.mixins
val extends = Optdef.option c.extends
val mounted = optdef wrap_meth_callback c.mounted
val name = optdef string c.name
val components = to_tablef_def coerce c.components
end
let make_arg_js ?template ?render ?props ?data ?computed ?methods ?watch ?mixins
?extends ?mounted ?name ?(components= L []) () =
make_arg {template; props; data; render; computed; watch; methods; mixins;
extends; mounted; name; components}
end
type ('data, 'all) component_args = ('data, 'all) Internal.component_args = {
template : string option;
props : props_options option;
data : ('all t -> 'data t) option ;
render : ('all t -> any -> any) option;
computed : ('all t -> any optdef) table_cons option;
watch : ('all t -> any -> any -> any) table_cons option;
methods : any table_cons option;
mixins : any list option;
extends : any option;
mounted : ('all t -> unit) option;
name : string option;
components : (top, top) Internal.component_arg t table_cons
}
let empty = {
template = None; props = None; data = None; render = None; computed = None;
watch = None; methods = None; mixins = None; extends = None; mounted = None;
name = None; components = L []
}
type 'a component = 'a Internal.vue_output
let make ?template ?render ?props ?data ?computed ?methods ?watch ?mixins
?extends ?mounted ?components name =
let arg = Internal.make_arg_js ?template ?render ?props ?data ?computed ?methods ?watch
?mixins ?extends ?mounted ?components () in
match extends, mixins with
| None, None ->
let v : ('data, 'all) Internal.vue_object t = Unsafe.global##._Vue in
v##component (string name) (def arg)
| _ ->
let v : ('data, 'all) Internal.vue_object t = Unsafe.global##._Vue in
let cs = v##component_extend (string name) (def arg) in
new%js cs
(** functors *)
module type Tables_S = sig
type all
val methods_t : any table
val watch_t : (all t -> any -> any -> any) table
val computed_t : (all t -> any optdef) table
val components_t : (top, top) Internal.component_arg t table
val add_method : string -> (all t -> 'a) -> unit
val add_method0 : string -> (all t -> 'a) -> unit
val add_method1 : string -> (all t -> 'a -> 'b) -> unit
val add_method2 : string -> (all t -> 'a -> 'b -> 'c) -> unit
val add_method3 : string -> (all t -> 'a -> 'b -> 'c -> 'd) -> unit
val add_method4 : string -> (all t -> 'a -> 'b -> 'c -> 'd -> 'e) -> unit
val add_watch : string -> (all t -> 'a -> 'a -> 'b) -> unit
val add_computed : string -> (all t -> 'a optdef) -> unit
val add_component : string -> ('a, 'b) Internal.component_arg t -> unit
val merge_lists_component :
?computed:(string * (all t -> any optdef)) list ->
?methods:(string * any) list ->
?watch:(string * (all t -> any -> any -> any)) list ->
?components:(string * (top, top) Internal.component_arg t) list ->
unit -> unit
end
module Tables(S : sig type all end) = struct
type all = S.all
let methods_t = Table.create ()
let watch_t = Table.create ()
let computed_t = Table.create ()
let components_t = Table.create ()
let add_method name m =
Table.add methods_t name (to_any (wrap_meth_callback m))
let add_method0 name m = add_method name m
let add_method1 name m = add_method name m
let add_method2 name m = add_method name m
let add_method3 name m = add_method name m
let add_method4 name m = add_method name m
let add_watch name w = Table.add watch_t name w
let add_computed name c = Table.add computed_t name c
let add_component name c = Table.add components_t name @@ coerce c
let merge_lists_component ?(computed=[]) ?(methods=[]) ?(watch=[]) ?(components=[]) () =
Table.add_list methods_t methods;
Table.add_list computed_t computed;
Table.add_list watch_t watch;
Table.add_list components_t components
end
module Make(S : sig
val name : string
val template : string option
val props : props_options option
type data
type all
end) = struct
include Tables(struct type all = S.all end)
let component : S.all component ref = ref (Unsafe.obj [||])
let load ?(export=true) ?(data: (all t -> S.data t) option) () =
component := make ?data ?template:S.template ?props:S.props
~methods:(T methods_t) ~watch:(T watch_t) ~computed:(T computed_t) S.name;
if export then Js.export S.name !component;
!component
let get () = !component
end