@@ -1,4 +1,109 @@
1−module Internal.Model exposing (Aligned(..), Angle, Attribute(..), Axis(..), Children(..), Color(..), Description(..), Element(..), EmbedStyle(..), FocusStyle, Font(..), Gathered, HAlign(..), HoverSetting(..), LayoutContext(..), Length(..), Location(..), NodeName(..), Option(..), OptionRecord, Padding(..), Property(..), PseudoClass(..), RenderMode(..), Shadow, Spacing(..), Style(..), TransformComponent(..), Transformation(..), VAlign(..), XYZ, addNodeName, addWhen, alignXName, alignYName, asColumn, asEl, asGrid, asParagraph, asRow, asTextColumn, boxShadowName, columnClass, composeTransformation, contextClasses, createElement, defaultOptions, div, element, embedKeyed, embedWith, extractSpacingAndPadding, filter, finalizeNode, floatClass, focusDefaultStyle, formatBoxShadow, formatColor, formatColorClass, formatDropShadow, formatTextShadow, gatherAttrRecursive, get, getHeight, getSpacing, getStyleName, getWidth, gridClass, htmlClass, lengthClassName, map, mapAttr, mapAttrFromStyle, noStyleSheet, onlyStyles, optionsToRecord, paddingName, pageClass, paragraphClass, reduceRecursive, reduceRecursiveCalcName, reduceStyles, reduceStylesRecursive, removeNever, renderFocusStyle, renderFont, renderFontClassName, renderHeight, renderRoot, renderWidth, rootStyle, rowClass, singleClass, skippable, sortedReduce, spacingName, staticRoot, tag, textElement, textElementFill, textShadowName, toHtml, toStyleSheet, toStyleSheetString, transformClass, transformValue, unit, unstyled, untransformed, unwrapDecorations, unwrapDecsHelper)
1+module Internal.Model exposing
2+ ( Aligned(..)
3+ , Angle
4+ , Attribute(..)
5+ , Axis(..)
6+ , Children(..)
7+ , Color(..)
8+ , Description(..)
9+ , Element(..)
10+ , EmbedStyle(..)
11+ , FocusStyle
12+ , Font(..)
13+ , Gathered
14+ , HAlign(..)
15+ , HoverSetting(..)
16+ , LayoutContext(..)
17+ , Length(..)
18+ , Location(..)
19+ , NearbyChildren(..)
20+ , NodeName(..)
21+ , Option(..)
22+ , OptionRecord
23+ , Padding(..)
24+ , Property(..)
25+ , PseudoClass(..)
26+ , RenderMode(..)
27+ , Shadow
28+ , Spacing(..)
29+ , Style(..)
30+ , TransformComponent(..)
31+ , Transformation(..)
32+ , VAlign(..)
33+ , Variant(..)
34+ , XYZ
35+ , addNodeName
36+ , addWhen
37+ , alignXName
38+ , alignYName
39+ , asColumn
40+ , asEl
41+ , asGrid
42+ , asParagraph
43+ , asRow
44+ , asTextColumn
45+ , boxShadowClass
46+ , columnClass
47+ , composeTransformation
48+ , contextClasses
49+ , createElement
50+ , defaultOptions
51+ , div
52+ , element
53+ , embedKeyed
54+ , embedWith
55+ , extractSpacingAndPadding
56+ , filter
57+ , finalizeNode
58+ , floatClass
59+ , focusDefaultStyle
60+ , formatBoxShadow
61+ , formatColor
62+ , formatColorClass
63+ , formatDropShadow
64+ , formatTextShadow
65+ , gatherAttrRecursive
66+ , get
67+ , getHeight
68+ , getSpacing
69+ , getStyleName
70+ , getWidth
71+ , gridClass
72+ , htmlClass
73+ , isContent
74+ , lengthClassName
75+ , map
76+ , mapAttr
77+ , mapAttrFromStyle
78+ , noStyleSheet
79+ , onlyStyles
80+ , optionsToRecord
81+ , paddingName
82+ , paddingNameFloat
83+ , pageClass
84+ , paragraphClass
85+ , reduceRecursive
86+ , reduceStyles
87+ , reduceStylesRecursive
88+ , removeNever
89+ , renderFontClassName
90+ , renderHeight
91+ , renderRoot
92+ , renderVariant
93+ , renderWidth
94+ , rootStyle
95+ , rowClass
96+ , singleClass
97+ , spacingName
98+ , tag
99+ , textShadowClass
100+ , toHtml
101+ , toStyleSheet
102+ , transformClass
103+ , unstyled
104+ , unwrapDecorations
105+ , variantName
106+ )
2107
3108{-| -}
4109
@@ -7,7 +112,7 @@ import Html.Attributes
7112import Html.Keyed
8113import Internal.Flag as Flag exposing (Flag)
9114import Internal.Style exposing (classes, dot)
10−import Json.Encode as Json
115+import Json.Encode as Encode
11116import Set exposing (Set)
12117import VirtualDom
13118
@@ -68,7 +173,8 @@ type Style
68173 | Single String String String
69174 | Colored String String Color
70175 | SpacingStyle String Int Int
71− | PaddingStyle String Int Int Int Int
176+ | BorderWidth String Int Int Int Int
177+ | PaddingStyle String Float Float Float Float
72178 | GridTemplateStyle
73179 { spacing : ( Length, Length )
74180 , columns : List Length
@@ -99,12 +205,86 @@ type PseudoClass
99205 | Active
100206
101207
208+{-| -}
209+type alias Adjustment =
210+ { capital : Float
211+ , lowercase : Float
212+ , baseline : Float
213+ , descender : Float
214+ }
215+
216+
102217type Font
103218 = Serif
104219 | SansSerif
105220 | Monospace
106221 | Typeface String
107222 | ImportFont String String
223+ | FontWith
224+ { name : String
225+ , adjustment : Maybe Adjustment
226+ , variants : List Variant
227+ }
228+
229+
230+type Variant
231+ = VariantActive String
232+ | VariantOff String
233+ | VariantIndexed String Int
234+
235+
236+renderVariant var =
237+ case var of
238+ VariantActive name ->
239+ "\"" ++ name ++ "\""
240+
241+ VariantOff name ->
242+ "\"" ++ name ++ "\" 0"
243+
244+ VariantIndexed name index ->
245+ "\"" ++ name ++ "\" " ++ String.fromInt index
246+
247+
248+variantName var =
249+ case var of
250+ VariantActive name ->
251+ name
252+
253+ VariantOff name ->
254+ name ++ "-0"
255+
256+ VariantIndexed name index ->
257+ name ++ "-" ++ String.fromInt index
258+
259+
260+renderVariants typeface =
261+ case typeface of
262+ FontWith font ->
263+ Just (String.join ", " (List.map renderVariant font.variants))
264+
265+ _ ->
266+ Nothing
267+
268+
269+isSmallCaps var =
270+ case var of
271+ VariantActive name ->
272+ name == "smcp"
273+
274+ VariantOff name ->
275+ False
276+
277+ VariantIndexed name index ->
278+ name == "smcp" && index == 1
279+
280+
281+hasSmallCaps typeface =
282+ case typeface of
283+ FontWith font ->
284+ List.any isSmallCaps font.variants
285+
286+ _ ->
287+ False
108288
109289
110290type Property
@@ -192,6 +372,13 @@ type NodeName
192372 | Embedded String String
193373
194374
375+type NearbyChildren msg
376+ = NoNearbyChildren
377+ | ChildrenBehind (List (Html.Html msg))
378+ | ChildrenInFront (List (Html.Html msg))
379+ | ChildrenBehindAndInFront (List (Html.Html msg)) (List (Html.Html msg))
380+
381+
195382div =
196383 Generic
197384
@@ -200,7 +387,7 @@ type alias Gathered msg =
200387 { node : NodeName
201388 , attributes : List (VirtualDom.Attribute msg)
202389 , styles : List Style
203− , children : List (VirtualDom.Node msg)
390+ , children : NearbyChildren msg
204391 , has : Flag.Field
205392 }
206393
@@ -268,7 +455,10 @@ finalizeNode has node attributes children embedMode parentContext =
268455 Embedded nodeName internal ->
269456 VirtualDom.node nodeName
270457 attributes
271− [ createNode internal [ Html.Attributes.class (classes.any ++ " " ++ classes.single) ]
458+ [ createNode internal
459+ [ Html.Attributes.class
460+ (classes.any ++ " " ++ classes.single)
461+ ]
272462 ]
273463 in
274464 case parentContext of
@@ -345,49 +535,45 @@ finalizeNode has node attributes children embedMode parentContext =
345535
346536
347537embedWith static opts styles children =
538+ let
539+ dynamicStyleSheet =
540+ styles
541+ |> List.foldl reduceStyles ( Set.empty, renderFocusStyle opts.focus )
542+ |> Tuple.second
543+ -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
544+ -- |> sortedReduce
545+ |> toStyleSheet opts
546+ in
348547 if static then
349− staticRoot
350− :: (styles
351− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
352− |> Tuple.second
353− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
354− -- |> sortedReduce
355− |> toStyleSheet opts
356− )
548+ staticRoot opts
549+ :: dynamicStyleSheet
357550 :: children
358551
359552 else
360− (styles
361− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
362− |> Tuple.second
363− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
364− -- |> sortedReduce
365− |> toStyleSheet opts
366− )
553+ dynamicStyleSheet
367554 :: children
368555
369556
370557embedKeyed static opts styles children =
558+ let
559+ dynamicStyleSheet =
560+ styles
561+ |> List.foldl reduceStyles ( Set.empty, renderFocusStyle opts.focus )
562+ |> Tuple.second
563+ -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
564+ -- |> sortedReduce
565+ |> toStyleSheet opts
566+ in
371567 if static then
372− ( "static-stylesheet", staticRoot )
568+ ( "static-stylesheet", staticRoot opts )
373569 :: ( "dynamic-stylesheet"
374− , styles
375− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
376− |> Tuple.second
377− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
378− -- |> sortedReduce
379− |> toStyleSheet opts
570+ , dynamicStyleSheet
380571 )
381572 :: children
382573
383574 else
384575 ( "dynamic-stylesheet"
385− , styles
386− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
387− |> Tuple.second
388− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
389− -- |> sortedReduce
390− |> toStyleSheet opts
576+ , dynamicStyleSheet
391577 )
392578 :: children
393579
@@ -703,7 +889,16 @@ skippable flag style =
703889 False
704890
705891
706−gatherAttrRecursive : String -> NodeName -> Flag.Field -> Transformation -> List Style -> List (VirtualDom.Attribute msg) -> List (VirtualDom.Node msg) -> List (Attribute aligned msg) -> Gathered msg
892+gatherAttrRecursive :
893+ String
894+ -> NodeName
895+ -> Flag.Field
896+ -> Transformation
897+ -> List Style
898+ -> List (VirtualDom.Attribute msg)
899+ -> NearbyChildren msg
900+ -> List (Attribute aligned msg)
901+ -> Gathered msg
707902gatherAttrRecursive classes node has transform styles attrs children elementAttrs =
708903 case elementAttrs of
709904 [] ->
@@ -837,7 +1032,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
8371032 in
8381033 gatherAttrRecursive (classes ++ " " ++ newClass)
8391034 node
840− (Flag.merge addToFlags has)
1035+ (Flag.merge addToFlags (Flag.add Flag.width has))
8411036 transform
8421037 (newStyles ++ styles)
8431038 attrs
@@ -858,7 +1053,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
8581053 name =
8591054 "height-px-" ++ val
8601055 in
861− gatherAttrRecursive (name ++ " " ++ classes)
1056+ gatherAttrRecursive (Internal.Style.classes.heightExact ++ " " ++ name ++ " " ++ classes)
8621057 node
8631058 (Flag.add Flag.height has)
8641059 transform
@@ -915,7 +1110,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
9151110 in
9161111 gatherAttrRecursive (classes ++ " " ++ newClass)
9171112 node
918− (Flag.merge addToFlags has)
1113+ (Flag.merge addToFlags (Flag.add Flag.height has))
9191114 transform
9201115 (newStyles ++ styles)
9211116 attrs
@@ -947,20 +1142,15 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
9471142 gatherAttrRecursive classes (addNodeName "h6" node) has transform styles attrs children remaining
9481143
9491144 Paragraph ->
950− let
951− newNode =
952− case node of
953− Generic ->
954− NodeName "p"
955−
956− NodeName name ->
957− NodeName name
958−
959− Embedded x y ->
960− Embedded x y
961− in
962− gatherAttrRecursive classes
963− newNode
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.
1151+ gatherAttrRecursive
1152+ classes
1153+ node
9641154 has
9651155 transform
9661156 styles
@@ -995,75 +1185,16 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
9951185
9961186 Styled styled ->
9971187 styles ++ styled.styles
998−
999− nearbyElement =
1000− Html.div
1001− [ Html.Attributes.class <|
1002− case location of
1003− Above ->
1004− String.join " "
1005− [ Internal.Style.classes.any
1006− , Internal.Style.classes.single
1007− , Internal.Style.classes.above
1008− ]
1009−
1010− Below ->
1011− String.join " "
1012− [ Internal.Style.classes.any
1013− , Internal.Style.classes.single
1014− , Internal.Style.classes.below
1015− ]
1016−
1017− OnRight ->
1018− String.join " "
1019− [ Internal.Style.classes.any
1020− , Internal.Style.classes.single
1021− , Internal.Style.classes.onRight
1022− ]
1023−
1024− OnLeft ->
1025− String.join " "
1026− [ Internal.Style.classes.any
1027− , Internal.Style.classes.single
1028− , Internal.Style.classes.onLeft
1029− ]
1030−
1031− InFront ->
1032− String.join " "
1033− [ Internal.Style.classes.any
1034− , Internal.Style.classes.single
1035− , Internal.Style.classes.inFront
1036− ]
1037−
1038− Behind ->
1039− String.join " "
1040− [ Internal.Style.classes.any
1041− , Internal.Style.classes.single
1042− , Internal.Style.classes.behind
1043− ]
1044− ]
1045− [ case elem of
1046− Empty ->
1047− VirtualDom.text ""
1048−
1049− Text str ->
1050− textElement str
1051−
1052− Unstyled html ->
1053− html asEl
1054−
1055− Styled styled ->
1056− styled.html NoStyleSheet asEl
1057− ]
1058−
1059− newClasses =
1060− if location == Behind then
1061− Internal.Style.classes.hasBehind ++ " " ++ classes
1062−
1063− else
1064− classes
10651188 in
1066− gatherAttrRecursive newClasses node has transform newStyles attrs (nearbyElement :: children) remaining
1189+ gatherAttrRecursive
1190+ classes
1191+ node
1192+ has
1193+ transform
1194+ newStyles
1195+ attrs
1196+ (addNearbyElement location elem children)
1197+ remaining
10671198
10681199 AlignX x ->
10691200 if Flag.present Flag.xAlign has then
@@ -1119,6 +1250,106 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
11191250 remaining
11201251
11211252
1253+addNearbyElement location elem existing =
1254+ let
1255+ nearby =
1256+ nearbyElement location elem
1257+ in
1258+ case existing of
1259+ NoNearbyChildren ->
1260+ case location of
1261+ Behind ->
1262+ ChildrenBehind [ nearby ]
1263+
1264+ _ ->
1265+ ChildrenInFront [ nearby ]
1266+
1267+ ChildrenBehind existingBehind ->
1268+ case location of
1269+ Behind ->
1270+ ChildrenBehind (nearby :: existingBehind)
1271+
1272+ _ ->
1273+ ChildrenBehindAndInFront existingBehind [ nearby ]
1274+
1275+ ChildrenInFront existingInFront ->
1276+ case location of
1277+ Behind ->
1278+ ChildrenBehindAndInFront [ nearby ] existingInFront
1279+
1280+ _ ->
1281+ ChildrenInFront (nearby :: existingInFront)
1282+
1283+ ChildrenBehindAndInFront existingBehind existingInFront ->
1284+ case location of
1285+ Behind ->
1286+ ChildrenBehindAndInFront (nearby :: existingBehind) existingInFront
1287+
1288+ _ ->
1289+ ChildrenBehindAndInFront existingBehind (nearby :: existingInFront)
1290+
1291+
1292+nearbyElement location elem =
1293+ Html.div
1294+ [ Html.Attributes.class <|
1295+ case location of
1296+ Above ->
1297+ String.join " "
1298+ [ Internal.Style.classes.nearby
1299+ , Internal.Style.classes.single
1300+ , Internal.Style.classes.above
1301+ ]
1302+
1303+ Below ->
1304+ String.join " "
1305+ [ Internal.Style.classes.nearby
1306+ , Internal.Style.classes.single
1307+ , Internal.Style.classes.below
1308+ ]
1309+
1310+ OnRight ->
1311+ String.join " "
1312+ [ Internal.Style.classes.nearby
1313+ , Internal.Style.classes.single
1314+ , Internal.Style.classes.onRight
1315+ ]
1316+
1317+ OnLeft ->
1318+ String.join " "
1319+ [ Internal.Style.classes.nearby
1320+ , Internal.Style.classes.single
1321+ , Internal.Style.classes.onLeft
1322+ ]
1323+
1324+ InFront ->
1325+ String.join " "
1326+ [ Internal.Style.classes.nearby
1327+ , Internal.Style.classes.single
1328+ , Internal.Style.classes.inFront
1329+ ]
1330+
1331+ Behind ->
1332+ String.join " "
1333+ [ Internal.Style.classes.nearby
1334+ , Internal.Style.classes.single
1335+ , Internal.Style.classes.behind
1336+ ]
1337+ ]
1338+ [ case elem of
1339+ Empty ->
1340+ VirtualDom.text ""
1341+
1342+ Text str ->
1343+ textElement str
1344+
1345+ Unstyled html ->
1346+ html asEl
1347+
1348+ Styled styled ->
1349+ styled.html NoStyleSheet asEl
1350+ ]
1351+
1352+
11221353renderWidth w =
11231354 case w of
11241355 Px px ->
@@ -1205,7 +1436,7 @@ renderHeight h =
12051436 "height-px-" ++ val
12061437 in
12071438 ( Flag.none
1208− , name
1439+ , Internal.Style.classes.heightExact ++ " " ++ name
12091440 , [ Single name "height" (val ++ "px") ]
12101441 )
12111442
@@ -1228,7 +1459,7 @@ renderHeight h =
12281459 , [ Single
12291460 (Internal.Style.classes.any
12301461 ++ "."
1231− ++ Internal.Style.classes.row
1462+ ++ Internal.Style.classes.column
12321463 ++ " > "
12331464 ++ (Internal.Style.dot <| "height-fill-" ++ String.fromInt portion)
12341465 )
@@ -1247,7 +1478,9 @@ renderHeight h =
12471478 Single
12481479 cls
12491480 "min-height"
1250− (String.fromInt minSize ++ "px")
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")
12511484
12521485 ( newFlag, newAttrs, newStyle ) =
12531486 renderHeight len
@@ -1325,7 +1558,7 @@ element : LayoutContext -> NodeName -> List (Attribute aligned msg) -> Children
13251558element context node attributes children =
13261559 attributes
13271560 |> List.reverse
1328− |> gatherAttrRecursive (contextClasses context) node Flag.none untransformed [] [] []
1561+ |> gatherAttrRecursive (contextClasses context) node Flag.none untransformed [] [] NoNearbyChildren
13291562 |> createElement context children
13301563
13311564
@@ -1333,13 +1566,6 @@ untransformed =
13331566 Untransformed
13341567
13351568
1336−
1337−-- space =
1338−-- VirtualDom.text " "
1339−-- keyedSpace =
1340−-- ( " ", space )
1341−
1342−
13431569createElement : LayoutContext -> Children (Element msg) -> Gathered msg -> Element msg
13441570createElement context children rendered =
13451571 let
@@ -1381,36 +1607,33 @@ createElement context children rendered =
13811607 -- Same if it's a column or row with one child and width-content, height-content
13821608 -- interferes with css grid
13831609 -- Maybe we could unpack text elements in a paragraph as well,
1384− -- however embedded style elements that are larger than the line height will overlap with exisitng text.
1610+ -- however, embedded elements that are larger than the line height will overlap with exisitng text.
13851611 -- I don't think that's what we want.
1386− if
1387− context
1388− == asEl
1389− || context
1390− == asParagraph
1391− then
1392− ( VirtualDom.text
1393− (if context == asParagraph then
1394− str ++ " "
1395−
1396− else
1397− str
1398− )
1399− :: htmls
1400− , existingStyles
1401− )
1402−
1403− else
1404− ( textElement
1405− (if context == asParagraph then
1406− str ++ " "
1407−
1408− else
1409− str
1410− )
1411− :: htmls
1412− , existingStyles
1413− )
1612+ -- if
1613+ -- context
1614+ -- == asEl
1615+ -- || context
1616+ -- == asParagraph
1617+ -- then
1618+ -- ( VirtualDom.text
1619+ -- (if context == asParagraph then
1620+ -- str
1621+ -- else
1622+ -- str
1623+ -- )
1624+ -- :: htmls
1625+ -- , existingStyles
1626+ -- )
1627+ -- else
1628+ ( (if context == asEl then
1629+ textElementFill str
1630+
1631+ else
1632+ textElement str
1633+ )
1634+ :: htmls
1635+ , existingStyles
1636+ )
14141637
14151638 Empty ->
14161639 ( htmls, existingStyles )
@@ -1452,38 +1675,30 @@ createElement context children rendered =
14521675 -- TEXT OPTIMIZATION
14531676 -- You can have raw text if the element is an el, and has `width-content` and `height-content`
14541677 -- Same if it's a column or row with one child and width-content, height-content
1455− if
1456− context
1457− == asEl
1458− || context
1459− == asParagraph
1460− then
1461− ( ( key
1462− , VirtualDom.text
1463− (if context == asParagraph then
1464− str ++ " "
1465−
1466− else
1467− str
1468− )
1469− )
1470− :: htmls
1471− , existingStyles
1472− )
1473−
1474− else
1475− ( ( key
1476− , textElement
1477− (if context == asParagraph then
1478− str ++ " "
1678+ -- if
1679+ -- context
1680+ -- == asEl
1681+ -- || context
1682+ -- == asParagraph
1683+ -- then
1684+ -- ( ( key
1685+ -- , VirtualDom.text
1686+ -- str
1687+ -- )
1688+ -- :: htmls
1689+ -- , existingStyles
1690+ -- )
1691+ -- else
1692+ ( ( key
1693+ , if context == asEl then
1694+ textElementFill str
14791695
1480− else
1481− str
1482− )
1483− )
1484− :: htmls
1485− , existingStyles
1486− )
1696+ else
1697+ textElement str
1698+ )
1699+ :: htmls
1700+ , existingStyles
1701+ )
14871702
14881703 Empty ->
14891704 ( htmls, existingStyles )
@@ -1506,7 +1721,9 @@ createElement context children rendered =
15061721 (finalizeNode rendered.has
15071722 rendered.node
15081723 rendered.attributes
1509− (Keyed <| List.map (\x -> ( "nearby-elements-pls", x )) rendered.children ++ keyed)
1724+ (Keyed
1725+ (addKeyedChildren "nearby-element-pls" keyed rendered.children)
1726+ )
15101727 NoStyleSheet
15111728 )
15121729
@@ -1514,7 +1731,13 @@ createElement context children rendered =
15141731 Styled
15151732 { styles = allStyles
15161733 , html =
1517− finalizeNode rendered.has rendered.node rendered.attributes (Keyed (List.map (\x -> ( "nearby-elements-pls", x )) rendered.children ++ keyed))
1734+ finalizeNode
1735+ rendered.has
1736+ rendered.node
1737+ rendered.attributes
1738+ (Keyed
1739+ (addKeyedChildren "nearby-element-pls" keyed rendered.children)
1740+ )
15181741 }
15191742
15201743 Unkeyed unkeyedChildren ->
@@ -1531,20 +1754,58 @@ createElement context children rendered =
15311754 case newStyles of
15321755 [] ->
15331756 Unstyled
1534− (finalizeNode rendered.has
1757+ (finalizeNode
1758+ rendered.has
15351759 rendered.node
15361760 rendered.attributes
1537− (Unkeyed <| rendered.children ++ unkeyed)
1761+ (Unkeyed (addChildren unkeyed rendered.children))
15381762 NoStyleSheet
15391763 )
15401764
15411765 allStyles ->
15421766 Styled
15431767 { styles = allStyles
1544− , html = finalizeNode rendered.has rendered.node rendered.attributes (Unkeyed (rendered.children ++ unkeyed))
1768+ , html =
1769+ finalizeNode
1770+ rendered.has
1771+ rendered.node
1772+ rendered.attributes
1773+ (Unkeyed (addChildren unkeyed rendered.children))
15451774 }
15461775
15471776
1777+addChildren existing nearbyChildren =
1778+ case nearbyChildren of
1779+ NoNearbyChildren ->
1780+ existing
1781+
1782+ ChildrenBehind behind ->
1783+ behind ++ existing
1784+
1785+ ChildrenInFront inFront ->
1786+ existing ++ inFront
1787+
1788+ ChildrenBehindAndInFront behind inFront ->
1789+ behind ++ existing ++ inFront
1790+
1791+
1792+addKeyedChildren key existing nearbyChildren =
1793+ case nearbyChildren of
1794+ NoNearbyChildren ->
1795+ existing
1796+
1797+ ChildrenBehind behind ->
1798+ List.map (\x -> ( key, x )) behind ++ existing
1799+
1800+ ChildrenInFront inFront ->
1801+ existing ++ List.map (\x -> ( key, x )) inFront
1802+
1803+ ChildrenBehindAndInFront behind inFront ->
1804+ List.map (\x -> ( key, x )) behind
1805+ ++ existing
1806+ ++ List.map (\x -> ( key, x )) inFront
1807+
1808+
15481809unit =
15491810 0
15501811
@@ -1556,8 +1817,20 @@ defaultOptions =
15561817 }
15571818
15581819
1559−staticRoot =
1560− VirtualDom.node "style" [] [ VirtualDom.text Internal.Style.rules ]
1820+staticRoot : OptionRecord -> VirtualDom.Node msg
1821+staticRoot opts =
1822+ case opts.mode of
1823+ Layout ->
1824+ -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
1825+ VirtualDom.node "div"
1826+ []
1827+ [ VirtualDom.node "style" [] [ VirtualDom.text Internal.Style.rules ] ]
1828+
1829+ NoStaticStyleSheet ->
1830+ VirtualDom.text ""
1831+
1832+ WithVirtualCss ->
1833+ VirtualDom.node "elm-ui-static-rules" [ VirtualDom.property "rules" (Encode.string Internal.Style.rules) ] []
15611834
15621835
15631836addWhen ifThis x to =
@@ -1640,6 +1913,21 @@ filter attrs =
16401913 attrs
16411914
16421915
1916+isContent len =
1917+ case len of
1918+ Content ->
1919+ True
1920+
1921+ Max _ l ->
1922+ isContent l
1923+
1924+ Min _ l ->
1925+ isContent l
1926+
1927+ _ ->
1928+ False
1929+
1930+
16431931get : List (Attribute aligned msg) -> (Attribute aligned msg -> Bool) -> List (Attribute aligned msg)
16441932get attrs isAttr =
16451933 attrs
@@ -1660,7 +1948,7 @@ type Spacing
16601948
16611949
16621950type Padding
1663− = Padding String Int Int Int Int
1951+ = Padding String Float Float Float Float
16641952
16651953
16661954extractSpacingAndPadding : List (Attribute aligned msg) -> ( Maybe Padding, Maybe Spacing )
@@ -1756,35 +2044,44 @@ getHeight attrs =
17562044 Nothing
17572045
17582046
2047+textElementClasses : String
2048+textElementClasses =
2049+ classes.any
2050+ ++ " "
2051+ ++ classes.text
2052+ ++ " "
2053+ ++ classes.widthContent
2054+ ++ " "
2055+ ++ classes.heightContent
2056+
2057+
17592058textElement : String -> VirtualDom.Node msg
17602059textElement str =
17612060 Html.div
17622061 [ Html.Attributes.class
1763− (String.join " "
1764− [ classes.any
1765− , classes.text
1766− , classes.widthContent
1767− , classes.heightContent
1768− ]
1769− )
2062+ textElementClasses
17702063 ]
17712064 [ Html.text str ]
17722065
17732066
2067+textElementFillClasses : String
2068+textElementFillClasses =
2069+ classes.any
2070+ ++ " "
2071+ ++ classes.text
2072+ ++ " "
2073+ ++ classes.widthFill
2074+ ++ " "
2075+ ++ classes.heightFill
2076+
2077+
17742078textElementFill : String -> VirtualDom.Node msg
17752079textElementFill str =
1776− VirtualDom.node "div"
1777− [ VirtualDom.property "className"
1778− (Json.string <|
1779− String.join " "
1780− [ classes.any
1781− , classes.text
1782− , classes.widthFill
1783− , classes.heightFill
1784− ]
1785− )
2080+ Html.div
2081+ [ Html.Attributes.class
2082+ textElementFillClasses
17862083 ]
1787− [ VirtualDom.text str ]
2084+ [ Html.text str ]
17882085
17892086
17902087type Children x
@@ -1792,10 +2089,6 @@ type Children x
17922089 | Keyed (List ( String, x ))
17932090
17942091
1795−
1796−-- toHtml : OptionRecord -> Element msg -> VirtualDom.Node msg
1797−
1798−
17992092toHtml mode el =
18002093 case el of
18012094 Unstyled html ->
@@ -1831,8 +2124,7 @@ renderRoot optionList attributes child =
18312124
18322125
18332126type RenderMode
1834− = Viewport
1835− | Layout
2127+ = Layout
18362128 | NoStaticStyleSheet
18372129 | WithVirtualCss
18382130
@@ -1881,10 +2173,8 @@ rootStyle =
18812173 , SansSerif
18822174 ]
18832175 in
1884− [ StyleClass Flag.bgColor (Colored ("bg-color-" ++ formatColorClass (Rgba 1 1 1 1)) "background-color" (Rgba 1 1 1 1))
1885− , StyleClass Flag.fontColor (Colored ("font-color-" ++ formatColorClass (Rgba 0 0 0 1)) "color" (Rgba 0 0 0 1))
1886−
1887− -- , StyleClass Flag.fontSize (Single "font-size-20" "font-size" "20px")
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))
18882178 , StyleClass Flag.fontSize (FontSize 20)
18892179 , StyleClass Flag.fontFamily <|
18902180 FontFamily (List.foldl renderFontClassName "font-" families)
@@ -1916,14 +2206,49 @@ renderFontClassName font current =
19162206 |> String.toLower
19172207 |> String.words
19182208 |> String.join "-"
2209+
2210+ FontWith { name } ->
2211+ name
2212+ |> String.toLower
2213+ |> String.words
2214+ |> String.join "-"
19192215 )
19202216
19212217
19222218renderFocusStyle :
19232219 FocusStyle
1924− -> Style
2220+ -> List Style
19252221renderFocusStyle focus =
1926− Style (Internal.Style.dot classes.any ++ ":focus .focusable, " ++ Internal.Style.dot classes.any ++ ".focusable: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
2226+ , Maybe.map
2227+ (\shadow ->
2228+ Property "box-shadow"
2229+ (formatBoxShadow
2230+ { color = shadow.color
2231+ , offset =
2232+ shadow.offset
2233+ |> Tuple.mapFirst toFloat
2234+ |> Tuple.mapSecond toFloat
2235+ , inset = False
2236+ , blur =
2237+ toFloat shadow.blur
2238+ , size =
2239+ toFloat shadow.size
2240+ }
2241+ )
2242+ )
2243+ focus.shadow
2244+ , Just <| Property "outline" "none"
2245+ ]
2246+ )
2247+ , Style
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")
2251+ )
19272252 (List.filterMap identity
19282253 [ Maybe.map (\color -> Property "border-color" (formatColor color)) focus.borderColor
19292254 , Maybe.map (\color -> Property "background-color" (formatColor color)) focus.backgroundColor
@@ -1946,6 +2271,7 @@ renderFocusStyle focus =
19462271 , Just <| Property "outline" "none"
19472272 ]
19482273 )
2274+ ]
19492275
19502276
19512277focusDefaultStyle : { backgroundColor : Maybe Color, borderColor : Maybe Color, shadow : Maybe Shadow }
@@ -1957,7 +2283,7 @@ focusDefaultStyle =
19572283 { color =
19582284 Rgba (155 / 255) (203 / 255) 1 1
19592285 , offset = ( 0, 0 )
1960− , blur = 3
2286+ , blur = 0
19612287 , size = 3
19622288 }
19632289 }
@@ -2025,498 +2351,734 @@ optionsToRecord options =
20252351 options
20262352
20272353
2028−renderFont : List Font -> String
2029−renderFont families =
2354+toStyleSheet : OptionRecord -> List Style -> VirtualDom.Node msg
2355+toStyleSheet options styleSheet =
2356+ case options.mode of
2357+ Layout ->
2358+ -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
2359+ VirtualDom.node "div"
2360+ []
2361+ [ VirtualDom.node "style"
2362+ []
2363+ [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2364+ ]
2365+
2366+ NoStaticStyleSheet ->
2367+ -- wrap the style node in a div to prevent `Dark Reader` from blowin up the dom.
2368+ VirtualDom.node "div"
2369+ []
2370+ [ VirtualDom.node "style"
2371+ []
2372+ [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2373+ ]
2374+
2375+ WithVirtualCss ->
2376+ VirtualDom.node "elm-ui-rules"
2377+ [ VirtualDom.property "rules"
2378+ (encodeStyles options styleSheet)
2379+ ]
2380+ []
2381+
2382+
2383+renderTopLevelValues rules =
20302384 let
2031− fontName font =
2385+ withImport font =
20322386 case font of
2033− Serif ->
2034− "serif"
2387+ ImportFont _ url ->
2388+ Just ("@import url('" ++ url ++ "');")
2389+
2390+ -- FontWith with ->
2391+ -- case with.url of
2392+ -- Just x ->
2393+ -- Just ("@import url('" ++ x ++ "');")
2394+ -- Nothing ->
2395+ -- Nothing
2396+ _ ->
2397+ Nothing
20352398
2036− SansSerif ->
2037− "sans-serif"
2399+ allNames =
2400+ List.map Tuple.first rules
20382401
2039− Monospace ->
2040− "monospace"
2402+ fontImports ( name, typefaces ) =
2403+ let
2404+ imports =
2405+ String.join "\n" (List.filterMap withImport typefaces)
2406+ in
2407+ imports
20412408
2042− Typeface name ->
2043− "\"" ++ name ++ "\""
2409+ fontAdjustments ( name, typefaces ) =
2410+ case typefaceAdjustment typefaces of
2411+ Nothing ->
2412+ String.join ""
2413+ (List.map (renderNullAdjustmentRule name) allNames)
20442414
2045− ImportFont name url ->
2046− "\"" ++ name ++ "\""
2415+ Just adjustment ->
2416+ String.join ""
2417+ (List.map (renderFontAdjustmentRule name adjustment) allNames)
20472418 in
2048− families
2049− |> List.map fontName
2050− |> String.join ", "
2419+ String.join "\n" (List.map fontImports rules)
2420+ ++ String.join "\n" (List.map fontAdjustments rules)
20512421
20522422
2053−toStyleSheet : OptionRecord -> List Style -> VirtualDom.Node msg
2054−toStyleSheet options styleSheet =
2055− VirtualDom.node "style" [] [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2423+renderNullAdjustmentRule fontToAdjust otherFontName =
2424+ let
2425+ name =
2426+ if fontToAdjust == otherFontName then
2427+ fontToAdjust
20562428
2429+ else
2430+ otherFontName ++ " ." ++ fontToAdjust
2431+ in
2432+ String.join " "
2433+ [ bracket
2434+ ("."
2435+ ++ name
2436+ ++ "."
2437+ ++ classes.sizeByCapital
2438+ ++ ", "
2439+ ++ "."
2440+ ++ name
2441+ ++ " ."
2442+ ++ classes.sizeByCapital
2443+ )
2444+ [ ( "line-height", "1" )
2445+ ]
2446+ , bracket
2447+ ("."
2448+ ++ name
2449+ ++ "."
2450+ ++ classes.sizeByCapital
2451+ ++ "> ."
2452+ ++ Internal.Style.classes.text
2453+ ++ ", ."
2454+ ++ name
2455+ ++ " ."
2456+ ++ classes.sizeByCapital
2457+ ++ " > ."
2458+ ++ Internal.Style.classes.text
2459+ )
2460+ [ ( "vertical-align", "0" )
2461+ , ( "line-height", "1" )
2462+ ]
2463+ ]
20572464
2058−toStyleSheetString : OptionRecord -> List Style -> String
2059−toStyleSheetString options stylesheet =
2060− let
2061− renderTopLevels rule =
2062− case rule of
2063− FontFamily name typefaces ->
2064− let
2065− getImports font =
2066− case font of
2067− ImportFont _ url ->
2068− Just ("@import url('" ++ url ++ "');")
20692465
2070− _ ->
2071− Nothing
2072− in
2073− typefaces
2074− |> List.filterMap getImports
2075− |> String.join "\n"
2076− |> Just
2466+fontRule name modifier ( parentAdj, textAdjustment ) =
2467+ [ bracket
2468+ ("."
2469+ ++ name
2470+ ++ "."
2471+ ++ modifier
2472+ ++ ", "
2473+ ++ "."
2474+ ++ name
2475+ ++ " ."
2476+ ++ modifier
2477+ )
2478+ parentAdj
2479+ , bracket
2480+ ("."
2481+ ++ name
2482+ ++ "."
2483+ ++ modifier
2484+ ++ "> ."
2485+ ++ Internal.Style.classes.text
2486+ ++ ", ."
2487+ ++ name
2488+ ++ " ."
2489+ ++ modifier
2490+ ++ " > ."
2491+ ++ Internal.Style.classes.text
2492+ )
2493+ textAdjustment
2494+ ]
20772495
2078− _ ->
2079− Nothing
20802496
2081− renderProps force (Property key val) existing =
2082− if force then
2083− existing ++ "\n " ++ key ++ ": " ++ val ++ " !important;"
2497+renderFontAdjustmentRule fontToAdjust ( full, capital ) otherFontName =
2498+ let
2499+ name =
2500+ if fontToAdjust == otherFontName then
2501+ fontToAdjust
20842502
20852503 else
2086− existing ++ "\n " ++ key ++ ": " ++ val ++ ";"
2504+ otherFontName ++ " ." ++ fontToAdjust
2505+ in
2506+ String.join " "
2507+ (fontRule name classes.sizeByCapital capital ++ fontRule name classes.fullSize full)
2508+
2509+
2510+bracket selector rules =
2511+ let
2512+ renderPair ( name, val ) =
2513+ name ++ ": " ++ val ++ ";"
2514+ in
2515+ selector ++ " {" ++ String.join "" (List.map renderPair rules) ++ "}"
2516+
20872517
2088− renderStyle maybePseudo selector props =
2089− case maybePseudo of
2518+fontAdjustmentRules converted =
2519+ ( [ ( "display", "block" )
2520+ ]
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" )
2525+ ]
2526+ )
2527+
2528+
2529+typefaceAdjustment typefaces =
2530+ List.foldl
2531+ (\face found ->
2532+ case found of
20902533 Nothing ->
2091− selector ++ "{" ++ List.foldl (renderProps False) "" props ++ "\n}"
2534+ case face of
2535+ FontWith with ->
2536+ case with.adjustment of
2537+ Nothing ->
2538+ found
2539+
2540+ Just adjustment ->
2541+ Just
2542+ ( fontAdjustmentRules
2543+ (.full (convertAdjustment adjustment))
2544+ , fontAdjustmentRules
2545+ (.capital (convertAdjustment adjustment))
2546+ )
20922547
2093− Just pseudo ->
2094− case pseudo of
2095− Hover ->
2096− case options.hover of
2097− NoHover ->
2098− ""
2548+ _ ->
2549+ found
2550+
2551+ Just _ ->
2552+ found
2553+ )
2554+ Nothing
2555+ typefaces
20992556
2100− ForceHover ->
2101− selector ++ "-hv {" ++ List.foldl (renderProps True) "" props ++ "\n}"
21022557
2103− AllowHover ->
2104− selector ++ "-hv:hover {" ++ List.foldl (renderProps False) "" props ++ "\n}"
2558+fontName font =
2559+ case font of
2560+ Serif ->
2561+ "serif"
21052562
2106− Focus ->
2107− let
2108− renderedProps =
2109− List.foldl (renderProps False) "" props
2110− in
2111− String.join "\n"
2112− [ selector
2113− ++ "-fs:focus {"
2114− ++ renderedProps
2115− ++ "\n}"
2116− , "."
2117− ++ classes.any
2118− ++ ":focus ~ "
2119− ++ selector
2120− ++ "-fs:not(.focus) {"
2121− ++ renderedProps
2122− ++ "\n}"
2123− , "."
2124− ++ classes.any
2125− ++ ":focus "
2126− ++ selector
2127− ++ "-fs {"
2128− ++ renderedProps
2129− ++ "\n}"
2130− , ".focusable-parent:focus ~ "
2131− ++ "."
2132− ++ classes.any
2133− ++ " "
2134− ++ selector
2135− ++ "-fs {"
2136− ++ renderedProps
2137− ++ "\n}"
2138− ]
2563+ SansSerif ->
2564+ "sans-serif"
21392565
2140− Active ->
2141− selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}"
2566+ Monospace ->
2567+ "monospace"
21422568
2143− renderStyleRule rule maybePseudo =
2144− case rule of
2145− Style selector props ->
2146− renderStyle maybePseudo selector props
2569+ Typeface name ->
2570+ "\"" ++ name ++ "\""
2571+
2572+ ImportFont name url ->
2573+ "\"" ++ name ++ "\""
2574+
2575+ FontWith { name } ->
2576+ "\"" ++ name ++ "\""
2577+
2578+
2579+topLevelValue rule =
2580+ case rule of
2581+ FontFamily name typefaces ->
2582+ Just ( name, typefaces )
2583+
2584+ _ ->
2585+ Nothing
21472586
2148− Shadows name prop ->
2149− renderStyle
2150− maybePseudo
2151− ("." ++ name)
2152− [ Property "box-shadow" prop
2153− ]
21542587
2155− Transparency name transparency ->
2588+renderProps force (Property key val) existing =
2589+ if force then
2590+ existing ++ "\n " ++ key ++ ": " ++ val ++ " !important;"
2591+
2592+ else
2593+ existing ++ "\n " ++ key ++ ": " ++ val ++ ";"
2594+
2595+
2596+encodeStyles options stylesheet =
2597+ stylesheet
2598+ |> List.map
2599+ (\style ->
2600+ let
2601+ styled =
2602+ renderStyleRule options style Nothing
2603+ in
2604+ ( getStyleName style, Encode.list Encode.string styled )
2605+ )
2606+ |> Encode.object
2607+
2608+
2609+toStyleSheetString : OptionRecord -> List Style -> String
2610+toStyleSheetString options stylesheet =
2611+ let
2612+ combine style rendered =
2613+ { rules = rendered.rules ++ renderStyleRule options style Nothing
2614+ , topLevel =
2615+ case topLevelValue style of
2616+ Nothing ->
2617+ rendered.topLevel
2618+
2619+ Just topLevel ->
2620+ topLevel :: rendered.topLevel
2621+ }
2622+ in
2623+ case List.foldl combine { topLevel = [], rules = [] } stylesheet of
2624+ { topLevel, rules } ->
2625+ renderTopLevelValues topLevel ++ String.concat rules
2626+
2627+
2628+renderStyle : OptionRecord -> Maybe PseudoClass -> String -> List Property -> List String
2629+renderStyle options maybePseudo selector props =
2630+ case maybePseudo of
2631+ Nothing ->
2632+ [ selector ++ "{" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
2633+
2634+ Just pseudo ->
2635+ case pseudo of
2636+ Hover ->
2637+ case options.hover of
2638+ NoHover ->
2639+ []
2640+
2641+ ForceHover ->
2642+ [ selector ++ "-hv {" ++ List.foldl (renderProps True) "" props ++ "\n}" ]
2643+
2644+ AllowHover ->
2645+ [ selector ++ "-hv:hover {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
2646+
2647+ Focus ->
21562648 let
2157− opacity =
2158− (1 - transparency)
2159− |> min 1
2160− |> max 0
2649+ renderedProps =
2650+ List.foldl (renderProps False) "" props
21612651 in
2162− renderStyle
2163− maybePseudo
2164− ("." ++ name)
2165− [ Property "opacity" (String.fromFloat opacity)
2166− ]
2652+ [ selector ++ "-fs:focus {" ++ renderedProps ++ "\n}"
2653+ , ("." ++ classes.any ++ ":focus " ++ selector ++ "-fs {")
2654+ ++ renderedProps
2655+ ++ "\n}"
2656+ , (selector ++ "-fs:focus-within {")
2657+ ++ renderedProps
2658+ ++ "\n}"
2659+ , (".ui-slide-bar:focus + " ++ Internal.Style.dot classes.any ++ " .focusable-thumb" ++ selector ++ "-fs {")
2660+ ++ renderedProps
2661+ ++ "\n}"
2662+ ]
21672663
2168− FontSize i ->
2169− renderStyle
2170− maybePseudo
2171− (".font-size-" ++ String.fromInt i)
2172− [ Property "font-size" (String.fromInt i ++ "px")
2173− ]
2664+ Active ->
2665+ [ selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
21742666
2175− FontFamily name typefaces ->
2176− renderStyle
2177− maybePseudo
2178− ("." ++ name)
2179− [ Property "font-family" (renderFont typefaces)
2180− ]
21812667
2182− Single class prop val ->
2183− renderStyle
2184− maybePseudo
2185− ("." ++ class)
2186− [ Property prop val
2187− ]
2668+renderStyleRule : OptionRecord -> Style -> Maybe PseudoClass -> List String
2669+renderStyleRule options rule maybePseudo =
2670+ case rule of
2671+ Style selector props ->
2672+ renderStyle options maybePseudo selector props
21882673
2189− Colored class prop color ->
2190− renderStyle
2191− maybePseudo
2192− ("." ++ class)
2193− [ Property prop (formatColor color)
2194− ]
2674+ Shadows name prop ->
2675+ renderStyle options
2676+ maybePseudo
2677+ ("." ++ name)
2678+ [ Property "box-shadow" prop
2679+ ]
21952680
2196− SpacingStyle cls x y ->
2197− let
2198− class =
2199− "." ++ cls
2681+ Transparency name transparency ->
2682+ let
2683+ opacity =
2684+ (1 - transparency)
2685+ |> min 1
2686+ |> max 0
2687+ in
2688+ renderStyle options
2689+ maybePseudo
2690+ ("." ++ name)
2691+ [ Property "opacity" (String.fromFloat opacity)
2692+ ]
22002693
2201− xPx =
2202− String.fromInt x ++ "px"
2694+ FontSize i ->
2695+ renderStyle options
2696+ maybePseudo
2697+ (".font-size-" ++ String.fromInt i)
2698+ [ Property "font-size" (String.fromInt i ++ "px")
2699+ ]
22032700
2204− yPx =
2205− String.fromInt y ++ "px"
2701+ FontFamily name typefaces ->
2702+ let
2703+ features =
2704+ typefaces
2705+ |> List.filterMap renderVariants
2706+ |> String.join ", "
2707+
2708+ families =
2709+ [ Property "font-family"
2710+ (typefaces
2711+ |> List.map fontName
2712+ |> String.join ", "
2713+ )
2714+ , Property "font-feature-settings" features
2715+ , Property "font-variant"
2716+ (if List.any hasSmallCaps typefaces then
2717+ "small-caps"
22062718
2207− row =
2208− "." ++ Internal.Style.classes.row
2719+ else
2720+ "normal"
2721+ )
2722+ ]
2723+ in
2724+ renderStyle options
2725+ maybePseudo
2726+ ("." ++ name)
2727+ families
22092728
2210− wrappedRow =
2211− "." ++ Internal.Style.classes.wrapped ++ row
2729+ Single class prop val ->
2730+ renderStyle options
2731+ maybePseudo
2732+ ("." ++ class)
2733+ [ Property prop val
2734+ ]
22122735
2213− column =
2214− "." ++ Internal.Style.classes.column
2736+ Colored class prop color ->
2737+ renderStyle options
2738+ maybePseudo
2739+ ("." ++ class)
2740+ [ Property prop (formatColor color)
2741+ ]
22152742
2216− page =
2217− "." ++ Internal.Style.classes.page
2743+ SpacingStyle cls x y ->
2744+ let
2745+ class =
2746+ "." ++ cls
22182747
2219− paragraph =
2220− "." ++ Internal.Style.classes.paragraph
2748+ halfX =
2749+ String.fromFloat (toFloat x / 2) ++ "px"
22212750
2222− left =
2223− "." ++ Internal.Style.classes.alignLeft
2751+ halfY =
2752+ String.fromFloat (toFloat y / 2) ++ "px"
22242753
2225− right =
2226− "." ++ Internal.Style.classes.alignRight
2754+ xPx =
2755+ String.fromInt x ++ "px"
22272756
2228− any =
2229− "." ++ Internal.Style.classes.any
2757+ yPx =
2758+ String.fromInt y ++ "px"
22302759
2231− single =
2232− "." ++ Internal.Style.classes.single
2233− in
2234− String.concat
2235− [ renderStyle maybePseudo (class ++ row ++ " > " ++ any) [ Property "margin-right" xPx ]
2760+ row =
2761+ "." ++ Internal.Style.classes.row
22362762
2237− -- margins don't apply to last element of normal, unwrapped rows
2238− , renderStyle maybePseudo (class ++ row ++ " > " ++ any ++ ":last-child") [ Property "margin" "0" ]
2763+ wrappedRow =
2764+ "." ++ Internal.Style.classes.wrapped ++ row
22392765
2240− -- For wrapped rows, margins always apply because we handle "canceling out" the other margins manually in the element.
2241− , renderStyle maybePseudo
2242− (class ++ wrappedRow ++ " > " ++ any)
2243− [ Property "margin" ("0 " ++ xPx ++ " " ++ yPx ++ " 0")
2244− ]
2245− , renderStyle maybePseudo
2246− (class ++ wrappedRow ++ " > " ++ any ++ ":last-child")
2247− [ Property "margin-right" "0"
2248− ]
2766+ column =
2767+ "." ++ Internal.Style.classes.column
22492768
2250− -- columns
2251− , renderStyle maybePseudo (class ++ column ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2252− , renderStyle maybePseudo (class ++ page ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2253− , renderStyle maybePseudo (class ++ page ++ " > " ++ left) [ Property "margin-right" xPx ]
2254− , renderStyle maybePseudo (class ++ page ++ " > " ++ right) [ Property "margin-left" xPx ]
2255− , renderStyle
2256− maybePseudo
2257− (class ++ paragraph)
2258− [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2259− ]
2260− , renderStyle
2261− maybePseudo
2262− ("textarea" ++ class)
2263− [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2264− ]
2769+ page =
2770+ "." ++ Internal.Style.classes.page
22652771
2266− -- , renderStyle
2267− -- maybePseudo
2268− -- (class ++ paragraph ++ " > " ++ any)
2269− -- [ Property "margin-right" xPx
2270− -- , Property "margin-bottom" yPx
2271− -- ]
2272− , renderStyle
2273− maybePseudo
2274− (class ++ paragraph ++ " > " ++ left)
2275− [ Property "margin-right" xPx
2276− ]
2277− , renderStyle
2278− maybePseudo
2279− (class ++ paragraph ++ " > " ++ right)
2280− [ Property "margin-left" xPx
2281− ]
2282− , renderStyle
2283− maybePseudo
2284− (class ++ paragraph ++ "::after")
2285− [ Property "content" "''"
2286− , Property "display" "block"
2287− , Property "height" "0"
2288− , Property "width" "0"
2289− , Property "margin-top" (String.fromInt (-1 * (y // 2)) ++ "px")
2290− ]
2291− , renderStyle
2292− maybePseudo
2293− (class ++ paragraph ++ "::before")
2294− [ Property "content" "''"
2295− , Property "display" "block"
2296− , Property "height" "0"
2297− , Property "width" "0"
2298− , Property "margin-bottom" (String.fromInt (-1 * (y // 2)) ++ "px")
2299− ]
2300− ]
2772+ paragraph =
2773+ "." ++ Internal.Style.classes.paragraph
23012774
2302− PaddingStyle cls top right bottom left ->
2303− let
2304− class =
2305− "."
2306− ++ cls
2307− in
2308− renderStyle
2309− maybePseudo
2310− class
2311− [ Property "padding"
2312− (String.fromInt top
2313− ++ "px "
2314− ++ String.fromInt right
2315− ++ "px "
2316− ++ String.fromInt bottom
2317− ++ "px "
2318− ++ String.fromInt left
2319− ++ "px"
2320− )
2321− ]
2775+ left =
2776+ "." ++ Internal.Style.classes.alignLeft
23222777
2323− GridTemplateStyle template ->
2324− let
2325− class =
2326− ".grid-rows-"
2327− ++ String.join "-" (List.map lengthClassName template.rows)
2328− ++ "-cols-"
2329− ++ String.join "-" (List.map lengthClassName template.columns)
2330− ++ "-space-x-"
2331− ++ lengthClassName (Tuple.first template.spacing)
2332− ++ "-space-y-"
2333− ++ lengthClassName (Tuple.second template.spacing)
2334−
2335− ySpacing =
2336− toGridLength (Tuple.second template.spacing)
2337−
2338− xSpacing =
2339− toGridLength (Tuple.first template.spacing)
2340−
2341− toGridLength x =
2342− toGridLengthHelper Nothing Nothing x
2343−
2344− toGridLengthHelper minimum maximum x =
2345− case x of
2346− Px px ->
2347− String.fromInt px ++ "px"
2348−
2349− Content ->
2350− case ( minimum, maximum ) of
2351− ( Nothing, Nothing ) ->
2352− "max-content"
2353−
2354− ( Just minSize, Nothing ) ->
2355− "minmax(" ++ String.fromInt minSize ++ "px, " ++ "max-content)"
2356−
2357− ( Nothing, Just maxSize ) ->
2358− "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2359−
2360− ( Just minSize, Just maxSize ) ->
2361− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2362−
2363− Fill i ->
2364− case ( minimum, maximum ) of
2365− ( Nothing, Nothing ) ->
2366− String.fromInt i ++ "fr"
2367−
2368− ( Just minSize, Nothing ) ->
2369− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt i ++ "fr" ++ "fr)"
2370−
2371− ( Nothing, Just maxSize ) ->
2372− "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2373−
2374− ( Just minSize, Just maxSize ) ->
2375− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2376−
2377− Min m len ->
2378− toGridLengthHelper (Just m) maximum len
2379−
2380− Max m len ->
2381− toGridLengthHelper minimum (Just m) len
2382−
2383− msColumns =
2384− template.columns
2385− |> List.map toGridLength
2386− |> String.join ySpacing
2387− |> (\x -> "-ms-grid-columns: " ++ x ++ ";")
2388−
2389− msRows =
2390− template.columns
2391− |> List.map toGridLength
2392− |> String.join ySpacing
2393− |> (\x -> "-ms-grid-rows: " ++ x ++ ";")
2394−
2395− base =
2396− class ++ "{" ++ msColumns ++ msRows ++ "}"
2397−
2398− columns =
2399− template.columns
2400− |> List.map toGridLength
2401− |> String.join " "
2402− |> (\x -> "grid-template-columns: " ++ x ++ ";")
2403−
2404− rows =
2405− template.rows
2406− |> List.map toGridLength
2407− |> String.join " "
2408− |> (\x -> "grid-template-rows: " ++ x ++ ";")
2409−
2410− gapX =
2411− "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
2412−
2413− gapY =
2414− "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
2415−
2416− modernGrid =
2417− class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
2418−
2419− supports =
2420− "@supports (display:grid) {" ++ modernGrid ++ "}"
2421− in
2422− base ++ supports
2778+ right =
2779+ "." ++ Internal.Style.classes.alignRight
24232780
2424− GridPosition position ->
2425− let
2426− class =
2427− ".grid-pos-"
2428− ++ String.fromInt position.row
2429− ++ "-"
2430− ++ String.fromInt position.col
2431− ++ "-"
2432− ++ String.fromInt position.width
2433− ++ "-"
2434− ++ String.fromInt position.height
2435−
2436− msPosition =
2437− String.join " "
2438− [ "-ms-grid-row: "
2439− ++ String.fromInt position.row
2440− ++ ";"
2441− , "-ms-grid-row-span: "
2442− ++ String.fromInt position.height
2443− ++ ";"
2444− , "-ms-grid-column: "
2445− ++ String.fromInt position.col
2446− ++ ";"
2447− , "-ms-grid-column-span: "
2448− ++ String.fromInt position.width
2449− ++ ";"
2450− ]
2451−
2452− base =
2453− class ++ "{" ++ msPosition ++ "}"
2454−
2455− modernPosition =
2456− String.join " "
2457− [ "grid-row: "
2458− ++ String.fromInt position.row
2459− ++ " / "
2460− ++ String.fromInt (position.row + position.height)
2461− ++ ";"
2462− , "grid-column: "
2463− ++ String.fromInt position.col
2464− ++ " / "
2465− ++ String.fromInt (position.col + position.width)
2466− ++ ";"
2467− ]
2468−
2469− modernGrid =
2470− class ++ "{" ++ modernPosition ++ "}"
2471−
2472− supports =
2473− "@supports (display:grid) {" ++ modernGrid ++ "}"
2474− in
2475− base ++ supports
2781+ any =
2782+ "." ++ Internal.Style.classes.any
24762783
2477− PseudoSelector class styles ->
2478− let
2479− renderPseudoRule style =
2480− renderStyleRule style (Just class)
2481− in
2482− List.map renderPseudoRule styles
2784+ single =
2785+ "." ++ Internal.Style.classes.single
2786+ in
2787+ List.concat
2788+ [ renderStyle options maybePseudo (class ++ row ++ " > " ++ any ++ " + " ++ any) [ Property "margin-left" xPx ]
2789+
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
2794+ maybePseudo
2795+ (class ++ wrappedRow ++ " > " ++ any)
2796+ [ Property "margin" (halfY ++ " " ++ halfX)
2797+ ]
2798+
2799+ -- , renderStyle options maybePseudo
2800+ -- (class ++ wrappedRow ++ " > " ++ any ++ ":last-child")
2801+ -- [ Property "margin-right" "0"
2802+ -- ]
2803+ -- columns
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
2809+ maybePseudo
2810+ (class ++ paragraph)
2811+ [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2812+ ]
2813+ , renderStyle options
2814+ maybePseudo
2815+ ("textarea" ++ any ++ class)
2816+ [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2817+ , Property "height" ("calc(100% + " ++ String.fromInt y ++ "px)")
2818+ ]
2819+
2820+ -- , renderStyle options
2821+ -- maybePseudo
2822+ -- (class ++ paragraph ++ " > " ++ any)
2823+ -- [ Property "margin-right" xPx
2824+ -- , Property "margin-bottom" yPx
2825+ -- ]
2826+ , renderStyle options
2827+ maybePseudo
2828+ (class ++ paragraph ++ " > " ++ left)
2829+ [ Property "margin-right" xPx
2830+ ]
2831+ , renderStyle options
2832+ maybePseudo
2833+ (class ++ paragraph ++ " > " ++ right)
2834+ [ Property "margin-left" xPx
2835+ ]
2836+ , renderStyle options
2837+ maybePseudo
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")
2844+ ]
2845+ , renderStyle options
2846+ maybePseudo
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")
2853+ ]
2854+ ]
2855+
2856+ PaddingStyle cls top right bottom left ->
2857+ let
2858+ class =
2859+ "."
2860+ ++ cls
2861+ in
2862+ renderStyle options
2863+ maybePseudo
2864+ class
2865+ [ Property "padding"
2866+ (String.fromFloat top
2867+ ++ "px "
2868+ ++ String.fromFloat right
2869+ ++ "px "
2870+ ++ String.fromFloat bottom
2871+ ++ "px "
2872+ ++ String.fromFloat left
2873+ ++ "px"
2874+ )
2875+ ]
2876+
2877+ BorderWidth cls top right bottom left ->
2878+ let
2879+ class =
2880+ "."
2881+ ++ cls
2882+ in
2883+ renderStyle options
2884+ maybePseudo
2885+ class
2886+ [ Property "border-width"
2887+ (String.fromInt top
2888+ ++ "px "
2889+ ++ String.fromInt right
2890+ ++ "px "
2891+ ++ String.fromInt bottom
2892+ ++ "px "
2893+ ++ String.fromInt left
2894+ ++ "px"
2895+ )
2896+ ]
2897+
2898+ GridTemplateStyle template ->
2899+ let
2900+ class =
2901+ ".grid-rows-"
2902+ ++ String.join "-" (List.map lengthClassName template.rows)
2903+ ++ "-cols-"
2904+ ++ String.join "-" (List.map lengthClassName template.columns)
2905+ ++ "-space-x-"
2906+ ++ lengthClassName (Tuple.first template.spacing)
2907+ ++ "-space-y-"
2908+ ++ lengthClassName (Tuple.second template.spacing)
2909+
2910+ ySpacing =
2911+ toGridLength (Tuple.second template.spacing)
2912+
2913+ xSpacing =
2914+ toGridLength (Tuple.first template.spacing)
2915+
2916+ toGridLength x =
2917+ toGridLengthHelper Nothing Nothing x
2918+
2919+ toGridLengthHelper minimum maximum x =
2920+ case x of
2921+ Px px ->
2922+ String.fromInt px ++ "px"
2923+
2924+ Content ->
2925+ case ( minimum, maximum ) of
2926+ ( Nothing, Nothing ) ->
2927+ "max-content"
2928+
2929+ ( Just minSize, Nothing ) ->
2930+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ "max-content)"
2931+
2932+ ( Nothing, Just maxSize ) ->
2933+ "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2934+
2935+ ( Just minSize, Just maxSize ) ->
2936+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2937+
2938+ Fill i ->
2939+ case ( minimum, maximum ) of
2940+ ( Nothing, Nothing ) ->
2941+ String.fromInt i ++ "fr"
2942+
2943+ ( Just minSize, Nothing ) ->
2944+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt i ++ "fr" ++ "fr)"
2945+
2946+ ( Nothing, Just maxSize ) ->
2947+ "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2948+
2949+ ( Just minSize, Just maxSize ) ->
2950+ "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2951+
2952+ Min m len ->
2953+ toGridLengthHelper (Just m) maximum len
2954+
2955+ Max m len ->
2956+ toGridLengthHelper minimum (Just m) len
2957+
2958+ msColumns =
2959+ template.columns
2960+ |> List.map toGridLength
2961+ |> String.join ySpacing
2962+ |> (\x -> "-ms-grid-columns: " ++ x ++ ";")
2963+
2964+ msRows =
2965+ template.columns
2966+ |> List.map toGridLength
2967+ |> String.join ySpacing
2968+ |> (\x -> "-ms-grid-rows: " ++ x ++ ";")
2969+
2970+ base =
2971+ class ++ "{" ++ msColumns ++ msRows ++ "}"
2972+
2973+ columns =
2974+ template.columns
2975+ |> List.map toGridLength
24832976 |> String.join " "
2977+ |> (\x -> "grid-template-columns: " ++ x ++ ";")
24842978
2485− Transform transform ->
2486− let
2487− val =
2488− transformValue transform
2979+ rows =
2980+ template.rows
2981+ |> List.map toGridLength
2982+ |> String.join " "
2983+ |> (\x -> "grid-template-rows: " ++ x ++ ";")
24892984
2490− class =
2491− transformClass transform
2492− in
2493− case ( class, val ) of
2494− ( Just cls, Just v ) ->
2495− renderStyle
2496− maybePseudo
2497− ("." ++ cls)
2498− [ Property "transform"
2499− v
2500− ]
2985+ gapX =
2986+ "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
25012987
2502− _ ->
2503− ""
2988+ gapY =
2989+ "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
25042990
2505− combine style rendered =
2506− { rendered
2507− | rules = rendered.rules ++ renderStyleRule style Nothing
2508− , topLevel =
2509− case renderTopLevels style of
2510− Nothing ->
2511− rendered.topLevel
2991+ modernGrid =
2992+ class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
25122993
2513− Just topLevel ->
2514− rendered.topLevel ++ topLevel
2515− }
2516− in
2517− case List.foldl combine { rules = "", topLevel = "" } stylesheet of
2518− { topLevel, rules } ->
2519− topLevel ++ rules
2994+ supports =
2995+ "@supports (display:grid) {" ++ modernGrid ++ "}"
2996+ in
2997+ [ base
2998+ , supports
2999+ ]
3000+
3001+ GridPosition position ->
3002+ let
3003+ class =
3004+ ".grid-pos-"
3005+ ++ String.fromInt position.row
3006+ ++ "-"
3007+ ++ String.fromInt position.col
3008+ ++ "-"
3009+ ++ String.fromInt position.width
3010+ ++ "-"
3011+ ++ String.fromInt position.height
3012+
3013+ msPosition =
3014+ String.join " "
3015+ [ "-ms-grid-row: "
3016+ ++ String.fromInt position.row
3017+ ++ ";"
3018+ , "-ms-grid-row-span: "
3019+ ++ String.fromInt position.height
3020+ ++ ";"
3021+ , "-ms-grid-column: "
3022+ ++ String.fromInt position.col
3023+ ++ ";"
3024+ , "-ms-grid-column-span: "
3025+ ++ String.fromInt position.width
3026+ ++ ";"
3027+ ]
3028+
3029+ base =
3030+ class ++ "{" ++ msPosition ++ "}"
3031+
3032+ modernPosition =
3033+ String.join " "
3034+ [ "grid-row: "
3035+ ++ String.fromInt position.row
3036+ ++ " / "
3037+ ++ String.fromInt (position.row + position.height)
3038+ ++ ";"
3039+ , "grid-column: "
3040+ ++ String.fromInt position.col
3041+ ++ " / "
3042+ ++ String.fromInt (position.col + position.width)
3043+ ++ ";"
3044+ ]
3045+
3046+ modernGrid =
3047+ class ++ "{" ++ modernPosition ++ "}"
3048+
3049+ supports =
3050+ "@supports (display:grid) {" ++ modernGrid ++ "}"
3051+ in
3052+ [ base
3053+ , supports
3054+ ]
3055+
3056+ PseudoSelector class styles ->
3057+ let
3058+ renderPseudoRule style =
3059+ renderStyleRule options style (Just class)
3060+ in
3061+ List.concatMap renderPseudoRule styles
3062+
3063+ Transform transform ->
3064+ let
3065+ val =
3066+ transformValue transform
3067+
3068+ class =
3069+ transformClass transform
3070+ in
3071+ case ( class, val ) of
3072+ ( Just cls, Just v ) ->
3073+ renderStyle options
3074+ maybePseudo
3075+ ("." ++ cls)
3076+ [ Property "transform"
3077+ v
3078+ ]
3079+
3080+ _ ->
3081+ []
25203082
25213083
25223084lengthClassName : Length -> String
@@ -2556,12 +3118,12 @@ formatTextShadow shadow =
25563118 ]
25573119
25583120
2559−textShadowName shadow =
3121+textShadowClass shadow =
25603122 String.concat
25613123 [ "txt"
2562− , String.fromFloat (Tuple.first shadow.offset) ++ "px"
2563− , String.fromFloat (Tuple.second shadow.offset) ++ "px"
2564− , String.fromFloat shadow.blur ++ "px"
3124+ , floatClass (Tuple.first shadow.offset) ++ "px"
3125+ , floatClass (Tuple.second shadow.offset) ++ "px"
3126+ , floatClass shadow.blur ++ "px"
25653127 , formatColorClass shadow.color
25663128 ]
25673129
@@ -2582,17 +3144,17 @@ formatBoxShadow shadow =
25823144 ]
25833145
25843146
2585−boxShadowName shadow =
3147+boxShadowClass shadow =
25863148 String.concat <|
25873149 [ if shadow.inset then
25883150 "box-inset"
25893151
25903152 else
25913153 "box-"
2592− , String.fromFloat (Tuple.first shadow.offset) ++ "px"
2593− , String.fromFloat (Tuple.second shadow.offset) ++ "px"
2594− , String.fromFloat shadow.blur ++ "px"
2595− , String.fromFloat shadow.size ++ "px"
3154+ , floatClass (Tuple.first shadow.offset) ++ "px"
3155+ , floatClass (Tuple.second shadow.offset) ++ "px"
3156+ , floatClass shadow.blur ++ "px"
3157+ , floatClass shadow.size ++ "px"
25963158 , formatColorClass shadow.color
25973159 ]
25983160
@@ -2637,6 +3199,17 @@ paddingName top right bottom left =
26373199 ++ String.fromInt left
26383200
26393201
3202+paddingNameFloat top right bottom left =
3203+ "pad-"
3204+ ++ floatClass top
3205+ ++ "-"
3206+ ++ floatClass right
3207+ ++ "-"
3208+ ++ floatClass bottom
3209+ ++ "-"
3210+ ++ floatClass left
3211+
3212+
26403213getStyleName : Style -> String
26413214getStyleName style =
26423215 case style of
@@ -2667,6 +3240,9 @@ getStyleName style =
26673240 PaddingStyle cls top right bottom left ->
26683241 cls
26693242
3243+ BorderWidth cls top right bottom left ->
3244+ cls
3245+
26703246 GridTemplateStyle template ->
26713247 "grid-rows-"
26723248 ++ String.join "-" (List.map lengthClassName template.rows)
@@ -2899,3 +3475,76 @@ onlyStyles attr =
28993475
29003476 _ ->
29013477 Nothing
3478+
3479+
3480+
3481+{- Font Adjustments -}
3482+
3483+
3484+convertAdjustment adjustment =
3485+ let
3486+ lineHeight =
3487+ 1.5
3488+
3489+ base =
3490+ lineHeight
3491+
3492+ normalDescender =
3493+ (lineHeight - 1)
3494+ / 2
3495+
3496+ oldMiddle =
3497+ lineHeight / 2
3498+
3499+ newCapitalMiddle =
3500+ ((ascender - newBaseline) / 2) + newBaseline
3501+
3502+ newFullMiddle =
3503+ ((ascender - descender) / 2) + descender
3504+
3505+ lines =
3506+ [ adjustment.capital
3507+ , adjustment.baseline
3508+ , adjustment.descender
3509+ , adjustment.lowercase
3510+ ]
3511+
3512+ ascender =
3513+ Maybe.withDefault adjustment.capital (List.maximum lines)
3514+
3515+ descender =
3516+ Maybe.withDefault adjustment.descender (List.minimum lines)
3517+
3518+ newBaseline =
3519+ lines
3520+ |> List.filter (\x -> x /= descender)
3521+ |> List.minimum
3522+ |> Maybe.withDefault adjustment.baseline
3523+
3524+ capitalVertical =
3525+ 1 - ascender
3526+
3527+ capitalSize =
3528+ 1 / (ascender - newBaseline)
3529+
3530+ fullSize =
3531+ 1 / (ascender - descender)
3532+
3533+ fullVertical =
3534+ 1 - ascender
3535+
3536+ -- (oldMiddle - newFullMiddle) * 2
3537+ in
3538+ { full =
3539+ adjust fullSize (ascender - descender) fullVertical
3540+ , capital =
3541+ adjust capitalSize (ascender - newBaseline) capitalVertical
3542+ }
3543+
3544+
3545+adjust size height vertical =
3546+ { vertical = vertical
3547+ , height =
3548+ height / size
3549+ , size = size
3550+ }