Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Build artifacts
.stack-work/
dist-newstyle/
dist/

# Executables and other build outputs
*.o
*.hi
*.dyn_o
*.dyn_hi
*.prof
*.tix
*.hpc
*.eventlog
*.dump-*
*.exe
*.dll
*.so
*.dylib

# Editor-specific files
*~
.#*
.#*#
*.swp
*.swo
.vscode/
.idea/

# OS-specific files
.DS_Store
Thumbs.db

# Other common files to ignore
.ghci
.history
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Revision history for app

## 0.1.0.0 -- YYYY-mm-dd

* First version. Released on an unsuspecting world.
26 changes: 26 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

.PHONY= update build optim

all: update build optim

update:
wasm32-wasi-cabal update

build:
wasm32-wasi-cabal build
rm -rf public
cp -r static public
$(eval my_wasm=$(shell wasm32-wasi-cabal list-bin app | tail -n 1))
$(shell wasm32-wasi-ghc --print-libdir)/post-link.mjs --input $(my_wasm) --output public/ghc_wasm_jsffi.js
cp -v $(my_wasm) public/

optim:
wasm-opt -all -O2 public/app.wasm -o public/app.wasm
wasm-tools strip -o public/app.wasm public/app.wasm

serve:
http-server public

clean:
rm -rf dist-newstyle public

47 changes: 47 additions & 0 deletions app.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
cabal-version: 3.0
name: miso-bulma
version: 0.1.0.0
synopsis: miso-bulma component library
description: miso-bulma component library
license: BSD-3-Clause
license-file: LICENSE
author: dmjio
maintainer: code@dmj.io
copyright: haskell-miso @ 2025
category: Web
build-type: Simple
extra-doc-files: CHANGELOG.md

common warnings
ghc-options:
-funbox-strict-fields -O2 -ferror-spans -fspecialise-aggressively -Wall

common wasm
if arch(wasm32)
ghc-options:
-no-hs-main -optl-mexec-model=reactor "-optl-Wl,--export=hs_start"
cpp-options:
-DWASM

library
import:
wasm,
warnings
build-depends: base < 5, containers >= 0.7, miso
other-modules:
Bulma
hs-source-dirs:
lib
default-language:
Haskell2010

