elm-format

main
Bram 2024-11-03 21:09:37 +01:00
parent 85790d4e7b
commit 7711ce8c0d
9 changed files with 359 additions and 155 deletions

View File

@ -1,33 +1,49 @@
module Items.FlavorPicker exposing (..) module Items.FlavorPicker exposing (..)
{-| This module allows the user to pick whatever flavor they want to use. {-| This module allows the user to pick whatever flavor they want to use.
-} -}
import Color exposing (Color) import Color exposing (Color)
import Element exposing (Element) import Element exposing (Element)
import Element.Events
import Html.Attributes import Html.Attributes
import Layout
import Material.Icons import Material.Icons
import Theme exposing (Flavor(..)) import Theme exposing (Flavor(..))
import Layout
import Element.Events
-- MODEL -- MODEL
-- UPDATE -- UPDATE
-- VIEW -- VIEW
view : view :
{ height : Int { height : Int
, flavor : Flavor , flavor : Flavor
, onClick : Flavor -> msg , onClick : Flavor -> msg
, themeIcon : Flavor -> Color , themeIcon : Flavor -> Color
, width : Int , width : Int
} -> Element msg }
-> Element msg
view data = view data =
let let
lightMode = data.flavor == Latte lightMode =
icon = if lightMode then Material.Icons.dark_mode else Material.Icons.light_mode data.flavor == Latte
newFlavor = if lightMode then Frappe else Latte
icon =
if lightMode then
Material.Icons.dark_mode
else
Material.Icons.light_mode
newFlavor =
if lightMode then
Frappe
else
Latte
in in
Element.el Element.el
[ Element.Events.onClick (data.onClick newFlavor) [ Element.Events.onClick (data.onClick newFlavor)
@ -40,4 +56,3 @@ view data =
, width = data.width , width = data.width
} }
) )

View File

@ -1,28 +1,35 @@
module Items.Introduction exposing (..) module Items.Introduction exposing (..)
import Color exposing (Color) import Color exposing (Color)
import Element exposing (Element) import Element exposing (Element)
import Element.Background import Element.Background
import Widget.Material.Typography
import Theme import Theme
import Widget.Material.Typography
-- MODEL -- MODEL
type alias Model = ()
type alias Msg = () type alias Model =
()
type alias Msg =
()
-- UPDATE -- UPDATE
-- SUBSCRIPTIONS -- SUBSCRIPTIONS
-- VIEW -- VIEW
view : view :
{ colorBackground : Color { colorBackground : Color
, width : Int , width : Int
} -> Element msg }
-> Element msg
view data = view data =
[ header "Martiplier" [ header "Martiplier"
, text "Martiplier (short for Matrix Plier) is a unique client. It doesn't let you browse rooms and have chat conversations." , text "Martiplier (short for Matrix Plier) is a unique client. It doesn't let you browse rooms and have chat conversations."
@ -35,10 +42,14 @@ view data =
, Element.width (Element.px data.width) , Element.width (Element.px data.width)
] ]
header : String -> Element msg header : String -> Element msg
header = header =
Element.text >> Element.el Widget.Material.Typography.h1 Element.text
>> List.singleton >> Element.paragraph [] >> Element.el Widget.Material.Typography.h1
>> List.singleton
>> Element.paragraph []
text : String -> Element msg text : String -> Element msg
text = text =

View File

