git.iko.soy/rowtype-yoga/psfp
on e68af4f help sign in
273 lines 8.5 kB history raw
1module PSLayout where
3import Prelude
5import Data.Array as A
6import Data.Array as Array
7import Data.Array.NonEmpty as NEA
8import Data.Function.Uncurried (mkFn2)
9import Data.Maybe (Maybe(..), fromMaybe, isJust)
10import Data.Nullable (Nullable, toMaybe)
11import Data.Nullable as Nullable
12import Data.String as String
13import Data.Tuple.Nested ((/\))
14import Debug.Trace (spy)
15import Effect (Effect)
16import JSS (jss, jssClasses)
17import Justifill (justifill)
18import Milkis.Impl (FetchImpl)
19import React.Basic (JSX, ReactComponent, fragment)
20import React.Basic.DOM (unsafeCreateDOMComponent)
21import React.Basic.DOM as R
22import React.Basic.Helpers (jsx)
23import React.Basic.Hooks (ReactChildren, component, componentWithChildren, element, reactChildrenToArray, useEffect, useState)
24import React.Basic.Hooks as React
25import Unsafe.Coerce (unsafeCoerce)
26import Yoga.Box.Component as Box
27import Yoga.CompileEditor.Component (mkCompileEditor)
28import Yoga.Compiler.Api (apiCompiler)
29import Yoga.Compiler.Types (Compiler)
30import Yoga.FillInTheGaps.Component as FillInTheGaps
31import Yoga.FillInTheGaps.Logic (complete, parseSegments)
32import Yoga.Header.Component (mkHeader)
33import Yoga.Helpers ((?||))
34import Yoga.InlineCode.Component as InlineCode
35import Yoga.Theme (fromTheme)
36import Yoga.Theme.CSSBaseline (mkCssBaseline)
37import Yoga.Theme.Default (darkTheme)
38import Yoga.Theme.Provider (mkThemeProvider)
39import Yoga.Theme.Styles (makeStylesJSS)
40import Yoga.Theme.Types (CSSTheme)
41import Yoga.Typography.Header (HeadingLevel(..), mkH)
42import Yoga.Typography.Paragraph (mkP)
43import Yoga.WithSidebar.Component (makeComponent) as WithSidebar
45type SiteQueryResult
46 = { site ∷
47 { siteMetadata ∷
48 { title ∷ String
49 , menuLinks ∷ Array { name ∷ String, link ∷ String }
50 }
51 }
52 }
54type PreProps
55 = { children ∷
56 Nullable
57 { props ∷
58 Nullable
59 { mdxType ∷ Nullable String
60 , children ∷ Nullable String
61 , className ∷ Nullable String
62 }
63 }
64 }
66mkLayout ∷
67 FetchImpl ->
68 Effect
69 ( ReactComponent
70 { children ∷ ReactChildren JSX
71 , siteInfo ∷ SiteQueryResult
72 }
73 )
74mkLayout fetchImpl = do
75 themeProvider <- mkThemeProvider
76 mdxProviderComponent <- mkMdxProviderComponent (apiCompiler fetchImpl)
77 componentWithChildren "MDXLayout" \{ children, siteInfo } -> React.do
78 pure
79 $ element themeProvider
80 { theme: fromTheme darkTheme
81 , children:
82 [ element mdxProviderComponent
83 { children
84 , siteInfo
85 }
86 ]
87 }
89mkSecret ∷ Effect (ReactComponent { kids ∷ Array JSX, visible ∷ Boolean, register ∷ Effect Unit })
90mkSecret = do
91 component "Secret" \{ kids, visible, register } -> React.do
92 useEffect visible do
93 unless visible register
94 pure mempty
95 pure
96 $ R.div
97 { style: R.css { visibility: if visible then "visible" else "hidden" }
98 , children: kids
99 }
101mkMdxProviderComponent ∷
102 ∀ r.
103 { | Compiler r } ->
104 Effect
105 ( ReactComponent
106 { children ∷ ReactChildren JSX
107 , siteInfo ∷ SiteQueryResult
108 }
109 )
110mkMdxProviderComponent compiler = do
111 cssBaseline <- mkCssBaseline
112 editor <- mkCompileEditor compiler
113 fillInTheGaps <- FillInTheGaps.makeComponent
114 box <- Box.makeComponent
115 sidebar <- mkSidebar
116 header <- mkHeader
117 yogaInlineCode <- InlineCode.makeComponent
118 h <- mkH
119 p <- mkP
120 secret <- mkSecret
121 useStyles <-
122 makeStylesJSS
123 $ jssClasses \(theme ∷ CSSTheme) ->
124 { code:
125 { fontFamily: theme.codeFontFamily # NEA.head
126 , backgroundColor: theme.interfaceColour
127 , fontSize: "10pt"
128 , border: "1px solid #383c39"
129 , padding: "3px"
130 , borderRadius: "3px"
131 }
132 , flexer:
133 { display: "flex"
134 , flexDirection: "row"
135 }
136 }
137 componentWithChildren "MDXProviderComponent" \{ children, siteInfo } -> React.do
138 classes <- useStyles {}
139 visibleThrough /\ updateVisible <- useState 1
140 let
141 baseline child = element cssBaseline { kids: child }
143 kids = reactChildrenToArray children
145 visibleKids =
146 TODO
147 siteInfoJSX =
148 R.div
149 { children:
150 [ jsx header { className: "" } [ R.text siteInfo.site.siteMetadata.title ]
151 , element sidebar { links: siteInfo.site.siteMetadata.menuLinks }
152 , jsx box {} visibleKids
153 ]
154 }
156 mdxComponents =
157 { h1:
158 \props ->
159 element h ({ level: H2, text: props.children, className: Nothing })
160 , h2:
161 \props ->
162 element h { level: H3, text: props.children, className: Nothing }
163 , h3:
164 \props ->
165 element h { level: H4, text: props.children, className: Nothing }
166 , hr: (const $ R.hr {})
167 , p:
168 \props ->
169 R.div
170 { children: [ element p { text: props.children } ]
171 }
172 , inlineCode:
173 \props -> do
174 R.span { className: classes.code, children: props.children }
175 , pre:
176 \(props ∷ PreProps) -> do
177 let
178 childrenQ = Nullable.toMaybe props.children
180 propsQ = (_.props >>> Nullable.toMaybe) =<< childrenQ
182 mdxTypeQ = (_.mdxType >>> Nullable.toMaybe) =<< propsQ
184 childrenQ2 = (_.children >>> Nullable.toMaybe) =<< propsQ
186 classNameQ = (_.className >>> Nullable.toMaybe) =<< propsQ
188 isCode = fromMaybe false (mdxTypeQ <#> eq "code")
190 codeQ = childrenQ2
192 height =
193 (fromMaybe 200 >>> show >>> (_ <> "px")) do
194 code <- codeQ
195 pure
196 ( String.split (String.Pattern "\n") code
197 # Array.length
198 # \x -> (x * 12) + 100
199 )
201 language = fromMaybe "" (classNameQ >>= String.stripPrefix (String.Pattern "language-"))
203 segmentsQ = parseSegments (codeQ ?|| "")
204 case isCode, language, segmentsQ of
205 true, "purescript", Just initialSegments ->
206 jsx box {}
207 [ element fillInTheGaps
208 { initialSegments
209 , update:
210 \segs ->
211 when (complete segs)
212 $ updateVisible
213 (\_ -> spy "setting key to" (unsafeCoerce props).key)
214 }
215 ]
216 true, _, _ ->
217 element editor
218 { initialCode: fromMaybe "" codeQ
219 , height
220 , language
221 }
222 false, _, _ -> element (unsafeCreateDOMComponent "pre") props
223 }
224 useEffect (A.length kids) do
225 let
226 firstGaps = kids # A.find (\x -> (unsafeCoerce x).props.mdxType == "pre" &&
227 ((unsafeCoerce x).props.children.props.className == "language-purescript") &&
228 ((unsafeCoerce x).props.children.props.mdxType == "code") &&
229 ((unsafeCoerce x).props.children.props.children # parseSegments # isJust)
230 ) <#> (\x -> spy "first boy" $ (unsafeCoerce x).key)
232 lastKey = kids # A.last # unsafeCoerce # _.key
233 updateVisible (const (firstGaps ?|| lastKey))
234 pure mempty
235 pure
236 $ baseline
237 [ element mdxProvider
238 { children:
239 [ siteInfoJSX
240 ]
241 , components: mdxComponents
242 }
243 ]
245mkSidebar = do
246 withSidebar <- WithSidebar.makeComponent
247 useStyles <-
248 makeStylesJSS
249 $ jssClasses \(theme ∷ CSSTheme) ->
250 { flexer:
251 jss
252 { display: "flex"
253 , flexDirection: "row"
254 , width: "300px"
255 , height: "300px"
256 }
257 }
258 component "Sidebar" \{ links } -> React.do
259 classes <- useStyles {}
260 pure
261 $ element withSidebar
262 ( justifill
263 { sidebarChildren: [ R.div_ [ R.text "hahahaha" ] ]
264 , notSidebarChildren: [] ∷ Array JSX
265 }
266 )
268foreign import mdxProvider ∷
269 ∀ r.
270 ReactComponent
271 { components ∷ { | r } -- TODO Don't lie
272 , children ∷ Array JSX
273 }