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