@allxsmith/bestax-bulma 5.60.0 → 5.62.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 (98) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Carousel.js +3 -43
  4. package/dist/esm/components/Carousel.js.map +1 -1
  5. package/dist/esm/components/Command.js +3 -3
  6. package/dist/esm/components/Navbar.js +3 -1
  7. package/dist/esm/components/Navbar.js.map +1 -1
  8. package/dist/esm/components/Popover.js +7 -27
  9. package/dist/esm/components/Popover.js.map +1 -1
  10. package/dist/esm/components/Sidebar.js +17 -58
  11. package/dist/esm/components/Sidebar.js.map +1 -1
  12. package/dist/esm/components/TreeView.js +14 -10
  13. package/dist/esm/components/TreeView.js.map +1 -1
  14. package/dist/esm/form/ColorPicker.js +4 -4
  15. package/dist/esm/form/ColorPicker.js.map +1 -1
  16. package/dist/esm/form/Combobox.js +11 -16
  17. package/dist/esm/form/Combobox.js.map +1 -1
  18. package/dist/esm/form/Field.js.map +1 -1
  19. package/dist/esm/form/TreeSelect.js +395 -0
  20. package/dist/esm/form/TreeSelect.js.map +1 -0
  21. package/dist/esm/form/_pickerInternals/PickerPopover.js +5 -1
  22. package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
  23. package/dist/esm/form/_selectInternals/DialogSelect.js +208 -0
  24. package/dist/esm/form/_selectInternals/DialogSelect.js.map +1 -0
  25. package/dist/esm/form/_selectInternals/ValueTags.js +28 -0
  26. package/dist/esm/form/_selectInternals/ValueTags.js.map +1 -0
  27. package/dist/esm/helpers/overlayStack.js +33 -1
  28. package/dist/esm/helpers/overlayStack.js.map +1 -1
  29. package/dist/esm/helpers/treeData.js +97 -0
  30. package/dist/esm/helpers/treeData.js.map +1 -0
  31. package/dist/esm/helpers/useBulmaViewport.js +82 -0
  32. package/dist/esm/helpers/useBulmaViewport.js.map +1 -0
  33. package/dist/esm/helpers/useComboboxEngine.js +2 -2
  34. package/dist/esm/helpers/useComboboxEngine.js.map +1 -1
  35. package/dist/esm/helpers/useControlled.js +30 -0
  36. package/dist/esm/helpers/useControlled.js.map +1 -0
  37. package/dist/esm/helpers/useInertSiblings.js +7 -3
  38. package/dist/esm/helpers/useInertSiblings.js.map +1 -1
  39. package/dist/esm/helpers/useOutsidePress.js +53 -0
  40. package/dist/esm/helpers/useOutsidePress.js.map +1 -0
  41. package/dist/esm/helpers/useOverlayFocus.js +74 -0
  42. package/dist/esm/helpers/useOverlayFocus.js.map +1 -0
  43. package/dist/esm/helpers/useTreeView.js +15 -13
  44. package/dist/esm/helpers/useTreeView.js.map +1 -1
  45. package/dist/esm/layout/AppFrame.js +438 -0
  46. package/dist/esm/layout/AppFrame.js.map +1 -0
  47. package/dist/extras.css +1 -1
  48. package/dist/extras.css.map +1 -1
  49. package/dist/index.cjs +1767 -518
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.esm.js +2 -0
  52. package/dist/index.esm.js.map +1 -1
  53. package/dist/types/components/Navbar.d.ts +4 -3
  54. package/dist/types/form/Field.d.ts +1 -1
  55. package/dist/types/form/TreeSelect.d.ts +308 -0
  56. package/dist/types/form/_pickerInternals/PickerPopover.d.ts +8 -0
  57. package/dist/types/form/_selectInternals/DialogSelect.d.ts +86 -0
  58. package/dist/types/form/_selectInternals/ValueTags.d.ts +40 -0
  59. package/dist/types/helpers/overlayStack.d.ts +17 -0
  60. package/dist/types/helpers/treeData.d.ts +48 -0
  61. package/dist/types/helpers/useBulmaViewport.d.ts +34 -0
  62. package/dist/types/helpers/useControlled.d.ts +14 -0
  63. package/dist/types/helpers/useInertSiblings.d.ts +4 -1
  64. package/dist/types/helpers/useOutsidePress.d.ts +24 -0
  65. package/dist/types/helpers/useOverlayFocus.d.ts +44 -0
  66. package/dist/types/helpers/useTreeView.d.ts +30 -0
  67. package/dist/types/index.d.ts +2 -0
  68. package/dist/types/layout/AppFrame.d.ts +306 -0
  69. package/dist/types-cjs/components/Navbar.d.ts +4 -3
  70. package/dist/types-cjs/form/Field.d.ts +1 -1
  71. package/dist/types-cjs/form/TreeSelect.d.ts +308 -0
  72. package/dist/types-cjs/form/_pickerInternals/PickerPopover.d.ts +8 -0
  73. package/dist/types-cjs/form/_selectInternals/DialogSelect.d.ts +86 -0
  74. package/dist/types-cjs/form/_selectInternals/ValueTags.d.ts +40 -0
  75. package/dist/types-cjs/helpers/overlayStack.d.ts +17 -0
  76. package/dist/types-cjs/helpers/treeData.d.ts +48 -0
  77. package/dist/types-cjs/helpers/useBulmaViewport.d.ts +34 -0
  78. package/dist/types-cjs/helpers/useControlled.d.ts +14 -0
  79. package/dist/types-cjs/helpers/useInertSiblings.d.ts +4 -1
  80. package/dist/types-cjs/helpers/useOutsidePress.d.ts +24 -0
  81. package/dist/types-cjs/helpers/useOverlayFocus.d.ts +44 -0
  82. package/dist/types-cjs/helpers/useTreeView.d.ts +30 -0
  83. package/dist/types-cjs/index.d.ts +2 -0
  84. package/dist/types-cjs/layout/AppFrame.d.ts +306 -0
  85. package/dist/versions/bestax-no-dark-mode.css +1 -1
  86. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  87. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  88. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  89. package/dist/versions/bestax-no-helpers.css +1 -1
  90. package/dist/versions/bestax-no-helpers.css.map +1 -1
  91. package/dist/versions/bestax-prefixed.css +1 -1
  92. package/dist/versions/bestax-prefixed.css.map +1 -1
  93. package/package.json +1 -1
  94. package/src/scss/form/_index.scss +1 -0
  95. package/src/scss/form/_picker-popover.scss +6 -0
  96. package/src/scss/form/_treeselect.scss +146 -0
  97. package/src/scss/layout/_appframe.scss +306 -0
  98. package/src/scss/layout/_index.scss +1 -0
