Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@
var monthName = _culture.DateTimeFormat.GetMonthName(month);
var disabled = IsEnabled is false || IsMonthOutOfMinAndMaxDate(month);
var selected = month == _currentMonth;
<button @onclick="() => SelectMonth(month)"
<button @onclick="async () => await SelectMonth(month)"
type="button"
role="gridcell"
title="@monthName"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,13 @@ private int _minuteView
[CallOnSet(nameof(OnSetParameters))]
public DateTimeOffset? MinDate { get; set; }

/// <summary>
/// The selection mode of the DatePicker (DatePicker or MonthPicker).
/// </summary>
[Parameter]
[CallOnSet(nameof(OnSetParameters))]
public BitDatePickerMode Mode { get; set; } = BitDatePickerMode.DatePicker;

/// <summary>
/// Custom template to render the month cells of the DatePicker.
/// </summary>
Expand Down Expand Up @@ -547,7 +554,11 @@ protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(fa
return true;
}

if (DateTime.TryParseExact(value, DateFormat ?? _culture.DateTimeFormat.ShortDatePattern, _culture, DateTimeStyles.None, out DateTime parsedValue))
var pattern = DateFormat ?? (Mode == BitDatePickerMode.MonthPicker
? _culture.DateTimeFormat.YearMonthPattern
: _culture.DateTimeFormat.ShortDatePattern);