@ -1,26 +1,36 @@
module Items.ItemPicker exposing (..) module Items.ItemPicker exposing (..)
import Iddict exposing (Iddict) import Color exposing (Color)
import Element exposing (Element) import Element exposing (Element)
import Iddict exposing (Iddict)
import Layout import Layout
import Material.Icons import Material.Icons
import Color exposing (Color)
-- MODEL -- MODEL
type alias Model a = type alias Model a =
{ hover : Maybe Int { hover : Maybe Int
, items : Iddict a , items : Iddict a
} }
type Msg = OnHover Int | OnHoverOut Int
type Msg
= OnHover Int
| OnHoverOut Int
init : Iddict a -> Model a init : Iddict a -> Model a
init iddict = init iddict =
{ hover = Nothing, items = iddict } { hover = Nothing, items = iddict }
-- UPDATE -- UPDATE
update : Msg -> Model a -> Model a update : Msg -> Model a -> Model a
update msg model = update msg model =
case msg of case msg of
@ -30,19 +40,26 @@ update msg model =
OnHoverOut i -> OnHoverOut i ->
if model.hover == Just i then if model.hover == Just i then
{ model | hover = Nothing } { model | hover = Nothing }
else else
model model
updateContent : (Iddict a -> Iddict a) -> Model a -> Model a updateContent : (Iddict a -> Iddict a) -> Model a -> Model a
updateContent f model = updateContent f model =
{ model | items = f model.items } { model | items = f model.items }
-- VIEW -- VIEW
{-| Extract the original data set out of the item picker. {-| Extract the original data set out of the item picker.
-} -}
extract : Model a -> Iddict a extract : Model a -> Iddict a
extract = .items extract =
.items
{-| Display the item picker. Note that the item should not be wider than 360px. {-| Display the item picker. Note that the item should not be wider than 360px.
-} -}
@ -56,7 +73,8 @@ view :
, onAddNew : Maybe msg , onAddNew : Maybe msg
, onClick : Int -> msg , onClick : Int -> msg
, width : Int , width : Int
} -> Element msg }
-> Element msg
view data = view data =
Layout.sideList Layout.sideList
{ color = data.colorMenu { color = data.colorMenu

View File

@ -1,4 +1,5 @@
module Items.LoginView exposing (..) module Items.LoginView exposing (..)
{-| The Login screen allows the user to log in, as well as view a short display {-| The Login screen allows the user to log in, as well as view a short display
of what to expect from the Matrix client. of what to expect from the Matrix client.
-} -}
@ -7,15 +8,18 @@ import Color exposing (Color)
import Element exposing (Element) import Element exposing (Element)
import Element.Background import Element.Background
import Element.Border import Element.Border
import Items.FlavorPicker as FlavorPicker
import Layout
import Material.Icons
import Matrix import Matrix
import Matrix.Settings import Matrix.Settings
import Theme import Theme
import Layout
import Items.FlavorPicker as FlavorPicker
import Material.Icons
-- MODEL -- MODEL
type alias Model = type alias Model =
{ accessToken : String { accessToken : String
, loginMethod : LoginMethod , loginMethod : LoginMethod
@ -23,16 +27,19 @@ type alias Model =
, username : String , username : String
} }
type Msg type Msg
= SetAccessToken String = SetAccessToken String
| SetPassword String | SetPassword String
| SetUsername String | SetUsername String
| SwitchMethod LoginMethod | SwitchMethod LoginMethod
type LoginMethod type LoginMethod
= AccessToken = AccessToken
| Password | Password
init : Model init : Model
init = init =
{ accessToken = "" { accessToken = ""
@ -41,8 +48,11 @@ init =
, username = "" , username = ""
} }
-- UPDATE -- UPDATE
update : Msg -> Model -> Model update : Msg -> Model -> Model
update msg model = update msg model =
case msg of case msg of
@ -58,8 +68,11 @@ update msg model =
SwitchMethod method -> SwitchMethod method ->
{ model | loginMethod = method } { model | loginMethod = method }
-- VIEW -- VIEW
view : view :
{ colorBackground : Color { colorBackground : Color
, colorMain : Color , colorMain : Color
@ -73,7 +86,8 @@ view :
, onSubmit : Matrix.Vault -> msg , onSubmit : Matrix.Vault -> msg
, toMsg : Msg -> msg , toMsg : Msg -> msg
, width : Int , width : Int
} -> Element msg }
-> Element msg
view data = view data =
[ viewLoginMethodPicker [ viewLoginMethodPicker
{ color = data.colorMain { color = data.colorMain
@ -147,6 +161,7 @@ view data =
, Element.width (Element.px data.width) , Element.width (Element.px data.width)
] ]
toVault : Model -> Maybe Matrix.Vault toVault : Model -> Maybe Matrix.Vault
toVault model = toVault model =
case model.loginMethod of case model.loginMethod of
@ -168,6 +183,7 @@ toVault model =
|> Matrix.fromUserId |> Matrix.fromUserId
|> Maybe.map (Matrix.Settings.setPassword model.password) |> Maybe.map (Matrix.Settings.setPassword model.password)
viewLoginMethodPicker : { color : Color, loginMethod : LoginMethod, toMsg : LoginMethod -> msg } -> Element msg viewLoginMethodPicker : { color : Color, loginMethod : LoginMethod, toMsg : LoginMethod -> msg } -> Element msg
viewLoginMethodPicker data = viewLoginMethodPicker data =
Layout.tab Layout.tab
@ -182,12 +198,12 @@ viewLoginMethodPicker data =
} }
] ]
, onSelect = , onSelect =
(\i -> \i ->
if i == 0 then if i == 0 then
data.toMsg AccessToken data.toMsg AccessToken
else else
data.toMsg Password data.toMsg Password
)
, selected = , selected =
case data.loginMethod of case data.loginMethod of
AccessToken -> AccessToken ->

