From 474be2c91ebbeac7be06156c46213753374a7242 Mon Sep 17 00:00:00 2001 From: Max Wilson Date: Sun, 21 Jan 2024 19:14:55 -0800 Subject: [PATCH] Turn stub into basic placeholder. Switch back to js instead of jsx format because apparently HMR doesn't work well with ReactComponents inside of JSX. (It fails to detect changes so the UI remains unchanged, at least in case of changes to RibbitPlayground's View.) Since we haven't really made use of JSX because I prefer Feliz, it makes sense to just switch back to .js format. --- index.html | 2 +- main.sass | 17 ++++++++ package.json | 6 +-- src/UI/CommonUI.fs | 18 ++++++++ src/UI/Ribbit/RibbitPlaygroundView.fs | 62 +++++++++++++++++++++++---- 5 files changed, 92 insertions(+), 13 deletions(-) diff --git a/index.html b/index.html index 8b7099b8..87c9b27e 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,6 @@
- + diff --git a/main.sass b/main.sass index bfc696de..dbcc25f8 100644 --- a/main.sass +++ b/main.sass @@ -154,3 +154,20 @@ ul @extend .hasMargins max-height: calc(100svh - 6px) +table + border: thin solid + td + border: thin solid + > * // put the padding on the child element so that e.g. dangerouslyLow can be all red with no gap for parent padding + padding: 2px + +.dangerouslyLow + background-color: red + color: white + +.mediumLow + background-color: yellow + +$limegreen: #32CD32 +.enough + background-color: $limegreen \ No newline at end of file diff --git a/package.json b/package.json index b5fc9a7a..fd993ffd 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "private": true, "scripts": { - "start": "dotnet tool restore && dotnet fable watch src -e .jsx -o dist --runFast vite --port 8080", - "buildGithub": "dotnet fable src -e .jsx -o dist --sourceMaps --run vite build --base /ShiningSword", - "build": "dotnet tool restore && dotnet fable src -e .jsx -o dist --run vite build", + "start": "dotnet tool restore && dotnet fable watch src -o dist --runFast vite --port 8080", + "buildGithub": "dotnet fable src -o dist --sourceMaps --run vite build --base /ShiningSword", + "build": "dotnet tool restore && dotnet fable src -o dist --run vite build", "clean": "dotnet fable clean src --yes" }, "dependencies": { diff --git a/src/UI/CommonUI.fs b/src/UI/CommonUI.fs index 54837b43..00225a85 100644 --- a/src/UI/CommonUI.fs +++ b/src/UI/CommonUI.fs @@ -37,6 +37,24 @@ type React = static member ofJsx (jsx: Fable.Core.JSX.Element) = jsx |> unbox static member toJsx (element: ReactElement) = element |> unbox +type 'row TableColumn = { header: string; cell: 'row -> ReactElement } +let table (headers: _ TableColumn list) bodyRows = + Html.table [ + Html.thead [ + Html.tr [ + for header in headers do + Html.th [ Html.text header.header ] + ] + ] + Html.tbody [ + for row in bodyRows do + Html.tr [ + for header in headers do + Html.td [ header.cell row ] + ] + ] + ] + // originally from https://github.com/fable-compiler/fable-react/blob/master/docs/react-error-boundaries.md, but updated to Fable 4 module ReactErrorBoundary = open Fable.Core diff --git a/src/UI/Ribbit/RibbitPlaygroundView.fs b/src/UI/Ribbit/RibbitPlaygroundView.fs index 17b6e701..b7f30f92 100644 --- a/src/UI/Ribbit/RibbitPlaygroundView.fs +++ b/src/UI/Ribbit/RibbitPlaygroundView.fs @@ -3,20 +3,64 @@ open Ribbit open Feliz open Feliz.UseElmish -type DataKey = string -type Value = Text of string | Number of int -type DataBank = Map -type TODO = Unit -type Model = { data: DataBank; definitions: TODO } +type private DataKey = string +type private Value = Text of string | Number of int +type private DataBank = Map +type private TODO = Unit +type private Model = { data: DataBank; definitions: TODO } with static member fresh = { data = Map.empty; definitions = () } -type Msg = TODO +type private Msg = TODO -let init _ = Model.fresh +// make this module private so it will interfere less with React hot-loading +module private Impl = + let data = + [ + "Rath", [ "HP", Number 14; "maxHP", Number 53; "AC", Number 3; "Status", Text "OK" ] + "Delsenora", [ "HP", Number 23; "maxHP", Number 23; "SP", Number 22; "maxSP", Number 29; "AC", Number 10; "Status", Text "OK" ] + "Wild Boar", [ "HP", Number 34; "maxHP", Number 49; "AC", Number 6; "Status", Text "OK" ] + ] + |> List.map (fun (name, stats) -> Map.ofList (("Name", Text name)::stats)) + let numberValue name row = + match Map.tryFind name row with + | Some (Number v) -> Some v + | _ -> None + let textValue name row = + match Map.tryFind name row with + | Some (Text v) -> Some v + | _ -> None + let text name = { header = name; cell = textValue name >> Option.defaultValue "" >> Html.text } + let textWithDefault name defaultValue = { header = name; cell = textValue name >> Option.defaultValue defaultValue >> Html.text } + let numeric name = { header = name; cell = fun row -> match numberValue name row, numberValue ("max" + name) row with + | Some v, Some max -> + let className = if v <= max / 3 then "dangerouslyLow" elif v <= (max * 2 / 3) then "mediumLow" else "enough" + classP' className Html.div [prop.text $"{v}/{max}"] + | Some v, None -> Html.div (string v) + | _ -> Html.div [] + } -let update msg model = model + let init _ = Model.fresh + let update msg model = model +open Impl + +[] let View() = let model dispatch = React.useElmishSimple init update - Html.div "RibbitPlayground: placeholder" \ No newline at end of file + class' "scrollParent" Html.div [ + srcLink + table [ + text "Name" + numeric "HP" + numeric "SP" + numeric "AC" + textWithDefault "Status" "OK" + ] data + class' "scrollable" Html.div [ + Html.div "Rath's HP are now 14" + Html.div "Delsenora casts Fireball!" + Html.div "Wild Boar attacks Rath!" + ] + Html.input [prop.placeholder "Enter a command"] + ] \ No newline at end of file