Merge branch 'master' into lab/stickyable-segmented-control

This commit is contained in:
Tessa 2020-08-04 21:44:47 -07:00 committed by GitHub
commit ef6ee0ab21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 9 additions and 369 deletions

View File

@ -49,7 +49,6 @@
"Nri.Ui.Select.V7",
"Nri.Ui.Slide.V1",
"Nri.Ui.SlideModal.V2",
"Nri.Ui.SortableTable.V1",
"Nri.Ui.SortableTable.V2",
"Nri.Ui.Svg.V1",
"Nri.Ui.Table.V4",

View File

@ -2,7 +2,6 @@ filename,name,version
src/Nri/Ui/Page/V3.elm,Nri.Ui.Text,2
src/Nri/Ui/SlideModal/V2.elm,Nri.Ui.Button,8
src/Nri/Ui/SlideModal/V2.elm,Nri.Ui.Text,2
src/Nri/Ui/SortableTable/V1.elm,Nri.Ui.Table,4
src/Nri/Ui/Button/V8.elm,Html,DEPRECATED
src/Nri/Ui/Icon/V3.elm,Accessibility.Role,DEPRECATED
src/Nri/Ui/Icon/V3.elm,Html,DEPRECATED

1 filename name version
2 src/Nri/Ui/Page/V3.elm Nri.Ui.Text 2
3 src/Nri/Ui/SlideModal/V2.elm Nri.Ui.Button 8
4 src/Nri/Ui/SlideModal/V2.elm Nri.Ui.Text 2
src/Nri/Ui/SortableTable/V1.elm Nri.Ui.Table 4
5 src/Nri/Ui/Button/V8.elm Html DEPRECATED
6 src/Nri/Ui/Icon/V3.elm Accessibility.Role DEPRECATED
7 src/Nri/Ui/Icon/V3.elm Html DEPRECATED

View File