View File

@ -1,39 +1,57 @@
module Items.VaultList exposing (..) module Items.VaultList exposing (..)
{-| # Vault list
{-|
# Vault list
The vault list contains a list of stored vaults that can be picked from. The vault list contains a list of stored vaults that can be picked from.
-} -}
import Iddict exposing (Iddict) import Iddict exposing (Iddict)
import Matrix import Matrix
-- MODEL -- MODEL
type alias Model = Iddict VaultBlock
type alias Model =
Iddict VaultBlock
type Msg type Msg
= AddVault { name : String, vault : Matrix.Vault } = AddVault { name : String, vault : Matrix.Vault }
| OnVaultUpdate Int Matrix.VaultUpdate | OnVaultUpdate Int Matrix.VaultUpdate
type alias VaultBlock = type alias VaultBlock =
{ logs : List { channel : String, content : String } { logs : List { channel : String, content : String }
, name : String , name : String
, vault : Matrix.Vault , vault : Matrix.Vault
} }
init : Model init : Model
init = Iddict.empty init =
Iddict.empty
-- UPDATE -- UPDATE
addVault : { name : String, vault : Matrix.Vault } -> Model -> Model addVault : { name : String, vault : Matrix.Vault } -> Model -> Model
addVault = addVault =
AddVault >> update AddVault >> update
insertVaultUpdate : Int -> Matrix.VaultUpdate -> Model -> Model insertVaultUpdate : Int -> Matrix.VaultUpdate -> Model -> Model
insertVaultUpdate i vu = insertVaultUpdate i vu =
update (OnVaultUpdate i vu) update (OnVaultUpdate i vu)
update : Msg -> Model -> Model update : Msg -> Model -> Model
update msg model = update msg model =
case msg of case msg of
@ -55,9 +73,11 @@ update msg model =
) )
model model
-- VIEW -- VIEW
getVault : Int -> Model -> Maybe Matrix.Vault getVault : Int -> Model -> Maybe Matrix.Vault
getVault i model = getVault i model =
Iddict.get i model |> Maybe.map .vault Iddict.get i model |> Maybe.map .vault

View File

