📜 Items rolled up on both sides of a focus
→ good fit for dynamic choice selection: tabs, playlist, timeline...
Scroll can even focus a gap Down or Up from every item.
Not what you were looking for? Check out alternatives.
Position in a Scroll relative to its focus.
import Linear exposing (DirectionLinear(..))
import Emptiable exposing (Emptiable, filled, fillMap, fillMapFlat)
import Stack exposing (topDown)
Scroll.only 0
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.to (Scroll.AtSide Up 2)
|> fillMap Scroll.focusItem
--> filled 3
--: Emptiable (Stacked number_) PossiblyThe Location directly Down|Up the focus.
import Emptiable exposing (Emptiable, filled, fillMap)
import Stack exposing (onTopLay, topDown)
import Scroll exposing (Scroll, FocusGap)
import Linear exposing (DirectionLinear(..))
Scroll.only "hello"
|> Scroll.sideAlter
( Up, \_ -> topDown "scrollable" [ "world" ] )
|> Scroll.toEnd Up
|> Scroll.to (Down |> Scroll.nearest)
|> fillMap Scroll.focusItem
--> filled "scrollable"
--: Emptiable (Scroll String FocusGap Never) Possibly
Scroll.empty
|> Scroll.sideAlter
( Down, \_ -> topDown "world" [ "scrollable" ] )
|> Scroll.to (Down |> Scroll.nearest)
--> Scroll.only "world"
--> |> Scroll.sideAlter
--> ( Down, \_ -> Stack.only "scrollable" )
--> |> filled
--: Emptiable (Scroll String FocusGap Never) Possibly
Scroll.empty
|> Scroll.sideAlter
( Up, onTopLay "foo" )
|> Scroll.to (Up |> Scroll.nearest)
--> filled (Scroll.only "foo")
--: Emptiable (Scroll String FocusGap Never) Possibly
nearest =
\side ->
Scroll.AtSide side 0An empty Scroll on a gap
with nothing before and after it.
It's the loneliest of all Scrolls.
<>import Emptiable
Scroll.empty |> Scroll.toStack
--> Emptiable.emptyA Scroll with a single focussed item in it,
nothing Down and Up it.
🍊 -> <🍊>import Stack
Scroll.only "wat" |> Scroll.focusItem
--> "wat"
Scroll.only "wat" |> Scroll.toStack
--> Stack.only "wat"The focused item.
🍍 🍓 <🍊> 🍉 🍇 -> 🍊import Stack exposing (topDown)
import Linear exposing (DirectionLinear(..))
Scroll.only "hi there" |> Scroll.focusItem
--> "hi there"
Scroll.only 1
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ 3, 4 ] )
|> Scroll.toEnd Up
|> Scroll.focusItem
--> 4The focused item or gap.
🍍 🍓 <🍊> 🍉 🍇 -> 🍊
🍍 🍓 <> 🍉 🍇 -> _import Emptiable exposing (filled, fill)
Scroll.empty |> Scroll.focus
--> Emptiable.empty
Scroll.only "hi there" |> Scroll.focus |> fill
--> "hi there"focusItem is short for focus |> fill.
The Stack to one side of the focus.
Down
🍍←🍓) <🍊> 🍉 🍇Up
🍍 🍓 <🍊> (🍉→🍇import Emptiable exposing (Emptiable, fillMapFlat)
import Stack exposing (Stacked, topDown)
import Linear exposing (DirectionLinear(..))
Scroll.only 0
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.to (Up |> Scroll.nearest)
|> fillMapFlat (Scroll.to (Up |> Scroll.nearest))
|> fillMapFlat (Scroll.side Down)
--> topDown 1 [ 0 ]
--: Emptiable (Stacked number_) Possibly
Scroll.only 0
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.to (Up |> Scroll.nearest)
|> fillMapFlat (Scroll.side Up)
--> topDown 2 [ 3 ]
--: Emptiable (Stacked number_) PossiblyCounting all contained items.
import Stack exposing (topDown)
import Linear exposing (DirectionLinear(..))
Scroll.only 0
|> Scroll.sideAlter
( Down, \_ -> topDown -1 [ -2 ] )
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.length
--> 6
Scroll.empty
|> Scroll.sideAlter
( Down, \_ -> topDown -1 [ -2 ] )
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.length
--> 5Try to move the focus to the item at a given Scroll.Location.
Scroll.to (Down |> Scroll.nearest)🍊 <🍉> 🍇 -> <🍊> 🍉 🍇import Linear exposing (DirectionLinear(..))
import Emptiable exposing (Emptiable, filled, fillMap)
import Scroll exposing (Scroll, FocusGap)
Scroll.empty |> Scroll.to (Down |> Scroll.nearest)
--> Emptiable.empty
Scroll.only "hello"
|> Scroll.sideAlter
( Up, \_ -> topDown "scrollable" [ "world" ] )
|> Scroll.toEnd Up
|> Scroll.to (Down |> Scroll.nearest)
|> fillMap Scroll.focusItem
--> filled "scrollable"
--: Emptiable (Scroll String FocusGap Never) PossiblyThis also works from within gaps:
🍊 🍉 <> 🍇 -> 🍊 <🍉> 🍇import Linear exposing (DirectionLinear(..))
import Emptiable exposing (Emptiable, filled)
import Stack exposing (onTopLay)
import Scroll exposing (Scroll, FocusGap)
Scroll.empty
|> Scroll.sideAlter
( Down, onTopLay "foo" )
|> Scroll.to (Down |> Scroll.nearest)
--> filled (Scroll.only "foo")
--: Emptiable (Scroll String FocusGap Never) PossiblyScroll.to (Up |> Scroll.nearest)<🍊> 🍉 🍇 -> 🍊 <🍉> 🍇import Linear exposing (DirectionLinear(..))
import Emptiable exposing (Emptiable, filled, fillMap)
import Scroll exposing (Scroll, FocusGap)
Scroll.only 0
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.to (Up |> Scroll.nearest)
|> fillMap Scroll.focusItem
--> filled 1
--: Emptiable number_ PossiblyThis also works from within gaps:
🍊 <> 🍉 🍇 -> 🍊 <🍉> 🍇import Linear exposing (DirectionLinear(..))
import Emptiable exposing (Emptiable, filled)
import Stack exposing (onTopLay)
import Scroll exposing (Scroll, FocusGap)
Scroll.empty
|> Scroll.sideAlter
( Up, \_ -> Stack.only "foo" )
|> Scroll.to (Up |> Scroll.nearest)
--> filled (Scroll.only "foo")
--: Emptiable (Scroll String FocusGap Never) PossiblyIf there is no next item, the result is empty.
import Linear exposing (DirectionLinear(..))
import Emptiable
import Stack exposing (topDown)
Scroll.empty |> Scroll.to (Up |> Scroll.nearest)
--> Emptiable.empty
Scroll.only 0
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.toEnd Up
|> Scroll.to (Up |> Scroll.nearest)
--> Emptiable.emptyScroll.to Locationimport Element as Ui
import Element.Input as UIn
import Emptiable exposing (fillMap)
import RecordWithoutConstructorFunction exposing (RecordWithoutConstructorFunction)
import Scroll exposing (FocusGap, Scroll)
import Stack
type alias Model =
RecordWithoutConstructorFunction
{ numbers : Scroll Int FocusGap Never
}
type Event
= NumberClicked Scroll.Location
update : Event -> Model -> ( Model, Cmd Event )
update event model =
case event of
NumberClicked location ->
( { model
| numbers =
model.numbers
|> Scroll.to location
|> Emptiable.fillElseOnEmpty (\_ -> model.numbers)
|> Scroll.focusAlter (fillMap (\n -> n + 1))
}
, Cmd.none
)
interface : Model -> Ui.Element Event
interface =
\{ numbers } ->
numbers
|> Scroll.map numberInterface
|> Scroll.toList
|> Ui.column []
numberInterface :
Scroll.Location
-> Int
-> Ui.Element Event
numberInterface location =
\number ->
UIn.button []
{ onPress = NumberClicked location |> Just
, label =
number
|> String.fromInt
|> Ui.text
}The same functionality is often provided as duplicate : Scroll item ... -> Scroll (Scroll item) ...
List.NonEmpty.Zipper.duplicateSelectList.selectedMapZipper.duplicateReference.List.unwrapSaving a Scroll with every item becomes expensive for long Scrolls, though!
Move the focus to the gap directly Down|Up.
Feel free to plug that gap right up!
Scroll.toGap Down🍍 <🍊> 🍉 -> 🍍 <> 🍊 🍉import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled)
import Stack exposing (topDown)
Scroll.only "world"
|> Scroll.toGap Down
|> Scroll.focusAlter (\_ -> "hello" |> filled)
|> Scroll.toStack
--> topDown "hello" [ "world" ]Scroll.toGap Up🍍 <🍊> 🍉 -> 🍍 🍊 <> 🍉import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled)
import Stack exposing (topDown)
Scroll.only "hello"
|> Scroll.sideAlter
( Up, \_ -> Stack.only "world" )
|> Scroll.toGap Up
|> Scroll.focusAlter (\_ -> filled "scrollable")
|> Scroll.toStack
--> topDown "hello" [ "scrollable", "world" ]Focus the furthest item Down/Up the focus.
Down
🍍 🍓 <🍊> 🍉 -> <🍍> 🍓 🍊 🍉Up
🍓 <🍊> 🍉 🍇 -> 🍓 🍊 🍉 <🍇>import Linear exposing (DirectionLinear(..))
import Emptiable exposing (Emptiable)
import Stack exposing (Stacked, topDown)
Scroll.only 1
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ 3, 4 ] )
|> Scroll.sideAlter
( Down, \_ -> topDown 4 [ 3, 2 ] )
|> Scroll.toEnd Down
|> Scroll.focusItem
--> 2
Scroll.only 1
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ 3, 4 ] )
|> Scroll.toEnd Up
|> Scroll.focusItem
--> 4
Scroll.only 1
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ 3, 4 ] )
|> Scroll.toEnd Up
|> Scroll.side Down
--> topDown 3 [ 2, 1 ]
--: Emptiable (Stacked number_) PossiblyFocus the gap beyond the furthest item Down|Up.
Remember that gaps surround everything!
Down
🍍 🍓 <🍊> 🍉 -> <> 🍍 🍓 🍊 🍉Up
🍓 <🍊> 🍉 -> 🍓 🍊 🍉 <>import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled)
import Stack exposing (topDown)
Scroll.only 1
-- <1>
|> Scroll.sideAlter
( Up, \_ -> topDown 3 [ 4 ] )
-- <1> 3 4
|> Scroll.toGap Up
-- 1 <> 3 4
|> Scroll.focusAlter (\_ -> filled 2)
-- 1 <2> 3 4
|> Scroll.toEndGap Down
-- <> 1 2 3 4
|> Scroll.focusAlter (\_ -> filled 0)
-- <0> 1 2 3 4
|> Scroll.toStack
--> topDown 0 [ 1, 2, 3, 4 ]
Scroll.only 1
-- <1>
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ 3 ] )
-- <1> 2 3
|> Scroll.toEndGap Up
-- 1 2 3 <>
|> Scroll.focusAlter (\_ -> filled 4)
-- 1 2 3 <4>
|> Scroll.toStack
--> topDown 1 [ 2, 3, 4 ]Move the focus to the nearest item Down|Up that matches a predicate.
If no such item was found return with Emptiable.empty.
import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled, fillMap)
import Stack exposing (topDown)
import Linear exposing (DirectionLinear(..))
Scroll.only 4
|> Scroll.sideAlter
( Down, \_ -> topDown 2 [ -1, 0, 3 ] )
|> Scroll.toWhere ( Down, \_ item -> item < 0 )
|> Emptiable.fillMap Scroll.focusItem
--> filled -1
Scroll.only 4
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ -1, 0, 3 ] )
|> Scroll.toWhere ( Up, \_ item -> item < 0 )
|> fillMap focusItem
--> filled -1
Scroll.only -4
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ -1, 0, 3 ] )
|> Scroll.toWhere ( Up, \_ item -> item < 0 )
|> fillMap focusItem
--> filled -4Try to move the focus to the nearest item Down|Up.
Down
🍊 🍉 <🍓> 🍇 -> 🍊 <🍓> 🍉 🍇
🍊 🍉 <> 🍇 -> 🍊 <> 🍉 🍇Up
🍊 <🍓> 🍉 🍇 -> 🍊 🍉 <🍓> 🍇
🍊 <> 🍉 🍇 -> 🍊 🍉 <> 🍇import Linear exposing (DirectionLinear(..))
import Emptiable exposing (Emptiable, fillMapFlat)
import Scroll exposing (Scroll, FocusGap)
Scroll.only 0
|> Scroll.sideAlter
( Down, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.focusDrag Down
|> fillMapFlat Scroll.toStack
--> topDown 3 [ 2, 0, 1 ]
--: Emptiable (Stacked number_) Possibly
Scroll.only 0
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.focusDrag Up
|> fillMapFlat Scroll.toStack
--> topDown 1 [ 0, 2, 3 ]
--: Emptiable (Stacked number_) PossiblyIf there is no nearest item, the result is empty.
import Linear exposing (DirectionLinear(..))
import Emptiable
import Stack exposing (topDown)
Scroll.only 0
|> Scroll.sideAlter
( Up, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.focusDrag Down
--> Emptiable.empty
Scroll.only 0
|> Scroll.sideAlter
( Down, \_ -> topDown 1 [ 2, 3 ] )
|> Scroll.focusDrag Up
--> Emptiable.emptyEmptiable.empty if the current focussed thing is a gap,
Emptiable.filled if it's an item.
import Emptiable
import Stack exposing (topDown)
import Linear exposing (DirectionLinear(..))
Scroll.only 3
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ 1 ] )
|> Scroll.toGap Up
|> Scroll.focusItemTry
--> Emptiable.emptyChange every item based on its current value.
import Linear exposing (DirectionLinear(..))
import Stack exposing (topDown)
Scroll.only "first"
|> Scroll.sideAlter
( Down, \_ -> Stack.only "zeroth" )
|> Scroll.sideAlter
( Up, \_ -> topDown "second" [ "third" ] )
|> Scroll.map (\_ -> String.toUpper)
|> Scroll.toStack
--> topDown "ZEROTH" [ "FIRST", "SECOND", "THIRD" ]focusSidesMap allows changing the individual parts separately.
Change the focus,
the sides Down and Up
using different functions.
import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled, fillMap)
import Stack exposing (topDown)
Scroll.only "first"
|> Scroll.sideAlter
( Up, \_ -> Stack.only "second" )
|> Scroll.toGap Up
|> Scroll.focusAlter (\_ -> filled "one-and-a-halfth")
|> Scroll.focusSidesMap
{ side =
\side ->
Stack.map
(\_ item ->
String.concat
[ side |> sideToString, ": ", item ]
)
, focus =
fillMap (\item -> "focused item: " ++ item)
}
|> Scroll.toStack
--→
topDown
"before: first"
[ "focused item: one-and-a-halfth"
, "after: second"
]
sideToString =
\side ->
case side of
Down ->
"before"
Up ->
"after"map transforms every item.
Reduce in a direction.
import Linear exposing (DirectionLinear(..))
import Stack exposing (topDown)
Scroll.only 'e'
|> Scroll.sideAlter
( Down, \_ -> topDown 'v' [ 'i', 'l' ] )
|> Scroll.foldFrom "" Down String.cons
--> "live"
Scroll.only 'e'
|> Scroll.sideAlter
( Down, \_ -> topDown 'v' [ 'i', 'l' ] )
|> Scroll.foldFrom "" Up String.cons
--> "evil"Roll out the Scroll to both ends into a Stack:
import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled)
import Stack exposing (topDown)
Scroll.empty
|> Scroll.toStack
--> Emptiable.empty
Scroll.only 123
|> Scroll.sideAlter
( Up, \_ -> Stack.only 789 )
|> Scroll.toGap Up
|> Scroll.focusAlter (\_-> filled 456)
|> Scroll.toStack
--> topDown 123 [ 456, 789 ]the type information gets carried over, so
Never Scroll.FocusGap -> Stacked Never
Possibly Scroll.FocusGap -> Stacked PossiblyConverts it to a List, rolled out to both ends:
import Linear exposing (DirectionLinear(..))
import Stack
Scroll.only 456
|> Scroll.sideAlter
( Down, \_ -> Stack.only 123 )
|> Scroll.sideAlter
( Up, \_ -> Stack.only 789 )
|> Scroll.toList
--> [ 123, 456, 789 ]Only use this if you need a list in the end.
Otherwise, use toStack to preserve some information about its length.
Swap the stack on the side Down the focus
with the stack on the side Up.
🍓 <🍊> 🍉 🍇 <-> 🍇 🍉 <🍊> 🍓import Linear exposing (DirectionLinear(..))
import Stack exposing (topDown)
Scroll.only 1
|> Scroll.sideAlter
( Up, \_ -> topDown 2 [ 3, 4 ] )
|> Scroll.sideAlter
( Down, \_ -> topDown 4 [ 3, 2 ] )In contrast to List or stack, this can be done in O(1) time.
Alter the focus – item or gap – based on its current value.
Scroll.focusAlter (\_ -> 🍊 |> filled)🍊 -> 🍓 <?> 🍉 -> 🍓 <🍊> 🍉import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled, fillMap)
import Stack exposing (topDown, onTopLay)
Scroll.empty
-- <>
|> Scroll.sideAlter
( Down, onTopLay "🍓" )
-- "🍓" <>
|> Scroll.sideAlter
( Up, onTopLay "🍉" )
-- "🍓" <> "🍉"
|> Scroll.focusAlter (\_ -> "🍊" |> filled)
-- "🍓" <"🍊"> "🍉"
|> Scroll.toStack
--> topDown "🍓" [ "🍊", "🍉" ]Scroll.focusAlter (\_ -> Emptiable.empty)🍓 <?> 🍉 -> 🍓 <> 🍉import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled, fillMap)
import Stack exposing (topDown)
Scroll.only "hello"
|> Scroll.sideAlter
( Up, \_ -> topDown "scrollable" [ "world" ] )
|> Scroll.to (Up |> Scroll.nearest)
|> fillMap (Scroll.focusAlter (\_ -> Emptiable.empty))
|> fillMap Scroll.toList
--> filled [ "hello", "world" ]Scroll.focusAlter (?🍒 -> ?🍊)(?🍒 -> ?🍊) -> 🍓 <?🍒> 🍉 -> 🍓 <?🍊> 🍉import Linear exposing (DirectionLinear(..))
import Emptiable exposing (filled, fillMap)
import Stack exposing (topDown, onTopLay)
Scroll.empty
-- <>
|> Scroll.sideAlter
( Down, onTopLay "🍓" )
-- "🍓" <>
|> Scroll.sideAlter
( Up, onTopLay "🍉" )
-- "🍓" <> "🍉"
|> Scroll.focusAlter
(\_ -> filled "🍊")
-- "🍓" <"🍊"> "🍉"
|> Scroll.toStack
--> topDown "🍓" [ "🍊", "🍉" ]
Scroll.only "first"
|> Scroll.sideAlter
( Down, \_ -> Stack.only "zeroth" )
|> Scroll.sideAlter
( Up, \_ -> topDown "second" [ "third" ] )
|> Scroll.focusAlter (fillMap String.toUpper)
|> Scroll.toStack
--> topDown "zeroth" [ "FIRST", "second", "third" ]Look Down|Up the focus and operate directly an the Stack you see.
sideAlter ( DirectionLinear, \_ -> 🍒🍋 )Down
🍓 <🍊> 🍉
↓
🍋 🍒 <🍊> 🍉Up
🍍 🍓 <🍊> 🍉
↓
🍍 🍓 <🍊> 🍒 🍋import Linear exposing (DirectionLinear(..))
import Emptiable
import Stack exposing (topDown)
Scroll.only "selectoo"
|> Scroll.sideAlter
( Down, \_ -> topDown "earlee" [ "agua", "enutai" ] )
|> Scroll.sideAlter
( Up, \_ -> topDown "orangloo" [ "iquipy", "oice" ] )
|> Scroll.sideAlter
( Up, \_ -> Emptiable.empty )
|> Scroll.toStack
--> topDown "enutai" [ "agua", "earlee", "selectoo" ]sideAlter ( DirectionLinear, Stack.map ... )import Linear exposing (DirectionLinear(..))
import Stack exposing (topDown)
Scroll.only "second"
|> Scroll.sideAlter
( Down, \_ -> topDown "first" [ "zeroth" ] )
|> Scroll.sideAlter
( Down, Stack.map (\_ -> String.toUpper) )
|> Scroll.toStack
--> topDown "ZEROTH" [ "FIRST", "second" ]
Scroll.only "zeroth"
|> Scroll.sideAlter
( Up, \_ -> topDown "first" [ "second" ] )
|> Scroll.sideAlter
( Up, Stack.map (\_ -> String.toUpper) )
|> Scroll.toStack
--> topDown "zeroth" [ "FIRST", "SECOND" ]Look to one side from the focus and slide items in directly at the nearest location.
sideAlter ( DirectionLinear, Stack.onTopGlue/onTopStack 🍒🍋 )Down
🍒🍋
🍍 🍓 \↓/ <🍊> 🍉Up
🍒🍋
🍓 <🍊> \↓/ 🍉 🍇import Linear exposing (DirectionLinear(..))
import Stack exposing (topDown)
Scroll.only 0
|> Scroll.sideAlter
( Down, Stack.onTopGlue [ -4, -5 ] )
|> Scroll.sideAlter
( Down, Stack.onTopStack (topDown -1 [ -2, -3 ]) )
|> Scroll.toStack
--> topDown -5 [ -4, -3, -2, -1, 0 ]
Scroll.only 0
|> Scroll.sideAlter
( Up, Stack.onTopGlue [ 4, 5 ] )
|> Scroll.sideAlter
( Up, Stack.onTopStack (topDown 1 [ 2, 3 ]) )
|> Scroll.toStack
--> topDown 0 [ 1, 2, 3, 4, 5 ]Scroll.sideAlter ( DirectionLinear, \side -> 🍒🍋 |> onTopStack side )Down
🍋🍒
\↓ 🍍 🍓 <🍊> 🍉Up
🍒🍋
🍓 <🍊> 🍉 🍇 ↓/import Linear exposing (DirectionLinear(..))
import Stack exposing (topDown, onTopStack)
Scroll.only 1
|> Scroll.sideAlter
( Up, \after -> topDown 2 [ 3, 4 ] |> onTopStack after )
|> Scroll.toEnd Up
|> Scroll.sideAlter
( Down, \before -> topDown 7 [ 6, 5 ] |> onTopStack before )
|> Scroll.toStack
--> topDown 5 [ 6, 7, 1, 2, 3, 4 ]
Scroll.only 123
|> Scroll.sideAlter
( Up, \after -> Stack.only 456 |> onTopStack after )
|> Scroll.sideAlter
( Up, \after -> topDown 789 [ 0 ] |> onTopStack after )
|> Scroll.toStack
--> topDown 123 [ 456, 789, 0 ]sideAlter ( DirectionLinear,Stack.onTopLay ... )Down
🍒
🍍 🍓 ↓ <🍊> 🍉Up 🍒
🍓 <🍊> ↓ 🍉 🍇import Linear exposing (DirectionLinear(..))
import Stack exposing (topDown, onTopLay)
Scroll.only 123
|> Scroll.sideAlter
( Down, onTopLay 456 )
|> Scroll.toStack
--> topDown 456 [ 123 ]
Scroll.only 123
|> Scroll.sideAlter
( Up, \_ -> Stack.only 789 )
|> Scroll.sideAlter
( Up, onTopLay 456 )
|> Scroll.toStack
--> topDown 123 [ 456, 789 ]Change the possiblyOrNever type
A Scroll ... FocusGap possiblyOrNever
can't be used as a Scroll ... Possibly?
import Possibly exposing (Possibly(..))
Scroll.focusGapAdapt (always Possible)A Scroll ... FocusGap Never
can't be unified with Scroll ... Possibly or FocusGap possiblyOrNever?
Scroll.focusGapAdapt neverPlease read more at Emptiable.emptyAdapt.
map (Location -> ...), focusDrag, toNonEmptyList, sideAlter (so no squeezing in multiple items, ...)List.NonEmpty.Zipper
complete; cluttered (for example update & map); some unintuitive namesfocusWheremap (Location -> ...)map (Location -> ...), sideAlter (so no squeezing in multiple items, ...)focusDrag, map (Location -> ...), toNonEmptyListside, ...focusDrag, toNonEmptyList, sideAlter (so no squeezing in multiple items, ...)Reference.List
only overList, sides impossible to access & alter
📜 Items rolled up on both sides of a focus
→ good fit for dynamic choice selection: tabs, playlist, ...
Scrollcan even focus a gapDownandUpevery item:🍍 🍓 <🍊> 🍉 🍇:Scroll ... FocusGap Never🍍 🍓 <?> 🍉 🍇:Scroll ...PossiblyFocusGap<?>means both are possible:🍍 🍓 <> 🍉 🍇: a gap between items ... Heh.🍍 🍓 <🍊> 🍉 🍇in arguments
in types
where
RecordWithoutConstructorFunctionstops the compiler from creating a constructor function forModel.