You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Components/Utilities/CssBuilder.cs

136 lines
5.3 KiB

2 years ago
// Copyright (c) 2011 - 2019 Ed Charbeneau
// License: MIT
// See https://github.com/EdCharbeneau
namespace Connected.Utilities
{
public struct CssBuilder
{
private string stringBuffer;
/// <summary>
/// Creates a CssBuilder used to define conditional CSS classes used in a component.
/// Call Build() to return the completed CSS Classes as a string.
/// </summary>
/// <param name="value"></param>
public static CssBuilder Default(string value) => new(value);
/// <summary>
/// Creates an Empty CssBuilder used to define conditional CSS classes used in a component.
/// Call Build() to return the completed CSS Classes as a string.
/// </summary>
public static CssBuilder Empty() => new();
/// <summary>
/// Creates a CssBuilder used to define conditional CSS classes used in a component.
/// Call Build() to return the completed CSS Classes as a string.
/// </summary>
/// <param name="value"></param>
public CssBuilder(string value) => stringBuffer = value;
/// <summary>
/// Adds a raw string to the builder that will be concatenated with the next class or value added to the builder.
/// </summary>
/// <param name="value"></param>
/// <returns>CssBuilder</returns>
public CssBuilder AddValue(string value)
{
stringBuffer += value;
return this;
}
/// <summary>
/// Adds a CSS Class to the builder with space separator.
/// </summary>
/// <param name="value">CSS Class to add</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(string? value)
{
if (value is null)
return this;
return AddValue($" {value}");
}
/// <summary>
/// Adds a conditional CSS Class to the builder with space separator.
/// </summary>
/// <param name="value">CSS Class to conditionally add.</param>
/// <param name="when">Condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(string value, bool when = true) => when ? this.AddClass(value) : this;
/// <summary>
/// Adds a conditional CSS Class to the builder with space separator.
/// </summary>
/// <param name="value">CSS Class to conditionally add.</param>
/// <param name="when">Nullable condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(string value, bool? when = true) => when == true ? this.AddClass(value) : this;
/// <summary>
/// Adds a conditional CSS Class to the builder with space separator.
/// </summary>
/// <param name="value">CSS Class to conditionally add.</param>
/// <param name="when">Condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(string value, Func<bool> when = null) => this.AddClass(value, when != null && when());
/// <summary>
/// Adds a conditional CSS Class to the builder with space separator.
/// </summary>
/// <param name="value">Function that returns a CSS Class to conditionally add.</param>
/// <param name="when">Condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(Func<string> value, bool when = true) => when ? this.AddClass(value()) : this;
/// <summary>
/// Adds a conditional CSS Class to the builder with space separator.
/// </summary>
/// <param name="value">Function that returns a CSS Class to conditionally add.</param>
/// <param name="when">Condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(Func<string> value, Func<bool> when = null) => this.AddClass(value, when != null && when());
/// <summary>
/// Adds a conditional nested CssBuilder to the builder with space separator.
/// </summary>
/// <param name="builder">CSS Class to conditionally add.</param>
/// <param name="when">Condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(CssBuilder builder, bool when = true) => when ? this.AddClass(builder.Build()) : this;
/// <summary>
/// Adds a conditional CSS Class to the builder with space separator.
/// </summary>
/// <param name="builder">CSS Class to conditionally add.</param>
/// <param name="when">Condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(CssBuilder builder, Func<bool> when = null) => this.AddClass(builder, when != null && when());
/// <summary>
/// Adds a conditional CSS Class when it exists in a dictionary to the builder with space separator.
/// Null safe operation.
/// </summary>
/// <param name="additionalAttributes">Additional Attribute splat parameters</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddClassFromAttributes(IReadOnlyDictionary<string, object> additionalAttributes) =>
additionalAttributes == null ? this :
additionalAttributes.TryGetValue("class", out var c) ? AddClass(c.ToString()) : this;
/// <summary>
/// Finalize the completed CSS Classes as a string.
/// </summary>
/// <returns>string</returns>
public string Build()
{
// String buffer finalization code
return stringBuffer != null ? stringBuffer.Trim() : string.Empty;
}
// ToString should only and always call Build to finalize the rendered string.
public override string ToString() => Build();
}
}