@@ -0,0 +1,24 @@
1
+ import type React from 'react';
2
+ import type { RefObject } from 'react';
3
+ /**
4
+ * Calls `onOutsidePress` for a `pointerdown` outside `ref`'s element while
5
+ * `active`, as a Popover closes on one.
6
+ *
7
+ * A press counts as inside in two ways: on the element's own path in the DOM,
8
+ * and anywhere in a React tree the returned handler is put on, as
9
+ * `onPointerDownCapture`. React's tree includes content portaled out of it,
10
+ * which the DOM path doesn't, and React has seen a press there by the time
11
+ * the document hears it.
12
+ *
13
+ * The listener is on the element's own document, an iframe's when the tree
14
+ * renders into one, and reads the latest `onOutsidePress` as a press
15
+ * arrives, so it stays put while the callback changes identity.
16
+ *
17
+ * @function useOutsidePress
18
+ * @param ref - Ref to the element a press inside of doesn't count.
19
+ * @param active - Whether to listen.
20
+ * @param onOutsidePress - Called with each press outside.
21
+ * @returns The `onPointerDownCapture` handler that marks a press in its tree
22
+ * as inside.
23
+ */
24
+ export declare function useOutsidePress(ref: RefObject<Element | null>, active: boolean, onOutsidePress: (event: PointerEvent) => void): (event: React.PointerEvent) => void;
@@ -0,0 +1,44 @@
1
+ import type { RefObject } from 'react';
2
+ /** Options for `useOverlayFocus`. */
3
+ export interface OverlayFocusOptions {
4
+ /**
5
+ * Whether the overlay is modal. One that isn't, opened while a modal
6
+ * overlay is open under it, leaves focus where it is: that overlay keeps
7
+ * Tab, so a Tab from this one's controls would only go back to it. It's
8
+ * read as the overlay opens, so a change while it's open moves nothing.
9
+ */
10
+ modal: boolean;
11
+ /**
12
+ * A value that remounts the overlay's nodes while it's open when it
13
+ * changes, such as a new portal target. Focus is handed back from the old
14
+ * nodes and moved into the new ones.
15
+ */
16
+ remountKey?: unknown;
17
+ /**
18
+ * Asked as the overlay closes, while it still holds focus: `false` leaves
19
+ * focus where it is, for a close that shouldn't send it back, such as one
20
+ * whose overlay stays on the page as something else.
21
+ */
22
+ restore?: () => boolean;
23
+ }
24
+ /**
25
+ * Moves focus into an overlay as it opens, to the first stop Tab wraps to
26
+ * inside `ref`'s element or the element itself, and hands it back to
27
+ * whatever had it as it closes, as `Modal` does. Focus goes back only while
28
+ * the overlay still holds it, or it's been dropped to `<body>`: closing one
29
+ * under another overlay mustn't pull focus out of the one on top, and focus
30
+ * moved out to the page stays there. The opener is found wherever it sits,
31
+ * inside a shadow root too, in the overlay's own document, an iframe's when
32
+ * it renders into one. It's read in a layout effect as the overlay opens, so
33
+ * before the commit's passive effects, such as one that makes the page
34
+ * inert. Content inside the overlay with a layout effect of its own, or an
35
+ * `autoFocus`, can still move focus first, and then there's no opener to go
36
+ * back to: focus is never handed back into the overlay that's closing.
37
+ *
38
+ * @function useOverlayFocus
39
+ * @param ref - Ref to the overlay's element.
40
+ * @param open - Whether the overlay is open.
41
+ * @param options - Whether it's modal, what remounts it, and whether a
42
+ * close hands focus back.
43
+ */
44
+ export declare function useOverlayFocus(ref: RefObject<HTMLElement | null>, open: boolean, { modal, remountKey, restore }: OverlayFocusOptions): void;
@@ -37,6 +37,36 @@ export interface TreeViewItemState {
37
37
  selected?: boolean;
38
38
  checked?: TreeViewCheckState;
39
39
  }
40
+ /**
41
+ * The values of the items a tree hides while they stay in it, as TreeSelect's
42
+ * search hides the items that don't match. A hidden item renders as one under
43
+ * a closed parent does: nothing on the page, and in a `checkbox` tree it and
44
+ * its children still register, so a check still reaches them. Internal, for
45
+ * the components that put a TreeView inside them.
46
+ */
47
+ export declare const TreeViewHiddenContext: React.Context<ReadonlySet<string>>;
48
+ /**
49
+ * Every known item's check state, by the rules in #1096:
50
+ *
51
+ * - a disabled item is checked only when its own value is listed;
52
+ * - an enabled item with no enabled items anywhere under it is checked when
53
+ * it, or any item above it, is listed;
54
+ * - any other enabled item follows the items of that second kind in its
55
+ * branch: checked when they all are, unchecked when none is, mixed between.
56
+ *
57
+ * Also returns the items of the second kind, which are what a toggle sets.
58
+ */
59
+ export declare function readChecks(records: Map<string, TreeViewItemRecord>, listed: Set<string>): {
60
+ states: Map<string, TreeViewCheckState>;
61
+ ends: string[];
62
+ };
63
+ /**
64
+ * The list a toggle of `value` leaves: it and every enabled item under it
65
+ * take the opposite of its state (a mixed one checks), and the rest is read
66
+ * back by the rules. That's every item that shows checked, parents
67
+ * included, plus any listed value no item has.
68
+ */
69
+ export declare function toggledList(records: Map<string, TreeViewItemRecord>, list: string[], value: string): string[];
40
70
  /** Options for `useTreeView`: the TreeView's own props. */
41
71
  export interface TreeViewOptions {
42
72
  mode: TreeViewSelectionMode;
@@ -96,6 +96,7 @@ export * from './form/PinInput.js';
96
96
  export * from './form/Rate.js';
97
97
  export * from './form/Autocomplete.js';
98
98
  export * from './form/Combobox.js';
99
+ export * from './form/TreeSelect.js';
99
100
  export * from './form/Taginput.js';
100
101
  export * from './form/ColorPicker.js';
101
102
  export { InputBase } from './form/InputBase.js';
@@ -151,6 +152,7 @@ export { useNumberFormat } from './helpers/localeFormat.js';
151
152
  export type { NumberFormatFunction } from './helpers/localeFormat.js';
152
153
  export { useFocusTrap } from './helpers/useFocusTrap.js';
153
154
  export type { UseFocusTrapOptions } from './helpers/useFocusTrap.js';
155
+ export * from './layout/AppFrame.js';
154
156
  export * from './layout/Center.js';
155
157
  export * from './layout/Container.js';
156
158
  export * from './layout/Flex.js';
@@ -0,0 +1,306 @@
1
+ import React from 'react';
2
+ import { BulmaClassesProps, validColors } from '../helpers/useBulmaClasses.js';
3
+ import type { NavbarBurgerProps } from '../components/Navbar.js';
4
+ import type { ContainerBreakpoint } from './Container.js';
5
+ /**
6
+ * The strings AppFrame renders, each with an English default. A key left
7
+ * out, or set to an empty string, keeps its default.
8
+ */
9
+ export interface AppFrameLabels {
10
+ /**
11
+ * The skip link's text.
12
+ * @defaultValue 'Skip to main content'
13
+ */
14
+ skipLink?: string;
15
+ /**
16
+ * The nav's accessible name, when `AppFrame.Nav` has no `aria-label` or
17
+ * `aria-labelledby`. Leave the word "navigation" out: the role says it.
18
+ * @defaultValue 'Sections'
19
+ */
20
+ nav?: string;
21
+ /**
22
+ * The name of the close button at the top of the drawer.
23
+ * @defaultValue 'Close navigation'
24
+ */
25
+ closeNav?: string;
26
+ /**
27
+ * The burger's name, when `AppFrame.Burger` has no `aria-label`.
28
+ * @defaultValue 'menu', Navbar.Burger's
29
+ */
30
+ burger?: string;
31
+ }
32
+ /**
33
+ * Props for the AppFrame component. The helper props, the other attributes
34
+ * and the `ref` land on the root `<div>`.
35
+ *
36
+ * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the root `<div>`.
37
+ */
38
+ export interface AppFrameProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
39
+ /**
40
+ * The parts, each a direct child: `Header`, `Nav`, `Main`, `Aside` and
41
+ * `Footer`, in that order, since it's the Tab order. The frame reads the
42
+ * `id` of `Main` and `Nav` off its children for the skip link and the
43
+ * burger, so a part wrapped in a component of your own takes no `id` of
44
+ * its own. Put the frame at the top of the page, outside any `main` or
45
+ * sectioning element.
46
+ */
47
+ children?: React.ReactNode;
48
+ /**
49
+ * The width from which the nav is a column beside the page. Below it, the
50
+ * nav is a drawer the burger opens. The stylesheet switches the layout at
51
+ * Bulma's breakpoint, and the script reads the width at Bulma's default
52
+ * breakpoints, so a theme that moves Bulma's breakpoints moves the layout
53
+ * but not which state the burger toggles.
54
+ * @defaultValue 'desktop'
55
+ */
56
+ breakpoint?: ContainerBreakpoint;
57
+ /**
58
+ * Whether the drawer is open, below the breakpoint. With it, the state is
59
+ * yours: update it from `onNavOpenChange`. It has no effect from the
60
+ * breakpoint up, where the frame asks to close it.
61
+ */
62
+ navOpen?: boolean;
63
+ /** Whether the drawer starts open. */
64
+ defaultNavOpen?: boolean;
65
+ /**
66
+ * Called with the state asked for: by the burger, `useAppFrame()`, Escape,
67
+ * a press outside, the close button, a followed link (see
68
+ * `AppFrame.Nav`'s `closeOnNavigate`), or the window being at or past the
69
+ * breakpoint while it's open, which closes it.
70
+ */
71
+ onNavOpenChange?: (open: boolean) => void;
72
+ /**
73
+ * Whether the column is collapsed out of view, from the breakpoint up.
74
+ * With it, the state is yours: update it from `onNavCollapsedChange`. It
75
+ * has no effect below the breakpoint, where the drawer always shows the
76
+ * whole nav.
77
+ */
78
+ navCollapsed?: boolean;
79
+ /** Whether the column starts collapsed. */
80
+ defaultNavCollapsed?: boolean;
81
+ /** Called with the state asked for, by the burger or `useAppFrame()`. */
82
+ onNavCollapsedChange?: (collapsed: boolean) => void;
83
+ /**
84
+ * Renders a skip link first, visible when it has focus, that moves focus
85
+ * to `AppFrame.Main`. Turn it off only for a page that has its own.
86
+ */
87
+ skipLink?: boolean;
88
+ /** The strings the frame renders. Each one left out keeps its English default. */
89
+ labels?: AppFrameLabels;
90
+ /** Text color helper. */
91
+ textColor?: (typeof validColors)[number] | 'inherit' | 'current';
92
+ /** Background color helper. */
93
+ bgColor?: (typeof validColors)[number] | 'inherit' | 'current';
94
+ }
95
+ /**
96
+ * Props for AppFrame.Header, on its `<header>`, which sticks to the top.
97
+ *
98
+ * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the `<header>`.
99
+ */
100
+ export interface AppFrameHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'color'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
101
+ /**
102
+ * Usually a `Navbar`, not `fixed`, with `AppFrame.Burger` in its
103
+ * `Navbar.Brand`. A header taller than Bulma's navbar sets
104
+ * `--bulma-app-frame-header-height` on `:root`, so the nav column, an
105
+ * in-page link and focus clear it.
106
+ */
107
+ children?: React.ReactNode;
108
+ }
109
+ /**
110
+ * Props for AppFrame.Nav, on its `<nav>`.
111
+ *
112
+ * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the `<nav>`.
113
+ * @extraProp {string} [id] - The nav's id, which the burger's `aria-controls` points at. The frame makes one when there's none.
114
+ * @extraProp {string} [aria-label] - The nav's name. Without it or `aria-labelledby`, it's the frame's `labels.nav`, "Sections".
115
+ */
116
+ export interface AppFrameNavProps extends Omit<React.HTMLAttributes<HTMLElement>, 'color'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
117
+ /**
118
+ * Usually a `Menu`. A nav taller than the window scrolls on its own. With
119
+ * `overlay`, the rest of the frame is inert while the drawer is open, so an
120
+ * overlay opened from the drawer, such as a `Modal`, goes inside the nav or
121
+ * renders outside the frame (Modal's `portal`).
122
+ */
123
+ children?: React.ReactNode;
124
+ /**
125
+ * The column's width, and the drawer's up to the window's width less a
126
+ * strip of backdrop. A number is pixels, and a string any CSS length. It
127
+ * writes `--bulma-app-frame-nav-width`, 16rem by default.
128
+ */
129
+ width?: number | string;
130
+ /**
131
+ * Shows a backdrop behind the drawer and makes it modal: Tab stays inside,
132
+ * the page scroll locks, and the rest of the frame is inert, while what
133
+ * renders outside it, such as a Modal opened from the drawer or a toast,
134
+ * stays live. Without it the drawer covers the page without holding Tab,
135
+ * and focus can move to the page beside it. Either way focus moves in as
136
+ * it opens. Sidebar's `overlay`.
137
+ */
138
+ overlay?: boolean;
139
+ /**
140
+ * Closes the drawer on Escape, while it's the topmost overlay, so Escape
141
+ * closes one layer at a time.
142
+ */
143
+ closeOnEscape?: boolean;
144
+ /**
145
+ * Closes the drawer on a press outside it while it's the topmost overlay:
146
+ * a click on the backdrop, or without `overlay` a press anywhere outside
147
+ * it. Focus goes back to the burger as it closes. Without `overlay`, the
148
+ * press's own mousedown then moves it, as on any page: to what was pressed
149
+ * if that takes focus, and otherwise off the burger to the page. A touch
150
+ * that scrolls leaves it on the burger. A press on a control whose
151
+ * `aria-controls` names the nav, such as the burger, is left to that
152
+ * control. Popover's `closeOnClickOutside`.
153
+ */
154
+ closeOnClickOutside?: boolean;
155
+ /**
156
+ * Closes the drawer when a link inside it is followed with a plain click:
157
+ * not with a modifier key held, and not on a link with a `target` other
158
+ * than `_self` or a `download`. Only a link the nav holds in the page
159
+ * counts, not one in a Modal or a popup it portals elsewhere. Focus goes
160
+ * back to the burger, and the navigation takes it from there: a router
161
+ * that moves focus on navigation moves it, and an in-page `#` link leaves
162
+ * it at its target, as it does anywhere on the page. Turn it off for a
163
+ * drawer of filters rather than links.
164
+ */
165
+ closeOnNavigate?: boolean;
166
+ }
167
+ /**
168
+ * Props for AppFrame.Main, on the page's one `<main>`. Don't put another
169
+ * `<main>` inside it. It takes your `id`, or a generated one, for the skip
170
+ * link, and `tabIndex={-1}` so the link can move focus to it.
171
+ *
172
+ * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the `<main>`.
173
+ * @extraProp {string} [id] - Its id, which the skip link points at. The frame makes one when there's none.
174
+ */
175
+ export interface AppFrameMainProps extends Omit<React.HTMLAttributes<HTMLElement>, 'color'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
176
+ /** The page. A `Container` or a `Section` inside it gives Bulma's widths and padding. */
177
+ children?: React.ReactNode;
178
+ }
179
+ /**
180
+ * Props for AppFrame.Aside, on its `<aside>`, a complementary landmark.
181
+ * Give it an `aria-label` when the page has more than one.
182
+ *
183
+ * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the `<aside>`.
184
+ */
185
+ export interface AppFrameAsideProps extends Omit<React.HTMLAttributes<HTMLElement>, 'color'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
186
+ /** What sits beside the page: an outline, details, filters. */
187
+ children?: React.ReactNode;
188
+ /**
189
+ * Its width from the breakpoint up; below it, the aside moves under the
190
+ * page. A number is pixels, and a string any CSS length. It writes
191
+ * `--bulma-app-frame-aside-width`, 20rem by default.
192
+ */
193
+ width?: number | string;
194
+ }
195
+ /**
196
+ * Props for AppFrame.Footer, on its `<footer>`.
197
+ *
198
+ * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the `<footer>`.
199
+ */
200
+ export interface AppFrameFooterProps extends Omit<React.HTMLAttributes<HTMLElement>, 'color'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
201
+ /** Plain content, or bestax's `Footer` with `as="div"` for Bulma's footer look. */
202
+ children?: React.ReactNode;
203
+ }
204
+ /**
205
+ * Props for AppFrame.Burger: Navbar.Burger's, less the state the frame
206
+ * fills in. Its `<button>` opens and closes the drawer below the breakpoint
207
+ * and collapses and expands the column from it up, with `aria-expanded` and
208
+ * `aria-controls` following the nav. It shows at every width. Hide it from
209
+ * the breakpoint up with the visibility helpers when the column never
210
+ * collapses. Outside an AppFrame it controls nothing.
211
+ */
212
+ export type AppFrameBurgerProps = Omit<NavbarBurgerProps, 'active' | 'aria-expanded' | 'aria-controls'>;
213
+ /** What `useAppFrame()` returns. */
214
+ export interface AppFrameState {
215
+ /** Whether the drawer is open. */
216
+ navOpen: boolean;
217
+ /** Asks to open or close the drawer, through `onNavOpenChange`. */
218
+ setNavOpen: (open: boolean) => void;
219
+ /** Whether the column is collapsed. */
220
+ navCollapsed: boolean;
221
+ /** Asks to collapse or expand the column, through `onNavCollapsedChange`. */
222
+ setNavCollapsed: (collapsed: boolean) => void;
223
+ /**
224
+ * Whether the nav is a drawer at the current width. `false` on the server
225
+ * and until the first layout effect has read the width.
226
+ */
227
+ isDrawer: boolean;
228
+ /** Toggles whichever state applies at the current width, as the burger does. */
229
+ toggleNav: () => void;
230
+ /** The nav's `id`, for a custom toggle's `aria-controls`. */
231
+ navId: string;
232
+ }
233
+ /**
234
+ * The top bar of an AppFrame, which sticks while the page scrolls.
235
+ *
236
+ * @function
237
+ * @param {AppFrameHeaderProps} props - Props for AppFrame.Header.
238
+ * @param {React.Ref<HTMLElement>} ref - Forwarded ref to the `<header>`.
239
+ * @returns {JSX.Element} The rendered header.
240
+ */
241
+ export declare const AppFrameHeader: React.ForwardRefExoticComponent<AppFrameHeaderProps & React.RefAttributes<HTMLElement>>;
242
+ /**
243
+ * The navigation of an AppFrame: a column beside the page from the breakpoint up, and a drawer below it.
244
+ *
245
+ * @function
246
+ * @param {AppFrameNavProps} props - Props for AppFrame.Nav.
247
+ * @param {React.Ref<HTMLElement>} ref - Forwarded ref to the `<nav>`.
248
+ * @returns {JSX.Element} The rendered nav, and the drawer's backdrop.
249
+ */
250
+ export declare const AppFrameNav: React.ForwardRefExoticComponent<AppFrameNavProps & React.RefAttributes<HTMLElement>>;
251
+ /**
252
+ * The page's main content in an AppFrame, which the skip link moves focus to.
253
+ *
254
+ * @function
255
+ * @param {AppFrameMainProps} props - Props for AppFrame.Main.
256
+ * @param {React.Ref<HTMLElement>} ref - Forwarded ref to the `<main>`.
257
+ * @returns {JSX.Element} The rendered main.
258
+ */
259
+ export declare const AppFrameMain: React.ForwardRefExoticComponent<AppFrameMainProps & React.RefAttributes<HTMLElement>>;
260
+ /**
261
+ * Content beside the page in an AppFrame, which moves under it below the breakpoint.
262
+ *
263
+ * @function
264
+ * @param {AppFrameAsideProps} props - Props for AppFrame.Aside.
265
+ * @param {React.Ref<HTMLElement>} ref - Forwarded ref to the `<aside>`.
266
+ * @returns {JSX.Element} The rendered aside.
267
+ */
268
+ export declare const AppFrameAside: React.ForwardRefExoticComponent<AppFrameAsideProps & React.RefAttributes<HTMLElement>>;
269
+ /**
270
+ * The bottom of an AppFrame, under the page.
271
+ *
272
+ * @function
273
+ * @param {AppFrameFooterProps} props - Props for AppFrame.Footer.
274
+ * @param {React.Ref<HTMLElement>} ref - Forwarded ref to the `<footer>`.
275
+ * @returns {JSX.Element} The rendered footer.
276
+ */
277
+ export declare const AppFrameFooter: React.ForwardRefExoticComponent<AppFrameFooterProps & React.RefAttributes<HTMLElement>>;
278
+ /**
279
+ * The button that opens the drawer, or collapses the column from the breakpoint up: Navbar.Burger, wired to the frame.
280
+ *
281
+ * @function
282
+ * @param {AppFrameBurgerProps} props - Props for AppFrame.Burger.
283
+ * @param {React.Ref<HTMLButtonElement>} ref - Forwarded ref to the `<button>`.
284
+ * @returns {JSX.Element} The rendered burger.
285
+ */
286
+ export declare const AppFrameBurger: React.ForwardRefExoticComponent<AppFrameBurgerProps & React.RefAttributes<HTMLButtonElement>>;
287
+ /**
288
+ * The frame's state, for a control of your own inside it: whether the
289
+ * drawer is open and the column collapsed, setters that go through the
290
+ * frame's callbacks, and `toggleNav()`, which does what the burger does.
291
+ * Outside an AppFrame it's `null`, as the library's other context hooks
292
+ * are, so a control that can sit outside one renders a fallback or nothing.
293
+ *
294
+ * @function useAppFrame
295
+ * @returns The frame's state, or `null` outside an AppFrame.
296
+ */
297
+ export declare function useAppFrame(): AppFrameState | null;
298
+ export declare const AppFrame: React.ForwardRefExoticComponent<AppFrameProps & React.RefAttributes<HTMLDivElement>> & {
299
+ Header: React.ForwardRefExoticComponent<AppFrameHeaderProps & React.RefAttributes<HTMLElement>>;
300
+ Nav: React.ForwardRefExoticComponent<AppFrameNavProps & React.RefAttributes<HTMLElement>>;
301
+ Main: React.ForwardRefExoticComponent<AppFrameMainProps & React.RefAttributes<HTMLElement>>;
302
+ Aside: React.ForwardRefExoticComponent<AppFrameAsideProps & React.RefAttributes<HTMLElement>>;
303
+ Footer: React.ForwardRefExoticComponent<AppFrameFooterProps & React.RefAttributes<HTMLElement>>;
304
+ Burger: React.ForwardRefExoticComponent<AppFrameBurgerProps & React.RefAttributes<HTMLButtonElement>>;
305
+ };
306
+ export default AppFrame;
@@ -126,7 +126,7 @@ export declare const NavbarItem: PolymorphicComponent<NavbarItemOwnProps, "a">;
126
126
  * @extraProp {React.Ref<HTMLButtonElement>} [ref] - Ref forwarded to the burger button element.
127
127
  * @extraProp {'button' | 'submit' | 'reset'} [type='button'] - Button type. Defaults to `'button'`, so a burger inside a form does not submit it. Pass `'submit'` or `'reset'` and yours is used; any other value, or a spread carrying `type: undefined`, renders `'button'`.
128
128
  */
129
- export interface NavbarBurgerProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
129
+ export interface NavbarBurgerProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'aria-expanded'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
130
130
  /** Additional CSS classes. */
131
131
  className?: string;
132
132
  /** Text color for the burger. */
@@ -155,11 +155,12 @@ export interface NavbarBurgerProps extends React.ButtonHTMLAttributes<HTMLButton
155
155
  'aria-label'?: string;
156
156
  /**
157
157
  * Expanded state for assistive technology. It follows `active` unless you
158
- * pass `true` or `false`; a spread carrying `'aria-expanded': undefined`
158
+ * pass `true` or `false`, and `null` leaves it off, for a burger whose
159
+ * state isn't known yet; a spread carrying `'aria-expanded': undefined`
159
160
  * still follows `active`.
160
161
  * @defaultValue active
161
162
  */
162
- 'aria-expanded'?: boolean;
163
+ 'aria-expanded'?: boolean | null;
163
164
  /** Click handler. */
164
165
  onClick?: React.MouseEventHandler<HTMLButtonElement>;
165
166
  }
@@ -12,7 +12,7 @@ export interface FieldProps extends React.HTMLAttributes<HTMLDivElement>, Omit<B
12
12
  hasAddons?: boolean | 'centered' | 'right';
13
13
  /** Constrains the field to its content's width (used inside horizontal field bodies). */
14
14
  narrow?: boolean;
15
- /** Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase`, `TextAreaBase`, `DateInputBase`, `TimeInputBase` or `DateTimeInputBase` (an `inline` picker has no input, so it takes nothing), or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `PinInput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Combobox`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`, or a composed `DateRangeInputBase`, `inline` or not) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. A range `Slider` takes the id on its low thumb and also starts each thumb's name with the label through `aria-labelledby`, unless its `ariaLabel` names that thumb or its own `aria-label` or `aria-labelledby` takes the label's place. An `Autocomplete`, a `Combobox` or a `Taginput` also names its open list after the label through `aria-labelledby`. `Checkbox`, `Radio` and `Switch` are named by their own children, and the label names one only when you wire it as you would any control with an `id` of its own, `labelProps={{ htmlFor }}` plus that control's `id`. Only the single inputs take the `htmlFor`, so once the Field's content has mounted the label keeps it only while one of them holds the id, and drops it over anything else: a group, a `Checkbox`, `Radio` or `Switch`, an `inline` picker, an inner `Field`, an input with an `id` of its own, markup of your own, or nothing at all. A server render, and the first render while hydrating, still write the `htmlFor`, which keeps hydration matching, and an input that mounts later puts it back. The label names an input with an `id` of your own only through `labelProps={{ htmlFor }}` set to that `id`, a `for` it always keeps; `labelProps={{ htmlFor: undefined }}` opts out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own. */
15
+ /** Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase`, `TextAreaBase`, `DateInputBase`, `TimeInputBase` or `DateTimeInputBase` (an `inline` picker has no input, so it takes nothing), or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `PinInput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Combobox`, `TreeSelect`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`, or a composed `DateRangeInputBase`, `inline` or not) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. A range `Slider` takes the id on its low thumb and also starts each thumb's name with the label through `aria-labelledby`, unless its `ariaLabel` names that thumb or its own `aria-label` or `aria-labelledby` takes the label's place. An `Autocomplete`, a `Combobox` or a `Taginput` also names its open list after the label through `aria-labelledby`, and a `TreeSelect` its panel and the tree in it. `Checkbox`, `Radio` and `Switch` are named by their own children, and the label names one only when you wire it as you would any control with an `id` of its own, `labelProps={{ htmlFor }}` plus that control's `id`. Only the single inputs take the `htmlFor`, so once the Field's content has mounted the label keeps it only while one of them holds the id, and drops it over anything else: a group, a `Checkbox`, `Radio` or `Switch`, an `inline` picker, an inner `Field`, an input with an `id` of its own, markup of your own, or nothing at all. A server render, and the first render while hydrating, still write the `htmlFor`, which keeps hydration matching, and an input that mounts later puts it back. The label names an input with an `id` of your own only through `labelProps={{ htmlFor }}` set to that `id`, a `for` it always keeps; `labelProps={{ htmlFor: undefined }}` opts out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own. */
16
16
  label?: React.ReactNode;
17
17
  /** Size for the label. */
18
18
  labelSize?: 'small' | 'normal' | 'medium' | 'large';