aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/data/format/css/value.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/library/lux/data/format/css/value.lux')
-rw-r--r--stdlib/source/library/lux/data/format/css/value.lux1329
1 files changed, 1329 insertions, 0 deletions
diff --git a/stdlib/source/library/lux/data/format/css/value.lux b/stdlib/source/library/lux/data/format/css/value.lux
new file mode 100644
index 000000000..f85272a04
--- /dev/null
+++ b/stdlib/source/library/lux/data/format/css/value.lux
@@ -0,0 +1,1329 @@
+(.module:
+ [library
+ [lux (#- All Cursor and static false true)
+ [control
+ [parser
+ ["s" code]]]
+ [data
+ ["." color]
+ ["." product]
+ ["." maybe]
+ [number
+ ["n" nat]
+ ["i" int]
+ ["r" rev]
+ ["f" frac]]
+ ["." text
+ ["%" format (#+ Format format)]]
+ [collection
+ ["." list ("#\." functor)]]]
+ [type
+ abstract]
+ [macro
+ ["." template]
+ ["." code]
+ [syntax (#+ syntax:)]]
+ [world
+ [net (#+ URL)]]]]
+ [//
+ [selector (#+ Label)]])
+
+(syntax: (text-identifier {identifier s.text})
+ (wrap (list (code.local-identifier identifier))))
+
+(template: (enumeration: <abstraction> <representation> <out> <sample>+ <definition>+)
+ (abstract: #export <abstraction>
+ <representation>
+
+ (def: #export <out>
+ (-> <abstraction> <representation>)
+ (|>> :representation))
+
+ (`` (template [<name> <value>]
+ [(def: #export <name> <abstraction> (:abstraction <value>))]
+
+ (~~ (template.splice <sample>+))
+ ))
+
+ (template.splice <definition>+)))
+
+(template: (multi: <multi> <type> <separator>)
+ (def: #export (<multi> pre post)
+ (-> (Value <type>) (Value <type>) (Value <type>))
+ (:abstraction (format (:representation pre)
+ <separator>
+ (:representation post)))))
+
+(def: (%number value)
+ (Format Frac)
+ (let [raw (%.frac value)]
+ (if (f.< +0.0 value)
+ raw
+ (|> raw (text.split 1) maybe.assume product.right))))
+
+(abstract: #export (Value brand)
+ Text
+
+ (def: #export value
+ (-> (Value Any) Text)
+ (|>> :representation))
+
+ (template [<name> <value>]
+ [(def: #export <name> Value (:abstraction <value>))]
+
+ [initial "initial"]
+ [inherit "inherit"]
+ [unset "unset"]
+ )
+
+ (template [<brand> <alias>+ <value>+]
+ [(abstract: #export <brand> Any)
+
+ (`` (template [<name> <value>]
+ [(def: #export <name>
+ (Value <brand>)
+ (:abstraction <value>))]
+
+ (~~ (template.splice <alias>+))))
+
+ (with-expansions [<rows> (template.splice <value>+)]
+ (template [<value>]
+ [(`` (def: #export (~~ (text-identifier <value>))
+ (Value <brand>)
+ (:abstraction <value>)))]
+
+ <rows>))]
+
+ [All
+ []
+ []]
+
+ [Number
+ []
+ []]
+
+ [Length
+ []
+ []]
+
+ [Time
+ []
+ []]
+
+ [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.join-with ..value-separator)
+ (text.enclose ["(" ")"])
+ (format name)
+ :abstraction))
+
+ (enumeration: Step Text
+ step
+ [[start "start"]
+ [end "end"]]
+ [])
+
+ (def: #export (steps intervals step)
+ (-> Nat Step (Value Timing))
+ (..apply "steps" (list (%.nat intervals) (..step step))))
+
+ (def: #export (cubic-bezier p0 p1 p2 p3)
+ (-> Frac Frac Frac Frac (Value Timing))
+ (|> (list p0 p1 p2 p3)
+ (list\map %number)
+ (..apply "cubic-bezier")))
+
+ (template [<name> <brand>]
+ [(def: #export <name>
+ (-> Nat (Value <brand>))
+ (|>> %.nat :abstraction))]
+
+ [iteration Iteration]
+ [count Count]
+ [slice-number/1 Slice]
+ [span-line Grid-Span]
+ )
+
+ (def: #export animation
+ (-> Label (Value Animation))
+ (|>> :abstraction))
+
+ (def: #export (rgb color)
+ (-> color.Color (Value Color))
+ (let [[red green blue] (color.to-rgb color)]
+ (..apply "rgb" (list (%.nat red)
+ (%.nat green)
+ (%.nat blue)))))
+
+ (def: #export (rgba pigment)
+ (-> color.Pigment (Value Color))
+ (let [(^slots [#color.color #color.alpha]) pigment
+ [red green blue] (color.to-rgb color)]
+ (..apply "rgba" (list (%.nat red)
+ (%.nat green)
+ (%.nat blue)
+ (if (r.= (\ r.interval top) alpha)
+ "1.0"
+ (format "0" (%.rev alpha)))))))
+
+ (template [<name> <suffix>]
+ [(def: #export (<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))))
+
+ (template [<name> <suffix>]
+ [(def: #export (<name> value)
+ (-> Int (Value Time))
+ (:abstraction (format (if (i.< +0 value)
+ (%.int value)
+ (%.nat (.nat value)))
+ <suffix>)))]
+
+
+ [seconds "s"]
+ [milli-seconds "ms"]
+ )
+
+ (def: #export thickness
+ (-> (Value Length) (Value Thickness))
+ (|>> :transmutation))
+
+ (def: slice-separator " ")
+
+ (def: #export (slice-number/2 horizontal vertical)
+ (-> Nat Nat (Value Slice))
+ (:abstraction (format (%.nat horizontal) ..slice-separator
+ (%.nat vertical))))
+
+ (abstract: #export Stop
+ Text
+
+ (def: #export stop
+ (-> (Value Color) Stop)
+ (|>> (:representation Value) (:abstraction Stop)))
+
+ (def: stop-separator " ")
+
+ (def: #export (single-stop length color)
+ (-> (Value Length) (Value Color) Stop)
+ (:abstraction (format (:representation Value color) ..stop-separator
+ (:representation Value length))))
+
+ (def: #export (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))))
+
+ (abstract: #export Hint
+ Text
+
+ (def: #export hint
+ (-> (Value Length) Hint)
+ (|>> (:representation Value) (:abstraction Hint)))
+
+ (def: (with-hint [hint stop])
+ (-> [(Maybe Hint) Stop] Text)
+ (case hint
+ #.None
+ (:representation Stop stop)
+
+ (#.Some hint)
+ (format (:representation Hint hint) ..value-separator (:representation Stop stop))))))
+
+ (type: #export (List/1 a)
+ [a (List a)])
+
+ (abstract: #export Angle
+ Text
+
+ (def: #export angle
+ (-> Angle Text)
+ (|>> :representation))
+
+ (def: #export (turn value)
+ (-> Rev Angle)
+ (:abstraction (format (%.rev value) "turn")))
+
+ (def: degree-limit Nat 360)
+
+ (def: #export (degree value)
+ (-> Nat Angle)
+ (:abstraction (format (%.nat (n.% ..degree-limit value)) "deg")))
+
+ (template [<degree> <name>]
+ [(def: #export <name> Angle (..degree <degree>))]
+
+ [000 to-top]
+ [090 to-right]
+ [180 to-bottom]
+ [270 to-left]
+ )
+
+ (template [<name> <function>]
+ [(def: #export (<name> angle start next)
+ (-> Angle Stop (List/1 [(Maybe Hint) Stop]) (Value Image))
+ (let [[now after] next]
+ (..apply <function> (list& (:representation Angle angle)
+ (with-hint now)
+ (list\map with-hint after)))))]
+
+ [linear-gradient "linear-gradient"]
+ [repeating-linear-gradient "repeating-linear-gradient"]
+ )
+ )
+
+ (abstract: #export Percentage
+ Text
+
+ (def: #export percentage
+ (-> Percentage Text)
+ (|>> :representation))
+
+ (def: percentage-limit Nat (.inc 100))
+
+ (def: #export (%% value)
+ (-> Nat Percentage)
+ (:abstraction (format (%.nat (n.% percentage-limit value)) "%")))
+
+ (def: #export slice-percent/1
+ (-> Percentage (Value Slice))
+ (|>> :representation (:abstraction Value)))
+
+ (def: #export (slice-percent/2 horizontal vertical)
+ (-> Percentage Percentage (Value Slice))
+ (:abstraction Value (format (:representation horizontal) ..slice-separator
+ (:representation vertical))))
+
+ (template [<input> <pre> <function>+]
+ [(`` (template [<name> <function>]
+ [(def: #export <name>
+ (-> <input> (Value Filter))
+ (|>> <pre> (list) (..apply <function>)))]
+
+ (~~ (template.splice <function>+))))]
+
+ [Nat (<| (:representation Value) ..px n.frac)
+ [[blur "blur"]]]
+ [Nat (<| ..angle ..degree)
+ [[hue-rotate "hue-rotate"]]]
+ [Percentage (:representation Percentage)
+ [[brightness "brightness"]
+ [contrast "contrast"]
+ [grayscale "grayscale"]
+ [invert "invert"]
+ [opacity "opacity"]
+ [saturate "saturate"]
+ [sepia "sepia"]]]
+ )
+ )
+
+ (def: #export svg-filter
+ (-> URL (Value Filter))
+ (|>> (list) (..apply "url")))
+
+ (def: default-shadow-length (px +0.0))
+
+ (def: #export (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.default ..default-shadow-length) :representation)
+ (|> spread (maybe.default ..default-shadow-length) :representation)
+ (:representation color))
+ (text.join-with " ")
+ (list)
+ (..apply "drop-shadow")))
+
+ (def: length-separator " ")
+
+ (template [<name> <type>]
+ [(def: #export (<name> horizontal vertical)
+ (-> (Value Length) (Value Length) (Value <type>))
+ (:abstraction (format (:representation horizontal)
+ ..length-separator
+ (:representation vertical))))]
+
+ [location Location]
+ [fit Fit]
+ )
+
+ (def: #export (fit/1 length)
+ (-> (Value Length) (Value Fit))
+ (..fit length length))
+
+ (def: #export 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"]]
+ [])
+
+ (template [<name> <function>]
+ [(def: #export (<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 (case extent
+ (#.Some extent)
+ (format (..extent extent) " " after-extent)
+
+ #.None
+ after-extent)
+ where (format (..shape shape) " " with-extent)
+ [now after] next]
+ (..apply <function> (list& (..shape shape)
+ (with-hint now)
+ (list\map with-hint after)))))]
+
+ [radial-gradient "radial-gradient"]
+ [repeating-radial-gradient "repeating-radial-gradient"]
+ )
+
+ (def: #export (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& (:representation horizontal)
+ (:representation vertical)
+ (|> blur (maybe.default ..default-shadow-length) :representation)
+ (|> spread (maybe.default ..default-shadow-length) :representation)
+ (:representation color)
+ with-inset)
+ (text.join-with " ")
+ :abstraction)))
+
+ (type: #export Rectangle
+ {#top (Value Length)
+ #right (Value Length)
+ #bottom (Value Length)
+ #left (Value Length)})
+
+ (def: #export (clip rectangle)
+ (-> Rectangle (Value Clip))
+ (`` (..apply "rect" (list (~~ (template [<side>]
+ [(:representation (get@ <side> rectangle))]
+
+ [#top] [#right] [#bottom] [#left]))))))
+
+ (def: #export counter
+ (-> Label (Value Counter))
+ (|>> :abstraction))
+
+ (def: #export current-count
+ (-> (Value Counter) (Value Content))
+ (|>> :representation (list) (..apply "counter")))
+
+ (def: #export text
+ (-> Text (Value Content))
+ (|>> %.text :abstraction))
+
+ (def: #export attribute
+ (-> Label (Value Content))
+ (|>> (list) (..apply "attr")))
+
+ (def: #export 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: #export font
+ (-> Text Font)
+ (|>> %.text :abstraction))
+
+ (def: #export (font-family options)
+ (-> (List Font) (Value Font))
+ (case options
+ (#.Cons _)
+ (|> options
+ (list\map ..font-name)
+ (text.join-with ",")
+ (:abstraction Value))
+
+ #.Nil
+ ..initial))])
+
+ (def: #export font-size
+ (-> (Value Length) (Value Font-Size))
+ (|>> :transmutation))
+
+ (def: #export number
+ (-> Frac (Value Number))
+ (|>> %number :abstraction))
+
+ (def: #export grid
+ (-> Label (Value Grid))
+ (|>> :abstraction))
+
+ (def: #export fit-content
+ (-> (Value Length) (Value Grid-Content))
+ (|>> :representation (list) (..apply "fit-content")))
+
+ (def: #export (min-max min max)
+ (-> (Value Grid-Content) (Value Grid-Content) (Value Grid-Content))
+ (..apply "minmax" (list (:representation min)
+ (:representation max))))
+
+ (def: #export grid-span
+ (-> Nat (Value Grid-Span))
+ (|>> %.nat (format "span ") :abstraction))
+
+ (def: grid-column-separator " ")
+ (def: grid-row-separator " ")
+
+ (def: #export grid-template
+ (-> (List (List (Maybe (Value Grid)))) (Value Grid-Template))
+ (let [empty (: (Value Grid)
+ (:abstraction "."))]
+ (|>> (list\map (|>> (list\map (|>> (maybe.default empty)
+ :representation))
+ (text.join-with ..grid-column-separator)
+ (text.enclose ["'" "'"])))
+ (text.join-with ..grid-row-separator)
+ :abstraction)))
+
+ (def: #export (resolution dpi)
+ (-> Nat (Value Resolution))
+ (:abstraction (format (%.nat dpi) "dpi")))
+
+ (def: #export (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: #export quote
+ (-> Text Quote)
+ (|>> :abstraction))])
+
+ (def: quote-separator " ")
+
+ (def: #export (quotes [left0 right0] [left1 right1])
+ (-> [Quote Quote] [Quote Quote] (Value Quotes))
+ (|> (list left0 right0 left1 right1)
+ (list\map (|>> ..quote-text %.text))
+ (text.join-with ..quote-separator)
+ :abstraction))
+
+ (def: #export (matrix-2d [a b] [c d] [tx ty])
+ (-> [Frac Frac]
+ [Frac Frac]
+ [Frac Frac]
+ (Value Transform))
+ (|> (list a b c d tx ty)
+ (list\map %number)
+ (..apply "matrix")))
+
+ (def: #export (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\map %number)
+ (..apply "matrix3d")))
+
+ (template [<name> <function> <input-types> <input-values>]
+ [(`` (def: #export (<name> [(~~ (template.splice <input-values>))])
+ (-> [(~~ (template.splice <input-types>))] (Value Transform))
+ (|> (list (~~ (template.splice <input-values>)))
+ (list\map %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]]
+ )
+
+ (template [<name> <function> <input-types> <input-values>]
+ [(`` (def: #export (<name> [(~~ (template.splice <input-values>))])
+ (-> [(~~ (template.splice <input-types>))] (Value Transform))
+ (|> (list (~~ (template.splice <input-values>)))
+ (list\map ..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: #export (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: #export (origin-2d x y)
+ (-> (Value Length) (Value Length) (Value Transform-Origin))
+ (:abstraction (format (:representation x) ..origin-separator
+ (:representation y))))
+
+ (def: #export (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: #export vertical-align
+ (-> (Value Length) (Value Vertical-Align))
+ (|>> :transmutation))
+
+ (def: #export (z-index index)
+ (-> Int (Value Z-Index))
+ (:abstraction (if (i.< +0 index)
+ (%.int index)
+ (%.nat (.nat index)))))
+
+ (multi: multi-image Image ",")
+ (multi: multi-shadow Shadow ",")
+ (multi: multi-content Content " ")
+ )