@allxsmith/bestax-bulma 5.22.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.
- package/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +1769 -562
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +1764 -564
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/Popover.d.ts +166 -0
- package/dist/types/form/DateInput.d.ts +1 -1
- package/dist/types/form/DateInputBase.d.ts +33 -3
- package/dist/types/form/_pickerInternals/Calendar.d.ts +11 -1
- package/dist/types/form/_pickerInternals/dateUtils.d.ts +36 -1
- package/dist/types/form/_pickerInternals/formatters.d.ts +2 -0
- package/dist/types/form/_pickerInternals/nativeInputSupport.d.ts +11 -0
- package/dist/types/form/_pickerInternals/pickerTypes.d.ts +10 -0
- package/dist/types/form/_pickerInternals/useSegmentedEntry.d.ts +9 -1
- package/dist/types/helpers/portal.d.ts +62 -0
- package/dist/types/helpers/shadowDom.d.ts +3 -1
- package/dist/types/helpers/useAnchoredPosition.d.ts +59 -0
- package/dist/types/helpers/useClientLayoutEffect.d.ts +7 -0
- package/dist/types/helpers/useFocusTrap.d.ts +84 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types-cjs/components/Popover.d.ts +166 -0
- package/dist/types-cjs/form/DateInput.d.ts +1 -1
- package/dist/types-cjs/form/DateInputBase.d.ts +33 -3
- package/dist/types-cjs/form/_pickerInternals/Calendar.d.ts +11 -1
- package/dist/types-cjs/form/_pickerInternals/dateUtils.d.ts +36 -1
- package/dist/types-cjs/form/_pickerInternals/formatters.d.ts +2 -0
- package/dist/types-cjs/form/_pickerInternals/nativeInputSupport.d.ts +11 -0
- package/dist/types-cjs/form/_pickerInternals/pickerTypes.d.ts +10 -0
- package/dist/types-cjs/form/_pickerInternals/useSegmentedEntry.d.ts +9 -1
- package/dist/types-cjs/helpers/portal.d.ts +62 -0
- package/dist/types-cjs/helpers/shadowDom.d.ts +3 -1
- package/dist/types-cjs/helpers/useAnchoredPosition.d.ts +59 -0
- package/dist/types-cjs/helpers/useClientLayoutEffect.d.ts +7 -0
- package/dist/types-cjs/helpers/useFocusTrap.d.ts +84 -0
- package/dist/types-cjs/index.d.ts +5 -0
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/components/_index.scss +1 -0
- package/src/scss/components/_popover.scss +144 -0
- package/src/scss/form/_dateinput.scss +20 -3
- package/dist/types/form/_pickerInternals/useFocusTrap.d.ts +0 -7
- package/dist/types-cjs/form/_pickerInternals/useFocusTrap.d.ts +0 -7
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
|
|
3
|
+
import { ButtonOwnProps } from '../elements/Button.js';
|
|
4
|
+
import type { PickerPosition } from '../form/_pickerInternals/pickerTypes.js';
|
|
5
|
+
/**
|
|
6
|
+
* Where the panel opens against its trigger: below (`bottom-*`) or above
|
|
7
|
+
* (`top-*`), lined up with the trigger's left or right edge. `auto` picks the
|
|
8
|
+
* one that keeps the panel in the viewport, preferring below and lined up on
|
|
9
|
+
* the left. The same union the date and time pickers take.
|
|
10
|
+
*/
|
|
11
|
+
export type PopoverPosition = PickerPosition;
|
|
12
|
+
/**
|
|
13
|
+
* Props for the Popover component. `className`, `id`, the other HTML
|
|
14
|
+
* attributes and the helper props land on the wrapper around the trigger,
|
|
15
|
+
* not on the panel; `contentClassName` reaches the panel.
|
|
16
|
+
* @extraProp {string} [className] - Additional classes for the wrapper around the trigger. The panel takes `contentClassName`.
|
|
17
|
+
*/
|
|
18
|
+
export interface PopoverProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'children'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
|
|
19
|
+
/**
|
|
20
|
+
* The element that opens and closes the popover, such as a `Button`.
|
|
21
|
+
* Popover gives it `aria-haspopup="dialog"`, `aria-expanded`,
|
|
22
|
+
* `aria-controls` while the panel is open, and click and key handlers that
|
|
23
|
+
* run after its own (call `preventDefault()` in yours to keep the popover
|
|
24
|
+
* from toggling). It has to be a single element that passes `onClick` and
|
|
25
|
+
* `onKeyDown` to its DOM node. Enter and Space toggle a trigger the browser
|
|
26
|
+
* doesn't click on its own, and an intrinsic element that isn't already a
|
|
27
|
+
* control (a `<span>`) also gets `role="button"` and `tabIndex={0}` unless
|
|
28
|
+
* it sets them; a component that renders one has to take those itself.
|
|
29
|
+
*/
|
|
30
|
+
trigger: React.ReactElement;
|
|
31
|
+
/** The panel's content, usually `Popover.Header`, `Popover.Body` and `Popover.Footer`. */
|
|
32
|
+
children?: React.ReactNode;
|
|
33
|
+
/**
|
|
34
|
+
* Controlled open state. When set, the trigger and every dismissal only
|
|
35
|
+
* report through `onOpenChange`.
|
|
36
|
+
*/
|
|
37
|
+
open?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Initial open state when uncontrolled. Opening moves focus into the
|
|
40
|
+
* panel, so a popover that starts open takes focus once the page loads.
|
|
41
|
+
* @defaultValue false
|
|
42
|
+
*/
|
|
43
|
+
defaultOpen?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Called with the state asked for: `true` from the trigger opening it,
|
|
46
|
+
* `false` from the trigger, `Popover.Close`, Escape or an outside
|
|
47
|
+
* `pointerdown`. Fires in both controlled and uncontrolled use.
|
|
48
|
+
*/
|
|
49
|
+
onOpenChange?: (open: boolean) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Where the panel opens against the trigger.
|
|
52
|
+
* @defaultValue 'bottom-left'
|
|
53
|
+
*/
|
|
54
|
+
position?: PopoverPosition;
|
|
55
|
+
/**
|
|
56
|
+
* Render the panel at the end of `document.body` through `Portal`, fixed to
|
|
57
|
+
* the viewport, so an ancestor's `overflow`, `transform` or stacking context
|
|
58
|
+
* can't clip it. The panel then shows from the commit after hydration,
|
|
59
|
+
* never in server markup. It is measured against the trigger when it opens
|
|
60
|
+
* and on resize and scroll, so it doesn't follow content that changes size
|
|
61
|
+
* while it is open. Theming variables set on an ancestor of the trigger
|
|
62
|
+
* don't reach it there.
|
|
63
|
+
* @defaultValue false
|
|
64
|
+
*/
|
|
65
|
+
appendToBody?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Keep Tab and Shift+Tab inside the panel while it is open, as the ARIA
|
|
68
|
+
* dialog pattern does for a non-modal dialog. Pointer focus leaves freely
|
|
69
|
+
* and the page stays usable. With `false`, Tab moves past the panel and
|
|
70
|
+
* the popover stays open. Focus moves into the panel on open and back to
|
|
71
|
+
* the trigger on close either way.
|
|
72
|
+
* @defaultValue true
|
|
73
|
+
*/
|
|
74
|
+
trapFocus?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Close on a `pointerdown` outside the trigger and the panel. Content the
|
|
77
|
+
* panel renders through a portal (a nested `Popover`, a portaled picker)
|
|
78
|
+
* still counts as inside.
|
|
79
|
+
* @defaultValue true
|
|
80
|
+
*/
|
|
81
|
+
closeOnClickOutside?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Close on Escape while focus is in the panel or on the trigger. A dialog
|
|
84
|
+
* nested in the panel, such as a date picker's calendar, takes its own
|
|
85
|
+
* Escape first, and so does content that calls `preventDefault()` on it.
|
|
86
|
+
* @defaultValue true
|
|
87
|
+
*/
|
|
88
|
+
closeOnEscape?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* The panel's accessible name. Without it the panel is named by its
|
|
91
|
+
* `Popover.Header`, and a development build warns when it has neither.
|
|
92
|
+
*/
|
|
93
|
+
ariaLabel?: string;
|
|
94
|
+
/** Additional classes for the panel (`.popover-content`). */
|
|
95
|
+
contentClassName?: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Props for the Popover.Header component. Its `id` is the one the panel's
|
|
99
|
+
* `aria-labelledby` names, so it isn't yours to set.
|
|
100
|
+
*/
|
|
101
|
+
export interface PopoverHeaderProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'id'>, BulmaClassesProps {
|
|
102
|
+
/** Additional CSS classes. */
|
|
103
|
+
className?: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The popover's title, which names the panel for assistive technology.
|
|
107
|
+
*
|
|
108
|
+
* @function
|
|
109
|
+
* @param {PopoverHeaderProps} props - Props for the Popover.Header component.
|
|
110
|
+
* @returns {JSX.Element} The header element.
|
|
111
|
+
*/
|
|
112
|
+
export declare const PopoverHeader: React.FC<PopoverHeaderProps>;
|
|
113
|
+
/**
|
|
114
|
+
* Props for the Popover.Body component.
|
|
115
|
+
*/
|
|
116
|
+
export interface PopoverBodyProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>, BulmaClassesProps {
|
|
117
|
+
/** Additional CSS classes. */
|
|
118
|
+
className?: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The popover's main content area.
|
|
122
|
+
*
|
|
123
|
+
* @function
|
|
124
|
+
* @param {PopoverBodyProps} props - Props for the Popover.Body component.
|
|
125
|
+
* @returns {JSX.Element} The body element.
|
|
126
|
+
*/
|
|
127
|
+
export declare const PopoverBody: React.FC<PopoverBodyProps>;
|
|
128
|
+
/**
|
|
129
|
+
* Props for the Popover.Footer component.
|
|
130
|
+
*/
|
|
131
|
+
export interface PopoverFooterProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>, BulmaClassesProps {
|
|
132
|
+
/** Additional CSS classes. */
|
|
133
|
+
className?: string;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* A row of actions along the bottom of the popover, aligned to the end.
|
|
137
|
+
*
|
|
138
|
+
* @function
|
|
139
|
+
* @param {PopoverFooterProps} props - Props for the Popover.Footer component.
|
|
140
|
+
* @returns {JSX.Element} The footer element.
|
|
141
|
+
*/
|
|
142
|
+
export declare const PopoverFooter: React.FC<PopoverFooterProps>;
|
|
143
|
+
/**
|
|
144
|
+
* Props for the Popover.Close component: the props of a `Button` rendered as
|
|
145
|
+
* a `<button>`.
|
|
146
|
+
* @extraProp {'button' | 'submit' | 'reset'} [type='button'] - Button type. Defaults to `'button'`, so a close button inside a form doesn't submit it.
|
|
147
|
+
* @extraProp {React.MouseEventHandler<HTMLButtonElement>} [onClick] - Runs before the popover closes. Call `preventDefault()` to keep it open.
|
|
148
|
+
*/
|
|
149
|
+
export interface PopoverCloseProps extends ButtonOwnProps, Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof ButtonOwnProps> {
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* A `Button` that closes the popover, handing focus back to the trigger.
|
|
153
|
+
*
|
|
154
|
+
* @function
|
|
155
|
+
* @param {PopoverCloseProps} props - Props for the Popover.Close component.
|
|
156
|
+
* @returns {JSX.Element} The close button.
|
|
157
|
+
*/
|
|
158
|
+
export declare const PopoverClose: React.FC<PopoverCloseProps>;
|
|
159
|
+
/** Popover with Header, Body, Footer and Close sub-components. */
|
|
160
|
+
export declare const Popover: React.FC<PopoverProps> & {
|
|
161
|
+
Header: React.FC<PopoverHeaderProps>;
|
|
162
|
+
Body: React.FC<PopoverBodyProps>;
|
|
163
|
+
Footer: React.FC<PopoverFooterProps>;
|
|
164
|
+
Close: React.FC<PopoverCloseProps>;
|
|
165
|
+
};
|
|
166
|
+
export default Popover;
|
|
@@ -5,7 +5,7 @@ import { DateInputBaseProps } from './DateInputBase.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* Props for the DateInput convenience wrapper. Extends `DateInputBaseProps`
|
|
7
7
|
* with Field-level (label, horizontal) and Control-level (icons, loading) props.
|
|
8
|
-
* @extraProp {string} [name] - Form field name.
|
|
8
|
+
* @extraProp {string} [name] - Form field name. The text field submits the text it displays. The native input on touch devices submits the ISO value (`YYYY-MM-DD`, or `YYYY-MM` at month granularity), and an `inline` calendar, which has no visible input, submits it from a hidden input (`YYYY-MM-DD`, `YYYY-MM` or `YYYY`).
|
|
9
9
|
* @extraProp {string} [form] - Form id the input belongs to.
|
|
10
10
|
* @extraProp {boolean} [required=false] - Marks the input as required.
|
|
11
11
|
* @extraProp {string} [className] - Additional CSS classes for the input.
|
|
@@ -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
|
-
*
|
|
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
|
-
/**
|
|
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. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
/**
|
|
2
3
|
* Resolves a portal target: an `HTMLElement` is used directly, a non-empty
|
|
3
4
|
* `string` is treated as a `document.querySelector` selector (falling back to
|
|
@@ -13,3 +14,64 @@
|
|
|
13
14
|
* @returns The resolved DOM node to portal into.
|
|
14
15
|
*/
|
|
15
16
|
export declare function resolvePortalContainer(container?: string | HTMLElement): HTMLElement;
|
|
17
|
+
/**
|
|
18
|
+
* Props for the Portal component.
|
|
19
|
+
*/
|
|
20
|
+
export interface PortalProps {
|
|
21
|
+
/** Content to render into the container. */
|
|
22
|
+
children?: React.ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* Where the content goes: an element, or a `document.querySelector`
|
|
25
|
+
* selector. Omitted, empty, or a selector that matches nothing, it goes to
|
|
26
|
+
* `document.body`. A selector is looked up again on each render, so the
|
|
27
|
+
* content follows the target when it changes. Moving to another target
|
|
28
|
+
* remounts the children and resets their state, which includes a selector
|
|
29
|
+
* that only starts matching after the content has shown in `document.body`.
|
|
30
|
+
* Render the target first, or pass the element once you have it.
|
|
31
|
+
*/
|
|
32
|
+
container?: string | HTMLElement;
|
|
33
|
+
/**
|
|
34
|
+
* Render the children in place instead, on the server as well as the
|
|
35
|
+
* client. Lets a component that portals only sometimes keep a single code
|
|
36
|
+
* path.
|
|
37
|
+
* @defaultValue false
|
|
38
|
+
*/
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Renders its children into another part of the page, `document.body` unless `container` says otherwise, so floating content escapes an ancestor's `overflow`, `transform` or stacking context.
|
|
43
|
+
*
|
|
44
|
+
* React's server renderer can't render a portal, so `Portal` renders nothing
|
|
45
|
+
* on the server and during hydration, and mounts its children in the commit
|
|
46
|
+
* that follows. The first client render then matches the server markup. In an app
|
|
47
|
+
* without server rendering it portals on the first render.
|
|
48
|
+
*
|
|
49
|
+
* React context, such as `ConfigProvider`'s class prefix, reaches the
|
|
50
|
+
* portaled children, and their React events bubble through the React tree.
|
|
51
|
+
* CSS inheritance follows the DOM instead: a scoped (non-`isRoot`) `Theme`
|
|
52
|
+
* sets its variables on a wrapper element the portaled content has left, so
|
|
53
|
+
* that content sees the page-level theme. Point `container` at an element
|
|
54
|
+
* inside the themed area to keep it.
|
|
55
|
+
*
|
|
56
|
+
* Tab order and focus follow the DOM too. Content portaled from inside a
|
|
57
|
+
* focus trap is no longer inside the trapped element, so the trap neither
|
|
58
|
+
* reaches it nor holds focus there: render nested overlays inside the
|
|
59
|
+
* trapped element, or give them a trap of their own.
|
|
60
|
+
*
|
|
61
|
+
* @function
|
|
62
|
+
* @param {PortalProps} props - Props for the Portal component.
|
|
63
|
+
* @returns The portal, the children in place when `disabled`, or nothing
|
|
64
|
+
* before hydration.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* <Portal>
|
|
68
|
+
* <div className="box">Rendered at the end of document.body</div>
|
|
69
|
+
* </Portal>
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* // Into a dedicated overlay root
|
|
73
|
+
* <Portal container="#overlays">
|
|
74
|
+
* <CommandPalette />
|
|
75
|
+
* </Portal>
|
|
76
|
+
*/
|
|
77
|
+
export declare function Portal({ children, container, disabled }: PortalProps): React.JSX.Element | null;
|
|
@@ -49,6 +49,8 @@ export declare function getActiveElementInTree(node: Node | null | undefined): E
|
|
|
49
49
|
* opener sits in. A closed shadow root cannot be entered, so focus inside one
|
|
50
50
|
* reads as its host.
|
|
51
51
|
*
|
|
52
|
+
* @param doc - The document to start from: the component's own, when it may
|
|
53
|
+
* render into one other than the page's (an iframe's). Defaults to `document`.
|
|
52
54
|
* @returns The focused element, or `null` when the document has none.
|
|
53
55
|
*/
|
|
54
|
-
export declare function getDeepestActiveElement(): Element | null;
|
|
56
|
+
export declare function getDeepestActiveElement(doc?: Document): Element | null;
|
|
@@ -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;
|
|
@@ -0,0 +1,84 @@
|
|
|
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;
|
|
9
|
+
/**
|
|
10
|
+
* Options for `useFocusTrap`.
|
|
11
|
+
*/
|
|
12
|
+
export interface UseFocusTrapOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Whether the trap is on. Turning it on moves focus into the container;
|
|
15
|
+
* turning it off (or unmounting) releases Tab and restores focus.
|
|
16
|
+
* @defaultValue true
|
|
17
|
+
*/
|
|
18
|
+
active?: boolean;
|
|
19
|
+
/**
|
|
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.
|
|
26
|
+
*/
|
|
27
|
+
initialFocusRef?: RefObject<HTMLElement | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Where focus goes when the trap turns off. `true` returns it to the element
|
|
30
|
+
* that had focus when the trap turned on; a ref sends it to that element
|
|
31
|
+
* instead; `false` leaves it alone. Focus is only moved while the trap still
|
|
32
|
+
* holds it, so a click that already put focus somewhere else outside the
|
|
33
|
+
* container keeps it there.
|
|
34
|
+
*
|
|
35
|
+
* `true` reads focus after the container's content has mounted, so content
|
|
36
|
+
* that focuses itself as it mounts (an `autoFocus` input) hides the element
|
|
37
|
+
* that opened it. And some browsers don't focus a button when it is
|
|
38
|
+
* clicked. For a panel opened from a button, pass the button's ref.
|
|
39
|
+
* @defaultValue true
|
|
40
|
+
*/
|
|
41
|
+
restoreFocus?: boolean | RefObject<HTMLElement | null>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Keeps keyboard focus inside a container while it is active: focus moves in
|
|
45
|
+
* when the trap turns on, Tab and Shift+Tab wrap between the first and last
|
|
46
|
+
* tab stops, and focus goes back where it came from when the trap turns off.
|
|
47
|
+
*
|
|
48
|
+
* Tab stops are what the browser's Tab visits, in document order: links,
|
|
49
|
+
* form controls, frames, media with controls, a `<details>` summary, editable
|
|
50
|
+
* regions, anything with `tabIndex={0}`, and the content of open shadow
|
|
51
|
+
* roots. Hidden, disabled, inert and `tabIndex={-1}` elements are skipped,
|
|
52
|
+
* and a radio group counts once. Give the container `tabIndex={-1}` so it can
|
|
53
|
+
* hold focus itself when nothing inside can. The trap listens on the
|
|
54
|
+
* container, so a trap nested inside another handles Tab first and the outer
|
|
55
|
+
* one stands aside.
|
|
56
|
+
*
|
|
57
|
+
* The trap is about Tab. If a Tab it let through still takes focus out (a
|
|
58
|
+
* browser can leave out a stop the page has, such as links when its settings
|
|
59
|
+
* say to), it sends focus back to the other end. A pointer or a script moving
|
|
60
|
+
* focus out is left alone, because pulling focus back from a click is modal
|
|
61
|
+
* behaviour, and a modal also has to block the page behind it, which `Modal`
|
|
62
|
+
* does. Content the container renders through a portal lives elsewhere in
|
|
63
|
+
* the DOM, so it is outside the trap: render nested overlays inside the
|
|
64
|
+
* container, or give them a trap of their own.
|
|
65
|
+
*
|
|
66
|
+
* The container has to be in the DOM when the trap turns on. The trap waits
|
|
67
|
+
* for hydration, so a container that only appears once the page has
|
|
68
|
+
* hydrated, the way portaled content does, still has it attach in the commit
|
|
69
|
+
* where the container appears.
|
|
70
|
+
*
|
|
71
|
+
* @function useFocusTrap
|
|
72
|
+
* @param containerRef - Ref to the element focus stays inside.
|
|
73
|
+
* @param options - When the trap is on, and where focus starts and ends.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const panelRef = useRef<HTMLDivElement>(null);
|
|
77
|
+
* useFocusTrap(panelRef, { active: isOpen });
|
|
78
|
+
* return isOpen ? (
|
|
79
|
+
* <div ref={panelRef} role="dialog" aria-label="Filters" tabIndex={-1}>
|
|
80
|
+
* …
|
|
81
|
+
* </div>
|
|
82
|
+
* ) : null;
|
|
83
|
+
*/
|
|
84
|
+
export declare function useFocusTrap(containerRef: RefObject<HTMLElement | null>, options?: UseFocusTrapOptions): void;
|
|
@@ -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';
|
|
@@ -110,6 +111,10 @@ export * from './helpers/Config.js';
|
|
|
110
111
|
export { ClientOnly } from './helpers/ClientOnly.js';
|
|
111
112
|
export type { ClientOnlyProps } from './helpers/ClientOnly.js';
|
|
112
113
|
export { useIsHydrated } from './helpers/useIsHydrated.js';
|
|
114
|
+
export { Portal } from './helpers/portal.js';
|
|
115
|
+
export type { PortalProps } from './helpers/portal.js';
|
|
116
|
+
export { useFocusTrap } from './helpers/useFocusTrap.js';
|
|
117
|
+
export type { UseFocusTrapOptions } from './helpers/useFocusTrap.js';
|
|
113
118
|
export * from './layout/Container.js';
|
|
114
119
|
export * from './layout/Footer.js';
|
|
115
120
|
export * from './layout/Hero.js';
|