@@ -1,13 +1,15 @@
1module Yoga.Editor where
1module Yoga.Editor where
3import Prelude
3import Prelude
4−import CSS (borderBox, borderRadius, boxSizing, calc, margin, padding, pct, px, toHexString, unitless, width)
4+import CSS (borderBox, borderRadius, boxSizing, margin, padding, pct, px, unitless, width)
5import CSS.Overflow (hidden, overflowY)
5import CSS.Overflow (hidden, overflowY)
6import Control.Promise (Promise)
6import Control.Promise (Promise)
7import Control.Promise as Promise
7import Control.Promise as Promise
8−import Data.Foldable (for_)
8+import Data.Foldable (fold, foldMap, for_)
9import Data.Maybe (Maybe(..), maybe)
9import Data.Maybe (Maybe(..), maybe)
10+import Data.Monoid (guard)
10−import Data.Nullable (Nullable)
11+import Data.Nullable (Nullable, notNull, null)
12+import Data.Time.Duration (Seconds(..))
11import Data.Tuple.Nested ((/\))
13import Data.Tuple.Nested ((/\))
12import Effect (Effect)
14import Effect (Effect)
13import Effect.Aff (Aff)
15import Effect.Aff (Aff)
@@ -19,16 +21,14 @@ import JSS (jssClasses)
19import Prim.Row (class Union)
21import Prim.Row (class Union)
20import React.Basic (JSX, ReactComponent, Ref, element, fragment)
22import React.Basic (JSX, ReactComponent, Ref, element, fragment)
21import React.Basic.DOM as R
23import React.Basic.DOM as R
22−import React.Basic.Emotion (var)
23−import React.Basic.Hooks (reactComponent, useEffect, useState)
24+import React.Basic.Hooks (reactComponent, useEffect, useEffectAlways, useState)
24import React.Basic.Hooks as React
25import React.Basic.Hooks as React
25import React.Basic.Hooks.Aff (useAff)
26import React.Basic.Hooks.Aff (useAff)
26import Web.DOM (Node)
27import Web.DOM (Node)
27import Web.HTML (HTMLElement)
28import Web.HTML (HTMLElement)
28−import Yoga.Theme (fromTheme)
29+import Yoga.Block.Container.Style (DarkOrLightMode(..), getDarkOrLightMode)
29−import Yoga.Theme.Default (darkTheme)
30+import Yoga.Block.Hook.UseResize (useOnResize)
30import Yoga.Theme.Styles (makeStylesJSS)
31import Yoga.Theme.Styles (makeStylesJSS)
31−import Yoga.Theme.Types (CSSTheme)
33type EditorProps =
33type EditorProps =
34 ( value ∷ String
34 ( value ∷ String
@@ -52,7 +52,7 @@ foreign import setThemeImpl ∷ Monaco -> String -> Effect Unit
53foreign import nightOwlTheme ∷ String -> MonacoTheme
53foreign import nightOwlTheme ∷ String -> MonacoTheme
55−foreign import vsCodeTheme ∷ String -> MonacoTheme
55+foreign import horizonTheme ∷ String -> MonacoTheme
57foreign import getValue ∷ Editor -> Effect String
57foreign import getValue ∷ Editor -> Effect String
@@ -60,6 +60,8 @@ foreign import setValue ∷ String -> Editor -> Effect Unit
61foreign import colorizeImpl ∷ String -> String -> { tabSize ∷ Int } -> Editor -> Promise String
61foreign import colorizeImpl ∷ String -> String -> { tabSize ∷ Int } -> Editor -> Promise String
63+foreign import layout ∷ Editor -> Effect Unit
63foreign import data Monaco ∷ Type
65foreign import data Monaco ∷ Type
65foreign import data Editor ∷ Type
67foreign import data Editor ∷ Type
@@ -75,7 +77,7 @@ darkThemeName ∷ String
75darkThemeName = "NightOwl"
77darkThemeName = "NightOwl"
77lightThemeName ∷ String
79lightThemeName ∷ String
78−lightThemeName = "VSCode"
80+lightThemeName = "Horizon"
80foreign import data MonarchLanguage ∷ Type
82foreign import data MonarchLanguage ∷ Type
@@ -85,10 +87,10 @@ foreign import registerLanguageImpl ∷ Monaco -> String -> Effect Unit
86foreign import setMonarchTokensProviderImpl ∷ Monaco -> String -> MonarchLanguage -> Effect Unit
88foreign import setMonarchTokensProviderImpl ∷ Monaco -> String -> MonarchLanguage -> Effect Unit
88−initEditor ∷ CSSTheme -> Monaco -> Effect Unit
90+initEditor ∷ Monaco -> Effect Unit
89−initEditor theme monaco = do
91+initEditor monaco = do
90− defineThemeImpl monaco darkThemeName (nightOwlTheme (toHexString theme.backgroundColour))
92+ defineThemeImpl monaco darkThemeName (nightOwlTheme "#212134") -- [TODO] Read from somewhere else
91− defineThemeImpl monaco lightThemeName (vsCodeTheme (toHexString theme.backgroundColour))
93+ defineThemeImpl monaco lightThemeName (horizonTheme "#EBDFDE") -- [TODO] Don't hardcode
92 registerLanguageImpl monaco "purescript"
94 registerLanguageImpl monaco "purescript"
93 setMonarchTokensProviderImpl monaco "purescript" purescriptSyntax
95 setMonarchTokensProviderImpl monaco "purescript" purescriptSyntax
@@ -111,26 +113,35 @@ mkEditor = do
111 padding (4.0 # px) (8.0 # px) (0.0 # px) (8.0 # px)
113 padding (4.0 # px) (8.0 # px) (0.0 # px) (8.0 # px)
112 width (100.0 # pct)
114 width (100.0 # pct)
113 overflowY hidden
115 overflowY hidden
114− -- backgroundColor (colour.background) [TODO]
116+ -- backgroundColor (colour.background) [ TODO ]
116 reactComponent "Editor" \{ onLoad, height, language } -> React.do
118 reactComponent "Editor" \{ onLoad, height, language } -> React.do
117 classes <- useStyles {}
119 classes <- useStyles {}
118− maybeEditor /\ modifyEditor <- useState Nothing
120+ mbEditorComponent /\ setEditorComponent <- React.useState' Nothing
119− maybeMonaco /\ modifyMonaco <- useState Nothing
121+ monacoRef <- React.useRef null
122+ editorRef <- React.useRef null
123+ useOnResize (3.0 # Seconds) \_ -> do
124+ mbEditor <- React.readRefMaybe editorRef
125+ for_ mbEditor layout
120 useAff unit do
126 useAff unit do
121− eddy <- monacoEditor
127+ med <- monacoEditor
122− liftEffect $ modifyEditor (const (Just eddy))
128+ setEditorComponent (Just med) # liftEffect
123− useEffect unit do -- [TODO] notice theme change
129+ useEffectAlways do
124− for_ maybeMonaco (initEditor (fromTheme darkTheme))
130+ mbMode <- getDarkOrLightMode
131+ mbMonaco <- React.readRefMaybe monacoRef
132+ case mbMode, mbMonaco of
133+ Just DarkMode, Just monaco -> setThemeImpl monaco darkThemeName
134+ Just LightMode, Just monaco -> setThemeImpl monaco lightThemeName
125− pure mempty
136+ mempty
126 let themeName = darkThemeName
137 let themeName = darkThemeName
128 $ fragment
139 $ fragment
130 { className: classes.wrapper
141 { className: classes.wrapper
131 , children:
142 , children:
132− [ maybeEditor
143+ [ mbEditorComponent
133− # maybe mempty \editor ->
144+ # foldMap \editor ->
134 element editor
145 element editor
135 { theme: themeName
146 { theme: themeName
@@ -154,11 +165,14 @@ mkEditor = do
155 , language
166 , language
156 -- https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
167 -- https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
157− , editorDidMount: mkEffectFn2 \e _ -> onLoad e
168+ , editorDidMount:
169+ mkEffectFn2 \e _ -> do
170+ React.writeRef editorRef (notNull e)
158 , editorWillMount:
172 , editorWillMount:
159 mkEffectFn1 \m -> do
173 mkEffectFn1 \m -> do
160− modifyMonaco (const $ Just m)
174+ React.writeRef monacoRef (notNull m)
161− (initEditor (fromTheme darkTheme) m)
175+ initEditor m