Files
Htmx/Htmx.ApiDemo/Templates/Components/TimePicker.htmx.cs
T

90 lines
4.1 KiB
C#

namespace Htmx.ApiDemo.Templates.Components;
/// <summary>
/// shadcn-style TimePicker. Syncs hour+minute inputs to a hidden HH:MM field via inline JS.
/// </summary>
public sealed class TimePicker : TimePickerBase
{
private readonly byte[] _uniqueIdData;
private readonly byte[] _nameData;
private readonly byte[] _use12hData;
private readonly byte[] _labelData;
private readonly byte[] _descriptionData;
private readonly byte[] _defaultHourData;
private readonly byte[] _defaultMinuteData;
private readonly byte[] _defaultValueData;
private readonly byte[] _hourMinData;
private readonly byte[] _hourMaxData;
private readonly byte[] _amPmToggleData;
public TimePicker(
string name = "time",
TimeOnly? selected = null,
string label = "",
string description = "",
bool use12h = false)
{
var time = selected ?? TimeOnly.FromDateTime(DateTime.Now);
var uid = Guid.NewGuid().ToString("N")[..8]; // short unique suffix
_uniqueIdData = uid.ToUtf8Bytes();
_nameData = name.ToUtf8Bytes();
_use12hData = (use12h ? "true" : "false").ToUtf8Bytes();
_defaultValueData = time.ToString("HH:mm").ToUtf8Bytes();
_labelData = string.IsNullOrEmpty(label)
? []
: $"""<span class="text-sm font-medium leading-none">{label}</span>""".ToUtf8Bytes();
_descriptionData = string.IsNullOrEmpty(description)
? []
: $"""<p class="text-xs text-muted-foreground">{description}</p>""".ToUtf8Bytes();
if (use12h)
{
int hour12 = time.Hour % 12;
if (hour12 == 0) hour12 = 12;
bool isPm = time.Hour >= 12;
_defaultHourData = hour12.ToString().ToUtf8Bytes();
_defaultMinuteData = time.Minute.ToString("D2").ToUtf8Bytes();
_hourMinData = "1".ToUtf8Bytes();
_hourMaxData = "12".ToUtf8Bytes();
_amPmToggleData = BuildAmPmToggle(isPm);
}
else
{
_defaultHourData = time.Hour.ToString("D2").ToUtf8Bytes();
_defaultMinuteData = time.Minute.ToString("D2").ToUtf8Bytes();
_hourMinData = "0".ToUtf8Bytes();
_hourMaxData = "23".ToUtf8Bytes();
_amPmToggleData = [];
}
}
private static byte[] BuildAmPmToggle(bool isPm)
{
var amSel = isPm ? "" : " selected";
var pmSel = isPm ? " selected" : "";
return $"""
<select class="timepicker-ampm h-10 rounded-md border border-input bg-background px-2 text-sm
focus:outline-none focus:ring-2 focus:ring-ring">
<option value="AM"{amSel}>AM</option>
<option value="PM"{pmSel}>PM</option>
</select>
""".ToUtf8Bytes();
}
protected override void RenderUniqueId(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_uniqueIdData);
protected override void RenderName(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_nameData);
protected override void RenderUse12h(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_use12hData);
protected override void RenderLabel(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_labelData);
protected override void RenderDescription(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_descriptionData);
protected override void RenderDefaultHour(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_defaultHourData);
protected override void RenderDefaultMinute(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_defaultMinuteData);
protected override void RenderDefaultValue(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_defaultValueData);
protected override void RenderHourMin(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_hourMinData);
protected override void RenderHourMax(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_hourMaxData);
protected override void RenderAmPmToggle(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_amPmToggleData);
}