@ -1,362 +0,0 @@
module Nri.Ui.SortableTable.V1 exposing
( Column, Config, Sorter, State
, init, initDescending
, custom, string, view, viewLoading
, invariantSort, simpleSort, combineSorters
)
{-|
@docs Column, Config, Sorter, State
@docs init, initDescending
@docs custom, string, view, viewLoading
@docs invariantSort, simpleSort, combineSorters
-}
import Color
import Css exposing (..)
import Css.Global exposing (Snippet, adjacentSiblings, children, class, descendants, each, everything, media, selector, withClass)
import Html.Styled as Html exposing (Html)
import Html.Styled.Attributes exposing (css)
import Html.Styled.Events
import Nri.Ui.Colors.Extra
import Nri.Ui.Colors.V1
import Nri.Ui.CssVendorPrefix.V1 as CssVendorPrefix
import Nri.Ui.Table.V4
import Svg.Styled as Svg exposing (Svg)
import Svg.Styled.Attributes as SvgAttributes
type SortDirection
= Ascending
| Descending
{-| -}
type alias Sorter a =
SortDirection -> a -> a -> Order
{-| -}
type Column id entry msg
= Column
{ id : id
, header : Html msg
, view : entry -> Html msg
, sorter : Sorter entry
, width : Int
}
{-| -}
type alias State id =
{ column : id
, sortDirection : SortDirection
}
{-| -}
type alias Config id entry msg =
{ updateMsg : State id -> msg
, columns : List (Column id entry msg)
}
{-| -}
init : id -> State id
init initialSort =
{ column = initialSort
, sortDirection = Ascending
}
{-| -}
initDescending : id -> State id
initDescending initialSort =
{ column = initialSort
, sortDirection = Descending
}
{-| -}
string :
{ id : id
, header : String
, value : entry -> String
, width : Int
}
-> Column id entry msg
string { id, header, value, width } =
Column
{ id = id
, header = Html.text header
, view = value >> Html.text
, sorter = simpleSort value
, width = width
}
{-| -}
custom :
{ id : id
, header : Html msg
, view : entry -> Html msg
, sorter : Sorter entry
, width : Int
}
-> Column id entry msg
custom config =
Column
{ id = config.id
, header = config.header
, view = config.view
, sorter = config.sorter
, width = config.width
}
{-| Create a sorter function that always orders the entries in the same order.
For example, this is useful when we want to resolve ties and sort the tied
entries by name, no matter of the sort direction set on the table.
-}
invariantSort : (entry -> comparable) -> Sorter entry
invariantSort mapper =
\sortDirection elem1 elem2 ->
compare (mapper elem1) (mapper elem2)
{-| Create a simple sorter function that orders entries by mapping a function
over the collection. It will also reverse it when the sort direction is descending.
-}
simpleSort : (entry -> comparable) -> Sorter entry
simpleSort mapper =
\sortDirection elem1 elem2 ->
let
result =
compare (mapper elem1) (mapper elem2)
in
case sortDirection of
Ascending ->
result
Descending ->
flipOrder result
flipOrder : Order -> Order
flipOrder order =
case order of
LT ->
GT
EQ ->
EQ
GT ->
LT
{-| -}
combineSorters : List (Sorter entry) -> Sorter entry
combineSorters sorters =
\sortDirection elem1 elem2 ->
let
folder =
\sorter acc ->
case acc of
EQ ->
sorter sortDirection elem1 elem2
_ ->
acc
in
List.foldl folder EQ sorters
{-| -}
viewLoading : Config id entry msg -> State id -> Html msg
viewLoading config state =
let
tableColumns =
List.map (buildTableColumn config.updateMsg state) config.columns
in
Nri.Ui.Table.V4.viewLoading
tableColumns
{-| -}
view : Config id entry msg -> State id -> List entry -> Html msg
view config state entries =
let
tableColumns =
List.map (buildTableColumn config.updateMsg state) config.columns
sorter =
findSorter config.columns state.column
in
Nri.Ui.Table.V4.view
tableColumns
(List.sortWith (sorter state.sortDirection) entries)
findSorter : List (Column id entry msg) -> id -> Sorter entry
findSorter columns columnId =
columns
|> listExtraFind (\(Column column) -> column.id == columnId)
|> Maybe.map (\(Column column) -> column.sorter)
|> Maybe.withDefault identitySorter
{-| Taken from <https://github.com/elm-community/list-extra/blob/8.2.0/src/List/Extra.elm#L556>
-}
listExtraFind : (a -> Bool) -> List a -> Maybe a
listExtraFind predicate list =
case list of
[] ->
Nothing
first :: rest ->
if predicate first then
Just first
else
listExtraFind predicate rest
identitySorter : Sorter a
identitySorter =
\sortDirection item1 item2 ->
EQ
buildTableColumn : (State id -> msg) -> State id -> Column id entry msg -> Nri.Ui.Table.V4.Column entry msg
buildTableColumn updateMsg state (Column column) =
Nri.Ui.Table.V4.custom
{ header = viewSortHeader column.header updateMsg state column.id
, view = column.view
, width = Css.px (toFloat column.width)
}
viewSortHeader : Html msg -> (State id -> msg) -> State id -> id -> Html msg
viewSortHeader header updateMsg state id =
let
nextState =
nextTableState state id
in
Html.div
[ css
[ Css.displayFlex
, Css.alignItems Css.center
, Css.justifyContent Css.spaceBetween
, cursor pointer
, CssVendorPrefix.property "user-select" "none"
, if state.column == id then
fontWeight bold
else
fontWeight normal
]
, Html.Styled.Events.onClick (updateMsg nextState)
]
[ Html.div [] [ header ]
, viewSortButton updateMsg state id
]
viewSortButton : (State id -> msg) -> State id -> id -> Html msg
viewSortButton updateMsg state id =
let
arrows upHighlighted downHighlighted =
Html.div
[ css
[ Css.displayFlex
, Css.flexDirection Css.column
, Css.alignItems Css.center
, Css.justifyContent Css.center
]
]
[ sortArrow Up upHighlighted
, sortArrow Down downHighlighted
]
buttonContent =
case ( state.column == id, state.sortDirection ) of
( True, Ascending ) ->
arrows True False
( True, Descending ) ->
arrows False True
( False, _ ) ->
arrows False False
in
Html.div [ css [ padding (px 2) ] ] [ buttonContent ]
nextTableState : State id -> id -> State id
nextTableState state id =
if state.column == id then
{ column = id
, sortDirection = flipSortDirection state.sortDirection
}
else
{ column = id
, sortDirection = Ascending
}
flipSortDirection : SortDirection -> SortDirection
flipSortDirection order =
case order of
Ascending ->
Descending
Descending ->
Ascending
type Direction
= Up
| Down
sortArrow : Direction -> Bool -> Html msg
sortArrow direction active =
Html.div
[ css
[ width (px 8)
, height (px 6)
, position relative
, margin2 (px 1) zero
]
]
[ Svg.svg
[ SvgAttributes.viewBox "0 0 8 6"
, SvgAttributes.css
[ position absolute
, top zero
, left zero
, case direction of
Up ->
Css.batch []
Down ->
Css.batch [ transform <| rotate (deg 180) ]
]
, if active then
SvgAttributes.fill (toCssString Nri.Ui.Colors.V1.azure)
else
SvgAttributes.fill (toCssString Nri.Ui.Colors.V1.gray75)
]
[ Svg.polygon [ SvgAttributes.points "0 6 4 0 8 6 0 6" ] []
]
]
toCssString : Css.Color -> String
toCssString =
Color.toRGBString << Nri.Ui.Colors.Extra.fromCssColor

