@allxsmith/bestax-bulma 5.58.0 → 5.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Affix.js +46 -0
  4. package/dist/esm/components/Affix.js.map +1 -0
  5. package/dist/esm/components/Dialog.js +2 -6
  6. package/dist/esm/components/Dialog.js.map +1 -1
  7. package/dist/esm/components/Modal.js +12 -24
  8. package/dist/esm/components/Modal.js.map +1 -1
  9. package/dist/esm/elements/Buttons.js +2 -0
  10. package/dist/esm/elements/Buttons.js.map +1 -1
  11. package/dist/esm/elements/IconButton.js +114 -0
  12. package/dist/esm/elements/IconButton.js.map +1 -0
  13. package/dist/esm/helpers/containerBreakpoints.js +14 -0
  14. package/dist/esm/helpers/containerBreakpoints.js.map +1 -0
  15. package/dist/esm/helpers/polymorphic.js.map +1 -1
  16. package/dist/esm/helpers/portal.js +28 -1
  17. package/dist/esm/helpers/portal.js.map +1 -1
  18. package/dist/esm/helpers/stackLayout.js +30 -0
  19. package/dist/esm/helpers/stackLayout.js.map +1 -0
  20. package/dist/esm/helpers/useBulmaClasses.js +8 -2
  21. package/dist/esm/helpers/useBulmaClasses.js.map +1 -1
  22. package/dist/esm/helpers/useFlexboxClasses.js +17 -4
  23. package/dist/esm/helpers/useFlexboxClasses.js.map +1 -1
  24. package/dist/esm/layout/Center.js +33 -0
  25. package/dist/esm/layout/Center.js.map +1 -0
  26. package/dist/esm/layout/Container.js +2 -6
  27. package/dist/esm/layout/Container.js.map +1 -1
  28. package/dist/esm/layout/Flex.js +34 -0
  29. package/dist/esm/layout/Flex.js.map +1 -0
  30. package/dist/esm/layout/Group.js +43 -0
  31. package/dist/esm/layout/Group.js.map +1 -0
  32. package/dist/esm/layout/Stack.js +34 -0
  33. package/dist/esm/layout/Stack.js.map +1 -0
  34. package/dist/extras.css +1 -1
  35. package/dist/extras.css.map +1 -1
  36. package/dist/index.cjs +476 -160
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.esm.js +6 -0
  39. package/dist/index.esm.js.map +1 -1
  40. package/dist/types/components/Affix.d.ts +67 -0
  41. package/dist/types/elements/Buttons.d.ts +1 -0
  42. package/dist/types/elements/IconButton.d.ts +110 -0
  43. package/dist/types/helpers/containerBreakpoints.d.ts +2 -0
  44. package/dist/types/helpers/polymorphic.d.ts +19 -0
  45. package/dist/types/helpers/portal.d.ts +42 -0
  46. package/dist/types/helpers/stackLayout.d.ts +62 -0
  47. package/dist/types/helpers/useBulmaClasses.d.ts +8 -2
  48. package/dist/types/helpers/useFlexboxClasses.d.ts +26 -3
  49. package/dist/types/index.d.ts +8 -1
  50. package/dist/types/layout/Center.d.ts +54 -0
  51. package/dist/types/layout/Flex.d.ts +92 -0
  52. package/dist/types/layout/Group.d.ts +86 -0
  53. package/dist/types/layout/Stack.d.ts +63 -0
  54. package/dist/types-cjs/components/Affix.d.ts +67 -0
  55. package/dist/types-cjs/elements/Buttons.d.ts +1 -0
  56. package/dist/types-cjs/elements/IconButton.d.ts +110 -0
  57. package/dist/types-cjs/helpers/containerBreakpoints.d.ts +2 -0
  58. package/dist/types-cjs/helpers/polymorphic.d.ts +19 -0
  59. package/dist/types-cjs/helpers/portal.d.ts +42 -0
  60. package/dist/types-cjs/helpers/stackLayout.d.ts +62 -0
  61. package/dist/types-cjs/helpers/useBulmaClasses.d.ts +8 -2
  62. package/dist/types-cjs/helpers/useFlexboxClasses.d.ts +26 -3
  63. package/dist/types-cjs/index.d.ts +8 -1
  64. package/dist/types-cjs/layout/Center.d.ts +54 -0
  65. package/dist/types-cjs/layout/Flex.d.ts +92 -0
  66. package/dist/types-cjs/layout/Group.d.ts +86 -0
  67. package/dist/types-cjs/layout/Stack.d.ts +63 -0
  68. package/dist/versions/bestax-no-dark-mode.css +1 -1
  69. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  70. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  71. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  72. package/dist/versions/bestax-no-helpers.css +1 -1
  73. package/dist/versions/bestax-no-helpers.css.map +1 -1
  74. package/dist/versions/bestax-prefixed.css +1 -1
  75. package/dist/versions/bestax-prefixed.css.map +1 -1
  76. package/package.json +1 -1
  77. package/src/scss/components/_affix.scss +74 -0
  78. package/src/scss/components/_index.scss +1 -0
  79. package/src/scss/elements/_iconbutton.scss +36 -0
  80. package/src/scss/elements/_index.scss +1 -0
  81. package/src/scss/layout/_index.scss +1 -0
  82. package/src/scss/layout/_stack.scss +145 -0
