-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathApp.fs
158 lines (118 loc) · 4.42 KB
/
App.fs
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
module App
open System
open Fable.Core
open Feliz
open Fable.React
open Elmish
JsInterop.importSideEffects "@fontsource/roboto/300.css"
JsInterop.importSideEffects "@fontsource/roboto/400.css"
JsInterop.importSideEffects "@fontsource/roboto/500.css"
JsInterop.importSideEffects "@fontsource/roboto/700.css"
[<Import("createTheme", from = "@mui/material/styles")>]
let createTheme (theme: obj) : obj = jsNative
let theme = createTheme {|
palette = {|
primary = {| main = "#63C2C8" |}
|}
|}
[<Erase>]
type Mui =
[<ReactComponent(import="default", from="@mui/material/Button")>]
static member Button(?children: string, ?color: string, ?onClick: unit -> unit) : ReactElement = jsNative
[<ReactComponent(import="default", from="@mui/material/Typography")>]
static member Typography(?children: string, ?variant: string): ReactElement = jsNative
module private Components =
open Elmish
open Fable.React
open Utils
module TextField =
type State = string
type Msg = | Update of string | Clear
let init () = "", Cmd.none
let update dispatch msg state =
match msg with
| Clear -> "", Cmd.none
| Update s ->
printfn $"received an update: {s}"
// calling parent dispatch
s |> dispatch
s, Cmd.none
[<JSX.Component>]
let TextField (props: {| label : string; text : string; dispatch : string -> unit |}) =
let theme = Mui.useTheme ()
let (someText, setSomeText) = React.useState props.text
let state, dispatch = React.useElmish(TextField.init, TextField.update props.dispatch)
let applySetText s =
s |> TextField.Update |> dispatch
s |> setSomeText
JSX.jsx
$"""
import * from 'react';
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import Stack from '@mui/material/Stack';
<React.Fragment>
<TextField
sx={ {| marginTop = theme.spacing 3 |} }
variant="standard" label={props.label} color="warning"
value={someText} onChange={OnChange.value >> applySetText}> </TextField>
</React.Fragment>
"""
[<ReactComponent>]
let Counter (props: {| title: string; dispatch : int -> unit |}) =
let (count, setCount) = React.useState 0
React.fragment [
Mui.Typography(props.title, variant="h1")
Mui.Typography($"You clicked {count} times")
Mui.Button("Click me", onClick = fun _ -> setCount(count + 1))
]
[<ReactComponent(import="ApplicationBar", from="./ApplicationBar.jsx")>]
let AppBar(): ReactElement = jsNative
module private Root =
type State = { Text : string; Count : int }
type Msg = | TextUpdate of string | CountUpdate of int
let init () =
{ Text = ""; Count = 0 }, Cmd.none
let update msg state =
printfn "running Root update"
match msg with
| TextUpdate s -> { state with Text = s }, Cmd.none
| CountUpdate c -> { state with Count = c }, Cmd. none
[<JSX.Component>]
let Root () =
let state, dispatch = React.useElmish(Root.init, Root.update)
printfn $"root state is now: {state}"
JSX.jsx
$"""
import {{ ThemeProvider}} from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import React from "react";
import Stack from '@mui/material/Stack';
import Container from '@mui/material/Container';
<React.StrictMode>
<ThemeProvider theme={theme}>
<CssBaseline/>
<Container>
{Components.AppBar()}
<Stack>
<Box>
{
Components.Counter
{| title = "Counter"; dispatch = ignore |}
}
</Box>
<Box>
{
Components.TextField
{| label = "Textfield"; text = ""; dispatch = ignore |}
}
</Box>
</Stack>
</Container>
</ThemeProvider>
</React.StrictMode>
"""
open Browser.Dom
document.getElementById "root"
|> ReactDOM.createRoot
|> fun r -> r.render (Root() |> unbox)