mirror of
https://github.com/rowtype-yoga/psfp.git
synced 2024-09-11 16:25:36 +03:00
Remove autofocus
This commit is contained in:
parent
f2e3678bc9
commit
fb93bc9c94
@ -5,10 +5,8 @@ import Data.Array (intercalate)
|
||||
import Data.Either (Either(..))
|
||||
import Data.Foldable (for_)
|
||||
import Data.Maybe (Maybe(..))
|
||||
import Data.Monoid (guard)
|
||||
import Data.Tuple.Nested ((/\))
|
||||
import Data.TwoOrMore (twoOrMore)
|
||||
import Debug.Trace (spy)
|
||||
import Effect (Effect)
|
||||
import Effect.Aff (Error, launchAff_, message, try)
|
||||
import Effect.Class (liftEffect)
|
||||
@ -44,7 +42,7 @@ mkCompileEditor { compileAndRun } = do
|
||||
themeMode /\ setThemeMode <- React.useState' Nothing
|
||||
React.useEffectAlways do
|
||||
mode <- getDarkOrLightMode
|
||||
unless (mode == themeMode) do setThemeMode (spy "mode" mode)
|
||||
unless (mode == themeMode) do setThemeMode mode
|
||||
mempty
|
||||
let
|
||||
onLoad e = do
|
||||
|
@ -4,32 +4,28 @@ import Prelude
|
||||
import Color as Color
|
||||
import Data.Array as A
|
||||
import Data.Foldable (traverse_)
|
||||
import Data.Maybe (Maybe(..), fromMaybe, isJust)
|
||||
import Data.Maybe (Maybe(..), fromMaybe)
|
||||
import Effect (Effect)
|
||||
import Literals.Undefined (undefined)
|
||||
import Prim.Row (class Lacks)
|
||||
import React.Basic (JSX, ReactComponent, element, elementKeyed)
|
||||
import React.Basic.DOM as R
|
||||
import React.Basic.DOM.Events (preventDefault, targetValue)
|
||||
import React.Basic.Events (handler, handler_)
|
||||
import React.Basic.Hooks (reactComponent)
|
||||
import React.Basic.Hooks as React
|
||||
import React.Basic.SyntaxHighlighter.Component (mkHighlighterTheme, syntaxHighlighter)
|
||||
import Unsafe.Coerce (unsafeCoerce)
|
||||
import Yoga (el)
|
||||
import Yoga.Block as Block
|
||||
import Yoga.Block.Atom.Button.Types as ButtonType
|
||||
import Yoga.Block.Atom.CodeInput as CodeInput
|
||||
import Yoga.DOM.Hook (useFocus)
|
||||
import Yoga.FillInTheGaps.Logic (Segment(..), findFirstHoleIndex, holeToFiller, updateSegments)
|
||||
import Yoga.Helpers ((?||))
|
||||
|
||||
visibleRange ∷ Array (Array Segment) -> { end ∷ Int, start ∷ Int }
|
||||
visibleRange arr = { start, end }
|
||||
where
|
||||
start = A.findIndex (_ == [ Start ]) arr ?|| 0
|
||||
start = A.findIndex (_ == [ Start ]) arr ?|| 0
|
||||
|
||||
end = A.findIndex (_ == [ End ]) arr ?|| A.length arr
|
||||
end = A.findIndex (_ == [ End ]) arr ?|| A.length arr
|
||||
|
||||
mkSegment ∷
|
||||
∀ p.
|
||||
@ -48,13 +44,11 @@ mkSegment ∷
|
||||
)
|
||||
mkSegment =
|
||||
reactComponent "Segment" \{ update, maxLength, text, theKey, focusOnFirstRender } -> React.do
|
||||
focusRef <- useFocus
|
||||
pure
|
||||
$ elementKeyed CodeInput.component
|
||||
{ onChange: handler targetValue (traverse_ update)
|
||||
, maxLength
|
||||
, value: text
|
||||
, ref: if focusOnFirstRender then focusRef else (unsafeCoerce undefined)
|
||||
, key: theKey
|
||||
}
|
||||
|
||||
@ -69,34 +63,34 @@ renderSegments ∷
|
||||
((Array (Array Segment) -> Array (Array Segment)) -> Effect Unit) -> Array (Array Segment) -> JSX
|
||||
renderSegments segment update arrs = R.div_ (A.mapWithIndex renderLine arrs)
|
||||
where
|
||||
firstHoleIndex = findFirstHoleIndex arrs
|
||||
firstHoleIndex = findFirstHoleIndex arrs
|
||||
|
||||
{ start, end } = visibleRange arrs
|
||||
{ start, end } = visibleRange arrs
|
||||
|
||||
renderLine i l = R.div_ (A.mapWithIndex (renderSegment i) l)
|
||||
renderLine i l = R.div_ (A.mapWithIndex (renderSegment i) l)
|
||||
|
||||
renderSegment i j s = case s, between start end i of
|
||||
Filler s', true ->
|
||||
element
|
||||
syntaxHighlighter
|
||||
{ style:
|
||||
mkHighlighterTheme
|
||||
{ grey: Color.rgb 50 50 50
|
||||
, highlightColour: Color.hsl 30.0 0.5 0.4
|
||||
, textColour: Color.rgb 0 0 1
|
||||
}
|
||||
, language: "purescript"
|
||||
, children: s'
|
||||
}
|
||||
Hole maxLength text, true ->
|
||||
element segment
|
||||
{ maxLength
|
||||
, theKey: show i <> "," <> show j
|
||||
, update: update <<< updateSegments i j
|
||||
, text
|
||||
, focusOnFirstRender: (firstHoleIndex <#> \fh -> fh.i == i && fh.j == j) # fromMaybe false
|
||||
}
|
||||
_, _ -> mempty
|
||||
renderSegment i j s = case s, between start end i of
|
||||
Filler s', true ->
|
||||
element
|
||||
syntaxHighlighter
|
||||
{ style:
|
||||
mkHighlighterTheme
|
||||
{ grey: Color.rgb 50 50 50
|
||||
, highlightColour: Color.hsl 30.0 0.5 0.4
|
||||
, textColour: Color.rgb 0 0 1
|
||||
}
|
||||
, language: "purescript"
|
||||
, children: s'
|
||||
}
|
||||
Hole maxLength text, true ->
|
||||
element segment
|
||||
{ maxLength
|
||||
, theKey: show i <> "," <> show j
|
||||
, update: update <<< updateSegments i j
|
||||
, text
|
||||
, focusOnFirstRender: (firstHoleIndex <#> \fh -> fh.i == i && fh.j == j) # fromMaybe false
|
||||
}
|
||||
_, _ -> mempty
|
||||
|
||||
type Props =
|
||||
{ segments ∷ Array (Array Segment)
|
||||
@ -109,7 +103,6 @@ makeComponent ∷ Effect (ReactComponent Props)
|
||||
makeComponent = do
|
||||
segment <- mkSegment
|
||||
reactComponent "FillInTheGaps" \(props@{ updateSegments, segments, run, solvedWith } ∷ Props) -> React.do
|
||||
ref <- useFocus
|
||||
pure
|
||||
$ R.form
|
||||
{ onSubmit: handler preventDefault (const run)
|
||||
@ -128,7 +121,6 @@ makeComponent = do
|
||||
[ el Block.button
|
||||
{ onClick: handler_ mempty
|
||||
, buttonType: ButtonType.Primary
|
||||
, ref: if isJust (findFirstHoleIndex segments) then unsafeCoerce undefined else ref
|
||||
}
|
||||
[ R.text "Run" ]
|
||||
]
|
||||
|
@ -82,6 +82,7 @@ exports.colorizeImpl = function (text) {
|
||||
};
|
||||
};
|
||||
exports.setValue = function (value) { return function (editor) { return function () { return editor.setValue(value); }; }; };
|
||||
exports.layout = (editor) => () => editor.layout()
|
||||
exports.defineThemeImpl = function (monacoInstance) {
|
||||
return function (name) {
|
||||
return function (theme) {
|
||||
@ -114,99 +115,138 @@ exports.setMonarchTokensProviderImpl = function (monacoInstance) {
|
||||
};
|
||||
};
|
||||
};
|
||||
exports.vsCodeTheme = function (bg) {
|
||||
exports.horizonTheme = function (bg) {
|
||||
return ({
|
||||
base: "vs",
|
||||
inherit: true,
|
||||
rules: [
|
||||
{
|
||||
foreground: "008e00",
|
||||
token: "comment",
|
||||
foreground: "#33333380",
|
||||
fontStyle: "italic",
|
||||
token: "comment"
|
||||
},
|
||||
{
|
||||
foreground: "7d4726",
|
||||
token: "meta.preprocessor",
|
||||
foreground: "#DC3318",
|
||||
token: "constant"
|
||||
},
|
||||
{
|
||||
foreground: "7d4726",
|
||||
token: "keyword.control.import",
|
||||
foreground: "#F77D26",
|
||||
token: "entity.name"
|
||||
},
|
||||
{
|
||||
foreground: "df0002",
|
||||
token: "string",
|
||||
foreground: "#1D8991",
|
||||
token: "entity.name.function"
|
||||
},
|
||||
{
|
||||
foreground: "3a00dc",
|
||||
token: "constant.numeric",
|
||||
foreground: "#DA103F",
|
||||
token: "entity.name.tag"
|
||||
},
|
||||
{
|
||||
foreground: "c800a4",
|
||||
token: "constant.language",
|
||||
foreground: "#F77D26",
|
||||
token: "entity.name.type"
|
||||
},
|
||||
{
|
||||
foreground: "275a5e",
|
||||
token: "constant.character",
|
||||
foreground: "#DA103F",
|
||||
token: "variable"
|
||||
},
|
||||
{
|
||||
foreground: "275a5e",
|
||||
token: "constant.other",
|
||||
foreground: "#DA103F",
|
||||
token: "entity.name.variable"
|
||||
},
|
||||
{
|
||||
foreground: "c800a4",
|
||||
token: "variable.language",
|
||||
foreground: "#8A31B9",
|
||||
token: "keyword"
|
||||
},
|
||||
{
|
||||
foreground: "c800a4",
|
||||
token: "variable.other",
|
||||
foreground: "#333333",
|
||||
token: "keyword.operator"
|
||||
},
|
||||
{
|
||||
foreground: "c800a4",
|
||||
token: "keyword",
|
||||
foreground: "#8A31B9",
|
||||
token: "keyword.operator.new"
|
||||
},
|
||||
{
|
||||
foreground: "c900a4",
|
||||
token: "storage",
|
||||
foreground: "#8A31B9",
|
||||
token: "keyword.operator.expression"
|
||||
},
|
||||
{
|
||||
foreground: "438288",
|
||||
token: "entity.name.class",
|
||||
foreground: "#8A31B9",
|
||||
token: "keyword.operator.logical, keyword.operator.delete"
|
||||
},
|
||||
{
|
||||
foreground: "790ead",
|
||||
token: "entity.name.tag",
|
||||
foreground: "#8A31B9",
|
||||
token: "keyword.operator.delete"
|
||||
},
|
||||
{
|
||||
foreground: "450084",
|
||||
token: "entity.other.attribute-name",
|
||||
foreground: "#DC3318",
|
||||
token: "keyword.other.unit"
|
||||
},
|
||||
{
|
||||
foreground: "450084",
|
||||
token: "support.function",
|
||||
foreground: "#F6661EB3",
|
||||
fontStyle: "italic",
|
||||
token: "markup.quote"
|
||||
},
|
||||
{
|
||||
foreground: "450084",
|
||||
token: "support.constant",
|
||||
foreground: "#DA103F",
|
||||
token: "entity.name.section"
|
||||
},
|
||||
{
|
||||
foreground: "790ead",
|
||||
token: "support.type",
|
||||
foreground: "#8A31B9",
|
||||
token: "storage"
|
||||
},
|
||||
{
|
||||
foreground: "790ead",
|
||||
token: "support.class",
|
||||
foreground: "#F6661E",
|
||||
token: "string"
|
||||
},
|
||||
{
|
||||
foreground: "790ead",
|
||||
token: "support.other.variable",
|
||||
foreground: "#F77D26",
|
||||
token: "support"
|
||||
},
|
||||
{
|
||||
foreground: "#1D8991",
|
||||
token: "support.function"
|
||||
},
|
||||
{
|
||||
foreground: "#DA103F",
|
||||
token: "support.variable"
|
||||
},
|
||||
{
|
||||
foreground: "#DA103F",
|
||||
token: "support.type.property-name"
|
||||
},
|
||||
{
|
||||
foreground: "#DA103F",
|
||||
token: "meta.object-literal.key"
|
||||
},
|
||||
{
|
||||
foreground: "#333333",
|
||||
token: "support.type.property-name.css"
|
||||
},
|
||||
{
|
||||
foreground: "#F77D26",
|
||||
fontStyle: "italic",
|
||||
token: "variable.language"
|
||||
},
|
||||
{
|
||||
fontStyle: "italic",
|
||||
token: "variable.parameter"
|
||||
},
|
||||
{
|
||||
foreground: "#DA103FB3",
|
||||
token: "punctuation.definition.tag"
|
||||
},
|
||||
{
|
||||
foreground: "#333333",
|
||||
token: "punctuation.separator"
|
||||
},
|
||||
],
|
||||
colors: {
|
||||
"editor.foreground": "#000000",
|
||||
"editor.background": bg,
|
||||
"editor.selectionBackground": "#B5D5FF",
|
||||
"editor.background": bg, //"#FDF0ED"
|
||||
"editor.selectionBackground": "#F9CBBE80",
|
||||
"editor.lineHighlightBackground": "#B5D5FF",
|
||||
"editor.lineHighlightBorder": "#B5D5FF",
|
||||
"editorCursor.foreground": "#000000",
|
||||
"editorCursor.foreground": "#333333",
|
||||
"editorWhitespace.foreground": "#BFBFBF",
|
||||
},
|
||||
});
|
||||
@ -218,6 +258,7 @@ exports.nightOwlTheme = function (bg) {
|
||||
rules: [
|
||||
{
|
||||
foreground: "637777",
|
||||
fontStyle: "italic",
|
||||
token: "comment",
|
||||
},
|
||||
{
|
||||
|
@ -1,13 +1,15 @@
|
||||
module Yoga.Editor where
|
||||
|
||||
import Prelude
|
||||
import CSS (borderBox, borderRadius, boxSizing, calc, margin, padding, pct, px, toHexString, unitless, width)
|
||||
import CSS (borderBox, borderRadius, boxSizing, margin, padding, pct, px, unitless, width)
|
||||
import CSS.Overflow (hidden, overflowY)
|
||||
import Control.Promise (Promise)
|
||||
import Control.Promise as Promise
|
||||
import Data.Foldable (for_)
|
||||
import Data.Foldable (fold, foldMap, for_)
|
||||
import Data.Maybe (Maybe(..), maybe)
|
||||
import Data.Nullable (Nullable)
|
||||
import Data.Monoid (guard)
|
||||
import Data.Nullable (Nullable, notNull, null)
|
||||
import Data.Time.Duration (Seconds(..))
|
||||
import Data.Tuple.Nested ((/\))
|
||||
import Effect (Effect)
|
||||
import Effect.Aff (Aff)
|
||||
@ -19,16 +21,14 @@ import JSS (jssClasses)
|
||||
import Prim.Row (class Union)
|
||||
import React.Basic (JSX, ReactComponent, Ref, element, fragment)
|
||||
import React.Basic.DOM as R
|
||||
import React.Basic.Emotion (var)
|
||||
import React.Basic.Hooks (reactComponent, useEffect, useState)
|
||||
import React.Basic.Hooks (reactComponent, useEffect, useEffectAlways, useState)
|
||||
import React.Basic.Hooks as React
|
||||
import React.Basic.Hooks.Aff (useAff)
|
||||
import Web.DOM (Node)
|
||||
import Web.HTML (HTMLElement)
|
||||
import Yoga.Theme (fromTheme)
|
||||
import Yoga.Theme.Default (darkTheme)
|
||||
import Yoga.Block.Container.Style (DarkOrLightMode(..), getDarkOrLightMode)
|
||||
import Yoga.Block.Hook.UseResize (useOnResize)
|
||||
import Yoga.Theme.Styles (makeStylesJSS)
|
||||
import Yoga.Theme.Types (CSSTheme)
|
||||
|
||||
type EditorProps =
|
||||
( value ∷ String
|
||||
@ -52,7 +52,7 @@ foreign import setThemeImpl ∷ Monaco -> String -> Effect Unit
|
||||
|
||||
foreign import nightOwlTheme ∷ String -> MonacoTheme
|
||||
|
||||
foreign import vsCodeTheme ∷ String -> MonacoTheme
|
||||
foreign import horizonTheme ∷ String -> MonacoTheme
|
||||
|
||||
foreign import getValue ∷ Editor -> Effect String
|
||||
|
||||
@ -60,6 +60,8 @@ foreign import setValue ∷ String -> Editor -> Effect Unit
|
||||
|
||||
foreign import colorizeImpl ∷ String -> String -> { tabSize ∷ Int } -> Editor -> Promise String
|
||||
|
||||
foreign import layout ∷ Editor -> Effect Unit
|
||||
|
||||
foreign import data Monaco ∷ Type
|
||||
|
||||
foreign import data Editor ∷ Type
|
||||
@ -75,7 +77,7 @@ darkThemeName ∷ String
|
||||
darkThemeName = "NightOwl"
|
||||
|
||||
lightThemeName ∷ String
|
||||
lightThemeName = "VSCode"
|
||||
lightThemeName = "Horizon"
|
||||
|
||||
foreign import data MonarchLanguage ∷ Type
|
||||
|
||||
@ -85,10 +87,10 @@ foreign import registerLanguageImpl ∷ Monaco -> String -> Effect Unit
|
||||
|
||||
foreign import setMonarchTokensProviderImpl ∷ Monaco -> String -> MonarchLanguage -> Effect Unit
|
||||
|
||||
initEditor ∷ CSSTheme -> Monaco -> Effect Unit
|
||||
initEditor theme monaco = do
|
||||
defineThemeImpl monaco darkThemeName (nightOwlTheme (toHexString theme.backgroundColour))
|
||||
defineThemeImpl monaco lightThemeName (vsCodeTheme (toHexString theme.backgroundColour))
|
||||
initEditor ∷ Monaco -> Effect Unit
|
||||
initEditor monaco = do
|
||||
defineThemeImpl monaco darkThemeName (nightOwlTheme "#212134") -- [TODO] Read from somewhere else
|
||||
defineThemeImpl monaco lightThemeName (horizonTheme "#EBDFDE") -- [TODO] Don't hardcode
|
||||
registerLanguageImpl monaco "purescript"
|
||||
setMonarchTokensProviderImpl monaco "purescript" purescriptSyntax
|
||||
|
||||
@ -111,26 +113,35 @@ mkEditor = do
|
||||
padding (4.0 # px) (8.0 # px) (0.0 # px) (8.0 # px)
|
||||
width (100.0 # pct)
|
||||
overflowY hidden
|
||||
-- backgroundColor (colour.background) [TODO]
|
||||
-- backgroundColor (colour.background) [ TODO ]
|
||||
}
|
||||
reactComponent "Editor" \{ onLoad, height, language } -> React.do
|
||||
classes <- useStyles {}
|
||||
maybeEditor /\ modifyEditor <- useState Nothing
|
||||
maybeMonaco /\ modifyMonaco <- useState Nothing
|
||||
mbEditorComponent /\ setEditorComponent <- React.useState' Nothing
|
||||
monacoRef <- React.useRef null
|
||||
editorRef <- React.useRef null
|
||||
useOnResize (3.0 # Seconds) \_ -> do
|
||||
mbEditor <- React.readRefMaybe editorRef
|
||||
for_ mbEditor layout
|
||||
useAff unit do
|
||||
eddy <- monacoEditor
|
||||
liftEffect $ modifyEditor (const (Just eddy))
|
||||
useEffect unit do -- [TODO] notice theme change
|
||||
for_ maybeMonaco (initEditor (fromTheme darkTheme))
|
||||
pure mempty
|
||||
med <- monacoEditor
|
||||
setEditorComponent (Just med) # liftEffect
|
||||
useEffectAlways do
|
||||
mbMode <- getDarkOrLightMode
|
||||
mbMonaco <- React.readRefMaybe monacoRef
|
||||
case mbMode, mbMonaco of
|
||||
Just DarkMode, Just monaco -> setThemeImpl monaco darkThemeName
|
||||
Just LightMode, Just monaco -> setThemeImpl monaco lightThemeName
|
||||
_, _ -> mempty
|
||||
mempty
|
||||
let themeName = darkThemeName
|
||||
pure
|
||||
$ fragment
|
||||
[ R.div
|
||||
{ className: classes.wrapper
|
||||
, children:
|
||||
[ maybeEditor
|
||||
# maybe mempty \editor ->
|
||||
[ mbEditorComponent
|
||||
# foldMap \editor ->
|
||||
element editor
|
||||
{ theme: themeName
|
||||
, height
|
||||
@ -154,11 +165,14 @@ mkEditor = do
|
||||
}
|
||||
, language
|
||||
-- https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
||||
, editorDidMount: mkEffectFn2 \e _ -> onLoad e
|
||||
, editorDidMount:
|
||||
mkEffectFn2 \e _ -> do
|
||||
React.writeRef editorRef (notNull e)
|
||||
onLoad e
|
||||
, editorWillMount:
|
||||
mkEffectFn1 \m -> do
|
||||
modifyMonaco (const $ Just m)
|
||||
(initEditor (fromTheme darkTheme) m)
|
||||
React.writeRef monacoRef (notNull m)
|
||||
initEditor m
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user