package/dist/index.cjs CHANGED
@@ -970,8 +970,9 @@ const useVisibilityClasses = (props) => {
970
970
  /**
971
971
  * A hook that generates Bulma flexbox helper classes. Flex container helpers
972
972
  * (direction, wrap, justify/align content, align items) are only emitted when
973
- * one of the display props indicates a flex display; flex item helpers
974
- * (align self, grow, shrink) are always emitted.
973
+ * one of the display props indicates a flex display, or when `options` says
974
+ * the element is a flex container by its own CSS; flex item helpers (align
975
+ * self, grow, shrink) are always emitted.
975
976
  *
976
977
  * Note: this hook reads the display props purely as a gate and never emits
977
978
  * display classes — `is-flex` and friends come from useVisibilityClasses (or
@@ -979,6 +980,7 @@ const useVisibilityClasses = (props) => {
979
980
  *
980
981
  * @function useFlexboxClasses
981
982
  * @param props - Flexbox-related Bulma helper props.
983
+ * @param options - Whether the element is a flex container without a display prop.
982
984
  * @returns A space-separated string of flexbox helper classes.
983
985
  * @example
984
986
  * const flexboxClasses = useFlexboxClasses({
@@ -987,14 +989,24 @@ const useVisibilityClasses = (props) => {
987
989
  * });
988
990
  * // flexboxClasses: 'is-justify-content-center'
989
991
  * // ('is-flex' itself comes from useVisibilityClasses/useBulmaClasses)
990
- */
991
- const useFlexboxClasses = (props) => {
992
+ *
993
+ * @example
994
+ * // An element whose own stylesheet makes it a flex container
995
+ * const flexboxClasses = useFlexboxClasses(
996
+ * { alignItems: 'center' },
997
+ * { flexContainer: true }
998
+ * );
999
+ * // flexboxClasses: 'is-align-items-center'
1000
+ */
1001
+ const useFlexboxClasses = (props, options = {}) => {
992
1002
  const { classPrefix } = useConfig();
1003
+ const { flexContainer = false } = options;
993
1004
  const { flexDirection, flexWrap, justifyContent, alignContent, alignItems, alignSelf, flexGrow, flexShrink, display, displayMobile, displayTablet, displayTabletOnly, displayTouch, displayDesktop, displayDesktopOnly, displayWidescreen, displayWidescreenOnly, displayFullhd, } = props;
994
1005
  return React.useMemo(() => {
995
1006
  const { classes, addClassNoViewport } = createBulmaClassHelpers(classPrefix);
996
1007
  // Flexbox
997
- const hasFlexDisplay = display === 'flex' ||
1008
+ const hasFlexDisplay = flexContainer ||
1009
+ display === 'flex' ||
998
1010
  display === 'inline-flex' ||
999
1011
  displayMobile === 'flex' ||
1000
1012
  displayMobile === 'inline-flex' ||
@@ -1030,6 +1042,7 @@ const useFlexboxClasses = (props) => {
1030
1042
  return classNames(classes);
1031
1043
  }, [
1032
1044
  classPrefix,
1045
+ flexContainer,
1033
1046
  flexDirection,
1034
1047
  flexWrap,
1035
1048
  justifyContent,
@@ -1170,8 +1183,14 @@ const useOtherClasses = (props) => {
1170
1183
  * `background-color: var(--bulma-scheme-*)` style (`undefined` for all other
1171
1184
  * inputs). Merge it with a user `style` prop via `mergeBulmaStyles`.
1172
1185
  *
1186
+ * The flex container props (`flexDirection`, `flexWrap`, `justifyContent`,
1187
+ * `alignContent`, `alignItems`) emit a class only on a flex container: when a
1188
+ * `display` prop is `flex` or `inline-flex`, or when `options.flexContainer`
1189
+ * says the element's own stylesheet makes it one.
1190
+ *
1173
1191
  * @function useBulmaClasses
1174
1192
  * @param props - Combination of BulmaClassesPropsWithScheme and additional props.
1193
+ * @param options - Passed to `useFlexboxClasses`: whether the element is a flex container without a display prop.
1175
1194
  * @returns An object containing the Bulma helper classes, optional helper
1176
1195
  * styles, and unhandled props.
1177
1196
  * @example
@@ -1184,7 +1203,7 @@ const useOtherClasses = (props) => {
1184
1203
  * // bulmaHelperStyles: { backgroundColor: 'var(--bulma-scheme-main-bis)' }
1185
1204
  * // rest: { className: 'custom-class' }
1186
1205
  */
1187
- const useBulmaClasses = (props) => {
1206
+ const useBulmaClasses = (props, options) => {
1188
1207
  const { color, backgroundColor, colorShade, backgroundColorShade, m, mt, mr, mb, ml, mx, my, p, pt, pr, pb, pl, px, py, gap, columnGap, rowGap, gapless, 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;
1189
1208
  const colorClasses = useColorClasses({
1190
1209
  color,
@@ -1273,7 +1292,7 @@ const useBulmaClasses = (props) => {
1273
1292
  displayWidescreen,
1274
1293
  displayWidescreenOnly,
1275
1294
  displayFullhd,
1276
- });
1295
+ }, options);
1277
1296
  const otherClasses = useOtherClasses({
1278
1297
  float,
1279
1298
  overflow,
@@ -3570,129 +3589,6 @@ const Button = React.forwardRef(function Button(props, ref) {
3570
3589
  });
3571
3590
  Button.displayName = 'Button';
3572
3591
 
3573
- /**
3574
- * The `LinkButton` component renders a `<button>` that visually looks like text or a link.
3575
- *
3576
- * @function
3577
- * @param {LinkButtonProps} props - Props for the LinkButton component.
3578
- * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
3579
- * @returns {JSX.Element} The rendered link-styled button element.
3580
- *
3581
- * @example
3582
- * // Text variant (default)
3583
- * <LinkButton onClick={handleClick}>Click me</LinkButton>
3584
- *
3585
- * @example
3586
- * // Underline variant with color
3587
- * <LinkButton variant="underline" color="primary">Learn more</LinkButton>
3588
- */
3589
- const LinkButton = React.forwardRef(function LinkButton({ variant = 'text', color, className, ...props }, ref) {
3590
- const buttonColor = variant === 'underline' ? 'text' : variant;
3591
- const prefixedClasses = usePrefixedClassNames('link-button', color && `link-button-${color}`, variant === 'underline' && 'link-button-underline');
3592
- return (jsxRuntime.jsx(Button
3593
- // LinkButton is polymorphic through to Button, which resolves the element
3594
- // from `as`. TS cannot infer that through the spread below.
3595
- , {
3596
- // LinkButton is polymorphic through to Button, which resolves the element
3597
- // from `as`. TS cannot infer that through the spread below.
3598
- ref: ref, color: buttonColor, className: classNames(prefixedClasses, className), ...props }));
3599
- });
3600
- LinkButton.displayName = 'LinkButton';
3601
-
3602
- /**
3603
- * The `ToggleButton` component renders a button that stays pressed until it's pressed again, and says whether it's on through `aria-pressed`.
3604
- *
3605
- * It's always a `<button type="button">`, so it never submits a form and
3606
- * carries no form value: a setting saved with a form is a `Checkbox` or a
3607
- * `Switch`. A set of toggles that each turn on and off on their own goes in
3608
- * `Buttons hasAddons` with `role="group"` and an `aria-label`. A set where only
3609
- * one can be on is a radio group rather than a row of these: use
3610
- * `SegmentedControl`, or `Radios` for a choice that's sent with a form.
3611
- *
3612
- * @function
3613
- * @param {ToggleButtonProps} props - Props for the ToggleButton component.
3614
- * @param {React.Ref<HTMLButtonElement>} ref - Forwarded ref to the `<button>`.
3615
- * @returns {JSX.Element} The rendered toggle button.
3616
- * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/button/ | APG button pattern}
3617
- *
3618
- * @example
3619
- * <ToggleButton onPressedChange={setMuted}>Mute</ToggleButton>
3620
- *
3621
- * @example
3622
- * <Buttons hasAddons role="group" aria-label="Text style">
3623
- * <ToggleButton aria-label="Bold" pressed={bold} onPressedChange={setBold}>
3624
- * <Icon name="bold" />
3625
- * </ToggleButton>
3626
- * </Buttons>
3627
- */
3628
- const ToggleButton = React.forwardRef(function ToggleButton({ pressed: controlledPressed, defaultPressed = false, onPressedChange, color = 'link', isLoading, 'aria-busy': ariaBusy, 'aria-disabled': ariaDisabled, className, onClick, ...props }, ref) {
3629
- const isControlled = controlledPressed !== undefined;
3630
- const [internalPressed, setInternalPressed] = React.useState(defaultPressed);
3631
- const pressed = controlledPressed ?? internalPressed;
3632
- // Prefixed like Button's own classes, which a hand-written
3633
- // `className="is-selected"` could not be under ConfigProvider classPrefix.
3634
- // Bulma lifts `is-selected` above its neighbours in `.buttons.has-addons`.
3635
- const selectedClass = usePrefixedClassNames({ 'is-selected': pressed });
3636
- // The caller's onClick runs first, so a `preventDefault()` there vetoes
3637
- // the toggle, as it does in Radix, MUI and Zag. Enter and Space reach here
3638
- // through the button's own click, and a disabled button gets no click.
3639
- //
3640
- // A loading one gets the click but drops it. Bulma's spinner only stops a
3641
- // pointer, so without this a key flipped a toggle the mouse couldn't.
3642
- // `disabled` would stop both, but it takes focus away mid-save.
3643
- const handleClick = (event) => {
3644
- if (isLoading)
3645
- return;
3646
- onClick?.(event);
3647
- if (event.defaultPrevented)
3648
- return;
3649
- const next = !pressed;
3650
- onPressedChange?.(next);
3651
- if (!isControlled)
3652
- setInternalPressed(next);
3653
- };
3654
- // The props are spread first, so what a toggle depends on wins over
3655
- // anything a JavaScript caller or a spread object passes along: it stays
3656
- // a button, never submits, reports the state it's in, and says it's busy
3657
- // and won't respond while it's loading. A caller's own `aria-busy` or
3658
- // `aria-disabled` stays when it isn't loading.
3659
- return (jsxRuntime.jsx(Button, { ...props, ref: ref, as: "button", type: "button", isLoading: isLoading, "aria-busy": isLoading || ariaBusy, "aria-disabled": isLoading || ariaDisabled, "aria-pressed": pressed, color: pressed ? color : undefined, className: classNames(selectedClass, className), onClick: handleClick }));
3660
- });
3661
- ToggleButton.displayName = 'ToggleButton';
3662
-
3663
- const validButtonsSizes = ['small', 'medium', 'large'];
3664
- /**
3665
- * The `Buttons` component lets you group multiple `Button` elements together with Bulma's spacing, alignment, and add-on features.
3666
- *
3667
- * @function
3668
- * @param {ButtonsProps} props - Props for the Buttons component.
3669
- * @returns {JSX.Element} The rendered group of buttons.
3670
- * @see {@link https://bulma.io/documentation/elements/button/#group | Bulma Button Group documentation}
3671
- */
3672
- const ButtonsComponent = ({ className, textColor, color, bgColor, isCentered, isRight, hasAddons, size, children, ...props }) => {
3673
- const buttonsClasses = usePrefixedClassNames('buttons', {
3674
- 'is-centered': isCentered,
3675
- 'is-right': isRight,
3676
- 'has-addons': hasAddons,
3677
- [`are-${size}`]: size && validButtonsSizes.includes(size),
3678
- });
3679
- /**
3680
- * Generates Bulma helper classes and separates out remaining props.
3681
- */
3682
- const { bulmaHelperClasses, rest } = useBulmaClasses({
3683
- color: textColor ?? color,
3684
- backgroundColor: bgColor,
3685
- ...props,
3686
- });
3687
- const combinedClasses = classNames(buttonsClasses, className, bulmaHelperClasses);
3688
- return (jsxRuntime.jsx("div", { className: combinedClasses, ...rest, children: children }));
3689
- };
3690
- const Buttons = withSubComponents(ButtonsComponent, {
3691
- Button,
3692
- LinkButton,
3693
- ToggleButton,
3694
- }, 'Buttons');
3695
-
3696
3592
  /**
3697
3593
  * Strips a redundant leading library prefix from an icon name (e.g. `fa-check` -> `check`
3698
3594
  * for the `fa` library, `mdi-account` -> `account` for `mdi`), so `name` behaves the same
@@ -3940,6 +3836,231 @@ color, containerClassName, children, ...restProps }) => {
3940
3836
  return (jsxRuntime.jsx("span", { className: iconContainerClasses, ...a11yProps, style: style, ...rest, children: jsxRuntime.jsx("i", { className: iClasses }) }));
3941
3837
  };
3942
3838
 
3839
+ /** Whether a string has something in it besides spaces. */
3840
+ const hasText = (value) => typeof value === 'string' && value.trim() !== '';
3841
+ /** Whether a string is only spaces, which JSX leaves between elements. */
3842
+ const isBlank = (node) => typeof node === 'string' && node.trim() === '';
3843
+ /**
3844
+ * The glyph in one `.icon`, which is what Bulma keeps square: an `<Icon>` as
3845
+ * given, Fragments opened up and blank text left out, and anything else
3846
+ * inside an `Icon`. Null when there's nothing to draw, so an empty Fragment
3847
+ * or array counts as no glyph.
3848
+ */
3849
+ function iconOf(node) {
3850
+ const items = flattenChildren(node).filter(item => !isBlank(item));
3851
+ if (items.length === 0)
3852
+ return null;
3853
+ const [only] = items;
3854
+ if (items.length === 1 && React.isValidElement(only) && only.type === Icon) {
3855
+ return only;
3856
+ }
3857
+ return jsxRuntime.jsx(Icon, { children: items });
3858
+ }
3859
+ /** The glyph `icon` draws: a string is an `Icon` name, the rest as `iconOf`. */
3860
+ function iconFromProp(icon) {
3861
+ if (typeof icon !== 'string')
3862
+ return iconOf(icon);
3863
+ return hasText(icon) ? jsxRuntime.jsx(Icon, { name: icon }) : null;
3864
+ }
3865
+ /**
3866
+ * The `IconButton` component renders a button that shows only an icon, and requires a name for it.
3867
+ *
3868
+ * It renders through `Button`, so it takes everything `Button` takes, and
3869
+ * adds the icon and a name the types require: `aria-label`, or
3870
+ * `aria-labelledby` in its place. Bulma keeps a button whose only child is an
3871
+ * `.icon` square at every size, and `isRounded` makes it a circle. It has no
3872
+ * tooltip of its own: wrap it in `Tooltip` for a description.
3873
+ *
3874
+ * @function
3875
+ * @param {IconButtonProps} props - Props for the IconButton component.
3876
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
3877
+ * @returns {JSX.Element} The rendered button, anchor, or custom element.
3878
+ * @see {@link https://bulma.io/documentation/elements/button/ | Bulma Button documentation}
3879
+ *
3880
+ * @example
3881
+ * <IconButton icon="trash" aria-label="Delete" color="danger" />
3882
+ *
3883
+ * @example
3884
+ * <IconButton aria-label="Settings">
3885
+ * <Icon name="cog" />
3886
+ * </IconButton>
3887
+ */
3888
+ const IconButton = React.forwardRef(function IconButton(props, ref) {
3889
+ const { icon, children, className, ...rest } = props;
3890
+ const iconButtonClass = usePrefixedClassNames('icon-button');
3891
+ const unnamed = !hasText(rest['aria-label']) && !hasText(rest['aria-labelledby']);
3892
+ // Each way of giving the glyph counts only if it draws something, so an
3893
+ // empty Fragment or array as `icon` doesn't hide real children, and an
3894
+ // empty one as children doesn't warn.
3895
+ const fromIcon = iconFromProp(icon);
3896
+ const fromChildren = iconOf(children);
3897
+ const both = fromIcon !== null && fromChildren !== null;
3898
+ // One glyph, from `icon` or else from `children`, so the button's only
3899
+ // child is one `.icon`, which Bulma keeps square, and round with
3900
+ // `isRounded`.
3901
+ const glyph = fromIcon ?? fromChildren;
3902
+ const empty = glyph === null;
3903
+ // Only top-level text, Fragments opened up, and only in development, where
3904
+ // the warning below can say something about it.
3905
+ const textInside = isDev() &&
3906
+ flattenChildren(children).some(child => typeof child === 'number' || hasText(child));
3907
+ React.useEffect(() => {
3908
+ if (unnamed) {
3909
+ warnOnce('IconButton:unnamed', '[bestax-bulma] <IconButton> has no accessible name. Pass ' +
3910
+ 'aria-label naming what it does ("Delete"), or aria-labelledby, ' +
3911
+ 'so a screen reader has something to announce.');
3912
+ }
3913
+ if (empty) {
3914
+ warnOnce('IconButton:no-glyph', '[bestax-bulma] <IconButton> has no glyph: neither icon nor ' +
3915
+ 'children draws one, so it renders an empty square. Pass an icon ' +
3916
+ 'name, an <Icon> or another node.');
3917
+ }
3918
+ if (both) {
3919
+ warnOnce('IconButton:icon-and-children', '[bestax-bulma] <IconButton> was given both icon and children. It ' +
3920
+ 'draws icon and leaves the children out: give the glyph one way.');
3921
+ }
3922
+ if (textInside) {
3923
+ warnOnce('IconButton:text', '[bestax-bulma] <IconButton> was given text as children. Its ' +
3924
+ 'aria-label replaces the text as its name, so a button with text ' +
3925
+ 'is a <Button>.');
3926
+ }
3927
+ }, [unnamed, empty, both, textInside]);
3928
+ // `type` is a button's only on a `<button>`. On an `<a>` it's the MIME hint,
3929
+ // and a custom component owns what it means, so those get it as given.
3930
+ const tag = rest.as ?? 'button';
3931
+ const typeProp = tag === 'button' ? { type: buttonType(rest.type) } : undefined;
3932
+ return (jsxRuntime.jsx(Button
3933
+ // IconButton is polymorphic through to Button, which resolves the
3934
+ // element from `as`. TS can't infer that through the spread, so the
3935
+ // props and the ref are read at Button's default element.
3936
+ , { ...rest, ...typeProp, ref: ref, className: classNames(iconButtonClass, className), children: glyph }));
3937
+ });
3938
+ IconButton.displayName = 'IconButton';
3939
+
3940
+ /**
3941
+ * The `LinkButton` component renders a `<button>` that visually looks like text or a link.
3942
+ *
3943
+ * @function
3944
+ * @param {LinkButtonProps} props - Props for the LinkButton component.
3945
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
3946
+ * @returns {JSX.Element} The rendered link-styled button element.
3947
+ *
3948
+ * @example
3949
+ * // Text variant (default)
3950
+ * <LinkButton onClick={handleClick}>Click me</LinkButton>
3951
+ *
3952
+ * @example
3953
+ * // Underline variant with color
3954
+ * <LinkButton variant="underline" color="primary">Learn more</LinkButton>
3955
+ */
3956
+ const LinkButton = React.forwardRef(function LinkButton({ variant = 'text', color, className, ...props }, ref) {
3957
+ const buttonColor = variant === 'underline' ? 'text' : variant;
3958
+ const prefixedClasses = usePrefixedClassNames('link-button', color && `link-button-${color}`, variant === 'underline' && 'link-button-underline');
3959
+ return (jsxRuntime.jsx(Button
3960
+ // LinkButton is polymorphic through to Button, which resolves the element
3961
+ // from `as`. TS cannot infer that through the spread below.
3962
+ , {
3963
+ // LinkButton is polymorphic through to Button, which resolves the element
3964
+ // from `as`. TS cannot infer that through the spread below.
3965
+ ref: ref, color: buttonColor, className: classNames(prefixedClasses, className), ...props }));
3966
+ });
3967
+ LinkButton.displayName = 'LinkButton';
3968
+
3969
+ /**
3970
+ * The `ToggleButton` component renders a button that stays pressed until it's pressed again, and says whether it's on through `aria-pressed`.
3971
+ *
3972
+ * It's always a `<button type="button">`, so it never submits a form and
3973
+ * carries no form value: a setting saved with a form is a `Checkbox` or a
3974
+ * `Switch`. A set of toggles that each turn on and off on their own goes in
3975
+ * `Buttons hasAddons` with `role="group"` and an `aria-label`. A set where only
3976
+ * one can be on is a radio group rather than a row of these: use
3977
+ * `SegmentedControl`, or `Radios` for a choice that's sent with a form.
3978
+ *
3979
+ * @function
3980
+ * @param {ToggleButtonProps} props - Props for the ToggleButton component.
3981
+ * @param {React.Ref<HTMLButtonElement>} ref - Forwarded ref to the `<button>`.
3982
+ * @returns {JSX.Element} The rendered toggle button.
3983
+ * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/button/ | APG button pattern}
3984
+ *
3985
+ * @example
3986
+ * <ToggleButton onPressedChange={setMuted}>Mute</ToggleButton>
3987
+ *
3988
+ * @example
3989
+ * <Buttons hasAddons role="group" aria-label="Text style">
3990
+ * <ToggleButton aria-label="Bold" pressed={bold} onPressedChange={setBold}>
3991
+ * <Icon name="bold" />
3992
+ * </ToggleButton>
3993
+ * </Buttons>
3994
+ */
3995
+ const ToggleButton = React.forwardRef(function ToggleButton({ pressed: controlledPressed, defaultPressed = false, onPressedChange, color = 'link', isLoading, 'aria-busy': ariaBusy, 'aria-disabled': ariaDisabled, className, onClick, ...props }, ref) {
3996
+ const isControlled = controlledPressed !== undefined;
3997
+ const [internalPressed, setInternalPressed] = React.useState(defaultPressed);
3998
+ const pressed = controlledPressed ?? internalPressed;
3999
+ // Prefixed like Button's own classes, which a hand-written
4000
+ // `className="is-selected"` could not be under ConfigProvider classPrefix.
4001
+ // Bulma lifts `is-selected` above its neighbours in `.buttons.has-addons`.
4002
+ const selectedClass = usePrefixedClassNames({ 'is-selected': pressed });
4003
+ // The caller's onClick runs first, so a `preventDefault()` there vetoes
4004
+ // the toggle, as it does in Radix, MUI and Zag. Enter and Space reach here
4005
+ // through the button's own click, and a disabled button gets no click.
4006
+ //
4007
+ // A loading one gets the click but drops it. Bulma's spinner only stops a
4008
+ // pointer, so without this a key flipped a toggle the mouse couldn't.
4009
+ // `disabled` would stop both, but it takes focus away mid-save.
4010
+ const handleClick = (event) => {
4011
+ if (isLoading)
4012
+ return;
4013
+ onClick?.(event);
4014
+ if (event.defaultPrevented)
4015
+ return;
4016
+ const next = !pressed;
4017
+ onPressedChange?.(next);
4018
+ if (!isControlled)
4019
+ setInternalPressed(next);
4020
+ };
4021
+ // The props are spread first, so what a toggle depends on wins over
4022
+ // anything a JavaScript caller or a spread object passes along: it stays
4023
+ // a button, never submits, reports the state it's in, and says it's busy
4024
+ // and won't respond while it's loading. A caller's own `aria-busy` or
4025
+ // `aria-disabled` stays when it isn't loading.
4026
+ return (jsxRuntime.jsx(Button, { ...props, ref: ref, as: "button", type: "button", isLoading: isLoading, "aria-busy": isLoading || ariaBusy, "aria-disabled": isLoading || ariaDisabled, "aria-pressed": pressed, color: pressed ? color : undefined, className: classNames(selectedClass, className), onClick: handleClick }));
4027
+ });
4028
+ ToggleButton.displayName = 'ToggleButton';
4029
+
4030
+ const validButtonsSizes = ['small', 'medium', 'large'];
4031
+ /**
4032
+ * The `Buttons` component lets you group multiple `Button` elements together with Bulma's spacing, alignment, and add-on features.
4033
+ *
4034
+ * @function
4035
+ * @param {ButtonsProps} props - Props for the Buttons component.
4036
+ * @returns {JSX.Element} The rendered group of buttons.
4037
+ * @see {@link https://bulma.io/documentation/elements/button/#group | Bulma Button Group documentation}
4038
+ */
4039
+ const ButtonsComponent = ({ className, textColor, color, bgColor, isCentered, isRight, hasAddons, size, children, ...props }) => {
4040
+ const buttonsClasses = usePrefixedClassNames('buttons', {
4041
+ 'is-centered': isCentered,
4042
+ 'is-right': isRight,
4043
+ 'has-addons': hasAddons,
4044
+ [`are-${size}`]: size && validButtonsSizes.includes(size),
4045
+ });
4046
+ /**
4047
+ * Generates Bulma helper classes and separates out remaining props.
4048
+ */
4049
+ const { bulmaHelperClasses, rest } = useBulmaClasses({
4050
+ color: textColor ?? color,
4051
+ backgroundColor: bgColor,
4052
+ ...props,
4053
+ });
4054
+ const combinedClasses = classNames(buttonsClasses, className, bulmaHelperClasses);
4055
+ return (jsxRuntime.jsx("div", { className: combinedClasses, ...rest, children: children }));
4056
+ };
4057
+ const Buttons = withSubComponents(ButtonsComponent, {
4058
+ Button,
4059
+ LinkButton,
4060
+ ToggleButton,
4061
+ IconButton,
4062
+ }, 'Buttons');
4063
+
3943
4064
  /**
3944
4065
  * The `Paragraph` component renders a styled `<p>` element with Bulma helper class integration.
3945
4066
  *
@@ -4482,6 +4603,33 @@ function usePortalContainer() {
4482
4603
  const { portalContainer } = useConfig();
4483
4604
  return container => resolvePortalContainer(container || portalContainer);
4484
4605
  }
4606
+ /**
4607
+ * Reads Modal's `portal` prop (`boolean | string | HTMLElement`) for a
4608
+ * component that takes it: whether the content is in its portal yet, and
4609
+ * where it goes.
4610
+ *
4611
+ * A portal has no server-rendered counterpart, so such a component renders in
4612
+ * place on the server and while hydrating, and moves into its portal once the
4613
+ * client takes over. Render the content in `Portal` with
4614
+ * `disabled={!isPortaled}` and this `container`. Moving remounts the content,
4615
+ * so an effect that holds one of its nodes depends on `isPortaled`, `portal`
4616
+ * and `defaultTarget`.
4617
+ *
4618
+ * @function usePortalProp
4619
+ * @param portal - The component's `portal` prop.
4620
+ * @returns Whether it's portaled now, its `container`, and the provider's
4621
+ * target while that places it.
4622
+ */
4623
+ function usePortalProp(portal) {
4624
+ const hydrated = useIsHydrated();
4625
+ const { portalContainer } = useConfig();
4626
+ const isPortaled = Boolean(portal) && hydrated;
4627
+ return {
4628
+ isPortaled,
4629
+ container: typeof portal === 'boolean' ? undefined : portal,
4630
+ defaultTarget: isPortaled && portal === true ? portalContainer : undefined,
4631
+ };
4632
+ }
4485
4633
  /**
4486
4634
  * Renders its children into another part of the page, `document.body` unless `container` or a `ConfigProvider` says otherwise, so floating content escapes an ancestor's `overflow`, `transform` or stacking context.
4487
4635
  *
@@ -5280,7 +5428,7 @@ const ModalClose = ({ className, size = 'large', variant = 'delete', onClick, ..
5280
5428
  * @see {@link https://bulma.io/documentation/components/modal/ | Bulma Modal documentation}
5281
5429
  */
5282
5430
  const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClose, className, textColor, bgColor, modalCardTitle, modalCardFoot, type, children, closeOnEscape = true, lockScroll = true, portal = false, role, 'aria-modal': ariaModalProp, ...props }, ref) {
5283
- const { classPrefix, portalContainer } = useConfig();
5431
+ const { classPrefix } = useConfig();
5284
5432
  const { bulmaHelperClasses, rest } = useBulmaClasses({
5285
5433
  color: textColor,
5286
5434
  backgroundColor: bgColor,
@@ -5326,20 +5474,15 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
5326
5474
  const previouslyFocusedRef = React.useRef(null);
5327
5475
  const generatedTitleId = React.useId();
5328
5476
  // A portal has no server-rendered counterpart, so the server render and the
5329
- // hydrating render have to stay inline and only move into the portal once
5330
- // we're past hydration.
5331
- const onClient = useIsHydrated();
5332
- const resolveContainer = usePortalContainer();
5333
- // Moving into the portal, or from one portal target to another, remounts
5334
- // the modal's subtree, so any effect holding a DOM node from before the move
5335
- // is holding a detached one. Effects that touch the modal's nodes key on
5336
- // this, on `portal` and on `defaultTarget`, so they re-run against the new
5337
- // tree.
5338
- const isPortaled = Boolean(portal) && onClient;
5339
- // The configured `portalContainer` only places a modal portaled with
5340
- // `portal` set to `true`. In place, or with a target of its own, a change
5341
- // to it moves nothing, so it mustn't re-run the effects either.
5342
- const defaultTarget = isPortaled && portal === true ? portalContainer : undefined;
5477
+ // hydrating render stay inline and only move into the portal once we're
5478
+ // past hydration. Moving into the portal, or from one portal target to
5479
+ // another, remounts the modal's subtree, so any effect holding a DOM node
5480
+ // from before the move is holding a detached one. Effects that touch the
5481
+ // modal's nodes key on `isPortaled`, on `portal` and on `defaultTarget`, so
5482
+ // they re-run against the new tree. `defaultTarget` is the configured
5483
+ // `portalContainer` only while it places the modal (portaled with `portal`
5484
+ // set to `true`), so a change to it that moves nothing re-runs nothing.
5485
+ const { isPortaled, container, defaultTarget } = usePortalProp(portal);
5343
5486
  useScrollLock(isModalActive && lockScroll);
5344
5487
  // Read when Escape arrives, so the key listener stays put while `onClose`
5345
5488
  // changes identity, as an inline one does on every render of the parent.
@@ -5452,11 +5595,7 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
5452
5595
  }
5453
5596
  // In both forms, so a `Modal.Close` anywhere inside closes this modal.
5454
5597
  modalElement = (jsxRuntime.jsx(ModalCloseContext.Provider, { value: onClose, children: modalElement }));
5455
- if (isPortaled) {
5456
- const target = resolveContainer(typeof portal === 'boolean' ? undefined : portal);
5457
- return reactDom.createPortal(jsxRuntime.jsx(LocalePortalScope, { target: target, children: modalElement }), target);
5458
- }
5459
- return modalElement;
5598
+ return (jsxRuntime.jsx(Portal, { disabled: !isPortaled, container: container, children: modalElement }));
5460
5599
  });
5461
5600
  const Modal = withSubComponents(ModalRoot, {
5462
5601
  Background: ModalBackground,
@@ -9846,10 +9985,7 @@ const Dialog = React.forwardRef(({ isOpen, title, message, type = 'default', con
9846
9985
  // the Modal's subtree, these buttons included, so the focus effect below
9847
9986
  // has to re-run against the new nodes, exactly as the Modal's own focus
9848
9987
  // effect does, on the same inputs.
9849
- const isHydrated = useIsHydrated();
9850
- const isPortaled = Boolean(portal) && isHydrated;
9851
- const { portalContainer } = useConfig();
9852
- const defaultTarget = isPortaled && portal === true ? portalContainer : undefined;
9988
+ const { isPortaled, defaultTarget } = usePortalProp(portal);
9853
9989
  // Focus management — Dialog picks a specific button rather than the
9854
9990
  // Modal's default (first focusable/root); this effect runs after the
9855
9991
  // inner Modal's own focus-on-open effect, so it wins.
@@ -14503,6 +14639,42 @@ const DataTable = React.forwardRef(function DataTableRender({ columns, data, tab
14503
14639
  });
14504
14640
  DataTable.displayName = 'DataTable';
14505
14641
 
14642
+ /**
14643
+ * The `Affix` component keeps its content fixed to a corner of the viewport while the page scrolls under it.
14644
+ *
14645
+ * It's a `<div>` with no role, so what's inside keeps its own. It sits
14646
+ * `--bulma-affix-offset-vertical` and `--bulma-affix-offset-horizontal`
14647
+ * from its corner's edges, plus the device's safe-area inset, and stacks at
14648
+ * `--bulma-affix-z-index`, over the page's content and under its navbar,
14649
+ * static or fixed, its menus, popovers, the Sidebar, the modals, Tooltip and
14650
+ * Toast. It's as wide as its
14651
+ * content and never wider than the viewport less its offsets. It doesn't
14652
+ * scroll, so nothing inside it is clipped, and content that can be taller
14653
+ * than the screen scrolls itself. Its place in the reading and Tab order is
14654
+ * its place in the DOM, whatever corner it shows in.
14655
+ *
14656
+ * @function
14657
+ * @param {AffixProps} props - Props for the Affix component.
14658
+ * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the `<div>`.
14659
+ * @returns The `<div>`, in place or in its portal.
14660
+ *
14661
+ * @example
14662
+ * <Affix position="bottom-left">
14663
+ * <Button color="primary">Feedback</Button>
14664
+ * </Affix>
14665
+ */
14666
+ const Affix = React.forwardRef(({ position = 'bottom-right', portal = false, className, children, ...props }, ref) => {
14667
+ const { bulmaHelperClasses, rest } = useBulmaClasses(props);
14668
+ const affixClasses = usePrefixedClassNames('affix', {
14669
+ [`is-${position}`]: true,
14670
+ });
14671
+ // In place on the server and while hydrating, then into the portal, as
14672
+ // Modal does. The move remounts the `<div>`.
14673
+ const { isPortaled, container } = usePortalProp(portal);
14674
+ return (jsxRuntime.jsx(Portal, { disabled: !isPortaled, container: container, children: jsxRuntime.jsx("div", { ref: ref, className: classNames(affixClasses, bulmaHelperClasses, className), ...rest, children: children }) }));
14675
+ });
14676
+ Affix.displayName = 'Affix';
14677
+
14506
14678
  /**
14507
14679
  * The `Block` component renders a simple container with Bulma's `.block` class, adding vertical margin between sections of content.
14508
14680
  *
@@ -26839,6 +27011,63 @@ function ClientOnly({ children, fallback = null }) {
26839
27011
  return jsxRuntime.jsx(jsxRuntime.Fragment, { children: typeof children === 'function' ? children() : children });
26840
27012
  }
26841
27013
 
27014
+ /**
27015
+ * The `.stack` element behind Stack, Group, Center and Flex.
27016
+ *
27017
+ * With `as="ul"` or `as="ol"` it renders `role="list"`, which Safari needs:
27018
+ * WebKit stops exposing a list as one once its markers are hidden, and
27019
+ * Bulma's reset hides a `<ul>`'s. Menu.List restates it for the same reason.
27020
+ */
27021
+ const StackLayout = React.forwardRef(function StackLayout({ as = 'div', className, textColor, bgColor,
27022
+ // Not accepted, and taken out before the spread below, where a spread's
27023
+ // `color: undefined`, or a JavaScript caller's `color`, would replace
27024
+ // `textColor`, as `backgroundColor` would `bgColor`.
27025
+ color: _color, backgroundColor: _backgroundColor, modifiers, children, ...props }, ref) {
27026
+ // The partial makes the element a flex container, so the container
27027
+ // helpers (alignItems and the rest) apply without a `display` prop.
27028
+ const { bulmaHelperClasses, rest } = useBulmaClasses({ color: textColor, backgroundColor: bgColor, ...props }, { flexContainer: true });
27029
+ const stackClasses = usePrefixedClassNames('stack', modifiers);
27030
+ const Component = as;
27031
+ const isList = as === 'ul' || as === 'ol';
27032
+ return (jsxRuntime.jsx(Component, { ref: ref, className: classNames(stackClasses, bulmaHelperClasses, className), ...rest, ...(isList ? { role: rest.role || 'list' } : {}), children: children }));
27033
+ });
27034
+
27035
+ /**
27036
+ * The `Center` component centers its content on both axes.
27037
+ *
27038
+ * Use it for a loader, an icon or an empty state in the middle of a box, a
27039
+ * card or a section. Give it a height, or put it in something that has one,
27040
+ * to center down the middle as well as across. Several children sit side by
27041
+ * side in the middle, with no gap unless you set one.
27042
+ *
27043
+ * @function
27044
+ * @param {CenterProps} props - Props for the Center component.
27045
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
27046
+ * @returns {JSX.Element} The rendered center.
27047
+ *
27048
+ * @example
27049
+ * <Center p="6">
27050
+ * <Loader />
27051
+ * </Center>
27052
+ */
27053
+ const Center = React.forwardRef(function Center(props, ref) {
27054
+ return (jsxRuntime.jsx(StackLayout, { ref: ref, ...props,
27055
+ // Centered both ways, in the children's own order.
27056
+ flexDirection: undefined, modifiers: { 'is-centered': true } }));
27057
+ });
27058
+ Center.displayName = 'Center';
27059
+
27060
+ // INTERNAL: not exported from src/index.ts, which re-exports Container's
27061
+ // module whole, so this list lives here rather than beside the type.
27062
+ //
27063
+ // Every value `ContainerBreakpoint` takes, in one list, so Container's and
27064
+ // Group's checks of a JavaScript caller's `breakpoint` can't drift apart.
27065
+ const CONTAINER_BREAKPOINTS = [
27066
+ 'tablet',
27067
+ 'desktop',
27068
+ 'widescreen',
27069
+ ];
27070
+
26842
27071
  /**
26843
27072
  * The `Container` component provides a responsive and flexible layout wrapper for your Bulma React UI.
26844
27073
  *
@@ -26854,14 +27083,9 @@ const Container = ({ as: Tag = 'div', className, textColor, color, bgColor, flui
26854
27083
  ...props,
26855
27084
  });
26856
27085
  // Only allow isMax for supported breakpoints
26857
- const validMaxBreakpoints = [
26858
- 'tablet',
26859
- 'desktop',
26860
- 'widescreen',
26861
- ];
26862
27086
  let breakpointClass;
26863
27087
  if (breakpoint) {
26864
- if (isMax && validMaxBreakpoints.includes(breakpoint)) {
27088
+ if (isMax && CONTAINER_BREAKPOINTS.includes(breakpoint)) {
26865
27089
  breakpointClass = `is-max-${breakpoint}`;
26866
27090
  }
26867
27091
  else if (!isMax) {
@@ -26879,6 +27103,32 @@ const Container = ({ as: Tag = 'div', className, textColor, color, bgColor, flui
26879
27103
  return (jsxRuntime.jsx(Tag, { className: containerClasses, style: mergeBulmaStyles(bulmaHelperStyles, style), ...rest, children: children }));
26880
27104
  };
26881
27105
 
27106
+ /**
27107
+ * The `Flex` component is a flex container with CSS's own defaults, taking the flex container's properties as props.
27108
+ *
27109
+ * It's a row that doesn't wrap, with its children stretched across it and no
27110
+ * gap, until you set otherwise. Use it for a layout of your own, such as a
27111
+ * fixed side beside a growing one, with `flexGrow` and `flexShrink` on the
27112
+ * children. Its children's own block margins are zeroed, so the gap is the
27113
+ * only space. For a column of blocks or a row of controls with Bulma's
27114
+ * spacing already in place, `Stack` and `Group` start closer.
27115
+ *
27116
+ * @function
27117
+ * @param {FlexProps} props - Props for the Flex component.
27118
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
27119
+ * @returns {JSX.Element} The rendered flex container.
27120
+ *
27121
+ * @example
27122
+ * <Flex gap="4" alignItems="flex-start">
27123
+ * <Box flexShrink="0">…</Box>
27124
+ * <Box flexGrow="1">…</Box>
27125
+ * </Flex>
27126
+ */
27127
+ const Flex = React.forwardRef(function Flex(props, ref) {
27128
+ return jsxRuntime.jsx(StackLayout, { ref: ref, ...props });
27129
+ });
27130
+ Flex.displayName = 'Flex';
27131
+
26882
27132
  /**
26883
27133
  * The `Footer` component provides a semantic and accessible site footer for your Bulma React UI.
26884
27134
  *
@@ -26904,6 +27154,40 @@ const Footer = ({ as = 'footer', className, children, color, bgColor, textColor,
26904
27154
  return (jsxRuntime.jsx(Tag, { className: footerClasses, style: mergeBulmaStyles(bulmaHelperStyles, style), ...rest, children: children }));
26905
27155
  };
26906
27156
 
27157
+ /**
27158
+ * The `Group` component lays its children out in a row that wraps, centered on each other, with half of Bulma's block spacing between them.
27159
+ *
27160
+ * Use it for a row of buttons, tags or avatars beside some text, or a toolbar
27161
+ * with `justifyContent="space-between"` pushing its ends apart. The children's
27162
+ * own block margins are zeroed, so the gap is the only space. With
27163
+ * `breakpoint`, it's a column on narrow screens and a row from that
27164
+ * breakpoint up. For controls joined into one, with no gap and shared
27165
+ * borders, use `hasAddons` on Field or Buttons instead.
27166
+ *
27167
+ * @function
27168
+ * @param {GroupProps} props - Props for the Group component.
27169
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
27170
+ * @returns {JSX.Element} The rendered group.
27171
+ *
27172
+ * @example
27173
+ * <Group justifyContent="space-between">
27174
+ * <Title as="h2" size="4">Invoices</Title>
27175
+ * <Button color="primary">New invoice</Button>
27176
+ * </Group>
27177
+ */
27178
+ const Group = React.forwardRef(function Group(props, ref) {
27179
+ const { isFullwidth, breakpoint, ...rest } = props;
27180
+ return (jsxRuntime.jsx(StackLayout, { ref: ref, ...rest,
27181
+ // A row always, or a column below `breakpoint`: never reversed, so
27182
+ // reading and Tab order follow what's seen.
27183
+ flexDirection: undefined, modifiers: {
27184
+ 'is-horizontal': true,
27185
+ 'is-fullwidth': isFullwidth,
27186
+ [`is-${breakpoint}`]: !!breakpoint && CONTAINER_BREAKPOINTS.includes(breakpoint),
27187
+ } }));
27188
+ });
27189
+ Group.displayName = 'Group';
27190
+
26907
27191
  /**
26908
27192
  * The `Hero` component provides a responsive, flexible, and visually striking section for your Bulma React UI.
26909
27193
  *
@@ -27709,6 +27993,33 @@ const Splitter = withSubComponents(SplitterRoot, {
27709
27993
  Pane: SplitterPane,
27710
27994
  });
27711
27995
 
27996
+ /**
27997
+ * The `Stack` component lays its children out in a column, with Bulma's block spacing between them and the margins Bulma gives them zeroed.
27998
+ *
27999
+ * A Stack of Boxes, Cards or Notifications looks like Bulma's own stacked
28000
+ * blocks, spaced by the gap alone, so there are no margins to undo. A `gap`
28001
+ * step replaces the default spacing. It's always a column, top to bottom.
28002
+ *
28003
+ * @function
28004
+ * @param {StackProps} props - Props for the Stack component.
28005
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
28006
+ * @returns {JSX.Element} The rendered stack.
28007
+ *
28008
+ * @example
28009
+ * <Stack>
28010
+ * <Notification color="info">Your changes are saved.</Notification>
28011
+ * <Box>…</Box>
28012
+ * </Stack>
28013
+ */
28014
+ const Stack = React.forwardRef(function Stack(props, ref) {
28015
+ return (jsxRuntime.jsx(StackLayout, { ref: ref, ...props,
28016
+ // A column always: reading and Tab order follow the children's order,
28017
+ // and a reversed column would show them in another.
28018
+ flexDirection: undefined, modifiers: { 'is-vertical': true } }));
28019
+ });
28020
+ Stack.displayName = 'Stack';
28021
+
28022
+ exports.Affix = Affix;
27712
28023
  exports.Autocomplete = Autocomplete;
27713
28024
  exports.Avatar = Avatar;
27714
28025
  exports.Avatars = Avatars;
@@ -27722,6 +28033,7 @@ exports.Card = Card;
27722
28033
  exports.Carousel = Carousel;
27723
28034
  exports.CarouselItem = CarouselItem;
27724
28035
  exports.Cell = Cell;
28036
+ exports.Center = Center;
27725
28037
  exports.Checkbox = Checkbox;
27726
28038
  exports.CheckboxCard = CheckboxCard;
27727
28039
  exports.Checkboxes = Checkboxes;
@@ -27790,14 +28102,17 @@ exports.FieldLabel = FieldLabel;
27790
28102
  exports.Fieldset = Fieldset;
27791
28103
  exports.Figure = Figure;
27792
28104
  exports.File = File;
28105
+ exports.Flex = Flex;
27793
28106
  exports.Footer = Footer;
27794
28107
  exports.Grid = Grid;
28108
+ exports.Group = Group;
27795
28109
  exports.Hero = Hero;
27796
28110
  exports.HeroBody = HeroBody;
27797
28111
  exports.HeroFoot = HeroFoot;
27798
28112
  exports.HeroHead = HeroHead;
27799
28113
  exports.HoverCard = HoverCard;
27800
28114
  exports.Icon = Icon;
28115
+ exports.IconButton = IconButton;
27801
28116
  exports.IconText = IconText;
27802
28117
  exports.Image = Image;
27803
28118
  exports.Input = Input;
@@ -27883,6 +28198,7 @@ exports.Slider = Slider;
27883
28198
  exports.Span = Span;
27884
28199
  exports.Splitter = Splitter;
27885
28200
  exports.SplitterPane = SplitterPane;
28201
+ exports.Stack = Stack;
27886
28202
  exports.Step = Step;
27887
28203
  exports.Steps = Steps;
27888
28204
  exports.Strong = Strong;