@allxsmith/bestax-bulma 5.40.0 → 5.42.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 (40) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Carousel.js +282 -103
  4. package/dist/esm/components/Carousel.js.map +1 -1
  5. package/dist/esm/components/Menu.js +77 -2
  6. package/dist/esm/components/Menu.js.map +1 -1
  7. package/dist/esm/components/Modal.js +3 -3
  8. package/dist/esm/components/Modal.js.map +1 -1
  9. package/dist/esm/components/Popover.js +2 -2
  10. package/dist/esm/components/Popover.js.map +1 -1
  11. package/dist/esm/components/Sidebar.js +2 -2
  12. package/dist/esm/components/Sidebar.js.map +1 -1
  13. package/dist/esm/elements/Image.js +4 -12
  14. package/dist/esm/elements/Image.js.map +1 -1
  15. package/dist/esm/helpers/useFocusTrap.js +60 -41
  16. package/dist/esm/helpers/useFocusTrap.js.map +1 -1
  17. package/dist/extras.css +1 -1
  18. package/dist/extras.css.map +1 -1
  19. package/dist/index.cjs +442 -181
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.esm.js +1 -1
  22. package/dist/types/components/Carousel.d.ts +96 -8
  23. package/dist/types/components/Menu.d.ts +49 -0
  24. package/dist/types/elements/Image.d.ts +6 -1
  25. package/dist/types/helpers/useFocusTrap.d.ts +16 -8
  26. package/dist/types-cjs/components/Carousel.d.ts +96 -8
  27. package/dist/types-cjs/components/Menu.d.ts +49 -0
  28. package/dist/types-cjs/elements/Image.d.ts +6 -1
  29. package/dist/types-cjs/helpers/useFocusTrap.d.ts +16 -8
  30. package/dist/versions/bestax-no-dark-mode.css +1 -1
  31. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  32. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  33. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  34. package/dist/versions/bestax-no-helpers.css +1 -1
  35. package/dist/versions/bestax-no-helpers.css.map +1 -1
  36. package/dist/versions/bestax-prefixed.css +1 -1
  37. package/dist/versions/bestax-prefixed.css.map +1 -1
  38. package/package.json +6 -6
  39. package/src/scss/components/_carousel.scss +77 -24
  40. package/src/scss/components/_menu.scss +130 -3
package/dist/index.esm.js CHANGED
@@ -8,7 +8,7 @@ export { Breadcrumb } from './esm/components/Breadcrumb.js';
8
8
  export { Card } from './esm/components/Card.js';
9
9
  export { Dropdown, DropdownDivider, DropdownItem, isBrowser } from './esm/components/Dropdown.js';
10
10
  export { EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateIndicator, EmptyStateTitle } from './esm/components/EmptyState.js';
11
- export { Menu, MenuItem, MenuLabel, MenuList } from './esm/components/Menu.js';
11
+ export { Menu, MenuItem, MenuLabel, MenuList, MenuSection } from './esm/components/Menu.js';
12
12
  export { Message } from './esm/components/Message.js';
13
13
  export { Modal } from './esm/components/Modal.js';
14
14
  export { Navbar, NavbarBrand, NavbarBurger, NavbarDivider, NavbarDropdown, NavbarDropdownMenu, NavbarEnd, NavbarItem, NavbarLink, NavbarMenu, NavbarStart } from './esm/components/Navbar.js';