@ -1,9 +1,12 @@
module Layout exposing module Layout exposing
( tab, twoBlocks ( twoBlocks
, tab, sideIconBar
, iconAsElement, iconAsIcon , iconAsElement, iconAsIcon
, containedButton, outlinedButton, textButton, sideList , containedButton, outlinedButton, textButton
, textInput, passwordInput , textInput, passwordInput
, loadingIndicator, itemWithSubtext , itemWithSubtext
, sideList
, loadingIndicator
) )
{-| {-|
@ -19,14 +22,17 @@ beautiful Material design Elm webpage.
@docs twoBlocks @docs twoBlocks
## Elements ## Elements
@docs tab @docs tab, sideIconBar
## Icons ## Icons
@docs iconAsElement, iconAsIcon @docs iconAsElement, iconAsIcon
## Buttons ## Buttons
@docs containedButton, outlinedButton, textButton @docs containedButton, outlinedButton, textButton
@ -36,14 +42,17 @@ beautiful Material design Elm webpage.
@docs textInput, passwordInput @docs textInput, passwordInput
## Items in a list ## Items in a list
@docs itemWithSubtext @docs itemWithSubtext
## Lists ## Lists
@docs sideList @docs sideList
## Other elements ## Other elements
@docs loadingIndicator @docs loadingIndicator
@ -52,12 +61,13 @@ beautiful Material design Elm webpage.
import Color exposing (Color) import Color exposing (Color)
import Element exposing (Element) import Element exposing (Element)
import Element.Events
import Element.Input import Element.Input
import Material.Icons.Types
import Widget import Widget
import Widget.Customize as Customize import Widget.Customize as Customize
import Widget.Icon exposing (Icon) import Widget.Icon exposing (Icon)
import Widget.Material as Material import Widget.Material as Material
import Material.Icons.Types
{-| A contained button representing the most important action of a group. {-| A contained button representing the most important action of a group.
@ -79,12 +89,14 @@ containedButton data =
) )
{ text = data.text, icon = data.icon, onPress = data.onPress } { text = data.text, icon = data.icon, onPress = data.onPress }
iconAsElement : iconAsElement :
{ color : Color { color : Color
, height : Int , height : Int
, icon : Material.Icons.Types.Icon msg , icon : Material.Icons.Types.Icon msg
, width : Int , width : Int
} -> Element msg }
-> Element msg
iconAsElement data = iconAsElement data =
data.icon data.icon
|> iconAsIcon |> iconAsIcon
@ -95,10 +107,12 @@ iconAsElement data =
, Element.width (Element.px data.width) , Element.width (Element.px data.width)
] ]
iconAsIcon : Material.Icons.Types.Icon msg -> Widget.Icon.Icon msg iconAsIcon : Material.Icons.Types.Icon msg -> Widget.Icon.Icon msg
iconAsIcon = iconAsIcon =
Widget.Icon.elmMaterialIcons Material.Icons.Types.Color Widget.Icon.elmMaterialIcons Material.Icons.Types.Color
{-| Multiline item {-| Multiline item
-} -}
itemWithSubtext : itemWithSubtext :
@ -123,6 +137,7 @@ itemWithSubtext data =
, text = data.text , text = data.text
} }
{-| Circular loading bar indicator {-| Circular loading bar indicator
-} -}
loadingIndicator : loadingIndicator :
@ -137,6 +152,7 @@ loadingIndicator data =
) )
Nothing Nothing
{-| An outlined button representing an important action within a group. {-| An outlined button representing an important action within a group.
-} -}
outlinedButton : outlinedButton :
@ -154,6 +170,7 @@ outlinedButton data =
) )
{ text = data.text, icon = data.icon, onPress = data.onPress } { text = data.text, icon = data.icon, onPress = data.onPress }
{-| Show a password field {-| Show a password field
-} -}
passwordInput : passwordInput :
@ -201,10 +218,48 @@ singlePalette { primary, onPrimary } =
} }
} }
sideIconBar :
{ colorBackground : Color
, colorText : Color
, height : Int
, items : List { icon : Widget.Icon.Icon msg, onPress : msg, text : String }
, width : Int
}
-> Element msg
sideIconBar data =
let
buttonHeight =
round (toFloat data.width * 1.618)
iconSize =
data.width // 2
in
data.items
|> List.map
(\item ->
[ item.icon { size = iconSize, color = data.colorText }
, Element.paragraph [] [ Element.text item.text ]
]
|> Element.column [ Element.centerX, Element.centerY ]
|> Element.el
[ Element.Events.onClick item.onPress
, Element.height (Element.px buttonHeight)
, Element.width (Element.px data.width)
]
)
|> Element.column
[ Element.height (Element.px data.height)
, Element.scrollbarY
, Element.width (Element.px data.width)
]
sideList : { color : Color, items : List (Widget.Item msg), width : Int } -> Element msg sideList : { color : Color, items : List (Widget.Item msg), width : Int } -> Element msg
sideList data = sideList data =
let let
width px = Element.width (Element.px px) width px =
Element.width (Element.px px)
in in
Widget.itemList Widget.itemList
({ primary = data.color, onPrimary = data.color } ({ primary = data.color, onPrimary = data.color }
@ -215,6 +270,7 @@ sideList data =
|> Element.el [ Element.centerX, width (Basics.min 360 data.width) ] |> Element.el [ Element.centerX, width (Basics.min 360 data.width) ]
|> Element.el [ width data.width ] |> Element.el [ width data.width ]
{-| A tab selector that always has an item selected. {-| A tab selector that always has an item selected.
-} -}
tab : tab :
@ -285,6 +341,7 @@ textInput data =
, onChange = data.onChange , onChange = data.onChange
} }
{-| Two blocks either next to each other or below each other, depending on the {-| Two blocks either next to each other or below each other, depending on the
screen shape. screen shape.
-} -}
@ -293,13 +350,33 @@ twoBlocks :
, el1 : { height : Int, width : Int } -> Element msg , el1 : { height : Int, width : Int } -> Element msg
, el2 : { height : Int, width : Int } -> Element msg , el2 : { height : Int, width : Int } -> Element msg
, width : Int , width : Int
} -> Element msg }
-> Element msg
twoBlocks data = twoBlocks data =
let let
goesVertical = 2 * data.width <= 3 * data.height goesVertical =
direction = if goesVertical then Element.column else Element.row 2 * data.width <= 3 * data.height
width = if goesVertical then data.width else data.width // 2
height = if goesVertical then data.height // 2 else data.height direction =
if goesVertical then
Element.column
else
Element.row
width =
if goesVertical then
data.width
else
data.width // 2
height =
if goesVertical then
data.height // 2
else
data.height
in in
direction direction
[ Element.height (Element.px data.height) [ Element.height (Element.px data.height)

View File

@ -5,14 +5,14 @@ import Browser.Dom
import Browser.Events import Browser.Events
import Element exposing (Element) import Element exposing (Element)
import Element.Background import Element.Background
import Element.Font
import Items.VaultList as VaultList
import Matrix
import Recursion
import Screen.Vault as VaultScreen
import Screen.Welcome as WelcomeScreen
import Task import Task
import Theme import Theme
import Items.VaultList as VaultList
import Screen.Welcome as WelcomeScreen
import Screen.Vault as VaultScreen
import Element.Font
import Recursion
import Matrix
main : Program () Model Msg main : Program () Model Msg
@ -36,10 +36,12 @@ type alias Model =
, width : Int , width : Int
} }
type Screen type Screen
= ScreenWelcome WelcomeScreen.Model = ScreenWelcome WelcomeScreen.Model
| ScreenVault Vaults Int VaultScreen.Model | ScreenVault Vaults Int VaultScreen.Model
type Msg type Msg
= OnScreenVault Int VaultScreen.Msg = OnScreenVault Int VaultScreen.Msg
| OnScreenWelcome WelcomeScreen.Msg | OnScreenWelcome WelcomeScreen.Msg
@ -49,7 +51,9 @@ type Msg
| ScreenSize { height : Int, width : Int } | ScreenSize { height : Int, width : Int }
| SetFlavor Theme.Flavor | SetFlavor Theme.Flavor
type alias Vaults = VaultList.Model
type alias Vaults =
VaultList.Model
init : () -> ( Model, Cmd Msg ) init : () -> ( Model, Cmd Msg )
@ -86,6 +90,7 @@ update msg model =
( { model | screen = ScreenVault welcomeMdl i newMdl } ( { model | screen = ScreenVault welcomeMdl i newMdl }
, Cmd.none , Cmd.none
) )
else else
( model, Cmd.none ) ( model, Cmd.none )
@ -114,6 +119,7 @@ update msg model =
ScreenVault _ j old -> ScreenVault _ j old ->
if i == j then if i == j then
ScreenVault vaults j old ScreenVault vaults j old
else else
ScreenVault vaults i VaultScreen.init ScreenVault vaults i VaultScreen.init
} }
@ -174,15 +180,27 @@ view model =
|> List.singleton |> List.singleton
} }
viewScreen : Model -> Element Msg viewScreen : Model -> Element Msg
viewScreen model = viewScreen model =
let let
colorBackground = Theme.base model.flavor colorBackground =
colorBackground2 = Theme.mantle model.flavor Theme.base model.flavor
colorMain = Theme.mauve model.flavor
colorSurface0 = Theme.surface0 model.flavor colorBackground2 =
colorSurface1 = Theme.surface1 model.flavor Theme.mantle model.flavor
colorText = Theme.text model.flavor
colorMain =
Theme.mauve model.flavor
colorSurface0 =
Theme.surface0 model.flavor
colorSurface1 =
Theme.surface1 model.flavor
colorText =
Theme.text model.flavor
in in
Recursion.runRecursion Recursion.runRecursion
(\screen -> (\screen ->
@ -226,4 +244,3 @@ viewScreen model =
|> Recursion.base |> Recursion.base
) )
model.screen model.screen

