aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/web/css
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/library/lux/web/css')
-rw-r--r--stdlib/source/library/lux/web/css/class.lux34
-rw-r--r--stdlib/source/library/lux/web/css/font.lux24
-rw-r--r--stdlib/source/library/lux/web/css/id.lux34
-rw-r--r--stdlib/source/library/lux/web/css/property.lux517
-rw-r--r--stdlib/source/library/lux/web/css/query.lux135
-rw-r--r--stdlib/source/library/lux/web/css/selector.lux213
-rw-r--r--stdlib/source/library/lux/web/css/style.lux39
-rw-r--r--stdlib/source/library/lux/web/css/value.lux1422
8 files changed, 2418 insertions, 0 deletions
diff --git a/stdlib/source/library/lux/web/css/class.lux b/stdlib/source/library/lux/web/css/class.lux
new file mode 100644
index 000000000..46e980a47
--- /dev/null
+++ b/stdlib/source/library/lux/web/css/class.lux
@@ -0,0 +1,34 @@
+(.require
+ [library
+ [lux (.except)
+ [abstract
+ [monad (.only do)]]
+ [data
+ ["[0]" text (.use "[1]#[0]" hash)
+ ["%" \\format (.only format)]]]
+ ["[0]" meta (.only)
+ ["[0]" code]
+ [macro
+ [syntax (.only syntax)]]
+ [type
+ ["[0]" nominal (.except def)]]]]])
+
+(nominal.def .public Class
+ Text
+
+ (def .public class
+ (-> Class Text)
+ (|>> representation))
+
+ (def .public custom
+ (-> Text Class)
+ (|>> abstraction))
+
+ (def .public generic
+ (syntax (_ [])
+ (do meta.monad
+ [module meta.current_module_name
+ class meta.seed]
+ (in (list (` (..custom (, (code.text (format "c" (%.nat_16 class)
+ "_" (%.nat_16 (text#hash module))))))))))))
+ )
diff --git a/stdlib/source/library/lux/web/css/font.lux b/stdlib/source/library/lux/web/css/font.lux
new file mode 100644
index 000000000..f69a8f602
--- /dev/null
+++ b/stdlib/source/library/lux/web/css/font.lux
@@ -0,0 +1,24 @@
+(.require
+ [library
+ [lux (.except #source)
+ [meta
+ [code
+ ["s" \\parser]]]
+ [world
+ [net (.only URL)]]]]
+ ["[0]" //
+ ["[1][0]" value (.only Value Font_Stretch Font_Style Font_Weight)]])
+
+(type .public Unicode_Range
+ (Record
+ [#start Nat
+ #end Nat]))
+
+(type .public Font
+ (Record
+ [#family Text
+ #source URL
+ #stretch (Maybe (Value Font_Stretch))
+ #style (Maybe (Value Font_Style))
+ #weight (Maybe (Value Font_Weight))
+ #unicode_range (Maybe Unicode_Range)]))
diff --git a/stdlib/source/library/lux/web/css/id.lux b/stdlib/source/library/lux/web/css/id.lux
new file mode 100644
index 000000000..fc93ec1bb
--- /dev/null
+++ b/stdlib/source/library/lux/web/css/id.lux
@@ -0,0 +1,34 @@
+(.require
+ [library
+ [lux (.except)
+ [abstract
+ [monad (.only do)]]
+ [data
+ ["[0]" text (.use "[1]#[0]" hash)
+ ["%" \\format (.only format)]]]
+ ["[0]" meta (.only)
+ ["[0]" code]
+ [macro
+ [syntax (.only syntax)]]
+ [type
+ ["[0]" nominal (.except def)]]]]])
+
+(nominal.def .public ID
+ Text
+
+ (def .public id
+ (-> ID Text)
+ (|>> representation))
+
+ (def .public custom
+ (-> Text ID)
+ (|>> abstraction))
+
+ (def .public generic
+ (syntax (_ [])
+ (do meta.monad
+ [module meta.current_module_name
+ id meta.seed]
+ (in (list (` (..custom (, (code.text (format "i" (%.nat_16 id)
+ "_" (%.nat_16 (text#hash module))))))))))))
+ )
diff --git a/stdlib/source/library/lux/web/css/property.lux b/stdlib/source/library/lux/web/css/property.lux
new file mode 100644
index 000000000..192f0395a
--- /dev/null
+++ b/stdlib/source/library/lux/web/css/property.lux
@@ -0,0 +1,517 @@
+(.require
+ [library
+ [lux (.except All Location all left right)
+ [data
+ ["[0]" text]]
+ [meta
+ ["[0]" code (.only)
+ ["s" \\parser]]
+ [macro
+ [syntax (.only syntax)]
+ ["[0]" template]]
+ [type
+ ["[0]" nominal (.except def)]]]]]
+ [//
+ [value (.only All
+ Number
+ Length Thickness Time
+ Color
+ Location Fit
+ Slice
+ Alignment Animation_Direction
+ Animation Animation_Fill
+ Column_Fill Column_Span
+ Iteration Count
+ Play
+ Timing Visibility Attachment
+ Blend Span Image
+ Angle Repeat Border
+ Collapse Box_Decoration_Break Caption
+ Float Clear
+ Content
+ Cursor
+ Shadow Clip
+ Text_Direction
+ Display Empty
+ Filter
+ Flex_Direction Flex_Wrap
+ Font Font_Kerning Font_Size Font_Stretch Font_Style Font_Weight Font_Variant
+ Grid Grid_Content Grid_Flow Grid_Span Grid_Template
+ Hanging_Punctuation Hyphens Isolation
+ List_Style_Position List_Style_Type
+ Overflow Page_Break Pointer_Events
+ Position
+ Quotes
+ Resize Scroll_Behavior Table_Layout
+ Text_Align Text_Align_Last
+ Text_Decoration_Line Text_Decoration_Style
+ Text_Justification Text_Overflow Text_Transform
+ Transform Transform_Origin Transform_Style
+ Transition
+ Bidi User_Select
+ Vertical_Align
+ White_Space Word_Break Word_Wrap Writing_Mode
+ Z_Index)]])
+
+(def text_symbol
+ (syntax (_ [symbol s.text])
+ (in (list (code.local (text.replaced "-" "_" symbol))))))
+
+(nominal.def .public (Property brand)
+ Text
+
+ (def .public name
+ (-> (Property Any) Text)
+ (|>> representation))
+
+ (with_template [<brand> <alias>+ <property>+]
+ [(`` (with_template [<alias> <property>]
+ [(def .public <alias>
+ (Property <brand>)
+ (abstraction <property>))]
+
+ (,, (template.spliced <alias>+))))
+
+ (with_expansions [<rows> (template.spliced <property>+)]
+ (with_template [<property>]
+ [(`` (def .public (,, (text_symbol <property>))
+ (Property <brand>)
+ (abstraction <property>)))]
+
+ <rows>))]
+
+ [All
+ []
+ [["all"]]]
+
+ [Length
+ []
+ [["border-image-outset"]
+ ["border-image-width"]
+ ["bottom"]
+ ["column-gap"]
+ ["column-width"]
+ ["flex-basis"]
+ ["grid-column-gap"]
+ ["grid-gap"]
+ ["grid-row-gap"]
+ ["height"]
+ ["left"]
+ ["letter-spacing"]
+ ["line-height"]
+ ["margin"]
+ ["margin-bottom"]
+ ["margin-left"]
+ ["margin-right"]
+ ["margin-top"]
+ ["max-height"]
+ ["max-width"]
+ ["min-height"]
+ ["min-width"]
+ ["outline-offset"]
+ ["padding"]
+ ["padding-bottom"]
+ ["padding-left"]
+ ["padding-right"]
+ ["padding-top"]
+ ["perspective"]
+ ["right"]
+ ["text-indent"]
+ ["top"]
+ ["width"]
+ ["word-spacing"]]]
+
+ [Time
+ []
+ [["animation-delay"]
+ ["animation-duration"]
+ ["transition-delay"]
+ ["transition-duration"]]]
+
+ [Slice
+ []
+ [["border-image-slice"]]]
+
+ [Color
+ [[text_color "color"]]
+ [["background-color"]
+ ["border-color"]
+ ["border-bottom-color"]
+ ["border-left-color"]
+ ["border-right-color"]
+ ["border-top-color"]
+ ["caret-color"]
+ ["column-rule-color"]
+ ["outline-color"]
+ ["text-decoration-color"]]]
+
+ [Alignment
+ []
+ [["align-content"]
+ ["align-items"]
+ ["align-self"]
+ ["justify-content"]]]
+
+ [Animation
+ []
+ [["animation-name"]]]
+
+ [Animation_Direction
+ []
+ [["animation-direction"]]]
+
+ [Animation_Fill
+ []
+ [["animation-fill-mode"]]]
+
+ [Column_Fill
+ []
+ [["column-fill"]]]
+
+ [Column_Span
+ []
+ [["column-span"]]]
+
+ [Iteration
+ []
+ [["animation-iteration-count"]]]
+
+ [Count
+ []
+ [["column-count"]
+ ["flex-grow"]
+ ["flex-shrink"]
+ ["order"]
+ ["tab-size"]]]
+
+ [Play
+ []
+ [["animation-play-state"]]]
+
+ [Timing
+ []
+ [["animation-timing-function"]
+ ["transition-timing-function"]]]
+
+ [Visibility
+ []
+ [["backface-visibility"]
+ ["visibility"]]]
+
+ [Attachment
+ []
+ [["background-attachment"]]]
+
+ [Blend
+ []
+ [["background-blend-mode"]
+ ["mix-blend-mode"]]]
+
+ [Image
+ []
+ [["background-image"]
+ ["border-image-source"]
+ ["list-style-image"]]]
+
+ [Span
+ []
+ [["background-clip"]
+ ["background-origin"]
+ ["box-sizing"]]]
+
+ [Location
+ []
+ [["background-position"]
+ ["object-position"]
+ ["perspective-origin"]]]
+
+ [Repeat
+ []
+ [["background-repeat"]
+ ["border-image-repeat"]]]
+
+ [Fit
+ []
+ [["background-size"]
+ ["border-radius"]
+ ["border-bottom-left-radius"]
+ ["border-bottom-right-radius"]
+ ["border-top-left-radius"]
+ ["border-top-right-radius"]
+ ["border-spacing"]
+ ["object-fit"]]]
+
+ [Border
+ []
+ [["border-style"]
+ ["border-bottom-style"]
+ ["border-left-style"]
+ ["border-right-style"]
+ ["border-top-style"]
+ ["column-rule-style"]
+ ["outline-style"]]]
+
+ [Thickness
+ []
+ [["border-width"]
+ ["border-bottom-width"]
+ ["border-left-width"]
+ ["border-right-width"]
+ ["border-top-width"]
+ ["column-rule-width"]
+ ["outline-width"]]]
+
+ [Collapse
+ []
+ [["border-collapse"]]]
+
+ [Box_Decoration_Break
+ []
+ [["box-decoration-break"]]]
+
+ [Caption
+ []
+ [["caption-side"]]]
+
+ [Clear
+ []
+ [["clear"]]]
+
+ [Shadow
+ []
+ [["box-shadow"]
+ ["text-shadow"]]]
+
+ [Clip
+ []
+ [["clip"]]]
+
+ [Content
+ []
+ [["counter-reset"]
+ ["counter-increment"]]]
+
+ [Cursor
+ []
+ [["cursor"]]]
+
+ [Text_Direction
+ [[text_direction "direction"]]
+ []]
+
+ [Display
+ []
+ [["display"]]]
+
+ [Empty
+ []
+ [["empty-cells"]]]
+
+ [Filter
+ []
+ [["filter"]]]
+
+ [Flex_Direction
+ []
+ [["flex-direction"]]]
+
+ [Flex_Wrap
+ []
+ [["flex-wrap"]]]
+
+ [Float
+ []
+ [["float"]]]
+
+ [Font
+ []
+ [["font-family"]]]
+
+ [Font_Kerning
+ []
+ [["font-kerning"]]]
+
+ [Font_Size
+ []
+ [["font-size"]]]
+
+ [Font_Stretch
+ []
+ [["font-stretch"]]]
+
+ [Font_Style
+ []
+ [["font-style"]]]
+
+ [Font_Weight
+ []
+ [["font-weight"]]]
+
+ [Font_Variant
+ []
+ [["font-variant"]]]
+
+ [Grid
+ []
+ [["grid-area"]]]
+
+ [Grid_Content
+ []
+ [["grid-auto-columns"]
+ ["grid-auto-rows"]
+ ["grid-template-columns"]
+ ["grid-template-rows"]]]
+
+ [Grid_Flow
+ []
+ [["grid-auto-flow"]]]
+
+ [Grid_Span
+ []
+ [["grid-column-end"]
+ ["grid-column-start"]
+ ["grid-row-end"]
+ ["grid-row-start"]]]
+
+ [Grid_Template
+ []
+ [["grid-template-areas"]]]
+
+ [Hanging_Punctuation
+ []
+ [["hanging-punctuation"]]]
+
+ [Hyphens
+ []
+ [["hyphens"]]]
+
+ [Isolation
+ []
+ [["isolation"]]]
+
+ [List_Style_Position
+ []
+ [["list-style-position"]]]
+
+ [List_Style_Type
+ []
+ [["list-style-type"]]]
+
+ [Number
+ []
+ [["font-size-adjust"]
+ ["opacity"]]]
+
+ [Overflow
+ []
+ [["overflow"]
+ ["overflow-x"]
+ ["overflow-y"]]]
+
+ [Page_Break
+ []
+ [["page-break-after"]
+ ["page-break-before"]
+ ["page-break-inside"]]]
+
+ [Pointer_Events
+ []
+ [["pointer-events"]]]
+
+ [Position
+ []
+ [["position"]]]
+
+ [Quotes
+ []
+ [["quotes"]]]
+
+ [Resize
+ []
+ [["resize"]]]
+
+ [Scroll_Behavior
+ []
+ [["scroll-behavior"]]]
+
+ [Table_Layout
+ []
+ [["table-layout"]]]
+
+ [Text_Align
+ []
+ [["text-align"]]]
+
+ [Text_Align_Last
+ []
+ [["text-align-last"]]]
+
+ [Text_Decoration_Line
+ []
+ [["text-decoration-line"]]]
+
+ [Text_Decoration_Style
+ []
+ [["text-decoration-style"]]]
+
+ [Text_Justification
+ []
+ [["text-justify"]]]
+
+ [Text_Overflow
+ []
+ [["text-overflow"]]]
+
+ [Text_Transform
+ []
+ [["text-transform"]]]
+
+ [Transform
+ []
+ [["transform"]]]
+
+ [Transform_Origin
+ []
+ [["transform-origin"]]]
+
+ [Transform_Style
+ []
+ [["transform-style"]]]
+
+ [Transition
+ []
+ [["transition-property"]]]
+
+ [Bidi
+ []
+ [["unicode-bidi"]]]
+
+ [User_Select
+ []
+ [["user-select"]]]
+
+ [Vertical_Align
+ []
+ [["vertical-align"]]]
+
+ [White_Space
+ []
+ [["white-space"]]]
+
+ [Word_Break
+ []
+ [["word-break"]]]
+
+ [Word_Wrap
+ []
+ [["word-wrap"]]]
+
+ [Writing_Mode
+ []
+ [["writing-mode"]]]
+
+ [Z_Index
+ []
+ [["z-index"]]]
+ )
+ )
diff --git a/stdlib/source/library/lux/web/css/query.lux b/stdlib/source/library/lux/web/css/query.lux
new file mode 100644
index 000000000..de3defe3b
--- /dev/null
+++ b/stdlib/source/library/lux/web/css/query.lux
@@ -0,0 +1,135 @@
+(.require
+ [library
+ [lux (.except and or not all only except)
+ [data
+ ["[0]" text (.only)
+ ["%" \\format (.only format)]]]
+ [meta
+ ["[0]" code (.only)
+ ["s" \\parser]]
+ [macro
+ [syntax (.only syntax)]
+ ["[0]" template]]
+ [type
+ ["[0]" nominal (.except def)]]]]]
+ ["[0]" //
+ ["[1][0]" value (.only Value Length Count Resolution Ratio
+ Orientation Scan Boolean Update
+ Block_Overflow Inline_Overflow
+ Display_Mode Color_Gamut Inverted_Colors
+ Pointer Hover
+ Light Scripting Motion Color_Scheme)]])
+
+(def text_symbol
+ (syntax (_ [symbol s.text])
+ (in (list (code.local (text.replaced "-" "_" symbol))))))
+
+(nominal.def .public Media
+ Text
+
+ (def .public media
+ (-> Media Text)
+ (|>> representation))
+
+ (with_template [<media>]
+ [(`` (def .public (,, (text_symbol <media>))
+ Media
+ (abstraction <media>)))]
+
+ ["all"]
+ ["print"]
+ ["screen"]
+ ["speech"]
+ ))
+
+(nominal.def .public Feature
+ Text
+
+ (def .public feature
+ (-> Feature Text)
+ (|>> representation))
+
+ (with_template [<feature> <brand>]
+ [(`` (def .public ((,, (text_symbol <feature>)) input)
+ (-> (Value <brand>) Feature)
+ (abstraction (format "(" <feature> ": " (//value.value input) ")"))))]
+
+ ["min-color" Count]
+ ["color" Count]
+ ["max-color" Count]
+
+ ["min-color-index" Count]
+ ["color-index" Count]
+ ["max-color-index" Count]
+
+ ["min-monochrome" Count]
+ ["monochrome" Count]
+ ["max-monochrome" Count]
+
+ ["min-height" Length]
+ ["height" Length]
+ ["max-height" Length]
+
+ ["min-width" Length]
+ ["width" Length]
+ ["max-width" Length]
+
+ ["min-resolution" Resolution]
+ ["resolution" Resolution]
+ ["max-resolution" Resolution]
+
+ ["aspect-ratio" Ratio]
+ ["max-aspect-ratio" Ratio]
+ ["min-aspect-ratio" Ratio]
+
+ ["display-mode" Display_Mode]
+ ["color-gamut" Color_Gamut]
+ ["grid" Boolean]
+ ["orientation" Orientation]
+ ["overflow-block" Block_Overflow]
+ ["overflow-inline" Inline_Overflow]
+ ["scan" Scan]
+ ["update" Update]
+ ["inverted-colors" Inverted_Colors]
+ ["pointer" Pointer]
+ ["any-pointer" Pointer]
+ ["hover" Hover]
+ ["any-hover" Hover]
+ ["light-level" Light]
+ ["scripting" Scripting]
+ ["prefers-reduced-motion" Motion]
+ ["prefers-color-scheme" Color_Scheme]
+ )
+ )
+
+(nominal.def .public Query
+ Text
+
+ (def .public query
+ (-> Query Text)
+ (|>> representation))
+
+ (with_template [<name> <operator>]
+ [(def .public <name>
+ (-> Media Query)
+ (|>> ..media (format <operator>) abstraction))]
+
+ [except "not "]
+ [only "only "]
+ )
+
+ (def .public not
+ (-> Feature Query)
+ (|>> ..feature (format "not ") abstraction))
+
+ (with_template [<name> <operator>]
+ [(def .public (<name> left right)
+ (-> Query Query Query)
+ (abstraction (format (representation left)
+ <operator>
+ (representation right))))]
+
+ [and " and "]
+ [or " or "]
+ )
+ )
diff --git a/stdlib/source/library/lux/web/css/selector.lux b/stdlib/source/library/lux/web/css/selector.lux
new file mode 100644
index 000000000..292e27300
--- /dev/null
+++ b/stdlib/source/library/lux/web/css/selector.lux
@@ -0,0 +1,213 @@
+(.require
+ [library
+ [lux (.except Label Tag or and for same? not)
+ [data
+ ["[0]" text (.only)
+ ["%" \\format (.only format)]]]
+ [math
+ [number
+ ["i" int]]]
+ [meta
+ [macro
+ ["[0]" template]]
+ [type
+ ["[0]" nominal (.except def)]]]
+ [world
+ ["[0]" locale (.only Locale)]]]]
+ ["[0]" //
+ ["[1][0]" id (.only ID)]
+ ["[1][0]" class (.only Class)]])
+
+(type .public Label Text)
+
+(type .public Tag Label)
+(type .public Attribute Label)
+
+(nominal.def .public (Generic brand) Any)
+
+(with_template [<generic> <brand>]
+ [(nominal.def <brand> Any)
+ (type .public <generic> (Generic <brand>))]
+
+ [Can_Chain Can_Chain']
+ [Cannot_Chain Cannot_Chain']
+ )
+
+(nominal.def .public Unique Any)
+(nominal.def .public Specific Any)
+(nominal.def .public Composite Any)
+
+(nominal.def .public (Selector kind)
+ Text
+
+ (def .public selector
+ (-> (Selector Any) Text)
+ (|>> representation))
+
+ (def .public any
+ (Selector Cannot_Chain)
+ (abstraction "*"))
+
+ (def .public tag
+ (-> Tag (Selector Cannot_Chain))
+ (|>> abstraction))
+
+ (with_template [<name> <type> <prefix> <kind> <out>]
+ [(def .public <name>
+ (-> <type> (Selector <kind>))
+ (|>> <out> (format <prefix>) abstraction))]
+
+ [id ID "#" Unique //id.id]
+ [class Class "." Can_Chain //class.class]
+ )
+
+ (with_template [<right> <left> <combinator>+]
+ [(`` (with_template [<combinator> <name>]
+ [(def .public (<name> right left)
+ (-> (Selector <right>) (Selector <left>) (Selector Composite))
+ (abstraction (format (representation left)
+ <combinator>
+ (representation right))))]
+
+ (,, (template.spliced <combinator>+))))]
+
+ [Can_Chain (Generic Any)
+ [["" and]]]
+ [Specific (Generic Any)
+ [["" at]]]
+ [Unique (Generic Any)
+ [["" for]]]
+ [Any Any
+ [["," or]
+ [" " in]
+ [">" sub]
+ ["+" next]
+ ["~" later]]]
+ )
+
+ (type .public (Specializer kind)
+ (-> (Selector kind) (Selector (Generic Any)) (Selector Composite)))
+
+ (type .public Combinator
+ (-> (Selector Any) (Selector Any) (Selector Composite)))
+
+ (def .public (with? attribute)
+ (-> Attribute (Selector Can_Chain))
+ (abstraction (format "[" attribute "]")))
+
+ (with_template [<check> <name>]
+ [(def .public (<name> attribute value)
+ (-> Attribute Text (Selector Can_Chain))
+ (abstraction (format "[" attribute <check> value "]")))]
+
+ ["=" same?]
+ ["~=" has?]
+ ["|=" has_start?]
+ ["^=" starts?]
+ ["$=" ends?]
+ ["*=" contains?]
+ )
+
+ (with_template [<kind> <pseudo>+]
+ [(`` (with_template [<name> <pseudo>]
+ [(def .public <name>
+ (Selector <kind>)
+ (abstraction <pseudo>))]
+
+ (,, (template.spliced <pseudo>+))))]
+
+ [Can_Chain
+ [[active ":active"]
+ [checked ":checked"]
+ [default ":default"]
+ [disabled ":disabled"]
+ [empty ":empty"]
+ [enabled ":enabled"]
+ [first_child ":first-child"]
+ [first_of_type ":first-of-type"]
+ [focused ":focus"]
+ [hovered ":hover"]
+ [in_range ":in-range"]
+ [indeterminate ":indeterminate"]
+ [invalid ":invalid"]
+ [last_child ":last-child"]
+ [last_of_type ":last-of-type"]
+ [link ":link"]
+ [only_of_type ":only-of-type"]
+ [only_child ":only-child"]
+ [optional ":optional"]
+ [out_of_range ":out-of-range"]
+ [read_only ":read-only"]
+ [read_write ":read-write"]
+ [required ":required"]
+ [root ":root"]
+ [target ":target"]
+ [valid ":valid"]
+ [visited ":visited"]]]
+
+ [Specific
+ [[after "::after"]
+ [before "::before"]
+ [first_letter "::first-letter"]
+ [first_line "::first-line"]
+ [placeholder "::placeholder"]
+ [selection "::selection"]]]
+ )
+
+ (def .public (language locale)
+ (-> Locale (Selector Can_Chain))
+ (|> locale
+ locale.code
+ (text.enclosed ["(" ")"])
+ (format ":lang")
+ abstraction))
+
+ (def .public not
+ (-> (Selector Any) (Selector Can_Chain))
+ (|>> representation
+ (text.enclosed ["(" ")"])
+ (format ":not")
+ abstraction))
+
+ (nominal.def .public Index
+ Text
+
+ (def .public index
+ (-> Nat Index)
+ (|>> %.nat abstraction))
+
+ (with_template [<name> <index>]
+ [(def .public <name> Index (abstraction <index>))]
+
+ [odd "odd"]
+ [even "even"]
+ )
+
+ (type .public Formula
+ (Record
+ [#constant Int
+ #variable Int]))
+
+ (def .public (formula input)
+ (-> Formula Index)
+ (let [(open "_[0]") input]
+ (abstraction (format (if (i.< +0 _#variable)
+ (%.int _#variable)
+ (%.nat (.nat _#variable)))
+ (%.int _#constant)))))
+
+ (with_template [<name> <pseudo>]
+ [(def .public (<name> index)
+ (-> Index (Selector Can_Chain))
+ (|> (representation index)
+ (text.enclosed ["(" ")"])
+ (format <pseudo>)
+ (abstraction Selector)))]
+
+ [nth_child ":nth-child"]
+ [nth_last_child ":nth-last-child"]
+ [nth_of_type ":nth-of-type"]
+ [nth_last_of_type ":nth-last-of-type"]
+ )
+ )
+ )
diff --git a/stdlib/source/library/lux/web/css/style.lux b/stdlib/source/library/lux/web/css/style.lux
new file mode 100644
index 000000000..d1bd1899d
--- /dev/null
+++ b/stdlib/source/library/lux/web/css/style.lux
@@ -0,0 +1,39 @@
+(.require
+ [library
+ [lux (.except with)
+ [data
+ [text
+ ["%" \\format (.only format)]]
+ [collection
+ ["[0]" list (.use "[1]#[0]" mix)]]]
+ [meta
+ [type
+ ["[0]" nominal (.except def)]]]]]
+ ["[0]" //
+ ["[1][0]" value (.only Value)]
+ ["[1][0]" property (.only Property)]])
+
+(nominal.def .public Style
+ Text
+
+ (def .public empty
+ Style
+ (abstraction ""))
+
+ (def .public (with [property value])
+ (All (_ brand)
+ (-> [(Property brand) (Value brand)]
+ (-> Style Style)))
+ (|>> representation
+ (format (//property.name property) ": " (//value.value value) ";")
+ abstraction))
+
+ (def .public inline
+ (-> Style Text)
+ (|>> representation))
+
+ (def .public (style config)
+ (-> (List (Ex (_ brand) [(Property brand) (Value brand)]))
+ Style)
+ (list#mix ..with ..empty config))
+ )
diff --git a/stdlib/source/library/lux/web/css/value.lux b/stdlib/source/library/lux/web/css/value.lux
new file mode 100644
index 000000000..37c8580a0
--- /dev/null
+++ b/stdlib/source/library/lux/web/css/value.lux
@@ -0,0 +1,1422 @@
+(.require
+ [library
+ [lux (.except Label All Location and static false true all)
+ [control
+ ["[0]" maybe]]
+ [data
+ ["[0]" product]
+ ["[0]" color (.only)
+ [pigment (.only Pigment)]
+ ["[0]" rgb]]
+ ["[0]" text (.only)
+ ["%" \\format (.only Format format)]]
+ [collection
+ ["[0]" list (.use "[1]#[0]" functor)]]]
+ [math
+ [number
+ ["n" nat]
+ ["i" int]
+ ["r" rev]
+ ["f" frac]]]
+ [meta
+ ["[0]" code (.only)
+ ["<[1]>" \\parser]]
+ [macro
+ [syntax (.only syntax)]
+ ["[0]" template]]
+ [type
+ ["[0]" nominal (.except def)]]]
+ [world
+ [net (.only URL)]]]]
+ [//
+ [selector (.only Label)]])
+
+(def text_symbol
+ (syntax (_ [symbol <code>.text])
+ (in (list (code.local (text.replaced "-" "_" symbol))))))
+
+(def enumeration
+ (template (_ <abstraction> <representation> <out> <sample>+ <definition>+)
+ [(nominal.def .public <abstraction>
+ <representation>
+
+ (def .public <out>
+ (-> <abstraction> <representation>)
+ (|>> representation))
+
+ (`` (with_template [<name> <value>]
+ [(def .public <name> <abstraction> (abstraction <value>))]
+
+ (,, (template.spliced <sample>+))
+ ))
+
+ (template.spliced <definition>+))]))
+
+(def (%number value)
+ (Format Frac)
+ (let [raw (%.frac value)]
+ (if (f.< +0.0 value)
+ raw
+ (|> raw (text.split_at 1) maybe.trusted product.right))))
+
+(nominal.def .public (Value brand)
+ Text
+
+ (def .public value
+ (-> (Value Any)
+ Text)
+ (|>> representation))
+
+ (with_template [<name> <value>]
+ [(def .public <name>
+ Value
+ (abstraction <value>))]
+
+ [initial "initial"]
+ [inherit "inherit"]
+ [unset "unset"]
+ )
+
+ (nominal.def .public (Numeric kind) Any)
+
+ (with_template [<name>]
+ [(with_expansions [<name>' (template.symbol [<name> "'"])]
+ (nominal.def .public <name>' Any)
+ (type .public <name>
+ (Numeric <name>')))]
+
+ [Number]
+ [Length]
+ [Time]
+ [Percentage]
+ )
+
+ (with_template [<brand> <alias>+ <value>+]
+ [(nominal.def .public <brand> Any)
+
+ (`` (with_template [<name> <value>]
+ [(def .public <name>
+ (Value <brand>)
+ (abstraction <value>))]
+
+ (,, (template.spliced <alias>+))))
+
+ (with_expansions [<rows> (template.spliced <value>+)]
+ (with_template [<value>]
+ [(`` (def .public (,, (..text_symbol <value>))
+ (Value <brand>)
+ (abstraction <value>)))]
+
+ <rows>))]
+
+ [All
+ []
+ []]
+
+ [Thickness
+ []
+ [["medium"]
+ ["thin"]
+ ["thick"]]]
+
+ [Slice
+ [[full_slice "fill"]]
+ []]
+
+ [Alignment
+ [[auto_alignment "auto"]]
+ [["stretch"]
+ ["center"]
+ ["flex-start"]
+ ["flex-end"]
+ ["baseline"]
+ ["space-between"]
+ ["space-around"]]]
+
+ [Animation
+ []
+ []]
+
+ [Animation_Direction
+ [[normal_direction "normal"]]
+ [["reverse"]
+ ["alternate"]
+ ["alternate-reverse"]]]
+
+ [Animation_Fill
+ [[fill_forwards "forwards"]
+ [fill_backwards "backwards"]
+ [fill_both "both"]]
+ []]
+
+ [Column_Fill
+ []
+ [["balance"]
+ ["auto"]]]
+
+ [Column_Span
+ []
+ [["all"]]]
+
+ [Iteration
+ []
+ [["infinite"]]]
+
+ [Count
+ []
+ []]
+
+ [Play
+ []
+ [["paused"]
+ ["running"]]]
+
+ [Timing
+ []
+ [["linear"]
+ ["ease"]
+ ["ease-in"]
+ ["ease-out"]
+ ["ease-in-out"]
+ ["step-start"]
+ ["step-end"]]]
+
+ [Visibility
+ [[invisible "hidden"]
+ [collapse_visibility "collapse"]]
+ [["visible"]]]
+
+ [Attachment
+ [[scroll_attachment "scroll"]
+ [fixed_attachment "fixed"]
+ [local_attachment "local"]]
+ []]
+
+ [Blend
+ [[normal_blend "normal"]]
+ [["multiply"]
+ ["screen"]
+ ["overlay"]
+ ["darken"]
+ ["lighten"]
+ ["color-dodge"]
+ ["color-burn"]
+ ["difference"]
+ ["exclusion"]
+ ["hue"]
+ ["saturation"]
+ ["color"]
+ ["luminosity"]]]
+
+ [Span
+ []
+ [["border-box"]
+ ["padding-box"]
+ ["content-box"]]]
+
+ [Image
+ [[no_image "none"]]
+ []]
+
+ [Repeat
+ [[stretch_repeat "stretch"]]
+ [["repeat"]
+ ["repeat-x"]
+ ["repeat-y"]
+ ["no-repeat"]
+ ["space"]
+ ["round"]]]
+
+ [Location
+ [[left_top "left top"]
+ [left_center "left center"]
+ [left_bottom "left bottom"]
+ [right_top "right top"]
+ [right_center "right center"]
+ [right_bottom "right bottom"]
+ [center_top "center top"]
+ [center_center "center center"]
+ [center_bottom "center bottom"]]
+ []]
+
+ [Fit
+ [[no_fit "none"]]
+ [["fill"]
+ ["cover"]
+ ["contain"]
+ ["scale-down"]]]
+
+ [Border
+ []
+ [["hidden"]
+ ["dotted"]
+ ["dashed"]
+ ["solid"]
+ ["double"]
+ ["groove"]
+ ["ridge"]
+ ["inset"]
+ ["outset"]]]
+
+ [Collapse
+ []
+ [["separate"]
+ ["collapse"]]]
+
+ [Box_Decoration_Break
+ []
+ [["slice"]
+ ["clone"]]]
+
+ [Caption
+ []
+ [["top"]
+ ["bottom"]]]
+
+ [Float
+ [[float_left "left"]
+ [float_right "right"]]
+ []]
+
+ [Clear
+ [[clear_left "left"]
+ [clear_right "right"]
+ [clear_both "both"]]
+ []]
+
+ [Counter
+ []
+ []]
+
+ [Content
+ []
+ [["open-quote"]
+ ["close-quote"]
+ ["no-open-quote"]
+ ["no-close-quote"]]]
+
+ [Cursor
+ [[horizontal_text "text"]
+ [no_cursor "none"]]
+ [["alias"]
+ ["all-scroll"]
+ ["cell"]
+ ["context-menu"]
+ ["col-resize"]
+ ["copy"]
+ ["crosshair"]
+ ["default"]
+ ["e-resize"]
+ ["ew-resize"]
+ ["grab"]
+ ["grabbing"]
+ ["help"]
+ ["move"]
+ ["n-resize"]
+ ["ne-resize"]
+ ["nesw-resize"]
+ ["ns-resize"]
+ ["nw-resize"]
+ ["nwse-resize"]
+ ["no-drop"]
+ ["not-allowed"]
+ ["pointer"]
+ ["progress"]
+ ["row-resize"]
+ ["s-resize"]
+ ["se-resize"]
+ ["sw-resize"]
+ ["vertical-text"]
+ ["w-resize"]
+ ["wait"]
+ ["zoom-in"]
+ ["zoom-out"]]]
+
+ [Shadow
+ []
+ []]
+
+ [Clip
+ []
+ []]
+
+ [Text_Direction
+ [[left_to_right "ltr"]
+ [right_to_left "rtl"]]
+ []]
+
+ [Display
+ [[grid_display "grid"]
+ [no_display "none"]]
+ [["inline"]
+ ["block"]
+ ["contents"]
+ ["flex"]
+ ["inline-block"]
+ ["inline-flex"]
+ ["inline-grid"]
+ ["inline-table"]
+ ["list-item"]
+ ["run-in"]
+ ["table"]
+ ["table-caption"]
+ ["table-column-group"]
+ ["table-header-group"]
+ ["table-footer-group"]
+ ["table-row-group"]
+ ["table-cell"]
+ ["table-column"]
+ ["table-row"]]]
+
+ [Empty
+ []
+ [["show"]
+ ["hide"]]]
+
+ [Filter
+ []
+ []]
+
+ [Flex_Direction
+ []
+ [["row"]
+ ["row-reverse"]
+ ["column"]
+ ["column-reverse"]]]
+
+ [Flex_Wrap
+ [[no_wrap "nowrap"]]
+ [["wrap"]
+ ["wrap_reverse"]]]
+
+ [Font_Kerning
+ [[auto_kerning "auto"]
+ [normal_kerning "normal"]
+ [no_kerning "none"]]
+ []]
+
+ [Font_Size
+ [[medium_size "medium"]
+ [xx_small_size "xx-small"]
+ [x_small_size "x-small"]
+ [small_size "small"]
+ [large_size "large"]
+ [x_large_size "x-large"]
+ [xx_large_size "xx-large"]
+ [smaller_size "smaller"]
+ [larger_size "larger"]]
+ []]
+
+ [Font_Stretch
+ [[normal_stretch "normal"]]
+ [["condensed"]
+ ["ultra-condensed"]
+ ["extra-condensed"]
+ ["semi-condensed"]
+ ["expanded"]
+ ["semi-expanded"]
+ ["extra-expanded"]
+ ["ultra-expanded"]]]
+
+ [Font_Style
+ [[normal_style "normal"]]
+ [["italic"]
+ ["oblique"]]]
+
+ [Font_Weight
+ [[normal_weight "normal"]
+ [weight_100 "100"]
+ [weight_200 "200"]
+ [weight_300 "300"]
+ [weight_400 "400"]
+ [weight_500 "500"]
+ [weight_600 "600"]
+ [weight_700 "700"]
+ [weight_800 "800"]
+ [weight_900 "900"]]
+ [["bold"]]]
+
+ [Font_Variant
+ [[normal_font "normal"]]
+ [["small-caps"]]]
+
+ [Grid
+ []
+ []]
+
+ [Grid_Content
+ [[auto_content "auto"]]
+ [["max-content"]
+ ["min-content"]]]
+
+ [Grid_Flow
+ [[row_flow "row"]
+ [column_flow "column"]
+ [dense_flow "dense"]
+ [row_dense_flow "row dense"]
+ [column_dense_flow "column dense"]]
+ []]
+
+ [Grid_Span
+ [[auto_span "auto"]]
+ []]
+
+ [Grid_Template
+ []
+ []]
+
+ [Hanging_Punctuation
+ [[no_hanging_punctuation "none"]]
+ [["first"]
+ ["last"]
+ ["allow-end"]
+ ["force-end"]]]
+
+ [Hyphens
+ [[no_hyphens "none"]
+ [manual_hyphens "manual"]
+ [auto_hyphens "auto"]]
+ []]
+
+ [Orientation
+ []
+ [["portrait"]
+ ["landscape"]]]
+
+ [Resolution
+ []
+ []]
+
+ [Scan
+ []
+ [["interlace"]
+ ["progressive"]]]
+
+ [Boolean
+ [[false "0"]
+ [true "1"]]
+ []]
+
+ [Update
+ [[no_update "none"]
+ [slow_update "slow"]
+ [fast_update "fast"]]
+ []]
+
+ [Block_Overflow
+ [[no_block_overflow "none"]
+ [scroll_block_overflow "scroll"]
+ [optional_paged_block_overflow "optional-paged"]
+ [paged_block_overflow "paged"]]
+ []]
+
+ [Inline_Overflow
+ [[no_inline_overflow "none"]
+ [scroll_inline_overflow "scroll"]]
+ []]
+
+ [Display_Mode
+ []
+ [["fullscreen"]
+ ["standalone"]
+ ["minimal-ui"]
+ ["browser"]]]
+
+ [Color_Gamut
+ []
+ [["srgb"]
+ ["p3"]
+ ["rec2020"]]]
+
+ [Inverted_Colors
+ [[no_inverted_colors "none"]
+ [inverted_colors "inverted"]]
+ []]
+
+ [Pointer
+ [[no_pointer "none"]
+ [coarse_pointer "coarse"]
+ [fine_pointer "fine"]]
+ []]
+
+ [Hover
+ [[no_hover "none"]]
+ [["hover"]]]
+
+ [Light
+ [[dim_light "dim"]
+ [normal_light "normal"]
+ [washed_light "washed"]]
+ []]
+
+ [Ratio
+ []
+ []]
+
+ [Scripting
+ [[no_scripting "none"]
+ [initial_scripting_only "initial-only"]
+ [scripting_enabled "enabled"]]
+ []]
+
+ [Motion
+ [[no_motion_preference "no-preference"]
+ [reduced_motion "reduce"]]
+ []]
+
+ [Color_Scheme
+ [[no_color_scheme_preference "no-preference"]
+ [light_color_scheme "light"]
+ [dark_color_scheme "dark"]]
+ []]
+
+ [Isolation
+ [[auto_isolation "auto"]]
+ [["isolate"]]]
+
+ [List_Style_Position
+ []
+ [["inside"]
+ ["outside"]]]
+
+ [List_Style_Type
+ [[no_list_style "none"]]
+ [["disc"]
+ ["armenian"]
+ ["circle"]
+ ["cjk-ideographic"]
+ ["decimal"]
+ ["decimal-leading-zero"]
+ ["georgian"]
+ ["hebrew"]
+ ["hiragana"]
+ ["hiragana-iroha"]
+ ["katakana"]
+ ["katakana-iroha"]
+ ["lower-alpha"]
+ ["lower-greek"]
+ ["lower-latin"]
+ ["lower-roman"]
+ ["square"]
+ ["upper-alpha"]
+ ["upper-greek"]
+ ["upper-latin"]
+ ["upper-roman"]]]
+
+ [Color
+ []
+ []]
+
+ [Overflow
+ [[visible_overflow "visible"]
+ [hidden_overflow "hidden"]
+ [scroll_overflow "scroll"]
+ [auto_overflow "auto"]]
+ []]
+
+ [Page_Break
+ [[auto_page_break "auto"]
+ [always_page_break "always"]
+ [avoid_page_break "avoid"]
+ [left_page_break "left"]
+ [right_page_break "right"]]
+ []]
+
+ [Pointer_Events
+ [[auto_pointer_events "auto"]
+ [no_pointer_events "none"]]
+ []]
+
+ [Position
+ []
+ [["static"]
+ ["absolute"]
+ ["fixed"]
+ ["relative"]
+ ["sticky"]]]
+
+ [Quotes
+ [[no_quotes "none"]]
+ []]
+
+ [Resize
+ [[resize_none "none"]
+ [resize_both "both"]
+ [resize_horizontal "horizontal"]
+ [resize_vertical "vertical"]]
+ []]
+
+ [Scroll_Behavior
+ [[auto_scroll_behavior "auto"]
+ [smooth_scroll_behavior "smooth"]]
+ []]
+
+ [Table_Layout
+ [[auto_table_layout "auto"]
+ [fixed_table_layout "fixed"]]
+ []]
+
+ [Text_Align
+ [[left_text_align "left"]
+ [right_text_align "right"]
+ [center_text_align "center"]
+ [justify_text_align "justify"]]
+ []]
+
+ [Text_Align_Last
+ [[auto_text_align_last "auto"]
+ [left_text_align_last "left"]
+ [right_text_align_last "right"]
+ [center_text_align_last "center"]
+ [justify_text_align_last "justify"]
+ [start_text_align_last "start"]
+ [end_text_align_last "end"]]
+ []]
+
+ [Text_Decoration_Line
+ [[no_text_decoration_line "none"]
+ [underline_text_decoration_line "underline"]
+ [overline_text_decoration_line "overline"]
+ [line_through_text_decoration_line "line-through"]]
+ []]
+
+ [Text_Decoration_Style
+ [[solid_text_decoration_style "solid"]
+ [double_text_decoration_style "double"]
+ [dotted_text_decoration_style "dotted"]
+ [dashed_text_decoration_style "dashed"]
+ [wavy_text_decoration_style "wavy"]]
+ []]
+
+ [Text_Justification
+ [[auto_text_justification "auto"]
+ [inter_word_text_justification "inter-word"]
+ [inter_character_text_justification "inter-character"]
+ [no_text_justification "none"]]
+ []]
+
+ [Text_Overflow
+ [[clip_text_overflow "clip"]
+ [ellipsis_text_overflow "ellipsis"]]
+ []]
+
+ [Text_Transform
+ [[no_text_transform "none"]]
+ [["capitalize"]
+ ["uppercase"]
+ ["lowercase"]]]
+
+ [Transform
+ [[no_transform "none"]]
+ []]
+
+ [Transform_Origin
+ []
+ []]
+
+ [Transform_Style
+ []
+ [["flat"]
+ ["preserve_3d"]]]
+
+ [Transition
+ [[transition_none "none"]
+ [transition_all "all"]]
+ []]
+
+ [Bidi
+ [[bidi_normal "normal"]
+ [bidi_embed "embed"]
+ [bidi_isolate "isolate"]
+ [bidi_isolate_override "isolate-override"]
+ [bidi_plaintext "plaintext"]]
+ [["bidi-override"]]]
+
+ [User_Select
+ [[user_select_auto "auto"]
+ [user_select_none "none"]
+ [user_select_text "text"]
+ [user_select_all "all"]]
+ []]
+
+ [Vertical_Align
+ [[vertical_align_baseline "baseline"]
+ [vertical_align_sub "sub"]
+ [vertical_align_super "super"]
+ [vertical_align_top "top"]
+ [vertical_align_text_top "text-top"]
+ [vertical_align_middle "middle"]
+ [vertical_align_bottom "bottom"]
+ [vertical_align_text_bottom "text-bottom"]]
+ []]
+
+ [White_Space
+ [[normal_white_space "normal"]
+ [no_wrap_white_space "nowrap"]
+ [pre_white_space "pre"]
+ [pre_line_white_space "pre-line"]
+ [pre_wrap_white_space "pre-wrap"]]
+ []]
+
+ [Word_Break
+ [[normal_word_break "normal"]]
+ [["break-all"]
+ ["keep-all"]
+ ["break-word"]]]
+
+ [Word_Wrap
+ [[normal_word_wrap "normal"]
+ [break_word_word_wrap "break-word"]]
+ []]
+
+ [Writing_Mode
+ [[top_to_bottom_writing_mode "horizontal-tb"]
+ [left_to_right_writing_mode "vertical-rl"]
+ [right_to_left_writing_mode "vertical-lr"]]
+ []]
+
+ [Z_Index
+ []
+ []]
+ )
+
+ (def value_separator
+ ",")
+
+ (def (apply name inputs)
+ (-> Text (List Text)
+ Value)
+ (|> inputs
+ (text.interposed ..value_separator)
+ (text.enclosed ["(" ")"])
+ (format name)
+ abstraction))
+
+ (enumeration
+ Step
+ Text
+ step
+ [[start "start"]
+ [end "end"]]
+ [])
+
+ (def .public (steps intervals step)
+ (-> Nat Step
+ (Value Timing))
+ (..apply "steps" (list (%.nat intervals) (..step step))))
+
+ (def .public (cubic_bezier p0 p1 p2 p3)
+ (-> Frac Frac Frac Frac
+ (Value Timing))
+ (|> (list p0 p1 p2 p3)
+ (list#each %number)
+ (..apply "cubic-bezier")))
+
+ (with_template [<name> <brand>]
+ [(def .public <name>
+ (-> Nat
+ (Value <brand>))
+ (|>> %.nat abstraction))]
+
+ [iteration Iteration]
+ [count Count]
+ [slice_number/1 Slice]
+ [span_line Grid_Span]
+ )
+
+ (def .public animation
+ (-> Label
+ (Value Animation))
+ (|>> abstraction))
+
+ (def .public (rgb color)
+ (-> color.Color
+ (Value Color))
+ (let [color (color.rgb color)]
+ (..apply "rgb" (list (%.nat (rgb.red color))
+ (%.nat (rgb.green color))
+ (%.nat (rgb.blue color))))))
+
+ (def .public (rgba pigment)
+ (-> Pigment
+ (Value Color))
+ (let [(open "/[0]") pigment]
+ (..apply "rgba" (list (%.nat (rgb.red /#color))
+ (%.nat (rgb.green /#color))
+ (%.nat (rgb.blue /#color))
+ (if (r.= (of r.interval top) /#alpha)
+ "1.0"
+ (format "0" (%.rev /#alpha)))))))
+
+ (with_template [<name> <suffix>]
+ [(def .public (<name> value)
+ (-> Frac
+ (Value Length))
+ (abstraction (format (%number value) <suffix>)))]
+
+ [em "em"]
+ [ex "ex"]
+ [rem "rem"]
+ [ch "ch"]
+ [vw "vw"]
+ [vh "vh"]
+ [vmin "vmin"]
+ [vmax "vmax"]
+ [% "%"]
+ [cm "cm"]
+ [mm "mm"]
+ [in "in"]
+ [px "px"]
+ [pt "pt"]
+ [pc "pc"]
+ [fr "fr"]
+ )
+
+ (def (%int value)
+ (Format Int)
+ (if (i.< +0 value)
+ (%.int value)
+ (%.nat (.nat value))))
+
+ (with_template [<name> <suffix>]
+ [(def .public (<name> value)
+ (-> Int
+ (Value Time))
+ (abstraction (format (if (i.< +0 value)
+ (%.int value)
+ (%.nat (.nat value)))
+ <suffix>)))]
+
+
+ [seconds "s"]
+ [milli_seconds "ms"]
+ )
+
+ (def .public thickness
+ (-> (Value Length)
+ (Value Thickness))
+ (|>> transmutation))
+
+ (def slice_separator " ")
+
+ (def .public (slice_number/2 horizontal vertical)
+ (-> Nat Nat
+ (Value Slice))
+ (abstraction (format (%.nat horizontal) ..slice_separator
+ (%.nat vertical))))
+
+ (nominal.def .public Stop
+ Text
+
+ (def .public stop
+ (-> (Value Color)
+ Stop)
+ (|>> (representation Value) (abstraction Stop)))
+
+ (def stop_separator
+ " ")
+
+ (def .public (single_stop length color)
+ (-> (Value Length) (Value Color)
+ Stop)
+ (abstraction (format (representation Value color) ..stop_separator
+ (representation Value length))))
+
+ (def .public (double_stop start end color)
+ (-> (Value Length) (Value Length) (Value Color)
+ Stop)
+ (abstraction (format (representation Value color) ..stop_separator
+ (representation Value start) ..stop_separator
+ (representation Value end))))
+
+ (nominal.def .public Hint
+ Text
+
+ (def .public hint
+ (-> (Value Length)
+ Hint)
+ (|>> (representation Value) (abstraction Hint)))
+
+ (def (with_hint [hint stop])
+ (-> [(Maybe Hint) Stop]
+ Text)
+ (when hint
+ {.#None}
+ (representation Stop stop)
+
+ {.#Some hint}
+ (format (representation Hint hint) ..value_separator (representation Stop stop))))))
+
+ (type .public (List/1 a)
+ [a (List a)])
+
+ (nominal.def .public Angle
+ Text
+
+ (def .public angle
+ (-> Angle
+ Text)
+ (|>> representation))
+
+ (def .public (turn value)
+ (-> Rev
+ Angle)
+ (abstraction (format (%.rev value) "turn")))
+
+ (def degree_limit
+ Nat
+ 360)
+
+ (def .public (degree value)
+ (-> Nat
+ Angle)
+ (abstraction (format (%.nat (n.% ..degree_limit value)) "deg")))
+
+ (with_template [<degree> <name>]
+ [(def .public <name>
+ Angle
+ (..degree <degree>))]
+
+ [000 to_top]
+ [090 to_right]
+ [180 to_bottom]
+ [270 to_left]
+ )
+
+ (with_template [<name> <function>]
+ [(def .public (<name> angle start next)
+ (-> Angle Stop (List/1 [(Maybe Hint) Stop])
+ (Value Image))
+ (let [[now after] next]
+ (..apply <function> (list.partial (representation Angle angle)
+ (with_hint now)
+ (list#each with_hint after)))))]
+
+ [linear_gradient "linear-gradient"]
+ [repeating_linear_gradient "repeating-linear-gradient"]
+ )
+ )
+
+ (def percentage_limit
+ Nat
+ (.++ 100))
+
+ (def .public (%% value)
+ (-> Nat
+ (Value Percentage))
+ (abstraction (format (%.nat (n.% percentage_limit value)) "%")))
+
+ (def .public slice_percent/1
+ (-> (Value Percentage)
+ (Value Slice))
+ (|>> transmutation))
+
+ (def .public (slice_percent/2 horizontal vertical)
+ (-> (Value Percentage) (Value Percentage)
+ (Value Slice))
+ (abstraction (format (representation horizontal) ..slice_separator
+ (representation vertical))))
+
+ (with_template [<input> <pre> <function>+]
+ [(`` (with_template [<name> <function>]
+ [(def .public <name>
+ (-> <input>
+ (Value Filter))
+ (|>> <pre> (list) (..apply <function>)))]
+
+ (,, (template.spliced <function>+))))]
+
+ [Nat (<| representation ..px n.frac)
+ [[blur "blur"]]]
+ [Nat (<| ..angle ..degree)
+ [[hue_rotate "hue-rotate"]]]
+ [(Value Percentage) representation
+ [[brightness "brightness"]
+ [contrast "contrast"]
+ [grayscale "grayscale"]
+ [invert "invert"]
+ [opacity "opacity"]
+ [saturate "saturate"]
+ [sepia "sepia"]]]
+ )
+
+ (def .public svg_filter
+ (-> URL
+ (Value Filter))
+ (|>> (list) (..apply "url")))
+
+ (def default_shadow_length
+ (px +0.0))
+
+ (def .public (drop_shadow horizontal vertical blur spread color)
+ (-> (Value Length) (Value Length)
+ (Maybe (Value Length)) (Maybe (Value Length))
+ (Value Color)
+ (Value Filter))
+ (|> (list (representation horizontal)
+ (representation vertical)
+ (|> blur (maybe.else ..default_shadow_length) representation)
+ (|> spread (maybe.else ..default_shadow_length) representation)
+ (representation color))
+ (text.interposed " ")
+ (list)
+ (..apply "drop-shadow")))
+
+ (def length_separator
+ " ")
+
+ (with_template [<name> <type>]
+ [(def .public (<name> horizontal vertical)
+ (-> (Value Length) (Value Length)
+ (Value <type>))
+ (abstraction (format (representation horizontal)
+ ..length_separator
+ (representation vertical))))]
+
+ [location Location]
+ [fit Fit]
+ )
+
+ (def .public (fit/1 length)
+ (-> (Value Length)
+ (Value Fit))
+ (..fit length length))
+
+ (def .public image
+ (-> URL
+ (Value Image))
+ (|>> %.text
+ (list)
+ (..apply "url")))
+
+ (enumeration
+ Shape
+ Text
+ shape
+ [[ellipse_shape "ellipse"]
+ [circle_shape "circle"]]
+ [])
+
+ (enumeration
+ Extent
+ Text
+ extent
+ [[closest_side "closest-side"]
+ [closest_corner "closest-corner"]
+ [farthest_side "farthest-side"]
+ [farthest_corner "farthest-corner"]]
+ [])
+
+ (with_template [<name> <function>]
+ [(def .public (<name> shape extent location start next)
+ (-> Shape (Maybe Extent) (Value Location)
+ Stop (List/1 [(Maybe Hint) Stop])
+ (Value Image))
+ (let [after_extent (format "at " (representation location))
+ with_extent (when extent
+ {.#Some extent}
+ (format (..extent extent) " " after_extent)
+
+ {.#None}
+ after_extent)
+ where (format (..shape shape) " " with_extent)
+ [now after] next]
+ (..apply <function> (list.partial (..shape shape)
+ (with_hint now)
+ (list#each with_hint after)))))]
+
+ [radial_gradient "radial-gradient"]
+ [repeating_radial_gradient "repeating-radial-gradient"]
+ )
+
+ (def .public (shadow horizontal vertical blur spread color inset?)
+ (-> (Value Length) (Value Length)
+ (Maybe (Value Length)) (Maybe (Value Length))
+ (Value Color) Bit
+ (Value Shadow))
+ (let [with_inset (if inset?
+ (list "inset")
+ (list))]
+ (|> (list.partial (representation horizontal)
+ (representation vertical)
+ (|> blur (maybe.else ..default_shadow_length) representation)
+ (|> spread (maybe.else ..default_shadow_length) representation)
+ (representation color)
+ with_inset)
+ (text.interposed " ")
+ abstraction)))
+
+ (type .public Rectangle
+ (Record
+ [#top (Value Length)
+ #right (Value Length)
+ #bottom (Value Length)
+ #left (Value Length)]))
+
+ (def .public (clip rectangle)
+ (-> Rectangle
+ (Value Clip))
+ (`` (..apply "rect" (list (,, (with_template [<side>]
+ [(representation (the <side> rectangle))]
+
+ [#top] [#right] [#bottom] [#left]))))))
+
+ (def .public counter
+ (-> Label
+ (Value Counter))
+ (|>> abstraction))
+
+ (def .public current_count
+ (-> (Value Counter)
+ (Value Content))
+ (|>> representation (list) (..apply "counter")))
+
+ (def .public text
+ (-> Text
+ (Value Content))
+ (|>> %.text abstraction))
+
+ (def .public attribute
+ (-> Label
+ (Value Content))
+ (|>> (list) (..apply "attr")))
+
+ (def .public media
+ (-> URL
+ (Value Content))
+ (|>> (list) (..apply "url")))
+
+ (enumeration
+ Font
+ Text
+ font_name
+ [[serif "serif"]
+ [sans_serif "sans-serif"]
+ [cursive "cursive"]
+ [fantasy "fantasy"]
+ [monospace "monospace"]]
+ [(def .public font
+ (-> Text Font)
+ (|>> %.text abstraction))
+
+ (def .public (font_family options)
+ (-> (List Font) (Value Font))
+ (when options
+ {.#Item _}
+ (|> options
+ (list#each ..font_name)
+ (text.interposed ",")
+ (abstraction Value))
+
+ {.#End}
+ ..initial))])
+
+ (def .public font_size
+ (-> (Value Length)
+ (Value Font_Size))
+ (|>> transmutation))
+
+ (def .public number
+ (-> Frac
+ (Value Number))
+ (|>> %number abstraction))
+
+ (def .public grid
+ (-> Label
+ (Value Grid))
+ (|>> abstraction))
+
+ (def .public fit_content
+ (-> (Value Length)
+ (Value Grid_Content))
+ (|>> representation (list) (..apply "fit-content")))
+
+ (def .public (min_max min max)
+ (-> (Value Grid_Content) (Value Grid_Content)
+ (Value Grid_Content))
+ (..apply "minmax" (list (representation min)
+ (representation max))))
+
+ (def .public grid_span
+ (-> Nat
+ (Value Grid_Span))
+ (|>> %.nat (format "span ") abstraction))
+
+ (def grid_column_separator " ")
+ (def grid_row_separator " ")
+
+ (def .public grid_template
+ (-> (List (List (Maybe (Value Grid))))
+ (Value Grid_Template))
+ (let [empty (is (Value Grid)
+ (abstraction "."))]
+ (|>> (list#each (|>> (list#each (|>> (maybe.else empty)
+ representation))
+ (text.interposed ..grid_column_separator)
+ (text.enclosed ["'" "'"])))
+ (text.interposed ..grid_row_separator)
+ abstraction)))
+
+ (def .public (resolution dpi)
+ (-> Nat
+ (Value Resolution))
+ (abstraction (format (%.nat dpi) "dpi")))
+
+ (def .public (ratio numerator denominator)
+ (-> Nat Nat
+ (Value Ratio))
+ (abstraction (format (%.nat numerator) "/" (%.nat denominator))))
+
+ (enumeration
+ Quote
+ Text
+ quote_text
+ [[double_quote "\0022"]
+ [single_quote "\0027"]
+ [single_left_angle_quote "\2039"]
+ [single_right_angle_quote "\203A"]
+ [double_left_angle_quote "\00AB"]
+ [double_right_angle_quote "\00BB"]
+ [single_left_quote "\2018"]
+ [single_right_quote "\2019"]
+ [double_left_quote "\201C"]
+ [double_right_quote "\201D"]
+ [low_double_quote "\201E"]]
+ [(def .public quote
+ (-> Text Quote)
+ (|>> abstraction))])
+
+ (def quote_separator " ")
+
+ (def .public (quotes [left0 right0] [left1 right1])
+ (-> [Quote Quote] [Quote Quote]
+ (Value Quotes))
+ (|> (list left0 right0 left1 right1)
+ (list#each (|>> ..quote_text %.text))
+ (text.interposed ..quote_separator)
+ abstraction))
+
+ (def .public (matrix_2d [a b] [c d] [tx ty])
+ (-> [Frac Frac]
+ [Frac Frac]
+ [Frac Frac]
+ (Value Transform))
+ (|> (list a b c d tx ty)
+ (list#each %number)
+ (..apply "matrix")))
+
+ (def .public (matrix_3d [a0 b0 c0 d0] [a1 b1 c1 d1] [a2 b2 c2 d2] [a3 b3 c3 d3])
+ (-> [Frac Frac Frac Frac]
+ [Frac Frac Frac Frac]
+ [Frac Frac Frac Frac]
+ [Frac Frac Frac Frac]
+ (Value Transform))
+ (|> (list a0 b0 c0 d0 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3)
+ (list#each %number)
+ (..apply "matrix3d")))
+
+ (with_template [<name> <function> <input_types> <input_values>]
+ [(`` (def .public (<name> [(,, (template.spliced <input_values>))])
+ (-> [(,, (template.spliced <input_types>))]
+ (Value Transform))
+ (|> (list (,, (template.spliced <input_values>)))
+ (list#each %number)
+ (..apply <function>))))]
+
+ [translate_2d "translate" [Frac Frac] [x y]]
+ [translate_3d "translate3d" [Frac Frac Frac] [x y z]]
+ [translate_x "translateX" [Frac] [value]]
+ [translate_y "translateY" [Frac] [value]]
+ [translate_z "translateZ" [Frac] [value]]
+
+ [scale_2d "scale" [Frac Frac] [x y]]
+ [scale_3d "scale3d" [Frac Frac Frac] [x y z]]
+ [scale_x "scaleX" [Frac] [value]]
+ [scale_y "scaleY" [Frac] [value]]
+ [scale_z "scaleZ" [Frac] [value]]
+
+ [perspective "perspective" [Frac] [value]]
+ )
+
+ (with_template [<name> <function> <input_types> <input_values>]
+ [(`` (def .public (<name> [(,, (template.spliced <input_values>))])
+ (-> [(,, (template.spliced <input_types>))]
+ (Value Transform))
+ (|> (list (,, (template.spliced <input_values>)))
+ (list#each ..angle)
+ (..apply <function>))))]
+
+ [rotate_2d "rotate" [Angle] [angle]]
+ [rotate_x "rotateX" [Angle] [angle]]
+ [rotate_y "rotateY" [Angle] [angle]]
+ [rotate_z "rotateZ" [Angle] [angle]]
+
+ [skew "skew" [Angle Angle] [x_angle y_angle]]
+ [skew_x "skewX" [Angle] [angle]]
+ [skew_y "skewY" [Angle] [angle]]
+ )
+
+ (def .public (rotate_3d [x y z angle])
+ (-> [Frac Frac Frac Angle]
+ (Value Transform))
+ (..apply "rotate3d"
+ (list (%number x) (%number y) (%number z) (..angle angle))))
+
+ (def origin_separator " ")
+
+ (def .public (origin_2d x y)
+ (-> (Value Length) (Value Length)
+ (Value Transform_Origin))
+ (abstraction (format (representation x) ..origin_separator
+ (representation y))))
+
+ (def .public (origin_3d x y z)
+ (-> (Value Length) (Value Length) (Value Length)
+ (Value Transform_Origin))
+ (abstraction (format (representation x) ..origin_separator
+ (representation y) ..origin_separator
+ (representation z))))
+
+ (def .public vertical_align
+ (-> (Value Length)
+ (Value Vertical_Align))
+ (|>> transmutation))
+
+ (def .public (z_index index)
+ (-> Int
+ (Value Z_Index))
+ (abstraction (if (i.< +0 index)
+ (%.int index)
+ (%.nat (.nat index)))))
+
+ (with_template [<separator> <type> <multi>]
+ [(def .public (<multi> pre post)
+ (-> (Value <type>) (Value <type>)
+ (Value <type>))
+ (abstraction (format (representation pre)
+ <separator>
+ (representation post))))]
+
+ ["," Image multi_image]
+ ["," Shadow multi_shadow]
+ [" " Content multi_content]
+ )
+
+ ... https://developer.mozilla.org/en-US/docs/Web/CSS/calc()
+ (with_template [<name> <parameter>]
+ [(def .public (<name> parameter subject)
+ (.All (_ kind)
+ (-> (Value <parameter>) (Value (Numeric kind))
+ (Value (Numeric kind))))
+ (|> (format (representation subject)
+ (template.text [" " <name> " "])
+ (representation parameter))
+ (text.enclosed ["calc(" ")"])
+ abstraction))]
+
+ [+ (Numeric kind)]
+ [- (Numeric kind)]
+ [* Number]
+ [/ Number]
+ )
+ )