View File

@ -12,7 +12,7 @@ import Example exposing (Example)
import Html.Styled as Html
import KeyboardSupport exposing (Direction(..), Key(..))
import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.SortableTable.V1 as SortableTable
import Nri.Ui.SortableTable.V2 as SortableTable
type Column
@ -35,7 +35,7 @@ type alias State =
{-| -}
example : Example State Msg
example =
{ name = "Nri.Ui.SortableTable.V1"
{ name = "Nri.Ui.SortableTable.V2"
, categories = [ Tables, Layout ]
, atomicDesignType = Molecule
, keyboardSupport = []
@ -53,12 +53,14 @@ example =
, header = "First name"
, value = .firstName
, width = 125
, cellStyles = \_ -> []
}
, SortableTable.string
{ id = LastName
, header = "Last name"
, value = .lastName
, width = 125
, cellStyles = \_ -> []
}
, SortableTable.custom
{ id = Coins
@ -66,6 +68,7 @@ example =
, view = .coins >> String.fromInt >> Html.text
, sorter = SortableTable.simpleSort .coins
, width = 125
, cellStyles = \_ -> []
}
]
}

View File

@ -1,8 +1,8 @@
module Spec.Nri.Ui.SortableTable.V1 exposing (spec)
module Spec.Nri.Ui.SortableTable.V2 exposing (spec)
import Expect exposing (Expectation)
import Html.Styled
import Nri.Ui.SortableTable.V1 as SortableTable
import Nri.Ui.SortableTable.V2 as SortableTable
import Test exposing (..)
import Test.Html.Query as Query
import Test.Html.Selector as Selector
@ -33,12 +33,14 @@ config =
, header = "First name"
, value = .firstName
, width = 125
, cellStyles = \_ -> []
}
, SortableTable.string
{ id = LastName
, header = "Last name"
, value = .lastName
, width = 125
, cellStyles = \_ -> []
}
]
}

View File

@ -45,7 +45,6 @@
"Nri.Ui.Select.V7",
"Nri.Ui.Slide.V1",
"Nri.Ui.SlideModal.V2",
"Nri.Ui.SortableTable.V1",
"Nri.Ui.SortableTable.V2",
"Nri.Ui.Svg.V1",
"Nri.Ui.Table.V4",