@@ -1,4 +1,109 @@
1−module Internal.Model exposing (..)
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,13 +455,17 @@ 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
275465 AsRow ->
276466 if Flag.present Flag.widthFill has && not (Flag.present Flag.widthBetween has) then
277467 html
468+
278469 else if Flag.present Flag.alignRight has then
279470 Html.u
280471 [ Html.Attributes.class
@@ -288,6 +479,7 @@ finalizeNode has node attributes children embedMode parentContext =
288479 )
289480 ]
290481 [ html ]
482+
291483 else if Flag.present Flag.centerX has then
292484 Html.s
293485 [ Html.Attributes.class
@@ -301,12 +493,14 @@ finalizeNode has node attributes children embedMode parentContext =
301493 )
302494 ]
303495 [ html ]
496+
304497 else
305498 html
306499
307500 AsColumn ->
308501 if Flag.present Flag.heightFill has && not (Flag.present Flag.heightBetween has) then
309502 html
503+
310504 else if Flag.present Flag.centerY has then
311505 Html.s
312506 [ Html.Attributes.class
@@ -319,6 +513,7 @@ finalizeNode has node attributes children embedMode parentContext =
319513 )
320514 ]
321515 [ html ]
516+
322517 else if Flag.present Flag.alignBottom has then
323518 Html.u
324519 [ Html.Attributes.class
@@ -331,6 +526,7 @@ finalizeNode has node attributes children embedMode parentContext =
331526 )
332527 ]
333528 [ html ]
529+
334530 else
335531 html
336532
@@ -339,47 +535,45 @@ finalizeNode has node attributes children embedMode parentContext =
339535
340536
341537embedWith 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
342547 if static then
343− staticRoot
344− :: (styles
345− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
346− |> Tuple.second
347− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
348− -- |> sortedReduce
349− |> toStyleSheet opts
350− )
548+ staticRoot opts
549+ :: dynamicStyleSheet
351550 :: children
551+
352552 else
353− (styles
354− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
355− |> Tuple.second
356− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
357− -- |> sortedReduce
358− |> toStyleSheet opts
359− )
553+ dynamicStyleSheet
360554 :: children
361555
362556
363557embedKeyed 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
364567 if static then
365− ( "static-stylesheet", staticRoot )
568+ ( "static-stylesheet", staticRoot opts )
366569 :: ( "dynamic-stylesheet"
367− , styles
368− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
369− |> Tuple.second
370− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
371− -- |> sortedReduce
372− |> toStyleSheet opts
570+ , dynamicStyleSheet
373571 )
374572 :: children
573+
375574 else
376575 ( "dynamic-stylesheet"
377− , styles
378− |> List.foldl reduceStyles ( Set.empty, [ renderFocusStyle opts.focus ] )
379− |> Tuple.second
380− -- |> reduceStylesRecursive Set.empty [ ]) --renderFocusStyle opts.focus ]
381− -- |> sortedReduce
382− |> toStyleSheet opts
576+ , dynamicStyleSheet
383577 )
384578 :: children
385579
@@ -397,6 +591,7 @@ reduceStylesRecursive cache found styles =
397591 in
398592 if Set.member styleName cache then
399593 reduceStylesRecursive cache found remaining
594+
400595 else
401596 reduceStylesRecursive (Set.insert styleName cache) (head :: found) remaining
402597
@@ -409,6 +604,7 @@ reduceStyles style (( cache, existing ) as nevermind) =
409604 in
410605 if Set.member styleName cache then
411606 nevermind
607+
412608 else
413609 ( Set.insert styleName cache
414610 , style :: existing
@@ -434,6 +630,7 @@ reduceRecursiveCalcName found styles =
434630 headOfList :: other :: remaining ->
435631 if headOfList /= other then
436632 reduceRecursiveCalcName (headOfList :: found) (other :: remaining)
633+
437634 else
438635 reduceRecursiveCalcName found (other :: remaining)
439636
@@ -450,6 +647,7 @@ reduceRecursive found styles =
450647 ( headOfListName, headOfList ) :: ( otherName, other ) :: remaining ->
451648 if headOfListName /= otherName then
452649 reduceRecursive (headOfList :: found) (( otherName, other ) :: remaining)
650+
453651 else
454652 reduceRecursive found (( otherName, other ) :: remaining)
455653
@@ -674,6 +872,7 @@ skippable flag style =
674872
675873 _ ->
676874 False
875+
677876 else
678877 case style of
679878 FontSize i ->
@@ -690,7 +889,16 @@ skippable flag style =
690889 False
691890
692891
693−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
694902gatherAttrRecursive classes node has transform styles attrs children elementAttrs =
695903 case elementAttrs of
696904 [] ->
@@ -719,6 +927,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
719927 Class flag exactClassName ->
720928 if Flag.present flag has then
721929 gatherAttrRecursive classes node has transform styles attrs children remaining
930+
722931 else
723932 gatherAttrRecursive (exactClassName ++ " " ++ classes) node (Flag.add flag has) transform styles attrs children remaining
724933
@@ -728,6 +937,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
728937 StyleClass flag style ->
729938 if Flag.present flag has then
730939 gatherAttrRecursive classes node has transform styles attrs children remaining
940+
731941 else if skippable flag style then
732942 gatherAttrRecursive (getStyleName style ++ " " ++ classes)
733943 node
@@ -737,6 +947,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
737947 attrs
738948 children
739949 remaining
950+
740951 else
741952 gatherAttrRecursive (getStyleName style ++ " " ++ classes)
742953 node
@@ -760,6 +971,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
760971 Width width ->
761972 if Flag.present Flag.width has then
762973 gatherAttrRecursive classes node has transform styles attrs children remaining
974+
763975 else
764976 case width of
765977 Px px ->
@@ -792,6 +1004,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
7921004 attrs
7931005 children
7941006 remaining
1007+
7951008 else
7961009 gatherAttrRecursive (classes ++ " " ++ Internal.Style.classes.widthFillPortion ++ " width-fill-" ++ String.fromInt portion)
7971010 node
@@ -819,7 +1032,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
8191032 in
8201033 gatherAttrRecursive (classes ++ " " ++ newClass)
8211034 node
822− (Flag.merge addToFlags has)
1035+ (Flag.merge addToFlags (Flag.add Flag.width has))
8231036 transform
8241037 (newStyles ++ styles)
8251038 attrs
@@ -829,6 +1042,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
8291042 Height height ->
8301043 if Flag.present Flag.height has then
8311044 gatherAttrRecursive classes node has transform styles attrs children remaining
1045+
8321046 else
8331047 case height of
8341048 Px px ->
@@ -839,7 +1053,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
8391053 name =
8401054 "height-px-" ++ val
8411055 in
842− gatherAttrRecursive (name ++ " " ++ classes)
1056+ gatherAttrRecursive (Internal.Style.classes.heightExact ++ " " ++ name ++ " " ++ classes)
8431057 node
8441058 (Flag.add Flag.height has)
8451059 transform
@@ -868,6 +1082,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
8681082 attrs
8691083 children
8701084 remaining
1085+
8711086 else
8721087 gatherAttrRecursive (classes ++ " " ++ (Internal.Style.classes.heightFillPortion ++ " height-fill-" ++ String.fromInt portion))
8731088 node
@@ -895,7 +1110,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
8951110 in
8961111 gatherAttrRecursive (classes ++ " " ++ newClass)
8971112 node
898− (Flag.merge addToFlags has)
1113+ (Flag.merge addToFlags (Flag.add Flag.height has))
8991114 transform
9001115 (newStyles ++ styles)
9011116 attrs
@@ -919,26 +1134,23 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
9191134 Heading i ->
9201135 if i <= 1 then
9211136 gatherAttrRecursive classes (addNodeName "h1" node) has transform styles attrs children remaining
1137+
9221138 else if i < 7 then
9231139 gatherAttrRecursive classes (addNodeName ("h" ++ String.fromInt i) node) has transform styles attrs children remaining
1140+
9241141 else
9251142 gatherAttrRecursive classes (addNodeName "h6" node) has transform styles attrs children remaining
9261143
9271144 Paragraph ->
928− let
929− newNode =
930− case node of
931− Generic ->
932− NodeName "p"
933−
934− NodeName name ->
935− NodeName name
936−
937− Embedded x y ->
938− Embedded x y
939− in
940− gatherAttrRecursive classes
941− 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
9421154 has
9431155 transform
9441156 styles
@@ -973,78 +1185,21 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
9731185
9741186 Styled styled ->
9751187 styles ++ styled.styles
976−
977− nearbyElement =
978− Html.div
979− [ Html.Attributes.class <|
980− case location of
981− Above ->
982− String.join " "
983− [ Internal.Style.classes.any
984− , Internal.Style.classes.single
985− , Internal.Style.classes.above
986− ]
987−
988− Below ->
989− String.join " "
990− [ Internal.Style.classes.any
991− , Internal.Style.classes.single
992− , Internal.Style.classes.below
993− ]
994−
995− OnRight ->
996− String.join " "
997− [ Internal.Style.classes.any
998− , Internal.Style.classes.single
999− , Internal.Style.classes.onRight
1000− ]
1001−
1002− OnLeft ->
1003− String.join " "
1004− [ Internal.Style.classes.any
1005− , Internal.Style.classes.single
1006− , Internal.Style.classes.onLeft
1007− ]
1008−
1009− InFront ->
1010− String.join " "
1011− [ Internal.Style.classes.any
1012− , Internal.Style.classes.single
1013− , Internal.Style.classes.inFront
1014− ]
1015−
1016− Behind ->
1017− String.join " "
1018− [ Internal.Style.classes.any
1019− , Internal.Style.classes.single
1020− , Internal.Style.classes.behind
1021− ]
1022− ]
1023− [ case elem of
1024− Empty ->
1025− VirtualDom.text ""
1026−
1027− Text str ->
1028− textElement str
1029−
1030− Unstyled html ->
1031− html asEl
1032−
1033− Styled styled ->
1034− styled.html NoStyleSheet asEl
1035− ]
1036−
1037− newClasses =
1038− if location == Behind then
1039− Internal.Style.classes.hasBehind ++ " " ++ classes
1040− else
1041− classes
10421188 in
1043− 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
10441198
10451199 AlignX x ->
10461200 if Flag.present Flag.xAlign has then
10471201 gatherAttrRecursive classes node has transform styles attrs children remaining
1202+
10481203 else
10491204 gatherAttrRecursive (alignXName x ++ " " ++ classes)
10501205 node
@@ -1071,6 +1226,7 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
10711226 AlignY y ->
10721227 if Flag.present Flag.yAlign has then
10731228 gatherAttrRecursive classes node has transform styles attrs children remaining
1229+
10741230 else
10751231 gatherAttrRecursive (alignYName y ++ " " ++ classes)
10761232 node
@@ -1094,6 +1250,106 @@ gatherAttrRecursive classes node has transform styles attrs children elementAttr
10941250 remaining
10951251
10961252
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+
10971353renderWidth w =
10981354 case w of
10991355 Px px ->
@@ -1114,6 +1370,7 @@ renderWidth w =
11141370 , Internal.Style.classes.widthFill
11151371 , []
11161372 )
1373+
11171374 else
11181375 ( Flag.add Flag.widthFill Flag.none
11191376 , Internal.Style.classes.widthFillPortion ++ " width-fill-" ++ String.fromInt portion
@@ -1179,7 +1436,7 @@ renderHeight h =
11791436 "height-px-" ++ val
11801437 in
11811438 ( Flag.none
1182− , name
1439+ , Internal.Style.classes.heightExact ++ " " ++ name
11831440 , [ Single name "height" (val ++ "px") ]
11841441 )
11851442
@@ -1195,13 +1452,14 @@ renderHeight h =
11951452 , Internal.Style.classes.heightFill
11961453 , []
11971454 )
1455+
11981456 else
11991457 ( Flag.add Flag.heightFill Flag.none
12001458 , Internal.Style.classes.heightFillPortion ++ " height-fill-" ++ String.fromInt portion
12011459 , [ Single
12021460 (Internal.Style.classes.any
12031461 ++ "."
1204− ++ Internal.Style.classes.row
1462+ ++ Internal.Style.classes.column
12051463 ++ " > "
12061464 ++ (Internal.Style.dot <| "height-fill-" ++ String.fromInt portion)
12071465 )
@@ -1220,7 +1478,9 @@ renderHeight h =
12201478 Single
12211479 cls
12221480 "min-height"
1223− (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")
12241484
12251485 ( newFlag, newAttrs, newStyle ) =
12261486 renderHeight len
@@ -1298,7 +1558,7 @@ element : LayoutContext -> NodeName -> List (Attribute aligned msg) -> Children
12981558element context node attributes children =
12991559 attributes
13001560 |> List.reverse
1301− |> gatherAttrRecursive (contextClasses context) node Flag.none untransformed [] [] []
1561+ |> gatherAttrRecursive (contextClasses context) node Flag.none untransformed [] [] NoNearbyChildren
13021562 |> createElement context children
13031563
13041564
@@ -1306,13 +1566,6 @@ untransformed =
13061566 Untransformed
13071567
13081568
1309−
1310−-- space =
1311−-- VirtualDom.text " "
1312−-- keyedSpace =
1313−-- ( " ", space )
1314−
1315−
13161569createElement : LayoutContext -> Children (Element msg) -> Gathered msg -> Element msg
13171570createElement context children rendered =
13181571 let
@@ -1323,6 +1576,7 @@ createElement context children rendered =
13231576 ( html context :: htmls
13241577 , existingStyles
13251578 )
1579+
13261580 else
13271581 ( html context :: htmls
13281582 , existingStyles
@@ -1333,13 +1587,16 @@ createElement context children rendered =
13331587 ( styled.html NoStyleSheet context :: htmls
13341588 , if List.isEmpty existingStyles then
13351589 styled.styles
1590+
13361591 else
13371592 styled.styles ++ existingStyles
13381593 )
1594+
13391595 else
13401596 ( styled.html NoStyleSheet context :: htmls
13411597 , if List.isEmpty existingStyles then
13421598 styled.styles
1599+
13431600 else
13441601 styled.styles ++ existingStyles
13451602 )
@@ -1350,33 +1607,33 @@ createElement context children rendered =
13501607 -- Same if it's a column or row with one child and width-content, height-content
13511608 -- interferes with css grid
13521609 -- Maybe we could unpack text elements in a paragraph as well,
1353− -- 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.
13541611 -- I don't think that's what we want.
1355− if
1356− context
1357− == asEl
1358− || context
1359− == asParagraph
1360− then
1361− ( VirtualDom.text
1362− (if context == asParagraph then
1363− str ++ " "
1364− else
1365− str
1366− )
1367− :: htmls
1368− , existingStyles
1369− )
1370− else
1371− ( textElement
1372− (if context == asParagraph then
1373− str ++ " "
1374− else
1375− str
1376− )
1377− :: htmls
1378− , existingStyles
1379− )
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+ )
13801637
13811638 Empty ->
13821639 ( htmls, existingStyles )
@@ -1388,6 +1645,7 @@ createElement context children rendered =
13881645 ( ( key, html context ) :: htmls
13891646 , existingStyles
13901647 )
1648+
13911649 else
13921650 ( ( key, html context ) :: htmls
13931651 , existingStyles
@@ -1399,13 +1657,16 @@ createElement context children rendered =
13991657 :: htmls
14001658 , if List.isEmpty existingStyles then
14011659 styled.styles
1660+
14021661 else
14031662 styled.styles ++ existingStyles
14041663 )
1664+
14051665 else
14061666 ( ( key, styled.html NoStyleSheet context ) :: htmls
14071667 , if List.isEmpty existingStyles then
14081668 styled.styles
1669+
14091670 else
14101671 styled.styles ++ existingStyles
14111672 )
@@ -1414,35 +1675,30 @@ createElement context children rendered =
14141675 -- TEXT OPTIMIZATION
14151676 -- You can have raw text if the element is an el, and has `width-content` and `height-content`
14161677 -- Same if it's a column or row with one child and width-content, height-content
1417− if
1418− context
1419− == asEl
1420− || context
1421− == asParagraph
1422− then
1423− ( ( key
1424− , VirtualDom.text
1425− (if context == asParagraph then
1426− str ++ " "
1427− else
1428− str
1429− )
1430− )
1431− :: htmls
1432− , existingStyles
1433− )
1434− else
1435− ( ( key
1436− , textElement
1437− (if context == asParagraph then
1438− str ++ " "
1439− else
1440− str
1441− )
1442− )
1443− :: htmls
1444− , existingStyles
1445− )
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
1695+
1696+ else
1697+ textElement str
1698+ )
1699+ :: htmls
1700+ , existingStyles
1701+ )
14461702
14471703 Empty ->
14481704 ( htmls, existingStyles )
@@ -1455,6 +1711,7 @@ createElement context children rendered =
14551711 newStyles =
14561712 if List.isEmpty styles then
14571713 rendered.styles
1714+
14581715 else
14591716 rendered.styles ++ styles
14601717 in
@@ -1464,7 +1721,9 @@ createElement context children rendered =
14641721 (finalizeNode rendered.has
14651722 rendered.node
14661723 rendered.attributes
1467− (Keyed <| List.map (\x -> ( "nearby-elements-pls", x )) rendered.children ++ keyed)
1724+ (Keyed
1725+ (addKeyedChildren "nearby-element-pls" keyed rendered.children)
1726+ )
14681727 NoStyleSheet
14691728 )
14701729
@@ -1472,7 +1731,13 @@ createElement context children rendered =
14721731 Styled
14731732 { styles = allStyles
14741733 , html =
1475− 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+ )
14761741 }
14771742
14781743 Unkeyed unkeyedChildren ->
@@ -1482,26 +1747,65 @@ createElement context children rendered =
14821747 newStyles =
14831748 if List.isEmpty styles then
14841749 rendered.styles
1750+
14851751 else
14861752 rendered.styles ++ styles
14871753 in
14881754 case newStyles of
14891755 [] ->
14901756 Unstyled
1491− (finalizeNode rendered.has
1757+ (finalizeNode
1758+ rendered.has
14921759 rendered.node
14931760 rendered.attributes
1494− (Unkeyed <| rendered.children ++ unkeyed)
1761+ (Unkeyed (addChildren unkeyed rendered.children))
14951762 NoStyleSheet
14961763 )
14971764
14981765 allStyles ->
14991766 Styled
15001767 { styles = allStyles
1501− , 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))
15021774 }
15031775
15041776
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+
15051809unit =
15061810 0
15071811
@@ -1513,13 +1817,26 @@ defaultOptions =
15131817 }
15141818
15151819
1516−staticRoot =
1517− 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) ] []
15181834
15191835
15201836addWhen ifThis x to =
15211837 if ifThis then
15221838 x :: to
1839+
15231840 else
15241841 to
15251842
@@ -1550,18 +1867,21 @@ filter attrs =
15501867 Width width ->
15511868 if Set.member "width" has then
15521869 ( found, has )
1870+
15531871 else
15541872 ( x :: found, Set.insert "width" has )
15551873
15561874 Height height ->
15571875 if Set.member "height" has then
15581876 ( found, has )
1877+
15591878 else
15601879 ( x :: found, Set.insert "height" has )
15611880
15621881 Describe description ->
15631882 if Set.member "described" has then
15641883 ( found, has )
1884+
15651885 else
15661886 ( x :: found, Set.insert "described" has )
15671887
@@ -1571,18 +1891,21 @@ filter attrs =
15711891 AlignX _ ->
15721892 if Set.member "align-x" has then
15731893 ( found, has )
1894+
15741895 else
15751896 ( x :: found, Set.insert "align-x" has )
15761897
15771898 AlignY _ ->
15781899 if Set.member "align-y" has then
15791900 ( found, has )
1901+
15801902 else
15811903 ( x :: found, Set.insert "align-y" has )
15821904
15831905 TransformComponent _ _ ->
15841906 if Set.member "transform" has then
15851907 ( found, has )
1908+
15861909 else
15871910 ( x :: found, Set.insert "transform" has )
15881911 )
@@ -1590,6 +1913,21 @@ filter attrs =
15901913 attrs
15911914
15921915
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+
15931931get : List (Attribute aligned msg) -> (Attribute aligned msg -> Bool) -> List (Attribute aligned msg)
15941932get attrs isAttr =
15951933 attrs
@@ -1598,6 +1936,7 @@ get attrs isAttr =
15981936 (\x found ->
15991937 if isAttr x then
16001938 x :: found
1939+
16011940 else
16021941 found
16031942 )
@@ -1609,7 +1948,7 @@ type Spacing
16091948
16101949
16111950type Padding
1612− = Padding String Int Int Int Int
1951+ = Padding String Float Float Float Float
16131952
16141953
16151954extractSpacingAndPadding : List (Attribute aligned msg) -> ( Maybe Padding, Maybe Spacing )
@@ -1705,35 +2044,44 @@ getHeight attrs =
17052044 Nothing
17062045
17072046
2047+textElementClasses : String
2048+textElementClasses =
2049+ classes.any
2050+ ++ " "
2051+ ++ classes.text
2052+ ++ " "
2053+ ++ classes.widthContent
2054+ ++ " "
2055+ ++ classes.heightContent
2056+
2057+
17082058textElement : String -> VirtualDom.Node msg
17092059textElement str =
17102060 Html.div
17112061 [ Html.Attributes.class
1712− (String.join " "
1713− [ classes.any
1714− , classes.text
1715− , classes.widthContent
1716− , classes.heightContent
1717− ]
1718− )
2062+ textElementClasses
17192063 ]
17202064 [ Html.text str ]
17212065
17222066
2067+textElementFillClasses : String
2068+textElementFillClasses =
2069+ classes.any
2070+ ++ " "
2071+ ++ classes.text
2072+ ++ " "
2073+ ++ classes.widthFill
2074+ ++ " "
2075+ ++ classes.heightFill
2076+
2077+
17232078textElementFill : String -> VirtualDom.Node msg
17242079textElementFill str =
1725− VirtualDom.node "div"
1726− [ VirtualDom.property "className"
1727− (Json.string <|
1728− String.join " "
1729− [ classes.any
1730− , classes.text
1731− , classes.widthFill
1732− , classes.heightFill
1733− ]
1734− )
2080+ Html.div
2081+ [ Html.Attributes.class
2082+ textElementFillClasses
17352083 ]
1736− [ VirtualDom.text str ]
2084+ [ Html.text str ]
17372085
17382086
17392087type Children x
@@ -1741,10 +2089,6 @@ type Children x
17412089 | Keyed (List ( String, x ))
17422090
17432091
1744−
1745−-- toHtml : OptionRecord -> Element msg -> VirtualDom.Node msg
1746−
1747−
17482092toHtml mode el =
17492093 case el of
17502094 Unstyled html ->
@@ -1780,8 +2124,7 @@ renderRoot optionList attributes child =
17802124
17812125
17822126type RenderMode
1783− = Viewport
1784− | Layout
2127+ = Layout
17852128 | NoStaticStyleSheet
17862129 | WithVirtualCss
17872130
@@ -1830,10 +2173,8 @@ rootStyle =
18302173 , SansSerif
18312174 ]
18322175 in
1833− [ StyleClass Flag.bgColor (Colored ("bg-color-" ++ formatColorClass (Rgba 1 1 1 1)) "background-color" (Rgba 1 1 1 1))
1834− , StyleClass Flag.fontColor (Colored ("font-color-" ++ formatColorClass (Rgba 0 0 0 1)) "color" (Rgba 0 0 0 1))
1835−
1836− -- , 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))
18372178 , StyleClass Flag.fontSize (FontSize 20)
18382179 , StyleClass Flag.fontFamily <|
18392180 FontFamily (List.foldl renderFontClassName "font-" families)
@@ -1865,14 +2206,49 @@ renderFontClassName font current =
18652206 |> String.toLower
18662207 |> String.words
18672208 |> String.join "-"
2209+
2210+ FontWith { name } ->
2211+ name
2212+ |> String.toLower
2213+ |> String.words
2214+ |> String.join "-"
18682215 )
18692216
18702217
18712218renderFocusStyle :
18722219 FocusStyle
1873− -> Style
2220+ -> List Style
18742221renderFocusStyle focus =
1875− 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+ )
18762252 (List.filterMap identity
18772253 [ Maybe.map (\color -> Property "border-color" (formatColor color)) focus.borderColor
18782254 , Maybe.map (\color -> Property "background-color" (formatColor color)) focus.backgroundColor
@@ -1895,6 +2271,7 @@ renderFocusStyle focus =
18952271 , Just <| Property "outline" "none"
18962272 ]
18972273 )
2274+ ]
18982275
18992276
19002277focusDefaultStyle : { backgroundColor : Maybe Color, borderColor : Maybe Color, shadow : Maybe Shadow }
@@ -1906,7 +2283,7 @@ focusDefaultStyle =
19062283 { color =
19072284 Rgba (155 / 255) (203 / 255) 1 1
19082285 , offset = ( 0, 0 )
1909− , blur = 3
2286+ , blur = 0
19102287 , size = 3
19112288 }
19122289 }
@@ -1974,497 +2351,734 @@ optionsToRecord options =
19742351 options
19752352
19762353
1977−renderFont : List Font -> String
1978−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 =
19792384 let
1980− fontName font =
2385+ withImport font =
19812386 case font of
1982− Serif ->
1983− "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
19842398
1985− SansSerif ->
1986− "sans-serif"
2399+ allNames =
2400+ List.map Tuple.first rules
19872401
1988− Monospace ->
1989− "monospace"
2402+ fontImports ( name, typefaces ) =
2403+ let
2404+ imports =
2405+ String.join "\n" (List.filterMap withImport typefaces)
2406+ in
2407+ imports
19902408
1991− Typeface name ->
1992− "\"" ++ name ++ "\""
2409+ fontAdjustments ( name, typefaces ) =
2410+ case typefaceAdjustment typefaces of
2411+ Nothing ->
2412+ String.join ""
2413+ (List.map (renderNullAdjustmentRule name) allNames)
19932414
1994− ImportFont name url ->
1995− "\"" ++ name ++ "\""
2415+ Just adjustment ->
2416+ String.join ""
2417+ (List.map (renderFontAdjustmentRule name adjustment) allNames)
19962418 in
1997− families
1998− |> List.map fontName
1999− |> String.join ", "
2419+ String.join "\n" (List.map fontImports rules)
2420+ ++ String.join "\n" (List.map fontAdjustments rules)
20002421
20012422
2002−toStyleSheet : OptionRecord -> List Style -> VirtualDom.Node msg
2003−toStyleSheet options styleSheet =
2004− VirtualDom.node "style" [] [ VirtualDom.text (toStyleSheetString options styleSheet) ]
2423+renderNullAdjustmentRule fontToAdjust otherFontName =
2424+ let
2425+ name =
2426+ if fontToAdjust == otherFontName then
2427+ fontToAdjust
20052428
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+ ]
20062464
2007−toStyleSheetString : OptionRecord -> List Style -> String
2008−toStyleSheetString options stylesheet =
2009− let
2010− renderTopLevels rule =
2011− case rule of
2012− FontFamily name typefaces ->
2013− let
2014− getImports font =
2015− case font of
2016− ImportFont _ url ->
2017− Just ("@import url('" ++ url ++ "');")
20182465
2019− _ ->
2020− Nothing
2021− in
2022− typefaces
2023− |> List.filterMap getImports
2024− |> String.join "\n"
2025− |> 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+ ]
20262495
2027− _ ->
2028− Nothing
20292496
2030− renderProps force (Property key val) existing =
2031− if force then
2032− existing ++ "\n " ++ key ++ ": " ++ val ++ " !important;"
2497+renderFontAdjustmentRule fontToAdjust ( full, capital ) otherFontName =
2498+ let
2499+ name =
2500+ if fontToAdjust == otherFontName then
2501+ fontToAdjust
2502+
20332503 else
2034− existing ++ "\n " ++ key ++ ": " ++ val ++ ";"
2504+ otherFontName ++ " ." ++ fontToAdjust
2505+ in
2506+ String.join " "
2507+ (fontRule name classes.sizeByCapital capital ++ fontRule name classes.fullSize full)
2508+
20352509
2036− renderStyle maybePseudo selector props =
2037− case maybePseudo of
2510+bracket selector rules =
2511+ let
2512+ renderPair ( name, val ) =
2513+ name ++ ": " ++ val ++ ";"
2514+ in
2515+ selector ++ " {" ++ String.join "" (List.map renderPair rules) ++ "}"
2516+
2517+
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
20382533 Nothing ->
2039− 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+ )
20402547
2041− Just pseudo ->
2042− case pseudo of
2043− Hover ->
2044− case options.hover of
2045− NoHover ->
2046− ""
2548+ _ ->
2549+ found
20472550
2048− ForceHover ->
2049− selector ++ "-hv {" ++ List.foldl (renderProps True) "" props ++ "\n}"
2551+ Just _ ->
2552+ found
2553+ )
2554+ Nothing
2555+ typefaces
20502556
2051− AllowHover ->
2052− selector ++ "-hv:hover {" ++ List.foldl (renderProps False) "" props ++ "\n}"
20532557
2054− Focus ->
2055− let
2056− renderedProps =
2057− List.foldl (renderProps False) "" props
2058− in
2059− String.join "\n"
2060− [ selector
2061− ++ "-fs:focus {"
2062− ++ renderedProps
2063− ++ "\n}"
2064− , "."
2065− ++ classes.any
2066− ++ ":focus ~ "
2067− ++ selector
2068− ++ "-fs:not(.focus) {"
2069− ++ renderedProps
2070− ++ "\n}"
2071− , "."
2072− ++ classes.any
2073− ++ ":focus "
2074− ++ selector
2075− ++ "-fs {"
2076− ++ renderedProps
2077− ++ "\n}"
2078− , ".focusable-parent:focus ~ "
2079− ++ "."
2080− ++ classes.any
2081− ++ " "
2082− ++ selector
2083− ++ "-fs {"
2084− ++ renderedProps
2085− ++ "\n}"
2086− ]
2558+fontName font =
2559+ case font of
2560+ Serif ->
2561+ "serif"
20872562
2088− Active ->
2089− selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}"
2563+ SansSerif ->
2564+ "sans-serif"
20902565
2091− renderStyleRule rule maybePseudo =
2092− case rule of
2093− Style selector props ->
2094− renderStyle maybePseudo selector props
2566+ Monospace ->
2567+ "monospace"
20952568
2096− Shadows name prop ->
2097− renderStyle
2098− maybePseudo
2099− ("." ++ name)
2100− [ Property "box-shadow" prop
2101− ]
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
2586+
2587+
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
21022607
2103− Transparency name transparency ->
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 ->
21042648 let
2105− opacity =
2106− (1 - transparency)
2107− |> min 1
2108− |> max 0
2649+ renderedProps =
2650+ List.foldl (renderProps False) "" props
21092651 in
2110− renderStyle
2111− maybePseudo
2112− ("." ++ name)
2113− [ Property "opacity" (String.fromFloat opacity)
2114− ]
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+ ]
21152663
2116− FontSize i ->
2117− renderStyle
2118− maybePseudo
2119− (".font-size-" ++ String.fromInt i)
2120− [ Property "font-size" (String.fromInt i ++ "px")
2121− ]
2664+ Active ->
2665+ [ selector ++ "-act:active {" ++ List.foldl (renderProps False) "" props ++ "\n}" ]
21222666
2123− FontFamily name typefaces ->
2124− renderStyle
2125− maybePseudo
2126− ("." ++ name)
2127− [ Property "font-family" (renderFont typefaces)
2128− ]
21292667
2130− Single class prop val ->
2131− renderStyle
2132− maybePseudo
2133− ("." ++ class)
2134− [ Property prop val
2135− ]
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
21362673
2137− Colored class prop color ->
2138− renderStyle
2139− maybePseudo
2140− ("." ++ class)
2141− [ Property prop (formatColor color)
2142− ]
2674+ Shadows name prop ->
2675+ renderStyle options
2676+ maybePseudo
2677+ ("." ++ name)
2678+ [ Property "box-shadow" prop
2679+ ]
21432680
2144− SpacingStyle cls x y ->
2145− let
2146− class =
2147− "." ++ 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+ ]
21482693
2149− xPx =
2150− 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+ ]
21512700
2152− yPx =
2153− 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"
21542718
2155− row =
2156− "." ++ Internal.Style.classes.row
2719+ else
2720+ "normal"
2721+ )
2722+ ]
2723+ in
2724+ renderStyle options
2725+ maybePseudo
2726+ ("." ++ name)
2727+ families
21572728
2158− wrappedRow =
2159− "." ++ Internal.Style.classes.wrapped ++ row
2729+ Single class prop val ->
2730+ renderStyle options
2731+ maybePseudo
2732+ ("." ++ class)
2733+ [ Property prop val
2734+ ]
21602735
2161− column =
2162− "." ++ Internal.Style.classes.column
2736+ Colored class prop color ->
2737+ renderStyle options
2738+ maybePseudo
2739+ ("." ++ class)
2740+ [ Property prop (formatColor color)
2741+ ]
21632742
2164− page =
2165− "." ++ Internal.Style.classes.page
2743+ SpacingStyle cls x y ->
2744+ let
2745+ class =
2746+ "." ++ cls
21662747
2167− paragraph =
2168− "." ++ Internal.Style.classes.paragraph
2748+ halfX =
2749+ String.fromFloat (toFloat x / 2) ++ "px"
21692750
2170− left =
2171− "." ++ Internal.Style.classes.alignLeft
2751+ halfY =
2752+ String.fromFloat (toFloat y / 2) ++ "px"
21722753
2173− right =
2174− "." ++ Internal.Style.classes.alignRight
2754+ xPx =
2755+ String.fromInt x ++ "px"
21752756
2176− any =
2177− "." ++ Internal.Style.classes.any
2757+ yPx =
2758+ String.fromInt y ++ "px"
21782759
2179− single =
2180− "." ++ Internal.Style.classes.single
2181− in
2182− String.concat
2183− [ renderStyle maybePseudo (class ++ row ++ " > " ++ any) [ Property "margin-right" xPx ]
2760+ row =
2761+ "." ++ Internal.Style.classes.row
21842762
2185− -- margins don't apply to last element of normal, unwrapped rows
2186− , renderStyle maybePseudo (class ++ row ++ " > " ++ any ++ ":last-child") [ Property "margin" "0" ]
2763+ wrappedRow =
2764+ "." ++ Internal.Style.classes.wrapped ++ row
21872765
2188− -- For wrapped rows, margins always apply because we handle "canceling out" the other margins manually in the element.
2189− , renderStyle maybePseudo
2190− (class ++ wrappedRow ++ " > " ++ any)
2191− [ Property "margin" ("0 " ++ xPx ++ " " ++ yPx ++ " 0")
2192− ]
2193− , renderStyle maybePseudo
2194− (class ++ wrappedRow ++ " > " ++ any ++ ":last-child")
2195− [ Property "margin-right" "0"
2196− ]
2766+ column =
2767+ "." ++ Internal.Style.classes.column
21972768
2198− -- columns
2199− , renderStyle maybePseudo (class ++ column ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2200− , renderStyle maybePseudo (class ++ page ++ " > " ++ any ++ " + " ++ any) [ Property "margin-top" yPx ]
2201− , renderStyle maybePseudo (class ++ page ++ " > " ++ left) [ Property "margin-right" xPx ]
2202− , renderStyle maybePseudo (class ++ page ++ " > " ++ right) [ Property "margin-left" xPx ]
2203− , renderStyle
2204− maybePseudo
2205− (class ++ paragraph)
2206− [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2207− ]
2208− , renderStyle
2209− maybePseudo
2210− ("textarea" ++ class)
2211− [ Property "line-height" ("calc(1em + " ++ String.fromInt y ++ "px)")
2212− ]
2769+ page =
2770+ "." ++ Internal.Style.classes.page
22132771
2214− -- , renderStyle
2215− -- maybePseudo
2216− -- (class ++ paragraph ++ " > " ++ any)
2217− -- [ Property "margin-right" xPx
2218− -- , Property "margin-bottom" yPx
2219− -- ]
2220− , renderStyle
2221− maybePseudo
2222− (class ++ paragraph ++ " > " ++ left)
2223− [ Property "margin-right" xPx
2224− ]
2225− , renderStyle
2226− maybePseudo
2227− (class ++ paragraph ++ " > " ++ right)
2228− [ Property "margin-left" xPx
2229− ]
2230− , renderStyle
2231− maybePseudo
2232− (class ++ paragraph ++ "::after")
2233− [ Property "content" "''"
2234− , Property "display" "block"
2235− , Property "height" "0"
2236− , Property "width" "0"
2237− , Property "margin-top" (String.fromInt (-1 * (y // 2)) ++ "px")
2238− ]
2239− , renderStyle
2240− maybePseudo
2241− (class ++ paragraph ++ "::before")
2242− [ Property "content" "''"
2243− , Property "display" "block"
2244− , Property "height" "0"
2245− , Property "width" "0"
2246− , Property "margin-bottom" (String.fromInt (-1 * (y // 2)) ++ "px")
2247− ]
2248− ]
2772+ paragraph =
2773+ "." ++ Internal.Style.classes.paragraph
22492774
2250− PaddingStyle cls top right bottom left ->
2251− let
2252− class =
2253− "."
2254− ++ cls
2255− in
2256− renderStyle
2257− maybePseudo
2258− class
2259− [ Property "padding"
2260− (String.fromInt top
2261− ++ "px "
2262− ++ String.fromInt right
2263− ++ "px "
2264− ++ String.fromInt bottom
2265− ++ "px "
2266− ++ String.fromInt left
2267− ++ "px"
2268− )
2269− ]
2775+ left =
2776+ "." ++ Internal.Style.classes.alignLeft
22702777
2271− GridTemplateStyle template ->
2272− let
2273− class =
2274− ".grid-rows-"
2275− ++ String.join "-" (List.map lengthClassName template.rows)
2276− ++ "-cols-"
2277− ++ String.join "-" (List.map lengthClassName template.columns)
2278− ++ "-space-x-"
2279− ++ lengthClassName (Tuple.first template.spacing)
2280− ++ "-space-y-"
2281− ++ lengthClassName (Tuple.second template.spacing)
2282−
2283− ySpacing =
2284− toGridLength (Tuple.second template.spacing)
2285−
2286− xSpacing =
2287− toGridLength (Tuple.first template.spacing)
2288−
2289− toGridLength x =
2290− toGridLengthHelper Nothing Nothing x
2291−
2292− toGridLengthHelper minimum maximum x =
2293− case x of
2294− Px px ->
2295− String.fromInt px ++ "px"
2296−
2297− Content ->
2298− case ( minimum, maximum ) of
2299− ( Nothing, Nothing ) ->
2300− "max-content"
2301−
2302− ( Just minSize, Nothing ) ->
2303− "minmax(" ++ String.fromInt minSize ++ "px, " ++ "max-content)"
2304−
2305− ( Nothing, Just maxSize ) ->
2306− "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2307−
2308− ( Just minSize, Just maxSize ) ->
2309− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2310−
2311− Fill i ->
2312− case ( minimum, maximum ) of
2313− ( Nothing, Nothing ) ->
2314− String.fromInt i ++ "fr"
2315−
2316− ( Just minSize, Nothing ) ->
2317− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt i ++ "fr" ++ "fr)"
2318−
2319− ( Nothing, Just maxSize ) ->
2320− "minmax(max-content, " ++ String.fromInt maxSize ++ "px)"
2321−
2322− ( Just minSize, Just maxSize ) ->
2323− "minmax(" ++ String.fromInt minSize ++ "px, " ++ String.fromInt maxSize ++ "px)"
2324−
2325− Min m len ->
2326− toGridLengthHelper (Just m) maximum len
2327−
2328− Max m len ->
2329− toGridLengthHelper minimum (Just m) len
2330−
2331− msColumns =
2332− template.columns
2333− |> List.map toGridLength
2334− |> String.join ySpacing
2335− |> (\x -> "-ms-grid-columns: " ++ x ++ ";")
2336−
2337− msRows =
2338− template.columns
2339− |> List.map toGridLength
2340− |> String.join ySpacing
2341− |> (\x -> "-ms-grid-rows: " ++ x ++ ";")
2342−
2343− base =
2344− class ++ "{" ++ msColumns ++ msRows ++ "}"
2345−
2346− columns =
2347− template.columns
2348− |> List.map toGridLength
2349− |> String.join " "
2350− |> (\x -> "grid-template-columns: " ++ x ++ ";")
2351−
2352− rows =
2353− template.rows
2354− |> List.map toGridLength
2355− |> String.join " "
2356− |> (\x -> "grid-template-rows: " ++ x ++ ";")
2357−
2358− gapX =
2359− "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
2360−
2361− gapY =
2362− "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
2363−
2364− modernGrid =
2365− class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
2366−
2367− supports =
2368− "@supports (display:grid) {" ++ modernGrid ++ "}"
2369− in
2370− base ++ supports
2778+ right =
2779+ "." ++ Internal.Style.classes.alignRight
23712780
2372− GridPosition position ->
2373− let
2374− class =
2375− ".grid-pos-"
2376− ++ String.fromInt position.row
2377− ++ "-"
2378− ++ String.fromInt position.col
2379− ++ "-"
2380− ++ String.fromInt position.width
2381− ++ "-"
2382− ++ String.fromInt position.height
2383−
2384− msPosition =
2385− String.join " "
2386− [ "-ms-grid-row: "
2387− ++ String.fromInt position.row
2388− ++ ";"
2389− , "-ms-grid-row-span: "
2390− ++ String.fromInt position.height
2391− ++ ";"
2392− , "-ms-grid-column: "
2393− ++ String.fromInt position.col
2394− ++ ";"
2395− , "-ms-grid-column-span: "
2396− ++ String.fromInt position.width
2397− ++ ";"
2398− ]
2399−
2400− base =
2401− class ++ "{" ++ msPosition ++ "}"
2402−
2403− modernPosition =
2404− String.join " "
2405− [ "grid-row: "
2406− ++ String.fromInt position.row
2407− ++ " / "
2408− ++ String.fromInt (position.row + position.height)
2409− ++ ";"
2410− , "grid-column: "
2411− ++ String.fromInt position.col
2412− ++ " / "
2413− ++ String.fromInt (position.col + position.width)
2414− ++ ";"
2415− ]
2416−
2417− modernGrid =
2418− class ++ "{" ++ modernPosition ++ "}"
2419−
2420− supports =
2421− "@supports (display:grid) {" ++ modernGrid ++ "}"
2422− in
2423− base ++ supports
2781+ any =
2782+ "." ++ Internal.Style.classes.any
24242783
2425− PseudoSelector class styles ->
2426− let
2427− renderPseudoRule style =
2428− renderStyleRule style (Just class)
2429− in
2430− 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
24312976 |> String.join " "
2977+ |> (\x -> "grid-template-columns: " ++ x ++ ";")
24322978
2433− Transform transform ->
2434− let
2435− val =
2436− transformValue transform
2979+ rows =
2980+ template.rows
2981+ |> List.map toGridLength
2982+ |> String.join " "
2983+ |> (\x -> "grid-template-rows: " ++ x ++ ";")
24372984
2438− class =
2439− transformClass transform
2440− in
2441− case ( class, val ) of
2442− ( Just cls, Just v ) ->
2443− renderStyle
2444− maybePseudo
2445− ("." ++ cls)
2446− [ Property "transform"
2447− v
2448− ]
2985+ gapX =
2986+ "grid-column-gap:" ++ toGridLength (Tuple.first template.spacing) ++ ";"
24492987
2450− _ ->
2451− ""
2988+ gapY =
2989+ "grid-row-gap:" ++ toGridLength (Tuple.second template.spacing) ++ ";"
24522990
2453− combine style rendered =
2454− { rendered
2455− | rules = rendered.rules ++ renderStyleRule style Nothing
2456− , topLevel =
2457− case renderTopLevels style of
2458− Nothing ->
2459− rendered.topLevel
2991+ modernGrid =
2992+ class ++ "{" ++ columns ++ rows ++ gapX ++ gapY ++ "}"
24602993
2461− Just topLevel ->
2462− rendered.topLevel ++ topLevel
2463− }
2464− in
2465− case List.foldl combine { rules = "", topLevel = "" } stylesheet of
2466− { topLevel, rules } ->
2467− 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+ []
24683082
24693083
24703084lengthClassName : Length -> String
@@ -2504,12 +3118,12 @@ formatTextShadow shadow =
25043118 ]
25053119
25063120
2507−textShadowName shadow =
3121+textShadowClass shadow =
25083122 String.concat
25093123 [ "txt"
2510− , String.fromFloat (Tuple.first shadow.offset) ++ "px"
2511− , String.fromFloat (Tuple.second shadow.offset) ++ "px"
2512− , String.fromFloat shadow.blur ++ "px"
3124+ , floatClass (Tuple.first shadow.offset) ++ "px"
3125+ , floatClass (Tuple.second shadow.offset) ++ "px"
3126+ , floatClass shadow.blur ++ "px"
25133127 , formatColorClass shadow.color
25143128 ]
25153129
@@ -2519,6 +3133,7 @@ formatBoxShadow shadow =
25193133 List.filterMap identity
25203134 [ if shadow.inset then
25213135 Just "inset"
3136+
25223137 else
25233138 Nothing
25243139 , Just <| String.fromFloat (Tuple.first shadow.offset) ++ "px"
@@ -2529,16 +3144,17 @@ formatBoxShadow shadow =
25293144 ]
25303145
25313146
2532−boxShadowName shadow =
3147+boxShadowClass shadow =
25333148 String.concat <|
25343149 [ if shadow.inset then
25353150 "box-inset"
3151+
25363152 else
25373153 "box-"
2538− , String.fromFloat (Tuple.first shadow.offset) ++ "px"
2539− , String.fromFloat (Tuple.second shadow.offset) ++ "px"
2540− , String.fromFloat shadow.blur ++ "px"
2541− , 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"
25423158 , formatColorClass shadow.color
25433159 ]
25443160
@@ -2583,6 +3199,17 @@ paddingName top right bottom left =
25833199 ++ String.fromInt left
25843200
25853201
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+
25863213getStyleName : Style -> String
25873214getStyleName style =
25883215 case style of
@@ -2613,6 +3240,9 @@ getStyleName style =
26133240 PaddingStyle cls top right bottom left ->
26143241 cls
26153242
3243+ BorderWidth cls top right bottom left ->
3244+ cls
3245+
26163246 GridTemplateStyle template ->
26173247 "grid-rows-"
26183248 ++ String.join "-" (List.map lengthClassName template.rows)
@@ -2845,3 +3475,76 @@ onlyStyles attr =
28453475
28463476 _ ->
28473477 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+ }