1module Internal.Model exposing
30 , TransformComponent(..)
47 , composeTransformation
55 , extractSpacingAndPadding
87 , reduceStylesRecursive
111import Html.Attributes
113import Internal.Flag as Flag exposing (Flag)
114import Internal.Style exposing (classes, dot)
115import Json.Encode as Encode
116import Set exposing (Set)
121 = Unstyled (LayoutContext -> VirtualDom.Node msg)
123 { styles : List Style
124 , html : EmbedStyle -> LayoutContext -> VirtualDom.Node msg
132 | StaticRootAndDynamic OptionRecord (List Style)
133 | OnlyDynamic OptionRecord (List Style)
136noStyleSheet : EmbedStyle
152 | Aligned (Maybe HAlign) (Maybe VAlign)
168 = Style String (List Property)
170 | FontFamily String (List Font)
172 -- classname, prop, value
173 | Single String String String
174 | Colored String String Color
175 | SpacingStyle String Int Int
176 | BorderWidth String Int Int Int Int
177 | PaddingStyle String Float Float Float Float
179 { spacing : ( Length, Length )
180 , columns : List Length
189 | Transform Transformation
190 | PseudoSelector PseudoClass (List Style)
191 | Transparency String Float
192 | Shadows String String
198 -- translate, scale, rotate
199 | FullTransform XYZ XYZ XYZ Angle
209type alias Adjustment =
222 | ImportFont String String
225 , adjustment : Maybe Adjustment
226 , variants : List Variant
231 = VariantActive String
233 | VariantIndexed String Int
238 VariantActive name ->
242 "\"" ++ name ++ "\" 0"
244 VariantIndexed name index ->
245 "\"" ++ name ++ "\" " ++ String.fromInt index
250 VariantActive name ->
256 VariantIndexed name index ->
257 name ++ "-" ++ String.fromInt index
260renderVariants typeface =
263 Just (String.join ", " (List.map renderVariant font.variants))
271 VariantActive name ->
277 VariantIndexed name index ->
278 name == "smcp" && index == 1
281hasSmallCaps typeface =
284 List.any isSmallCaps font.variants
291 = Property String String
295 ( Float, Float, Float )
302type Attribute aligned msg
304 | Attr (VirtualDom.Attribute msg)
305 | Describe Description
306 -- invalidation key and literal class
308 -- invalidation key "border-color" as opposed to "border-color-10-10-10" that will be the key for the class
309 | StyleClass Flag Style
314 | Nearby Location (Element msg)
315 | TransformComponent Flag TransformComponent
318type TransformComponent
366 = Rgba Float Float Float Float
372 | Embedded String String
375type NearbyChildren msg
377 | ChildrenBehind (List (Html.Html msg))
378 | ChildrenInFront (List (Html.Html msg))
379 | ChildrenBehindAndInFront (List (Html.Html msg)) (List (Html.Html msg))
386type alias Gathered msg =
388 , attributes : List (VirtualDom.Attribute msg)
389 , styles : List Style
390 , children : NearbyChildren msg
395htmlClass : String -> Attribute aligned msg
397 Attr <| Html.Attributes.class cls
401unstyled : VirtualDom.Node msg -> Element msg
406finalizeNode has node attributes children embedMode parentContext =
408 createNode nodeName attrs =
411 VirtualDom.keyedNode nodeName
417 OnlyDynamic opts styles ->
418 embedKeyed False opts styles keyed
420 StaticRootAndDynamic opts styles ->
421 embedKeyed True opts styles keyed
433 VirtualDom.node nodeName
440 OnlyDynamic opts styles ->
441 embedWith False opts styles unkeyed
443 StaticRootAndDynamic opts styles ->
444 embedWith True opts styles unkeyed
450 createNode "div" attributes
453 createNode nodeName attributes
455 Embedded nodeName internal ->
456 VirtualDom.node nodeName
458 [ createNode internal
459 [ Html.Attributes.class
460 (classes.any ++ " " ++ classes.single)
464 case parentContext of
466 if Flag.present Flag.widthFill has && not (Flag.present Flag.widthBetween has) then
469 else if Flag.present Flag.alignRight has then
471 [ Html.Attributes.class
476 , classes.contentCenterY
477 , classes.alignContainerRight
483 else if Flag.present Flag.centerX has then
485 [ Html.Attributes.class
490 , classes.contentCenterY
491 , classes.alignContainerCenterX
501 if Flag.present Flag.heightFill has && not (Flag.present Flag.heightBetween has) then
504 else if Flag.present Flag.centerY has then
506 [ Html.Attributes.class
511 , classes.alignContainerCenterY
517 else if Flag.present Flag.alignBottom has then
519 [ Html.Attributes.class
524 , classes.alignContainerBottom
537embedWith static opts styles children =
541 |> List.foldl reduceStyles ( Set.empty, renderFocusStyle opts.focus )
543 -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
557embedKeyed static opts styles children =
561 |> List.foldl reduceStyles ( Set.empty, renderFocusStyle opts.focus )
563 -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
568 ( "static-stylesheet", staticRoot opts )
569 :: ( "dynamic-stylesheet"
575 ( "dynamic-stylesheet"
581reduceStylesRecursive : Set String -> List Style -> List Style -> List Style
582reduceStylesRecursive cache found styles =
592 if Set.member styleName cache then
593 reduceStylesRecursive cache found remaining
596 reduceStylesRecursive (Set.insert styleName cache) (head :: found) remaining
599reduceStyles : Style -> ( Set String, List Style ) -> ( Set String, List Style )
600reduceStyles style (( cache, existing ) as nevermind) =
605 if Set.member styleName cache then
609 ( Set.insert styleName cache
616 -- |> List.map (\x -> ( getStyleName x, x ))
617 |> List.sortBy getStyleName
618 |> reduceRecursiveCalcName []
621reduceRecursiveCalcName : List Style -> List Style -> List Style
622reduceRecursiveCalcName found styles =
630 headOfList :: other :: remaining ->
631 if headOfList /= other then
632 reduceRecursiveCalcName (headOfList :: found) (other :: remaining)
635 reduceRecursiveCalcName found (other :: remaining)
638reduceRecursive : List Style -> List ( String, Style ) -> List Style
639reduceRecursive found styles =
644 ( _, headOfList ) :: [] ->
647 ( headOfListName, headOfList ) :: ( otherName, other ) :: remaining ->
648 if headOfListName /= otherName then
649 reduceRecursive (headOfList :: found) (( otherName, other ) :: remaining)
652 reduceRecursive found (( otherName, other ) :: remaining)
655addNodeName : String -> NodeName -> NodeName
656addNodeName newNode old =
662 Embedded name newNode
668alignXName : HAlign -> String
672 classes.alignedHorizontally ++ " " ++ classes.alignLeft
675 classes.alignedHorizontally ++ " " ++ classes.alignRight
678 classes.alignedHorizontally ++ " " ++ classes.alignCenterX
681alignYName : VAlign -> String
685 classes.alignedVertically ++ " " ++ classes.alignTop
688 classes.alignedVertically ++ " " ++ classes.alignBottom
691 classes.alignedVertically ++ " " ++ classes.alignCenterY
694transformClass transform =
708 FullTransform ( tx, ty, tz ) ( sx, sy, sz ) ( ox, oy, oz ) angle ->
732transformValue transform =
740 ++ String.fromFloat x
742 ++ String.fromFloat y
744 ++ String.fromFloat z
747 FullTransform ( tx, ty, tz ) ( sx, sy, sz ) ( ox, oy, oz ) angle ->
751 ++ String.fromFloat tx
753 ++ String.fromFloat ty
755 ++ String.fromFloat tz
760 ++ String.fromFloat sx
762 ++ String.fromFloat sy
764 ++ String.fromFloat sz
769 ++ String.fromFloat ox
771 ++ String.fromFloat oy
773 ++ String.fromFloat oz
775 ++ String.fromFloat angle
778 Just <| translate ++ " " ++ scale ++ " " ++ rotate
781composeTransformation transform component =
798 FullTransform ( 0, 0, 0 ) ( 1, 1, 1 ) xyz angle
801 FullTransform ( 0, 0, 0 ) xyz ( 0, 0, 1 ) 0
803 Moved (( x, y, z ) as moved) ->
818 FullTransform moved ( 1, 1, 1 ) xyz angle
821 FullTransform moved scale ( 0, 0, 1 ) 0
823 FullTransform (( x, y, z ) as moved) scaled origin angle ->
826 FullTransform ( newX, y, z ) scaled origin angle
829 FullTransform ( x, newY, z ) scaled origin angle
832 FullTransform ( x, y, newZ ) scaled origin angle
835 FullTransform newMove scaled origin angle
837 Rotate newOrigin newAngle ->
838 FullTransform moved scaled newOrigin newAngle
841 FullTransform moved newScale origin angle
844skippable flag style =
845 if flag == Flag.borderWidth then
881 PaddingStyle name t r b l ->
882 t == b && t == r && t == l && t >= 0 && t <= 24
884 -- SpacingStyle _ _ _ ->
898 -> List (VirtualDom.Attribute msg)
899 -> NearbyChildren msg
900 -> List (Attribute aligned msg)
902gatherAttrRecursive classes node has transform styles attrs children elementAttrs =
905 case transformClass transform of
907 { attributes = Html.Attributes.class classes :: attrs
910 , children = children
915 { attributes = Html.Attributes.class (classes ++ " " ++ class) :: attrs
916 , styles = Transform transform :: styles
918 , children = children
922 attribute :: remaining ->
925 gatherAttrRecursive classes node has transform styles attrs children remaining
927 Class flag exactClassName ->
928 if Flag.present flag has then
929 gatherAttrRecursive classes node has transform styles attrs children remaining
932 gatherAttrRecursive (exactClassName ++ " " ++ classes) node (Flag.add flag has) transform styles attrs children remaining
934 Attr actualAttribute ->
935 gatherAttrRecursive classes node has transform styles (actualAttribute :: attrs) children remaining
937 StyleClass flag style ->
938 if Flag.present flag has then
939 gatherAttrRecursive classes node has transform styles attrs children remaining
941 else if skippable flag style then
942 gatherAttrRecursive (getStyleName style ++ " " ++ classes)
952 gatherAttrRecursive (getStyleName style ++ " " ++ classes)
961 TransformComponent flag component ->
962 gatherAttrRecursive classes
965 (composeTransformation transform component)
972 if Flag.present Flag.width has then
973 gatherAttrRecursive classes node has transform styles attrs children remaining
978 gatherAttrRecursive ((Internal.Style.classes.widthExact ++ " width-px-" ++ String.fromInt px) ++ " " ++ classes)
980 (Flag.add Flag.width has)
982 (Single ("width-px-" ++ String.fromInt px) "width" (String.fromInt px ++ "px") :: styles)
988 gatherAttrRecursive (classes ++ " " ++ Internal.Style.classes.widthContent)
990 (Flag.add Flag.widthContent (Flag.add Flag.width has))
999 gatherAttrRecursive (classes ++ " " ++ Internal.Style.classes.widthFill)
1001 (Flag.add Flag.widthFill (Flag.add Flag.width has))
1009 gatherAttrRecursive (classes ++ " " ++ Internal.Style.classes.widthFillPortion ++ " width-fill-" ++ String.fromInt portion)
1011 (Flag.add Flag.widthFill (Flag.add Flag.width has))
1014 (Internal.Style.classes.any
1016 ++ Internal.Style.classes.row
1018 ++ (Internal.Style.dot <| "width-fill-" ++ String.fromInt portion)
1021 (String.fromInt (portion * 100000))
1030 ( addToFlags, newClass, newStyles ) =
1033 gatherAttrRecursive (classes ++ " " ++ newClass)
1035 (Flag.merge addToFlags (Flag.add Flag.width has))
1037 (newStyles ++ styles)
1043 if Flag.present Flag.height has then
1044 gatherAttrRecursive classes node has transform styles attrs children remaining
1051 String.fromInt px ++ "px"
1056 gatherAttrRecursive (Internal.Style.classes.heightExact ++ " " ++ name ++ " " ++ classes)
1058 (Flag.add Flag.height has)
1060 (Single name "height " val :: styles)
1066 gatherAttrRecursive (Internal.Style.classes.heightContent ++ " " ++ classes)
1068 (Flag.add Flag.heightContent (Flag.add Flag.height has))
1076 if portion == 1 then
1077 gatherAttrRecursive (Internal.Style.classes.heightFill ++ " " ++ classes)
1079 (Flag.add Flag.heightFill (Flag.add Flag.height has))
1087 gatherAttrRecursive (classes ++ " " ++ (Internal.Style.classes.heightFillPortion ++ " height-fill-" ++ String.fromInt portion))
1089 (Flag.add Flag.heightFill (Flag.add Flag.height has))
1092 (Internal.Style.classes.any
1094 ++ Internal.Style.classes.column
1096 ++ (Internal.Style.dot <| "height-fill-" ++ String.fromInt portion)
1099 (String.fromInt (portion * 100000))
1108 ( addToFlags, newClass, newStyles ) =
1111 gatherAttrRecursive (classes ++ " " ++ newClass)
1113 (Flag.merge addToFlags (Flag.add Flag.height has))
1115 (newStyles ++ styles)
1120 Describe description ->
1123 gatherAttrRecursive classes (addNodeName "main" node) has transform styles attrs children remaining
1126 gatherAttrRecursive classes (addNodeName "nav" node) has transform styles attrs children remaining
1129 gatherAttrRecursive classes (addNodeName "footer" node) has transform styles attrs children remaining
1132 gatherAttrRecursive classes (addNodeName "aside" node) has transform styles attrs children remaining
1136 gatherAttrRecursive classes (addNodeName "h1" node) has transform styles attrs children remaining
1139 gatherAttrRecursive classes (addNodeName ("h" ++ String.fromInt i) node) has transform styles attrs children remaining
1142 gatherAttrRecursive classes (addNodeName "h6" node) has transform styles attrs children remaining
1145 -- previously we rendered a <p> tag, though apparently this invalidates the html if it has <div>s inside.
1146 -- Since we can't guaranteee that there are no divs, we need another strategy.
1147 -- While it's not documented in many places, there apparently is a paragraph aria role
1148 -- https://github.com/w3c/aria/blob/11f85f41a5b621fdbe85fc9bcdcd270e653a48ba/common/script/roleInfo.js
1149 -- Though we'll need to wait till it gets released in an official wai-aria spec to use it.
1150 -- If it's used at the moment, then Lighthouse complains (likely rightfully) that role paragraph is not recognized.
1162 gatherAttrRecursive classes node has transform styles (VirtualDom.attribute "role" "button" :: attrs) children remaining
1165 gatherAttrRecursive classes node has transform styles (VirtualDom.attribute "aria-label" label :: attrs) children remaining
1168 gatherAttrRecursive classes node has transform styles (VirtualDom.attribute "aria-live" "polite" :: attrs) children remaining
1171 gatherAttrRecursive classes node has transform styles (VirtualDom.attribute "aria-live" "assertive" :: attrs) children remaining
1173 Nearby location elem ->
1187 styles ++ styled.styles
1196 (addNearbyElement location elem children)
1200 if Flag.present Flag.xAlign has then
1201 gatherAttrRecursive classes node has transform styles attrs children remaining
1204 gatherAttrRecursive (alignXName x ++ " " ++ classes)
1207 |> Flag.add Flag.xAlign
1211 Flag.add Flag.centerX flags
1214 Flag.add Flag.alignRight flags
1227 if Flag.present Flag.yAlign has then
1228 gatherAttrRecursive classes node has transform styles attrs children remaining
1231 gatherAttrRecursive (alignYName y ++ " " ++ classes)
1233 (Flag.add Flag.yAlign has
1237 Flag.add Flag.centerY flags
1240 Flag.add Flag.alignBottom flags
1253addNearbyElement location elem existing =
1256 nearbyElement location elem
1262 ChildrenBehind [ nearby ]
1265 ChildrenInFront [ nearby ]
1267 ChildrenBehind existingBehind ->
1270 ChildrenBehind (nearby :: existingBehind)
1273 ChildrenBehindAndInFront existingBehind [ nearby ]
1275 ChildrenInFront existingInFront ->
1278 ChildrenBehindAndInFront [ nearby ] existingInFront
1281 ChildrenInFront (nearby :: existingInFront)
1283 ChildrenBehindAndInFront existingBehind existingInFront ->
1286 ChildrenBehindAndInFront (nearby :: existingBehind) existingInFront
1289 ChildrenBehindAndInFront existingBehind (nearby :: existingInFront)
1292nearbyElement location elem =
1294 [ Html.Attributes.class <|
1298 [ Internal.Style.classes.nearby
1299 , Internal.Style.classes.single
1300 , Internal.Style.classes.above
1305 [ Internal.Style.classes.nearby
1306 , Internal.Style.classes.single
1307 , Internal.Style.classes.below
1312 [ Internal.Style.classes.nearby
1313 , Internal.Style.classes.single
1314 , Internal.Style.classes.onRight
1319 [ Internal.Style.classes.nearby
1320 , Internal.Style.classes.single
1321 , Internal.Style.classes.onLeft
1326 [ Internal.Style.classes.nearby
1327 , Internal.Style.classes.single
1328 , Internal.Style.classes.inFront
1333 [ Internal.Style.classes.nearby
1334 , Internal.Style.classes.single
1335 , Internal.Style.classes.behind
1349 styled.html NoStyleSheet asEl
1357 , Internal.Style.classes.widthExact ++ " width-px-" ++ String.fromInt px
1358 , [ Single ("width-px-" ++ String.fromInt px) "width" (String.fromInt px ++ "px") ]
1362 ( Flag.add Flag.widthContent Flag.none
1363 , Internal.Style.classes.widthContent
1368 if portion == 1 then
1369 ( Flag.add Flag.widthFill Flag.none
1370 , Internal.Style.classes.widthFill
1375 ( Flag.add Flag.widthFill Flag.none
1376 , Internal.Style.classes.widthFillPortion ++ " width-fill-" ++ String.fromInt portion
1378 (Internal.Style.classes.any
1380 ++ Internal.Style.classes.row
1382 ++ (Internal.Style.dot <| "width-fill-" ++ String.fromInt portion)
1385 (String.fromInt (portion * 100000))
1393 ++ String.fromInt minSize
1399 (String.fromInt minSize ++ "px")
1401 ( newFlag, newAttrs, newStyle ) =
1404 ( Flag.add Flag.widthBetween newFlag
1405 , cls ++ " " ++ newAttrs
1412 "max-width-" ++ String.fromInt maxSize
1417 (String.fromInt maxSize ++ "px")
1419 ( newFlag, newAttrs, newStyle ) =
1422 ( Flag.add Flag.widthBetween newFlag
1423 , cls ++ " " ++ newAttrs
1439 , Internal.Style.classes.heightExact ++ " " ++ name
1440 , [ Single name "height" (val ++ "px") ]
1444 ( Flag.add Flag.heightContent Flag.none
1445 , Internal.Style.classes.heightContent
1450 if portion == 1 then
1451 ( Flag.add Flag.heightFill Flag.none
1452 , Internal.Style.classes.heightFill
1457 ( Flag.add Flag.heightFill Flag.none
1458 , Internal.Style.classes.heightFillPortion ++ " height-fill-" ++ String.fromInt portion
1460 (Internal.Style.classes.any
1462 ++ Internal.Style.classes.column
1464 ++ (Internal.Style.dot <| "height-fill-" ++ String.fromInt portion)
1467 (String.fromInt (portion * 100000))
1475 ++ String.fromInt minSize
1481 -- This needs to be !important because we're using `min-height: min-content`
1482 -- to correct for safari's incorrect implementation of flexbox.
1483 (String.fromInt minSize ++ "px !important")
1485 ( newFlag, newAttrs, newStyle ) =
1488 ( Flag.add Flag.heightBetween newFlag
1489 , cls ++ " " ++ newAttrs
1496 "max-height-" ++ String.fromInt maxSize
1501 (String.fromInt maxSize ++ "px")
1503 ( newFlag, newAttrs, newStyle ) =
1506 ( Flag.add Flag.heightBetween newFlag
1507 , cls ++ " " ++ newAttrs
1513 classes.any ++ " " ++ classes.row
1517 classes.any ++ " " ++ classes.column
1521 classes.any ++ " " ++ classes.single
1525 classes.any ++ " " ++ classes.grid
1529 classes.any ++ " " ++ classes.paragraph
1533 classes.any ++ " " ++ classes.page
1536contextClasses context =
1557element : LayoutContext -> NodeName -> List (Attribute aligned msg) -> Children (Element msg) -> Element msg
1558element context node attributes children =
1561 |> gatherAttrRecursive (contextClasses context) node Flag.none untransformed [] [] NoNearbyChildren
1562 |> createElement context children
1569createElement : LayoutContext -> Children (Element msg) -> Gathered msg -> Element msg
1570createElement context children rendered =
1572 gather child ( htmls, existingStyles ) =
1575 if context == asParagraph then
1576 ( html context :: htmls
1581 ( html context :: htmls
1586 if context == asParagraph then
1587 ( styled.html NoStyleSheet context :: htmls
1588 , if List.isEmpty existingStyles then
1592 styled.styles ++ existingStyles
1596 ( styled.html NoStyleSheet context :: htmls
1597 , if List.isEmpty existingStyles then
1601 styled.styles ++ existingStyles
1605 -- TEXT OPTIMIZATION
1606 -- You can have raw text if the element is an el, and has `width-content` and `height-content`
1607 -- Same if it's a column or row with one child and width-content, height-content
1608 -- interferes with css grid
1609 -- Maybe we could unpack text elements in a paragraph as well,
1610 -- however, embedded elements that are larger than the line height will overlap with exisitng text.
1611 -- I don't think that's what we want.
1618 -- ( VirtualDom.text
1619 -- (if context == asParagraph then
1628 ( (if context == asEl then
1639 ( htmls, existingStyles )
1641 gatherKeyed ( key, child ) ( htmls, existingStyles ) =
1644 if context == asParagraph then
1645 ( ( key, html context ) :: htmls
1650 ( ( key, html context ) :: htmls
1655 if context == asParagraph then
1656 ( ( key, styled.html NoStyleSheet context )
1658 , if List.isEmpty existingStyles then
1662 styled.styles ++ existingStyles
1666 ( ( key, styled.html NoStyleSheet context ) :: htmls
1667 , if List.isEmpty existingStyles then
1671 styled.styles ++ existingStyles
1675 -- TEXT OPTIMIZATION
1676 -- You can have raw text if the element is an el, and has `width-content` and `height-content`
1677 -- Same if it's a column or row with one child and width-content, height-content
1685 -- , VirtualDom.text
1693 , if context == asEl then
1704 ( htmls, existingStyles )
1707 Keyed keyedChildren ->
1708 case List.foldr gatherKeyed ( [], [] ) keyedChildren of
1709 ( keyed, styles ) ->
1712 if List.isEmpty styles then
1716 rendered.styles ++ styles
1721 (finalizeNode rendered.has
1725 (addKeyedChildren "nearby-element-pls" keyed rendered.children)
1732 { styles = allStyles
1739 (addKeyedChildren "nearby-element-pls" keyed rendered.children)
1743 Unkeyed unkeyedChildren ->
1744 case List.foldr gather ( [], [] ) unkeyedChildren of
1745 ( unkeyed, styles ) ->
1748 if List.isEmpty styles then
1752 rendered.styles ++ styles
1761 (Unkeyed (addChildren unkeyed rendered.children))
1767 { styles = allStyles
1773 (Unkeyed (addChildren unkeyed rendered.children))
1777addChildren existing nearbyChildren =
1778 case nearbyChildren of
1782 ChildrenBehind behind ->
1785 ChildrenInFront inFront ->
1788 ChildrenBehindAndInFront behind inFront ->
1789 behind ++ existing ++ inFront
1792addKeyedChildren key existing nearbyChildren =
1793 case nearbyChildren of
1797 ChildrenBehind behind ->
1798 List.map (\x -> ( key, x )) behind ++ existing
1800 ChildrenInFront inFront ->
1801 existing ++ List.map (\x -> ( key, x )) inFront
1803 ChildrenBehindAndInFront behind inFront ->
1804 List.map (\x -> ( key, x )) behind
1806 ++ List.map (\x -> ( key, x )) inFront
1814 { hover = AllowHover
1815 , focus = focusDefaultStyle
1820staticRoot : OptionRecord -> VirtualDom.Node msg
1824 -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
1825 VirtualDom.node "div"
1827 [ VirtualDom.node "style" [] [ VirtualDom.text Internal.Style.rules ] ]
1829 NoStaticStyleSheet ->
1833 VirtualDom.node "elm-ui-static-rules" [ VirtualDom.property "rules" (Encode.string Internal.Style.rules) ] []
1836addWhen ifThis x to =
1846This doesn't reduce equivalent attributes completely.
1849filter : List (Attribute aligned msg) -> List (Attribute aligned msg)
1853 (\x ( found, has ) ->
1864 StyleClass _ style ->
1868 if Set.member "width" has then
1872 ( x :: found, Set.insert "width" has )
1875 if Set.member "height" has then
1879 ( x :: found, Set.insert "height" has )
1881 Describe description ->
1882 if Set.member "described" has then
1886 ( x :: found, Set.insert "described" has )
1888 Nearby location elem ->
1892 if Set.member "align-x" has then
1896 ( x :: found, Set.insert "align-x" has )
1899 if Set.member "align-y" has then
1903 ( x :: found, Set.insert "align-y" has )
1905 TransformComponent _ _ ->
1906 if Set.member "transform" has then
1910 ( x :: found, Set.insert "transform" has )
1931get : List (Attribute aligned msg) -> (Attribute aligned msg -> Bool) -> List (Attribute aligned msg)
1947 = Spaced String Int Int
1951 = Padding String Float Float Float Float
1954extractSpacingAndPadding : List (Attribute aligned msg) -> ( Maybe Padding, Maybe Spacing )
1955extractSpacingAndPadding attrs =
1957 (\attr ( pad, spacing ) ->
1964 StyleClass _ (PaddingStyle name t r b l) ->
1965 Just (Padding name t r b l)
1975 StyleClass _ (SpacingStyle name x y) ->
1976 Just (Spaced name x y)
1982 ( Nothing, Nothing )
1986getSpacing : List (Attribute aligned msg) -> ( Int, Int ) -> ( Int, Int )
1987getSpacing attrs default =
1997 StyleClass _ (SpacingStyle _ x y) ->
2004 |> Maybe.withDefault default
2007getWidth : List (Attribute aligned msg) -> Maybe Length
2027getHeight : List (Attribute aligned msg) -> Maybe Length
2047textElementClasses : String
2053 ++ classes.widthContent
2055 ++ classes.heightContent
2058textElement : String -> VirtualDom.Node msg
2061 [ Html.Attributes.class
2067textElementFillClasses : String
2068textElementFillClasses =
2073 ++ classes.widthFill
2075 ++ classes.heightFill
2078textElementFill : String -> VirtualDom.Node msg
2079textElementFill str =
2081 [ Html.Attributes.class
2082 textElementFillClasses
2089 | Keyed (List ( String, x ))
2097 Styled { styles, html } ->
2098 html (mode styles) asEl
2108renderRoot : List Option -> List (Attribute aligned msg) -> Element msg -> VirtualDom.Node msg
2109renderRoot optionList attributes child =
2112 optionsToRecord optionList
2115 case options.mode of
2116 NoStaticStyleSheet ->
2120 StaticRootAndDynamic options
2122 element asEl div attributes (Unkeyed [ child ])
2123 |> toHtml embedStyle
2128 | NoStaticStyleSheet
2132type alias OptionRecord =
2133 { hover : HoverSetting
2134 , focus : FocusStyle
2146 = HoverOption HoverSetting
2147 | FocusStyleOption FocusStyle
2148 | RenderModeOption RenderMode
2151type alias FocusStyle =
2152 { borderColor : Maybe Color
2153 , shadow : Maybe Shadow
2154 , backgroundColor : Maybe Color
2160 , offset : ( Int, Int )
2166rootStyle : List (Attribute aligned msg)
2170 [ Typeface "Open Sans"
2171 , Typeface "Helvetica"
2172 , Typeface "Verdana"
2176 [ StyleClass Flag.bgColor (Colored ("bg-" ++ formatColorClass (Rgba 1 1 1 0)) "background-color" (Rgba 1 1 1 0))
2177 , StyleClass Flag.fontColor (Colored ("fc-" ++ formatColorClass (Rgba 0 0 0 1)) "color" (Rgba 0 0 0 1))
2178 , StyleClass Flag.fontSize (FontSize 20)
2179 , StyleClass Flag.fontFamily <|
2180 FontFamily (List.foldl renderFontClassName "font-" families)
2185renderFontClassName : Font -> String -> String
2186renderFontClassName font current =
2204 ImportFont name url ->
2210 FontWith { name } ->
2221renderFocusStyle focus =
2222 [ Style (Internal.Style.dot classes.focusedWithin ++ ":focus-within")
2223 (List.filterMap identity
2224 [ Maybe.map (\color -> Property "border-color" (formatColor color)) focus.borderColor
2225 , Maybe.map (\color -> Property "background-color" (formatColor color)) focus.backgroundColor
2228 Property "box-shadow"
2230 { color = shadow.color
2233 |> Tuple.mapFirst toFloat
2234 |> Tuple.mapSecond toFloat
2244 , Just <| Property "outline" "none"
2248 ((Internal.Style.dot classes.any ++ ":focus .focusable, ")
2249 ++ (Internal.Style.dot classes.any ++ ".focusable:focus, ")
2250 ++ (".ui-slide-bar:focus + " ++ Internal.Style.dot classes.any ++ " .focusable-thumb")
2252 (List.filterMap identity
2253 [ Maybe.map (\color -> Property "border-color" (formatColor color)) focus.borderColor
2254 , Maybe.map (\color -> Property "background-color" (formatColor color)) focus.backgroundColor
2257 Property "box-shadow"
2259 { color = shadow.color
2262 |> Tuple.mapFirst toFloat
2263 |> Tuple.mapSecond toFloat
2265 , blur = toFloat shadow.blur
2266 , size = toFloat shadow.size
2271 , Just <| Property "outline" "none"
2277focusDefaultStyle : { backgroundColor : Maybe Color, borderColor : Maybe Color, shadow : Maybe Shadow }
2279 { backgroundColor = Nothing
2280 , borderColor = Nothing
2284 Rgba (155 / 255) (203 / 255) 1 1
2292optionsToRecord : List Option -> OptionRecord
2293optionsToRecord options =
2295 combine opt record =
2297 HoverOption hoverable ->
2298 case record.hover of
2300 { record | hover = Just hoverable }
2305 FocusStyleOption focusStyle ->
2306 case record.focus of
2308 { record | focus = Just focusStyle }
2313 RenderModeOption renderMode ->
2316 { record | mode = Just renderMode }
2323 case record.hover of
2330 case record.focus of
2354toStyleSheet : OptionRecord -> List Style -> VirtualDom.Node msg
2355toStyleSheet options styleSheet =
2356 case options.mode of
2358 -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
2359 VirtualDom.node "div"
2361 [ VirtualDom.node "style"
2363 [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2366 NoStaticStyleSheet ->
2367 -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
2368 VirtualDom.node "div"
2370 [ VirtualDom.node "style"
2372 [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2376 VirtualDom.node "elm-ui-rules"
2377 [ VirtualDom.property "rules"
2378 (encodeStyles options styleSheet)
2383renderTopLevelValues rules =
2388 Just ("@import url('" ++ url ++ "');")
2393 -- Just ("@import url('" ++ x ++ "');")
2400 List.map Tuple.first rules
2402 fontImports ( name, typefaces ) =
2405 String.join "\n" (List.filterMap withImport typefaces)
2409 fontAdjustments ( name, typefaces ) =
2410 case typefaceAdjustment typefaces of
2413 (List.map (renderNullAdjustmentRule name) allNames)
2417 (List.map (renderFontAdjustmentRule name adjustment) allNames)
2419 String.join "\n" (List.map fontImports rules)
2420 ++ String.join "\n" (List.map fontAdjustments rules)
2423renderNullAdjustmentRule fontToAdjust otherFontName =
2426 if fontToAdjust == otherFontName then
2430 otherFontName ++ " ." ++ fontToAdjust
2437 ++ classes.sizeByCapital
2442 ++ classes.sizeByCapital
2444 [ ( "line-height", "1" )
2450 ++ classes.sizeByCapital
2452 ++ Internal.Style.classes.text
2456 ++ classes.sizeByCapital
2458 ++ Internal.Style.classes.text
2460 [ ( "vertical-align", "0" )
2461 , ( "line-height", "1" )
2466fontRule name modifier ( parentAdj, textAdjustment ) =
2485 ++ Internal.Style.classes.text
2491 ++ Internal.Style.classes.text
2497renderFontAdjustmentRule fontToAdjust ( full, capital ) otherFontName =
2500 if fontToAdjust == otherFontName then
2504 otherFontName ++ " ." ++ fontToAdjust
2507 (fontRule name classes.sizeByCapital capital ++ fontRule name classes.fullSize full)
2510bracket selector rules =
2512 renderPair ( name, val ) =
2513 name ++ ": " ++ val ++ ";"
2515 selector ++ " {" ++ String.join "" (List.map renderPair rules) ++ "}"
2518fontAdjustmentRules converted =
2519 ( [ ( "display", "block" )
2521 , [ ( "display", "inline-block" )
2522 , ( "line-height", String.fromFloat converted.height )
2523 , ( "vertical-align", String.fromFloat converted.vertical ++ "em" )
2524 , ( "font-size", String.fromFloat converted.size ++ "em" )
2529typefaceAdjustment typefaces =
2536 case with.adjustment of
2542 ( fontAdjustmentRules
2543 (.full (convertAdjustment adjustment))
2544 , fontAdjustmentRules
2545 (.capital (convertAdjustment adjustment))
2570 "\"" ++ name ++ "\""
2572 ImportFont name url ->
2573 "\"" ++ name ++ "\""
2575 FontWith { name } ->
2576 "\"" ++ name ++ "\""
2581 FontFamily name typefaces ->
2582 Just ( name, typefaces )
2588renderProps force (Property key val) existing =
2590 existing ++ "\n " ++ key ++ ": " ++ val ++ " !important;"
2593 existing ++ "\n " ++ key ++ ": " ++ val ++ ";"
2596encodeStyles options stylesheet =
2602 renderStyleRule options style Nothing
2604 ( getStyleName style, Encode.list Encode.string styled )
2609toStyleSheetString : OptionRecord -> List Style -> String
2610toStyleSheetString options stylesheet =
2612 combine style rendered =
2613 { rules = rendered.rules ++ renderStyleRule options style Nothing
2615 case topLevelValue style of
2620 topLevel :: rendered.topLevel
2623 case List.foldl combine { topLevel = [], rules = [] } stylesheet of
2624 { topLevel, rules } ->
2625 renderTopLevelValues topLevel ++ String.concat rules
2628renderStyle : OptionRecord -> Maybe PseudoClass -> String -> List Property -> List String
2629renderStyle options maybePseudo selector props =
2632 [ selector ++ "{" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
2637 case options.hover of
2642 [ selector ++ "-hv {" ++ List.foldl (renderProps True) "" props ++ "\n}" ]
2645 [ selector ++ "-hv:hover {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
2650 List.foldl (renderProps False) "" props
2652 [ selector ++ "-fs:focus {" ++ renderedProps ++ "\n}"
2653 , ("." ++ classes.any ++ ":focus " ++ selector ++ "-fs {")
2656 , (selector ++ "-fs:focus-within {")
2659 , (".ui-slide-bar:focus + " ++ Internal.Style.dot classes.any ++ " .focusable-thumb" ++ selector ++ "-fs {")
2665 [ selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
2668renderStyleRule : OptionRecord -> Style -> Maybe PseudoClass -> List String
2669renderStyleRule options rule maybePseudo =
2671 Style selector props ->
2672 renderStyle options maybePseudo selector props
2674 Shadows name prop ->
2678 [ Property "box-shadow" prop
2681 Transparency name transparency ->
2691 [ Property "opacity" (String.fromFloat opacity)
2697 (".font-size-" ++ String.fromInt i)
2698 [ Property "font-size" (String.fromInt i ++ "px")
2701 FontFamily name typefaces ->
2705 |> List.filterMap renderVariants
2709 [ Property "font-family"
2711 |> List.map fontName
2714 , Property "font-feature-settings" features
2715 , Property "font-variant"
2716 (if List.any hasSmallCaps typefaces then
2729 Single class prop val ->
2736 Colored class prop color ->
2740 [ Property prop (formatColor color)
2743 SpacingStyle cls x y ->
2749 String.fromFloat (toFloat x / 2) ++ "px"
2752 String.fromFloat (toFloat y / 2) ++ "px"
2755 String.fromInt x ++ "px"
2758 String.fromInt y ++ "px"
2761 "." ++ Internal.Style.classes.row
2764 "." ++ Internal.Style.classes.wrapped ++ row
2767 "." ++ Internal.Style.classes.column
2770 "." ++ Internal.Style.classes.page
2773 "." ++ Internal.Style.classes.paragraph
2776 "." ++ Internal.Style.classes.alignLeft
2779 "." ++ Internal.Style.classes.alignRight
2782 "." ++ Internal.Style.classes.any
2785 "." ++ Internal.Style.classes.single
2788 [ renderStyle options maybePseudo (class ++ row ++ " > " ++ any ++ " + " ++ any) [ Property "margin-left" xPx ]
2790 -- margins don't apply to last element of normal, unwrapped rows
2791 -- , renderStyle options maybePseudo (class ++ row ++ " > " ++ any ++ ":first-child") [ Property "margin" "0" ]
2792 -- For wrapped rows, margins always apply because we handle "canceling out" the other margins manually in the element.
2793 , renderStyle options
2795 (class ++ wrappedRow ++ " > " ++ any)
2796 [ Property "margin" (halfY ++ " " ++ halfX)
2799 -- , renderStyle options maybePseudo
2800 -- (class ++ wrappedRow ++ " > " ++ any ++ ":last-child")
2801 -- [ Property "margin-right" "0"
2804 , renderStyle options maybePseudo (class ++ column ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2805 , renderStyle options maybePseudo (class ++ page ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2806 , renderStyle options maybePseudo (class ++ page ++ " > " ++ left) [ Property "margin-right" xPx ]
2807 , renderStyle options maybePseudo (class ++ page ++ " > " ++ right) [ Property "margin-left" xPx ]
2808 , renderStyle options
2810 (class ++ paragraph)
2811 [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2813 , renderStyle options
2815 ("textarea" ++ any ++ class)
2816 [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2817 , Property "height" ("calc(100% + " ++ String.fromInt y ++ "px)")
2820 -- , renderStyle options
2822 -- (class ++ paragraph ++ " > " ++ any)
2823 -- [ Property "margin-right" xPx
2824 -- , Property "margin-bottom" yPx
2826 , renderStyle options
2828 (class ++ paragraph ++ " > " ++ left)
2829 [ Property "margin-right" xPx
2831 , renderStyle options
2833 (class ++ paragraph ++ " > " ++ right)
2834 [ Property "margin-left" xPx
2836 , renderStyle options
2838 (class ++ paragraph ++ "::after")
2839 [ Property "content" "''"
2840 , Property "display" "block"
2841 , Property "height" "0"
2842 , Property "width" "0"
2843 , Property "margin-top" (String.fromInt (-1 * (y // 2)) ++ "px")
2845 , renderStyle options
2847 (class ++ paragraph ++ "::before")
2848 [ Property "content" "''"
2849 , Property "display" "block"
2850 , Property "height" "0"
2851 , Property "width" "0"
2852 , Property "margin-bottom" (String.fromInt (-1 * (y // 2)) ++ "px")
2856 PaddingStyle cls top right bottom left ->
2865 [ Property "padding"
2866 (String.fromFloat top
2868 ++ String.fromFloat right
2870 ++ String.fromFloat bottom
2872 ++ String.fromFloat left
2877 BorderWidth cls top right bottom left ->
2886 [ Property "border-width"
2889 ++ String.fromInt right
2891 ++ String.fromInt bottom
2893 ++ String.fromInt left
2898 GridTemplateStyle template ->
2902 ++ String.join "-" (List.map lengthClassName template.rows)
2904 ++ String.join "-" (List.map lengthClassName template.columns)
2906 ++ lengthClassName (Tuple.first template.spacing)
2908 ++ lengthClassName (Tuple.second template.spacing)
2911 toGridLength (Tuple.second template.spacing)
2914 toGridLength (Tuple.first template.spacing)
2917 toGridLengthHelper Nothing Nothing x
2919 toGridLengthHelper minimum maximum x =
2922 String.fromInt px ++ "px"
2925 case ( minimum, maximum ) of
2926 ( Nothing, Nothing ) ->
2929 ( Just minSize, Nothing ) ->
2930 "minmax(" ++ String.fromInt minSize ++ "px, " ++ "max-content)"
2932 ( Nothing, Just maxSize ) ->
2933 "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2935 ( Just minSize, Just maxSize ) ->
2936 "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2939 case ( minimum, maximum ) of
2940 ( Nothing, Nothing ) ->
2941 String.fromInt i ++ "fr"
2943 ( Just minSize, Nothing ) ->
2944 "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt i ++ "fr" ++ "fr)"
2946 ( Nothing, Just maxSize ) ->
2947 "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2949 ( Just minSize, Just maxSize ) ->
2950 "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2953 toGridLengthHelper (Just m) maximum len
2956 toGridLengthHelper minimum (Just m) len
2960 |> List.map toGridLength
2961 |> String.join ySpacing
2962 |> (\x -> "-ms-grid-columns: " ++ x ++ ";")
2966 |> List.map toGridLength
2967 |> String.join ySpacing
2968 |> (\x -> "-ms-grid-rows: " ++ x ++ ";")
2971 class ++ "{" ++ msColumns ++ msRows ++ "}"
2975 |> List.map toGridLength
2977 |> (\x -> "grid-template-columns: " ++ x ++ ";")
2981 |> List.map toGridLength
2983 |> (\x -> "grid-template-rows: " ++ x ++ ";")
2986 "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
2989 "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
2992 class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
2995 "@supports (display:grid) {" ++ modernGrid ++ "}"
3001 GridPosition position ->
3005 ++ String.fromInt position.row
3007 ++ String.fromInt position.col
3009 ++ String.fromInt position.width
3011 ++ String.fromInt position.height
3016 ++ String.fromInt position.row
3018 , "-ms-grid-row-span: "
3019 ++ String.fromInt position.height
3021 , "-ms-grid-column: "
3022 ++ String.fromInt position.col
3024 , "-ms-grid-column-span: "
3025 ++ String.fromInt position.width
3030 class ++ "{" ++ msPosition ++ "}"
3035 ++ String.fromInt position.row
3037 ++ String.fromInt (position.row + position.height)
3040 ++ String.fromInt position.col
3042 ++ String.fromInt (position.col + position.width)
3047 class ++ "{" ++ modernPosition ++ "}"
3050 "@supports (display:grid) {" ++ modernGrid ++ "}"
3056 PseudoSelector class styles ->
3058 renderPseudoRule style =
3059 renderStyleRule options style (Just class)
3061 List.concatMap renderPseudoRule styles
3063 Transform transform ->
3066 transformValue transform
3069 transformClass transform
3071 case ( class, val ) of
3072 ( Just cls, Just v ) ->
3076 [ Property "transform"
3084lengthClassName : Length -> String
3088 String.fromInt px ++ "px"
3094 String.fromInt i ++ "fr"
3097 "min" ++ String.fromInt min ++ lengthClassName len
3100 "max" ++ String.fromInt max ++ lengthClassName len
3103formatDropShadow shadow =
3105 [ String.fromFloat (Tuple.first shadow.offset) ++ "px"
3106 , String.fromFloat (Tuple.second shadow.offset) ++ "px"
3107 , String.fromFloat shadow.blur ++ "px"
3108 , formatColor shadow.color
3112formatTextShadow shadow =
3114 [ String.fromFloat (Tuple.first shadow.offset) ++ "px"
3115 , String.fromFloat (Tuple.second shadow.offset) ++ "px"
3116 , String.fromFloat shadow.blur ++ "px"
3117 , formatColor shadow.color
3121textShadowClass shadow =
3124 , floatClass (Tuple.first shadow.offset) ++ "px"
3125 , floatClass (Tuple.second shadow.offset) ++ "px"
3126 , floatClass shadow.blur ++ "px"
3127 , formatColorClass shadow.color
3131formatBoxShadow shadow =
3133 List.filterMap identity
3134 [ if shadow.inset then
3139 , Just <| String.fromFloat (Tuple.first shadow.offset) ++ "px"
3140 , Just <| String.fromFloat (Tuple.second shadow.offset) ++ "px"
3141 , Just <| String.fromFloat shadow.blur ++ "px"
3142 , Just <| String.fromFloat shadow.size ++ "px"
3143 , Just <| formatColor shadow.color
3147boxShadowClass shadow =
3149 [ if shadow.inset then
3154 , floatClass (Tuple.first shadow.offset) ++ "px"
3155 , floatClass (Tuple.second shadow.offset) ++ "px"
3156 , floatClass shadow.blur ++ "px"
3157 , floatClass shadow.size ++ "px"
3158 , formatColorClass shadow.color
3162floatClass : Float -> String
3164 String.fromInt (round (x * 255))
3167formatColor : Color -> String
3168formatColor (Rgba red green blue alpha) =
3170 ++ String.fromInt (round (red * 255))
3171 ++ ("," ++ String.fromInt (round (green * 255)))
3172 ++ ("," ++ String.fromInt (round (blue * 255)))
3173 ++ ("," ++ String.fromFloat alpha ++ ")")
3176formatColorClass : Color -> String
3177formatColorClass (Rgba red green blue alpha) =
3188 "spacing-" ++ String.fromInt x ++ "-" ++ String.fromInt y
3191paddingName top right bottom left =
3193 ++ String.fromInt top
3195 ++ String.fromInt right
3197 ++ String.fromInt bottom
3199 ++ String.fromInt left
3202paddingNameFloat top right bottom left =
3208 ++ floatClass bottom
3213getStyleName : Style -> String
3219 Transparency name o ->
3225 FontFamily name _ ->
3229 "font-size-" ++ String.fromInt i
3234 Colored class _ _ ->
3237 SpacingStyle cls x y ->
3240 PaddingStyle cls top right bottom left ->
3243 BorderWidth cls top right bottom left ->
3246 GridTemplateStyle template ->
3248 ++ String.join "-" (List.map lengthClassName template.rows)
3250 ++ String.join "-" (List.map lengthClassName template.columns)
3252 ++ lengthClassName (Tuple.first template.spacing)
3254 ++ lengthClassName (Tuple.second template.spacing)
3258 ++ String.fromInt pos.row
3260 ++ String.fromInt pos.col
3262 ++ String.fromInt pos.width
3264 ++ String.fromInt pos.height
3266 PseudoSelector selector subStyle ->
3281 case getStyleName sty of
3286 styleName ++ "-" ++ name
3292 Maybe.withDefault "" (transformClass x)
3299asGrid : LayoutContext
3304asRow : LayoutContext
3309asColumn : LayoutContext
3319asParagraph : LayoutContext
3324asTextColumn : LayoutContext
3333map : (msg -> msg1) -> Element msg -> Element msg1
3338 { styles = styled.styles
3339 , html = \add context -> VirtualDom.map fn <| styled.html add context
3343 Unstyled (VirtualDom.map fn << html)
3352mapAttr : (msg -> msg1) -> Attribute aligned msg -> Attribute aligned msg1
3358 Describe description ->
3359 Describe description
3376 StyleClass flag style ->
3377 StyleClass flag style
3379 Nearby location elem ->
3380 Nearby location (map fn elem)
3383 Attr (VirtualDom.mapAttribute fn htmlAttr)
3385 TransformComponent fl trans ->
3386 TransformComponent fl trans
3389mapAttrFromStyle : (msg -> msg1) -> Attribute Never msg -> Attribute () msg1
3390mapAttrFromStyle fn attr =
3395 Describe description ->
3396 Describe description
3410 -- invalidation key "border-color" as opposed to "border-color-10-10-10" that will be the key for the class
3414 StyleClass flag style ->
3415 StyleClass flag style
3417 Nearby location elem ->
3418 Nearby location (map fn elem)
3421 Attr (VirtualDom.mapAttribute fn htmlAttr)
3423 TransformComponent fl trans ->
3424 TransformComponent fl trans
3427unwrapDecorations : List (Attribute Never Never) -> List Style
3428unwrapDecorations attrs =
3429 case List.foldl unwrapDecsHelper ( [], Untransformed ) attrs of
3430 ( styles, transform ) ->
3431 Transform transform :: styles
3434unwrapDecsHelper attr ( styles, trans ) =
3435 case removeNever attr of
3436 StyleClass _ style ->
3437 ( style :: styles, trans )
3439 TransformComponent flag component ->
3440 ( styles, composeTransformation trans component )
3446removeNever : Attribute Never Never -> Attribute () msg
3448 mapAttrFromStyle Basics.never style
3451tag : String -> Style -> Style
3454 Single class prop val ->
3455 Single (label ++ "-" ++ class) prop val
3457 Colored class prop val ->
3458 Colored (label ++ "-" ++ class) prop val
3460 Style class props ->
3461 Style (label ++ "-" ++ class) props
3463 Transparency class o ->
3464 Transparency (label ++ "-" ++ class) o
3470onlyStyles : Attribute aligned msg -> Maybe Style
3473 StyleClass _ style ->
3481{- Font Adjustments -}
3484convertAdjustment adjustment =
3500 ((ascender - newBaseline) / 2) + newBaseline
3503 ((ascender - descender) / 2) + descender
3506 [ adjustment.capital
3507 , adjustment.baseline
3508 , adjustment.descender
3509 , adjustment.lowercase
3513 Maybe.withDefault adjustment.capital (List.maximum lines)
3516 Maybe.withDefault adjustment.descender (List.minimum lines)
3520 |> List.filter (\x -> x /= descender)
3522 |> Maybe.withDefault adjustment.baseline
3528 1 / (ascender - newBaseline)
3531 1 / (ascender - descender)
3536 -- (oldMiddle - newFullMiddle) * 2
3539 adjust fullSize (ascender - descender) fullVertical
3541 adjust capitalSize (ascender - newBaseline) capitalVertical
3545adjust size height vertical =
3546 { vertical = vertical
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list