| | | 1 | | namespace Allyaria.Theming.ThemeTypes; |
| | | 2 | | |
| | | 3 | | /// <summary> |
| | | 4 | | /// Represents a hierarchical theming component node that stores and resolves <see cref="ThemeVariant" /> instances for |
| | | 5 | | /// each <see cref="ComponentType" />. |
| | | 6 | | /// </summary> |
| | | 7 | | /// <remarks> |
| | | 8 | | /// <para> |
| | | 9 | | /// Each <see cref="ThemeComponent" /> corresponds to a level in the Allyaria theming structure. It can recursively |
| | | 10 | | /// build CSS declarations for child components and apply updates through <see cref="ThemeUpdater" /> objects. |
| | | 11 | | /// </para> |
| | | 12 | | /// <para> |
| | | 13 | | /// The structure supports both full theme traversal (when no component types are specified) and targeted CSS |
| | | 14 | | /// generation for specific <see cref="ComponentType" /> values. |
| | | 15 | | /// </para> |
| | | 16 | | /// </remarks> |
| | | 17 | | internal sealed class ThemeComponent |
| | | 18 | | { |
| | | 19 | | /// <summary>A collection of component variants indexed by <see cref="ComponentType" />.</summary> |
| | 54 | 20 | | private readonly Dictionary<ComponentType, ThemeVariant> _children = new(); |
| | | 21 | | |
| | | 22 | | /// <summary> |
| | | 23 | | /// Builds a CSS representation of this component and its children using the provided <see cref="CssBuilder" />. |
| | | 24 | | /// </summary> |
| | | 25 | | /// <param name="builder">The <see cref="CssBuilder" /> instance used to accumulate CSS output.</param> |
| | | 26 | | /// <param name="navigator">The <see cref="ThemeNavigator" /> that defines which components, themes, and states to i |
| | | 27 | | /// <param name="varPrefix">An optional variable prefix for CSS variable names (used for <c>:root</c> variable gener |
| | | 28 | | /// <returns>A <see cref="CssBuilder" /> instance containing the combined CSS for the specified theme scope.</return |
| | | 29 | | internal CssBuilder BuildCss(CssBuilder builder, ThemeNavigator navigator, string? varPrefix = "") |
| | | 30 | | { |
| | 78 | 31 | | if (navigator.ComponentTypes.Count is 0) |
| | | 32 | | { |
| | 18 | 33 | | foreach (var child in _children) |
| | | 34 | | { |
| | 4 | 35 | | builder = child.Value.BuildCss( |
| | 4 | 36 | | builder: builder, |
| | 4 | 37 | | navigator: navigator, |
| | 4 | 38 | | varPrefix: SetPrefix(varPrefix: varPrefix, type: child.Key) |
| | 4 | 39 | | ); |
| | | 40 | | } |
| | | 41 | | } |
| | | 42 | | else |
| | | 43 | | { |
| | 294 | 44 | | foreach (var key in navigator.ComponentTypes) |
| | | 45 | | { |
| | 74 | 46 | | builder = Get(key: key)?.BuildCss( |
| | 74 | 47 | | builder: builder, |
| | 74 | 48 | | navigator: navigator, |
| | 74 | 49 | | varPrefix: SetPrefix(varPrefix: varPrefix, type: key) |
| | 74 | 50 | | ) ?? builder; |
| | | 51 | | } |
| | | 52 | | } |
| | | 53 | | |
| | 78 | 54 | | return builder; |
| | | 55 | | } |
| | | 56 | | |
| | | 57 | | /// <summary>Retrieves the <see cref="ThemeVariant" /> associated with the given component type, if it exists.</summ |
| | | 58 | | /// <param name="key">The <see cref="ComponentType" /> to retrieve.</param> |
| | | 59 | | /// <returns>The corresponding <see cref="ThemeVariant" /> instance, or <see langword="null" /> if not found.</retur |
| | 5705 | 60 | | private ThemeVariant? Get(ComponentType key) => _children.GetValueOrDefault(key: key); |
| | | 61 | | |
| | | 62 | | /// <summary> |
| | | 63 | | /// Applies a theme update by inserting or updating child <see cref="ThemeVariant" /> instances according to the spe |
| | | 64 | | /// <see cref="ThemeUpdater" />. |
| | | 65 | | /// </summary> |
| | | 66 | | /// <param name="updater">The <see cref="ThemeUpdater" /> describing which components and style values to update.</p |
| | | 67 | | /// <returns>The current <see cref="ThemeComponent" /> instance, enabling fluent chaining.</returns> |
| | | 68 | | internal ThemeComponent Set(ThemeUpdater updater) |
| | | 69 | | { |
| | 22524 | 70 | | foreach (var key in updater.Navigator.ComponentTypes) |
| | | 71 | | { |
| | 5631 | 72 | | if (!_children.ContainsKey(key: key)) |
| | | 73 | | { |
| | 108 | 74 | | _children.Add(key: key, value: new ThemeVariant()); |
| | | 75 | | } |
| | | 76 | | |
| | 5631 | 77 | | Get(key: key)?.Set(updater: updater); |
| | | 78 | | } |
| | | 79 | | |
| | 5631 | 80 | | return this; |
| | | 81 | | } |
| | | 82 | | |
| | | 83 | | /// <summary> |
| | | 84 | | /// Constructs a CSS variable prefix by combining an existing prefix with the specified component type. |
| | | 85 | | /// </summary> |
| | | 86 | | /// <param name="varPrefix">The existing prefix, if any.</param> |
| | | 87 | | /// <param name="type">The <see cref="ComponentType" /> to append.</param> |
| | | 88 | | /// <returns>A normalized CSS-friendly prefix string suitable for use in variable naming.</returns> |
| | | 89 | | private static string SetPrefix(string? varPrefix, ComponentType type) |
| | | 90 | | { |
| | 27 | 91 | | var prefix = varPrefix?.ToCssName() ?? string.Empty; |
| | | 92 | | |
| | 27 | 93 | | return string.IsNullOrWhiteSpace(value: prefix) |
| | 27 | 94 | | ? string.Empty |
| | 27 | 95 | | : $"{prefix}-{type}".ToCssName(); |
| | | 96 | | } |
| | | 97 | | } |