custom_nepali_calendar 3.2.0
custom_nepali_calendar: ^3.2.0 copied to clipboard
Nepali Bikram Sambat calendar and date picker in a bottom sheet: single date or range, custom theme colours, live BS/AD switch, Nepali or English. No dependencies.
3.2.0 #
A correctness release. Four of these let a picker resolve to a day the caller had explicitly excluded, which is a data-integrity problem in the consuming app rather than a cosmetic one — worth upgrading for even if you use none of the new behavior.
Changed #
- Two romanized month names changed: month 3 is now
Ashadh(wasAshar) and month 6 is nowAshwin(wasAshoj). These are the standard romanizations, they are whatnepali_utilsuses — so an app depending on both packages now renders the same names from either — andAshadhis what this README already called month 3 in the fiscal-year section while the code said otherwise. Devanagari names are unchanged, as are the other ten Latin names. Nothing about the API changes; if you displayformat('MMMM')anywhere, the text your users see for those two months will differ.
Added #
CalendarStrings.monthNameShortgives the abbreviated month name for any month, system and language, and is now the only way short names are produced.MMMand the date strip's month caption both used to take the first three characters of the full name, which rendered two months three apart identically —12 Ash 2081could mean Ashadh or Ashwin, with nothing on screen to tell them apart. Abbreviations now come from a hand-written table, the same way weekday abbreviations always have:Bai Jes Asar Shr Bha Ash Kar Man Pou Mag Fal Cha, matchingnepali_utils. Devanagari is returned whole, since slicing it by code unit would cut a vowel mark off its consonant.bsMonthsShortEnglishandadMonthsShortEnglishare exposed alongside the existing name tables.CalendarStringsis now exported. It always documented itself as public API — "exposed publicly so consuming apps can reuse the same names in their own widgets" — but was missing from the library'sshowclause, so code following its own documentation did not compile. Month names, weekday names and their short forms in both languages are now reachable frompackage:custom_nepali_calendar/custom_nepali_calendar.dart, which is what you want when building your own month dropdown or report header. Purely additive.
Fixed #
- The Today button no longer returns a day outside your window. It was
checked against the visible month and then selected unconditionally, so
any
startDatefalling later in the current month — and anyselectableDatesallow-list — left Today free to pick a day the grid had already greyed out, with Done lit up and no signal that anything was wrong. Today now selects only when the day passes the same check the grid uses. When today is reachable but not selectable the button still navigates to that month without selecting; when today is out of range entirely the button renders disabled instead of looking live and swallowing the tap. initialSelectionno longer smuggles an excluded day back out. A preselected value is a value the sheet can resolve to — Done is live the moment it opens — but it was never checked againststartDate/endDate/durationDaysorselectableDates. That broke the ordinary "hand back whatever you got last time" pattern as soon as the window moved: a day picked yesterday, replayed into a window that now starts today, arrived preselected, rendered greyed out and selected at the same time, and could be confirmed without the user touching anything. It is now checked against exactly the bounds a tap is, and ignored when it fails — so replaying a stale value is always safe. A selection whose kind does not matchmodeis ignored for the same reason, which also stops the Clear button offering to erase a value the sheet never displayed.HorizontalDateStripno longer reports a selection you excluded. With noselectedDatethe strip picks a starting day and reports it throughonDateSelected, and that default ignoredendDate/durationDays/selectableDates— so the caller ended up holding a date the strip was simultaneously painting as disabled. It now defaults to the first day that actually qualifies, and reports nothing at all when none of the visible days do.- The strip no longer throws out of
buildat the top of the supported range. A strip anchored near BS 2199 walked off the end of the month-length table and threwDateConversionExceptionfrom insidebuild(), where a consumer has no way to catch it and the whole screen goes down. It now renders however many days remain. - Passing both
endDateanddurationDaysthrows in release too. It was a bareassert, so release builds silently droppeddurationDaysand usedendDate. It is now anArgumentError, matching the ordering checks that 3.1.2 upgraded for the same reason. HorizontalDateStripno longer callssetStateafter its calendar closes without checking it is still mounted — popping or replacing the host route while the sheet was open threw.- The strip's "today" indicator and its start/end window are now resolved once and reused rather than recomputed on every build. 3.1.2 claimed the first of these; it was not actually true of the strip until now.
Internal #
- Window and allow-list membership now live in one
isDaySelectablepredicate that the month grid, the strip, the Today action andinitialSelectionall share. Every excluded-day bug above is a variation of the same root cause — the same rule written down in four places and drifting apart — so there is now only one place for it to drift from. - Added a CI workflow: analyze (with
--fatal-infos), format check, package tests, example tests, anddart pub publish --dry-runon every push and pull request. - Added exhaustive test coverage: every one of the 84,009 representable days now round-trips BS→AD→BS and AD→BS→AD in CI, with the day-number sequence and the weekday cycle checked for breaks — which is what would catch a single mistyped month length in the table, even where the Nepali New Year dates on either side of it still line up. Alongside it, end-to-end coverage of the workflows a user actually walks and the inputs an app eventually supplies by accident. The suite went from 234 tests to 297 and still runs in under ten seconds.
- Added GitHub issue forms for bug reports and feature requests. The bug form
asks for the two things that make a date-picker report actionable — the
exact call, and the exact Bikram Sambat dates — because almost every defect
found so far has been an interaction between
startDate,endDate/durationDays,selectableDatesandinitialSelection.
Docs #
- README screenshots now resolve against the default branch instead of a
release tag. Pinning them to
v3.1.2broke every image on the package page when that tag was never pushed — the same failure 3.1.1 was released to fix. A branch reference cannot go stale this way.
3.1.2 #
Added #
selectableDatesrestricts the sheet and strip to a caller-supplied list of days — every other day is disabled, on top of whateverstartDate/endDate/durationDaysalready restrict, not instead of it. Useful for e.g. a fixed set of available appointment slots. TakesList<NepaliDate>, so parse any server-supplied date strings yourself first (same pattern as the fiscal-year recipe above).null(the default) keeps today's behavior; an empty list disables every day.showClearButtonallows a Clear button inshowNepaliCalendar(off by default). Even when enabled it only appears when the sheet opened on a value the caller already held, viainitialSelection— not just because the user tapped a day in this session (Cancel already covers undoing an in-progress pick). Pressing it resolves toNepaliCalendarSelection.cleared()rather than plainnull, so a caller can tell "the user explicitly removed the value" apart from "the user backed out via Cancel, leave it alone" — both used to be indistinguishable.clearLabeloverrides its text;NepaliCalendarSelection.isClearedis the flag to check. Styled as a compact outlined button, tinted red, so it's visually distinct from Cancel and reads as the irreversible action it is.initialSelectionpreselectsshowNepaliCalendarwith a value you already hold — typically whatever it returned last time. Reopening the sheet used to always start blank, with no way to show a previous pick; now passing the sameNepaliCalendarSelectionback in shows it already selected and opens on its month instead ofstartDate's.HorizontalDateStrip's own calendar button does this automatically with the strip's current value.null(the default) keeps the existing "nothing preselected" behavior.
Fixed #
- The sheet and strip no longer re-render the whole month grid on every tap — a controller update now only triggers a rebuild when the selection or calendar system actually changed, and month pages are memoized so an unrelated rebuild reuses the previous cells instead of recomputing them.
- Swiping between months no longer computes the visible page's cells twice.
- The header title no longer recomputes on every scroll frame while a month transition is animating — only once the page settles.
NepaliHolidaynow has value-based equality, so passing an equal-but-new holiday list on rebuild no longer forces the holiday lookup to recompute.endDate/durationDaysordering is now validated for real in release builds (previously only a debug-only assertion), so an inverted or non-positive window throws a clearArgumentErrorinstead of silently leaving nothing selectable.NepaliDateRange.daysno longer throws whenendisNepaliDate.max, and is now considerably cheaper on multi-month spans.HorizontalDateStrip's "today" indicator no longer reads from a fresh conversion on every build.
Docs #
- Added a "Nepali fiscal year windows" recipe to the README, showing how to
cap a picker at today for the current fiscal year while leaving a past one
fully open — built entirely from
NepaliDate's existing comparison operators,lastDayOfMonthand.now(), no new package API involved. - The example app now demonstrates that recipe, including parsing fiscal-year
bounds from server-supplied
"yyyy-MM-dd"strings — seeexample/lib/fiscal_year.dart. - The example app's date and range pickers both now demonstrate
showClearButton+initialSelectiontogether — pick a date, close, and reopen to see it preselected with Clear available; press Clear to see the result reflect that explicitly, distinct from Cancel.
3.1.1 #
Fixed #
- Docs: README screenshots pointed at relative
doc/screenshots/*.pngpaths, which pub.dev's README renderer cannot resolve — it silently drops the image and leaves the alt text instead. They now point at absoluteraw.githubusercontent.comURLs pinned to this release's tag.
3.1.0 #
Added #
holidaysmarks specific days with a caller-chosen colour — pass an organization's holiday list and each day in it is painted in its own colour wherever it falls in the visible window. Each entry is aNepaliHoliday(type,dates,color);typeis free-form and carried through purely for the caller's own bookkeeping. Taken by bothshowNepaliCalendarandHorizontalDateStrip, which forwards it into the sheet its button opens.
3.0.0 #
Breaking #
- Removed
titlefromshowNepaliCalendar. The calendar does not need a title of its own — the surrounding screen already says what is being picked. Drop the argument; nothing else changes.
2.1.1 #
Fixed #
titleis drawn as a heading at the top of the sheet/dialog, above the calendar. It used to sit between the grid and the buttons, where it read as a stray caption rather than a title. No API change —titlewas, and stays, optional.
2.1.0 #
Added #
presentationchooses where the calendar appears:NepaliCalendarPresentation.bottomSheet(the default, unchanged) orNepaliCalendarPresentation.centerfor a dialog in the middle of the screen. Both return the same value and honourisDismissible.HorizontalDateStriptakes it too, for the calendar behind its button.
Fixed #
- Switching to AD froze the calendar when the window reached the start of the supported range. The header converts the visible Gregorian month's first day to Bikram Sambat, and April 1913 opens twelve days before 1 Baishakh 1970, so that conversion threw mid-build. Conversions at both edges now clamp into the supported range.
- The confirm button was invisible while disabled whenever the calendar's palette
and the host app's brightness disagreed — a dark calendar in a light app took
Material's ambient disabled colours and vanished against its own background.
Those colours now come from the calendar's own
textColor.
2.0.1 #
- Docs:
HorizontalDateStripshipped in 2.0.0 without any documentation — it is now covered in the README with usage and a parameter table, and the example app demonstrates it alongside the bottom sheet.
2.0.0 #
Breaking #
themeis now required. Every field ofNepaliCalendarThemestill has a default, soconst NepaliCalendarTheme()remains valid to pass; the change is that the palette is always an explicit decision at the call site.allowedRangeandmaxDaysare replaced by a requiredstartDateplus an optionalendDateordurationDays— two ways of saying where the window closes, of which at most one may be given.durationDayscounts the start day, sodurationDays: 90means the start plus the next 89. The window bounds navigation as well as selection, in both modes and both calendar systems.isDismissiblenow defaults tofalse, so the sheet is modal: a tap on the barrier or a downward drag no longer discards a half-finished range, and the user leaves through Cancel or Done. PassisDismissible: truefor the old behaviour.
Added #
HorizontalDateStrip, an inline row of consecutive days with the full calendar one tap away. Takes the samestartDate/endDate/durationDayswindow, shows "Today" or the month above each date and the weekday below, selects a day on first build and reports it, and re-anchors when a date outside the strip is picked from the calendar.
Fixed #
- The "Today" button slid to the leading edge of the header when
showSystemSwitchwasfalse, instead of staying on the trailing edge. - The selected segment of the BS/AD switch was unreadable in dark palettes: its
pill fell back to
backgroundColorwhile its label usedprimaryColor, two near-identical darks. The pill now falls back toheaderTextColor, which is the colour already chosen to be legible against the header. - The
MMMformat token no longer abbreviates Devanagari month names, which could separate a vowel mark from its consonant. - The package description was over pub.dev's 180-character limit, costing 10 pub points.
Notes #
- Light and dark both run through the single
themeparameter: passNepaliCalendarTheme.fromTheme(Theme.of(context))to follow the host app including its brightness, orNepaliCalendarTheme.dark()for a fixed dark look.
1.0.0 #
Initial release.
showNepaliCalendar— one call opens a Nepali (Bikram Sambat) date picker in a modal bottom sheet and returns aNepaliCalendarSelection?, ornullwhen the user dismisses it.- Single day or start/end range via
mode; the range's in-between days are banded and confirm stays disabled until both ends are picked. - Caller-supplied colours, fonts and metrics through
NepaliCalendarTheme, with usable defaults, adark()preset andfromTheme(...)to follow the host app'sColorScheme. allowedRangeandmaxDaysbound the calendar — days outside grey out and the month arrows stop at the window's edges. Omit both for the full supported range.- Live Bikram Sambat / Gregorian switch inside the sheet that preserves the selection, and English or Nepali labels chosen by the caller.
NepaliDateandNepaliDateRangevalue types with validation, arithmetic, comparison and pattern formatting, plusDateConverterfor BS ⇄ AD conversion with no UI involved.- Bikram Sambat coverage BS 1970–2199 (AD 1913-04-13 – 2143-04-15), from a hard-coded month-length table anchored at 1 Baishakh 1970 BS = 13 April 1913 AD and verified against known Nepali New Year dates.
- No third-party dependencies, no platform channels, no native code.
