alexbruf/elm-cally/1.0.0

NOTE: the latest version is 1.1.0

Cally.Range

The date-range picker, a port of calendar-range/calendar-range.tsx.

Renders as <calendar-range>. The first click on a day starts a range and fires onRangeStart; the range then follows the pointer (and the keyboard) until a second click sorts the pair, fires onRangeEnd and then onChange.

type alias Value =
Maybe ( Date, Date )

What this picker selects: a start and an end, or nothing. The pair is always sorted.

type alias Model =
{ focusedDate : Date
, page : Page
, tentative : Maybe Date
, hovered : Maybe Date
}

Everything the picker remembers for itself.

tentative is the first click of a range, Cally's tentative property, and hovered is the day the provisional range currently reaches to.

type Msg

Opaque. Route it back with update through Config.toMsg.

type alias Config msg =
{ id : String
, today : Date
, locale : Locale
, min : Maybe Date
, max : Maybe Date
, months : Int
, pageBy : PageBy
, firstDayOfWeek : Weekday
, formatWeekday : WeekdayFormat
, showOutsideDays : Bool
, showWeekNumbers : Bool
, isDateDisallowed : Date -> Bool
, getDayParts : Date -> List String
, previous : Html msg
, next : Html msg
, heading : Maybe (Context msg -> Html msg)
, toMsg : Msg -> msg
, onChange : Value -> msg
, onFocusDay : Maybe (Date -> msg)
, onPageChange : Maybe (( Date, Date ) -> msg)
, onRangeStart : Maybe (Date -> msg)
, onRangeEnd : Maybe (Date -> msg)
}

Everything Cally takes as a prop, plus the messages this picker sends you.

id prefixes every DOM id the picker renders, so it must be unique on the page and stable across renders; focus uses those ids.

type PageBy
= Months
| Single

How the previous and next buttons move: a whole page of months at a time, or one month at a time. Cally's page-by.

= Day
| Next
| Previous

What focus should put the browser focus on.

{ id : String
, today : Date
, locale : Locale
, toMsg : Msg -> msg
, onChange : Value -> msg
}
-> Config msg

A Config with Cally's defaults: one month, paged by months, narrow weekday names, no outside days, no week numbers, and the locale's own first day of the week.

init : Config msg -> Value -> Model

The starting model. Focus lands on the start of the value, or on today when there is no value, clamped to min and max.

Config msg
-> Value
-> Model
-> List (Context msg -> Html msg)
-> Html msg

Render the picker. The children are the months, and anything else that reads the Context; each one is applied to the Context so it can sit anywhere in the tree.

update : Config msg -> Value -> Msg -> Model -> ( Model, Cmd msg )

The update you wire into your own.

Consumer callbacks (onChange, onFocusDay, onPageChange) come back as commands, so they arrive as ordinary messages on the next update. The command also carries the Browser.Dom.focus call that keyboard navigation needs.

Config msg
-> Value
-> Msg
-> Model
-> { model : Model
, events : List msg
, focus : Maybe FocusTarget
}

The pure core of update.

events are the callbacks the message produced, in the order Cally dispatches them, and focus is the element the picker wants the browser focus on afterwards (Cally's setTimeout(focus)). update is this function with the two turned into commands; tests use this one.

focus : Config msg -> Model -> FocusTarget -> Cmd msg

Put the browser focus on the day that holds tabindex="0", or on one of the paging buttons. Cally's focus({ target }).

focusDate : Config msg -> Date -> Model -> Model

Move the roving focus, Cally's focused-date property. The date is clamped to min and max, and the page follows it.

context : Config msg -> Value -> Model -> Context msg

The Context this picker hands its children. Exposed so you can build a child on your own, and so tests can inspect it.