Skip to content

fix(bulma-ui): read picker bounds and months in years 0 to 99 as written - #890

Merged
allxsmith merged 5 commits into
mainfrom
fix/date-bounds-early-years
Oct 5, 2026
Merged

allxsmith merged 5 commits into
mainfrom
fix/date-bounds-early-years

Conversation

@allxsmith

@allxsmith allxsmith commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

The picker's date helpers built dates with the multi-argument Date constructor, which reads years 0 to 99 as 1900 to 1999. #866 added a setter-based makeDate for the month and year grids; this moves the sites below onto it.

  • startOfDay and endOfDay, which normalize min and max, so a bound in those years was misread.
  • startOfMonth and endOfMonth, the same bug in the same file: startOfMonth lays out the day grid, so a year-19 month drew 1919 and disabled every day, and month keyboard navigation compares against it.
  • The month-length clamp in addMonths, which read February of year 0 as February 1900, not a leap year, and its twin daysInMonth in segmented typing.
  • The native inputs' read-back, fromIsoValue and fromIsoDateTime, so a native date pick in year 19 committed 1919. They also take a year of four or more digits now, as HTML allows, so a pick past 9999 commits that date instead of null.
  • toIsoDateTime, which didn't pad the year, so a year below 1000 gave datetime-local an invalid value, min, and max. It pads to four digits now, as toIsoValue already did.
  • parseDate, the pickers' default parse. The field shows year 19 as 0019, and the old round-trip check turned that into null, so the field couldn't read its own text back. This is the one change a user sees in free-text entry: a typed year below 100 now parses to that year, and dates like 30 February are still rejected.

New tests cover each of these. Year 0 and earlier still don't fit the native inputs, which is a product decision tracked in #902.

pnpm all passes locally.

The picker's day and month boundaries built dates with the multi-argument `Date` constructor,
which reads years 0 to 99 as 1900 to 1999. A `min` or `max` in those years was misread wherever
it passed through `startOfDay` or `endOfDay`, so a month picker ruled out a month a year-19 `min`
only cut partway through, and a year-19 `max` failed to rule out the months after it.
`startOfMonth` had the same flaw, and the day grid is built from it, so a calendar showing a
year-19 month laid out the 1919 one and disabled every day against a year-19 range.

`startOfDay`, `endOfDay`, `startOfMonth` and `endOfMonth` now build on the setter-based
`makeDate` that the month and year grids already use, and so does the month-length clamp in
`addMonths`, which read February of year 0 as the non-leap 1900.

New tests pin a year-19 bound in the boundary helpers, in `isPeriodUnselectable`, on the day
grid and on the month grid, plus the year-0 clamp. Each fails on the constructor-based helpers.
@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 41 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: allxsmith/bestax/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 29530fa9-1a8e-49f2-b5f0-03a10a08c385
📥 Commits

Reviewing files that changed from the base of the PR and between 99426b4 and e4e0466.

📒 Files selected for processing (11)
  • bulma-ui/src/form/DateInputBase.tsx
  • bulma-ui/src/form/DateTimeInputBase.tsx
  • bulma-ui/src/form/__tests__/Calendar.test.tsx
  • bulma-ui/src/form/__tests__/DateInput.test.tsx
  • bulma-ui/src/form/__tests__/DateTimeInput.test.tsx
  • bulma-ui/src/form/__tests__/dateUtils.test.ts
  • bulma-ui/src/form/__tests__/formatters.test.ts
  • bulma-ui/src/form/__tests__/segmentMap.test.ts
  • bulma-ui/src/form/_pickerInternals/dateUtils.ts
  • bulma-ui/src/form/_pickerInternals/formatters.ts
  • bulma-ui/src/form/_pickerInternals/segmentMap.ts
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://454e0fd7.bestax.pages.dev

Comment thread bulma-ui/src/form/_pickerInternals/dateUtils.ts Outdated
Comment thread bulma-ui/src/form/_pickerInternals/dateUtils.ts

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep review — 2 blocking · 3 advisory

# Severity Area Finding Location
1 🟠 Major Correctness Native day picker's ISO read-back still remaps years 0–99 (new Date(19, …) → 1919), while the 'month' branch beside it already uses makeDate; min/max reach the same input through the padded toIsoValue, so the bound fix is undone one layer up bulma-ui/src/form/DateInputBase.tsx:68
2 🟡 Minor Correctness The month-length clamp this PR fixed in addMonths has a byte-for-byte twin in segmented keyboard entry, feeding five clamps; 29 February year 0 clamps to the 28th bulma-ui/src/form/_pickerInternals/segmentMap.ts:156
3 🔵 Advisory Correctness parseDate is still constructor-based. The PR body's reasoning is right — the round-trip check nulls any year below 100 rather than misreading it — but the consequence is that a year-0–99 bound or value can only ever be set programmatically, never typed, so the day/month grids this PR fixes are reachable with such a year only from props bulma-ui/src/form/_pickerInternals/formatters.ts:144
4 🔵 Advisory Robustness toIsoDateTime does not pad the year (DateInputBase.toIsoValue does), so DateTimeInput's native round trip for a year below 1000 fails the \d{4} regex on read-back instead of misreading it. Pre-existing and outside this PR's stated scope — on the record because it is why finding 1's twin at DateTimeInputBase.tsx:62 is harder to reach bulma-ui/src/form/DateTimeInputBase.tsx:41
5 🔵 Advisory API The new free-floating comment scopes the change to min/max, but startOfMonth also lays out the day grid — which the commit message says and this comment does not. Imprecise rather than false; deleting the "a min or max" clause so it reads "…so a date in years 0–99 keeps its year" would cover both bulma-ui/src/form/_pickerInternals/dateUtils.ts:35

Overall: The core change is sound and well-targeted — swapping the four boundary helpers and the addMonths clamp onto the setter-based makeDate is semantically identical for years ≥ 100 (both paths go through MakeDay/MakeTime), endOfMonth's makeDate(y, m + 1, 0) handles the December wrap correctly via setFullYear's month-overflow rule, and Invalid Date / negative / out-of-range years behave exactly as before. Every new test is a genuine regression test: each one's assertion is falsified by the pre-fix expression (startOfDay → 1919-02-20, the day grid built from 1919-06-01, isPeriodUnselectable comparing a year-19 June against a 1919 min, and the year-0 February clamp returning 28). The riskiest part is not what the diff changed but what it did not: the same constructor remains in two adjacent executable paths that the fixed helpers hand off to, and finding 1 is the only place left where an early year produces a silently wrong value rather than a wrong-looking grid. Look at that one first.