executable bulma-example
import:
wasm, warnings
main-is:
Main.hs
build-depends: base < 5, containers >= 0.7, miso
hs-source-dirs:
app
default-language:
Haskell2010
180 changes: 180 additions & 0 deletions app/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
-----------------------------------------------------------------------------
{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
module Main where
-----------------------------------------------------------------------------
import Miso
import Miso.Html.Element as H
import Miso.Html.Event as E
import Miso.Html.Property as P
import Miso.Lens
import Miso.String
import qualified Miso.CSS as CSS
import Miso.CSS (StyleSheet)
-----------------------------------------------------------------------------
newtype Model = Model { _value :: Int }
deriving (Show, Eq)
-----------------------------------------------------------------------------
instance ToMisoString Model where
toMisoString (Model v) = toMisoString v
-----------------------------------------------------------------------------
value :: Lens Model Int
value = lens _value $ \m v -> m { _value = v }
-----------------------------------------------------------------------------
data Action
= AddOne PointerEvent
| SubtractOne PointerEvent
| SayHelloWorld
deriving (Show, Eq)
-----------------------------------------------------------------------------
#ifdef WASM
foreign export javascript "hs_start" main :: IO ()
#endif
-----------------------------------------------------------------------------
main :: IO ()
main = run $ startApp app
-----------------------------------------------------------------------------
app :: App Model Action
app = (component (Model 0) updateModel viewModel)
{ events = pointerEvents
, styles = [ Sheet sheet ]
}
-----------------------------------------------------------------------------
updateModel :: Action -> Transition Model Action
updateModel = \case
AddOne event -> do
value += 1
io_ $ consoleLog (ms (show event))
SubtractOne event -> do
value -= 1
io_ $ consoleLog (ms (show event))
SayHelloWorld ->
io_ (consoleLog "Hello World!")
-----------------------------------------------------------------------------
viewModel :: Model -> View Model Action
viewModel x = H.div_
[ P.class_ "counter-container" ]
[ H.h1_
[ P.class_ "counter-title"
]
[ "馃崪 Miso counter"
]
, H.div_
[ P.class_ "counter-display"
]
[ text (ms x)
]
, H.div_
[ P.class_ "buttons-container"
]
[ H.button_
[ E.onPointerDown AddOne
, P.class_ "decrement-btn"
] [text "+"]
, H.button_
[ E.onPointerDown SubtractOne
, P.class_ "increment-btn"
] [text "-"]
]
]
-----------------------------------------------------------------------------
sheet :: StyleSheet
sheet =
CSS.sheet_
[ CSS.selector_ ":root"
[ "--primary-color" =: "#4a6bff"
, "--primary-hover" =: "#3451d1"
, "--secondary-color" =: "#ff4a6b"
, "--secondary-hover" =: "#d13451"
, "--background" =: "#f7f9fc"
, "--text-color" =: "#333"
, "--shadow" =: "0 4px 10px rgba(0, 0, 0, 0.1);"
, "--transition" =: "all 0.3s ease;"
]
, CSS.selector_ "body"
[ CSS.fontFamily "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif"
, CSS.display "flex"
, CSS.justifyContent "center"
, CSS.alignItems "center"
, CSS.height "100vh"
, CSS.margin "0"
, CSS.backgroundColor (CSS.var "background")
, CSS.color (CSS.var "text-color")
]
, CSS.selector_ ".counter-container"
[ CSS.backgroundColor CSS.white
, CSS.padding (CSS.rem 2)
, CSS.borderRadius (CSS.px 12)
, CSS.boxShadow "shadow"
, CSS.textAlign "center"
]
, CSS.selector_ ".counter-display"
[ CSS.fontSize "5rem"
, CSS.fontWeight "bold"
, CSS.margin "1CSS.rem 0"
, CSS.transition "var(--transition)"
]
, CSS.selector_ ".buttons-container"
[ CSS.display "flex"
, CSS.gap "1rem"
, CSS.justifyContent "center"
, CSS.marginTop "1.5rem"
]
, CSS.selector_ "button"
[ CSS.fontSize "1.5rem"
, CSS.width "3rem"
, CSS.height "3rem"
, CSS.border "none"
, CSS.borderRadius "50%"
, CSS.cursor "pointer"
, CSS.transition "var(--transition)"
, CSS.color CSS.white
, CSS.display "flex"
, CSS.alignItems "center"
, CSS.justifyContent "center"
]
, CSS.selector_ ".increment-btn"
[ CSS.backgroundColor (CSS.var "primary-color")
]
, CSS.selector_ ".increment-btn:hover"
[ CSS.backgroundColor (CSS.var "primary-hover")
, CSS.transform "translateY(-2px)"
]
, CSS.selector_ ".decrement-btn"
[ CSS.backgroundColor (CSS.var "secondary-color")
]
, CSS.selector_ ".decrement-btn:hover"
[ CSS.backgroundColor (CSS.var "secondary-hover")
, CSS.transform "translateY(-2px)"
]
, CSS.keyframes_ "pulse"
[ CSS.pct 0 =:
[ CSS.transform "scale(1)"
]
, CSS.pct 50 =:
[ CSS.transform "scale(1.1)"
]
, CSS.pct 100 =:
[ CSS.transform "scale(1)"
]
]
, CSS.selector_ ".counter-display.animate"
[ CSS.animation "pulse 0.3s ease"
]
, CSS.media_ "(max-width: 480px)"
[ ".counter-container" =:
[ CSS.padding (CSS.rem 1.5)
]
, ".counter-display" =:
[ CSS.fontSize (CSS.rem 3)
]
, "button" =:
[ CSS.fontSize (CSS.rem 1.2)
, CSS.width (CSS.rem 2.5)
, CSS.width (CSS.rem 2.5)
]
]
]
-----------------------------------------------------------------------------
12 changes: 12 additions & 0 deletions cabal.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
packages:
.

allow-newer:
all:base

source-repository-package
type: git
location: https://github.com/dmjio/miso
tag: 3c3c359af12d657cf78ace32db53b088b5b8b7a2

flags: +template-haskell
Loading