Reason React Native Styled System (Beta)
-
-
Save hew/3d2b8c00b62e58fd45fb73fefc71d203 to your computer and use it in GitHub Desktop.
[@bs.module "react-native-responsive-fontsize"] | |
external rf: float => float = "default"; | |
module type Config = {let scale: array(int);}; | |
module TextMaker = (Config: Config) => { | |
open Belt.Option; | |
let systemize = shorthand => | |
shorthand->mapWithDefault(0, m => | |
switch (m) { | |
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 => Config.scale[m] | |
| _ => m | |
} | |
) | |
|> float_of_int; | |
let systemizeFont = v => | |
v->mapWithDefault(16, m => | |
switch (m) { | |
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 => Config.scale[m] | |
| _ => m | |
} | |
) | |
|> float_of_int; | |
let systemizeSize = v => v |> systemize |> Style.Size.pct; | |
let systemizeMargin = v => v |> systemize |> Style.Margin.pct; | |
[@react.component] | |
let make = | |
( | |
~py=?, | |
~px=?, | |
~p=?, | |
~mt=?, | |
~mb=?, | |
~ml=?, | |
~mr=?, | |
~size=?, | |
~style as styl: Style.t=?, | |
~color as clr=?, | |
~weight=?, | |
~align=?, | |
~children, | |
(), | |
) => | |
<Text | |
style=Style.( | |
listOption([ | |
mt->isSome | |
? Some(style(~marginTop=systemizeMargin(mt), ())) : None, | |
mb->isSome | |
? Some(style(~marginBottom=systemizeMargin(mb), ())) : None, | |
ml->isSome | |
? Some(style(~marginLeft=systemizeMargin(ml), ())) : None, | |
mr->isSome | |
? Some(style(~marginRight=systemizeMargin(mr), ())) : None, | |
p->isSome ? Some(style(~padding=systemizeSize(p), ())) : None, | |
py->isSome | |
? Some(style(~paddingTop=systemizeSize(py), ())) : None, | |
py->isSome | |
? Some(style(~paddingBottom=systemizeSize(py), ())) : None, | |
px->isSome | |
? Some(style(~paddingLeft=systemizeSize(px), ())) : None, | |
px->isSome | |
? Some(style(~paddingRight=systemizeSize(px), ())) : None, | |
size->isSome | |
? Some(style(~fontSize=systemizeFont(size), ())) : None, | |
clr->isSome | |
? Some( | |
style( | |
~color=clr->mapWithDefault("black", v => v) |> color, | |
(), | |
), | |
) | |
: None, | |
weight->isSome | |
? Some( | |
style( | |
~fontWeight=weight->mapWithDefault(`normal, w => w), | |
(), | |
), | |
) | |
: None, | |
align->isSome | |
? Some( | |
style(~textAlign=align->mapWithDefault(`center, w => w), ()), | |
) | |
: None, | |
Some(styl), | |
]) | |
)> | |
children | |
</Text>; | |
}; | |
module BoxMaker = (Config: Config) => { | |
open Belt.Option; | |
let systemize = shorthand => | |
shorthand->mapWithDefault(0, m => | |
switch (m) { | |
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 => Config.scale[m] | |
| _ => m | |
} | |
) | |
|> float_of_int; | |
let systemizeSize = v => v |> systemize |> rf |> Style.Size.pt; | |
let systemizeMargin = v => v |> systemize |> rf |> Style.Margin.pt; | |
[@react.component] | |
let make = | |
( | |
~py=?, | |
~px=?, | |
~p=?, | |
~mt=?, | |
~mb=?, | |
~ml=?, | |
~mr=?, | |
~bgColor=?, | |
~width=?, | |
~flex=?, | |
~content=?, | |
~direction=?, | |
~style as styl: Style.t=?, | |
~children=?, | |
(), | |
) => | |
<View | |
style=Style.( | |
listOption([ | |
mt->isSome | |
? Some(style(~marginTop=systemizeMargin(mt), ())) : None, | |
mb->isSome | |
? Some(style(~marginBottom=systemizeMargin(mb), ())) : None, | |
ml->isSome | |
? Some(style(~marginLeft=systemizeMargin(ml), ())) : None, | |
mr->isSome | |
? Some(style(~marginRight=systemizeMargin(mr), ())) : None, | |
p->isSome ? Some(style(~padding=systemizeSize(p), ())) : None, | |
py->isSome | |
? Some(style(~paddingTop=systemizeSize(py), ())) : None, | |
py->isSome | |
? Some(style(~paddingBottom=systemizeSize(py), ())) : None, | |
px->isSome | |
? Some(style(~paddingLeft=systemizeSize(px), ())) : None, | |
px->isSome | |
? Some(style(~paddingRight=systemizeSize(px), ())) : None, | |
width->isSome | |
? Some( | |
style( | |
~width=width->mapWithDefault(100., v => v) |> Size.pct, | |
(), | |
), | |
) | |
: None, | |
bgColor->isSome | |
? Some( | |
style( | |
~backgroundColor= | |
bgColor->mapWithDefault("black", v => v) |> color, | |
(), | |
), | |
) | |
: None, | |
content->isSome | |
? Some( | |
style( | |
~justifyContent=content->mapWithDefault(`flexStart, w => w), | |
(), | |
), | |
) | |
: None, | |
direction->isSome | |
? Some( | |
style( | |
~flexDirection=direction->mapWithDefault(`column, w => w), | |
(), | |
), | |
) | |
: None, | |
flex->isSome | |
? Some(style(~flex=flex->mapWithDefault(1., w => w), ())) : None, | |
Some(styl), | |
]) | |
)> | |
{switch (children) { | |
| Some(child) => child | |
| None => React.null | |
}} | |
</View>; | |
}; | |
module Box = | |
BoxMaker({ | |
let scale = System.Scale.space; | |
}); | |
module Txt = | |
TextMaker({ | |
let scale = System.Scale.font; | |
}); |
@hew Yes, this flag is sometimes used to 'overlay' a new set of standard modules on top of the built-in ones that are available in OCaml. Typically it's desirable to open
modules which will have as little effect on the global namespace as possible. So, open Belt
is not too bad because it brings a small number of top-level modules into scope (as seen in https://bucklescript.github.io/bucklescript/api/Belt.html ). But open Belt.Option
is a bit more frowned on because it will bring a large number of functions into scope. And at module scope it will pollute your namespace with lots of names. The more this is done, the harder it is to track where names are coming from and you have to keep referring to other parts of the code when you're reading some function, to figure it out.
I think I understand now. the global open only adds like 4 more things to the namespace, but Belt.Option
has a bunch of functions, and opening it floods any given namespace with all of them. I'll default to something like let Opt = Belt.Option in the future.
@yawaramin
Slightly off topic, but I sometimes see a flag in other people's bsconfig that is something to the effect of "-belt-open" and I always assumed it made Belt essentially globally available. Have you ever heard of that flag?