if (DateTime.TryParseExact(value, pattern, _culture, DateTimeStyles.None, out DateTime parsedValue))
{
result = new DateTimeOffset(parsedValue, _timeZone.GetUtcOffset(parsedValue));
validationErrorMessage = null;
Expand All @@ -561,9 +572,11 @@ protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(fa

protected override string? FormatValueAsString(DateTimeOffset? value)
{
return value.HasValue
? value.Value.ToString(DateFormat ?? _culture.DateTimeFormat.ShortDatePattern, _culture)
: null;
if (value.HasValue is false) return null;

return Mode == BitDatePickerMode.MonthPicker
? value.Value.ToString(DateFormat ?? _culture.DateTimeFormat.YearMonthPattern, _culture)
: value.Value.ToString(DateFormat ?? _culture.DateTimeFormat.ShortDatePattern, _culture);
}


Expand Down Expand Up @@ -747,7 +760,7 @@ private async Task SelectDate(DateTime selectedDate)
GenerateMonthData(_currentYear, _currentMonth);
}

private void SelectMonth(int month)
private async Task SelectMonth(int month)
{
if (IsEnabled is false) return;
if (IsMonthOutOfMinAndMaxDate(month)) return;
Expand All @@ -756,7 +769,13 @@ private void SelectMonth(int month)

GenerateMonthData(_currentYear, _currentMonth);

if (_showMonthPickerAsOverlayInternal || ShowTimePicker)
if (Mode == BitDatePickerMode.MonthPicker)
{
var selectedDate = _culture.Calendar.ToDateTime(_currentYear, _currentMonth, 1, 0, 0, 0, 0);

await SelectDate(selectedDate);
}
else if (_showMonthPickerAsOverlayInternal || ShowTimePicker)
{
ToggleMonthPickerOverlay();
}
Expand Down Expand Up @@ -1148,6 +1167,16 @@ private string GetMonthCellCssClass(int monthIndex, int todayYear, int todayMont
{
className.Append(" bit-dtp-psm");
}
else if (Mode == BitDatePickerMode.MonthPicker && CurrentValue.HasValue)
{
var selectedYear = _culture.Calendar.GetYear(CurrentValue.Value.DateTime);
var selectedMonth = _culture.Calendar.GetMonth(CurrentValue.Value.DateTime);

if (selectedYear == _currentYear && selectedMonth == monthIndex)
{
className.Append(" bit-dtp-psm");
}
}

return className.ToString();
}
Expand Down Expand Up @@ -1346,6 +1375,8 @@ private async Task CloseCallout()

private bool ShowDayPicker()
{
if (Mode == BitDatePickerMode.MonthPicker) return false;

if (ShowTimePicker)
{
if (ShowTimePickerAsOverlay)
Expand All @@ -1365,6 +1396,8 @@ private bool ShowDayPicker()

private bool ShowMonthPicker()
{
if (Mode == BitDatePickerMode.MonthPicker) return true;

if (ShowTimePicker)
{
if (ShowTimePickerAsOverlay)
Expand All @@ -1385,8 +1418,8 @@ private bool ShowMonthPicker()
private void ResetPickersState()
{
_showMonthPicker = true;
_isMonthPickerOverlayOnTop = false;
_showMonthPickerAsOverlayInternal = ShowMonthPickerAsOverlay;
_isMonthPickerOverlayOnTop = Mode == BitDatePickerMode.MonthPicker;
_showMonthPickerAsOverlayInternal = Mode == BitDatePickerMode.MonthPicker || ShowMonthPickerAsOverlay;
_isTimePickerOverlayOnTop = false;
_showTimePickerAsOverlayInternal = ShowTimePickerAsOverlay;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Bit.BlazorUI;

/// <summary>
/// Determines the selection mode of the BitDatePicker.
/// </summary>
public enum BitDatePickerMode
{
/// <summary>
/// Standard date picker mode allowing selection of a specific day.
/// </summary>
DatePicker,

/// <summary>
/// Month picker mode allowing selection of only month and year.
/// The day is automatically set to the 1st of the selected month.
/// </summary>
MonthPicker
}

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@page "/components/datepicker"
@page "/components/datepicker"
@page "/components/date-picker"
@using Bit.BlazorUI.Demo.Client.Core.Helpers

Expand Down Expand Up @@ -179,7 +179,40 @@
</div>
</DemoExample>

<DemoExample Title="ReadOnly" RazorCode="@example10RazorCode" CsharpCode="@example10CsharpCode" Id="example10">
<DemoExample Title="Mode" RazorCode="@example10RazorCode" CsharpCode="@example10CsharpCode" Id="example10">
<div>Use the BitDatePicker in MonthPicker mode to allow users to select only month and year. The day is automatically set to the 1st of the selected month.</div>
<br />
<div class="example-content">
<BitDatePicker Label="Basic MonthPicker"
Placeholder="Select a month"
Mode="BitDatePickerMode.MonthPicker" />
<br /><br />
<BitDatePicker @bind-Value="monthPickerDate"
Placeholder="Select a month"
Label="MonthPicker with binding"
Mode="BitDatePickerMode.MonthPicker" />
<br />
<div>Selected Date: @(monthPickerDate?.ToString("yyyy/MM/dd HH:mm:ss") ?? "None")</div>
<br /><br />
<BitDatePicker Placeholder="Select a month"
Label="MonthPicker with Min/Max"
Mode="BitDatePickerMode.MonthPicker"
MaxDate="DateTimeOffset.Now.AddMonths(6)"
MinDate="DateTimeOffset.Now.AddMonths(-6)" />
<br /><br />
<BitDatePicker HighlightCurrentMonth
HighlightSelectedMonth
Placeholder="Select a month"
Mode="BitDatePickerMode.MonthPicker"
Label="MonthPicker with highlighting" />
</div>
<br /><br />
<BitDatePicker Standalone
Label="Standalone MonthPicker"
Mode="BitDatePickerMode.MonthPicker" />
</DemoExample>

<DemoExample Title="ReadOnly" RazorCode="@example11RazorCode" CsharpCode="@example11CsharpCode" Id="example11">
<div>The ReadOnly parameter makes the date picker input non-editable, preventing users from manually changing the time value.</div>
<br />
<div class="example-content">
Expand All @@ -195,7 +228,7 @@
</div>
</DemoExample>

<DemoExample Title="Templates" RazorCode="@example11RazorCode" CsharpCode="@example11CsharpCode" Id="example11">
<DemoExample Title="Templates" RazorCode="@example12RazorCode" CsharpCode="@example12CsharpCode" Id="example12">
<div>Utilize various templates within the BitDatePicker, such as custom label templates, day cell templates, and year cell templates.</div>
<br />
<div class="example-content">
Expand Down Expand Up @@ -237,7 +270,7 @@
</div>
</DemoExample>

<DemoExample Title="Responsive" RazorCode="@example12RazorCode" Id="example12">
<DemoExample Title="Responsive" RazorCode="@example13RazorCode" Id="example13">
<div>Enable responsive design for the BitDatePicker, allowing it to adjust its layout and appearance based on the screen size.</div>
<br />
<div class="example-content">
Expand All @@ -248,7 +281,7 @@
</div>
</DemoExample>

<DemoExample Title="Validation" RazorCode="@example13RazorCode" CsharpCode="@example13CsharpCode" Id="example13">
<DemoExample Title="Validation" RazorCode="@example14RazorCode" CsharpCode="@example14CsharpCode" Id="example14">
<div>Implement form validation with BitDatePicker using data annotations, ensuring the user selects a valid date before submitting the form.</div>
<br />
<div class="example-content">
Expand All @@ -273,7 +306,7 @@
</div>
</DemoExample>

<DemoExample Title="Style & Class" RazorCode="@example14RazorCode" CsharpCode="@example14CsharpCode" Id="example14">
<DemoExample Title="Style & Class" RazorCode="@example15RazorCode" CsharpCode="@example15CsharpCode" Id="example15">
<div>Explore styling and class customization for BitDatePicker, including component styles, custom classes, and detailed styles.</div>
<br /><br />
<div>Component's Style & Class:</div><br />
Expand Down Expand Up @@ -320,7 +353,7 @@
</div>
</DemoExample>

<DemoExample Title="RTL" RazorCode="@example15RazorCode" Id="example15">
<DemoExample Title="RTL" RazorCode="@example16RazorCode" Id="example16">
<div>Use BitDatePicker in right-to-left (RTL).</div>
<br />
<div dir="rtl">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@ public partial class BitDatePickerDemo
Description = "The minimum date allowed for the DatePicker."
},
new()
{
Name = "Mode",
Type = "BitDatePickerMode",
DefaultValue = "BitDatePickerMode.DatePicker",
Description = "The selection mode of the DatePicker (DatePicker or MonthPicker).",
LinkType = LinkType.Link,
Href = "#datepicker-mode-enum"
},
new()
{
Name = "MonthCellTemplate",
Type = "RenderFragment<DateTimeOffset>?",
Expand Down Expand Up @@ -465,6 +474,27 @@ public partial class BitDatePickerDemo
Value="1"
}
}
},
new()
{
Id = "datepicker-mode-enum",
Name = "BitDatePickerMode",
Description = "",
Items = new()
{
new()
{
Name = "DatePicker",
Description = "Standard date picker mode allowing selection of a specific day.",
Value = "0"
},
new()
{
Name = "MonthPicker",
Description = "Month picker mode allowing selection of only month and year. The day is automatically set to the 1st of the selected month.",
Value = "1"
}
}
}
};

Expand Down Expand Up @@ -917,6 +947,7 @@ public partial class BitDatePickerDemo
private DateTimeOffset? timeZoneDate2;

private DateTimeOffset? classesValue;
private DateTimeOffset? monthPickerDate;

private CultureInfo culture = CultureInfo.CurrentUICulture;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,43 @@ public partial class BitDatePickerDemo
<BitDatePicker Label=""TimePicker"" ShowTimePicker Standalone />";

private readonly string example10RazorCode = @"
<BitDatePicker Label=""Basic MonthPicker""
Placeholder=""Select a month""
Mode=""BitDatePickerMode.MonthPicker"" />

<BitDatePicker @bind-Value=""monthPickerDate""
Placeholder=""Select a month""
Label=""MonthPicker with binding""
Mode=""BitDatePickerMode.MonthPicker"" />
<div>Selected Date: @(monthPickerDate?.ToString(""yyyy/MM/dd HH:mm:ss"") ?? ""None"")</div>

<BitDatePicker Placeholder=""Select a month""
Label=""MonthPicker with Min/Max""
Mode=""BitDatePickerMode.MonthPicker""
MaxDate=""DateTimeOffset.Now.AddMonths(6)""
MinDate=""DateTimeOffset.Now.AddMonths(-6)"" />

<BitDatePicker HighlightCurrentMonth
HighlightSelectedMonth
Placeholder=""Select a month""
Mode=""BitDatePickerMode.MonthPicker""
Label=""MonthPicker with highlighting"" />

<BitDatePicker Standalone
Label=""Standalone MonthPicker""
Mode=""BitDatePickerMode.MonthPicker"" />";
private readonly string example10CsharpCode = @"
private DateTimeOffset? monthPickerDate;";

private readonly string example11RazorCode = @"
<BitDatePicker Label=""Basic"" ReadOnly @bind-Value=""readOnlyDate"" />
<BitDatePicker Label=""Text input allowed"" ReadOnly AllowTextInput @bind-Value=""readOnlyDate"" />
<BitDatePicker Label=""Standalone"" ReadOnly Standalone @bind-Value=""readOnlyDate"" />
<BitDatePicker Label=""Standalone with TimePicker"" ReadOnly ShowTimePicker Standalone @bind-Value=""readOnlyDate"" />";
private readonly string example10CsharpCode = @"
private readonly string example11CsharpCode = @"
private DateTimeOffset? readOnlyDate = DateTimeOffset.Now;";

private readonly string example11RazorCode = @"
private readonly string example12RazorCode = @"
<style>
.day-cell {
width: 28px;
Expand Down Expand Up @@ -160,16 +189,16 @@ public partial class BitDatePickerDemo
</span>
</YearCellTemplate>
</BitDatePicker>";
private readonly string example11CsharpCode = @"
private readonly string example12CsharpCode = @"
private CultureInfo culture = CultureInfo.CurrentUICulture;";

private readonly string example12RazorCode = @"
private readonly string example13RazorCode = @"
<BitDatePicker Label=""Response DatePicker""
Responsive
ShowWeekNumbers
Placeholder=""Select a date"" />";

private readonly string example13RazorCode = @"
private readonly string example14RazorCode = @"
<style>
.validation-message {
color: red;
Expand All @@ -189,7 +218,7 @@ public partial class BitDatePickerDemo
Reset
</BitButton>
</EditForm>";
private readonly string example13CsharpCode = @"
private readonly string example14CsharpCode = @"
public class BitDatePickerValidationModel
{
[Required]
Expand All @@ -201,7 +230,7 @@ public class BitDatePickerValidationModel
private void HandleValidSubmit() { }
private void HandleInvalidSubmit() { }";

private readonly string example14RazorCode = @"
private readonly string example15RazorCode = @"
<style>
.custom-class {
overflow: hidden;
Expand Down Expand Up @@ -362,9 +391,9 @@ private void HandleValidSubmit() { }
DayPickerHeader = ""custom-day-header"",
WeekNumbersHeader = ""custom-week-header"",
YearMonthPickerWrapper = ""custom-year-picker"" })"" />";
private readonly string example14CsharpCode = @"
private readonly string example15CsharpCode = @"
private DateTimeOffset? classesValue;";

private readonly string example15RazorCode = @"
private readonly string example16RazorCode = @"
<BitDatePicker Dir=""BitDir.Rtl"" />";
}
Loading