///|
pub struct Length {
css : String
} derive(Eq, Debug)
///|
pub struct Color {
css : String
} derive(Eq, Debug)
///|
pub struct Time {
css : String
} derive(Eq, Debug)
///|
pub struct Angle {
css : String
} derive(Eq, Debug)
///|
pub(all) enum ValueCategory {
LengthCategory
ColorCategory
NumberCategory
PercentageCategory
LengthPercentageCategory
IntegerCategory
TimeCategory
AngleCategory
ResolutionCategory
UrlCategory
} derive(Eq, Debug)
///|
pub fn ValueCategory::name(self : ValueCategory) -> String {
match self {
LengthCategory => "length"
ColorCategory => "color"
NumberCategory => "number"
PercentageCategory => "percentage"
LengthPercentageCategory => "length-percentage"
IntegerCategory => "integer"
TimeCategory => "time"
AngleCategory => "angle"
ResolutionCategory => "resolution"
UrlCategory => "url"
}
}
///|
pub struct CssVar[T] {
name : String
default_css : String
category : ValueCategory
marker : T?
}
///|
pub(all) struct VarDefinition {
name : String
default_css : String
category : ValueCategory
} derive(Eq, Debug)
///|
pub(all) struct VarOverride {
name : String
value_css : String
category : ValueCategory
} derive(Eq, Debug)
///|
/// Distinguishes a theme token from a runtime-bound custom-property slot.
pub(all) enum VariableRole {
TokenRole
DynamicSlotRole
} derive(Eq, Debug)
///|
/// Erased variable metadata carried by the authoring builder. It never appears
/// in schema-v5 artifacts; the registry lowers it to the existing VariableSet
/// representation before extraction.
pub(all) struct VariableUse {
scope : String
local_name : String
definition : VarDefinition
role : VariableRole
} derive(Eq, Debug)
///|
pub struct Token[T] {
variable : CssVar[T]
scope : String
local_name : String
}
///|
pub struct DynamicSlot[T] {
variable : CssVar[T]
scope : String
local_name : String
}
///|
pub struct VariableScope {
scope : String
}
///|
pub type LengthToken = Token[Length]
///|
pub type ColorToken = Token[Color]
///|
pub type NumberToken = Token[Number]
///|
pub type PercentageToken = Token[Percentage]
///|
pub type LengthPercentageToken = Token[LengthPercentage]
///|
pub type IntegerToken = Token[Integer]
///|
pub type TimeToken = Token[Time]
///|
pub type AngleToken = Token[Angle]
///|
pub type ResolutionToken = Token[Resolution]
///|
pub type UrlToken = Token[Url]
///|
pub type LengthSlot = DynamicSlot[Length]
///|
pub type ColorSlot = DynamicSlot[Color]
///|
pub type NumberSlot = DynamicSlot[Number]
///|
pub type PercentageSlot = DynamicSlot[Percentage]
///|
pub type LengthPercentageSlot = DynamicSlot[LengthPercentage]
///|
pub type IntegerSlot = DynamicSlot[Integer]
///|
pub type TimeSlot = DynamicSlot[Time]
///|
pub type AngleSlot = DynamicSlot[Angle]
///|
pub type ResolutionSlot = DynamicSlot[Resolution]
///|
pub type UrlSlot = DynamicSlot[Url]
///|
pub(all) struct TokenOverride {
variable : VariableUse
override_ : VarOverride
} derive(Eq, Debug)
///|
/// The reviewed value categories that may be used by tokens and dynamic slots.
pub trait CssValue {
fn css_value(Self) -> String
fn value_category(Self) -> ValueCategory
}
///|
pub struct Percentage {
css : String
} derive(Eq, Debug)
///|
pub struct LengthPercentage {
css : String
} derive(Eq, Debug)
///|
pub struct Number {
css : String
} derive(Eq, Debug)
///|
pub struct Integer {
css : String
} derive(Eq, Debug)
///|
pub struct Resolution {
css : String
} derive(Eq, Debug)
///|
pub struct Url {
css : String
} derive(Eq, Debug)
///|
pub(all) enum LengthUnit {
Px
Rem
Em
Ch
Vh
Vw
Vmin
Vmax
Svh
Lvh
Dvh
Cm
Mm
Q
In
Pc
Pt
Ex
Cap
Ic
Rex
Rcap
Rch
Ric
Lh
Rlh
Vi
Vb
Svw
Svi
Svb
Svmin
Svmax
Lvw
Lvi
Lvb
Lvmin
Lvmax
Dvw
Dvi
Dvb
Dvmin
Dvmax
Cqw
Cqh
Cqi
Cqb
Cqmin
Cqmax
} derive(Eq, Debug)
///|
pub struct Ratio {
css : String
} derive(Eq, Debug)
///|
pub struct Position {
css : String
} derive(Eq, Debug)
///|
pub struct BackgroundSize {
css : String
} derive(Eq, Debug)
///|
pub(all) enum RepeatStyle {
Repeat
NoRepeat
RepeatX
RepeatY
Space
Round
} derive(Eq, Debug)
///|
pub struct TransformFunction {
expression : Expression
} derive(Eq, Debug)
///|
pub struct TransformList {
expression : Expression
} derive(Eq, Debug)
///|
pub struct TransformOrigin {
css : String
} derive(Eq, Debug)
///|
pub struct EasingFunction {
css : String
} derive(Eq, Debug)
///|
pub struct GridTrack {
css : String
expression : Expression
kind : TrackKind
} derive(Eq, Debug)
///|
pub struct GridTrackList {
css : String
expression : Expression
tracks : Array[GridTrack]
subgrid : Bool
} derive(Eq, Debug)
///|
pub struct GridLine {
css : String
} derive(Eq, Debug)
///|
pub(all) enum TouchActionPart {
PanX
PanY
PinchZoom
} derive(Eq, Debug)
///|
pub struct TouchAction {
css : String
} derive(Eq, Debug)
///|
pub(all) enum ContainPart {
Size
InlineSize
Layout
Style
Paint
} derive(Eq, Debug)
///|
pub struct Contain {
css : String
} derive(Eq, Debug)
///|
pub(all) enum FontVariantNumericPart {
LiningNums
OldstyleNums
ProportionalNums
TabularNums
DiagonalFractions
StackedFractions
Ordinal
SlashedZero
} derive(Eq, Debug)
///|
pub struct FontVariantNumeric {
css : String
} derive(Eq, Debug)
///|
pub(all) enum LineWidthKeyword {
LineWidthThin
LineWidthMedium
LineWidthThick
} derive(Eq, Debug)
///|
pub struct LineWidth {
css : String
} derive(Eq, Debug)
///|
pub(all) enum LineStyle {
LineStyleNone
LineStyleHidden
LineStyleDotted
LineStyleDashed
LineStyleSolid
LineStyleDouble
LineStyleGroove
LineStyleRidge
LineStyleInset
LineStyleOutset
} derive(Eq, Debug)
///|
pub struct CornerRadius {
expression : Expression
horizontal : Expression
} derive(Eq, Debug)
///|
pub struct BorderSide {
css : String
} derive(Eq, Debug)
///|
pub struct BorderWidths {
css : String
} derive(Eq, Debug)
///|
pub struct BorderStyles {
css : String
} derive(Eq, Debug)
///|
pub struct BorderColors {
css : String
} derive(Eq, Debug)
///|
pub struct OutlineColor {
css : String
} derive(Eq, Debug)
///|
pub(all) enum OutlineStyle {
OutlineStyleNone
OutlineStyleAuto
OutlineStyleDotted
OutlineStyleDashed
OutlineStyleSolid
OutlineStyleDouble
OutlineStyleGroove
OutlineStyleRidge
OutlineStyleInset
OutlineStyleOutset
} derive(Eq, Debug)
///|
pub struct Outline {
css : String
} derive(Eq, Debug)
///|
pub(all) suberror ValueError {
NonFinite(String)
OutOfRange(String)
EmptyUrl
InvalidUrl
EmptyValue(String)
InvalidValue(String)
InvalidCustomPropertyName(String)
} derive(Eq, Debug)
///|
pub(all) struct ValueIssue {
code : String
label : String
} derive(Eq, Debug)
///|
const VALUE_ISSUE_PREFIX : String = "__LAMPCLAW_VALUE_ISSUE__["
///|
const VALUE_ISSUE_SUFFIX : String = "]__"
///|
fn issue_css(code : String, label : String) -> String {
VALUE_ISSUE_PREFIX + code + "|" + label + VALUE_ISSUE_SUFFIX
}
///|
fn error_css(error : ValueError) -> String {
match error {
NonFinite(label) => issue_css("STYLE_VALUE_NON_FINITE", label)
OutOfRange(label) => issue_css("STYLE_VALUE_OUT_OF_RANGE", label)
EmptyUrl => issue_css("STYLE_VALUE_EMPTY", "url")
InvalidUrl => issue_css("STYLE_URL_INVALID", "url")
EmptyValue(label) => issue_css("STYLE_VALUE_EMPTY", label)
InvalidValue(label) => issue_css("STYLE_VALUE_INVALID", label)
InvalidCustomPropertyName(label) => issue_css("STYLE_VARIABLE_NAME", label)
}
}
///|
pub fn value_issues(css : String) -> Array[ValueIssue] {
let issues : Array[ValueIssue] = []
let segments = css.split(VALUE_ISSUE_PREFIX).to_array()
for index = 1; index < segments.length(); index = index + 1 {
let segment = segments[index].to_owned()
match segment.find(VALUE_ISSUE_SUFFIX) {
Some(end) => {
let payload = segment[:end].to_owned()
match payload.find("|") {
Some(separator) =>
issues.push({
code: payload[:separator].to_owned(),
label: payload[separator + 1:].to_owned(),
})
None => ()
}
}
None => ()
}
}
issues
}
///|
/// Adds constraints belonging to an individual property without narrowing the
/// shared value category. Negative percentages remain valid for other uses.
pub fn property_value_issues(
property : String,
css : String,
) -> Array[ValueIssue] {
let issues = value_issues(css)
if !issues.is_empty() {
return issues
}
let value = css.trim().to_owned()
if common_value_property(property) {
if value.has_prefix("-") {
issues.push({
code: "STYLE_VALUE_OUT_OF_RANGE",
label: property + " must be nonnegative",
})
}
if !common_property_keyword_valid(property, value) {
issues.push({
code: "STYLE_VALUE_KEYWORD",
label: "Invalid keyword for " + property,
})
}
return issues
}
if property != "fontWidth" && property != "font-width" {
return issues
}
if !value.has_suffix("%") {
return issues
}
let percentage = @string.parse_double(value[:value.length() - 1]) catch {
_ => {
issues.push({
code: "STYLE_VALUE_INVALID",
label: "font-width percentage",
})
return issues
}
}
if percentage.is_nan() || percentage.is_pos_inf() || percentage.is_neg_inf() {
issues.push({
code: "STYLE_VALUE_NON_FINITE",
label: "font-width percentage",
})
} else if percentage < 0 {
issues.push({
code: "STYLE_VALUE_OUT_OF_RANGE",
label: "font-width percentage",
})
}
issues
}
///|
fn finite(value : Double, label : String) -> Double raise ValueError {
if value.is_nan() || value.is_pos_inf() || value.is_neg_inf() {
raise NonFinite(label)
}
value
}
///|
pub fn px(value : Int32) -> Length {
{ css: if value == 0 { "0" } else { value.to_string() + "px" }, }
}
///|
fn LengthUnit::suffix(self : LengthUnit) -> String {
match self {
Px => "px"
Rem => "rem"
Em => "em"
Ch => "ch"
Vh => "vh"
Vw => "vw"
Vmin => "vmin"
Vmax => "vmax"
Svh => "svh"
Lvh => "lvh"
Dvh => "dvh"
Cm => "cm"
Mm => "mm"
Q => "Q"
In => "in"
Pc => "pc"
Pt => "pt"
Ex => "ex"
Cap => "cap"
Ic => "ic"
Rex => "rex"
Rcap => "rcap"
Rch => "rch"
Ric => "ric"
Lh => "lh"
Rlh => "rlh"
Vi => "vi"
Vb => "vb"
Svw => "svw"
Svi => "svi"
Svb => "svb"
Svmin => "svmin"
Svmax => "svmax"
Lvw => "lvw"
Lvi => "lvi"
Lvb => "lvb"
Lvmin => "lvmin"
Lvmax => "lvmax"
Dvw => "dvw"
Dvi => "dvi"
Dvb => "dvb"
Dvmin => "dvmin"
Dvmax => "dvmax"
Cqw => "cqw"
Cqh => "cqh"
Cqi => "cqi"
Cqb => "cqb"
Cqmin => "cqmin"
Cqmax => "cqmax"
}
}
///|
pub fn length(value : Double, unit : LengthUnit) -> Length raise ValueError {
let value = finite(value, "length")
{ css: if value == 0.0 { "0" } else { value.to_string() + unit.suffix() }, }
}
///|
pub fn rem(value : Double) -> Length raise ValueError {
length(value, Rem)
}
///|
pub fn em(value : Double) -> Length raise ValueError {
length(value, Em)
}
///|
pub fn ch(value : Double) -> Length raise ValueError {
length(value, Ch)
}
///|
pub fn vmin(value : Double) -> Length raise ValueError {
length(value, Vmin)
}
///|
pub fn vmax(value : Double) -> Length raise ValueError {
length(value, Vmax)
}
///|
pub fn svh(value : Double) -> Length raise ValueError {
length(value, Svh)
}
///|
pub fn lvh(value : Double) -> Length raise ValueError {
length(value, Lvh)
}
///|
pub fn dvh(value : Double) -> Length raise ValueError {
length(value, Dvh)
}
///|
pub fn percent(value : Int32) -> Length {
{ css: value.to_string() + "%", }
}
///|
pub fn vh(value : Int32) -> Length {
{ css: if value == 0 { "0" } else { value.to_string() + "vh" }, }
}
///|
pub fn vw(value : Int32) -> Length {
{ css: if value == 0 { "0" } else { value.to_string() + "vw" }, }
}
///|
pub fn zero() -> Length {
{ css: "0", }
}
///|
pub fn auto() -> Length {
{ css: "auto", }
}
///|
pub fn rgb(red : Int32, green : Int32, blue : Int32) -> Color {
{
css: "rgb(" +
red.to_string() +
" " +
green.to_string() +
" " +
blue.to_string() +
")",
}
}
///|
pub fn rgba(
red : Int32,
green : Int32,
blue : Int32,
alpha : Double,
) -> Color raise ValueError {
let alpha = finite(alpha, "alpha")
if alpha < 0.0 || alpha > 1.0 {
raise OutOfRange("alpha")
}
{
css: "rgb(" +
red.to_string() +
" " +
green.to_string() +
" " +
blue.to_string() +
" / " +
alpha.to_string() +
")",
}
}
///|
pub fn transparent() -> Color {
{ css: "transparent", }
}
///|
fn valid_hex_digit(value : Int32) -> Bool {
(value >= 48 && value <= 57) ||
(value >= 65 && value <= 70) ||
(value >= 97 && value <= 102)
}
///|
pub fn hex_color(value : String) -> Color raise ValueError {
let value = value.trim().to_owned()
let digits = if value.has_prefix("#") { value[1:].to_owned() } else { value }
if digits.length() != 3 &&
digits.length() != 4 &&
digits.length() != 6 &&
digits.length() != 8 {
raise InvalidValue("hex-color")
}
for i = 0; i < digits.length(); i = i + 1 {
if !valid_hex_digit(digits.unsafe_get(i).to_int()) {
raise InvalidValue("hex-color")
}
}
{ css: "#" + digits, }
}
///|
pub fn hsl(
hue : Double,
saturation : Double,
lightness : Double,
) -> Color raise ValueError {
let hue = finite(hue, "hue")
let saturation = finite(saturation, "saturation")
let lightness = finite(lightness, "lightness")
if saturation < 0.0 ||
saturation > 100.0 ||
lightness < 0.0 ||
lightness > 100.0 {
raise OutOfRange("hsl")
}
{
css: "hsl(" +
hue.to_string() +
" " +
saturation.to_string() +
"% " +
lightness.to_string() +
"%)",
}
}
///|
pub fn ms(value : Int32) -> Time {
{ css: value.to_string() + "ms", }
}
///|
pub fn seconds(value : Double) -> Time raise ValueError {
{ css: finite(value, "seconds").to_string() + "s", }
}
///|
pub fn deg(value : Double) -> Angle raise ValueError {
{ css: finite(value, "degrees").to_string() + "deg", }
}
///|
pub fn turn(value : Double) -> Angle raise ValueError {
{ css: finite(value, "turns").to_string() + "turn", }
}
///|
pub fn percentage(value : Double) -> Percentage raise ValueError {
{ css: finite(value, "percentage").to_string() + "%", }
}
///|
pub fn length_percentage_from_length(value : Length) -> LengthPercentage {
{ css: value.css, }
}
///|
pub fn length_percentage_from_percentage(
value : Percentage,
) -> LengthPercentage {
{ css: value.css, }
}
///|
pub fn Length::as_length_percentage(self : Length) -> LengthPercentage {
length_percentage_from_length(self)
}
///|
pub fn Percentage::as_length_percentage(self : Percentage) -> LengthPercentage {
length_percentage_from_percentage(self)
}
///|
pub fn number(value : Double) -> Number raise ValueError {
{ css: finite(value, "number").to_string(), }
}
///|
pub fn integer(value : Int32) -> Integer {
{ css: value.to_string(), }
}
///|
pub fn dpi(value : Double) -> Resolution raise ValueError {
let value = finite(value, "resolution")
if value <= 0.0 {
raise OutOfRange("resolution")
}
{ css: value.to_string() + "dpi", }
}
///|
pub fn dppx(value : Double) -> Resolution raise ValueError {
let value = finite(value, "resolution")
if value <= 0.0 {
raise OutOfRange("resolution")
}
{ css: value.to_string() + "dppx", }
}
///|
pub fn url(value : String) -> Url raise ValueError {
let value = value.trim().to_owned()
if value.is_empty() {
raise EmptyUrl
}
if value.contains("\"") ||
value.contains("\\") ||
value.contains("{") ||
value.contains("}") ||
value.contains("\n") ||
value.contains("\r") {
raise InvalidUrl
}
{ css: "url(\"" + value + "\")", }
}
///|
pub fn ratio(width : Int32, height : Int32) -> Ratio raise ValueError {
if width <= 0 || height <= 0 {
raise OutOfRange("ratio")
}
{ css: width.to_string() + " / " + height.to_string(), }
}
///|
pub fn ratio_auto() -> Ratio {
{ css: "auto", }
}
///|
pub fn position(x : LengthPercentage, y : LengthPercentage) -> Position {
{ css: x.css + " " + y.css, }
}
///|
pub fn position_center() -> Position {
{ css: "center", }
}
///|
pub fn background_cover() -> BackgroundSize {
{ css: "cover", }
}
///|
pub fn background_contain() -> BackgroundSize {
{ css: "contain", }
}
///|
pub fn background_size(
width : LengthPercentage,
height : LengthPercentage,
) -> BackgroundSize {
{ css: width.css + " " + height.css, }
}
///|
pub fn RepeatStyle::to_css(self : RepeatStyle) -> String {
match self {
Repeat => "repeat"
NoRepeat => "no-repeat"
RepeatX => "repeat-x"
RepeatY => "repeat-y"
Space => "space"
Round => "round"
}
}
///|
pub fn translate(
x : LengthPercentage,
y : LengthPercentage,
) -> TransformFunction {
{
expression: literal_expression(
"translate(" + x.css + ", " + y.css + ")",
"transform",
),
}
}
///|
pub fn rotate_transform(value : Angle) -> TransformFunction {
{ expression: literal_expression("rotate(" + value.css + ")", "transform"), }
}
///|
pub fn scale_transform(
x : Double,
y~ : Double? = None,
) -> TransformFunction raise ValueError {
let x = finite(x, "scale-x")
let values = match y {
Some(value) => x.to_string() + ", " + finite(value, "scale-y").to_string()
None => x.to_string()
}
{ expression: literal_expression("scale(" + values + ")", "transform"), }
}
///|
pub fn transform_list(
functions : Array[TransformFunction],
) -> TransformList raise ValueError {
if functions.is_empty() {
raise EmptyValue("transform-list")
}
{
expression: group_expression(
"transform",
"",
functions.map(item => item.expression),
" ",
"",
),
}
}
///|
pub fn transform_none() -> TransformList {
{ expression: literal_expression("none", "transform"), }
}
///|
pub fn transform_origin(
position : Position,
z~ : Length? = None,
) -> TransformOrigin {
let suffix = match z {
Some(value) => " " + value.css
None => ""
}
{ css: position.css + suffix, }
}
///|
pub fn ease() -> EasingFunction {
{ css: "ease", }
}
///|
pub fn linear_easing() -> EasingFunction {
{ css: "linear", }
}
///|
pub fn cubic_bezier(
x1 : Double,
y1 : Double,
x2 : Double,
y2 : Double,
) -> EasingFunction raise ValueError {
let x1 = finite(x1, "x1")
let y1 = finite(y1, "y1")
let x2 = finite(x2, "x2")
let y2 = finite(y2, "y2")
if x1 < 0.0 || x1 > 1.0 || x2 < 0.0 || x2 > 1.0 {
raise OutOfRange("cubic-bezier-x")
}
{
css: "cubic-bezier(" +
[x1, y1, x2, y2].map(value => value.to_string()).join(", ") +
")",
}
}
///|
pub fn steps(
count : Int32,
at_start~ : Bool = false,
) -> EasingFunction raise ValueError {
if count <= 0 {
raise OutOfRange("steps")
}
{
css: "steps(" +
count.to_string() +
", " +
(if at_start { "start" } else { "end" }) +
")",
}
}
///|
pub fn fr(value : Double) -> GridTrack raise ValueError {
let value = finite(value, "fr")
if value < 0.0 {
raise OutOfRange("fr")
}
make_track(
literal_expression(value.to_string() + "fr", "grid-track"),
Flexible,
)
}
///|
pub fn[T : LengthPercentageMathInput] track_length(value : T) -> GridTrack {
make_track(
value.length_percentage_math().expression.constrain("nonnegative"),
Fixed,
)
}
///|
pub fn minmax(minimum : GridTrack, maximum : GridTrack) -> GridTrack {
if !minimum.is_breadth() || !maximum.is_breadth() || minimum.kind == Flexible {
return invalid_track(
"minmax requires an inflexible minimum and track breadth maximum",
)
}
make_track(
group_expression(
"grid-track",
"minmax(",
[minimum.expression, maximum.expression],
", ",
")",
),
MinMax(minimum.is_fixed() || maximum.is_fixed()),
)
}
///|
pub fn grid_tracks(tracks : Array[GridTrack]) -> GridTrackList raise ValueError {
if tracks.is_empty() {
raise EmptyValue("grid-tracks")
}
make_tracks(tracks)
}
///|
pub fn repeat_tracks(
count : Int32,
tracks : GridTrackList,
) -> GridTrack raise ValueError {
if count <= 0 {
raise OutOfRange("repeat-tracks")
}
make_repeat(count.to_string(), tracks, false)
}
///|
pub fn grid_auto() -> GridLine {
{ css: "auto", }
}
///|
pub fn grid_line(value : Int32) -> GridLine raise ValueError {
if value == 0 {
raise OutOfRange("grid-line")
}
{ css: value.to_string(), }
}
///|
pub fn grid_span(value : Int32) -> GridLine raise ValueError {
if value <= 0 {
raise OutOfRange("grid-span")
}
{ css: "span " + value.to_string(), }
}
///|
pub fn named_grid_line(value : String) -> GridLine raise ValueError {
let value = value.trim().to_owned()
if !valid_name_part(value) {
raise InvalidValue("grid-line-name")
}
{ css: value, }
}
///|
pub fn touch_auto() -> TouchAction {
{ css: "auto", }
}
///|
pub fn touch_none() -> TouchAction {
{ css: "none", }
}
///|
pub fn touch_action(
parts : Array[TouchActionPart],
) -> TouchAction raise ValueError {
if parts.is_empty() {
raise EmptyValue("touch-action")
}
let values : Array[String] = []
for part in parts {
let value = match part {
PanX => "pan-x"
PanY => "pan-y"
PinchZoom => "pinch-zoom"
}
if !values.contains(value) {
values.push(value)
}
}
{ css: values.join(" "), }
}
///|
pub fn contain_none() -> Contain {
{ css: "none", }
}
///|
pub fn contain_strict() -> Contain {
{ css: "strict", }
}
///|
pub fn contain(parts : Array[ContainPart]) -> Contain raise ValueError {
if parts.is_empty() {
raise EmptyValue("contain")
}
let values : Array[String] = []
for part in parts {
let value = match part {
Size => "size"
InlineSize => "inline-size"
Layout => "layout"
Style => "style"
Paint => "paint"
}
if !values.contains(value) {
values.push(value)
}
}
{ css: values.join(" "), }
}
///|
pub fn font_variant_numeric_normal() -> FontVariantNumeric {
{ css: "normal", }
}
///|
pub fn font_variant_numeric(
parts : Array[FontVariantNumericPart],
) -> FontVariantNumeric raise ValueError {
if parts.is_empty() {
raise EmptyValue("font-variant-numeric")
}
let values : Array[String] = []
for part in parts {
let value = match part {
LiningNums => "lining-nums"
OldstyleNums => "oldstyle-nums"
ProportionalNums => "proportional-nums"
TabularNums => "tabular-nums"
DiagonalFractions => "diagonal-fractions"
StackedFractions => "stacked-fractions"
Ordinal => "ordinal"
SlashedZero => "slashed-zero"
}
if !values.contains(value) {
values.push(value)
}
}
{ css: values.join(" "), }
}
///|
fn non_negative_dimension_css(value : String) -> Bool {
!value.is_empty() &&
value != "auto" &&
!value.has_prefix("-") &&
!value.has_prefix("var(") &&
value.unsafe_get(value.length() - 1).to_int() != 37
}
///|
pub fn line_width_from_length(value : Length) -> LineWidth raise ValueError {
if !non_negative_dimension_css(value.css) {
raise InvalidValue("line-width")
}
{ css: value.css, }
}
///|
pub fn Length::as_line_width(self : Length) -> LineWidth {
authored_line_width_from_length(self)
}
///|
pub fn line_width_keyword(value : LineWidthKeyword) -> LineWidth {
{
css: match value {
LineWidthThin => "thin"
LineWidthMedium => "medium"
LineWidthThick => "thick"
},
}
}
///|
pub fn LineStyle::to_css(self : LineStyle) -> String {
match self {
LineStyleNone => "none"
LineStyleHidden => "hidden"
LineStyleDotted => "dotted"
LineStyleDashed => "dashed"
LineStyleSolid => "solid"
LineStyleDouble => "double"
LineStyleGroove => "groove"
LineStyleRidge => "ridge"
LineStyleInset => "inset"
LineStyleOutset => "outset"
}
}
///|
pub fn[T : BoxSizeValueInput] corner_radius(
horizontal : T,
vertical~ : LengthPercentage? = None,
) -> CornerRadius {
let horizontal = radius_operand(horizontal.value_expression())
let value : CornerRadius = { expression: horizontal, horizontal, }
match vertical {
Some(vertical) => value.vertical(vertical)
None => value
}
}
///|
pub fn border_side(
width~ : LineWidth? = None,
style~ : LineStyle? = None,
color~ : Color? = None,
) -> BorderSide raise ValueError {
let values : Array[String] = []
match width {
Some(value) => values.push(value.css)
None => ()
}
match style {
Some(value) => values.push(value.to_css())
None => ()
}
match color {
Some(value) => values.push(value.css)
None => ()
}
if values.is_empty() {
raise EmptyValue("border-side")
}
{ css: values.join(" "), }
}
///|
pub fn border_widths(
first : LineWidth,
second~ : LineWidth? = None,
) -> BorderWidths {
{
css: match second {
Some(value) => first.css + " " + value.css
None => first.css
},
}
}
///|
pub fn border_styles(
first : LineStyle,
second~ : LineStyle? = None,
) -> BorderStyles {
{
css: match second {
Some(value) => first.to_css() + " " + value.to_css()
None => first.to_css()
},
}
}
///|
pub fn border_colors(first : Color, second~ : Color? = None) -> BorderColors {
{
css: match second {
Some(value) => first.css + " " + value.css
None => first.css
},
}
}
///|
pub fn outline_color_from_color(value : Color) -> OutlineColor {
{ css: value.css, }
}
///|
pub fn Color::as_outline_color(self : Color) -> OutlineColor {
outline_color_from_color(self)
}
///|
pub fn outline_auto_color() -> OutlineColor {
{ css: "auto", }
}
///|
pub fn OutlineStyle::to_css(self : OutlineStyle) -> String {
match self {
OutlineStyleNone => "none"
OutlineStyleAuto => "auto"
OutlineStyleDotted => "dotted"
OutlineStyleDashed => "dashed"
OutlineStyleSolid => "solid"
OutlineStyleDouble => "double"
OutlineStyleGroove => "groove"
OutlineStyleRidge => "ridge"
OutlineStyleInset => "inset"
OutlineStyleOutset => "outset"
}
}
///|
pub fn outline(
width~ : LineWidth? = None,
style~ : OutlineStyle? = None,
color~ : OutlineColor? = None,
) -> Outline raise ValueError {
let values : Array[String] = []
match width {
Some(value) => values.push(value.css)
None => ()
}
match style {
Some(value) => values.push(value.to_css())
None => ()
}
match color {
Some(value) => values.push(value.css)
None => ()
}
if values.is_empty() {
raise EmptyValue("outline")
}
{ css: values.join(" "), }
}
///|
fn valid_name_part(value : String) -> Bool {
if value.is_empty() {
return false
}
let mut has_letter = false
for i = 0; i < value.length(); i = i + 1 {
let code = value.unsafe_get(i).to_int()
if code >= 97 && code <= 122 {
has_letter = true
} else if !(code >= 48 && code <= 57) && code != 45 {
return false
}
}
has_letter
}
///|
fn[T] scoped_var(
scope : String,
name : String,
default_css : String,
category : ValueCategory,
) -> CssVar[T] raise ValueError {
let scope = scope.trim().to_owned()
let name = name.trim().to_owned()
if !valid_name_part(scope) || !valid_name_part(name) {
raise InvalidCustomPropertyName(scope + ":" + name)
}
{ name: "--" + scope + "-" + name, default_css, category, marker: None, }
}
///|
pub fn length_var(
scope : String,
name : String,
default : Length,
) -> CssVar[Length] raise ValueError {
scoped_var(scope, name, default.css, LengthCategory)
}
///|
pub fn color_var(
scope : String,
name : String,
default : Color,
) -> CssVar[Color] raise ValueError {
scoped_var(scope, name, default.css, ColorCategory)
}
///|
pub fn number_var(
scope : String,
name : String,
default : Number,
) -> CssVar[Number] raise ValueError {
scoped_var(scope, name, default.css, NumberCategory)
}
///|
pub fn percentage_var(
scope : String,
name : String,
default : Percentage,
) -> CssVar[Percentage] raise ValueError {
scoped_var(scope, name, default.css, PercentageCategory)
}
///|
pub fn[T] CssVar::definition(self : CssVar[T]) -> VarDefinition {
{ name: self.name, default_css: self.default_css, category: self.category, }
}
///|
pub fn override_length(
variable : CssVar[Length],
value : Length,
) -> VarOverride {
{ name: variable.name, value_css: value.css, category: LengthCategory, }
}
///|
pub fn override_color(variable : CssVar[Color], value : Color) -> VarOverride {
{ name: variable.name, value_css: value.css, category: ColorCategory, }
}
///|
pub fn override_number(
variable : CssVar[Number],
value : Number,
) -> VarOverride {
{ name: variable.name, value_css: value.css, category: NumberCategory, }
}
///|
pub fn override_percentage(
variable : CssVar[Percentage],
value : Percentage,
) -> VarOverride {
{ name: variable.name, value_css: value.css, category: PercentageCategory, }
}
///|
pub fn Length::to_css(self : Length) -> String {
self.css
}
///|
pub fn Color::to_css(self : Color) -> String {
self.css
}
///|
pub fn Time::to_css(self : Time) -> String {
self.css
}
///|
pub fn Angle::to_css(self : Angle) -> String {
self.css
}
///|
pub fn Percentage::to_css(self : Percentage) -> String {
self.css
}
///|
pub fn LengthPercentage::to_css(self : LengthPercentage) -> String {
self.css
}
///|
pub fn Number::to_css(self : Number) -> String {
self.css
}
///|
pub fn Integer::to_css(self : Integer) -> String {
self.css
}
///|
pub fn Resolution::to_css(self : Resolution) -> String {
self.css
}
///|
pub fn Url::to_css(self : Url) -> String {
self.css
}
///|
pub fn Ratio::to_css(self : Ratio) -> String {
self.css
}
///|
pub fn Position::to_css(self : Position) -> String {
self.css
}
///|
pub fn BackgroundSize::to_css(self : BackgroundSize) -> String {
self.css
}
///|
pub fn TransformList::to_css(self : TransformList) -> String {
self.expression.to_css()
}
///|
pub fn TransformOrigin::to_css(self : TransformOrigin) -> String {
self.css
}
///|
pub fn EasingFunction::to_css(self : EasingFunction) -> String {
self.css
}
///|
pub fn GridTrackList::to_css(self : GridTrackList) -> String {
self.css
}
///|
pub fn GridLine::to_css(self : GridLine) -> String {
self.css
}
///|
pub fn TouchAction::to_css(self : TouchAction) -> String {
self.css
}
///|
pub fn Contain::to_css(self : Contain) -> String {
self.css
}
///|
pub fn FontVariantNumeric::to_css(self : FontVariantNumeric) -> String {
self.css
}
///|
pub fn LineWidth::to_css(self : LineWidth) -> String {
self.css
}
///|
pub fn CornerRadius::to_css(self : CornerRadius) -> String {
self.expression.to_css()
}
///|
pub fn BorderSide::to_css(self : BorderSide) -> String {
self.css
}
///|
pub fn BorderWidths::to_css(self : BorderWidths) -> String {
self.css
}
///|
pub fn BorderStyles::to_css(self : BorderStyles) -> String {
self.css
}
///|
pub fn BorderColors::to_css(self : BorderColors) -> String {
self.css
}
///|
pub fn OutlineColor::to_css(self : OutlineColor) -> String {
self.css
}
///|
pub fn Outline::to_css(self : Outline) -> String {
self.css
}
///|
pub fn[T] CssVar::name(self : CssVar[T]) -> String {
self.name
}
///|
pub fn[T] CssVar::default_css(self : CssVar[T]) -> String {
self.default_css
}
///|
pub fn var_length(value : CssVar[Length]) -> Length {
{ css: "var(" + value.name + ")", }
}
///|
pub fn var_color(value : CssVar[Color]) -> Color {
{ css: "var(" + value.name + ")", }
}
///|
fn[T] authored_scoped_var(
scope : String,
name : String,
default_css : String,
category : ValueCategory,
) -> CssVar[T] {
scoped_var(scope, name, default_css, category) catch {
error =>
{
name: "--invalid-variable",
default_css: error_css(error),
category,
marker: None,
}
}
}
///|
fn[T] token(
scope : String,
name : String,
default_css : String,
category : ValueCategory,
) -> Token[T] {
{
variable: authored_scoped_var(scope, name, default_css, category),
scope: scope.trim().to_owned(),
local_name: name.trim().to_owned(),
}
}
///|
fn[T] dynamic_slot(
scope : String,
name : String,
default_css : String,
category : ValueCategory,
) -> DynamicSlot[T] {
{
variable: authored_scoped_var(scope, name, default_css, category),
scope: scope.trim().to_owned(),
local_name: name.trim().to_owned(),
}
}
///|
pub fn variable_scope(scope : String) -> VariableScope {
{ scope, }
}
///|
pub fn length_token(
scope : String,
name : String,
default : Length,
) -> Token[Length] {
token(scope, name, default.css, LengthCategory)
}
///|
pub fn color_token(
scope : String,
name : String,
default : Color,
) -> Token[Color] {
token(scope, name, default.css, ColorCategory)
}
///|
pub fn number_token(
scope : String,
name : String,
default : Number,
) -> Token[Number] {
token(scope, name, default.css, NumberCategory)
}
///|
pub fn percentage_token(
scope : String,
name : String,
default : Percentage,
) -> Token[Percentage] {
token(scope, name, default.css, PercentageCategory)
}
///|
pub fn length_percentage_token(
scope : String,
name : String,
default : LengthPercentage,
) -> Token[LengthPercentage] {
token(scope, name, default.css, LengthPercentageCategory)
}
///|
pub fn integer_token(
scope : String,
name : String,
default : Integer,
) -> Token[Integer] {
token(scope, name, default.css, IntegerCategory)
}
///|
pub fn time_token(scope : String, name : String, default : Time) -> Token[Time] {
token(scope, name, default.css, TimeCategory)
}
///|
pub fn angle_token(
scope : String,
name : String,
default : Angle,
) -> Token[Angle] {
token(scope, name, default.css, AngleCategory)
}
///|
pub fn resolution_token(
scope : String,
name : String,
default : Resolution,
) -> Token[Resolution] {
token(scope, name, default.css, ResolutionCategory)
}
///|
pub fn url_token(scope : String, name : String, default : Url) -> Token[Url] {
token(scope, name, default.css, UrlCategory)
}
///|
pub fn length_slot(
scope : String,
name : String,
default : Length,
) -> DynamicSlot[Length] {
dynamic_slot(scope, name, default.css, LengthCategory)
}
///|
pub fn color_slot(
scope : String,
name : String,
default : Color,
) -> DynamicSlot[Color] {
dynamic_slot(scope, name, default.css, ColorCategory)
}
///|
pub fn number_slot(
scope : String,
name : String,
default : Number,
) -> DynamicSlot[Number] {
dynamic_slot(scope, name, default.css, NumberCategory)
}
///|
pub fn percentage_slot(
scope : String,
name : String,
default : Percentage,
) -> DynamicSlot[Percentage] {
dynamic_slot(scope, name, default.css, PercentageCategory)
}
///|
pub fn length_percentage_slot(
scope : String,
name : String,
default : LengthPercentage,
) -> DynamicSlot[LengthPercentage] {
dynamic_slot(scope, name, default.css, LengthPercentageCategory)
}
///|
pub fn integer_slot(
scope : String,
name : String,
default : Integer,
) -> DynamicSlot[Integer] {
dynamic_slot(scope, name, default.css, IntegerCategory)
}
///|
pub fn time_slot(
scope : String,
name : String,
default : Time,
) -> DynamicSlot[Time] {
dynamic_slot(scope, name, default.css, TimeCategory)
}
///|
pub fn angle_slot(
scope : String,
name : String,
default : Angle,
) -> DynamicSlot[Angle] {
dynamic_slot(scope, name, default.css, AngleCategory)
}
///|
pub fn resolution_slot(
scope : String,
name : String,
default : Resolution,
) -> DynamicSlot[Resolution] {
dynamic_slot(scope, name, default.css, ResolutionCategory)
}
///|
pub fn url_slot(
scope : String,
name : String,
default : Url,
) -> DynamicSlot[Url] {
dynamic_slot(scope, name, default.css, UrlCategory)
}
///|
pub fn VariableScope::length_token(
self : VariableScope,
name : String,
default : Length,
) -> LengthToken {
length_token(self.scope, name, default)
}
///|
pub fn VariableScope::color_token(
self : VariableScope,
name : String,
default : Color,
) -> ColorToken {
color_token(self.scope, name, default)
}
///|
pub fn VariableScope::number_token(
self : VariableScope,
name : String,
default : Number,
) -> NumberToken {
number_token(self.scope, name, default)
}
///|
pub fn VariableScope::percentage_token(
self : VariableScope,
name : String,
default : Percentage,
) -> PercentageToken {
percentage_token(self.scope, name, default)
}
///|
pub fn VariableScope::length_percentage_token(
self : VariableScope,
name : String,
default : LengthPercentage,
) -> LengthPercentageToken {
length_percentage_token(self.scope, name, default)
}
///|
pub fn VariableScope::integer_token(
self : VariableScope,
name : String,
default : Integer,
) -> IntegerToken {
integer_token(self.scope, name, default)
}
///|
pub fn VariableScope::time_token(
self : VariableScope,
name : String,
default : Time,
) -> TimeToken {
time_token(self.scope, name, default)
}
///|
pub fn VariableScope::angle_token(
self : VariableScope,
name : String,
default : Angle,
) -> AngleToken {
angle_token(self.scope, name, default)
}
///|
pub fn VariableScope::resolution_token(
self : VariableScope,
name : String,
default : Resolution,
) -> ResolutionToken {
resolution_token(self.scope, name, default)
}
///|
pub fn VariableScope::url_token(
self : VariableScope,
name : String,
default : Url,
) -> UrlToken {
url_token(self.scope, name, default)
}
///|
pub fn VariableScope::length_slot(
self : VariableScope,
name : String,
default : Length,
) -> LengthSlot {
length_slot(self.scope, name, default)
}
///|
pub fn VariableScope::color_slot(
self : VariableScope,
name : String,
default : Color,
) -> ColorSlot {
color_slot(self.scope, name, default)
}
///|
pub fn VariableScope::number_slot(
self : VariableScope,
name : String,
default : Number,
) -> NumberSlot {
number_slot(self.scope, name, default)
}
///|
pub fn VariableScope::percentage_slot(
self : VariableScope,
name : String,
default : Percentage,
) -> PercentageSlot {
percentage_slot(self.scope, name, default)
}
///|
pub fn VariableScope::length_percentage_slot(
self : VariableScope,
name : String,
default : LengthPercentage,
) -> LengthPercentageSlot {
length_percentage_slot(self.scope, name, default)
}
///|
pub fn VariableScope::integer_slot(
self : VariableScope,
name : String,
default : Integer,
) -> IntegerSlot {
integer_slot(self.scope, name, default)
}
///|
pub fn VariableScope::time_slot(
self : VariableScope,
name : String,
default : Time,
) -> TimeSlot {
time_slot(self.scope, name, default)
}
///|
pub fn VariableScope::angle_slot(
self : VariableScope,
name : String,
default : Angle,
) -> AngleSlot {
angle_slot(self.scope, name, default)
}
///|
pub fn VariableScope::resolution_slot(
self : VariableScope,
name : String,
default : Resolution,
) -> ResolutionSlot {
resolution_slot(self.scope, name, default)
}
///|
pub fn VariableScope::url_slot(
self : VariableScope,
name : String,
default : Url,
) -> UrlSlot {
url_slot(self.scope, name, default)
}
///|
pub fn[T] Token::variable_use(self : Token[T]) -> VariableUse {
{
scope: self.scope,
local_name: self.local_name,
definition: self.variable.definition(),
role: TokenRole,
}
}
///|
pub fn[T] DynamicSlot::variable_use(self : DynamicSlot[T]) -> VariableUse {
{
scope: self.scope,
local_name: self.local_name,
definition: self.variable.definition(),
role: DynamicSlotRole,
}
}
///|
pub fn[T] Token::reference_css(self : Token[T]) -> String {
"var(" + self.variable.name + ")"
}
///|
pub fn[T] DynamicSlot::variable_name(self : DynamicSlot[T]) -> String {
self.variable.name
}
///|
pub fn[T] Token::definition(self : Token[T]) -> VarDefinition {
self.variable.definition()
}
///|
pub fn[T] Token::definition_use(self : Token[T]) -> VariableUse {
self.variable_use()
}
///|
pub fn[T : CssValue] Token::with_value(
self : Token[T],
value : T,
) -> TokenOverride {
{
variable: self.variable_use(),
override_: {
name: self.variable.name,
value_css: value.css_value(),
category: value.value_category(),
},
}
}
///|
pub impl CssValue for Length with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Length with fn value_category(_self) {
LengthCategory
}
///|
pub impl CssValue for Color with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Color with fn value_category(_self) {
ColorCategory
}
///|
pub impl CssValue for Number with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Number with fn value_category(_self) {
NumberCategory
}
///|
pub impl CssValue for Percentage with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Percentage with fn value_category(_self) {
PercentageCategory
}
///|
pub impl CssValue for LengthPercentage with fn css_value(self) {
self.css
}
///|
pub impl CssValue for LengthPercentage with fn value_category(_self) {
LengthPercentageCategory
}
///|
pub impl CssValue for Integer with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Integer with fn value_category(_self) {
IntegerCategory
}
///|
pub impl CssValue for Time with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Time with fn value_category(_self) {
TimeCategory
}
///|
pub impl CssValue for Angle with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Angle with fn value_category(_self) {
AngleCategory
}
///|
pub impl CssValue for Resolution with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Resolution with fn value_category(_self) {
ResolutionCategory
}
///|
pub impl CssValue for Url with fn css_value(self) {
self.css
}
///|
pub impl CssValue for Url with fn value_category(_self) {
UrlCategory
}
///|
pub fn authored_length(value : Double, unit : LengthUnit) -> Length {
length(value, unit) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_rem(value : Double) -> Length {
rem(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_em(value : Double) -> Length {
em(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_ch(value : Double) -> Length {
ch(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_vmin(value : Double) -> Length {
vmin(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_vmax(value : Double) -> Length {
vmax(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_svh(value : Double) -> Length {
svh(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_lvh(value : Double) -> Length {
lvh(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_dvh(value : Double) -> Length {
dvh(value) catch {
error => { css: error_css(error), }
}
}
///|
fn invalid_rgb(red : Int32, green : Int32, blue : Int32) -> String? {
if red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255 {
Some(issue_css("STYLE_VALUE_OUT_OF_RANGE", "rgb"))
} else {
None
}
}
///|
pub fn authored_rgb(red : Int32, green : Int32, blue : Int32) -> Color {
match invalid_rgb(red, green, blue) {
Some(css) => { css, }
None => rgb(red, green, blue)
}
}
///|
pub fn authored_rgba(
red : Int32,
green : Int32,
blue : Int32,
alpha : Double,
) -> Color {
match invalid_rgb(red, green, blue) {
Some(css) => { css, }
None =>
rgba(red, green, blue, alpha) catch {
error => { css: error_css(error), }
}
}
}
///|
pub fn authored_hex_color(value : String) -> Color {
hex_color(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_hsl(
hue : Double,
saturation : Double,
lightness : Double,
) -> Color {
hsl(hue, saturation, lightness) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_seconds(value : Double) -> Time {
seconds(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_deg(value : Double) -> Angle {
deg(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_turn(value : Double) -> Angle {
turn(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_percentage(value : Double) -> Percentage {
percentage(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_number(value : Double) -> Number {
number(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_dpi(value : Double) -> Resolution {
dpi(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_dppx(value : Double) -> Resolution {
dppx(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_url(value : String) -> Url {
url(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_ratio(width : Int32, height : Int32) -> Ratio {
ratio(width, height) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_scale_transform(
x : Double,
y~ : Double? = None,
) -> TransformFunction {
scale_transform(x, y~) catch {
error => { expression: literal_expression(error_css(error), "transform"), }
}
}
///|
pub fn authored_transform_list(
functions : Array[TransformFunction],
) -> TransformList {
transform_list(functions) catch {
error => { expression: literal_expression(error_css(error), "transform"), }
}
}
///|
pub fn authored_cubic_bezier(
x1 : Double,
y1 : Double,
x2 : Double,
y2 : Double,
) -> EasingFunction {
cubic_bezier(x1, y1, x2, y2) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_steps(
count : Int32,
at_start~ : Bool = false,
) -> EasingFunction {
steps(count, at_start~) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_fr(value : Double) -> GridTrack {
fr(value) catch {
error =>
make_track(literal_expression(error_css(error), "grid-track"), Flexible)
}
}
///|
pub fn authored_grid_tracks(tracks : Array[GridTrack]) -> GridTrackList {
grid_tracks(tracks) catch {
error =>
make_tracks([
make_track(
literal_expression(error_css(error), "grid-track"),
Intrinsic,
),
])
}
}
///|
pub fn authored_repeat_tracks(
count : Int32,
tracks : GridTrackList,
) -> GridTrack {
repeat_tracks(count, tracks) catch {
error =>
make_track(literal_expression(error_css(error), "grid-track"), Intrinsic)
}
}
///|
pub fn authored_grid_line(value : Int32) -> GridLine {
grid_line(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_grid_span(value : Int32) -> GridLine {
grid_span(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_named_grid_line(value : String) -> GridLine {
named_grid_line(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_touch_action(parts : Array[TouchActionPart]) -> TouchAction {
touch_action(parts) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_contain(parts : Array[ContainPart]) -> Contain {
contain(parts) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_font_variant_numeric(
parts : Array[FontVariantNumericPart],
) -> FontVariantNumeric {
font_variant_numeric(parts) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_line_width_from_length(value : Length) -> LineWidth {
line_width_from_length(value) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_corner_radius(
horizontal : LengthPercentage,
vertical~ : LengthPercentage? = None,
) -> CornerRadius {
corner_radius(horizontal, vertical~)
}
///|
pub fn authored_border_side(
width~ : LineWidth? = None,
style~ : LineStyle? = None,
color~ : Color? = None,
) -> BorderSide {
border_side(width~, style~, color~) catch {
error => { css: error_css(error), }
}
}
///|
pub fn authored_outline(
width~ : LineWidth? = None,
style~ : OutlineStyle? = None,
color~ : OutlineColor? = None,
) -> Outline {
outline(width~, style~, color~) catch {
error => { css: error_css(error), }
}
}