Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jeongoon/elmnt-scrollpicker
elm-ui compatible scroll picker
https://github.com/jeongoon/elmnt-scrollpicker
elm elm-lang elm-ui picker scroll
Last synced: about 2 months ago
JSON representation
elm-ui compatible scroll picker
- Host: GitHub
- URL: https://github.com/jeongoon/elmnt-scrollpicker
- Owner: jeongoon
- License: osl-3.0
- Created: 2021-12-03T09:36:01.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2022-01-30T10:46:16.000Z (almost 3 years ago)
- Last Synced: 2024-10-20T00:59:25.467Z (3 months ago)
- Topics: elm, elm-lang, elm-ui, picker, scroll
- Language: Elm
- Homepage: https://package.elm-lang.org/packages/jeongoon/elmnt-scrollpicker/latest/
- Size: 281 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[setOptions]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#setOptions
[initMinimalState]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#initMinimalState
[setScrollStopCheckTime]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#setScrollStopCheckTime
[subscriptionsWith]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#subscriptionsWith
[defaultTheme]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#defaultTheme
[MinimalState]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#MinimalState
[Option]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#Option
[Msg]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#Msg
[anyNewOptionSelected]: /packages/jeongoon/elmnt-scrollpicker/latest/Elmnt-BaseScrollPicker#anyNewOptionSelected
[exampleUrl]: https://jeongoon.github.io/examples/7Dec2021.BaseScrollPicker.html# An Elm-Ui friendly Scroll Picker
```shell
elm install jeongoon/elmnt-scrollpicker
````elmnt-scrollpicker` provides an scroll picker with some animation. `elmnt`
is stands for [`Element`](https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/)
so you can use the View(widget) as an element in elm-ui.[See it in action here.][exampleUrl]
# Usage
This is low level module, So let me examplain fully. however If you are familiar
with other *Elm architecture* style module, it is easier. Or you have
chance to get used to it.## Import
```elm
import Element exposing (..)
import Dict exposing (Dict)
-- ^ options are stored in Dict
import Elmnt.BaseScrollPicker as ScrollPicker
-- ^ or as you'd like
```## Make your own Model and Msg
```elm
type AppMsg
= ScrollPickerMessage String
(ScrollPicker.Msg Int AppMsg)
```ScrollPicker.Msg type involves the type of Your own message (AppMsg)
and also the type of options that we'd like to pick from.
`Int` is used for [`Option`][Option] in this case.Some states of picker are required to store in internal record.
you might need to declare your own message wrapper
constructor *ScrollPickerMessage* is an wrapper constructor (or map function) to
create messages which is compatible to your own module message.Let's say we are making a simple time picker, we need two seprate
pickers for hour and minute value. If you want a Dict or List
go for it!```elm
type alias Model -- which is your own model
= { firstPickerState
: ScrollPicker.MinimalState Int AppMsg
, secondPickerState
: ScrollPicker.MinimalState Int AppMsg
, messageMapWith
: String -> (ScrollPicker.Msg Int AppMsg) ->
AppMsg
, pickerDirection
: ScrollPicker.Direction -- Horizontal or Vertical
}
```## Model
[`MinimalState`][MinimalState] shows the minimal states required to work
as a scroll picker. And even if you put *more* fields in your record,
all the function will still works with yours. Because the most of API
use partial record annotation.For example [`setOptions`][setOptions] function has the definition like below.
```elm
setOptions
: (vt -> String) -> -- vt stands for 'value type'
List (vt, Element msg) ->
{ state |
idString : String
, optionIds : List String
, optionIdToRecordDict : Dict String
(Option vt msg)
} -> -- At least, those fields are required
-- in the state record
{ state |
idString : String
, optionIds : List String
, optionIdToRecordDict : Dict String
(Option vt msg)
} --> will return the same structure of
-- the state record
```which makes setOptions can be provided with a subset of MinimalState.
## Init
Let's initialise our example model. Each picker model(or state) could be
initialised with functions such as [`initMinimalState`][initMinimalState],
[`setOptions`][setOptions] and [`setScrollStopCheckTime`][setScrollStopCheckTime]```elm
exampleInit : () -> ( Model, Cmd AppMsg )
exampleInit flags
= ( { firstPickerState -- for hour value
= ScrollPicker.initMinimalState
"firstScrollPicker" -- id
|> ScrollPicker.setOptions
(String.fromInt)
(List.range 1 12
|> List.map
( \n ->
( n
, n
|> ( String.fromInt >> text )
)
)
)
|> ScrollPicker.setScrollStopCheckTime 75
-- ^ a bit more quicker to check, secondPickerState -- for minute value
= ScrollPicker.initMinimalState
"secondScrollPicker"
|> ScrollPicker.setOptions
(String.fromInt)
(List.range 0 59
|> List.map
( \n ->
( n
, n
|> ( String.fromInt
>> String.padLeft 2 '0'
>> text
)
)
)
), messageMapWith
= ScrollPickerMessage
-- ^ a map function to wrap the picker messages
-- into the Msg, pickerDirection
= ScrollPicker.Vertical
}
```## Update
In your own update function, you might need to check picker Id and update
the matched picker state(or model) accordingly.```elm
exampleUpdate : AppMsg -> Model ->
( Model, Cmd AppMsg )
exampleUpdate msg model
= let update
= ScrollPicker.updateWith model
in
case msg of
ScrollPickerMessage idString pickerMsg ->
case idString of
"firstScrollPicker" ->
let ( firstPickerState, cmd )
= update pickerMsg
model.firstPickerStatenewModel
= { model |
firstPickerState
= firstPickerState
}
in ( case ScrollPicker.anyNewOptionSelected
pickerMsg ofJust option ->
{ newModel |
hourValue
= option.value
}
Nothing ->
newModel
, cmd
)"secondScrollPicker" ->
let ( secondPickerState, cmd )
= update pickerMsg
model.secondPickerStatenewModel
= { model |
secondPickerState
= secondPickerState
}
in ( case ScrollPicker.anyNewOptionSelected
pickerMsg ofJust option ->
{ newModel |
minuteValue
= option.value
}
Nothing ->
newModel
, cmd
)_ ->
( model, Cmd.none )
```And picker model itself *does not* hold selected option, you also need to
check some message [`Elmnt.BasePickerState.ScrollPickerSuccess`][Msg]
or you can use [`anyNewOptionSelected`][anyNewOptionSelected] function like above code.## View
Here is an example
```elm
exampleView : Model -> Html AppMsg
exampleView model
= let
theme
= defaultThemepalette
= theme.palettepickerHelper
= ScrollPicker.viewAsElement model themein
layout [ Background.color
(palette.on.surface
-- ^ use same color as shade
|> palette.toElmUiColor)
] <|
column [ centerX
, centerY
]
[ row [ spacing 1
]
[ pickerHelper model.firstPickerState
, pickerHelper model.secondPickerState
], el [ paddingEach
{ top = 20
, right = 0
, bottom = 0
, left = 0
}
, Font.size
( (modular 16 1.25 8)
|> (*) 0.7
|> truncate
)
, Font.color
( palette.secondary
|> palette.toElmUiColor )
, centerX
] <|
text <| "It's " ++
( model.hourValue
|> String.fromInt
) ++ ":" ++
( model.minuteValue
|> String.fromInt
|> String.padLeft 2 '0'
)
]
```## Subscriptions
Animation relies on subscriptions. elm-style-animation also does so.
[`subscriptionsWith`][subscriptionsWith] helps how to subscribe.```elm
exampleSubscriptions : Model -> Sub AppMsg
exampleSubscriptions model
= model |>
ScrollPicker.subscriptionsWith
[ model.firstPickerState
, model.secondPickerState
]
```## Main
Finally you can wire thems up in the elm architecture.
```elm
main : Program () Model AppMsg
main
= Browser.element
{ init = exampleInit
, view = exampleView
, update = exampleUpdate
, subscriptions = exampleSubscriptions
}
```# Testing Environment
- Firefox (currently 94.0.1) on Arch linux
- Vivaldi
- [`Gnome Web Epiphany`](https://apps.gnome.org/en-GB/app/org.gnome.Epiphany/)I'm a chef and not a professional programmer but have been still using Linux
since 2001. My 8 years old laptop can only run Linux smoothly.
And I don't have enough chance to check things on Apple product, either.so, if you need more techincal support on other platform, please contribute
your solution.# More Information
**Why elm-style-animation?** [`elm-style-animation`](/packages/mdgriffith/elm-style-animation/latest)
is not quite designed for low level animation. but you could use the module
for any other css-style based animation. So you could possibly add other
animation in your app without any additional module.[`elm-animation`](/packages/mgold/elm-animation/latest) was also considered,
and *it is* pretty straight-foward.
However the module cannot live together in the same application due to name
colision.