View File

@ -4,25 +4,39 @@ import Color exposing (Color)
import Element exposing (Element) import Element exposing (Element)
import Matrix import Matrix
-- MODEL -- MODEL
type alias Model = ()
type alias Msg = () type alias Model =
()
type alias Msg =
()
init : Model init : Model
init = () init =
()
-- UPDATE -- UPDATE
update : Msg -> Model -> Model update : Msg -> Model -> Model
update msg model = update msg model =
case msg of case msg of
() -> () ->
model model
-- VIEW -- VIEW
view : view :
{ colorBackground : Color { colorBackground : Color
, colorText : Color , colorText : Color
@ -32,7 +46,7 @@ view :
, toMsg : Msg -> msg , toMsg : Msg -> msg
, vault : Matrix.Vault , vault : Matrix.Vault
, width : Int , width : Int
} -> Element msg }
-> Element msg
view data = view data =
Element.none Element.none

View File

@ -1,23 +1,27 @@
module Screen.Welcome exposing (..) module Screen.Welcome exposing (..)
import Color exposing (Color) import Color exposing (Color)
import Element exposing (Element)
import Items.Introduction as Introduction import Items.Introduction as Introduction
import Items.ItemPicker as ItemPicker import Items.ItemPicker as ItemPicker
import Items.VaultList as VaultList
import Matrix
import Items.LoginView as LoginView import Items.LoginView as LoginView
import Element exposing (Element) import Items.VaultList as VaultList
import Layout import Layout
import Matrix
import Matrix.Settings import Matrix.Settings
import Theme import Theme
-- MODEL -- MODEL
type alias Model = type alias Model =
{ login : Maybe LoginView.Model { login : Maybe LoginView.Model
, vaults : ItemPicker.Model VaultList.VaultBlock , vaults : ItemPicker.Model VaultList.VaultBlock
} }
type Msg type Msg
= OnAddNew = OnAddNew
| OnLogin LoginView.Msg | OnLogin LoginView.Msg
@ -25,20 +29,25 @@ type Msg
| OnVaultUpdate Int Matrix.VaultUpdate | OnVaultUpdate Int Matrix.VaultUpdate
| OnVaults ItemPicker.Msg | OnVaults ItemPicker.Msg
init : Model init : Model
init = init =
{ login = Nothing -- Just LoginView.init { login = Nothing -- Just LoginView.init
, vaults = ItemPicker.init VaultList.init , vaults = ItemPicker.init VaultList.init
} }
fromVaults : VaultList.Model -> Model fromVaults : VaultList.Model -> Model
fromVaults items = fromVaults items =
{ login = Nothing { login = Nothing
, vaults = ItemPicker.init items , vaults = ItemPicker.init items
} }
-- UPDATE -- UPDATE
update : Msg -> Model -> Model update : Msg -> Model -> Model
update msg model = update msg model =
case msg of case msg of
@ -59,12 +68,16 @@ update msg model =
OnVaults m -> OnVaults m ->
{ model | vaults = ItemPicker.update m model.vaults } { model | vaults = ItemPicker.update m model.vaults }
updateVault : Int -> Matrix.VaultUpdate -> Model -> Model updateVault : Int -> Matrix.VaultUpdate -> Model -> Model
updateVault i vu = updateVault i vu =
update (OnVaultUpdate i vu) update (OnVaultUpdate i vu)
-- VIEW -- VIEW
view : view :
{ colorBackground : Color { colorBackground : Color
, colorBackground2 : Color , colorBackground2 : Color
@ -79,10 +92,12 @@ view :
, onSelectVault : VaultList.Model -> Int -> msg , onSelectVault : VaultList.Model -> Int -> msg
, toMsg : Msg -> msg , toMsg : Msg -> msg
, width : Int , width : Int
} -> Element msg }
-> Element msg
view data = view data =
let let
onSelectVault = data.onSelectVault (ItemPicker.extract data.model.vaults) onSelectVault =
data.onSelectVault (ItemPicker.extract data.model.vaults)
in in
case data.model.login of case data.model.login of
Just login -> Just login ->
@ -141,7 +156,8 @@ viewIntroduction :
, onAddNew : Maybe msg , onAddNew : Maybe msg
, onSelectVault : Int -> msg , onSelectVault : Int -> msg
, width : Int , width : Int
} -> Element msg }
-> Element msg
viewIntroduction data = viewIntroduction data =
[ Introduction.view { colorBackground = data.colorBackground, width = data.width } [ Introduction.view { colorBackground = data.colorBackground, width = data.width }
, ItemPicker.view , ItemPicker.view