git.iko.soy/rowtype-yoga/psfp
on 659e174 help sign in
rowtype-yoga/psfp/blog/src/components/FillInTheGaps.purs
54 lines 2.2 kB history raw
1module FillInTheGaps where
3import Prelude
5import Data.Array as A
6import Data.Maybe (Maybe(..), fromMaybe)
7import Data.String (Pattern(..), split)
8import Data.Tuple.Nested ((/\))
9import Effect (Effect)
10import Effect.Unsafe (unsafePerformEffect)
11import Justifill (justifill)
12import Partial.Unsafe (unsafeCrashWith)
13import React.Basic (JSX, ReactComponent, element)
14import React.Basic.DOM as R
15import React.Basic.Hooks (ReactChildren, componentWithChildren, reactChildrenToArray, useState)
16import React.Basic.Hooks as React
17import Yoga.InlineCode.Component as InlineCode
19data Segment = Filler String | Hole String
21renderSegments :: ReactComponent InlineCode.Props -> ((Array (Array Segment) -> Array (Array Segment)) -> Effect Unit) -> Array (Array Segment) -> JSX
22renderSegments ic update arrs = R.div_ (arrs `flip A.mapWithIndex` renderLine)
23 where
24 renderLine i l = R.div_ (l `flip A.mapWithIndex` renderSegment i)
25 renderSegment i j = case _ of
26 Filler s -> R.span_ [R.text s]
27 Hole _ -> element ic $ justifill { onSubmit: \s -> update (updateSegments i j s) }
29updateSegments :: Int -> Int -> String -> Array (Array Segment) -> Array (Array Segment)
30updateSegments i j v arrs = fromMaybe [] (A.modifyAt i (updateLine j v) arrs)
32updateLine :: Int -> String -> Array Segment -> Array Segment
33updateLine idx v arr = fromMaybe [] (A.modifyAt idx f arr)
34 where
35 f = case _ of
36 Filler s -> unsafeCrashWith "Updated a filler"
37 Hole _ -> Hole v
40fillInTheGaps :: ReactComponent { children :: ReactChildren String }
41fillInTheGaps = unsafePerformEffect do
42 ic <- InlineCode.makeComponent
43 componentWithChildren "InlineCodeWithChildren" \{ children } -> React.do
44 let
45 separator = "???"
46 child = children # reactChildrenToArray # A.head # fromMaybe "gurki"
47 lines = split (Pattern "\n") child
48 rawSegments = split (Pattern separator)
49 toSegment = case _ of
50 x | x == separator -> Hole ""
51 other -> Filler other
52 initialSegments = lines <#> \line -> rawSegments line <#> toSegment
53 (segments :: Array (Array Segment)) /\ modifySegments <- useState initialSegments
54 pure $ renderSegments ic (modifySegments) segments