@allxsmith/bestax-bulma 5.11.7 → 5.13.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/index.cjs.js +279 -20
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +279 -20
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/Dropdown.d.ts +2 -0
- package/dist/types/components/Message.d.ts +8 -1
- package/dist/types/components/Navbar.d.ts +2 -0
- package/dist/types/elements/Buttons.d.ts +8 -1
- package/dist/types/elements/Icon.d.ts +9 -1
- package/dist/types/elements/Tags.d.ts +16 -2
- package/dist/types/helpers/bulmaClassHelpers.d.ts +11 -3
- package/dist/types/helpers/useVisibilityClasses.d.ts +8 -0
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -324,6 +324,7 @@ const validDisplays = [
|
|
|
324
324
|
'inline',
|
|
325
325
|
'inline-block',
|
|
326
326
|
'inline-flex',
|
|
327
|
+
'grid',
|
|
327
328
|
];
|
|
328
329
|
/**
|
|
329
330
|
* Valid Bulma visibility classes.
|
|
@@ -412,8 +413,12 @@ const validFlexGrowShrink = ['0', '1', '2', '3', '4', '5'];
|
|
|
412
413
|
const validViewports = [
|
|
413
414
|
'mobile',
|
|
414
415
|
'tablet',
|
|
416
|
+
'tablet-only',
|
|
417
|
+
'touch',
|
|
415
418
|
'desktop',
|
|
419
|
+
'desktop-only',
|
|
416
420
|
'widescreen',
|
|
421
|
+
'widescreen-only',
|
|
417
422
|
'fullhd',
|
|
418
423
|
];
|
|
419
424
|
/**
|
|
@@ -433,9 +438,17 @@ const createBulmaClassHelpers = (classPrefix, viewport) => {
|
|
|
433
438
|
classes.push(classPrefix ? `${classPrefix}${className}` : className);
|
|
434
439
|
};
|
|
435
440
|
// Helper to add class with optional viewport
|
|
436
|
-
|
|
441
|
+
//
|
|
442
|
+
// `supportedViewports` narrows which viewports may be suffixed onto this
|
|
443
|
+
// class. It defaults to every viewport, but a few Bulma helper families
|
|
444
|
+
// (notably `is-size-*`, which ships no `-only` bands) support only a subset,
|
|
445
|
+
// so passing the emitting set keeps us from producing dead classes.
|
|
446
|
+
const addClass = (prefix, value, validValues, supportsViewport = false, supportedViewports = validViewports) => {
|
|
437
447
|
if (value && validValues.includes(value)) {
|
|
438
|
-
const className = supportsViewport &&
|
|
448
|
+
const className = supportsViewport &&
|
|
449
|
+
viewport &&
|
|
450
|
+
validViewports.includes(viewport) &&
|
|
451
|
+
supportedViewports.includes(viewport)
|
|
439
452
|
? `${prefix}-${value}-${viewport}`
|
|
440
453
|
: `${prefix}-${value}`;
|
|
441
454
|
addPrefixedClass(className);
|
|
@@ -560,6 +573,19 @@ const useSpacingClasses = (props) => {
|
|
|
560
573
|
}, [classPrefix, m, mt, mr, mb, ml, mx, my, p, pt, pr, pb, pl, px, py]);
|
|
561
574
|
};
|
|
562
575
|
|
|
576
|
+
/**
|
|
577
|
+
* Viewports Bulma generates `is-size-*` classes for. Unlike text alignment,
|
|
578
|
+
* text size ships no `-only` bands (`tablet-only`/`desktop-only`/`widescreen-only`),
|
|
579
|
+
* so the `viewport` prop's suffix is limited to these on the `is-size` path.
|
|
580
|
+
*/
|
|
581
|
+
const sizeSupportedViewports = [
|
|
582
|
+
'mobile',
|
|
583
|
+
'tablet',
|
|
584
|
+
'touch',
|
|
585
|
+
'desktop',
|
|
586
|
+
'widescreen',
|
|
587
|
+
'fullhd',
|
|
588
|
+
];
|
|
563
589
|
/**
|
|
564
590
|
* A hook that generates Bulma typography helper classes, including
|
|
565
591
|
* viewport-specific text size and alignment variants.
|
|
@@ -580,8 +606,11 @@ const useTypographyClasses = (props) => {
|
|
|
580
606
|
return React.useMemo(() => {
|
|
581
607
|
const { classes, addPrefixedClass, addClass, addClassNoViewport } = createBulmaClassHelpers(classPrefix, viewport);
|
|
582
608
|
// Typography
|
|
583
|
-
|
|
584
|
-
|
|
609
|
+
// Bulma emits `is-size-*` for the six main/`touch` breakpoints but not the
|
|
610
|
+
// three `-only` bands, so restrict the viewport suffix to the ones it ships
|
|
611
|
+
// — otherwise `viewport="tablet-only"` would render a dead `is-size-N-tablet-only`.
|
|
612
|
+
addClass('is-size', textSize, validTextSizes, true, sizeSupportedViewports); // supports viewport (no `-only` bands)
|
|
613
|
+
addClass('has-text', textAlign, validAlignments$1, true); // supports viewport (all bands)
|
|
585
614
|
addClassNoViewport('is', textTransform, validTextTransforms); // no viewport support
|
|
586
615
|
addClassNoViewport('has-text-weight', textWeight, validTextWeights); // no viewport support
|
|
587
616
|
addClassNoViewport('is-family', fontFamily, validFontFamilies); // no viewport support
|
|
@@ -647,7 +676,7 @@ const useTypographyClasses = (props) => {
|
|
|
647
676
|
*/
|
|
648
677
|
const useVisibilityClasses = (props) => {
|
|
649
678
|
const { classPrefix } = useConfig();
|
|
650
|
-
const { visibility, visibilityMobile, visibilityTablet, visibilityDesktop, visibilityWidescreen, visibilityFullhd, display, displayMobile, displayTablet, displayDesktop, displayWidescreen, displayFullhd, viewport, } = props;
|
|
679
|
+
const { visibility, visibilityMobile, visibilityTablet, visibilityTabletOnly, visibilityTouch, visibilityDesktop, visibilityDesktopOnly, visibilityWidescreen, visibilityWidescreenOnly, visibilityFullhd, display, displayMobile, displayTablet, displayTabletOnly, displayTouch, displayDesktop, displayDesktopOnly, displayWidescreen, displayWidescreenOnly, displayFullhd, viewport, } = props;
|
|
651
680
|
return React.useMemo(() => {
|
|
652
681
|
const { classes, addPrefixedClass, addClass } = createBulmaClassHelpers(classPrefix, viewport);
|
|
653
682
|
// Viewport-specific visibility
|
|
@@ -664,8 +693,12 @@ const useVisibilityClasses = (props) => {
|
|
|
664
693
|
};
|
|
665
694
|
addViewportSpecificVisibilityClass(visibilityMobile, '-mobile');
|
|
666
695
|
addViewportSpecificVisibilityClass(visibilityTablet, '-tablet');
|
|
696
|
+
addViewportSpecificVisibilityClass(visibilityTabletOnly, '-tablet-only');
|
|
697
|
+
addViewportSpecificVisibilityClass(visibilityTouch, '-touch');
|
|
667
698
|
addViewportSpecificVisibilityClass(visibilityDesktop, '-desktop');
|
|
699
|
+
addViewportSpecificVisibilityClass(visibilityDesktopOnly, '-desktop-only');
|
|
668
700
|
addViewportSpecificVisibilityClass(visibilityWidescreen, '-widescreen');
|
|
701
|
+
addViewportSpecificVisibilityClass(visibilityWidescreenOnly, '-widescreen-only');
|
|
669
702
|
addViewportSpecificVisibilityClass(visibilityFullhd, '-fullhd');
|
|
670
703
|
// Visibility and Display
|
|
671
704
|
// Handle viewport-specific display properties first (they take precedence)
|
|
@@ -682,14 +715,22 @@ const useVisibilityClasses = (props) => {
|
|
|
682
715
|
// Apply viewport-specific display classes
|
|
683
716
|
addDisplayClass(displayMobile, '-mobile');
|
|
684
717
|
addDisplayClass(displayTablet, '-tablet');
|
|
718
|
+
addDisplayClass(displayTabletOnly, '-tablet-only');
|
|
719
|
+
addDisplayClass(displayTouch, '-touch');
|
|
685
720
|
addDisplayClass(displayDesktop, '-desktop');
|
|
721
|
+
addDisplayClass(displayDesktopOnly, '-desktop-only');
|
|
686
722
|
addDisplayClass(displayWidescreen, '-widescreen');
|
|
723
|
+
addDisplayClass(displayWidescreenOnly, '-widescreen-only');
|
|
687
724
|
addDisplayClass(displayFullhd, '-fullhd');
|
|
688
725
|
// Apply legacy display/viewport combination if no viewport-specific display props are set
|
|
689
726
|
const hasViewportSpecificDisplay = !!(displayMobile ||
|
|
690
727
|
displayTablet ||
|
|
728
|
+
displayTabletOnly ||
|
|
729
|
+
displayTouch ||
|
|
691
730
|
displayDesktop ||
|
|
731
|
+
displayDesktopOnly ||
|
|
692
732
|
displayWidescreen ||
|
|
733
|
+
displayWidescreenOnly ||
|
|
693
734
|
displayFullhd);
|
|
694
735
|
if (!hasViewportSpecificDisplay) {
|
|
695
736
|
// Legacy display handling
|
|
@@ -722,14 +763,22 @@ const useVisibilityClasses = (props) => {
|
|
|
722
763
|
visibility,
|
|
723
764
|
visibilityMobile,
|
|
724
765
|
visibilityTablet,
|
|
766
|
+
visibilityTabletOnly,
|
|
767
|
+
visibilityTouch,
|
|
725
768
|
visibilityDesktop,
|
|
769
|
+
visibilityDesktopOnly,
|
|
726
770
|
visibilityWidescreen,
|
|
771
|
+
visibilityWidescreenOnly,
|
|
727
772
|
visibilityFullhd,
|
|
728
773
|
display,
|
|
729
774
|
displayMobile,
|
|
730
775
|
displayTablet,
|
|
776
|
+
displayTabletOnly,
|
|
777
|
+
displayTouch,
|
|
731
778
|
displayDesktop,
|
|
779
|
+
displayDesktopOnly,
|
|
732
780
|
displayWidescreen,
|
|
781
|
+
displayWidescreenOnly,
|
|
733
782
|
displayFullhd,
|
|
734
783
|
viewport,
|
|
735
784
|
]);
|
|
@@ -758,7 +807,7 @@ const useVisibilityClasses = (props) => {
|
|
|
758
807
|
*/
|
|
759
808
|
const useFlexboxClasses = (props) => {
|
|
760
809
|
const { classPrefix } = useConfig();
|
|
761
|
-
const { flexDirection, flexWrap, justifyContent, alignContent, alignItems, alignSelf, flexGrow, flexShrink, display, displayMobile, displayTablet, displayDesktop, displayWidescreen, displayFullhd, } = props;
|
|
810
|
+
const { flexDirection, flexWrap, justifyContent, alignContent, alignItems, alignSelf, flexGrow, flexShrink, display, displayMobile, displayTablet, displayTabletOnly, displayTouch, displayDesktop, displayDesktopOnly, displayWidescreen, displayWidescreenOnly, displayFullhd, } = props;
|
|
762
811
|
return React.useMemo(() => {
|
|
763
812
|
const { classes, addClassNoViewport } = createBulmaClassHelpers(classPrefix);
|
|
764
813
|
// Flexbox
|
|
@@ -768,10 +817,18 @@ const useFlexboxClasses = (props) => {
|
|
|
768
817
|
displayMobile === 'inline-flex' ||
|
|
769
818
|
displayTablet === 'flex' ||
|
|
770
819
|
displayTablet === 'inline-flex' ||
|
|
820
|
+
displayTabletOnly === 'flex' ||
|
|
821
|
+
displayTabletOnly === 'inline-flex' ||
|
|
822
|
+
displayTouch === 'flex' ||
|
|
823
|
+
displayTouch === 'inline-flex' ||
|
|
771
824
|
displayDesktop === 'flex' ||
|
|
772
825
|
displayDesktop === 'inline-flex' ||
|
|
826
|
+
displayDesktopOnly === 'flex' ||
|
|
827
|
+
displayDesktopOnly === 'inline-flex' ||
|
|
773
828
|
displayWidescreen === 'flex' ||
|
|
774
829
|
displayWidescreen === 'inline-flex' ||
|
|
830
|
+
displayWidescreenOnly === 'flex' ||
|
|
831
|
+
displayWidescreenOnly === 'inline-flex' ||
|
|
775
832
|
displayFullhd === 'flex' ||
|
|
776
833
|
displayFullhd === 'inline-flex';
|
|
777
834
|
if (hasFlexDisplay) {
|
|
@@ -801,8 +858,12 @@ const useFlexboxClasses = (props) => {
|
|
|
801
858
|
display,
|
|
802
859
|
displayMobile,
|
|
803
860
|
displayTablet,
|
|
861
|
+
displayTabletOnly,
|
|
862
|
+
displayTouch,
|
|
804
863
|
displayDesktop,
|
|
864
|
+
displayDesktopOnly,
|
|
805
865
|
displayWidescreen,
|
|
866
|
+
displayWidescreenOnly,
|
|
806
867
|
displayFullhd,
|
|
807
868
|
]);
|
|
808
869
|
};
|
|
@@ -915,7 +976,7 @@ const useOtherClasses = (props) => {
|
|
|
915
976
|
* // rest: { className: 'custom-class' }
|
|
916
977
|
*/
|
|
917
978
|
const useBulmaClasses = (props) => {
|
|
918
|
-
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, displayDesktop, displayWidescreen, displayFullhd, textSizeMobile, textSizeTablet, textSizeDesktop, textSizeWidescreen, textSizeFullhd, textAlignMobile, textAlignTablet, textAlignDesktop, textAlignWidescreen, textAlignFullhd, visibilityMobile, visibilityTablet, visibilityDesktop, visibilityWidescreen, visibilityFullhd, skeleton, clearfix, relative, fullHeight, ...rest } = props;
|
|
979
|
+
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;
|
|
919
980
|
const colorClasses = useColorClasses({
|
|
920
981
|
color,
|
|
921
982
|
colorShade,
|
|
@@ -961,14 +1022,22 @@ const useBulmaClasses = (props) => {
|
|
|
961
1022
|
visibility,
|
|
962
1023
|
visibilityMobile,
|
|
963
1024
|
visibilityTablet,
|
|
1025
|
+
visibilityTabletOnly,
|
|
1026
|
+
visibilityTouch,
|
|
964
1027
|
visibilityDesktop,
|
|
1028
|
+
visibilityDesktopOnly,
|
|
965
1029
|
visibilityWidescreen,
|
|
1030
|
+
visibilityWidescreenOnly,
|
|
966
1031
|
visibilityFullhd,
|
|
967
1032
|
display,
|
|
968
1033
|
displayMobile,
|
|
969
1034
|
displayTablet,
|
|
1035
|
+
displayTabletOnly,
|
|
1036
|
+
displayTouch,
|
|
970
1037
|
displayDesktop,
|
|
1038
|
+
displayDesktopOnly,
|
|
971
1039
|
displayWidescreen,
|
|
1040
|
+
displayWidescreenOnly,
|
|
972
1041
|
displayFullhd,
|
|
973
1042
|
viewport,
|
|
974
1043
|
});
|
|
@@ -984,8 +1053,12 @@ const useBulmaClasses = (props) => {
|
|
|
984
1053
|
display,
|
|
985
1054
|
displayMobile,
|
|
986
1055
|
displayTablet,
|
|
1056
|
+
displayTabletOnly,
|
|
1057
|
+
displayTouch,
|
|
987
1058
|
displayDesktop,
|
|
1059
|
+
displayDesktopOnly,
|
|
988
1060
|
displayWidescreen,
|
|
1061
|
+
displayWidescreenOnly,
|
|
989
1062
|
displayFullhd,
|
|
990
1063
|
});
|
|
991
1064
|
const otherClasses = useOtherClasses({
|
|
@@ -1709,6 +1782,8 @@ const isBrowser$1 = (win, doc) => typeof win !== 'undefined' && typeof doc !== '
|
|
|
1709
1782
|
const DropdownComponent = ({ label, children, className, menuClassName, active: activeProp, up, right, hoverable, disabled, onActiveChange, closeOnClick = true, id, ...props }) => {
|
|
1710
1783
|
const [active, setActive] = React.useState(!!activeProp);
|
|
1711
1784
|
const dropdownRef = React.useRef(null);
|
|
1785
|
+
const triggerRef = React.useRef(null);
|
|
1786
|
+
const pendingFocusRef = React.useRef(null);
|
|
1712
1787
|
const { bulmaHelperClasses, rest } = useBulmaClasses(props);
|
|
1713
1788
|
// Generate Bulma classes with prefix
|
|
1714
1789
|
const bulmaClasses = usePrefixedClassNames('dropdown', {
|
|
@@ -1757,8 +1832,126 @@ const DropdownComponent = ({ label, children, className, menuClassName, active:
|
|
|
1757
1832
|
onActiveChange?.(false);
|
|
1758
1833
|
}
|
|
1759
1834
|
};
|
|
1835
|
+
const getMenuItems = () => {
|
|
1836
|
+
/* istanbul ignore next: dropdownRef.current is never null once mounted */
|
|
1837
|
+
if (!dropdownRef.current)
|
|
1838
|
+
return [];
|
|
1839
|
+
return Array.from(dropdownRef.current.querySelectorAll('[role="menuitem"]')).filter(el => !el.hasAttribute('disabled') &&
|
|
1840
|
+
el.getAttribute('aria-disabled') !== 'true');
|
|
1841
|
+
};
|
|
1842
|
+
// Focus the pending menu item once the menu becomes visible; the item is
|
|
1843
|
+
// unfocusable while `display: none` applies, so this must wait for the
|
|
1844
|
+
// `is-active` class to actually land in the DOM.
|
|
1845
|
+
React.useEffect(() => {
|
|
1846
|
+
if (!active || !pendingFocusRef.current)
|
|
1847
|
+
return;
|
|
1848
|
+
const items = getMenuItems();
|
|
1849
|
+
if (items.length) {
|
|
1850
|
+
const index = pendingFocusRef.current === 'first' ? 0 : items.length - 1;
|
|
1851
|
+
items[index].focus();
|
|
1852
|
+
}
|
|
1853
|
+
pendingFocusRef.current = null;
|
|
1854
|
+
}, [active]);
|
|
1855
|
+
const handleTriggerKeyDown = (e) => {
|
|
1856
|
+
if (disabled)
|
|
1857
|
+
return;
|
|
1858
|
+
switch (e.key) {
|
|
1859
|
+
case 'ArrowDown':
|
|
1860
|
+
e.preventDefault();
|
|
1861
|
+
pendingFocusRef.current = 'first';
|
|
1862
|
+
if (!active) {
|
|
1863
|
+
setActive(true);
|
|
1864
|
+
onActiveChange?.(true);
|
|
1865
|
+
}
|
|
1866
|
+
else {
|
|
1867
|
+
const items = getMenuItems();
|
|
1868
|
+
if (items.length)
|
|
1869
|
+
items[0].focus();
|
|
1870
|
+
pendingFocusRef.current = null;
|
|
1871
|
+
}
|
|
1872
|
+
break;
|
|
1873
|
+
case 'ArrowUp':
|
|
1874
|
+
e.preventDefault();
|
|
1875
|
+
pendingFocusRef.current = 'last';
|
|
1876
|
+
if (!active) {
|
|
1877
|
+
setActive(true);
|
|
1878
|
+
onActiveChange?.(true);
|
|
1879
|
+
}
|
|
1880
|
+
else {
|
|
1881
|
+
const items = getMenuItems();
|
|
1882
|
+
if (items.length)
|
|
1883
|
+
items[items.length - 1].focus();
|
|
1884
|
+
pendingFocusRef.current = null;
|
|
1885
|
+
}
|
|
1886
|
+
break;
|
|
1887
|
+
case 'Enter':
|
|
1888
|
+
case ' ':
|
|
1889
|
+
e.preventDefault();
|
|
1890
|
+
if (!active) {
|
|
1891
|
+
pendingFocusRef.current = 'first';
|
|
1892
|
+
setActive(true);
|
|
1893
|
+
onActiveChange?.(true);
|
|
1894
|
+
}
|
|
1895
|
+
else {
|
|
1896
|
+
setActive(false);
|
|
1897
|
+
onActiveChange?.(false);
|
|
1898
|
+
}
|
|
1899
|
+
break;
|
|
1900
|
+
case 'Escape':
|
|
1901
|
+
if (active) {
|
|
1902
|
+
e.preventDefault();
|
|
1903
|
+
setActive(false);
|
|
1904
|
+
onActiveChange?.(false);
|
|
1905
|
+
}
|
|
1906
|
+
break;
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1909
|
+
const handleMenuKeyDown = (e) => {
|
|
1910
|
+
// Escape and Tab close the menu regardless of whether it has any focusable
|
|
1911
|
+
// items — an empty or all-disabled menu must still honor the close contract.
|
|
1912
|
+
if (e.key === 'Escape') {
|
|
1913
|
+
e.preventDefault();
|
|
1914
|
+
setActive(false);
|
|
1915
|
+
onActiveChange?.(false);
|
|
1916
|
+
triggerRef.current?.focus();
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
if (e.key === 'Tab') {
|
|
1920
|
+
setActive(false);
|
|
1921
|
+
onActiveChange?.(false);
|
|
1922
|
+
return;
|
|
1923
|
+
}
|
|
1924
|
+
const items = getMenuItems();
|
|
1925
|
+
if (!items.length)
|
|
1926
|
+
return;
|
|
1927
|
+
const currentIndex = items.indexOf(document.activeElement);
|
|
1928
|
+
switch (e.key) {
|
|
1929
|
+
case 'ArrowDown': {
|
|
1930
|
+
e.preventDefault();
|
|
1931
|
+
const next = currentIndex >= 0 ? (currentIndex + 1) % items.length : 0;
|
|
1932
|
+
items[next].focus();
|
|
1933
|
+
break;
|
|
1934
|
+
}
|
|
1935
|
+
case 'ArrowUp': {
|
|
1936
|
+
e.preventDefault();
|
|
1937
|
+
const prev = currentIndex >= 0
|
|
1938
|
+
? (currentIndex - 1 + items.length) % items.length
|
|
1939
|
+
: items.length - 1;
|
|
1940
|
+
items[prev].focus();
|
|
1941
|
+
break;
|
|
1942
|
+
}
|
|
1943
|
+
case 'Home':
|
|
1944
|
+
e.preventDefault();
|
|
1945
|
+
items[0].focus();
|
|
1946
|
+
break;
|
|
1947
|
+
case 'End':
|
|
1948
|
+
e.preventDefault();
|
|
1949
|
+
items[items.length - 1].focus();
|
|
1950
|
+
break;
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
1760
1953
|
const dropdownClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
|
|
1761
|
-
return (jsxRuntime.jsxs("div", { className: dropdownClasses, ref: dropdownRef, id: id, "data-testid": "dropdown-root", ...rest, children: [jsxRuntime.jsx("div", { className: usePrefixedClassNames('dropdown-trigger'), children: jsxRuntime.jsxs("button", { className: buttonClass, "aria-haspopup": "true", "aria-controls": id ? `${id}-menu` : undefined, "aria-expanded": active, onClick: handleToggle, disabled: disabled, type: "button", children: [jsxRuntime.jsx("span", { children: label }), jsxRuntime.jsx("span", { className: usePrefixedClassNames('icon', 'is-small'), "aria-hidden": "true", children: jsxRuntime.jsx("i", { className: "fas fa-angle-down" }) })] }) }), jsxRuntime.jsx("div", { className: classNames(usePrefixedClassNames('dropdown-menu'), menuClassName), id: id ? `${id}-menu` : undefined, role: "menu", "data-testid": "dropdown-menu", children: jsxRuntime.jsx("div", { className: usePrefixedClassNames('dropdown-content'), onClick: handleMenuClick, tabIndex: -1, children: children }) })] }));
|
|
1954
|
+
return (jsxRuntime.jsxs("div", { className: dropdownClasses, ref: dropdownRef, id: id, "data-testid": "dropdown-root", ...rest, children: [jsxRuntime.jsx("div", { className: usePrefixedClassNames('dropdown-trigger'), children: jsxRuntime.jsxs("button", { ref: triggerRef, className: buttonClass, "aria-haspopup": "true", "aria-controls": id ? `${id}-menu` : undefined, "aria-expanded": active, onClick: handleToggle, onKeyDown: handleTriggerKeyDown, disabled: disabled, type: "button", children: [jsxRuntime.jsx("span", { children: label }), jsxRuntime.jsx("span", { className: usePrefixedClassNames('icon', 'is-small'), "aria-hidden": "true", children: jsxRuntime.jsx("i", { className: "fas fa-angle-down" }) })] }) }), jsxRuntime.jsx("div", { className: classNames(usePrefixedClassNames('dropdown-menu'), menuClassName), id: id ? `${id}-menu` : undefined, role: "menu", "data-testid": "dropdown-menu", onKeyDown: handleMenuKeyDown, children: jsxRuntime.jsx("div", { className: usePrefixedClassNames('dropdown-content'), onClick: handleMenuClick, tabIndex: -1, children: children }) })] }));
|
|
1762
1955
|
};
|
|
1763
1956
|
/**
|
|
1764
1957
|
* Bulma Dropdown item.
|
|
@@ -1868,6 +2061,7 @@ const Menu = withSubComponents(MenuComponent, {
|
|
|
1868
2061
|
Item: MenuItem,
|
|
1869
2062
|
}, 'Menu');
|
|
1870
2063
|
|
|
2064
|
+
const validMessageSizes = ['small', 'medium', 'large'];
|
|
1871
2065
|
/**
|
|
1872
2066
|
* The `Message` component provides Bulma's flexible notice/message box for your Bulma React UI.
|
|
1873
2067
|
*
|
|
@@ -1876,7 +2070,7 @@ const Menu = withSubComponents(MenuComponent, {
|
|
|
1876
2070
|
* @returns {JSX.Element} The rendered message.
|
|
1877
2071
|
* @see {@link https://bulma.io/documentation/components/message/ | Bulma Message documentation}
|
|
1878
2072
|
*/
|
|
1879
|
-
const MessageComponent = ({ className, title, textColor, color, bgColor, onClose, children, ...props }) => {
|
|
2073
|
+
const MessageComponent = ({ className, title, textColor, color, bgColor, size, onClose, children, ...props }) => {
|
|
1880
2074
|
const { classPrefix } = useConfig();
|
|
1881
2075
|
const { bulmaHelperClasses, rest } = useBulmaClasses({
|
|
1882
2076
|
color: textColor,
|
|
@@ -1886,6 +2080,7 @@ const MessageComponent = ({ className, title, textColor, color, bgColor, onClose
|
|
|
1886
2080
|
// Generate Bulma classes with prefix
|
|
1887
2081
|
const bulmaClasses = usePrefixedClassNames('message', {
|
|
1888
2082
|
[`is-${color}`]: color,
|
|
2083
|
+
[`is-${size}`]: size && validMessageSizes.includes(size),
|
|
1889
2084
|
});
|
|
1890
2085
|
const deleteClass = usePrefixedClassNames('delete');
|
|
1891
2086
|
const messageClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
|
|
@@ -2085,6 +2280,7 @@ const Modal = withSubComponents(ModalRoot, {
|
|
|
2085
2280
|
Close: ModalClose,
|
|
2086
2281
|
}, 'Modal');
|
|
2087
2282
|
|
|
2283
|
+
const NavbarDropdownContext = React.createContext(null);
|
|
2088
2284
|
/**
|
|
2089
2285
|
* The `Navbar` component implements Bulma's powerful, responsive navigation bar for your Bulma React UI.
|
|
2090
2286
|
*
|
|
@@ -2208,9 +2404,45 @@ const NavbarLink = ({ className, as: Component = 'a', arrowless, textColor, bgCo
|
|
|
2208
2404
|
backgroundColor: bgColor,
|
|
2209
2405
|
...props,
|
|
2210
2406
|
});
|
|
2407
|
+
const dropdownContext = React.useContext(NavbarDropdownContext);
|
|
2408
|
+
const hasHref = rest.href !== undefined;
|
|
2409
|
+
const isNativeInteractive = Component === 'button' || hasHref;
|
|
2410
|
+
const handleKeyDown = (e) => {
|
|
2411
|
+
rest.onKeyDown?.(e);
|
|
2412
|
+
if (!dropdownContext || e.defaultPrevented)
|
|
2413
|
+
return;
|
|
2414
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
2415
|
+
e.preventDefault();
|
|
2416
|
+
dropdownContext.toggle();
|
|
2417
|
+
}
|
|
2418
|
+
else if (e.key === 'Escape' && dropdownContext.active) {
|
|
2419
|
+
e.preventDefault();
|
|
2420
|
+
dropdownContext.close();
|
|
2421
|
+
}
|
|
2422
|
+
};
|
|
2423
|
+
// When the link is not natively interactive (no `href`, not a `<button>`) it
|
|
2424
|
+
// renders as `role="button"`, so a mouse/touch click has no default action to
|
|
2425
|
+
// open the dropdown. Compose the caller's handler and toggle the dropdown
|
|
2426
|
+
// unless the caller prevented the default. Native links/buttons keep their own
|
|
2427
|
+
// click semantics (navigation / the caller's handler).
|
|
2428
|
+
const handleClick = (e) => {
|
|
2429
|
+
rest.onClick?.(e);
|
|
2430
|
+
if (!dropdownContext || isNativeInteractive || e.defaultPrevented)
|
|
2431
|
+
return;
|
|
2432
|
+
dropdownContext.toggle();
|
|
2433
|
+
};
|
|
2211
2434
|
return (jsxRuntime.jsx(Component, { className: classNames(usePrefixedClassNames('navbar-link', {
|
|
2212
2435
|
'is-arrowless': arrowless,
|
|
2213
|
-
}), bulmaHelperClasses, className), ...rest,
|
|
2436
|
+
}), bulmaHelperClasses, className), ...rest, ...(dropdownContext && {
|
|
2437
|
+
'aria-haspopup': 'true',
|
|
2438
|
+
'aria-expanded': dropdownContext.active,
|
|
2439
|
+
onKeyDown: handleKeyDown,
|
|
2440
|
+
...(!isNativeInteractive && {
|
|
2441
|
+
role: 'button',
|
|
2442
|
+
tabIndex: 0,
|
|
2443
|
+
onClick: handleClick,
|
|
2444
|
+
}),
|
|
2445
|
+
}), children: children }));
|
|
2214
2446
|
};
|
|
2215
2447
|
/**
|
|
2216
2448
|
* Dropdown parent (with options for hover, up, right, active)
|
|
@@ -2219,12 +2451,34 @@ const NavbarLink = ({ className, as: Component = 'a', arrowless, textColor, bgCo
|
|
|
2219
2451
|
* @param {NavbarDropdownProps} props - Props for the NavbarDropdown component.
|
|
2220
2452
|
* @returns {JSX.Element} The rendered dropdown.
|
|
2221
2453
|
*/
|
|
2222
|
-
const NavbarDropdown = ({ className, right, up, hoverable, active, children, ...props }) =>
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
'
|
|
2227
|
-
|
|
2454
|
+
const NavbarDropdown = ({ className, right, up, hoverable, active: activeProp, onActiveChange, children, ...props }) => {
|
|
2455
|
+
const [active, setActive] = React.useState(!!activeProp);
|
|
2456
|
+
React.useEffect(() => {
|
|
2457
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect -- syncing to controlled prop
|
|
2458
|
+
if (typeof activeProp === 'boolean')
|
|
2459
|
+
setActive(activeProp);
|
|
2460
|
+
}, [activeProp]);
|
|
2461
|
+
// Keep `onActiveChange` out of the state updater (a pure function) so Strict
|
|
2462
|
+
// Mode's double-invoked updaters don't double-fire it — mirrors `Dropdown`.
|
|
2463
|
+
const toggle = () => {
|
|
2464
|
+
const next = !active;
|
|
2465
|
+
setActive(next);
|
|
2466
|
+
onActiveChange?.(next);
|
|
2467
|
+
};
|
|
2468
|
+
const close = () => {
|
|
2469
|
+
/* istanbul ignore next: close() is only invoked once already active */
|
|
2470
|
+
if (!active)
|
|
2471
|
+
return;
|
|
2472
|
+
setActive(false);
|
|
2473
|
+
onActiveChange?.(false);
|
|
2474
|
+
};
|
|
2475
|
+
return (jsxRuntime.jsx(NavbarDropdownContext.Provider, { value: { active, toggle, close }, children: jsxRuntime.jsx("div", { className: classNames(usePrefixedClassNames('navbar-item', 'has-dropdown', {
|
|
2476
|
+
'has-dropdown-up': up,
|
|
2477
|
+
'is-right': right,
|
|
2478
|
+
'is-hoverable': hoverable,
|
|
2479
|
+
'is-active': active,
|
|
2480
|
+
}), className), ...props, children: children }) }));
|
|
2481
|
+
};
|
|
2228
2482
|
/**
|
|
2229
2483
|
* Dropdown menu container
|
|
2230
2484
|
*
|
|
@@ -4684,6 +4938,7 @@ const LinkButton = ({ variant = 'text', color, className, ...props }) => {
|
|
|
4684
4938
|
return (jsxRuntime.jsx(Button, { color: buttonColor, className: classNames(prefixedClasses, className), ...props }));
|
|
4685
4939
|
};
|
|
4686
4940
|
|
|
4941
|
+
const validButtonsSizes = ['small', 'medium', 'large'];
|
|
4687
4942
|
/**
|
|
4688
4943
|
* The `Buttons` component lets you group multiple `Button` elements together with Bulma's spacing, alignment, and add-on features.
|
|
4689
4944
|
*
|
|
@@ -4692,11 +4947,12 @@ const LinkButton = ({ variant = 'text', color, className, ...props }) => {
|
|
|
4692
4947
|
* @returns {JSX.Element} The rendered group of buttons.
|
|
4693
4948
|
* @see {@link https://bulma.io/documentation/elements/button/#group | Bulma Button Group documentation}
|
|
4694
4949
|
*/
|
|
4695
|
-
const ButtonsComponent = ({ className, textColor, color, bgColor, isCentered, isRight, hasAddons, children, ...props }) => {
|
|
4950
|
+
const ButtonsComponent = ({ className, textColor, color, bgColor, isCentered, isRight, hasAddons, size, children, ...props }) => {
|
|
4696
4951
|
const buttonsClasses = usePrefixedClassNames('buttons', {
|
|
4697
4952
|
'is-centered': isCentered,
|
|
4698
4953
|
'is-right': isRight,
|
|
4699
4954
|
'has-addons': hasAddons,
|
|
4955
|
+
[`are-${size}`]: size && validButtonsSizes.includes(size),
|
|
4700
4956
|
});
|
|
4701
4957
|
/**
|
|
4702
4958
|
* Generates Bulma helper classes and separates out remaining props.
|
|
@@ -5595,22 +5851,25 @@ const Tag = ({ className, color, size, isLight, isRounded, isDelete, isHoverable
|
|
|
5595
5851
|
return (jsxRuntime.jsx("span", { className: tagClasses, ...rest, children: children }));
|
|
5596
5852
|
};
|
|
5597
5853
|
|
|
5854
|
+
const validTagsSizes = ['medium', 'large'];
|
|
5598
5855
|
/**
|
|
5599
|
-
* The `Tags` component groups multiple `Tag` components together in a
|
|
5856
|
+
* The `Tags` component groups multiple `Tag` components together in a Bulma-styled container that wraps onto multiple lines by default.
|
|
5600
5857
|
*
|
|
5601
5858
|
* @function
|
|
5602
5859
|
* @param {TagsProps} props - Props for the Tags component.
|
|
5603
5860
|
* @returns {JSX.Element} The rendered tags container.
|
|
5604
5861
|
* @see {@link https://bulma.io/documentation/elements/tag/#list-of-tags | Bulma Tags documentation}
|
|
5605
5862
|
*/
|
|
5606
|
-
const TagsComponent = ({ className, hasAddons,
|
|
5863
|
+
const TagsComponent = ({ className, hasAddons,
|
|
5864
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- accepted for backwards compatibility, deprecated no-op (no `are-multiline` CSS ships)
|
|
5865
|
+
isMultiline, size, children, ...props }) => {
|
|
5607
5866
|
/**
|
|
5608
5867
|
* Generates Bulma helper classes and separates out remaining props.
|
|
5609
5868
|
*/
|
|
5610
5869
|
const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });
|
|
5611
5870
|
const bulmaClasses = usePrefixedClassNames('tags', {
|
|
5612
5871
|
'has-addons': hasAddons,
|
|
5613
|
-
|
|
5872
|
+
[`are-${size}`]: size && validTagsSizes.includes(size),
|
|
5614
5873
|
});
|
|
5615
5874
|
const tagsClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
|
|
5616
5875
|
return (jsxRuntime.jsx("div", { className: tagsClasses, ...rest, children: children }));
|