svg.escobar.life

A simple SVG markup editor for the web

View.elm (4174B)

      1 module View exposing (view)
      2 
      3 import Types exposing (..)
      4 import Editor exposing (editor)
      5 
      6 import Html exposing ( Html
      7                      , Attribute
      8                      , div
      9                      , img
     10                      , button
     11                      , a
     12                      , span
     13                      , text
     14                      , h1
     15                      , header
     16                      )
     17 import Html.Events exposing (onClick, on)
     18 import Html.Attributes exposing ( id
     19                                 , class
     20                                 , src
     21                                 , href
     22                                 , target
     23                                 , rel
     24                                 , alt
     25                                 , attribute
     26                                 , name
     27                                 )
     28 import Html.Lazy exposing (lazy)
     29 import Accessibility.Landmark exposing (application, region)
     30 import Accessibility.Role exposing (alert)
     31 import Accessibility.Key exposing (onKeyDown, enter)
     32 import Accessibility.Widget exposing (label, hidden)
     33 import Browser exposing (Document)
     34 import Json.Decode
     35 import Regex exposing (Regex, Match, replace)
     36 
     37 
     38 view : Model -> Document Msg
     39 view model =
     40   { title = "SVG Editor"
     41   , body =
     42       case model.load of
     43         Loading -> 
     44           []
     45 
     46         Loaded -> 
     47           [ lazy container model ]
     48   }
     49 
     50 container : Model -> Html Msg
     51 container model =
     52   div 
     53     (
     54       [ id "container", application, label "SVG Editor" ]
     55       ++ 
     56       (if valid model.status then [] else [class "error"])
     57     )
     58     [ display model
     59     , lazy editor model
     60     ]
     61 
     62 display : Model -> Html Msg
     63 display model =
     64   div 
     65     (
     66       [ id "display"
     67       , region
     68       , class (if model.darkModeOn then "dark" else "light") 
     69       , label "Picture preview"
     70       ] 
     71       ++ 
     72       -- Alert users when the image is invalid
     73       (if valid model.status then [] else [ alert ])
     74     )
     75     [ img 
     76       [ id "image", src (uri model), loaded model, alt "Input picture" ] 
     77       []
     78     , errorIcon
     79     , button 
     80         [ onClick Download
     81         , label "Download file"
     82         ] 
     83         [ downloadIcon ]
     84     , button 
     85         [ onClick (Upload Requested)
     86         , label "Upload file"
     87         ] 
     88         [ uploadIcon ]
     89     , button 
     90         [ onClick ToggleDarkMode
     91         , label "Toggle dark mode"
     92         ] 
     93         [ bulbIcon model ]
     94     ]
     95 
     96 uri : Model -> String
     97 uri model =
     98   "data:image/svg+xml;utf8," 
     99   ++ 
    100   (replace model.uriEncoder percentEscape model.image)
    101 
    102 percentEscape : Match -> String
    103 percentEscape m =
    104   case m.match of
    105     "!" -> "%21"
    106     "#" -> "%23"
    107     "$" -> "%24"
    108     "%" -> "%25"
    109     "&" -> "%26"
    110     "'" -> "%27"
    111     "(" -> "%28"
    112     ")" -> "%29"
    113     "*" -> "%2A"
    114     "+" -> "%2B"
    115     "," -> "%2C"
    116     "/" -> "%2F"
    117     ":" -> "%3A"
    118     ";" -> "%3B"
    119     "=" -> "%3D"
    120     "?" -> "%3F"
    121     "@" -> "%40"
    122     "[" -> "%5B"
    123     "]" -> "%5D"
    124     str -> str
    125 
    126 onError : msg -> Attribute msg
    127 onError f = 
    128   on "error" (Json.Decode.succeed f)
    129 
    130 onLoad : msg -> Attribute msg
    131 onLoad f = 
    132   on "load" (Json.Decode.succeed f)
    133 
    134 loaded : Model -> Attribute Msg
    135 loaded model =
    136   if valid model.status 
    137     then onError (Validation Invalid) 
    138     else onLoad (Validation Valid)
    139 
    140 valid : Status -> Bool
    141 valid status =
    142   case status of
    143     Valid -> 
    144       True
    145 
    146     Invalid -> 
    147       False
    148 
    149 downloadIcon : Html Msg
    150 downloadIcon = 
    151   img 
    152     [ src "assets/download.svg"
    153     , hidden True
    154     , alt "Download file"
    155     ] 
    156     []
    157 
    158 uploadIcon : Html Msg
    159 uploadIcon = 
    160   img 
    161     [ src "assets/upload.svg"
    162     , hidden True
    163     , alt "Upload file"
    164     ] 
    165     []
    166 
    167 bulbIcon : Model -> Html Msg
    168 bulbIcon model =
    169   let
    170     bulbOn = "assets/bulb-on.svg" 
    171     bulbOff = "assets/bulb-off.svg"
    172   in
    173     img 
    174       [ src (if model.darkModeOn then bulbOn else bulbOff)
    175       , hidden True
    176       , alt "Toggle dark mode"
    177       ] 
    178       []
    179 
    180 errorIcon : Html Msg
    181 errorIcon = 
    182   img 
    183     [ id "error", src "assets/error.svg", alt "Something Went Wrong" ] 
    184     []
    185