@allxsmith/bestax-bulma 5.23.0 → 5.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/extras.css +1 -1
  4. package/dist/extras.css.map +1 -1
  5. package/dist/index.cjs +6711 -5884
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.esm.js +6708 -5886
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/types/components/Popover.d.ts +166 -0
  10. package/dist/types/form/DateInput.d.ts +1 -1
  11. package/dist/types/form/DateInputBase.d.ts +33 -3
  12. package/dist/types/form/_pickerInternals/Calendar.d.ts +11 -1
  13. package/dist/types/form/_pickerInternals/dateUtils.d.ts +36 -1
  14. package/dist/types/form/_pickerInternals/formatters.d.ts +2 -0
  15. package/dist/types/form/_pickerInternals/nativeInputSupport.d.ts +11 -0
  16. package/dist/types/form/_pickerInternals/pickerTypes.d.ts +10 -0
  17. package/dist/types/form/_pickerInternals/useSegmentedEntry.d.ts +9 -1
  18. package/dist/types/helpers/useAnchoredPosition.d.ts +59 -0
  19. package/dist/types/helpers/useClientLayoutEffect.d.ts +7 -0
  20. package/dist/types/helpers/useFocusTrap.d.ts +13 -3
  21. package/dist/types/index.d.ts +1 -0
  22. package/dist/types-cjs/components/Popover.d.ts +166 -0
  23. package/dist/types-cjs/form/DateInput.d.ts +1 -1
  24. package/dist/types-cjs/form/DateInputBase.d.ts +33 -3
  25. package/dist/types-cjs/form/_pickerInternals/Calendar.d.ts +11 -1
  26. package/dist/types-cjs/form/_pickerInternals/dateUtils.d.ts +36 -1
  27. package/dist/types-cjs/form/_pickerInternals/formatters.d.ts +2 -0
  28. package/dist/types-cjs/form/_pickerInternals/nativeInputSupport.d.ts +11 -0
  29. package/dist/types-cjs/form/_pickerInternals/pickerTypes.d.ts +10 -0
  30. package/dist/types-cjs/form/_pickerInternals/useSegmentedEntry.d.ts +9 -1
  31. package/dist/types-cjs/helpers/useAnchoredPosition.d.ts +59 -0
  32. package/dist/types-cjs/helpers/useClientLayoutEffect.d.ts +7 -0
  33. package/dist/types-cjs/helpers/useFocusTrap.d.ts +13 -3
  34. package/dist/types-cjs/index.d.ts +1 -0
  35. package/dist/versions/bestax-no-dark-mode.css +1 -1
  36. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  37. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  38. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  39. package/dist/versions/bestax-no-helpers.css +1 -1
  40. package/dist/versions/bestax-no-helpers.css.map +1 -1
  41. package/dist/versions/bestax-prefixed.css +1 -1
  42. package/dist/versions/bestax-prefixed.css.map +1 -1
  43. package/package.json +1 -1
  44. package/src/scss/components/_index.scss +1 -0
  45. package/src/scss/components/_popover.scss +144 -0
  46. package/src/scss/form/_dateinput.scss +20 -3
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
3
- import { PickerPosition, DayOfWeek, PickerLabels } from './_pickerInternals/pickerTypes.js';
3
+ import { PickerPosition, DayOfWeek, DateGranularity, PickerLabels } from './_pickerInternals/pickerTypes.js';
4
4
  import { DateFormatOption } from './_pickerInternals/formatters.js';
5
5
  /**
6
6
  * Props for the raw DateInput base. Use the higher-level `DateInput` for
@@ -28,7 +28,29 @@ export interface DateInputBaseProps extends Omit<React.InputHTMLAttributes<HTMLI
28
28
  /** Placeholder text for the input. */
29
29
  placeholder?: string;