Residual risk:

  • Refuted — the four rewritten helpers for ordinary years. makeDate seeds from new Date(2000, 0, 1), so TimeWithinDay is 0 and setFullYear(y, m, d) reduces to the same MakeDay/local-offset computation the constructor performs; endOfDay/endOfMonth's added setHours(23, 59, 59, 999) is the same MakeTime the old literal arguments produced. All 38 src/form suites (1636 tests) pass on the branch.
  • Refuted — endOfMonth on December. makeDate(y, 12, 0) relies on MakeDay's ym = y + floor(m / 12): month 12 resolves to January of y + 1, day 0 steps back to 31 December of y. The pre-existing endOfMonth tests (including the non-leap February case) still pass.
  • Refuted — parseDate. formatters.ts:145-152 re-reads getFullYear()/getMonth()/getDate() off the constructed date and returns null on any mismatch, so a parsed year below 100 is rejected, never misread. The PR body's claim checks out.
  • Refuted — no other remaining sites in picker source. A grep for multi-argument new Date( across non-test bulma-ui/src leaves only the three findings above plus formatters.ts:317,334, which build fixed 2021 reference dates to harvest weekday/month names and never see a caller's year.
  • Open (posted as finding 1) — DateInputBase.fromIsoValue, day granularity: the native <input type="date"> round trip. This is the one that matters, because toIsoValue deliberately pads the year to four digits, so our own serialization does feed it 000Y-MM-DD.
  • Open (posted as finding 2) — segmentMap.daysInMonth, the twin of the clamp the diff fixed. Narrow: among years 0–99 only year 0's February length differs from its 19xx remap, so the visible defect is confined to 29 February year 0.
  • Open (bullet, not posted) — DateTimeInputBase.fromIsoDateTime at line 62 carries finding 1's exact expression, but its serializer does not zero-pad the year, so reaching it needs a native datetime-local to hand back a 000Y-… string on its own rather than echoing ours. Same one-word fix if finding 1 is taken.

Note on anchoring: both blocking findings live in files this PR does not touch, so GitHub rejects a line comment there. They are anchored on the nearest diff line in dateUtils.ts (the new boundary comment and the fixed addMonths clamp) and each names its real file and line in the body.

🏄 Clean little set-and-forget, dude — the gnarly 1900-year rip in the bounds is patched, and every new test actually wipes out on the old code, which is how you know they're real. Just two spots downstream still paddling the old board; grab fromIsoValue before you call it glassy.

Review of the early-year bounds fix found two more places that build dates with the
multi-argument constructor and so read years 0 to 99 as 1900 to 1999.

The native day picker read its ISO value back that way, so picking 4 March 0019 committed
4 March 1919, even with a year-19 `min` and `max` reaching the input through the padded
`toIsoValue`. The month branch beside it already used `makeDate`. The day branch now does too,
and so does DateTimeInput's `datetime-local` read-back, which then sets the time with
`setHours`.

Segmented entry clamps the day with its own month-length helper, a twin of the one in
`addMonths`. It read February of year 0 as February 1900, so typing 29 clamped to the 28th and
a year typed on the way to four digits pulled 29 February back a day. It now builds on
`makeDate` as well.

The boundary comment in dateUtils no longer limits the change to `min` and `max`, since
`startOfMonth` also lays out the day grid. New tests cover both read-backs and both segment
clamps, and each fails on the previous head.
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://569946de.bestax.pages.dev

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep review (verify) — 2 resolved · 0 open

# Severity Area Finding Location
1 🟠 Major Correctness Native day/datetime read-back remapped years 0–99 — fixed, resolved bulma-ui/src/form/DateInputBase.tsx:68
2 🟡 Minor Correctness The daysInMonth twin in segmentMap was left on the multi-arg constructor — fixed, resolved bulma-ui/src/form/_pickerInternals/segmentMap.ts:159

What I checked

  • #1 — the day branch of fromIsoValue (DateInputBase.tsx:68) now calls makeDate, matching the month branch beside it. DateTimeInputBase.fromIsoDateTime (DateTimeInputBase.tsx:61-62) was converted too, splitting the old 7-argument constructor into makeDate(...) plus setHours(h, m, s, 0) — behaviourally equivalent, and the explicit 0 keeps milliseconds pinned, which the new assertion checks alongside the dropped-fractional-seconds path. New tests commit 0019-03-04 and 0019-03-04T14:30:55 back as year 19, and the first also asserts native.min === "0019-01-01", so the padded toIsoValue → read-back round trip is closed end to end.
  • #2 — segmentMap.ts:159-160 builds on the now-imported makeDate (line 15), so all five consumers — the month increment (189), the day-increment wrap modulus (194), and the year / month / day digit writes (260, 272, 283) — see February of year 0 as 29 days. The three new assertions pin the increment (28 Feb year 0 → the 29th), the day write (29 holds), and a year-0 digit write off 29 Feb 2024.

Tests run: the four date suites (DateInput, DateTimeInput, segmentMap, dateUtils) — 314 passed; -t "year below 100" — 13 passed. I could not re-run the suites against the pre-fix source (reverting the three files was not permitted in this sandbox), so the "fails on previous head" claim rests on the ECMAScript semantics the findings cited (new Date(19, …) → 1919; 1900 is not a leap year while year 0 is) plus the year-0 and year-19 assertions in the tests themselves, which cannot pass through the old constructor.

Overall: this pass settled the two open threads and reviewed no commits. Both findings are genuinely fixed at the sites named, with tests that pin the exact boundaries, and the only non-mechanical edit — the fromIsoDateTime split — preserves the time-of-day and millisecond behaviour the surrounding tests already cover. Nothing is left open; a human reviewing this should focus on whether the deliberate parseDate exemption (a year below 100 becomes null), called out in the PR body, is the behaviour they want for typed text input.

Residual risk: verify-pass scope — the ways the early-year class could still occur were enumerated in the residual-risk section of the prior review and are not re-opened here. Of what that pass flagged, both executable gaps are now closed; the one remaining acknowledged path is the round-trip check in parseDate, which fails closed to null rather than misreading, and is documented as intentional in the PR body.

🏄 Two gnarly little 1900-year riptides got patched clean, brah — every early-year date now rides its own wave from the native input all the way through segment typing. Threads closed, tests green, this one is good to paddle out.

@allxsmith allxsmith added the needs-human-review Loop converged (or contested): awaiting owner review + manual merge label Oct 4, 2026
@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

📸 Story screenshots at handoff — e4e0466

No Storybook stories map to this PR's changed files — nothing to screenshot. (workflow run)

@github-actions github-actions Bot added the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 4, 2026
@allxsmith allxsmith removed the needs-human-review Loop converged (or contested): awaiting owner review + manual merge label Oct 4, 2026
`parseDate` was the last picker path still building dates with the multi-argument constructor.
Its round-trip check turned a year below 100 into null rather than misreading it, but the
`YYYY` token displays year 19 as `0019`, so the text the field shows for such a value could
not be parsed back, and typing it free-form was refused. It now builds on `makeDate` and sets
the time with `setHours`, keeping the round-trip check that rejects dates like 30 February.

DateTimeInput's `toIsoDateTime` did not pad the year, unlike DateInput's `toIsoValue`, so a
year below 1000 gave the native `datetime-local` input an invalid value, min and max, and it
showed nothing. It now pads to four digits, which the inline form value shares.

Both new tests fail on the previous head.
@github-actions github-actions Bot removed the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 4, 2026
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://c30b9850.bestax.pages.dev

@allxsmith

Copy link
Copy Markdown
Owner Author

Every finding from the reviews, fixed or answered:

  1. The native day picker's read-back: fixed in 306589c, verified by the last pass.
  2. segmentMap's month-length clamp: fixed in 306589c, verified by the last pass.
  3. parseDate still used the constructor: fixed in 5bfaf3c. The field pads year 19 to 0019, so it couldn't read its own text back; it now builds on makeDate and still rejects dates like 30 February.
  4. toIsoDateTime didn't pad the year: fixed in 5bfaf3c. It pads to four digits, so a year below 1000 gives datetime-local a valid value, min and max, and the inline form value shares the helper.
  5. The dateUtils comment scoped the change to bounds: fixed in 306589c.

Both new tests fail on 306589c.

@allxsmith

Copy link
Copy Markdown
Owner Author

deep-review: fresh

The advisories from the last review are fixed or answered in the comment above; this reviews 5bfaf3c.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep review — 0 blocking · 3 advisory

# Severity Area Finding Location
1 🔵 Advisory Robustness Year 0 still cannot reach the native inputs: both ISO builders now emit 0000-01-01…, and the HTML valid-date grammar requires year > 0, so a year-0 value/min/max is silently dropped by <input type="date"> / datetime-local. Not a regression (the unpadded 0-01-01… was invalid too), and year 0 is only ever transient in segmented typing, which does not render the native input — but the helper-level tests in this PR pin year 0, so the asymmetry is worth recording bulma-ui/src/form/DateTimeInputBase.tsx:43
2 🔵 Advisory Robustness Years above 9999 are the mirror hole: padStart(4, "0") does not truncate, so toIsoDateTime/toIsoValue emit a 5-digit year that the anchored ^(\d{4})- read-back regexes cannot match, and a native pick in such a year commits null. Pre-existing on both sides of the round trip and untouched here bulma-ui/src/form/DateTimeInputBase.tsx:54
3 🔵 Advisory Robustness Negative (BCE) years: String(-5).padStart(4, "0") → 00-5, an invalid native value, so the bound is ignored rather than enforced — again the same outcome as before the padding. Adjacent to this: with an early focused year and no min, the default year window in Calendar is windowYear - 100, so a year-19 picker lists years down to -81, and makeDate builds them happily. Untouched file, and the no-min/max case only bulma-ui/src/form/_pickerInternals/Calendar.tsx:429

Overall: Sound, and now complete for the failure class it names. Every date-bearing construction in bulma-ui/src/form is off the multi-argument Date constructor: a grep of the tree leaves only parseTime, TimeInputBase.fromIsoTime (both anchored on the current year, so the 0–99 remap is unreachable), the fixed 2021 anchors in getDayNames/getMonthNames, and the new Date(2000, 0, 1) base inside makeDate. The two non-mechanical edits are the riskiest part and both check out: splitting parseDate into makeDate(...) + setHours(h, m, s, 0) is behaviourally identical to the old 7-argument call for every year ≥ 100 — including the day-overflow (2024-02-30 → null), spring-forward (2024-03-10 02:30 → 03:30) and whole-day-skip (Pacific/Apia 2011-12-30 → null) cases, because the round-trip guard is unchanged and both paths resolve the same local time — and endOfMonth with makeDate(y, m + 1, 0) wraps December correctly through the month-overflow rule of setFullYear (setFullYear(19, 12, 0) → 31 Dec year 19). A human should look first at advisory 1: the helper tests here treat year 0 as in scope, while the native input path can still only represent years 1–9999.

Residual risk:

  • Other picker paths that lay out early years — refuted. buildMonthGrid goes through startOfMonth/addDays (setters), the month grid through makeDate(focusedYear, m), the year grid through makeDate(year) and setFullYear, and the header step through addMonths/addYears, whose clamp this PR moved onto makeDate. The prevDisabled/nextDisabled comparisons in Calendar are made against startOfDay(min)/startOfDay(max), so they are fixed by the same diff.
  • Segmented keyboard entry through an early year — refuted. The year digit write uses next.setFullYear(yr), and the month/day/increment clamps all route through the now-fixed daysInMonth; the three new segmentMap assertions pin February of year 0 at 29 days for the increment, the day write and a year-0 digit write.
  • A displayed early-year value that cannot be typed back — refuted. YYYY renders year 19 as 0019 and parseDate("0019-03-04 14:30", …) now returns year 19, while parseDate("0019-02-29") still returns null (19 is not a leap year), so the round-trip guard is intact. YY is unaffected — it maps into the 2000s before any date is built.
  • Native round trip for years 1–999 — refuted end to end: native.min === "0019-01-01" plus a 0019-03-04 change event committing year 19 for DateInput, and "0019-03-04T14:30" with native.min === "0019-01-01T09:00" for DateTimeInput.
  • Open: years 0, above 9999, and negative years on the native path (advisories 1–3). All three are limits of the HTML value grammar or of the fixed-width read-back regexes rather than year remapping, and none is a regression from this diff.
  • Verification note: the three source files could not be reverted in this sandbox, so the claim that the new tests fail on main rests on the ECMAScript semantics those tests encode (new Date(19, …) → 1919; year 0 is a leap year while 1900 is not; an unpadded 19-03-04T14:30 is not a valid datetime-local value) plus assertions that cannot hold through the old constructor. Run here on the PR head: the six date suites — 462 passed; the whole src/form tree with coverage — 1642 passed, with dateUtils.ts and segmentMap.ts at 100% statements and branches and src/form overall at 99.73% / 99.35%; typecheck:tests clean; prettier clean on all eleven changed files. No public API moved — parseDate is internal — so no docs, story or skills/ update is owed.

🏄 Three commits of patient paddling and the early-year swell is fully ridden — every new Date(19, …) trap in the picker is off the reef, the new tests actually bite, and the only water left is the year-0 and five-digit shorebreak that HTML itself will not let you surf. Clean ride, good to go.

@github-actions github-actions Bot added the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 4, 2026
@allxsmith

Copy link
Copy Markdown
Owner Author

On the latest review's findings, all answered with no code change:

  1. Year 0 can't reach the native inputs: refuted. HTML's valid date grammar requires a year above 0, so <input type="date"> and datetime-local can't represent year 0 however it's written; 0-01-01 was dropped before this PR and 0000-01-01 is dropped now. Year 0 only appears in passing while segmented typing builds a four-digit year, and segmented entry doesn't render the native input. This PR claims years 1 to 99.
  2. Years above 9999 don't round-trip: refuted. No one picks a date past 9999, and the hole is on both sides of the round trip before this PR: the read-back patterns and parseDate's YYYY token take exactly four digits. Widening them changes text parsing this PR doesn't touch, for an input no user hits.
  3. Negative years, and the calendar's year window: refuted. Native date inputs can't represent negative years, so such a bound was ignored before this PR and still is. The year window reaching below 0 needs an early focused year with no min, sits in a file this PR doesn't touch, and builds valid dates; neither is the 1900-to-1999 misreading this PR fixes.

@github-actions github-actions Bot removed the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 5, 2026
@allxsmith

Copy link
Copy Markdown
Owner Author

deep-review: fresh

Main is merged in, so this review posts every finding, advisory included, as its own thread. It reviews ddaa7e6.

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://19ce7e49.bestax.pages.dev

Comment thread bulma-ui/src/form/DateInputBase.tsx
Comment thread bulma-ui/src/form/DateTimeInputBase.tsx
Comment thread bulma-ui/src/form/DateTimeInputBase.tsx

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep review — 1 blocking · 2 advisory

# Severity Area Finding Location
1 🟡 Minor Correctness PR body describes only the first of three commits, and its parseDate paragraph is now the opposite of the code: a year below 100 typed into the field parses rather than becoming null bulma-ui/src/form/DateInputBase.tsx:68 (PR body — no line of its own)
2 🔵 Advisory Robustness Year 0 cannot reach either native input: 0000-… fails HTML's "year > 0" rule, while the helpers this PR tests pin year 0 bulma-ui/src/form/DateTimeInputBase.tsx:43
3 🔵 Advisory Robustness The mirror hole — a 5-digit year serializes fine but the \d{4} read-back rejects it (native pick commits null); a negative year emits 00-5 and the bound is ignored bulma-ui/src/form/DateTimeInputBase.tsx:62

Overall: the change is sound and, as of the third commit, complete for the failure class it names. Every date-bearing construction in bulma-ui/src/form is now off the multi-argument Date constructor — a grep of non-test source leaves only parseTime / TimeInputBase.fromIsoTime (anchored on the current year, so the 0–99 remap is unreachable), the fixed 2021 anchors in getDayNames/getMonthNames, and makeDate's own new Date(2000, 0, 1) seed. The two non-mechanical edits both check out: splitting parseDate and fromIsoDateTime into makeDate(…) + setHours(h, m, s, 0) is behaviourally identical to the old 7-argument calls for every year ≥ 100, because makeDate seeds at local midnight so TimeWithinDay is 0 and setFullYear reduces to the same MakeDay, and the explicit trailing 0 keeps milliseconds pinned; endOfMonth's makeDate(y, m + 1, 0) wraps December through setFullYear's month-overflow rule. The riskiest thing left is not in the code — it is that the PR body now tells a reviewer the one public behaviour change (free-text entry of 0019-03-04 committing year 19 instead of null) did not happen. Look at finding 1 first and decide that change on purpose.

Empirically verified here on ddaa7e68: all 38 src/form suites, 1678 tests passed; with coverage, dateUtils.ts and segmentMap.ts at 100% statements/branches/functions/lines, DateTimeInputBase.tsx 100% statements, formatters.ts 99.4%, DateInputBase.tsx 100% lines — no coverage gap in any of the new code. No public export moved (parseDate, makeDate and daysInMonth are all internal; src/index.ts is untouched), so no story, API page or skills/ update is owed.

Residual risk:

  • Native day and datetime round trip for years 1–999 — refuted end to end, not just by reading. DateInput: native.min === "0019-01-01" and a 0019-03-04 change event commits year 19. DateTimeInput: native.value === "0019-03-04T14:30", native.min === "0019-01-01T09:00", and 0019-03-04T14:30:55 commits [19, 2, 4, 14, 30, 55, 0].
  • year granularity on the native path — refuted as unreachable, which is why fromIsoValue's missing year branch is not a finding. DateInputBase.tsx:323-325 gates hasNativeInput on isDayGranularity || (granularity === 'month' && …), so a year picker never renders a native control however mobileNative is set, and the existing test at DateInput.test.tsx:1667 asserts exactly that.
  • Grid layout and keyboard navigation in an early year — refuted. buildMonthGrid goes through the now-fixed startOfMonth + addDays, the month grid through makeDate(focusedYear, m), the year grid through makeDate(year) / setFullYear, the header step through addMonths/addYears (whose clamp this PR moved onto makeDate), and prevDisabled/nextDisabled compare against startOfDay(min) / startOfDay(max). The new Calendar tests pin a year-19 day grid (10…20 enabled) and a year-19 month grid.
  • Segmented keyboard entry passing through an early year — refuted. The year write is setFullYear, and the month/day/increment clamps all route through the fixed daysInMonth; three new assertions pin February of year 0 at 29 days for the increment, the day write and a year-0 digit write.
  • DST-sensitive paths through the new makeDate + setHours split — refuted by the ECMAScript UTC(t) disambiguation rule: for a skipped local time the pre-transition offset is used, which moves the result forward, so makeDate can never land on the previous local day and setHours can never write the time onto the wrong date. The existing spring-forward, fall-back and skipped-day cases in formatters.test.ts and dateUtils.test.ts still pass.
  • Open, not posted as a finding: makeDate seeds from new Date(2000, 0, 1) and never calls setHours(0, 0, 0, 0), so it is correct only while that seed is exactly local midnight. I could find no IANA zone that skips 2000-01-01T00:00, and makeDate predates this PR (#866) — but this PR routes startOfDay, startOfMonth, endOfDay, endOfMonth and parseDate through it, which is what makes the seed load-bearing for the library's normalization primitives rather than for two grid builders. A one-line d.setHours(0, 0, 0, 0) would remove the assumption.
  • Open (findings 2 and 3): years 0, above 9999, and negative years on the native path. All three are limits of the HTML value grammar or of the fixed-width read-back regexes rather than year remapping, and none is a regression from this diff.
  • Verification note: reverting the five source files to 836e20b5 to re-run the new tests against pre-fix code was not permitted in this sandbox, so the "each fails on main" claim rests on the ECMAScript semantics those tests encode (new Date(19, …) → 1919; year 0 is a leap year while 1900 is not; an unpadded 19-03-04T14:30 is not a valid datetime-local value) — assertions that cannot hold through the old constructor.

🏄 Three commits deep and the early-year swell is fully ridden, brah — every new Date(19, …) reef break in the picker is cleared, coverage is glassy at 100% on both helper files, and the new tests actually bite. Only thing out of trim is the write-up on the back of the board: it still says you never paddled out for parseDate, and you did. Tidy that caption and this one is good to go.

HTML allows a date, month or datetime-local value a year of four or more
digits, and toIsoValue and toIsoDateTime pad without truncating, so they
write year 10000 as 10000-01-01. The read-back patterns took exactly four
digits, so a native pick in such a year committed null instead of the date.
They now take four or more.
@allxsmith

Copy link
Copy Markdown
Owner Author

deep-review: verify

Every open thread has a reply: fixed, with the commit, or refuted with a reason. This settles them on e4e0466.

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://c1bdf6ea.bestax.pages.dev

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep review (verify) — 3 resolved · 0 open

# Thread Outcome Location
1 PR body contradicted the code it described ✅ Verified fixed bulma-ui/src/form/DateInputBase.tsx:71 (body finding, no line of its own)
2 Year 0 cannot reach either native input (🔵 Advisory) ✅ Reason accepted bulma-ui/src/form/DateTimeInputBase.tsx:43
3 Years outside 1–9999 fall out of the native round trip (🔵 Advisory) ✅ Verified fixed + reason accepted bulma-ui/src/form/DateTimeInputBase.tsx:63

What I checked

  • Thread 1 — the rewritten body no longer says parseDate was left alone; it names parseDate as the one user-visible change to free-text entry, and lists the sites the later commits touched (daysInMonth, both native read-backs with their four-or-more-digit years, and the toIsoDateTime padding).
  • Thread 2 — refuted by the PR author (live role admin): the HTML date grammar admits no year at or below zero, so there is no alternative value the serializer could write, and the behaviour choice is tracked in #902. That issue exists, is open, and names exactly this. The reason holds.
  • Thread 3 — the five-digit half is genuinely fixed in e4e04660: fromIsoDateTime (DateTimeInputBase.tsx:59) and both fromIsoValue branches (DateInputBase.tsx:66,69) now match a year of four or more digits, with tests round-tripping a year-10000 native pick through the date, month and datetime-local inputs. The negative-year row and the untouched Calendar default year window are accepted as the same product decision tracked in #902.
  • Ran the picker suites — DateInput, DateInput.styles, DateTimeInput, dateUtils, formatters, segmentMap: 453 tests, all passing.

Overall: this pass settled threads and reviewed no commits. All three open threads are now resolved — one PR-body fix, one code fix verified against its tests, and two advisory limitations accepted as a deliberate product decision tracked in #902. Nothing of mine is left open; a reader who wants the current code reviewed afresh should ask for a fresh pass.

Residual risk: out of scope for a verify pass — no new findings were sought or raised. The one risk the settled threads leave standing is already on the record in #902: years at or below zero still cannot be carried by the native inputs, and the Calendar default year list and the YYYY token have no defined behaviour there.

🏄 Three threads paddled in clean — one patched, one coded, two waved through with a real reason and an issue number to back it. No chop left on the water; this one is good to go.

@github-actions github-actions Bot added the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 5, 2026
@allxsmith allxsmith added the needs-human-review Loop converged (or contested): awaiting owner review + manual merge label Oct 5, 2026
@github-actions github-actions Bot added review-converged Deep review converged: no blocking findings, all review threads resolved, checks green and removed review-converged Deep review converged: no blocking findings, all review threads resolved, checks green labels Oct 5, 2026
@allxsmith
allxsmith merged commit 02fb619 into main Oct 5, 2026
79 checks passed
@allxsmith
allxsmith deleted the fix/date-bounds-early-years branch October 5, 2026 11:41
bestax-release-bot Bot pushed a commit that referenced this pull request Oct 5, 2026
## [5.26.3](https://github.com/allxsmith/bestax/compare/@allxsmith/bestax-bulma@5.26.2...@allxsmith/bestax-bulma@5.26.3) (2026-10-05)

### Bug Fixes

* **bulma-ui:** fire the pickers' onOpen and onClose once under StrictMode ([#896](#896)) ([20b51ed](20b51ed))
* **bulma-ui:** let focus follow the keys in an inline calendar, and skip disabled days for the tab stop ([#885](#885)) ([f55af27](f55af27))
* **bulma-ui:** make Theme colorMode switch the scheme under the prefixed builds ([#894](#894)) ([2bd6ec2](2bd6ec2))
* **bulma-ui:** place a portaled picker panel by its coordinates alone ([#886](#886)) ([040299b](040299b))
* **bulma-ui:** read picker bounds and months in years 0 to 99 as written ([#890](#890)) ([02fb619](02fb619))
* **bulma-ui:** start a date picker's focus on the focused cell ([#897](#897)) ([6a55714](6a55714))
* **bulma-ui:** stop the indeterminate progress bar and skeleton pulse under reduced motion ([bcf5407](bcf5407))
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 5.26.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

bestax-release-bot Bot pushed a commit that referenced this pull request Oct 7, 2026
# [2.25.0](https://github.com/allxsmith/bestax/compare/bestax-migrate@2.24.0...bestax-migrate@2.25.0) (2026-10-07)

### Bug Fixes

* **bulma-ui:** announce polite notifications through a status region kept from mount ([#835](#835)) ([c93478d](c93478d))
* **bulma-ui:** answer the granularity review on native input and blur ([7a17486](7a17486))
* **bulma-ui:** attach useFocusTrap to a container that mounts after it turns on ([17a944d](17a944d))
* **bulma-ui:** bring File and Taginput under the bare-Control Field rule ([cdaa6c2](cdaa6c2))
* **bulma-ui:** clear a picker's unused seed whenever its popover closes ([cbe86c5](cbe86c5))
* **bulma-ui:** color the calendar from the color prop and read TimeInput's wheel variables ([2251e67](2251e67)), closes [#832](#832)
* **bulma-ui:** commit nothing when a picker popover is dismissed ([0a46209](0a46209))
* **bulma-ui:** commit nothing when Enter confirms untouched picker text ([773e146](773e146))
* **bulma-ui:** commit nothing when focus leaves a picker untouched ([30b4849](30b4849))
* **bulma-ui:** draw the time wheel focus ring where the wheel's mask shows it ([e1d8c9f](e1d8c9f)), closes [#832](#832)
* **bulma-ui:** fall back when useFocusTrap's initialFocusRef can't take focus ([c191931](c191931))
* **bulma-ui:** fire the pickers' onOpen and onClose once under StrictMode ([#896](#896)) ([20b51ed](20b51ed))
* **bulma-ui:** give the selected calendar cell a ring that shows on its fill ([b3eecc6](b3eecc6))
* **bulma-ui:** hide a picker's launcher for a loading Control it sits in ([9a3888e](9a3888e))
* **bulma-ui:** hide a picker's launcher only for the spinner it draws ([7a28a0e](7a28a0e))
* **bulma-ui:** hold Portal to looking a selector up on each render ([8fe02ce](8fe02ce))
* **bulma-ui:** hold the year-1 floor under a max before it ([4f6eb18](4f6eb18))
* **bulma-ui:** judge image map areas by their image in useFocusTrap ([af7bc59](af7bc59))
* **bulma-ui:** keep a tab stop in the year list when the year falls outside it ([fe028c1](fe028c1))
* **bulma-ui:** keep an empty picker's seed while a portaled popover is open ([1e66528](1e66528))
* **bulma-ui:** keep an inline date picker's calendar on its released id ([c26da07](c26da07)), closes [#897](#897) [#897](#897)
* **bulma-ui:** keep button defaults through a spread, and type the buttons that had none ([#853](#853)) ([0810482](0810482))
* **bulma-ui:** keep button types and Avatar's accessible name through a spread ([#826](#826)) ([dc798d4](dc798d4))
* **bulma-ui:** keep the Field for horizontal and fieldClassName in a bare Control ([e4dc513](e4dc513))
* **bulma-ui:** keep the picker focus rings visible in every color ([612aa09](612aa09))
* **bulma-ui:** let focus follow the keys in an inline calendar, and skip disabled days for the tab stop ([#885](#885)) ([f55af27](f55af27))
* **bulma-ui:** let the picker bases give way to a loading Control too ([66e803a](66e803a))
* **bulma-ui:** let useFocusTrap go of a container that leaves while it is on ([8c56d7a](8c56d7a))
* **bulma-ui:** make auto leave room for an in-place picker panel's themed offset ([8c534bd](8c534bd)), closes [#904](#904)
* **bulma-ui:** make Theme colorMode switch the scheme under the prefixed builds ([#894](#894)) ([2bd6ec2](2bd6ec2))
* **bulma-ui:** make useFocusTrap follow radio groups and initialFocusRef past the trap ([d6219d4](d6219d4))
* **bulma-ui:** match a picker's opening focus only inside its calendar ([e3c22ed](e3c22ed))
* **bulma-ui:** place a portaled picker panel by its coordinates alone ([#886](#886)) ([040299b](040299b))
* **bulma-ui:** place toasts and notifications at the position they were shown with ([#834](#834)) ([62feab9](62feab9))
* **bulma-ui:** read clicks and focus inside a shadow root ([474f2cc](474f2cc))
* **bulma-ui:** read picker bounds and months in years 0 to 99 as written ([#890](#890)) ([02fb619](02fb619))
* **bulma-ui:** restore a portaled Modal's focus to an opener in a shadow root ([c564bd3](c564bd3))
* **bulma-ui:** return focus to the input when a date picker closes ([b741264](b741264))
* **bulma-ui:** settle Popover's deep review findings ([feadaf4](feadaf4))
* **bulma-ui:** start a date picker's focus on the focused cell ([#897](#897)) ([6a55714](6a55714))
* **bulma-ui:** stop Bulma's spinners under reduced motion in every stylesheet ([b234712](b234712)), closes [#770](#770)
* **bulma-ui:** stop form wrappers nesting a Field in a bare Control ([2c6d295](2c6d295))
* **bulma-ui:** stop the date pickers at year 1 ([853142a](853142a))
* **bulma-ui:** stop the indeterminate progress bar and skeleton pulse under reduced motion ([bcf5407](bcf5407))
* **bulma-ui:** stop the Rate pop and DateTimeInput scrim under reduced motion ([3a59129](3a59129))
* **bulma-ui:** stop TimeInput reopening on the focus its popover hands back ([1c87c15](1c87c15))
* **bulma-ui:** warn when a root Theme drops its className and helpers ([05c10e0](05c10e0))
* **eslint-plugin:** judge Columns' gap by its own steps, and lengths as lengths ([4786c8d](4786c8d))

### Features

* **bestax-mcp:** publish to the official MCP Registry ([74efc7f](74efc7f))
* **bestax-migrate:** convert the gap, position, overflow, radius and aspect-ratio helpers ([13dcf63](13dcf63))
* **bulma-ui:** add Bulma's gap helper props to every component ([#877](#877)) ([1bd4abc](1bd4abc))
* **bulma-ui:** add Bulma's position, overflow, radius and aspect-ratio helper props ([#845](#845)) ([64fb91c](64fb91c))
* **bulma-ui:** add Collapses, an accordion group for Collapse ([#849](#849)) ([a12c823](a12c823))
* **bulma-ui:** add Loader, Bulma's inline spinner ([c5e9eb0](c5e9eb0)), closes [#770](#770)
* **bulma-ui:** add month and year pickers to DateInput through granularity ([c4cfc2b](c4cfc2b)), closes [#773](#773)
* **bulma-ui:** add Popover ([2e17fac](2e17fac)), closes [#776](#776)
* **bulma-ui:** export ClientOnly and useIsHydrated ([2c0c1e6](2c0c1e6))
* **bulma-ui:** export Portal ([346d8c2](346d8c2))
* **bulma-ui:** export useFocusTrap, counting the stops the browser's Tab visits ([c304fef](c304fef)), closes [#772](#772)
* **bulma-ui:** make columnGap the column gap helper on Theme ([eb2c611](eb2c611)), closes [#694](#694)
* **eslint-plugin:** check the gap helper props ([b53a749](b53a749))
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 2.25.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

bestax-release-bot Bot pushed a commit that referenced this pull request Oct 8, 2026
## [4.2.13](https://github.com/allxsmith/bestax/compare/create-bestax@4.2.12...create-bestax@4.2.13) (2026-10-08)

### Bug Fixes

* **bestax-mcp:** give .image's ratios their reason in the lookup ([3ea4d0c](3ea4d0c))
* **bestax-mcp:** say an .image converts around elements written out, not an expression ([49bb27b](49bb27b))
* **bestax-migrate:** convert an .image around its children only when they're elements ([ff99907](ff99907))
* **bestax-migrate:** flag react-bulma-components Pagination's delta={0} rather than renaming it ([e339ff1](e339ff1))
* **bestax-migrate:** keep a .menu-list around a bestax Menu.List as markup ([2119c3f](2119c3f))
* **bestax-migrate:** keep a Modal part as markup inside an existing bestax Modal ([cfd5f15](cfd5f15))
* **bestax-migrate:** keep a named anchor as markup instead of saying its name does nothing ([74dc360](74dc360)), closes [#fragment](https://github.com/allxsmith/bestax/issues/fragment)
* **bestax-migrate:** keep a page link as markup when its li is a component's only child ([0e72683](0e72683))
* **bestax-migrate:** know a bestax part imported under its flat export ([7a325ee](7a325ee))
* **bestax-migrate:** leave a wrapper tag alone when none of its classes would become a prop ([2397b9d](2397b9d))
* **bestax-migrate:** leave a wrapper tag with no helper class alone, TODOs and all ([1167a29](1167a29))
* **bestax-migrate:** map react-bulma-components Pagination onto the props it now renders from ([6cd4b51](6cd4b51))
* **bestax-migrate:** rename rbx innerRef to ref on a plain Navbar.Item too ([bb6ace0](bb6ace0)), closes [#734](#734)
* **bestax-migrate:** say why .image's ratios stay classes ([2fbfbd5](2fbfbd5))
* **bestax-migrate:** write a File text with a backslash as a string ([212831e](212831e))
* **bestax-migrate:** write a tabIndex string as a number on every root ([546bf8a](546bf8a)), closes [#814](#814)
* **bestax-migrate:** write isFullwidth from react-bulma-components too ([01da047](01da047))
* **bestax-migrate:** write isFullwidth rather than its deprecated alias from bloomer ([c2a1d22](c2a1d22)), closes [#680](#680)
* **bulma-ui:** announce polite notifications through a status region kept from mount ([#835](#835)) ([c93478d](c93478d))
* **bulma-ui:** answer the granularity review on native input and blur ([7a17486](7a17486))
* **bulma-ui:** apply textColor helper class on Navbar Menu, Start, End, and Burger ([#792](#792)) ([feb83c8](feb83c8))
* **bulma-ui:** attach useFocusTrap to a container that mounts after it turns on ([17a944d](17a944d))
* **bulma-ui:** avoid empty class attribute on several components ([#793](#793)) ([7c5c316](7c5c316))
* **bulma-ui:** bring File and Taginput under the bare-Control Field rule ([cdaa6c2](cdaa6c2))
* **bulma-ui:** clear a picker's unused seed whenever its popover closes ([cbe86c5](cbe86c5))
* **bulma-ui:** close a picker's popover on Alt+ArrowUp from inside it ([b6da4ef](b6da4ef))
* **bulma-ui:** color the calendar from the color prop and read TimeInput's wheel variables ([2251e67](2251e67)), closes [#832](#832)
* **bulma-ui:** color TimeInput's wheels from the color prop ([#832](#832)) ([ad370c9](ad370c9))
* **bulma-ui:** commit nothing when a picker popover is dismissed ([0a46209](0a46209))
* **bulma-ui:** commit nothing when Enter confirms untouched picker text ([773e146](773e146))
* **bulma-ui:** commit nothing when focus leaves a picker untouched ([30b4849](30b4849))
* **bulma-ui:** document the checkbox, radio and switch color and size tuples ([bd39ff3](bd39ff3))
* **bulma-ui:** draw the time wheel focus ring where the wheel's mask shows it ([e1d8c9f](e1d8c9f)), closes [#832](#832)
* **bulma-ui:** drop the openOnFocus TSDoc reason that only holds for segments ([efde0d9](efde0d9))
* **bulma-ui:** Dropdown items withhold attributes by tag and answer Enter and Space ([#827](#827)) ([f6aeb2d](f6aeb2d))
* **bulma-ui:** fall back when useFocusTrap's initialFocusRef can't take focus ([c191931](c191931))
* **bulma-ui:** fire the pickers' onOpen and onClose once under StrictMode ([#896](#896)) ([20b51ed](20b51ed))
* **bulma-ui:** give the calendar's day grid rows of a week ([971a196](971a196)), closes [#774](#774)
* **bulma-ui:** give the selected calendar cell a ring that shows on its fill ([b3eecc6](b3eecc6))
* **bulma-ui:** hide a picker's launcher for a loading Control it sits in ([9a3888e](9a3888e))
* **bulma-ui:** hide a picker's launcher only for the spinner it draws ([7a28a0e](7a28a0e))
* **bulma-ui:** hold Portal to looking a selector up on each render ([8fe02ce](8fe02ce))
* **bulma-ui:** hold the year-1 floor under a max before it ([4f6eb18](4f6eb18))
* **bulma-ui:** judge image map areas by their image in useFocusTrap ([af7bc59](af7bc59))
* **bulma-ui:** keep a range's end while the start's digits are coming ([8d1f862](8d1f862))
* **bulma-ui:** keep a read-only date or time picker closed on ArrowDown ([ba74bf7](ba74bf7))
* **bulma-ui:** keep a tab stop in the year list when the year falls outside it ([fe028c1](fe028c1))
* **bulma-ui:** keep an empty picker's seed while a portaled popover is open ([1e66528](1e66528))
* **bulma-ui:** keep an inline date picker's calendar on its released id ([c26da07](c26da07)), closes [#897](#897) [#897](#897)
* **bulma-ui:** keep button defaults through a spread, and type the buttons that had none ([#853](#853)) ([0810482](0810482))
* **bulma-ui:** keep button types and Avatar's accessible name through a spread ([#826](#826)) ([dc798d4](dc798d4))
* **bulma-ui:** keep menuitemcheckbox and menuitemradio items in Dropdown's arrow-key order ([#786](#786)) ([064155a](064155a))
* **bulma-ui:** keep Numberinput's buttons in a row inside Field > Control ([4dff84c](4dff84c))
* **bulma-ui:** keep Numberinput's Field examples in a row and labelled ([c937c88](c937c88))
* **bulma-ui:** keep radiusless zeroing the radius inside a Theme ([07db6a3](07db6a3)), closes [#829](#829) [#694](#694)
* **bulma-ui:** keep the calendar behind DateTimeInput's time wheels out of reach ([c7f674c](c7f674c))
* **bulma-ui:** keep the clock's seconds out of a picked date and time ([0af2e71](0af2e71))
* **bulma-ui:** keep the Field for horizontal and fieldClassName in a bare Control ([e4dc513](e4dc513))
* **bulma-ui:** keep the picker focus rings visible in every color ([612aa09](612aa09))
* **bulma-ui:** keep the range band under the pointer in the calendar ([c1f2008](c1f2008))
* **bulma-ui:** key the Avatar link warning on the element and attributes ([e628eba](e628eba)), closes [#733](#733) [#733](#733)
* **bulma-ui:** key the Control-level warning by its advice ([24cda3d](24cda3d))
* **bulma-ui:** leave keys on a control inside a tab to that control ([4a9f7b6](4a9f7b6))
* **bulma-ui:** leave rel out of the Avatar link attribute warning ([b059476](b059476)), closes [#733](#733) [#733](#733)
* **bulma-ui:** let Autocomplete's clear button give way to a loading spinner ([5c11fb2](5c11fb2))
* **bulma-ui:** let Escape in a popover's year dropdown go back to the grid ([a8b1dbf](a8b1dbf)), closes [#901](#901)
* **bulma-ui:** let File's picked-files count be reworded, and document its name in the label ([e86545c](e86545c))
* **bulma-ui:** let focus follow the keys in an inline calendar, and skip disabled days for the tab stop ([#885](#885)) ([f55af27](f55af27))
* **bulma-ui:** let several isRoot Themes share the :root style element ([04f399f](04f399f)), closes [#736](#736)
* **bulma-ui:** let the arrow keys move through the calendar's year dropdown ([6abc329](6abc329)), closes [#901](#901)
* **bulma-ui:** let the picker bases give way to a loading Control too ([66e803a](66e803a))
* **bulma-ui:** let useFocusTrap go of a container that leaves while it is on ([8c56d7a](8c56d7a))
* **bulma-ui:** let warnOnce decide when the Avatar link warning fires ([1a5965c](1a5965c)), closes [#733](#733)
* **bulma-ui:** make ArrowUp raise a time wheel's value ([c27c310](c27c310))
* **bulma-ui:** make auto leave room for an in-place picker panel's themed offset ([8c534bd](8c534bd)), closes [#904](#904)
* **bulma-ui:** make Tabs keyboard operable with the WAI-ARIA tabs pattern ([fe0e7ef](fe0e7ef))
* **bulma-ui:** make Theme colorMode switch the scheme under the prefixed builds ([#894](#894)) ([2bd6ec2](2bd6ec2))
* **bulma-ui:** make Theme's radius the helper it is typed as ([36c73d3](36c73d3)), closes [#694](#694)
* **bulma-ui:** make useFocusTrap follow radio groups and initialFocusRef past the trap ([d6219d4](d6219d4))
* **bulma-ui:** match a picker's opening focus only inside its calendar ([e3c22ed](e3c22ed))
* **bulma-ui:** merge className into Navbar.Divider instead of overwriting it ([#791](#791)) ([fcc0d51](fcc0d51))
* **bulma-ui:** move focus into DateTimeInput's time wheels as they open ([adfa9db](adfa9db))
* **bulma-ui:** move the year dropdown's tab stop with the arrow keys ([f56daf5](f56daf5))
* **bulma-ui:** name a picker's default icon when its icon size or column moves ([6f6de39](6f6de39))
* **bulma-ui:** name custom elements among the targets that get Avatar's target and rel ([a962259](a962259)), closes [#733](#733)
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([15cbbb8](15cbbb8)), closes [#952](#952)
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([9cbe7ca](9cbe7ca)), closes [#952](#952)
* **bulma-ui:** name Pagination's page links, and read a count that's no number as its default ([0a1cf06](0a1cf06))
* **bulma-ui:** open DateRangeInput's popover on Alt+ArrowDown, as the other pickers ([c0e22ec](c0e22ec))
* **bulma-ui:** open the date and time popovers on Alt+ArrowDown ([6db22cc](6db22cc))
* **bulma-ui:** order the Tabs fallback stop by index and style disabled tabs ([eefd283](eefd283))
* **bulma-ui:** pick a DateInput day at midnight by key as by click ([92c27ca](92c27ca))
* **bulma-ui:** place a portaled picker panel by its coordinates alone ([#886](#886)) ([040299b](040299b))
* **bulma-ui:** place toasts and notifications at the position they were shown with ([#834](#834)) ([62feab9](62feab9))
* **bulma-ui:** prefix the is-current and is-disabled classes on Pagination's parts ([c9a5fae](c9a5fae))
* **bulma-ui:** reach Taginput's delete buttons and Autocomplete's clear button ([21a064b](21a064b))
* **bulma-ui:** read a Pagination current page that's no number as the first ([68e963b](68e963b))
* **bulma-ui:** read clicks and focus inside a shadow root ([474f2cc](474f2cc))
* **bulma-ui:** read picker bounds and months in years 0 to 99 as written ([#890](#890)) ([02fb619](02fb619))
* **bulma-ui:** render the four burger spans Bulma v1 positions ([#785](#785)) ([8e4e1e6](8e4e1e6))
* **bulma-ui:** restore a portaled Modal's focus to an opener in a shadow root ([c564bd3](c564bd3))
* **bulma-ui:** return focus to the input when a date picker closes ([b741264](b741264))
* **bulma-ui:** say a picked DateTimeInput day keeps milliseconds and meets the bounds ([3536467](3536467))
* **bulma-ui:** say Tab reaches DateRangeInput's end input only when typing ([d2d3d1a](d2d3d1a))
* **bulma-ui:** say where Numberinput goes bare and test bare={false} in a Field ([0461631](0461631))
* **bulma-ui:** send a press on DateRangeInput's field to the nearer input ([f06b2b0](f06b2b0))
* **bulma-ui:** settle Popover's deep review findings ([feadaf4](feadaf4))
* **bulma-ui:** show the picked file with File's hasName and add a keyboard focus ring ([7881db4](7881db4))
* **bulma-ui:** show toasts, notifications and dialogs raised before their container mounts ([#828](#828)) ([2ab4493](2ab4493))
* **bulma-ui:** skip the Avatar target warning on elements with their own target ([27b58f4](27b58f4)), closes [#733](#733)
* **bulma-ui:** start a date picker's focus on the focused cell ([#897](#897)) ([6a55714](6a55714))
* **bulma-ui:** stop Bulma's spinners under reduced motion in every stylesheet ([b234712](b234712)), closes [#770](#770)
* **bulma-ui:** stop form wrappers nesting a Field in a bare Control ([2c6d295](2c6d295))
* **bulma-ui:** stop shipping test-only exports, and document notification() ([#781](#781)) ([5f95398](5f95398))
* **bulma-ui:** stop the date pickers at year 1 ([853142a](853142a))
* **bulma-ui:** stop the indeterminate progress bar and skeleton pulse under reduced motion ([bcf5407](bcf5407))
* **bulma-ui:** stop the Rate pop and DateTimeInput scrim under reduced motion ([3a59129](3a59129))
* **bulma-ui:** stop TimeInput reopening on the focus its popover hands back ([1c87c15](1c87c15))
* **bulma-ui:** strip the Avatar link warning from production builds ([a243fa5](a243fa5)), closes [#733](#733)
* **bulma-ui:** warn about a dropped Avatar href only for an as the caller wrote ([c93b27c](c93b27c)), closes [#733](#733)
* **bulma-ui:** warn in development when Avatar drops an href on a non-link as ([c76e632](c76e632)), closes [#733](#733)
* **bulma-ui:** warn when a root Theme drops its className and helpers ([05c10e0](05c10e0))
* **bulma-ui:** warn when a wrapper inside a Control drops its Control-level props ([cbf434b](cbf434b)), closes [#921](#921)
* **bulma-ui:** warn when an inline picker drops its Control-level props ([f0494bd](f0494bd)), closes [#921](#921)
* **bulma-ui:** warn when Avatar drops a target or rel on a non-link as ([50c385e](50c385e)), closes [#733](#733) [#733](#733)
* **create-bestax:** check the react ranges fit the library's peers, not equal them ([8ae5a0c](8ae5a0c)), closes [#950](#950)
* **create-bestax:** import the icon CSS for every Bulma flavor, not only complete ([a712b91](a712b91)), closes [#946](#946)
* **create-bestax:** install react and react-dom so Yarn 1 reports no unmet peers ([9c9814c](9c9814c)), closes [#644](#644) [#950](#950)
* **create-bestax:** name the files the overwrite prompt removes, and stop on a file path ([39b6232](39b6232)), closes [#945](#945)
* **create-bestax:** never empty a non-empty folder under -y, and validate flags first ([917f195](917f195)), closes [#950](#950) [#945](#945) [#950](#950)
* **create-bestax:** warn when the icon CSS import has nowhere to go ([f7f0b64](f7f0b64)), closes [#946](#946) [#946](#946)
* **eslint-plugin:** judge Columns' gap by its own steps, and lengths as lengths ([4786c8d](4786c8d))
* **eslint-plugin:** report .file as a class the codemod converts ([72a32c9](72a32c9))
* **eslint-plugin:** report .image with the message for a class the codemod converts ([d27c19b](d27c19b))
* **eslint-plugin:** report .menu, .menu-label and .menu-list with the converts message ([8ffaccc](8ffaccc))
* **eslint-plugin:** report .select and .breadcrumb as converted ([a9d8082](a9d8082))
* **eslint-plugin:** report Bulma form markup as classes the codemod converts ([128e832](128e832))
* **eslint-plugin:** report Bulma skeletons as converted ([04ca4ee](04ca4ee))
* **eslint-plugin:** report Modal's parts with the message for a class the codemod converts ([87f3c08](87f3c08))
* **eslint-plugin:** report Pagination's converting parts with the converts message ([6b94f14](6b94f14))
* **eslint-plugin:** report the pagination links and ellipsis as classes the codemod converts ([54ba0b3](54ba0b3))
* **eslint-plugin:** report Theme's deprecated radius route accurately ([5605816](5605816)), closes [#694](#694)
* **eslint-plugin:** suggest radiusless for a near miss on Theme ([21aa9a7](21aa9a7)), closes [#694](#694)

### Features

* **bestax-mcp:** look up .image as Image, with the props it takes from its <img> ([3e63230](3e63230))
* **bestax-mcp:** look up .menu and its label and list as Menu's parts ([f9fe7cd](f9fe7cd))
* **bestax-mcp:** look up Card's title and footer items on the tags their as takes ([ba8193e](ba8193e))
* **bestax-mcp:** look up Modal's parts as components ([b71583a](b71583a))
* **bestax-mcp:** look up Pagination, its list and its previous and next links as components ([f1298df](f1298df))
* **bestax-mcp:** look up the bestax component and props for a Bulma class string ([4a4b246](4a4b246)), closes [#744](#744)
* **bestax-mcp:** publish to the official MCP Registry ([74efc7f](74efc7f))
* **bestax-mcp:** say a Bulma field wraps its children only when horizontal ([929bc82](929bc82))
* **bestax-mcp:** say an .image converts around anything but a bare <img> ([60e9219](60e9219))
* **bestax-mcp:** say Menu.List renders .menu-list only at the top level ([dcce74f](dcce74f))
* **bestax-mcp:** say when a component renders the children from a count ([b60c295](b60c295))
* **bestax-mcp:** say when a component renders the element inside it ([4ced25c](4ced25c))
* **bestax-mcp:** say when a component renders the li around its element, or its own text ([8fd3faf](8fd3faf))
* **bestax-mcp:** say when a component renders the whole .file tree from props ([976d8a3](976d8a3))
* **bestax-migrate:** convert .file inside a Field, building its tree from props ([724dff5](724dff5)), closes [#809](#809)
* **bestax-migrate:** convert .icon-text, building its icons from props ([#823](#823)) ([933868f](933868f))
* **bestax-migrate:** convert .menu, its labels and its top-level lists ([02f4db6](02f4db6))
* **bestax-migrate:** convert .select and .breadcrumb with the element inside them ([d76c569](d76c569))
* **bestax-migrate:** convert .tabs and .icon around their children ([#815](#815)) ([3967a80](3967a80))
* **bestax-migrate:** convert a menu list's items to Menu.Item ([#816](#816)) ([b385687](b385687))
* **bestax-migrate:** convert an .image and its <img> to Image ([d4f3673](d4f3673)), closes [#793](#793)
* **bestax-migrate:** convert an .image around anything but a bare <img> ([0a31c5b](0a31c5b)), closes [#801](#801)
* **bestax-migrate:** convert Bulma cards built from their parts ([#752](#752)) ([1b08e17](1b08e17))
* **bestax-migrate:** convert Bulma form fields, controls, inputs and textareas ([3da788d](3da788d)), closes [#743](#743)
* **bestax-migrate:** convert Bulma grids and cells ([#760](#760)) ([22adc7c](22adc7c)), closes [#743](#743)
* **bestax-migrate:** convert Bulma navbars ([#754](#754)) ([02fdd72](02fdd72))
* **bestax-migrate:** convert Bulma skeletons ([2574ace](2574ace))
* **bestax-migrate:** convert Card's title and footer items on the tags their as takes ([20bc0c6](20bc0c6)), closes [#794](#794)
* **bestax-migrate:** convert conditional classes in clsx and classnames calls ([8948cce](8948cce))
* **bestax-migrate:** convert Modal's parts element by element ([4d41ad2](4d41ad2)), closes [#805](#805)
* **bestax-migrate:** convert navbar dividers with classes, and navbar text colors ([#796](#796)) ([c97c7e9](c97c7e9))
* **bestax-migrate:** convert Pagination, its list and its previous and next links ([d75bc70](d75bc70)), closes [#807](#807)
* **bestax-migrate:** convert Pagination's page links and ellipsis in their li's place ([ae720fa](ae720fa)), closes [#809](#809)
* **bestax-migrate:** convert Panel and its heading, tabs and blocks ([#811](#811)) ([0694e54](0694e54))
* **bestax-migrate:** convert the gap, position, overflow, radius and aspect-ratio helpers ([13dcf63](13dcf63))
* **bestax-migrate:** fold .table-container and .fixed-grid into the component inside ([#761](#761)) ([72504f5](72504f5)), closes [#743](#743)
* **bulma-ui:** add Bulma's gap helper props to every component ([#877](#877)) ([1bd4abc](1bd4abc))
* **bulma-ui:** add Bulma's position, overflow, radius and aspect-ratio helper props ([#845](#845)) ([64fb91c](64fb91c))
* **bulma-ui:** add Collapses, an accordion group for Collapse ([#849](#849)) ([a12c823](a12c823))
* **bulma-ui:** add DateRangeInput ([50fcba7](50fcba7)), closes [#774](#774)
* **bulma-ui:** add Loader, Bulma's inline spinner ([c5e9eb0](c5e9eb0)), closes [#770](#770)
* **bulma-ui:** add month and year pickers to DateInput through granularity ([c4cfc2b](c4cfc2b)), closes [#773](#773)
* **bulma-ui:** add Popover ([2e17fac](2e17fac)), closes [#776](#776)
* **bulma-ui:** export ClientOnly and useIsHydrated ([2c0c1e6](2c0c1e6))
* **bulma-ui:** export Portal ([346d8c2](346d8c2))
* **bulma-ui:** export useFocusTrap, counting the stops the browser's Tab visits ([c304fef](c304fef)), closes [#772](#772)
* **bulma-ui:** let Card.Header.Title and Card.FooterItem render Bulma's own tags ([#794](#794)) ([47ecdb6](47ecdb6))
* **bulma-ui:** make columnGap the column gap helper on Theme ([eb2c611](eb2c611)), closes [#694](#694)
* **bulma-ui:** render Pagination from total, current and onPageChange ([f7ddf04](f7ddf04)), closes [#813](#813)
* **eslint-plugin:** add an opt-in rule for plain elements styled with a Bulma component class ([#750](#750)) ([0bb4d80](0bb4d80))
* **eslint-plugin:** check the gap helper props ([b53a749](b53a749))
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 4.2.13 🎉

The release is available on:

Your semantic-release bot 📦🚀

bestax-release-bot Bot pushed a commit that referenced this pull request Oct 9, 2026
## [1.14.1](https://github.com/allxsmith/bestax/compare/bestax-mcp@1.14.0...bestax-mcp@1.14.1) (2026-10-09)

### Bug Fixes

* **bestax-mcp:** describe a built icon's attributes as the codemod writes them ([d2f341b](d2f341b)), closes [#942](#942)
* **bestax-mcp:** hold every docs Storybook link to a real story, and floor the index's ([3a6df21](3a6df21))
* **bestax-mcp:** keep a described or named component first in a sentence-shaped search ([2e2a1ef](2e2a1ef))
* **bestax-mcp:** name every component that declares a CSS variable, its owner first ([8bf01e3](8bf01e3))
* **bestax-mcp:** point the index's Storybook links at stories that exist ([0852de4](0852de4))
* **bestax-mcp:** rank the component a search is about above passing mentions ([cc952c2](cc952c2))
* **bestax-mcp:** read self-closing names, explain Theme on every query, advertise dot-paths ([62a4a3a](62a4a3a))
* **bestax-mcp:** release the skill examples that compile in a vite-ts scaffold ([3a7f222](3a7f222))
* **bestax-mcp:** smooth the rough edges a smoke test found ([b6ed21a](b6ed21a))
* **bestax-mcp:** stop the search comment claiming every variable has an owner ([4f1d102](4f1d102))
* **bestax-migrate:** convert a .icon to Icon by the attributes Icon now writes ([a3795fb](a3795fb)), closes [#942](#942)
* **bestax-migrate:** convert an unnamed .icon with a role of its own without aria-hidden ([7c5ff91](7c5ff91)), closes [#942](#942)
* **bestax-migrate:** convert an unnamed .icon with a tabIndex of its own without aria-hidden ([df24c06](df24c06)), closes [#942](#942)
* **bulma-ui:** attach useFocusTrap to a container that mounts after it turns on ([17a944d](17a944d))
* **bulma-ui:** bring File and Taginput under the bare-Control Field rule ([cdaa6c2](cdaa6c2))
* **bulma-ui:** carry Rate's value on its checked star, not the radiogroup ([84f86d8](84f86d8)), closes [#942](#942)
* **bulma-ui:** check initializers for import-time work and stop overstating namespace imports ([20ef350](20ef350))
* **bulma-ui:** clear a picker's unused seed whenever its popover closes ([cbe86c5](cbe86c5))
* **bulma-ui:** close a picker's popover on Alt+ArrowUp from inside it ([b6da4ef](b6da4ef))
* **bulma-ui:** collapse an inline DateTimeInput's wheels on Enter ([ff44aa3](ff44aa3))
* **bulma-ui:** commit nothing when a picker popover is dismissed ([0a46209](0a46209))
* **bulma-ui:** commit nothing when Enter confirms untouched picker text ([773e146](773e146))
* **bulma-ui:** commit nothing when focus leaves a picker untouched ([30b4849](30b4849))
* **bulma-ui:** commit the time on Enter from the seconds wheel too ([d2c0920](d2c0920))
* **bulma-ui:** drop the openOnFocus TSDoc reason that only holds for segments ([efde0d9](efde0d9))
* **bulma-ui:** emit the ESM build one file per module so unused components shake out ([2893197](2893197))
* **bulma-ui:** fire the pickers' onOpen and onClose once under StrictMode ([#896](#896)) ([20b51ed](20b51ed))
* **bulma-ui:** give the calendar's day grid rows of a week ([971a196](971a196)), closes [#774](#774)
* **bulma-ui:** give TimeInput's wheels an id apart from the popover's ([40824cc](40824cc))
* **bulma-ui:** hide a picker's launcher for a loading Control it sits in ([9a3888e](9a3888e))
* **bulma-ui:** hide a picker's launcher only for the spinner it draws ([7a28a0e](7a28a0e))
* **bulma-ui:** hide an unnamed Icon and make a named one an image ([f9de39c](f9de39c)), closes [#942](#942)
* **bulma-ui:** hold the year-1 floor under a max before it ([4f6eb18](4f6eb18))
* **bulma-ui:** keep a press on a time wheel item from focusing the hidden item ([c57836a](c57836a)), closes [#942](#942)
* **bulma-ui:** keep a range's end while the start's digits are coming ([8d1f862](8d1f862))
* **bulma-ui:** keep a read-only date or time picker closed on ArrowDown ([ba74bf7](ba74bf7))
* **bulma-ui:** keep a tab stop in the year list when the year falls outside it ([fe028c1](fe028c1))
* **bulma-ui:** keep an empty picker's seed while a portaled popover is open ([1e66528](1e66528))
* **bulma-ui:** keep an inline date picker's calendar on its released id ([c26da07](c26da07)), closes [#897](#897) [#897](#897)
* **bulma-ui:** keep each Rate star's name its own at a value a hair off a whole number ([eed3d99](eed3d99)), closes [#942](#942)
* **bulma-ui:** keep Numberinput's buttons in a row inside Field > Control ([4dff84c](4dff84c))
* **bulma-ui:** keep Numberinput's Field examples in a row and labelled ([c937c88](c937c88))
* **bulma-ui:** keep the calendar behind DateTimeInput's time wheels out of reach ([c7f674c](c7f674c))
* **bulma-ui:** keep the clock's seconds out of a picked date and time ([0af2e71](0af2e71))
* **bulma-ui:** keep the Field for horizontal and fieldClassName in a bare Control ([e4dc513](e4dc513))
* **bulma-ui:** keep the range band under the pointer in the calendar ([c1f2008](c1f2008))
* **bulma-ui:** keep the time wheels' items out of their spinbutton ([6a02615](6a02615)), closes [#942](#942)
* **bulma-ui:** key the Control-level warning by its advice ([24cda3d](24cda3d))
* **bulma-ui:** leave an unnamed Icon with a role of its own visible ([b1e85f5](b1e85f5)), closes [#942](#942)
* **bulma-ui:** leave an unnamed Icon with a tabIndex of its own visible ([a41d131](a41d131)), closes [#942](#942)
* **bulma-ui:** leave Dropdown's menu nothing focusable but its items ([c1ec016](c1ec016)), closes [#942](#942)
* **bulma-ui:** leave keys on a control inside a tab to that control ([4a9f7b6](4a9f7b6))
* **bulma-ui:** let Autocomplete's clear button give way to a loading spinner ([5c11fb2](5c11fb2))
* **bulma-ui:** let Escape in a popover's year dropdown go back to the grid ([a8b1dbf](a8b1dbf)), closes [#901](#901)
* **bulma-ui:** let File's picked-files count be reworded, and document its name in the label ([e86545c](e86545c))
* **bulma-ui:** let focus follow the keys in an inline calendar, and skip disabled days for the tab stop ([#885](#885)) ([f55af27](f55af27))
* **bulma-ui:** let the arrow keys move through the calendar's year dropdown ([6abc329](6abc329)), closes [#901](#901)
* **bulma-ui:** let the picker bases give way to a loading Control too ([66e803a](66e803a))
* **bulma-ui:** let useFocusTrap go of a container that leaves while it is on ([8c56d7a](8c56d7a))
* **bulma-ui:** make ArrowUp raise a time wheel's value ([c27c310](c27c310))
* **bulma-ui:** make auto leave room for an in-place picker panel's themed offset ([8c534bd](8c534bd)), closes [#904](#904)
* **bulma-ui:** make Tabs keyboard operable with the WAI-ARIA tabs pattern ([fe0e7ef](fe0e7ef))
* **bulma-ui:** make Theme colorMode switch the scheme under the prefixed builds ([#894](#894)) ([2bd6ec2](2bd6ec2))
* **bulma-ui:** match a picker's opening focus only inside its calendar ([e3c22ed](e3c22ed))
* **bulma-ui:** move focus into DateTimeInput's time wheels as they open ([adfa9db](adfa9db))
* **bulma-ui:** move the year dropdown's tab stop with the arrow keys ([f56daf5](f56daf5))
* **bulma-ui:** name a picker's default icon when its icon size or column moves ([6f6de39](6f6de39))
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([51fc017](51fc017)), closes [#952](#952)
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([633f5dc](633f5dc)), closes [#952](#952)
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([15cbbb8](15cbbb8)), closes [#952](#952)
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([9cbe7ca](9cbe7ca)), closes [#952](#952)
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([25b7a0b](25b7a0b)), closes [#952](#952)
* **bulma-ui:** open DateRangeInput's popover on Alt+ArrowDown, as the other pickers ([c0e22ec](c0e22ec))
* **bulma-ui:** open the date and time popovers on Alt+ArrowDown ([6db22cc](6db22cc))
* **bulma-ui:** order the Tabs fallback stop by index and style disabled tabs ([eefd283](eefd283))
* **bulma-ui:** pick a DateInput day at midnight by key as by click ([92c27ca](92c27ca))
* **bulma-ui:** place a portaled picker panel by its coordinates alone ([#886](#886)) ([040299b](040299b))
* **bulma-ui:** point Autocomplete's aria-controls at its list only while the list is on screen ([8a16115](8a16115)), closes [#942](#942)
* **bulma-ui:** reach Taginput's delete buttons and Autocomplete's clear button ([21a064b](21a064b))
* **bulma-ui:** read a day that is both today and a nearby month the same inside a range band ([4164c3b](4164c3b)), closes [#983](#983)
* **bulma-ui:** read DateTimeInput's footer time row at 4.5:1 in both schemes ([585aa3b](585aa3b)), closes [#976](#976)
* **bulma-ui:** read every calendar day at 4.5:1 in both schemes ([876fe60](876fe60)), closes [#983](#983)
* **bulma-ui:** read picker bounds and months in years 0 to 99 as written ([#890](#890)) ([02fb619](02fb619))
* **bulma-ui:** render the time wheels' inert calendar through inertProps ([f023f25](f023f25))
* **bulma-ui:** return focus to the input when a date picker closes ([b741264](b741264))
* **bulma-ui:** say a picked DateTimeInput day keeps milliseconds and meets the bounds ([3536467](3536467))
* **bulma-ui:** say Alt+ArrowUp closes DateTimeInput's popover from the wheels ([f994d7d](f994d7d))
* **bulma-ui:** say Tab reaches DateRangeInput's end input only when typing ([d2d3d1a](d2d3d1a))
* **bulma-ui:** say where Numberinput goes bare and test bare={false} in a Field ([0461631](0461631))
* **bulma-ui:** send a press on DateRangeInput's field to the nearer input ([f06b2b0](f06b2b0))
* **bulma-ui:** show the picked file with File's hasName and add a keyboard focus ring ([7881db4](7881db4))
* **bulma-ui:** start a date picker's focus on the focused cell ([#897](#897)) ([6a55714](6a55714))
* **bulma-ui:** stop form wrappers nesting a Field in a bare Control ([2c6d295](2c6d295))
* **bulma-ui:** stop the date pickers at year 1 ([853142a](853142a))
* **bulma-ui:** stop the indeterminate progress bar and skeleton pulse under reduced motion ([bcf5407](bcf5407))
* **bulma-ui:** stop the picker popover partial warning about global nth() ([0b34d84](0b34d84))
* **bulma-ui:** stop the Rate pop and DateTimeInput scrim under reduced motion ([3a59129](3a59129))
* **bulma-ui:** tie DateTimeInput's Time button to the wheels it opens ([889fc7e](889fc7e))
* **bulma-ui:** warn when a root Theme drops its className and helpers ([05c10e0](05c10e0))
* **bulma-ui:** warn when a wrapper inside a Control drops its Control-level props ([cbf434b](cbf434b)), closes [#921](#921)
* **bulma-ui:** warn when an inline picker drops its Control-level props ([f0494bd](f0494bd)), closes [#921](#921)
* **bulma-ui:** wire Autocomplete's combobox to a named listbox ([213f648](213f648)), closes [#942](#942)
* **create-bestax:** check the react ranges fit the library's peers, not equal them ([8ae5a0c](8ae5a0c)), closes [#950](#950)
* **create-bestax:** have the optimize skill install with the project's package manager ([e0ba314](e0ba314)), closes [#597](#597)
* **create-bestax:** import the icon CSS for every Bulma flavor, not only complete ([a712b91](a712b91)), closes [#946](#946)
* **create-bestax:** install react and react-dom so Yarn 1 reports no unmet peers ([9c9814c](9c9814c)), closes [#644](#644) [#950](#950)
* **create-bestax:** make every skill example compile in a vite-ts scaffold ([6cc5fec](6cc5fec))
* **create-bestax:** name the files the overwrite prompt removes, and stop on a file path ([39b6232](39b6232)), closes [#945](#945)
* **create-bestax:** never empty a non-empty folder under -y, and validate flags first ([917f195](917f195)), closes [#950](#950) [#945](#945) [#950](#950)
* **create-bestax:** read the flags after a `--` that pnpm or bun forwards ([82112a2](82112a2)), closes [#950](#950)
* **create-bestax:** tell the optimize skill's modular build to install bulma ([4289d0a](4289d0a)), closes [#597](#597)
* **create-bestax:** warn when the icon CSS import has nowhere to go ([f7f0b64](f7f0b64)), closes [#946](#946) [#946](#946)
* **eslint-plugin:** judge Columns' gap by its own steps, and lengths as lengths ([4786c8d](4786c8d))

### Features

* **bestax-migrate:** convert the gap, position, overflow, radius and aspect-ratio helpers ([13dcf63](13dcf63))
* **bulma-ui:** add Bulma's gap helper props to every component ([#877](#877)) ([1bd4abc](1bd4abc))
* **bulma-ui:** add DateRangeInput ([50fcba7](50fcba7)), closes [#774](#774)
* **bulma-ui:** make columnGap the column gap helper on Theme ([eb2c611](eb2c611)), closes [#694](#694)
* **eslint-plugin:** check the gap helper props ([b53a749](b53a749))
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 1.14.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deep-review needs-human-review Loop converged (or contested): awaiting owner review + manual merge released review-converged Deep review converged: no blocking findings, all review threads resolved, checks green

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant