@allxsmith/bestax-bulma 5.18.2 → 5.19.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/constants.cjs +67 -6
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +30 -6
- package/dist/constants.esm.js +65 -7
- package/dist/constants.esm.js.map +1 -1
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +598 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +596 -53
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/Card.d.ts +2 -0
- package/dist/types/components/Carousel.d.ts +8 -2
- package/dist/types/components/Modal.d.ts +2 -0
- package/dist/types/components/Navbar.d.ts +24 -3
- package/dist/types/components/Sidebar.d.ts +2 -0
- package/dist/types/components/Steps.d.ts +5 -1
- package/dist/types/elements/Delete.d.ts +9 -1
- package/dist/types/elements/Link.d.ts +7 -1
- package/dist/types/elements/Notification.d.ts +29 -3
- package/dist/types/elements/Tag.d.ts +7 -1
- package/dist/types/elements/Td.d.ts +21 -2
- package/dist/types/form/DateInputBase.d.ts +9 -1
- package/dist/types/form/DateTimeInputBase.d.ts +11 -4
- package/dist/types/form/TimeInputBase.d.ts +4 -2
- package/dist/types/helpers/Theme.d.ts +6 -1
- package/dist/types/helpers/bulmaClassHelpers.d.ts +30 -6
- package/dist/types/helpers/shadowDom.d.ts +54 -0
- package/dist/types/helpers/statusRegion.d.ts +61 -0
- package/dist/types/helpers/useBulmaClasses.d.ts +1 -1
- package/dist/types/helpers/useOtherClasses.d.ts +61 -5
- package/dist/types-cjs/components/Card.d.ts +2 -0
- package/dist/types-cjs/components/Carousel.d.ts +8 -2
- package/dist/types-cjs/components/Modal.d.ts +2 -0
- package/dist/types-cjs/components/Navbar.d.ts +24 -3
- package/dist/types-cjs/components/Sidebar.d.ts +2 -0
- package/dist/types-cjs/components/Steps.d.ts +5 -1
- package/dist/types-cjs/elements/Delete.d.ts +9 -1
- package/dist/types-cjs/elements/Link.d.ts +7 -1
- package/dist/types-cjs/elements/Notification.d.ts +29 -3
- package/dist/types-cjs/elements/Tag.d.ts +7 -1
- package/dist/types-cjs/elements/Td.d.ts +21 -2
- package/dist/types-cjs/form/DateInputBase.d.ts +9 -1
- package/dist/types-cjs/form/DateTimeInputBase.d.ts +11 -4
- package/dist/types-cjs/form/TimeInputBase.d.ts +4 -2
- package/dist/types-cjs/helpers/Theme.d.ts +6 -1
- package/dist/types-cjs/helpers/bulmaClassHelpers.d.ts +30 -6
- package/dist/types-cjs/helpers/shadowDom.d.ts +54 -0
- package/dist/types-cjs/helpers/statusRegion.d.ts +61 -0
- package/dist/types-cjs/helpers/useBulmaClasses.d.ts +1 -1
- package/dist/types-cjs/helpers/useOtherClasses.d.ts +61 -5
- 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/form/_dateinput.scss +36 -10
- package/src/scss/form/_timeinput.scss +30 -9
package/dist/index.esm.js
CHANGED
|
@@ -427,10 +427,59 @@ const validViewports = [
|
|
|
427
427
|
*/
|
|
428
428
|
const validFloats = ['left', 'right'];
|
|
429
429
|
/**
|
|
430
|
-
* Valid Bulma overflow
|
|
431
|
-
*
|
|
430
|
+
* Valid Bulma overflow values for one axis, taken by `overflowX` and
|
|
431
|
+
* `overflowY`. Each renders `is-overflow-x-<value>` or `is-overflow-y-<value>`.
|
|
432
|
+
* @example 'auto', 'hidden', 'scroll'
|
|
432
433
|
*/
|
|
433
|
-
const
|
|
434
|
+
const validAxisOverflows = [
|
|
435
|
+
'auto',
|
|
436
|
+
'clip',
|
|
437
|
+
'hidden',
|
|
438
|
+
'scroll',
|
|
439
|
+
'visible',
|
|
440
|
+
];
|
|
441
|
+
/**
|
|
442
|
+
* Valid Bulma overflow values for `overflow`.
|
|
443
|
+
*
|
|
444
|
+
* `clipped` renders `is-clipped`, the helper `overflow` started with. Every
|
|
445
|
+
* other value renders `is-overflow-<value>`.
|
|
446
|
+
* @example 'clipped', 'auto', 'hidden'
|
|
447
|
+
*/
|
|
448
|
+
const validOverflows = ['clipped', ...validAxisOverflows];
|
|
449
|
+
/**
|
|
450
|
+
* Valid Bulma position values, taken by `pos`. Each renders
|
|
451
|
+
* `is-position-<value>`.
|
|
452
|
+
* @example 'relative', 'absolute', 'sticky'
|
|
453
|
+
*/
|
|
454
|
+
const validPositions = [
|
|
455
|
+
'absolute',
|
|
456
|
+
'fixed',
|
|
457
|
+
'relative',
|
|
458
|
+
'static',
|
|
459
|
+
'sticky',
|
|
460
|
+
];
|
|
461
|
+
/**
|
|
462
|
+
* Valid Bulma aspect ratios, taken by `aspectRatio`. Each renders
|
|
463
|
+
* `is-aspect-ratio-<value>`.
|
|
464
|
+
* @example '1by1', '4by3', '16by9'
|
|
465
|
+
*/
|
|
466
|
+
const validAspectRatios = [
|
|
467
|
+
'1by1',
|
|
468
|
+
'5by4',
|
|
469
|
+
'4by3',
|
|
470
|
+
'3by2',
|
|
471
|
+
'5by3',
|
|
472
|
+
'16by9',
|
|
473
|
+
'2by1',
|
|
474
|
+
'3by1',
|
|
475
|
+
'4by5',
|
|
476
|
+
'3by4',
|
|
477
|
+
'2by3',
|
|
478
|
+
'3by5',
|
|
479
|
+
'9by16',
|
|
480
|
+
'1by2',
|
|
481
|
+
'1by3',
|
|
482
|
+
];
|
|
434
483
|
/**
|
|
435
484
|
* Valid Bulma interaction classes.
|
|
436
485
|
* @example 'unselectable', 'clickable'
|
|
@@ -458,10 +507,19 @@ const cursorClasses = {
|
|
|
458
507
|
help: 'is-cursor-help',
|
|
459
508
|
};
|
|
460
509
|
/**
|
|
461
|
-
* Valid Bulma border-radius helper
|
|
462
|
-
*
|
|
510
|
+
* Valid Bulma border-radius helper values.
|
|
511
|
+
*
|
|
512
|
+
* `radiusless` renders `is-radiusless` and removes the radius. The sizes
|
|
513
|
+
* render `has-radius-<value>` and set one from Bulma's radius scale.
|
|
514
|
+
* @example 'radiusless', 'small', 'rounded'
|
|
463
515
|
*/
|
|
464
|
-
const validRadii = [
|
|
516
|
+
const validRadii = [
|
|
517
|
+
'radiusless',
|
|
518
|
+
'small',
|
|
519
|
+
'normal',
|
|
520
|
+
'large',
|
|
521
|
+
'rounded',
|
|
522
|
+
];
|
|
465
523
|
/**
|
|
466
524
|
* Valid Bulma shadow helper classes.
|
|
467
525
|
* @example 'shadowless'
|
|
@@ -922,7 +980,7 @@ const useFlexboxClasses = (props) => {
|
|
|
922
980
|
/**
|
|
923
981
|
* A hook that generates miscellaneous Bulma helper classes (float, overflow,
|
|
924
982
|
* overlay, interaction, cursor, radius, shadow, responsive, skeleton,
|
|
925
|
-
* clearfix,
|
|
983
|
+
* clearfix, position, full height, and aspect ratio).
|
|
926
984
|
*
|
|
927
985
|
* @function useOtherClasses
|
|
928
986
|
* @param props - Miscellaneous Bulma helper props.
|
|
@@ -933,15 +991,32 @@ const useFlexboxClasses = (props) => {
|
|
|
933
991
|
*/
|
|
934
992
|
const useOtherClasses = (props) => {
|
|
935
993
|
const { classPrefix } = useConfig();
|
|
936
|
-
const { float, overflow, overlay, interaction, cursor, radius, shadow, responsive, skeleton, clearfix, relative, fullHeight, } = props;
|
|
994
|
+
const { float, overflow, overflowX, overflowY, overlay, interaction, cursor, radius, shadow, responsive, skeleton, clearfix, pos, relative, fullHeight, aspectRatio, } = props;
|
|
937
995
|
return useMemo(() => {
|
|
938
996
|
const { classes, addPrefixedClass, addClassNoViewport } = createBulmaClassHelpers(classPrefix);
|
|
939
997
|
// Other Helpers (no viewport support)
|
|
940
998
|
if (float) {
|
|
941
999
|
addClassNoViewport('is-pulled', float, validFloats);
|
|
942
1000
|
}
|
|
943
|
-
|
|
944
|
-
|
|
1001
|
+
// Bulma's overflow helpers are all `!important` at the same specificity
|
|
1002
|
+
// and ordered by value rather than by axis, so a both-axes class beside an
|
|
1003
|
+
// axis class would be settled by which value comes later in the
|
|
1004
|
+
// stylesheet. Once an axis prop is set, both axes are written per axis
|
|
1005
|
+
// instead: the axis prop wins its own, and `overflow` fills in the other,
|
|
1006
|
+
// `clipped` being `overflow: hidden`.
|
|
1007
|
+
const axisX = validAxisOverflows.find(v => v === overflowX);
|
|
1008
|
+
const axisY = validAxisOverflows.find(v => v === overflowY);
|
|
1009
|
+
if (axisX || axisY) {
|
|
1010
|
+
const rest = overflow === 'clipped' ? 'hidden' : overflow;
|
|
1011
|
+
addClassNoViewport('is-overflow-x', axisX ?? rest, validAxisOverflows);
|
|
1012
|
+
addClassNoViewport('is-overflow-y', axisY ?? rest, validAxisOverflows);
|
|
1013
|
+
}
|
|
1014
|
+
else if (overflow === 'clipped') {
|
|
1015
|
+
// The older helper, which keeps its own class.
|
|
1016
|
+
addPrefixedClass('is-clipped');
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
addClassNoViewport('is-overflow', overflow, validAxisOverflows);
|
|
945
1020
|
}
|
|
946
1021
|
if (overlay) {
|
|
947
1022
|
addPrefixedClass('is-overlay');
|
|
@@ -952,8 +1027,13 @@ const useOtherClasses = (props) => {
|
|
|
952
1027
|
if (cursor && validCursors.includes(cursor)) {
|
|
953
1028
|
addPrefixedClass(cursorClasses[cursor]);
|
|
954
1029
|
}
|
|
955
|
-
|
|
956
|
-
|
|
1030
|
+
// `radiusless` is an `is-` helper that removes the radius; the sizes are
|
|
1031
|
+
// Bulma's `has-radius-` helpers.
|
|
1032
|
+
if (radius === 'radiusless') {
|
|
1033
|
+
addPrefixedClass('is-radiusless');
|
|
1034
|
+
}
|
|
1035
|
+
else {
|
|
1036
|
+
addClassNoViewport('has-radius', radius, validRadii);
|
|
957
1037
|
}
|
|
958
1038
|
if (shadow) {
|
|
959
1039
|
addClassNoViewport('is', shadow, validShadows);
|
|
@@ -969,19 +1049,26 @@ const useOtherClasses = (props) => {
|
|
|
969
1049
|
if (clearfix) {
|
|
970
1050
|
addPrefixedClass('is-clearfix');
|
|
971
1051
|
}
|
|
972
|
-
// Position
|
|
973
|
-
|
|
1052
|
+
// Position Helpers. A valid `pos` decides the position on its own, so a
|
|
1053
|
+
// `relative` beside it cannot add a second, conflicting one.
|
|
1054
|
+
if (pos && validPositions.includes(pos)) {
|
|
1055
|
+
addPrefixedClass(`is-position-${pos}`);
|
|
1056
|
+
}
|
|
1057
|
+
else if (relative) {
|
|
974
1058
|
addPrefixedClass('is-relative');
|
|
975
1059
|
}
|
|
976
1060
|
// Full Height Helper
|
|
977
1061
|
if (fullHeight) {
|
|
978
1062
|
addPrefixedClass('is-full-height');
|
|
979
1063
|
}
|
|
1064
|
+
addClassNoViewport('is-aspect-ratio', aspectRatio, validAspectRatios);
|
|
980
1065
|
return classNames(classes);
|
|
981
1066
|
}, [
|
|
982
1067
|
classPrefix,
|
|
983
1068
|
float,
|
|
984
1069
|
overflow,
|
|
1070
|
+
overflowX,
|
|
1071
|
+
overflowY,
|
|
985
1072
|
overlay,
|
|
986
1073
|
interaction,
|
|
987
1074
|
cursor,
|
|
@@ -990,8 +1077,10 @@ const useOtherClasses = (props) => {
|
|
|
990
1077
|
responsive,
|
|
991
1078
|
skeleton,
|
|
992
1079
|
clearfix,
|
|
1080
|
+
pos,
|
|
993
1081
|
relative,
|
|
994
1082
|
fullHeight,
|
|
1083
|
+
aspectRatio,
|
|
995
1084
|
]);
|
|
996
1085
|
};
|
|
997
1086
|
|
|
@@ -1022,7 +1111,7 @@ const useOtherClasses = (props) => {
|
|
|
1022
1111
|
* // rest: { className: 'custom-class' }
|
|
1023
1112
|
*/
|
|
1024
1113
|
const useBulmaClasses = (props) => {
|
|
1025
|
-
const { color, backgroundColor, colorShade, backgroundColorShade, m, mt, mr, mb, ml, mx, my, p, pt, pr, pb, pl, px, py, textSize, textAlign, textTransform, textWeight, fontFamily, display, visibility, flexDirection, flexWrap, justifyContent, alignContent, alignItems, alignSelf, flexGrow, flexShrink, float, overflow, overlay, interaction, cursor, radius, shadow, responsive, viewport, displayMobile, displayTablet, displayTabletOnly, displayTouch, displayDesktop, displayDesktopOnly, displayWidescreen, displayWidescreenOnly, displayFullhd, textSizeMobile, textSizeTablet, textSizeDesktop, textSizeWidescreen, textSizeFullhd, textAlignMobile, textAlignTablet, textAlignDesktop, textAlignWidescreen, textAlignFullhd, visibilityMobile, visibilityTablet, visibilityTabletOnly, visibilityTouch, visibilityDesktop, visibilityDesktopOnly, visibilityWidescreen, visibilityWidescreenOnly, visibilityFullhd, skeleton, clearfix, relative, fullHeight, ...rest } = props;
|
|
1114
|
+
const { color, backgroundColor, colorShade, backgroundColorShade, m, mt, mr, mb, ml, mx, my, p, pt, pr, pb, pl, px, py, textSize, textAlign, textTransform, textWeight, fontFamily, display, visibility, flexDirection, flexWrap, justifyContent, alignContent, alignItems, alignSelf, flexGrow, flexShrink, float, overflow, overflowX, overflowY, overlay, interaction, cursor, radius, shadow, responsive, viewport, displayMobile, displayTablet, displayTabletOnly, displayTouch, displayDesktop, displayDesktopOnly, displayWidescreen, displayWidescreenOnly, displayFullhd, textSizeMobile, textSizeTablet, textSizeDesktop, textSizeWidescreen, textSizeFullhd, textAlignMobile, textAlignTablet, textAlignDesktop, textAlignWidescreen, textAlignFullhd, visibilityMobile, visibilityTablet, visibilityTabletOnly, visibilityTouch, visibilityDesktop, visibilityDesktopOnly, visibilityWidescreen, visibilityWidescreenOnly, visibilityFullhd, skeleton, clearfix, pos, relative, fullHeight, aspectRatio, ...rest } = props;
|
|
1026
1115
|
const colorClasses = useColorClasses({
|
|
1027
1116
|
color,
|
|
1028
1117
|
colorShade,
|
|
@@ -1110,6 +1199,8 @@ const useBulmaClasses = (props) => {
|
|
|
1110
1199
|
const otherClasses = useOtherClasses({
|
|
1111
1200
|
float,
|
|
1112
1201
|
overflow,
|
|
1202
|
+
overflowX,
|
|
1203
|
+
overflowY,
|
|
1113
1204
|
overlay,
|
|
1114
1205
|
interaction,
|
|
1115
1206
|
cursor,
|
|
@@ -1118,8 +1209,10 @@ const useBulmaClasses = (props) => {
|
|
|
1118
1209
|
responsive,
|
|
1119
1210
|
skeleton,
|
|
1120
1211
|
clearfix,
|
|
1212
|
+
pos,
|
|
1121
1213
|
relative,
|
|
1122
1214
|
fullHeight,
|
|
1215
|
+
aspectRatio,
|
|
1123
1216
|
});
|
|
1124
1217
|
const bulmaHelperClasses = useMemo(() => classNames(colorClasses, spacingClasses, typographyClasses, visibilityClasses, flexboxClasses, otherClasses), [
|
|
1125
1218
|
colorClasses,
|
|
@@ -2007,7 +2100,7 @@ const CardHeaderIcon = ({ className, children, color, bgColor, textColor, ...pro
|
|
|
2007
2100
|
backgroundColor: bgColor,
|
|
2008
2101
|
...props,
|
|
2009
2102
|
});
|
|
2010
|
-
return (jsx("button", { className: classNames(usePrefixedClassNames('card-header-icon'), bulmaHelperClasses, className), "aria-label":
|
|
2103
|
+
return (jsx("button", { className: classNames(usePrefixedClassNames('card-header-icon'), bulmaHelperClasses, className), ...rest, "aria-label": rest['aria-label'] || 'more options', type: buttonType(rest.type), children: children }));
|
|
2011
2104
|
};
|
|
2012
2105
|
/**
|
|
2013
2106
|
* Card image compound component. Wraps children in a `.card-image` element.
|
|
@@ -2105,6 +2198,72 @@ const Card = withSubComponents(CardComponent, {
|
|
|
2105
2198
|
FooterItem: CardFooterItem,
|
|
2106
2199
|
}, 'Card');
|
|
2107
2200
|
|
|
2201
|
+
/**
|
|
2202
|
+
* Event and focus checks that still hold when a component renders inside a
|
|
2203
|
+
* shadow root.
|
|
2204
|
+
*
|
|
2205
|
+
* Code outside a shadow root cannot see into it. A listener on `document`
|
|
2206
|
+
* reads an event from inside one with its `target` set to the shadow host,
|
|
2207
|
+
* and `document.activeElement` names the host instead of the element that has
|
|
2208
|
+
* focus. A component asking either question from `document` then takes a
|
|
2209
|
+
* click on its own menu for an outside click, or cannot tell which of its
|
|
2210
|
+
* items is focused. A web component or a sandboxed preview puts a component
|
|
2211
|
+
* in exactly that position.
|
|
2212
|
+
*
|
|
2213
|
+
* Focus comes in two questions, and each has its own function here. "Is focus
|
|
2214
|
+
* inside me, and on which of my elements?" is `getActiveElementInTree`. "Which
|
|
2215
|
+
* element has focus, wherever it is?", the one to record before moving focus
|
|
2216
|
+
* away and restore to later, is `getDeepestActiveElement`.
|
|
2217
|
+
*/
|
|
2218
|
+
/**
|
|
2219
|
+
* Whether `event` happened inside `node`. The event's composed path still
|
|
2220
|
+
* holds the element that was really clicked, where a `document` listener
|
|
2221
|
+
* reads the shadow host as the event's `target`.
|
|
2222
|
+
*
|
|
2223
|
+
* @param event - An event read by a listener outside `node`, usually on `document`.
|
|
2224
|
+
* @param node - The component's element, or nothing while it is unmounted.
|
|
2225
|
+
* @returns True when `node` is on the event's path.
|
|
2226
|
+
*/
|
|
2227
|
+
function isEventInside(event, node) {
|
|
2228
|
+
return !!node && event.composedPath().includes(node);
|
|
2229
|
+
}
|
|
2230
|
+
/**
|
|
2231
|
+
* The focused element as `node`'s own tree sees it: its shadow root's
|
|
2232
|
+
* `activeElement` when `node` is inside one, `document.activeElement` when it
|
|
2233
|
+
* is not. The result is comparable with `node` and its descendants, which
|
|
2234
|
+
* live in that same tree, so use it to ask whether focus is inside `node`.
|
|
2235
|
+
* Focus inside a shadow root nested within `node` reads as that root's host,
|
|
2236
|
+
* which `node` contains.
|
|
2237
|
+
*
|
|
2238
|
+
* A shadow root with nothing focused inside reports `null`, and a detached
|
|
2239
|
+
* node has no document above it. Both fall back to `document.activeElement`,
|
|
2240
|
+
* so focus elsewhere on the page still reads as outside `node`.
|
|
2241
|
+
*
|
|
2242
|
+
* @param node - An element of the component, or nothing while it is unmounted.
|
|
2243
|
+
* @returns The focused element in `node`'s tree, or the document's.
|
|
2244
|
+
*/
|
|
2245
|
+
function getActiveElementInTree(node) {
|
|
2246
|
+
const root = node?.getRootNode();
|
|
2247
|
+
return root?.activeElement ?? document.activeElement;
|
|
2248
|
+
}
|
|
2249
|
+
/**
|
|
2250
|
+
* The element that really has focus, followed down from
|
|
2251
|
+
* `document.activeElement` through every open shadow root on the way. Use it
|
|
2252
|
+
* to record where focus was before moving it, so it can be restored to that
|
|
2253
|
+
* element later: the tree a component renders into need not be the tree its
|
|
2254
|
+
* opener sits in. A closed shadow root cannot be entered, so focus inside one
|
|
2255
|
+
* reads as its host.
|
|
2256
|
+
*
|
|
2257
|
+
* @returns The focused element, or `null` when the document has none.
|
|
2258
|
+
*/
|
|
2259
|
+
function getDeepestActiveElement() {
|
|
2260
|
+
let active = document.activeElement;
|
|
2261
|
+
while (active?.shadowRoot?.activeElement) {
|
|
2262
|
+
active = active.shadowRoot.activeElement;
|
|
2263
|
+
}
|
|
2264
|
+
return active;
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2108
2267
|
/**
|
|
2109
2268
|
* Checks if code is running in a browser environment.
|
|
2110
2269
|
* @deprecated Dropdown's internal SSR guard, exported by accident; it will
|
|
@@ -2185,8 +2344,7 @@ const DropdownComponent = forwardRef(function DropdownComponent({ label, childre
|
|
|
2185
2344
|
if (!isBrowser$1(window, document))
|
|
2186
2345
|
return;
|
|
2187
2346
|
const handleClick = (e) => {
|
|
2188
|
-
|
|
2189
|
-
if (!dropdownRef.current?.contains(e.target)) {
|
|
2347
|
+
if (!isEventInside(e, dropdownRef.current)) {
|
|
2190
2348
|
setActive(false);
|
|
2191
2349
|
onActiveChange?.(false);
|
|
2192
2350
|
}
|
|
@@ -2202,10 +2360,16 @@ const DropdownComponent = forwardRef(function DropdownComponent({ label, childre
|
|
|
2202
2360
|
setActive(newActive);
|
|
2203
2361
|
onActiveChange?.(newActive);
|
|
2204
2362
|
};
|
|
2205
|
-
const handleMenuClick = () => {
|
|
2363
|
+
const handleMenuClick = (e) => {
|
|
2206
2364
|
if (closeOnClick) {
|
|
2207
2365
|
setActive(false);
|
|
2208
2366
|
onActiveChange?.(false);
|
|
2367
|
+
// Closing hides the item that has focus, and the browser drops focus
|
|
2368
|
+
// to the page when that happens. Hand it back to the trigger, as
|
|
2369
|
+
// Escape does. An item that moved focus somewhere else keeps it there.
|
|
2370
|
+
if (e.currentTarget.contains(getActiveElementInTree(e.currentTarget))) {
|
|
2371
|
+
triggerRef.current?.focus();
|
|
2372
|
+
}
|
|
2209
2373
|
}
|
|
2210
2374
|
};
|
|
2211
2375
|
const getMenuItems = () => {
|
|
@@ -2266,6 +2430,11 @@ const DropdownComponent = forwardRef(function DropdownComponent({ label, childre
|
|
|
2266
2430
|
case 'Enter':
|
|
2267
2431
|
case ' ':
|
|
2268
2432
|
e.preventDefault();
|
|
2433
|
+
// A held key sends a keydown per auto-repeat. Running an item hands
|
|
2434
|
+
// focus back here, so without this a held Enter would reopen the
|
|
2435
|
+
// menu and run whichever item it focused next.
|
|
2436
|
+
if (e.repeat)
|
|
2437
|
+
break;
|
|
2269
2438
|
if (!active) {
|
|
2270
2439
|
pendingFocusRef.current = 'first';
|
|
2271
2440
|
setActive(true);
|
|
@@ -2303,7 +2472,7 @@ const DropdownComponent = forwardRef(function DropdownComponent({ label, childre
|
|
|
2303
2472
|
const items = getMenuItems();
|
|
2304
2473
|
if (!items.length)
|
|
2305
2474
|
return;
|
|
2306
|
-
const currentIndex = items.indexOf(
|
|
2475
|
+
const currentIndex = items.indexOf(getActiveElementInTree(e.currentTarget));
|
|
2307
2476
|
switch (e.key) {
|
|
2308
2477
|
case 'ArrowDown': {
|
|
2309
2478
|
e.preventDefault();
|
|
@@ -2791,7 +2960,7 @@ const ModalCard = withSubComponents(ModalCardComponent, {
|
|
|
2791
2960
|
*/
|
|
2792
2961
|
const ModalClose = ({ className, size = 'large', variant = 'delete', ...props }) => {
|
|
2793
2962
|
const classes = classNames(usePrefixedClassNames(variant === 'delete' ? 'delete' : 'modal-close', variant === 'floating' && size && { [`is-${size}`]: true }), className);
|
|
2794
|
-
return (jsx("button", { className: classes, "aria-label":
|
|
2963
|
+
return (jsx("button", { className: classes, ...props, "aria-label": props['aria-label'] || 'close', type: buttonType(props.type) }));
|
|
2795
2964
|
};
|
|
2796
2965
|
/**
|
|
2797
2966
|
* The `Modal` component provides an empty, accessible overlay for arbitrary content — for a ready-made confirm or alert, reach for `Dialog` instead.
|
|
@@ -2908,7 +3077,7 @@ const ModalRoot = forwardRef(function ModalRoot({ active, isActive, onClose, cla
|
|
|
2908
3077
|
// Keep Tab within the modal — `aria-modal` hides the rest of the page
|
|
2909
3078
|
// from assistive technology, so the keyboard order has to agree.
|
|
2910
3079
|
const focusable = getTabbable(node);
|
|
2911
|
-
const activeElement =
|
|
3080
|
+
const activeElement = getActiveElementInTree(node);
|
|
2912
3081
|
if (focusable.length === 0) {
|
|
2913
3082
|
e.preventDefault();
|
|
2914
3083
|
node.focus();
|
|
@@ -2935,7 +3104,10 @@ const ModalRoot = forwardRef(function ModalRoot({ active, isActive, onClose, cla
|
|
|
2935
3104
|
useEffect(() => {
|
|
2936
3105
|
if (!isModalActive)
|
|
2937
3106
|
return undefined;
|
|
2938
|
-
|
|
3107
|
+
// The element that had focus, wherever it sits: a portaled modal renders
|
|
3108
|
+
// under `document.body` while its opener can be inside a shadow root.
|
|
3109
|
+
previouslyFocusedRef.current =
|
|
3110
|
+
getDeepestActiveElement();
|
|
2939
3111
|
const node = modalRootRef.current;
|
|
2940
3112
|
const focusable = node ? getTabbable(node)[0] : undefined;
|
|
2941
3113
|
(focusable ?? node)?.focus();
|
|
@@ -2943,7 +3115,7 @@ const ModalRoot = forwardRef(function ModalRoot({ active, isActive, onClose, cla
|
|
|
2943
3115
|
// Only hand focus back if this modal still owns it: closing a background
|
|
2944
3116
|
// modal must not pull focus out of one that is still open on top. A
|
|
2945
3117
|
// removed subtree leaves focus on <body>, which still counts as ours.
|
|
2946
|
-
const activeElement =
|
|
3118
|
+
const activeElement = getActiveElementInTree(node);
|
|
2947
3119
|
if (activeElement &&
|
|
2948
3120
|
activeElement !== document.body &&
|
|
2949
3121
|
!node?.contains(activeElement)) {
|
|
@@ -3061,7 +3233,7 @@ const NavbarItem = forwardRef(function NavbarItem(itemProps, ref) {
|
|
|
3061
3233
|
});
|
|
3062
3234
|
return (jsx(Component, { ref: ref, className: classNames(usePrefixedClassNames('navbar-item', {
|
|
3063
3235
|
'is-active': active,
|
|
3064
|
-
}), bulmaHelperClasses, className), ...rest, children: children }));
|
|
3236
|
+
}), bulmaHelperClasses, className), ...rest, ...(Component === 'button' ? { type: buttonType(rest.type) } : {}), children: children }));
|
|
3065
3237
|
});
|
|
3066
3238
|
NavbarItem.displayName = 'NavbarItem';
|
|
3067
3239
|
/**
|
|
@@ -3077,9 +3249,9 @@ const NavbarBurger = forwardRef(function NavbarBurger({ className, active, textC
|
|
|
3077
3249
|
color: textColor ?? color,
|
|
3078
3250
|
...props,
|
|
3079
3251
|
});
|
|
3080
|
-
return (jsxs("button", { ref: ref,
|
|
3252
|
+
return (jsxs("button", { ref: ref, className: classNames(usePrefixedClassNames('navbar-burger', {
|
|
3081
3253
|
'is-active': active,
|
|
3082
|
-
}), bulmaHelperClasses, className), "aria-label":
|
|
3254
|
+
}), bulmaHelperClasses, className), ...rest, "aria-label": rest['aria-label'] || 'menu', "aria-expanded": rest['aria-expanded'] ?? !!active, type: buttonType(rest.type), children: [jsx("span", { "aria-hidden": "true" }), jsx("span", { "aria-hidden": "true" }), jsx("span", { "aria-hidden": "true" }), jsx("span", { "aria-hidden": "true" }), children] }));
|
|
3083
3255
|
});
|
|
3084
3256
|
NavbarBurger.displayName = 'NavbarBurger';
|
|
3085
3257
|
/**
|
|
@@ -3209,7 +3381,7 @@ const NavbarLink = forwardRef(function NavbarLink(linkProps, ref) {
|
|
|
3209
3381
|
tabIndex: 0,
|
|
3210
3382
|
onClick: handleClick,
|
|
3211
3383
|
}),
|
|
3212
|
-
}), children: children }));
|
|
3384
|
+
}), ...(Component === 'button' ? { type: buttonType(rest.type) } : {}), children: children }));
|
|
3213
3385
|
});
|
|
3214
3386
|
NavbarLink.displayName = 'NavbarLink';
|
|
3215
3387
|
/**
|
|
@@ -4533,7 +4705,7 @@ const StepsComponent = ({ value = 0, items, size, color, hasMarker = true, anima
|
|
|
4533
4705
|
}
|
|
4534
4706
|
return null;
|
|
4535
4707
|
};
|
|
4536
|
-
return (jsxs("div", { className: combinedClasses, ...rest, children: [jsx("ul", { className: listClasses, children: renderSteps() }), hasNavigation && (jsxs("div", { className: stepsNavigationClass, children: [jsx("button", { className: prevButtonClass, disabled: value === 0, onClick: onPrev ?? (() => onStepClick?.(value - 1)), children: prevLabel ?? 'Previous' }), jsx("button", { className: nextButtonClass, disabled: value === totalSteps - 1, onClick: onNext ?? (() => onStepClick?.(value + 1)), children: nextLabel ?? 'Next' })] }))] }));
|
|
4708
|
+
return (jsxs("div", { className: combinedClasses, ...rest, children: [jsx("ul", { className: listClasses, children: renderSteps() }), hasNavigation && (jsxs("div", { className: stepsNavigationClass, children: [jsx("button", { type: "button", className: prevButtonClass, disabled: value === 0, onClick: onPrev ?? (() => onStepClick?.(value - 1)), children: prevLabel ?? 'Previous' }), jsx("button", { type: "button", className: nextButtonClass, disabled: value === totalSteps - 1, onClick: onNext ?? (() => onStepClick?.(value + 1)), children: nextLabel ?? 'Next' })] }))] }));
|
|
4537
4709
|
};
|
|
4538
4710
|
// Attach Step as static property
|
|
4539
4711
|
const Steps = withSubComponents(StepsComponent, { Step }, 'Steps');
|
|
@@ -4702,7 +4874,7 @@ const SidebarTitle = ({ className, children, ...props }) => {
|
|
|
4702
4874
|
*/
|
|
4703
4875
|
const SidebarClose = ({ className, children, ...props }) => {
|
|
4704
4876
|
const closeClass = usePrefixedClassNames('sidebar-close');
|
|
4705
|
-
return (jsx("button", {
|
|
4877
|
+
return (jsx("button", { className: classNames(closeClass, className), ...props, "aria-label": props['aria-label'] || 'Close', type: buttonType(props.type), children: children }));
|
|
4706
4878
|
};
|
|
4707
4879
|
/**
|
|
4708
4880
|
* Main content area of the sidebar.
|
|
@@ -4832,7 +5004,7 @@ const Toast = forwardRef(({ message, type = 'default', actionType, position = 't
|
|
|
4832
5004
|
if (!dismissible || !isVisible)
|
|
4833
5005
|
return undefined;
|
|
4834
5006
|
const handleDocumentClick = (e) => {
|
|
4835
|
-
if (toastRef.current && !toastRef.current
|
|
5007
|
+
if (toastRef.current && !isEventInside(e, toastRef.current)) {
|
|
4836
5008
|
handleClose();
|
|
4837
5009
|
}
|
|
4838
5010
|
};
|
|
@@ -5635,7 +5807,8 @@ const Carousel = forwardRef(({ value: controlledValue, autoplay = false, interva
|
|
|
5635
5807
|
// Keyboard navigation
|
|
5636
5808
|
useEffect(() => {
|
|
5637
5809
|
const handleKeyDown = (e) => {
|
|
5638
|
-
|
|
5810
|
+
const node = carouselRef.current;
|
|
5811
|
+
if (!node?.contains(getActiveElementInTree(node)))
|
|
5639
5812
|
return;
|
|
5640
5813
|
switch (e.key) {
|
|
5641
5814
|
case 'ArrowLeft':
|
|
@@ -5768,7 +5941,7 @@ const Carousel = forwardRef(({ value: controlledValue, autoplay = false, interva
|
|
|
5768
5941
|
transition: isDragging || skipTransition
|
|
5769
5942
|
? 'none'
|
|
5770
5943
|
: 'transform 0.3s ease-in-out',
|
|
5771
|
-
}, onTransitionEnd: handleTransitionEnd, children: renderSlides() }), arrow && itemCount > 1 && (jsxs(Fragment, { children: [jsx(Button, { className: carouselArrowPrevClass, onClick: goToPrev, isDisabled: !canGoPrev, "aria-label": "Previous slide", children: iconPrev ? (jsx(Icon, { name: iconPrev, library: iconLibrary, variant: iconVariant, size: iconSize, features: iconFeatures })) : (jsx(DefaultPrevIcon, {})) }), jsx(Button, { className: carouselArrowNextClass, onClick: goToNext, isDisabled: !canGoNext, "aria-label": "Next slide", children: iconNext ? (jsx(Icon, { name: iconNext, library: iconLibrary, variant: iconVariant, size: iconSize, features: iconFeatures })) : (jsx(DefaultNextIcon, {})) })] }))] }), indicator && itemCount > 1 && (jsx("div", { className: carouselIndicatorClass, role: "tablist", children: items.map((_, index) => (jsx(Button, { className: prefixedClassNames(classPrefix, 'indicator-item', {
|
|
5944
|
+
}, onTransitionEnd: handleTransitionEnd, children: renderSlides() }), arrow && itemCount > 1 && (jsxs(Fragment, { children: [jsx(Button, { type: "button", className: carouselArrowPrevClass, onClick: goToPrev, isDisabled: !canGoPrev, "aria-label": "Previous slide", children: iconPrev ? (jsx(Icon, { name: iconPrev, library: iconLibrary, variant: iconVariant, size: iconSize, features: iconFeatures })) : (jsx(DefaultPrevIcon, {})) }), jsx(Button, { type: "button", className: carouselArrowNextClass, onClick: goToNext, isDisabled: !canGoNext, "aria-label": "Next slide", children: iconNext ? (jsx(Icon, { name: iconNext, library: iconLibrary, variant: iconVariant, size: iconSize, features: iconFeatures })) : (jsx(DefaultNextIcon, {})) })] }))] }), indicator && itemCount > 1 && (jsx("div", { className: carouselIndicatorClass, role: "tablist", children: items.map((_, index) => (jsx(Button, { type: "button", className: prefixedClassNames(classPrefix, 'indicator-item', {
|
|
5772
5945
|
'is-active': index === activeIndex,
|
|
5773
5946
|
}), onClick: () => goToSlide(index), role: "tab", "aria-selected": index === activeIndex, "aria-label": `Go to slide ${index + 1}` }, index))) }))] }));
|
|
5774
5947
|
});
|
|
@@ -6076,12 +6249,14 @@ const Content = ({ className, textColor, color, bgColor, size, children, ...prop
|
|
|
6076
6249
|
/**
|
|
6077
6250
|
* The `Delete` component provides a Bulma-styled close/delete button for dismissing modals, notifications, tags, messages, and more.
|
|
6078
6251
|
*
|
|
6252
|
+
* It renders `type="button"`, so a delete button inside a form does not submit it.
|
|
6253
|
+
*
|
|
6079
6254
|
* @function
|
|
6080
6255
|
* @param {DeleteProps} props - Props for the Delete component.
|
|
6081
6256
|
* @returns {JSX.Element} The rendered delete button.
|
|
6082
6257
|
* @see {@link https://bulma.io/documentation/elements/delete/ | Bulma Delete documentation}
|
|
6083
6258
|
*/
|
|
6084
|
-
const Delete = ({ className, textColor, color, bgColor, onClick, size, ariaLabel
|
|
6259
|
+
const Delete = ({ className, textColor, color, bgColor, onClick, size, ariaLabel, disabled = false, ...props }) => {
|
|
6085
6260
|
/**
|
|
6086
6261
|
* Generates Bulma helper classes and separates out remaining props.
|
|
6087
6262
|
*/
|
|
@@ -6095,7 +6270,7 @@ const Delete = ({ className, textColor, color, bgColor, onClick, size, ariaLabel
|
|
|
6095
6270
|
'is-disabled': disabled,
|
|
6096
6271
|
});
|
|
6097
6272
|
const classes = classNames(bulmaClasses, bulmaHelperClasses, className);
|
|
6098
|
-
return (jsx("button", { className: classes, onClick: onClick, "aria-label": ariaLabel
|
|
6273
|
+
return (jsx("button", { className: classes, onClick: onClick, disabled: disabled, ...rest, "aria-label": rest['aria-label'] || ariaLabel || 'Close', type: buttonType(rest.type) }));
|
|
6099
6274
|
};
|
|
6100
6275
|
|
|
6101
6276
|
/**
|
|
@@ -6317,7 +6492,7 @@ const Link = forwardRef(function Link(linkProps, ref) {
|
|
|
6317
6492
|
'is-active': isActive,
|
|
6318
6493
|
});
|
|
6319
6494
|
const linkClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
|
|
6320
|
-
return (jsx(Component, { ref: ref, className: linkClasses || undefined, ...rest, children: children }));
|
|
6495
|
+
return (jsx(Component, { ref: ref, className: linkClasses || undefined, ...rest, ...(Component === 'button' ? { type: buttonType(rest.type) } : {}), children: children }));
|
|
6321
6496
|
});
|
|
6322
6497
|
Link.displayName = 'Link';
|
|
6323
6498
|
|
|
@@ -6342,6 +6517,281 @@ const ListItem = ({ className, textColor, bgColor, children, ...props }) => {
|
|
|
6342
6517
|
return (jsx("li", { className: itemClasses || undefined, ...rest, children: children }));
|
|
6343
6518
|
};
|
|
6344
6519
|
|
|
6520
|
+
/**
|
|
6521
|
+
* How long after an item appears its announcement is written, in ms. The wait
|
|
6522
|
+
* lets a screen reader register a region the container has only just mounted,
|
|
6523
|
+
* and items shown in quick succession are written, and read out, together.
|
|
6524
|
+
*/
|
|
6525
|
+
const announceDelay = 100;
|
|
6526
|
+
/**
|
|
6527
|
+
* How long an announcement stays in the region once written, in ms. That's
|
|
6528
|
+
* long enough for a screen reader to pick it up. Clearing it after keeps a
|
|
6529
|
+
* second copy of the item's text from sitting in the page, where someone
|
|
6530
|
+
* reading through the page, or a test looking the text up, would find it
|
|
6531
|
+
* again.
|
|
6532
|
+
*/
|
|
6533
|
+
const announcementLifetime = 1000;
|
|
6534
|
+
const noAnnouncements = [];
|
|
6535
|
+
const nothingWritten = [];
|
|
6536
|
+
const noAnnouncementsYet = {
|
|
6537
|
+
key: 0,
|
|
6538
|
+
waiting: noAnnouncements,
|
|
6539
|
+
written: nothingWritten,
|
|
6540
|
+
};
|
|
6541
|
+
// Hides the region with inline styles rather than a class, so it needs no
|
|
6542
|
+
// stylesheet, including the helper classes a modular Bulma build can leave
|
|
6543
|
+
// out. Clipping it, rather than using `display` or `visibility`, keeps it in
|
|
6544
|
+
// the accessibility tree. The declarations match the `extras-sr-only` mixin,
|
|
6545
|
+
// plus `clip-path`, which replaces the deprecated `clip`. The negative margin
|
|
6546
|
+
// pulls the 1px box back inside the page, so it doesn't add scrollable
|
|
6547
|
+
// overflow.
|
|
6548
|
+
const visuallyHidden = {
|
|
6549
|
+
position: 'absolute',
|
|
6550
|
+
width: '1px',
|
|
6551
|
+
height: '1px',
|
|
6552
|
+
padding: 0,
|
|
6553
|
+
margin: '-1px',
|
|
6554
|
+
overflow: 'hidden',
|
|
6555
|
+
clip: 'rect(0, 0, 0, 0)',
|
|
6556
|
+
clipPath: 'inset(50%)',
|
|
6557
|
+
whiteSpace: 'nowrap',
|
|
6558
|
+
border: 0,
|
|
6559
|
+
};
|
|
6560
|
+
/**
|
|
6561
|
+
* Works out what a status region says. Each item is announced once. Its
|
|
6562
|
+
* announcement is written `announceDelay` after it appears, or after the last
|
|
6563
|
+
* item to join it when several appear in quick succession, alongside whatever
|
|
6564
|
+
* the region still says. Once written, it stays for `announcementLifetime`,
|
|
6565
|
+
* whatever is written after it and whether or not its item goes in the
|
|
6566
|
+
* meantime. An item that goes before its announcement is written isn't
|
|
6567
|
+
* announced.
|
|
6568
|
+
*
|
|
6569
|
+
* Nothing is written in the commit that mounts the region or the item. A
|
|
6570
|
+
* screen reader reliably announces a polite live region whose content changes
|
|
6571
|
+
* after the region is already in the page, and not always one that arrives
|
|
6572
|
+
* with its content. By the time `describe` runs, an item's rendered text can
|
|
6573
|
+
* be read.
|
|
6574
|
+
*
|
|
6575
|
+
* @function useAnnouncements
|
|
6576
|
+
* @param items - The items to announce, in the order they were shown.
|
|
6577
|
+
* @param describe - The text to announce for an item, or nothing to skip it.
|
|
6578
|
+
* It runs once the item is on screen, and it must keep its identity between
|
|
6579
|
+
* renders (a module-level function or a `useCallback`), or every render
|
|
6580
|
+
* re-checks the items.
|
|
6581
|
+
* @returns The announcements to render, in the order they were written.
|
|
6582
|
+
*/
|
|
6583
|
+
function useAnnouncements(items, describe) {
|
|
6584
|
+
// The ids of the items on screen as of the last change, every one of which
|
|
6585
|
+
// has been looked at for an announcement already.
|
|
6586
|
+
const onScreenIdsRef = useRef(new Set());
|
|
6587
|
+
// Clears that haven't run yet. They outlive the batch that started them, so
|
|
6588
|
+
// they're only stopped when the region unmounts.
|
|
6589
|
+
const clearTimersRef = useRef(new Set());
|
|
6590
|
+
const [announcements, setAnnouncements] = useState(noAnnouncementsYet);
|
|
6591
|
+
// Runs after the commit that puts an item on screen, which is the first
|
|
6592
|
+
// point its rendered text can be read.
|
|
6593
|
+
useEffect(() => {
|
|
6594
|
+
const announced = onScreenIdsRef.current;
|
|
6595
|
+
const appeared = items.filter(item => !announced.has(item.id));
|
|
6596
|
+
// Items that have gone drop out here too. Ids are never reused, so
|
|
6597
|
+
// forgetting them can't bring an old item back.
|
|
6598
|
+
onScreenIdsRef.current = new Set(items.map(item => item.id));
|
|
6599
|
+
const next = [];
|
|
6600
|
+
for (const item of appeared) {
|
|
6601
|
+
const text = describe(item);
|
|
6602
|
+
if (text)
|
|
6603
|
+
next.push({ id: item.id, text });
|
|
6604
|
+
}
|
|
6605
|
+
if (next.length > 0) {
|
|
6606
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect -- an item's rendered text can only be read once it's on screen
|
|
6607
|
+
setAnnouncements(current => ({
|
|
6608
|
+
...current,
|
|
6609
|
+
key: current.key + 1,
|
|
6610
|
+
// Announcements still waiting go out with the new ones. What's
|
|
6611
|
+
// already written stays put.
|
|
6612
|
+
waiting: [...current.waiting, ...next],
|
|
6613
|
+
}));
|
|
6614
|
+
}
|
|
6615
|
+
}, [items, describe]);
|
|
6616
|
+
// The write only touches the batch it was started for: a newer batch can
|
|
6617
|
+
// be set before the render that cancels this timer. Its clear is started
|
|
6618
|
+
// by the write itself, so it's timed from the write without waiting on a
|
|
6619
|
+
// render, and a newer batch arriving doesn't cut short what's written.
|
|
6620
|
+
const { key } = announcements;
|
|
6621
|
+
useEffect(() => {
|
|
6622
|
+
if (key === noAnnouncementsYet.key)
|
|
6623
|
+
return undefined;
|
|
6624
|
+
const clearTimers = clearTimersRef.current;
|
|
6625
|
+
const write = setTimeout(() => {
|
|
6626
|
+
// Whether an item is on screen is decided here, once. An item that
|
|
6627
|
+
// went before its announcement was due isn't announced, and one that
|
|
6628
|
+
// goes after keeps its announcement for the rest of its lifetime, when
|
|
6629
|
+
// the region holds the only copy of its text rather than a second one.
|
|
6630
|
+
const onScreen = onScreenIdsRef.current;
|
|
6631
|
+
setAnnouncements(current => current.key === key
|
|
6632
|
+
? {
|
|
6633
|
+
...current,
|
|
6634
|
+
waiting: noAnnouncements,
|
|
6635
|
+
written: [
|
|
6636
|
+
...current.written,
|
|
6637
|
+
...current.waiting
|
|
6638
|
+
.filter(announcement => onScreen.has(announcement.id))
|
|
6639
|
+
.map(announcement => ({ ...announcement, batch: key })),
|
|
6640
|
+
],
|
|
6641
|
+
}
|
|
6642
|
+
: current);
|
|
6643
|
+
// eslint-disable-next-line @eslint-react/web-api-no-leaked-timeout -- it has to outlive this effect when a newer batch arrives, so the unmount effect below clears it
|
|
6644
|
+
const clear = setTimeout(() => {
|
|
6645
|
+
clearTimers.delete(clear);
|
|
6646
|
+
setAnnouncements(current => {
|
|
6647
|
+
const written = current.written.filter(announcement => announcement.batch !== key);
|
|
6648
|
+
return written.length === current.written.length
|
|
6649
|
+
? current
|
|
6650
|
+
: { ...current, written };
|
|
6651
|
+
});
|
|
6652
|
+
}, announcementLifetime);
|
|
6653
|
+
clearTimers.add(clear);
|
|
6654
|
+
}, announceDelay);
|
|
6655
|
+
return () => clearTimeout(write);
|
|
6656
|
+
}, [key]);
|
|
6657
|
+
useEffect(() => {
|
|
6658
|
+
const clearTimers = clearTimersRef.current;
|
|
6659
|
+
return () => {
|
|
6660
|
+
clearTimers.forEach(clearTimeout);
|
|
6661
|
+
clearTimers.clear();
|
|
6662
|
+
};
|
|
6663
|
+
}, []);
|
|
6664
|
+
return announcements.written;
|
|
6665
|
+
}
|
|
6666
|
+
/**
|
|
6667
|
+
* Reads an element out roughly the way a screen reader would: its text, with
|
|
6668
|
+
* an element's `aria-label`, or an image's `alt`, standing in for what's
|
|
6669
|
+
* inside it, a break between block-level elements, and parts that are
|
|
6670
|
+
* `aria-hidden`, `hidden` or inline-styled `display: none` left out. It isn't
|
|
6671
|
+
* the full accessible name computation, so `aria-labelledby`, CSS-generated
|
|
6672
|
+
* content, content hidden by a stylesheet and other ways of naming or hiding
|
|
6673
|
+
* content aren't followed.
|
|
6674
|
+
*
|
|
6675
|
+
* @function spokenText
|
|
6676
|
+
* @param element - The element to read.
|
|
6677
|
+
* @returns Its text, with runs of whitespace collapsed and the ends trimmed.
|
|
6678
|
+
*/
|
|
6679
|
+
function spokenText(element) {
|
|
6680
|
+
return readAloud(element).replace(/\s+/g, ' ').trim();
|
|
6681
|
+
}
|
|
6682
|
+
// Elements a browser displays as blocks by default, and `br`. A screen reader
|
|
6683
|
+
// pauses between them, so their text shouldn't run into the text beside them.
|
|
6684
|
+
// They're known by tag rather than by computed `display`, which would depend
|
|
6685
|
+
// on a stylesheet and on layout.
|
|
6686
|
+
const blockLevelTags = new Set([
|
|
6687
|
+
'ADDRESS',
|
|
6688
|
+
'ARTICLE',
|
|
6689
|
+
'ASIDE',
|
|
6690
|
+
'BLOCKQUOTE',
|
|
6691
|
+
'BR',
|
|
6692
|
+
'CAPTION',
|
|
6693
|
+
'DD',
|
|
6694
|
+
'DETAILS',
|
|
6695
|
+
'DIALOG',
|
|
6696
|
+
'DIV',
|
|
6697
|
+
'DL',
|
|
6698
|
+
'DT',
|
|
6699
|
+
'FIELDSET',
|
|
6700
|
+
'FIGCAPTION',
|
|
6701
|
+
'FIGURE',
|
|
6702
|
+
'FOOTER',
|
|
6703
|
+
'FORM',
|
|
6704
|
+
'H1',
|
|
6705
|
+
'H2',
|
|
6706
|
+
'H3',
|
|
6707
|
+
'H4',
|
|
6708
|
+
'H5',
|
|
6709
|
+
'H6',
|
|
6710
|
+
'HEADER',
|
|
6711
|
+
'HGROUP',
|
|
6712
|
+
'HR',
|
|
6713
|
+
'LEGEND',
|
|
6714
|
+
'LI',
|
|
6715
|
+
'MAIN',
|
|
6716
|
+
'MENU',
|
|
6717
|
+
'NAV',
|
|
6718
|
+
'OL',
|
|
6719
|
+
'P',
|
|
6720
|
+
'PRE',
|
|
6721
|
+
'SEARCH',
|
|
6722
|
+
'SECTION',
|
|
6723
|
+
'SUMMARY',
|
|
6724
|
+
'TABLE',
|
|
6725
|
+
'TBODY',
|
|
6726
|
+
'TD',
|
|
6727
|
+
'TFOOT',
|
|
6728
|
+
'TH',
|
|
6729
|
+
'THEAD',
|
|
6730
|
+
'TR',
|
|
6731
|
+
'UL',
|
|
6732
|
+
]);
|
|
6733
|
+
/**
|
|
6734
|
+
* Whether an element is left out of what a screen reader reads.
|
|
6735
|
+
*
|
|
6736
|
+
* @function isHidden
|
|
6737
|
+
* @param element - The element to check.
|
|
6738
|
+
* @returns True for `aria-hidden="true"`, the `hidden` attribute, and an
|
|
6739
|
+
* inline `display: none`, on an HTML, SVG or any other element with an
|
|
6740
|
+
* inline style.
|
|
6741
|
+
*/
|
|
6742
|
+
const isHidden = (element) => element.getAttribute('aria-hidden') === 'true' ||
|
|
6743
|
+
element.hasAttribute('hidden') ||
|
|
6744
|
+
element.style?.display === 'none';
|
|
6745
|
+
/**
|
|
6746
|
+
* The text `spokenText` reads for an element, before its whitespace is
|
|
6747
|
+
* tidied.
|
|
6748
|
+
*
|
|
6749
|
+
* @function readAloud
|
|
6750
|
+
* @param element - The element to read.
|
|
6751
|
+
* @returns Its text.
|
|
6752
|
+
*/
|
|
6753
|
+
function readAloud(element) {
|
|
6754
|
+
if (isHidden(element))
|
|
6755
|
+
return '';
|
|
6756
|
+
const name = element.getAttribute('aria-label') ||
|
|
6757
|
+
(element.tagName === 'IMG' ? element.getAttribute('alt') : null);
|
|
6758
|
+
const text = name ||
|
|
6759
|
+
Array.from(element.childNodes, child => {
|
|
6760
|
+
if (child instanceof Element)
|
|
6761
|
+
return readAloud(child);
|
|
6762
|
+
return child.nodeType === Node.TEXT_NODE ? child.textContent : '';
|
|
6763
|
+
}).join('');
|
|
6764
|
+
// A name stands in for the element's content, and a block's content stands
|
|
6765
|
+
// apart from what's around it, so both are padded to keep them from running
|
|
6766
|
+
// into the neighboring text. An inline run, like `<span>Up</span>` then
|
|
6767
|
+
// `<span>loaded</span>`, still reads as one word.
|
|
6768
|
+
return name || blockLevelTags.has(element.tagName) ? ` ${text} ` : text;
|
|
6769
|
+
}
|
|
6770
|
+
/**
|
|
6771
|
+
* A visually hidden, polite `status` live region that a programmatic
|
|
6772
|
+
* container announces its items through. The container renders it from the
|
|
6773
|
+
* moment it mounts, whether or not it has anything to show, so the region is
|
|
6774
|
+
* already in the page when an announcement is written into it.
|
|
6775
|
+
*
|
|
6776
|
+
* The announcements are this component's own state, so writing and clearing
|
|
6777
|
+
* them re-renders the region and leaves the container's items alone. Each one
|
|
6778
|
+
* is its own keyed node, so a re-render that leaves the announcements alone
|
|
6779
|
+
* leaves the region's content alone too, and nothing is read out twice.
|
|
6780
|
+
*
|
|
6781
|
+
* @function StatusRegion
|
|
6782
|
+
* @param props - The items to announce, and the text to announce for each.
|
|
6783
|
+
* @returns The region.
|
|
6784
|
+
*/
|
|
6785
|
+
function StatusRegion({ items, describe, }) {
|
|
6786
|
+
const announcements = useAnnouncements(items, describe);
|
|
6787
|
+
// `role="status"` makes a region atomic unless it says otherwise, which
|
|
6788
|
+
// reads the whole region on every change. Each announcement is its own
|
|
6789
|
+
// node, and only additions are relevant by default, so with atomic off a
|
|
6790
|
+
// screen reader reads just what was written, and removing one announcement
|
|
6791
|
+
// doesn't read out the ones still there.
|
|
6792
|
+
return (jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "false", style: visuallyHidden, children: announcements.map(announcement => (jsx("div", { children: announcement.text }, announcement.id))) }));
|
|
6793
|
+
}
|
|
6794
|
+
|
|
6345
6795
|
/**
|
|
6346
6796
|
* The `Notification` component is a Bulma-styled alert/message area for providing feedback, warnings, or information to users.
|
|
6347
6797
|
*
|
|
@@ -6365,7 +6815,7 @@ const Notification = ({ className, color, textColor, isLight, hasDelete, onDelet
|
|
|
6365
6815
|
});
|
|
6366
6816
|
const deleteClasses = usePrefixedClassNames('delete');
|
|
6367
6817
|
const notificationClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
|
|
6368
|
-
return (jsxs("div", { className: notificationClasses, ...rest, children: [hasDelete && (jsx("button", { className: deleteClasses, onClick: onDelete, "aria-label": "Close notification" })), children] }));
|
|
6818
|
+
return (jsxs("div", { className: notificationClasses, ...rest, children: [hasDelete && (jsx("button", { type: "button", className: deleteClasses, onClick: onDelete, "aria-label": "Close notification" })), children] }));
|
|
6369
6819
|
};
|
|
6370
6820
|
let notificationId = 0;
|
|
6371
6821
|
const notificationListeners = new Set();
|
|
@@ -6384,9 +6834,9 @@ const getServerNotifications = () => noNotifications;
|
|
|
6384
6834
|
// updates alone, so notifications raised before it mounted still appear. It is
|
|
6385
6835
|
// replaced rather than mutated, and only when listeners are notified, because
|
|
6386
6836
|
// useSyncExternalStore needs the same array back between changes. An empty
|
|
6387
|
-
// list is `noNotifications` itself, so
|
|
6388
|
-
//
|
|
6389
|
-
// again.
|
|
6837
|
+
// list is `noNotifications` itself, so an empty store reads the same snapshot
|
|
6838
|
+
// on the client as on the server, and a notify that leaves nothing showing
|
|
6839
|
+
// when nothing was showing doesn't render the container again.
|
|
6390
6840
|
let visibleNotifications = noNotifications;
|
|
6391
6841
|
const getVisibleNotifications = () => visibleNotifications;
|
|
6392
6842
|
const notifyNotificationListeners = () => {
|
|
@@ -6497,20 +6947,32 @@ const notification = {
|
|
|
6497
6947
|
return () => notificationListeners.delete(listener);
|
|
6498
6948
|
},
|
|
6499
6949
|
};
|
|
6950
|
+
/**
|
|
6951
|
+
* Whether a notification of this color announces itself as an alert, rather
|
|
6952
|
+
* than politely through NotificationContainer's status region.
|
|
6953
|
+
*
|
|
6954
|
+
* @function isUrgentColor
|
|
6955
|
+
* @param {NotificationOptions['color']} color - The notification's color.
|
|
6956
|
+
* @returns {boolean} True for `danger` and `warning`.
|
|
6957
|
+
*/
|
|
6958
|
+
const isUrgentColor = (color) => color === 'danger' || color === 'warning';
|
|
6500
6959
|
/**
|
|
6501
6960
|
* Single auto-dismissing notification item used by NotificationContainer.
|
|
6502
6961
|
*
|
|
6503
6962
|
* @function
|
|
6504
|
-
* @param {{ instance: NotificationInstance; onClose: (id: string) => void }} props - Component props.
|
|
6963
|
+
* @param {{ instance: NotificationInstance; onClose: (id: string) => void; registerMessage: (id: string, node: HTMLElement | null) => void }} props - Component props.
|
|
6505
6964
|
* @returns {JSX.Element} The rendered notification item.
|
|
6506
6965
|
*/
|
|
6507
|
-
const NotificationItem = ({ instance, onClose }) => {
|
|
6966
|
+
const NotificationItem = ({ instance, onClose, registerMessage }) => {
|
|
6508
6967
|
const { message, color, isLight, duration = 3000, hasDelete = true, indefinite = false, pauseOnHover = true, } = instance.options;
|
|
6509
6968
|
const [isPaused, setIsPaused] = useState(false);
|
|
6510
|
-
const urgent = color
|
|
6969
|
+
const urgent = isUrgentColor(color);
|
|
6511
6970
|
const handleClose = useCallback(() => {
|
|
6512
6971
|
onClose(instance.id);
|
|
6513
6972
|
}, [onClose, instance.id]);
|
|
6973
|
+
const messageRef = useCallback((node) => {
|
|
6974
|
+
registerMessage(instance.id, node);
|
|
6975
|
+
}, [registerMessage, instance.id]);
|
|
6514
6976
|
// Auto-close timer
|
|
6515
6977
|
useEffect(() => {
|
|
6516
6978
|
if (indefinite || duration === 0 || isPaused)
|
|
@@ -6526,7 +6988,7 @@ const NotificationItem = ({ instance, onClose }) => {
|
|
|
6526
6988
|
if (pauseOnHover)
|
|
6527
6989
|
setIsPaused(false);
|
|
6528
6990
|
}, [pauseOnHover]);
|
|
6529
|
-
return (jsx(Notification, { color: color, isLight: isLight, hasDelete: hasDelete, onDelete: handleClose, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: { pointerEvents: 'auto' }, children: urgent ? (jsx("span", { role: "alert", "aria-live": "assertive", children: message })) : (jsx("span", {
|
|
6991
|
+
return (jsx(Notification, { color: color, isLight: isLight, hasDelete: hasDelete, onDelete: handleClose, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: { pointerEvents: 'auto' }, children: urgent ? (jsx("span", { role: "alert", "aria-live": "assertive", children: message })) : (jsx("span", { ref: messageRef, children: message })) }));
|
|
6530
6992
|
};
|
|
6531
6993
|
// The order NotificationContainer renders its stacks in: across the top of the
|
|
6532
6994
|
// screen, then across the bottom.
|
|
@@ -6573,19 +7035,63 @@ const notificationStackStyle = (position) => {
|
|
|
6573
7035
|
* container's `position`, so the container renders a stack for each position
|
|
6574
7036
|
* in use.
|
|
6575
7037
|
*
|
|
7038
|
+
* It keeps a visually hidden `role="status"` live region in the page from the
|
|
7039
|
+
* moment it mounts, even while nothing is showing, and announces every
|
|
7040
|
+
* notification other than `danger` and `warning` through it, a moment after
|
|
7041
|
+
* the notification appears. Those notifications carry no `role="status"` of
|
|
7042
|
+
* their own, so `getByRole('status')` finds the region, not the notification.
|
|
7043
|
+
* The text stays in the region briefly, even if the notification closes in
|
|
7044
|
+
* the meantime, and while both are up the page holds two copies of it. A
|
|
7045
|
+
* polite notification that closes before its announcement is written, a
|
|
7046
|
+
* moment after it appears, isn't announced at all. `danger` and `warning`
|
|
7047
|
+
* notifications announce themselves as assertive alerts. The region is hidden
|
|
7048
|
+
* with inline styles, so it needs no stylesheet.
|
|
7049
|
+
*
|
|
6576
7050
|
* @function
|
|
6577
7051
|
* @param {{ position?: NotificationPosition }} props - Container props.
|
|
6578
|
-
* @returns {JSX.Element | null} The rendered notification container, or null
|
|
7052
|
+
* @returns {JSX.Element | null} The rendered notification container, or null on the server and while hydrating.
|
|
6579
7053
|
*/
|
|
6580
7054
|
const NotificationContainer = ({ position = 'top-right' }) => {
|
|
6581
7055
|
// Starts from the notifications already showing instead of an empty list,
|
|
6582
7056
|
// then follows changes.
|
|
6583
7057
|
const items = useSyncExternalStore(notification.subscribe, getVisibleNotifications, getServerNotifications);
|
|
6584
|
-
|
|
7058
|
+
// A portal needs a document, and it has no server-rendered counterpart, so
|
|
7059
|
+
// the server render and the hydrating one render nothing, and the container
|
|
7060
|
+
// portals in from the render after hydration.
|
|
7061
|
+
const isHydrated = useIsHydrated();
|
|
7062
|
+
// The notifications the status region announces. Danger and warning
|
|
7063
|
+
// announce themselves.
|
|
7064
|
+
const politeItems = useMemo(() => items.filter(item => !isUrgentColor(item.options.color)), [items]);
|
|
7065
|
+
// Each polite notification's message element, so the text the region
|
|
7066
|
+
// announces is the text on screen, whatever the message renders.
|
|
7067
|
+
const messageNodesRef = useRef(new Map());
|
|
7068
|
+
const registerMessage = useCallback((id, node) => {
|
|
7069
|
+
if (node) {
|
|
7070
|
+
messageNodesRef.current.set(id, node);
|
|
7071
|
+
}
|
|
7072
|
+
else {
|
|
7073
|
+
messageNodesRef.current.delete(id);
|
|
7074
|
+
}
|
|
7075
|
+
}, []);
|
|
7076
|
+
// StatusRegion only describes polite notifications that are on screen, and
|
|
7077
|
+
// each of those registered its message element when it mounted. The
|
|
7078
|
+
// fallback is for a notification announced without being rendered, should
|
|
7079
|
+
// the container ever render fewer than it announces: a plain-text message
|
|
7080
|
+
// still says itself, and anything else is skipped.
|
|
7081
|
+
const describe = useCallback((item) => {
|
|
7082
|
+
const node = messageNodesRef.current.get(item.id);
|
|
7083
|
+
/* istanbul ignore if: every polite notification on screen registers its message element when it mounts */
|
|
7084
|
+
if (!node) {
|
|
7085
|
+
const { message } = item.options;
|
|
7086
|
+
return typeof message === 'string' ? message : null;
|
|
7087
|
+
}
|
|
7088
|
+
return spokenText(node);
|
|
7089
|
+
}, []);
|
|
7090
|
+
if (typeof document === 'undefined' || !isHydrated) {
|
|
6585
7091
|
return null;
|
|
6586
7092
|
}
|
|
6587
7093
|
const stacks = groupIntoPositionStacks(items, item => item.options.position, position, notificationStackOrder);
|
|
6588
|
-
return createPortal(stacks.map(stack => (jsx("div", { style: notificationStackStyle(stack.position), children: stack.items.map(item => (jsx(NotificationItem, { instance: item, onClose: notification.close }, item.id))) }, stack.key))), document.body);
|
|
7094
|
+
return createPortal(jsxs(Fragment, { children: [stacks.map(stack => (jsx("div", { style: notificationStackStyle(stack.position), children: stack.items.map(item => (jsx(NotificationItem, { instance: item, onClose: notification.close, registerMessage: registerMessage }, item.id))) }, stack.key))), jsx(StatusRegion, { items: politeItems, describe: describe })] }), document.body);
|
|
6589
7095
|
};
|
|
6590
7096
|
|
|
6591
7097
|
/**
|
|
@@ -6837,7 +7343,26 @@ const Tfoot = ({ className, children, ...props }) => {
|
|
|
6837
7343
|
return (jsx("tfoot", { className: tfootClasses || undefined, ...rest, children: children }));
|
|
6838
7344
|
};
|
|
6839
7345
|
|
|
6840
|
-
/**
|
|
7346
|
+
/**
|
|
7347
|
+
* The values the table `color` prop accepts, as a readonly tuple.
|
|
7348
|
+
*
|
|
7349
|
+
* `TableColor` is typed from it, and `Tr`, `Th` and `Td` all take a
|
|
7350
|
+
* `TableColor`, so the tuple and those props list the same values. Map over
|
|
7351
|
+
* it to build a color picker, or check a value that arrives at runtime before
|
|
7352
|
+
* passing it in: the components add no color class for a value outside the
|
|
7353
|
+
* tuple.
|
|
7354
|
+
*
|
|
7355
|
+
* @example
|
|
7356
|
+
* import { Tr, Td, validTableColors } from '@allxsmith/bestax-bulma';
|
|
7357
|
+
*
|
|
7358
|
+
* <Tr>
|
|
7359
|
+
* {validTableColors.map(color => (
|
|
7360
|
+
* <Td key={color} color={color}>
|
|
7361
|
+
* {color}
|
|
7362
|
+
* </Td>
|
|
7363
|
+
* ))}
|
|
7364
|
+
* </Tr>;
|
|
7365
|
+
*/
|
|
6841
7366
|
const validTableColors = [
|
|
6842
7367
|
'primary',
|
|
6843
7368
|
'link',
|
|
@@ -6994,7 +7519,7 @@ const Tag = ({ className, color, size, isLight, isRounded, isDelete, isHoverable
|
|
|
6994
7519
|
});
|
|
6995
7520
|
const tagClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
|
|
6996
7521
|
if (isDelete) {
|
|
6997
|
-
return (jsx("button", { className: tagClasses, onClick: onDelete, "aria-label":
|
|
7522
|
+
return (jsx("button", { className: tagClasses, onClick: onDelete, ...rest, "aria-label": rest['aria-label'] || 'Delete tag', type: buttonType(rest.type) }));
|
|
6998
7523
|
}
|
|
6999
7524
|
return (jsx("span", { className: tagClasses, ...rest, children: children }));
|
|
7000
7525
|
};
|
|
@@ -9176,8 +9701,7 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
|
|
|
9176
9701
|
if (!isActive)
|
|
9177
9702
|
return undefined;
|
|
9178
9703
|
const handleClickOutside = (e) => {
|
|
9179
|
-
if (containerRef.current &&
|
|
9180
|
-
!containerRef.current.contains(e.target)) {
|
|
9704
|
+
if (containerRef.current && !isEventInside(e, containerRef.current)) {
|
|
9181
9705
|
setIsActive(false);
|
|
9182
9706
|
setHighlightedIndex(-1);
|
|
9183
9707
|
}
|
|
@@ -13337,9 +13861,18 @@ const bulmaVarPropMap = Object.fromEntries(bulmaCssVars
|
|
|
13337
13861
|
* real 0 keeps what
|
|
13338
13862
|
* people see and makes it valid CSS. Keyed by the helper values, so adding
|
|
13339
13863
|
* one means saying what it writes.
|
|
13864
|
+
*
|
|
13865
|
+
* The sizes write nothing and only add their class. Their classes read the
|
|
13866
|
+
* radius variables, so `normal` would point `--bulma-radius` at itself, which
|
|
13867
|
+
* is invalid and computes to 0, and `rounded` would turn every control inside
|
|
13868
|
+
* the Theme into a pill.
|
|
13340
13869
|
*/
|
|
13341
13870
|
const radiusHelperVars = {
|
|
13342
13871
|
radiusless: '0',
|
|
13872
|
+
small: undefined,
|
|
13873
|
+
normal: undefined,
|
|
13874
|
+
large: undefined,
|
|
13875
|
+
rounded: undefined,
|
|
13343
13876
|
};
|
|
13344
13877
|
/**
|
|
13345
13878
|
* What `radius` writes to `--bulma-radius` on a Theme, or `undefined` when it
|
|
@@ -13366,7 +13899,7 @@ const themeRadiusVar = (radius) => {
|
|
|
13366
13899
|
warnOnce('Theme:radius-variable', `[bestax-bulma] <Theme radius="${radius}">: setting --bulma-radius ` +
|
|
13367
13900
|
'through the radius prop is deprecated and will stop working in a ' +
|
|
13368
13901
|
'future major version. On Theme, as on every other component, radius ' +
|
|
13369
|
-
`is the "${validRadii.join('", "')}"
|
|
13902
|
+
`is the border radius helper ("${validRadii.join('", "')}"). Set the variable with ` +
|
|
13370
13903
|
`bulmaVars={{ '--bulma-radius': '${radius}' }} instead.`);
|
|
13371
13904
|
return radius;
|
|
13372
13905
|
};
|
|
@@ -13452,6 +13985,16 @@ const Theme = ({ bulmaVars = {}, children, className, isRoot = false, colorMode,
|
|
|
13452
13985
|
const radiusHelper = validRadii.includes(radius)
|
|
13453
13986
|
? radius
|
|
13454
13987
|
: undefined;
|
|
13988
|
+
// A radius size only adds its class, and a root Theme renders no wrapper to
|
|
13989
|
+
// carry one, so on `isRoot` it does nothing at all. Say so, as the other
|
|
13990
|
+
// radius routes that do not do what they look like do.
|
|
13991
|
+
if (isRoot && radiusHelper && radiusHelperVars[radiusHelper] === undefined) {
|
|
13992
|
+
warnOnce('Theme:root-radius-size', `[bestax-bulma] <Theme isRoot radius="${radiusHelper}">: a root Theme ` +
|
|
13993
|
+
`has no wrapper element for has-radius-${radiusHelper}, and the ` +
|
|
13994
|
+
'radius sizes set no variable, so this does nothing. To round one ' +
|
|
13995
|
+
`element, put radius="${radiusHelper}" on it. To change the radius ` +
|
|
13996
|
+
"across the page, set bulmaVars={{ '--bulma-radius': '…' }} instead.");
|
|
13997
|
+
}
|
|
13455
13998
|
// Extract Bulma variable props from restProps
|
|
13456
13999
|
const { bulmaVarProps, otherProps } = useMemo(() => {
|
|
13457
14000
|
const varProps = {};
|
|
@@ -13902,5 +14445,5 @@ const Section = ({ size, className, children, color, bgColor, textColor, style,
|
|
|
13902
14445
|
return (jsx("section", { className: sectionClasses, style: mergeBulmaStyles(bulmaHelperStyles, style), ...rest, children: children }));
|
|
13903
14446
|
};
|
|
13904
14447
|
|
|
13905
|
-
export { Autocomplete, Avatar, Avatars, Badge, Block, Box, Breadcrumb, Button, Buttons, Card, Carousel, CarouselItem, Cell, Checkbox, Checkboxes, Code, Collapse, Column, Columns, ConfigProvider, Container, Content, Control, DateInput, DateInputBase, DateTimeInput, DateTimeInputBase, Delete, Dialog, DialogContainer, Divider, Dropdown, DropdownDivider, DropdownItem, Emphasis, Field, FieldBody, FieldLabel, Figure, File, Footer, Grid, Hero, HeroBody, HeroFoot, HeroHead, Icon, IconText, Image, Input, InputBase, Level, LevelItem, LevelLeft, LevelRight, Link, LinkButton, ListItem, Loading, Media, MediaContent, MediaLeft, MediaRight, Menu, MenuItem, MenuLabel, MenuList, Message, Modal, Navbar, NavbarBrand, NavbarBurger, NavbarDivider, NavbarDropdown, NavbarDropdownMenu, NavbarEnd, NavbarItem, NavbarLink, NavbarMenu, NavbarStart, Notification, NotificationContainer, NumberInput, Numberinput, OrderedList, Pagination, PaginationEllipsis, PaginationLink, PaginationList, PaginationNext, PaginationPrevious, Panel, PanelBlock, PanelButtonBlock, PanelCheckboxBlock, PanelHeading, PanelIcon, PanelInputBlock, PanelTabs, Paragraph, Pre, Progress, Radio, Radios, Rate, Reveal, Section, Select, SelectBase, Sidebar, Skeleton, Slider, Span, Step, Steps, Strong, SubTitle, Switch, Tab, TabContentItem, TabItem, TabList, Table, Tabs, TabsContent, Tag, TagInput, Taginput, Tags, Tbody, Td, TextArea, TextAreaBase, Tfoot, Th, Thead, Theme, TimeInput, TimeInputBase, Title, Toast, ToastContainer, Tooltip, Tr, UnorderedList, checkboxColors, checkboxSizes, classNames, createPrefixedClassNames, dialog, isBrowser$1 as isBrowser, mergeBulmaStyles, notification, prefixedClassNames, radioColors, radioSizes, switchColors, switchSizes, toast, useBulmaClasses, useClassPrefix, useColorClasses, useColorStyles, useConfig, useFlexboxClasses, useIconLibrary, useInsideControl, useInsideField, useOtherClasses, usePrefixedClass, usePrefixedClassNames, useSpacingClasses, useTypographyClasses, useVisibilityClasses, validAlignContents, validAlignItems, validAlignSelfs, validAlignments$1 as validAlignments, validColorShades, validColors, validCursors, validDisplays, validFlexDirections, validFlexGrowShrink, validFlexWraps, validFloats, validFontFamilies, validInteractions, validJustifyContents, validOverflows, validRadii, validResponsives, validSchemeColors, validShadows, validSizes$1 as validSizes, validTableColors, validTextSizes, validTextTransforms, validTextWeights, validViewports, validVisibilities };
|
|
14448
|
+
export { Autocomplete, Avatar, Avatars, Badge, Block, Box, Breadcrumb, Button, Buttons, Card, Carousel, CarouselItem, Cell, Checkbox, Checkboxes, Code, Collapse, Column, Columns, ConfigProvider, Container, Content, Control, DateInput, DateInputBase, DateTimeInput, DateTimeInputBase, Delete, Dialog, DialogContainer, Divider, Dropdown, DropdownDivider, DropdownItem, Emphasis, Field, FieldBody, FieldLabel, Figure, File, Footer, Grid, Hero, HeroBody, HeroFoot, HeroHead, Icon, IconText, Image, Input, InputBase, Level, LevelItem, LevelLeft, LevelRight, Link, LinkButton, ListItem, Loading, Media, MediaContent, MediaLeft, MediaRight, Menu, MenuItem, MenuLabel, MenuList, Message, Modal, Navbar, NavbarBrand, NavbarBurger, NavbarDivider, NavbarDropdown, NavbarDropdownMenu, NavbarEnd, NavbarItem, NavbarLink, NavbarMenu, NavbarStart, Notification, NotificationContainer, NumberInput, Numberinput, OrderedList, Pagination, PaginationEllipsis, PaginationLink, PaginationList, PaginationNext, PaginationPrevious, Panel, PanelBlock, PanelButtonBlock, PanelCheckboxBlock, PanelHeading, PanelIcon, PanelInputBlock, PanelTabs, Paragraph, Pre, Progress, Radio, Radios, Rate, Reveal, Section, Select, SelectBase, Sidebar, Skeleton, Slider, Span, Step, Steps, Strong, SubTitle, Switch, Tab, TabContentItem, TabItem, TabList, Table, Tabs, TabsContent, Tag, TagInput, Taginput, Tags, Tbody, Td, TextArea, TextAreaBase, Tfoot, Th, Thead, Theme, TimeInput, TimeInputBase, Title, Toast, ToastContainer, Tooltip, Tr, UnorderedList, checkboxColors, checkboxSizes, classNames, createPrefixedClassNames, dialog, isBrowser$1 as isBrowser, mergeBulmaStyles, notification, prefixedClassNames, radioColors, radioSizes, switchColors, switchSizes, toast, useBulmaClasses, useClassPrefix, useColorClasses, useColorStyles, useConfig, useFlexboxClasses, useIconLibrary, useInsideControl, useInsideField, useOtherClasses, usePrefixedClass, usePrefixedClassNames, useSpacingClasses, useTypographyClasses, useVisibilityClasses, validAlignContents, validAlignItems, validAlignSelfs, validAlignments$1 as validAlignments, validAspectRatios, validAxisOverflows, validColorShades, validColors, validCursors, validDisplays, validFlexDirections, validFlexGrowShrink, validFlexWraps, validFloats, validFontFamilies, validInteractions, validJustifyContents, validOverflows, validPositions, validRadii, validResponsives, validSchemeColors, validShadows, validSizes$1 as validSizes, validTableColors, validTextSizes, validTextTransforms, validTextWeights, validViewports, validVisibilities };
|
|
13906
14449
|
//# sourceMappingURL=index.esm.js.map
|