30
30
  /**
31
- * Token format string or `Intl.DateTimeFormat` options. Default `'YYYY-MM-DD'`.
31
+ * What the calendar shows and what a selection means: `'day'` shows the
32
+ * day grid, `'month'` a grid of the focused year's months whose header
33
+ * steps a year at a time, and `'year'` the year list. A month or year value
34
+ * is the first day of that period at local midnight, so `onChange` gets
35
+ * `new Date(2026, 5, 1)` for June 2026. A `value` elsewhere in the period
36
+ * shows as that period and stays as given until the user picks a period or
37
+ * types a different one. `min`, `max`,
38
+ * `shouldDisableDate` and `unselectableDates` judge whole periods: a month
39
+ * or year can be picked while any day in it can, so a `min` of 15 June
40
+ * still allows June, and June commits as 1 June, earlier than that `min`.
41
+ * The default `format` follows the granularity (`'YYYY-MM'`, `'YYYY'`); a
42
+ * custom `format` with finer tokens still renders them, but typing skips
43
+ * them. `firstDayOfWeek`, `dayNames` and `nearbyMonthDays` only affect the
44
+ * day grid, and an `inline` calendar's hidden form value is `YYYY-MM` or
45
+ * `YYYY`. The `labels` keys `chooseMonth` / `chooseYear` name the launcher
46
+ * and popover, and `prevYear` / `nextYear` the month grid's header buttons.
47
+ * @defaultValue 'day'
48
+ */
49
+ granularity?: DateGranularity;
50
+ /**
51
+ * Token format string or `Intl.DateTimeFormat` options. Defaults to
52
+ * `'YYYY-MM-DD'`, or to `'YYYY-MM'` / `'YYYY'` when `granularity` is
53
+ * `'month'` / `'year'`.
32
54
  * @defaultValue 'YYYY-MM-DD'
33
55
  */
34
56
  format?: DateFormatOption;
@@ -38,7 +60,15 @@ export interface DateInputBaseProps extends Omit<React.InputHTMLAttributes<HTMLI
38
60
  locale?: string;
39
61
  /** Render the calendar inline (no popover). */
40
62
  inline?: boolean;
41
- /** Use `<input type="date">` on coarse-pointer + small-viewport devices. */
63
+ /**
64
+ * Use `<input type="date">` on coarse-pointer + small-viewport devices. At
65
+ * `'month'` granularity it uses `<input type="month">` where the browser
66
+ * implements one, as Chromium browsers, Safari on iOS and Firefox for
67
+ * Android do, and the calendar where it doesn't, as in desktop Firefox.
68
+ * Desktop Safari accepts the type but draws no month control, so forcing
69
+ * `true` there shows a plain text box. HTML has no year input, so `'year'`
70
+ * granularity always renders the calendar.
71
+ */
42
72
  mobileNative?: boolean | 'auto';
43
73
  /** Allow segmented keyboard typing in the input (type the date directly, auto-advancing across segments). `false` makes the field picker-only. */
44
74
  editable?: boolean;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { DayOfWeek, PickerLabels } from './pickerTypes.js';
2
+ import { DateGranularity, DayOfWeek, PickerLabels } from './pickerTypes.js';
3
3
  export interface CalendarProps {
4
4
  value: Date | null;
5
5
  focusedDate: Date;
@@ -25,8 +25,18 @@ export interface CalendarProps {
25
25
  /**
26
26
  * Inclusive `[min, max]` year range shown in the year-dropdown view.
27
27
  * Defaults to ±100 years around the focused year, clamped by `min`/`max`.
28
+ * At `'year'` granularity the window centres on the year focused when the
29
+ * calendar mounted, so moving focus never reflows the list.
28
30
  */
29
31
  yearsRange?: [number, number];
32
+ /**
33
+ * What a selection means. `'day'` shows the day grid; `'month'` shows a
34
+ * month grid for the focused year, with the year list one header click
35
+ * away for jumping; `'year'` shows the year list as the selection surface.
36
+ * A month or year cell is disabled when every day in it is, and `onSelect`
37
+ * receives the period's first day.
38
+ */
39
+ granularity?: DateGranularity;
30
40
  }
31
41
  export declare const Calendar: React.FC<CalendarProps>;
32
42
  export default Calendar;
@@ -1,4 +1,4 @@
1
- import { DayOfWeek } from './pickerTypes.js';
1
+ import { DateGranularity, DayOfWeek } from './pickerTypes.js';
2
2
  export interface CalendarCell {
3
3
  date: Date;
4
4
  inCurrentMonth: boolean;
@@ -13,6 +13,41 @@ export declare function startOfDay(d: Date): Date;
13
13
  export declare function endOfDay(d: Date): Date;
14
14
  export declare function startOfMonth(d: Date): Date;
15
15
  export declare function endOfMonth(d: Date): Date;
16
+ /**
17
+ * Local midnight on `year`-`month`-`day` (`month` from 0), like the
18
+ * `Date(y, m, d)` constructor except that years 0–99 stay as given rather than
19
+ * turning into 1900–1999.
20
+ */
21
+ export declare function makeDate(year: number, month?: number, day?: number): Date;
22
+ /**
23
+ * First instant of the day, month or year containing `d`. Works by setters on
24
+ * a copy rather than the `Date(y, m, d)` constructor, which reads years 0–99
25
+ * as 1900–1999: segmented typing passes through such years on the way to a
26
+ * four-digit one.
27
+ */
28
+ export declare function startOfPeriod(d: Date, granularity: DateGranularity): Date;
29
+ /** Last instant of the day, month or year containing `d`. */
30
+ export declare function endOfPeriod(d: Date, granularity: DateGranularity): Date;
31
+ /** The rules that make a single calendar day unselectable. */
32
+ export interface DayConstraints {
33
+ min?: Date;
34
+ max?: Date;
35
+ shouldDisableDate?: (d: Date) => boolean;
36
+ unselectableDates?: Date[];
37
+ }
38
+ /**
39
+ * Whether the day `d` falls outside `[min, max]` or is blocked by
40
+ * `shouldDisableDate` / `unselectableDates`. This is the day grid's rule for a
41
+ * disabled cell.
42
+ */
43
+ export declare function isDayUnselectable(d: Date, c: DayConstraints): boolean;
44
+ /**
45
+ * Whether every day of the month or year containing `d` is unselectable, so
46
+ * the period as a whole can't be picked. Walks the period's days and stops at
47
+ * the first selectable one. `min` and `max` count whole days here, so a `min`
48
+ * of 3pm on a month's last day leaves that day, and so its month, selectable.
49
+ */
50
+ export declare function isPeriodUnselectable(d: Date, granularity: DateGranularity, c: DayConstraints): boolean;
16
51
  export declare function addDays(d: Date, n: number): Date;
17
52
  export declare function addMonths(d: Date, n: number): Date;
18
53
  export declare function addYears(d: Date, n: number): Date;
@@ -1,5 +1,7 @@
1
1
  export type DateFormatOption = Intl.DateTimeFormatOptions | string;
2
2
  export declare const DEFAULT_DATE_FORMAT = "YYYY-MM-DD";
3
+ export declare const DEFAULT_MONTH_FORMAT = "YYYY-MM";
4
+ export declare const DEFAULT_YEAR_FORMAT = "YYYY";
3
5
  export declare const DEFAULT_TIME_FORMAT_24 = "HH:mm";
4
6
  export declare const DEFAULT_TIME_FORMAT_12 = "hh:mm A";
5
7
  export declare const DEFAULT_DATETIME_FORMAT = "YYYY-MM-DD HH:mm";
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Whether this browser implements `<input type={type}>`. A browser that
3
+ * doesn't know a type reads it back as `'text'`, so this sets the type on a
4
+ * detached input and checks what sticks. The answer can't change within a
5
+ * page, so it is worked out once per type.
6
+ *
7
+ * It needs a DOM, so callers ask only after hydration. It also can't see a
8
+ * browser that recognises a type without drawing a control for it: desktop
9
+ * Safari reports `'month'` but shows a plain text box.
10
+ */
11
+ export declare function supportsInputType(type: string): boolean;
@@ -1,6 +1,8 @@
1
1
  export type PickerPosition = 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'auto';
2
2
  export type HourFormat = '12' | '24';
3
3
  export type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6;
4
+ /** The unit a date picker selects: a day, a month or a year. */
5
+ export type DateGranularity = 'day' | 'month' | 'year';
4
6
  /**
5
7
  * Translatable strings used across all four pickers. Pass via the `labels`
6
8
  * prop to override defaults; consumers manage their own locale-driven mapping.
@@ -8,7 +10,15 @@ export type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6;
8
10
  export interface PickerLabels {
9
11
  prevMonth?: string;
10
12
  nextMonth?: string;
13
+ /** Month grid header: steps back a year. */
14
+ prevYear?: string;
15
+ /** Month grid header: steps forward a year. */
16
+ nextYear?: string;
11
17
  chooseDate?: string;
18
+ /** Launcher and popover name when the picker selects a month. */
19
+ chooseMonth?: string;
20
+ /** Launcher, popover and year list name when the picker selects a year. */
21
+ chooseYear?: string;
12
22
  hours?: string;
13
23
  minutes?: string;
14
24
  seconds?: string;
@@ -1,9 +1,17 @@
1
1
  import React from 'react';
2
2
  import { DateFormatOption } from './formatters.js';
3
- import { SegmentMap } from './segmentMap.js';
3
+ import { SegmentKind, SegmentMap } from './segmentMap.js';
4
4
  export interface UseSegmentedEntryParams {
5
5
  /** Resolved format actually used to render (the host's default format). */
6
6
  format: DateFormatOption;
7
+ /**
8
+ * Segment kinds the caret never stops on: they still render, but arrows,
9
+ * digits and separators pass over them. A month picker skips `'day'` so a
10
+ * format such as `'YYYY-MM-DD'` edits only the year and month. Must be
11
+ * referentially stable. A format left with no editable segment falls back
12
+ * to free-form entry.
13
+ */
14
+ skipKinds?: readonly SegmentKind[];
7
15
  /** Current canonical value (controlled or internal). */
8
16
  value: Date | null;
9
17
  /** Commit a new Date through the host's onChange / internal pipeline. */
@@ -0,0 +1,59 @@
1
+ import type { RefObject } from 'react';
2
+ import type { PickerPosition } from '../form/_pickerInternals/pickerTypes.js';
3
+ /** A corner of the anchor the panel opens from, once `auto` is resolved. */
4
+ export type AnchoredCorner = Exclude<PickerPosition, 'auto'>;
5
+ /**
6
+ * Where the panel goes: the corner it opens from and, when it is fixed to
7
+ * the viewport, its coordinates there.
8
+ */
9
+ export interface AnchoredPosition {
10
+ position: AnchoredCorner;
11
+ top?: number;
12
+ left?: number;
13
+ }
14
+ /**
15
+ * Options for `useAnchoredPosition`.
16
+ */
17
+ export interface UseAnchoredPositionOptions {
18
+ /** Whether the panel is on the page. Nothing is measured while it is not. */
19
+ active: boolean;
20
+ /** The corner asked for, or `auto` to pick one that keeps the panel in the viewport. */
21
+ position: PickerPosition;
22
+ /**
23
+ * Whether the panel is fixed to the viewport (it was portaled away from the
24
+ * anchor), which needs coordinates. Otherwise the panel's CSS places it
25
+ * against the anchor from the corner alone.
26
+ */
27
+ fixed: boolean;
28
+ /**
29
+ * The gap between the anchor and the panel, in pixels, that the hook puts
30
+ * there itself: added to the fixed coordinates and to the room `auto` asks
31
+ * for below the anchor.
32
+ * @defaultValue 4
33
+ */
34
+ offset?: number;
35
+ /**
36
+ * Reads the gap the panel's own stylesheet puts between it and the anchor,
37
+ * in pixels, each time the panel is measured. `auto` leaves room for it as
38
+ * well; the coordinates don't include it, because the stylesheet applies it.
39
+ */
40
+ styledGap?: (panel: HTMLElement) => number;
41
+ }
42
+ /**
43
+ * Places a floating panel against its anchor: resolves `auto` to a corner
44
+ * and, for a panel fixed to the viewport, works out its coordinates. It
45
+ * measures again on resize and on any scroll of the anchor's window (an
46
+ * iframe's, when the anchor renders into one), so a fixed panel follows its
47
+ * anchor. A measurement that changes nothing doesn't render again.
48
+ *
49
+ * Measuring happens in a layout effect, so the panel is placed before it
50
+ * paints. It needs both elements on the page while `active` is on, and
51
+ * keeps the last placement when either is missing.
52
+ *
53
+ * @function useAnchoredPosition
54
+ * @param anchorRef - The element the panel opens from.
55
+ * @param panelRef - The floating panel.
56
+ * @param options - Whether to measure, the corner asked for, and how the panel is placed.
57
+ * @returns The corner the panel opens from, with coordinates when it is fixed.
58
+ */
59
+ export declare function useAnchoredPosition(anchorRef: RefObject<HTMLElement | null>, panelRef: RefObject<HTMLElement | null>, { active, position, fixed, offset, styledGap }: UseAnchoredPositionOptions): AnchoredPosition;
@@ -0,0 +1,7 @@
1
+ import { useEffect } from 'react';
2
+ /**
3
+ * `useLayoutEffect` in the browser, `useEffect` on the server. A server
4
+ * render runs neither, and React 18 warns about a layout effect there, so the
5
+ * server is handed the plain one.
6
+ */
7
+ export declare const useClientLayoutEffect: typeof useEffect;
@@ -1,4 +1,11 @@
1
1
  import type { RefObject } from 'react';
2
+ /**
3
+ * The first tab stop inside `container`, found the way the trap finds it, or
4
+ * `null` when there is none. For a component that moves focus into a panel
5
+ * without trapping it there. `src/index.ts` names its exports from this
6
+ * module, so this one stays internal.
7
+ */
8
+ export declare function firstTabStop(container: HTMLElement): HTMLElement | null;
2
9
  /**
3
10
  * Options for `useFocusTrap`.
4
11
  */
@@ -10,9 +17,12 @@ export interface UseFocusTrapOptions {
10
17
  */
11
18
  active?: boolean;
12
19
  /**
13
- * The element to focus when the trap turns on. Without it, or while it
14
- * points at nothing, focus goes to the first tab stop inside the container,
15
- * and to the container itself when there is none.
20
+ * The element inside the container to focus when the trap turns on. It has
21
+ * to be one that can take focus, so a heading needs `tabIndex={-1}`. When
22
+ * focusing it doesn't put focus inside the container (the ref is empty, or
23
+ * its element is outside, disabled, hidden or can't take focus), focus goes
24
+ * to the first tab stop inside the container, and to the container itself
25
+ * when there is none.
16
26
  */
17
27
  initialFocusRef?: RefObject<HTMLElement | null>;
18
28
  /**
@@ -17,6 +17,7 @@ export * from './components/Loading.js';
17
17
  export * from './components/Collapse.js';
18
18
  export * from './components/Collapses.js';
19
19
  export * from './components/Tooltip.js';
20
+ export * from './components/Popover.js';
20
21
  export * from './components/Steps.js';
21
22
  export * from './components/Sidebar.js';
22
23
  export * from './components/Toast.js';