@@ -4,7 +4,10 @@ import { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
4
4
  * Props for the CarouselItem component.
5
5
  */
6
6
  export interface CarouselItemProps extends React.HTMLAttributes<HTMLDivElement> {
7
- /** Whether this item is active (set automatically). */
7
+ /**
8
+ * Whether this item is in view. `Carousel` sets it on every item in view,
9
+ * so with several in view several are active.
10
+ */
8
11
  active?: boolean;
9
12
  }
10
13
  /**
@@ -24,20 +27,93 @@ type IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';
24
27
  */
25
28
  export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'color'>, BulmaClassesProps {
26
29
  /**
27
- * Current active slide index (controlled).
30
+ * Index of the first item in view (controlled); with one item in view, the
31
+ * slide shown. A value between two of the positions a step lands on (see
32
+ * `itemsToScroll`) is shown as given, and the next step goes on from it.
33
+ * With `repeat`, a value past either end wraps around; without it, one
34
+ * that would leave empty space after the last item shows the last full
35
+ * view. Neither correction calls `onChange`. A value that takes the item
36
+ * holding focus out of view moves focus to the first item in view, as a
37
+ * swipe or a change of width does.
28
38
  * @defaultValue 0
29
39
  */
30
40
  value?: number;
31
- /** Enable auto-play. */
41
+ /**
42
+ * Enable auto-play: one step (`itemsToScroll` items) per `interval`.
43
+ * Without `repeat` it stops at the last position. It waits while the
44
+ * pointer is over the carousel (see `pauseOnHover`) and while focus is
45
+ * inside one of its items, so an item being read or used never moves out
46
+ * of view.
47
+ */
32
48
  autoplay?: boolean;
33
49
  /** Auto-play interval in milliseconds. Default: 5000. */
34
50
  interval?: number;
35
51
  /** Pause auto-play on hover. Default: true. */
36
52
  pauseOnHover?: boolean;
37
- /** Loop back to first slide after last. Default: true. */
53
+ /**
54
+ * Loop back to the first position after the last. Default: true. With
55
+ * several items in view, the view runs on past the last item into the
56
+ * first ones, so it can show the end and the start side by side. Only
57
+ * loops when some item is out of view.
58
+ */
38
59
  repeat?: boolean;
39
- /** Enable drag/swipe navigation. Default: true. */
60
+ /**
61
+ * Enable drag/swipe navigation. Default: true. A swipe moves one step,
62
+ * however far it travels.
63
+ */
40
64
  hasDrag?: boolean;
65
+ /**
66
+ * How many items are in view at once, at every width no
67
+ * `itemsToShow<Viewport>` prop covers. Those props read the way a
68
+ * `Column`'s `size<Viewport>` props do: `itemsToShowMobile` applies below
69
+ * Bulma's tablet breakpoint, each of the others from its own breakpoint
70
+ * up, and where several apply the widest one wins. A whole number, rounded
71
+ * down and at least 1. The widths come from the stylesheet, so they are
72
+ * right on the first paint; the arrows, indicators and steps use the
73
+ * count for the window's width once the page has hydrated, and this one
74
+ * until then. With this many children or fewer, every item keeps its
75
+ * share of the width, nothing moves, and no arrows or indicators render.
76
+ * @defaultValue 1
77
+ */
78
+ itemsToShow?: number;
79
+ /**
80
+ * Items in view at any width below Bulma's tablet breakpoint (769px),
81
+ * fractional ones included. Falls back to `itemsToShow`.
82
+ */
83
+ itemsToShowMobile?: number;
84
+ /**
85
+ * Items in view from Bulma's tablet breakpoint (769px) up, until a wider
86
+ * viewport's prop takes over. Falls back to `itemsToShow`.
87
+ */
88
+ itemsToShowTablet?: number;
89
+ /**
90
+ * Items in view from Bulma's desktop breakpoint (1024px) up, until a wider
91
+ * viewport's prop takes over. Falls back to `itemsToShowTablet`, then
92
+ * `itemsToShow`.
93
+ */
94
+ itemsToShowDesktop?: number;
95
+ /**
96
+ * Items in view from Bulma's widescreen breakpoint (1216px) up, until
97
+ * `itemsToShowFullhd` takes over. Falls back to `itemsToShowDesktop`, and
98
+ * on down to `itemsToShow`.
99
+ */
100
+ itemsToShowWidescreen?: number;
101
+ /**
102
+ * Items in view from Bulma's fullhd breakpoint (1408px) up. Falls back to
103
+ * `itemsToShowWidescreen`, and on down to `itemsToShow`.
104
+ */
105
+ itemsToShowFullhd?: number;
106
+ /**
107
+ * How many items one step moves, for an arrow, an arrow key, a swipe or an
108
+ * autoplay tick. A whole number, capped at the count in view so a step
109
+ * never skips an item. Without `repeat`, the last step stops at the last
110
+ * full view, so it can be shorter; with `repeat`, the step after the last
111
+ * position goes on to the first one. The indicators mark these positions,
112
+ * one per step rather than one per item. When the count in view changes
113
+ * with the window's width, the first item in view stays in view.
114
+ * @defaultValue 1
115
+ */
116
+ itemsToScroll?: number;
41
117
  /**
42
118
  * Show navigation arrows. Default: true. They render `type="button"`, so a
43
119
  * carousel inside a form is not submitted by moving between slides.
@@ -46,8 +122,9 @@ export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>
46
122
  /** Only show arrows on hover. */
47
123
  arrowHover?: boolean;
48
124
  /**
49
- * Show slide indicators. Default: true. They render `type="button"`, so a
50
- * carousel inside a form is not submitted by picking a slide.
125
+ * Show slide indicators. Default: true. There is one for each position a
126
+ * step can land on (see `itemsToScroll`). They render `type="button"`, so
127
+ * a carousel inside a form is not submitted by picking a slide.
51
128
  */
52
129
  indicator?: boolean;
53
130
  /** Position indicators inside carousel. */
@@ -74,7 +151,10 @@ export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>
74
151
  arrowColor?: 'light' | 'dark';
75
152
  /** Accessible label for the carousel region. Default: 'Image carousel'. */
76
153
  ariaLabel?: string;
77
- /** Callback when slide changes. */
154
+ /**
155
+ * Called with the index of the first item in view when an arrow, an arrow
156
+ * key, an indicator, a swipe or autoplay moves the carousel.
157
+ */
78
158
  onChange?: (value: number) => void;
79
159
  /** CarouselItem children. */
80
160
  children?: React.ReactNode;
@@ -105,6 +185,14 @@ export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>
105
185
  * <img src="image2.jpg" alt="Slide 2" />
106
186
  * </CarouselItem>
107
187
  * </Carousel>
188
+ *
189
+ * @example
190
+ * // Three cards in view on desktop, two on tablet, one on mobile
191
+ * <Carousel itemsToShow={1} itemsToShowTablet={2} itemsToShowDesktop={3}>
192
+ * {cards.map(card => (
193
+ * <CarouselItem key={card.id}>{card.body}</CarouselItem>
194
+ * ))}
195
+ * </Carousel>
108
196
  */
109
197
  export declare const Carousel: React.ForwardRefExoticComponent<CarouselProps & React.RefAttributes<HTMLDivElement>>;
110
198
  export default Carousel;
@@ -115,9 +115,58 @@ export type MenuItemProps<T extends React.ElementType = 'a'> = MenuItemOwnProps
115
115
  * @returns {JSX.Element} The rendered menu item.
116
116
  */
117
117
  export declare const MenuItem: PolymorphicComponent<MenuItemOwnProps, "a">;
118
+ /**
119
+ * Props for the MenuSection component. The helper props and the other
120
+ * attributes land on the wrapping `<div>`.
121
+ */
122
+ export interface MenuSectionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, keyof BulmaClassesProps>, BulmaClassesProps {
123
+ /** Additional CSS classes for the wrapping `<div>`. */
124
+ className?: string;
125
+ /** **Required.** The section's heading, drawn like `Menu.Label` inside the button that opens and closes it. Keep links and buttons out of it, since it's inside one. */
126
+ label: React.ReactNode;
127
+ /**
128
+ * The `Menu.List` of links the section shows while it's open. The section
129
+ * itself goes directly in `Menu`, beside its labels and lists: inside a
130
+ * `Menu.Item` it would render inside the item's link, and inside a
131
+ * `Menu.List` it wouldn't be a list item.
132
+ */
133
+ children: React.ReactNode;
134
+ /** Controlled open state. If provided, the section is controlled, and its button only reports through `onOpenChange`. */
135
+ open?: boolean;
136
+ /** Initial open state for uncontrolled usage. Open the section that holds the current page, so the reader sees where they are. */
137
+ defaultOpen?: boolean;
138
+ /** Called with the state the button asks for (`true` to open) each time it is clicked or activated with Enter or Space, in every mode. Pair it with `open` to let the button drive a controlled section. */
139
+ onOpenChange?: (open: boolean) => void;
140
+ }
141
+ /**
142
+ * A section of the menu that opens and closes: its heading is a button drawn like `Menu.Label`, and its `Menu.List` of links shows while it's open.
143
+ *
144
+ * It's APG's disclosure navigation, for a sidebar of link groups: the links
145
+ * stay ordinary links, each its own tab stop, and a closed section's list is
146
+ * `hidden` and `inert`, so Tab and assistive tech skip it. It goes directly in
147
+ * `Menu`, holding a `Menu.List`. Closing it while focus is on one of its links
148
+ * moves focus to its heading.
149
+ *
150
+ * @function
151
+ * @param {MenuSectionProps} props - Props for the MenuSection component.
152
+ * @returns {JSX.Element} The rendered menu section.
153
+ * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/ | APG Disclosure Navigation Menu example}
154
+ *
155
+ * @example
156
+ * <Menu>
157
+ * <Menu.Section label="Components" defaultOpen>
158
+ * <Menu.List>
159
+ * <Menu.Item href="/button" active>Button</Menu.Item>
160
+ * <Menu.Item href="/card">Card</Menu.Item>
161
+ * </Menu.List>
162
+ * </Menu.Section>
163
+ * </Menu>
164
+ */
165
+ export declare const MenuSection: React.FC<MenuSectionProps>;
118
166
  export declare const Menu: React.FC<MenuProps> & {
119
167
  Label: React.FC<MenuLabelProps>;
120
168
  List: React.FC<MenuListProps>;
121
169
  Item: PolymorphicComponent<MenuItemOwnProps, "a", never>;
170
+ Section: React.FC<MenuSectionProps>;
122
171
  };
123
172
  export default Menu;
@@ -17,7 +17,12 @@ export interface ImageProps extends React.HTMLAttributes<HTMLElement>, Omit<Bulm
17
17
  color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';
18
18
  /** Background color helper for the container. */
19
19
  bgColor?: (typeof validColors)[number] | 'inherit' | 'current';
20
- /** Fixed size or aspect ratio modifier for the image container. */
20
+ /**
21
+ * Fixed size or aspect ratio modifier for the image container. A ratio
22
+ * (`16by9` and the rest) renders only its `is-<ratio>` class there. Bulma
23
+ * stretches an `<img>` inside to fill the ratio, but any other child, such
24
+ * as an `iframe`, fills it only with `className="has-ratio"` of its own.
25
+ */
21
26
  size?: '16x16' | '24x24' | '32x32' | '48x48' | '64x64' | '96x96' | '128x128' | 'square' | '1by1' | '5by4' | '4by3' | '3by2' | '5by3' | '16by9' | '2by1' | '3by1' | '4by5' | '3by4' | '2by3' | '3by5' | '9by16' | '1by2' | '1by3';
22
27
  /** Renders the image with rounded corners. */
23
28
  isRounded?: boolean;
@@ -5,16 +5,24 @@ import type { RefObject } from 'react';
5
5
  * can read `-1` for an editable region or an `<embed>` that Tab still visits,
6
6
  * and `0` for a `<video>` without controls that it doesn't. So a valid
7
7
  * `tabindex` attribute decides, and otherwise the element's kind does.
8
- * Internal like `firstTabStop`: `src/index.ts` names what it takes from here.
8
+ * Internal like `focusTabStop`: `src/index.ts` names what it takes from here.
9
9
  */
10
10
  export declare function isTabbableKind(el: Element): boolean;
11
11
  /**
12
- * The first tab stop inside `container`, found the way the trap finds it, or
13
- * `null` when there is none. For a component that moves focus into a panel
14
- * itself rather than through the hook. `src/index.ts` names its exports from
12
+ * Moves focus to the first tab stop inside `container`, or the last when
13
+ * `fromLast`, and to the container when there is none. Every move a trap
14
+ * makes goes through here: into the container as it opens, to the other end
15
+ * on a wrap, and back in after a Tab the browser carried out.
16
+ *
17
+ * A stop that doesn't take focus is passed over for the next one in. An
18
+ * `<object>` or `<embed>` with nothing to show is one: it counts as a stop by
19
+ * its kind, but browsers refuse to focus it, and which ones they refuse
20
+ * depends on the browser and on what has loaded, so only trying tells. A
21
+ * stop took focus when focus moved, wherever it went (a stop can hand focus
22
+ * on), or when focus was on it already. `src/index.ts` names its exports from
15
23
  * this module, so this one stays internal.
16
24
  */
17
- export declare function firstTabStop(container: HTMLElement): HTMLElement | null;
25
+ export declare function focusTabStop(container: HTMLElement, fromLast?: boolean): void;
18
26
  /**
19
27
  * Holds Tab inside the element `container` returns until the returned
20
28
  * function is called. Tab and Shift+Tab heard on `keyTarget` wrap at the
@@ -25,7 +33,7 @@ export declare function firstTabStop(container: HTMLElement): HTMLElement | null
25
33
  * overlay whose nodes are remounted while it's open, as moving to another
26
34
  * portal target does, stays trapped without attaching again. `holds` is asked
27
35
  * on every Tab, and the trap leaves the key alone while it says no. Internal
28
- * like `firstTabStop`. It's for an overlay that holds Tab from a listener of
36
+ * like `focusTabStop`. It's for an overlay that holds Tab from a listener of
29
37
  * its own on `window` and asks the overlay stack first, so it stands aside
30
38
  * while another overlay is open over it, which a trap listening on the
31
39
  * container can't do.
@@ -46,8 +54,8 @@ export interface UseFocusTrapOptions {
46
54
  * to be one that can take focus, so a heading needs `tabIndex={-1}`. When
47
55
  * focusing it doesn't put focus inside the container (the ref is empty, or
48
56
  * its element is outside, disabled, hidden or can't take focus), focus goes
49
- * to the first tab stop inside the container, and to the container itself
50
- * when there is none.
57
+ * to the first tab stop inside the container that takes focus, and to the
58
+ * container itself when none does.
51
59
  */
52
60
  initialFocusRef?: RefObject<HTMLElement | null>;
53
61
  /**
@@ -4,7 +4,10 @@ import { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
4
4
  * Props for the CarouselItem component.
5
5
  */
6
6
  export interface CarouselItemProps extends React.HTMLAttributes<HTMLDivElement> {
7
- /** Whether this item is active (set automatically). */
7
+ /**
8
+ * Whether this item is in view. `Carousel` sets it on every item in view,
9
+ * so with several in view several are active.
10
+ */
8
11
  active?: boolean;
9
12
  }
10
13
  /**
@@ -24,20 +27,93 @@ type IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';
24
27
  */
25
28
  export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'color'>, BulmaClassesProps {
26
29
  /**
27
- * Current active slide index (controlled).
30
+ * Index of the first item in view (controlled); with one item in view, the
31
+ * slide shown. A value between two of the positions a step lands on (see
32
+ * `itemsToScroll`) is shown as given, and the next step goes on from it.
33
+ * With `repeat`, a value past either end wraps around; without it, one
34
+ * that would leave empty space after the last item shows the last full
35
+ * view. Neither correction calls `onChange`. A value that takes the item
36
+ * holding focus out of view moves focus to the first item in view, as a
37
+ * swipe or a change of width does.
28
38
  * @defaultValue 0
29
39
  */
30
40
  value?: number;
31
- /** Enable auto-play. */
41
+ /**
42
+ * Enable auto-play: one step (`itemsToScroll` items) per `interval`.
43
+ * Without `repeat` it stops at the last position. It waits while the
44
+ * pointer is over the carousel (see `pauseOnHover`) and while focus is
45
+ * inside one of its items, so an item being read or used never moves out
46
+ * of view.
47
+ */
32
48
  autoplay?: boolean;
33
49
  /** Auto-play interval in milliseconds. Default: 5000. */
34
50
  interval?: number;
35
51
  /** Pause auto-play on hover. Default: true. */
36
52
  pauseOnHover?: boolean;
37
- /** Loop back to first slide after last. Default: true. */
53
+ /**
54
+ * Loop back to the first position after the last. Default: true. With
55
+ * several items in view, the view runs on past the last item into the
56
+ * first ones, so it can show the end and the start side by side. Only
57
+ * loops when some item is out of view.
58
+ */
38
59
  repeat?: boolean;
39
- /** Enable drag/swipe navigation. Default: true. */
60
+ /**
61
+ * Enable drag/swipe navigation. Default: true. A swipe moves one step,
62
+ * however far it travels.
63
+ */
40
64
  hasDrag?: boolean;
65
+ /**
66
+ * How many items are in view at once, at every width no
67
+ * `itemsToShow<Viewport>` prop covers. Those props read the way a
68
+ * `Column`'s `size<Viewport>` props do: `itemsToShowMobile` applies below
69
+ * Bulma's tablet breakpoint, each of the others from its own breakpoint
70
+ * up, and where several apply the widest one wins. A whole number, rounded
71
+ * down and at least 1. The widths come from the stylesheet, so they are
72
+ * right on the first paint; the arrows, indicators and steps use the
73
+ * count for the window's width once the page has hydrated, and this one
74
+ * until then. With this many children or fewer, every item keeps its
75
+ * share of the width, nothing moves, and no arrows or indicators render.
76
+ * @defaultValue 1
77
+ */
78
+ itemsToShow?: number;
79
+ /**
80
+ * Items in view at any width below Bulma's tablet breakpoint (769px),
81
+ * fractional ones included. Falls back to `itemsToShow`.
82
+ */
83
+ itemsToShowMobile?: number;
84
+ /**
85
+ * Items in view from Bulma's tablet breakpoint (769px) up, until a wider
86
+ * viewport's prop takes over. Falls back to `itemsToShow`.
87
+ */
88
+ itemsToShowTablet?: number;
89
+ /**
90
+ * Items in view from Bulma's desktop breakpoint (1024px) up, until a wider
91
+ * viewport's prop takes over. Falls back to `itemsToShowTablet`, then
92
+ * `itemsToShow`.
93
+ */
94
+ itemsToShowDesktop?: number;
95
+ /**
96
+ * Items in view from Bulma's widescreen breakpoint (1216px) up, until
97
+ * `itemsToShowFullhd` takes over. Falls back to `itemsToShowDesktop`, and
98
+ * on down to `itemsToShow`.
99
+ */
100
+ itemsToShowWidescreen?: number;
101
+ /**
102
+ * Items in view from Bulma's fullhd breakpoint (1408px) up. Falls back to
103
+ * `itemsToShowWidescreen`, and on down to `itemsToShow`.
104
+ */
105
+ itemsToShowFullhd?: number;
106
+ /**
107
+ * How many items one step moves, for an arrow, an arrow key, a swipe or an
108
+ * autoplay tick. A whole number, capped at the count in view so a step
109
+ * never skips an item. Without `repeat`, the last step stops at the last
110
+ * full view, so it can be shorter; with `repeat`, the step after the last
111
+ * position goes on to the first one. The indicators mark these positions,
112
+ * one per step rather than one per item. When the count in view changes
113
+ * with the window's width, the first item in view stays in view.
114
+ * @defaultValue 1
115
+ */
116
+ itemsToScroll?: number;
41
117
  /**
42
118
  * Show navigation arrows. Default: true. They render `type="button"`, so a
43
119
  * carousel inside a form is not submitted by moving between slides.
@@ -46,8 +122,9 @@ export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>
46
122
  /** Only show arrows on hover. */
47
123
  arrowHover?: boolean;
48
124
  /**
49
- * Show slide indicators. Default: true. They render `type="button"`, so a
50
- * carousel inside a form is not submitted by picking a slide.
125
+ * Show slide indicators. Default: true. There is one for each position a
126
+ * step can land on (see `itemsToScroll`). They render `type="button"`, so
127
+ * a carousel inside a form is not submitted by picking a slide.
51
128
  */
52
129
  indicator?: boolean;
53
130
  /** Position indicators inside carousel. */
@@ -74,7 +151,10 @@ export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>
74
151
  arrowColor?: 'light' | 'dark';
75
152
  /** Accessible label for the carousel region. Default: 'Image carousel'. */
76
153
  ariaLabel?: string;
77
- /** Callback when slide changes. */
154
+ /**
155
+ * Called with the index of the first item in view when an arrow, an arrow
156
+ * key, an indicator, a swipe or autoplay moves the carousel.
157
+ */
78
158
  onChange?: (value: number) => void;
79
159
  /** CarouselItem children. */
80
160
  children?: React.ReactNode;
@@ -105,6 +185,14 @@ export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>
105
185
  * <img src="image2.jpg" alt="Slide 2" />
106
186
  * </CarouselItem>
107
187
  * </Carousel>
188
+ *
189
+ * @example
190
+ * // Three cards in view on desktop, two on tablet, one on mobile
191
+ * <Carousel itemsToShow={1} itemsToShowTablet={2} itemsToShowDesktop={3}>
192
+ * {cards.map(card => (
193
+ * <CarouselItem key={card.id}>{card.body}</CarouselItem>
194
+ * ))}
195
+ * </Carousel>
108
196
  */
109
197
  export declare const Carousel: React.ForwardRefExoticComponent<CarouselProps & React.RefAttributes<HTMLDivElement>>;
110
198
  export default Carousel;
@@ -115,9 +115,58 @@ export type MenuItemProps<T extends React.ElementType = 'a'> = MenuItemOwnProps
115
115
  * @returns {JSX.Element} The rendered menu item.
116
116
  */
117
117
  export declare const MenuItem: PolymorphicComponent<MenuItemOwnProps, "a">;
118
+ /**
119
+ * Props for the MenuSection component. The helper props and the other
120
+ * attributes land on the wrapping `<div>`.
121
+ */
122
+ export interface MenuSectionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, keyof BulmaClassesProps>, BulmaClassesProps {
123
+ /** Additional CSS classes for the wrapping `<div>`. */
124
+ className?: string;
125
+ /** **Required.** The section's heading, drawn like `Menu.Label` inside the button that opens and closes it. Keep links and buttons out of it, since it's inside one. */
126
+ label: React.ReactNode;
127
+ /**
128
+ * The `Menu.List` of links the section shows while it's open. The section
129
+ * itself goes directly in `Menu`, beside its labels and lists: inside a
130
+ * `Menu.Item` it would render inside the item's link, and inside a
131
+ * `Menu.List` it wouldn't be a list item.
132
+ */
133
+ children: React.ReactNode;
134
+ /** Controlled open state. If provided, the section is controlled, and its button only reports through `onOpenChange`. */
135
+ open?: boolean;
136
+ /** Initial open state for uncontrolled usage. Open the section that holds the current page, so the reader sees where they are. */
137
+ defaultOpen?: boolean;
138
+ /** Called with the state the button asks for (`true` to open) each time it is clicked or activated with Enter or Space, in every mode. Pair it with `open` to let the button drive a controlled section. */
139
+ onOpenChange?: (open: boolean) => void;
140
+ }
141
+ /**
142
+ * A section of the menu that opens and closes: its heading is a button drawn like `Menu.Label`, and its `Menu.List` of links shows while it's open.
143
+ *
144
+ * It's APG's disclosure navigation, for a sidebar of link groups: the links
145
+ * stay ordinary links, each its own tab stop, and a closed section's list is
146
+ * `hidden` and `inert`, so Tab and assistive tech skip it. It goes directly in
147
+ * `Menu`, holding a `Menu.List`. Closing it while focus is on one of its links
148
+ * moves focus to its heading.
149
+ *
150
+ * @function
151
+ * @param {MenuSectionProps} props - Props for the MenuSection component.
152
+ * @returns {JSX.Element} The rendered menu section.
153
+ * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/ | APG Disclosure Navigation Menu example}
154
+ *
155
+ * @example
156
+ * <Menu>
157
+ * <Menu.Section label="Components" defaultOpen>
158
+ * <Menu.List>
159
+ * <Menu.Item href="/button" active>Button</Menu.Item>
160
+ * <Menu.Item href="/card">Card</Menu.Item>
161
+ * </Menu.List>
162
+ * </Menu.Section>
163
+ * </Menu>
164
+ */
165
+ export declare const MenuSection: React.FC<MenuSectionProps>;
118
166
  export declare const Menu: React.FC<MenuProps> & {
119
167
  Label: React.FC<MenuLabelProps>;
120
168
  List: React.FC<MenuListProps>;
121
169
  Item: PolymorphicComponent<MenuItemOwnProps, "a", never>;
170
+ Section: React.FC<MenuSectionProps>;
122
171
  };
123
172
  export default Menu;
@@ -17,7 +17,12 @@ export interface ImageProps extends React.HTMLAttributes<HTMLElement>, Omit<Bulm
17
17
  color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';
18
18
  /** Background color helper for the container. */
19
19
  bgColor?: (typeof validColors)[number] | 'inherit' | 'current';
20
- /** Fixed size or aspect ratio modifier for the image container. */
20
+ /**
21
+ * Fixed size or aspect ratio modifier for the image container. A ratio
22
+ * (`16by9` and the rest) renders only its `is-<ratio>` class there. Bulma
23
+ * stretches an `<img>` inside to fill the ratio, but any other child, such
24
+ * as an `iframe`, fills it only with `className="has-ratio"` of its own.
25
+ */
21
26
  size?: '16x16' | '24x24' | '32x32' | '48x48' | '64x64' | '96x96' | '128x128' | 'square' | '1by1' | '5by4' | '4by3' | '3by2' | '5by3' | '16by9' | '2by1' | '3by1' | '4by5' | '3by4' | '2by3' | '3by5' | '9by16' | '1by2' | '1by3';
22
27
  /** Renders the image with rounded corners. */
23
28
  isRounded?: boolean;
@@ -5,16 +5,24 @@ import type { RefObject } from 'react';
5
5
  * can read `-1` for an editable region or an `<embed>` that Tab still visits,
6
6
  * and `0` for a `<video>` without controls that it doesn't. So a valid
7
7
  * `tabindex` attribute decides, and otherwise the element's kind does.
8
- * Internal like `firstTabStop`: `src/index.ts` names what it takes from here.
8
+ * Internal like `focusTabStop`: `src/index.ts` names what it takes from here.
9
9
  */
10
10
  export declare function isTabbableKind(el: Element): boolean;
11
11
  /**
12
- * The first tab stop inside `container`, found the way the trap finds it, or
13
- * `null` when there is none. For a component that moves focus into a panel
14
- * itself rather than through the hook. `src/index.ts` names its exports from
12
+ * Moves focus to the first tab stop inside `container`, or the last when
13
+ * `fromLast`, and to the container when there is none. Every move a trap
14
+ * makes goes through here: into the container as it opens, to the other end
15
+ * on a wrap, and back in after a Tab the browser carried out.
16
+ *
17
+ * A stop that doesn't take focus is passed over for the next one in. An
18
+ * `<object>` or `<embed>` with nothing to show is one: it counts as a stop by
19
+ * its kind, but browsers refuse to focus it, and which ones they refuse
20
+ * depends on the browser and on what has loaded, so only trying tells. A
21
+ * stop took focus when focus moved, wherever it went (a stop can hand focus
22
+ * on), or when focus was on it already. `src/index.ts` names its exports from
15
23
  * this module, so this one stays internal.
16
24
  */
17
- export declare function firstTabStop(container: HTMLElement): HTMLElement | null;
25
+ export declare function focusTabStop(container: HTMLElement, fromLast?: boolean): void;
18
26
  /**
19
27
  * Holds Tab inside the element `container` returns until the returned
20
28
  * function is called. Tab and Shift+Tab heard on `keyTarget` wrap at the
@@ -25,7 +33,7 @@ export declare function firstTabStop(container: HTMLElement): HTMLElement | null
25
33
  * overlay whose nodes are remounted while it's open, as moving to another
26
34
  * portal target does, stays trapped without attaching again. `holds` is asked
27
35
  * on every Tab, and the trap leaves the key alone while it says no. Internal
28
- * like `firstTabStop`. It's for an overlay that holds Tab from a listener of
36
+ * like `focusTabStop`. It's for an overlay that holds Tab from a listener of
29
37
  * its own on `window` and asks the overlay stack first, so it stands aside
30
38
  * while another overlay is open over it, which a trap listening on the
31
39
  * container can't do.
@@ -46,8 +54,8 @@ export interface UseFocusTrapOptions {
46
54
  * to be one that can take focus, so a heading needs `tabIndex={-1}`. When
47
55
  * focusing it doesn't put focus inside the container (the ref is empty, or
48
56
  * its element is outside, disabled, hidden or can't take focus), focus goes
49
- * to the first tab stop inside the container, and to the container itself
50
- * when there is none.
57
+ * to the first tab stop inside the container that takes focus, and to the
58
+ * container itself when none does.
51
59
  */
52
60
  initialFocusRef?: RefObject<HTMLElement | null>;
53
61
  /**