| | 1 | | using Allyaria.Theming.Values; |
| | 2 | | using System.Text; |
| | 3 | | using System.Text.RegularExpressions; |
| | 4 | |
|
| | 5 | | namespace Allyaria.Theming.Styles; |
| | 6 | |
|
| | 7 | | /// <summary> |
| | 8 | | /// Represents a strongly typed typography definition for Allyaria theming. Provides conversion to CSS inline styles or |
| | 9 | | /// variables. |
| | 10 | | /// </summary> |
| | 11 | | /// <param name="FontFamily">The font family to use (e.g., <c>"Inter, Segoe UI, sans-serif"</c>).</param> |
| | 12 | | /// <param name="FontSize">The font size.</param> |
| | 13 | | /// <param name="FontStyle">The font style (e.g., normal, italic).</param> |
| | 14 | | /// <param name="FontWeight">The font weight (e.g., bold, 400).</param> |
| | 15 | | /// <param name="LetterSpacing">The letter spacing.</param> |
| | 16 | | /// <param name="LineHeight">The line height.</param> |
| | 17 | | /// <param name="TextAlign">The text alignment.</param> |
| | 18 | | /// <param name="TextDecoration">The text decoration.</param> |
| | 19 | | /// <param name="TextTransform">The text transform (e.g., uppercase).</param> |
| | 20 | | /// <param name="VerticalAlign">The vertical alignment.</param> |
| | 21 | | /// <param name="WordSpacing">The word spacing.</param> |
| | 22 | | public readonly record struct AllyariaTypography( |
| 94 | 23 | | AllyariaStringValue? FontFamily = null, |
| 96 | 24 | | AllyariaStringValue? FontSize = null, |
| 92 | 25 | | AllyariaStringValue? FontStyle = null, |
| 92 | 26 | | AllyariaStringValue? FontWeight = null, |
| 92 | 27 | | AllyariaStringValue? LetterSpacing = null, |
| 90 | 28 | | AllyariaStringValue? LineHeight = null, |
| 92 | 29 | | AllyariaStringValue? TextAlign = null, |
| 92 | 30 | | AllyariaStringValue? TextDecoration = null, |
| 92 | 31 | | AllyariaStringValue? TextTransform = null, |
| 92 | 32 | | AllyariaStringValue? VerticalAlign = null, |
| 90 | 33 | | AllyariaStringValue? WordSpacing = null |
| | 34 | | ) |
| | 35 | | { |
| | 36 | | /// <summary>Appends a CSS declaration to the builder if the value is not null.</summary> |
| | 37 | | /// <param name="builder">The string builder to append to.</param> |
| | 38 | | /// <param name="value">The optional string value.</param> |
| | 39 | | /// <param name="propertyName">The CSS property name.</param> |
| | 40 | | private static void AppendIfNotNull(StringBuilder builder, AllyariaStringValue? value, string propertyName) |
| | 41 | | { |
| 528 | 42 | | if (value is not null) |
| | 43 | | { |
| 96 | 44 | | builder.Append(value.ToCss(propertyName)); |
| | 45 | | } |
| 528 | 46 | | } |
| | 47 | |
|
| | 48 | | /// <summary> |
| | 49 | | /// Creates a new <see cref="AllyariaTypography" /> instance by cascading the current values with the provided overr |
| | 50 | | /// Any parameter left <see langword="null" /> will keep the existing value from this instance. |
| | 51 | | /// </summary> |
| | 52 | | /// <param name="fontFamily">Optional override for <see cref="AllyariaTypography.FontFamily" />.</param> |
| | 53 | | /// <param name="fontSize">Optional override for <see cref="AllyariaTypography.FontSize" />.</param> |
| | 54 | | /// <param name="fontStyle">Optional override for <see cref="AllyariaTypography.FontStyle" />.</param> |
| | 55 | | /// <param name="fontWeight">Optional override for <see cref="AllyariaTypography.FontWeight" />.</param> |
| | 56 | | /// <param name="letterSpacing">Optional override for <see cref="AllyariaTypography.LetterSpacing" />.</param> |
| | 57 | | /// <param name="lineHeight">Optional override for <see cref="AllyariaTypography.LineHeight" />.</param> |
| | 58 | | /// <param name="textAlign">Optional override for <see cref="AllyariaTypography.TextAlign" />.</param> |
| | 59 | | /// <param name="textDecoration">Optional override for <see cref="AllyariaTypography.TextDecoration" />.</param> |
| | 60 | | /// <param name="textTransform">Optional override for <see cref="AllyariaTypography.TextTransform" />.</param> |
| | 61 | | /// <param name="verticalAlign">Optional override for <see cref="AllyariaTypography.VerticalAlign" />.</param> |
| | 62 | | /// <param name="wordSpacing">Optional override for <see cref="AllyariaTypography.WordSpacing" />.</param> |
| | 63 | | /// <returns>A new <see cref="AllyariaTypography" /> instance with the combined values.</returns> |
| | 64 | | public AllyariaTypography Cascade(AllyariaStringValue? fontFamily = null, |
| | 65 | | AllyariaStringValue? fontSize = null, |
| | 66 | | AllyariaStringValue? fontStyle = null, |
| | 67 | | AllyariaStringValue? fontWeight = null, |
| | 68 | | AllyariaStringValue? letterSpacing = null, |
| | 69 | | AllyariaStringValue? lineHeight = null, |
| | 70 | | AllyariaStringValue? textAlign = null, |
| | 71 | | AllyariaStringValue? textDecoration = null, |
| | 72 | | AllyariaStringValue? textTransform = null, |
| | 73 | | AllyariaStringValue? verticalAlign = null, |
| | 74 | | AllyariaStringValue? wordSpacing = null) |
| | 75 | | { |
| 16 | 76 | | var newFontFamily = fontFamily ?? FontFamily; |
| 16 | 77 | | var newFontSize = fontSize ?? FontSize; |
| 16 | 78 | | var newFontStyle = fontStyle ?? FontStyle; |
| 16 | 79 | | var newFontWeight = fontWeight ?? FontWeight; |
| 16 | 80 | | var newLetterSpacing = letterSpacing ?? LetterSpacing; |
| 16 | 81 | | var newLineHeight = lineHeight ?? LineHeight; |
| 16 | 82 | | var newTextAlign = textAlign ?? TextAlign; |
| 16 | 83 | | var newTextDecoration = textDecoration ?? TextDecoration; |
| 16 | 84 | | var newTextTransform = textTransform ?? TextTransform; |
| 16 | 85 | | var newVerticalAlign = verticalAlign ?? VerticalAlign; |
| 16 | 86 | | var newWordSpacing = wordSpacing ?? WordSpacing; |
| | 87 | |
|
| 16 | 88 | | return new AllyariaTypography |
| 16 | 89 | | { |
| 16 | 90 | | FontFamily = newFontFamily, |
| 16 | 91 | | FontSize = newFontSize, |
| 16 | 92 | | FontStyle = newFontStyle, |
| 16 | 93 | | FontWeight = newFontWeight, |
| 16 | 94 | | LetterSpacing = newLetterSpacing, |
| 16 | 95 | | LineHeight = newLineHeight, |
| 16 | 96 | | TextAlign = newTextAlign, |
| 16 | 97 | | TextDecoration = newTextDecoration, |
| 16 | 98 | | TextTransform = newTextTransform, |
| 16 | 99 | | VerticalAlign = newVerticalAlign, |
| 16 | 100 | | WordSpacing = newWordSpacing |
| 16 | 101 | | }; |
| | 102 | | } |
| | 103 | |
|
| | 104 | | /// <summary> |
| | 105 | | /// Builds a CSS style string representing this typography. Only appends declarations for non-null properties. |
| | 106 | | /// </summary> |
| | 107 | | /// <returns>A concatenated CSS style string.</returns> |
| | 108 | | public string ToCss() |
| | 109 | | { |
| 12 | 110 | | var builder = new StringBuilder(); |
| | 111 | |
|
| 12 | 112 | | AppendIfNotNull(builder, FontFamily, "font-family"); |
| 12 | 113 | | AppendIfNotNull(builder, FontSize, "font-size"); |
| 12 | 114 | | AppendIfNotNull(builder, FontStyle, "font-style"); |
| 12 | 115 | | AppendIfNotNull(builder, FontWeight, "font-weight"); |
| 12 | 116 | | AppendIfNotNull(builder, LetterSpacing, "letter-spacing"); |
| 12 | 117 | | AppendIfNotNull(builder, LineHeight, "line-height"); |
| 12 | 118 | | AppendIfNotNull(builder, TextAlign, "text-align"); |
| 12 | 119 | | AppendIfNotNull(builder, TextDecoration, "text-decoration"); |
| 12 | 120 | | AppendIfNotNull(builder, TextTransform, "text-transform"); |
| 12 | 121 | | AppendIfNotNull(builder, VerticalAlign, "vertical-align"); |
| 12 | 122 | | AppendIfNotNull(builder, WordSpacing, "word-spacing"); |
| | 123 | |
|
| 12 | 124 | | return builder.ToString(); |
| | 125 | | } |
| | 126 | |
|
| | 127 | | /// <summary> |
| | 128 | | /// Builds a CSS custom properties (variables) string representing this typography. The method normalizes the option |
| | 129 | | /// <paramref name="prefix" /> by trimming whitespace and dashes, converting to lowercase, and replacing spaces with |
| | 130 | | /// hyphens. If no usable prefix remains, variables are emitted with the default <c>--aa-</c> prefix; otherwise, the |
| | 131 | | /// computed prefix is applied (e.g., <c>--mytheme-font-size</c>). |
| | 132 | | /// </summary> |
| | 133 | | /// <param name="prefix"> |
| | 134 | | /// An optional string used to namespace the CSS variables. May contain spaces or leading/trailing dashes, which are |
| | 135 | | /// normalized before use. If empty or whitespace, defaults to <c>--aa-</c>. |
| | 136 | | /// </param> |
| | 137 | | /// <returns> |
| | 138 | | /// A concatenated CSS variables string containing only non-null typography properties (e.g., <c>--{prefix}-font-fam |
| | 139 | | /// , <c>--{prefix}-line-height</c>). |
| | 140 | | /// </returns> |
| | 141 | | /// <remarks> |
| | 142 | | /// Each variable is only appended if its corresponding property is non-null. This keeps the resulting CSS concise a |
| | 143 | | /// avoids redundant declarations. |
| | 144 | | /// </remarks> |
| | 145 | | public string ToCssVars(string prefix = "") |
| | 146 | | { |
| 36 | 147 | | var basePrefix = Regex.Replace(prefix, @"[\s-]+", "-").Trim('-').ToLowerInvariant(); |
| | 148 | |
|
| 36 | 149 | | basePrefix = string.IsNullOrWhiteSpace(prefix) |
| 36 | 150 | | ? "--aa-" |
| 36 | 151 | | : $"--{basePrefix}-"; |
| | 152 | |
|
| 36 | 153 | | var builder = new StringBuilder(); |
| | 154 | |
|
| 36 | 155 | | AppendIfNotNull(builder, FontFamily, $"{basePrefix}font-family"); |
| 36 | 156 | | AppendIfNotNull(builder, FontSize, $"{basePrefix}font-size"); |
| 36 | 157 | | AppendIfNotNull(builder, FontStyle, $"{basePrefix}font-style"); |
| 36 | 158 | | AppendIfNotNull(builder, FontWeight, $"{basePrefix}font-weight"); |
| 36 | 159 | | AppendIfNotNull(builder, LetterSpacing, $"{basePrefix}letter-spacing"); |
| 36 | 160 | | AppendIfNotNull(builder, LineHeight, $"{basePrefix}line-height"); |
| 36 | 161 | | AppendIfNotNull(builder, TextAlign, $"{basePrefix}text-align"); |
| 36 | 162 | | AppendIfNotNull(builder, TextDecoration, $"{basePrefix}text-decoration"); |
| 36 | 163 | | AppendIfNotNull(builder, TextTransform, $"{basePrefix}text-transform"); |
| 36 | 164 | | AppendIfNotNull(builder, VerticalAlign, $"{basePrefix}vertical-align"); |
| 36 | 165 | | AppendIfNotNull(builder, WordSpacing, $"{basePrefix}word-spacing"); |
| | 166 | |
|
| 36 | 167 | | return builder.ToString(); |
| | 168 | | } |
| | 169 | | } |