@allxsmith/bestax-bulma 5.15.0 → 5.15.1

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 CHANGED
@@ -1189,6 +1189,21 @@ const ColumnsComponent = ({ className, textColor, color: _fieldColor, bgColor, i
1189
1189
  };
1190
1190
  const Columns = withSubComponents(ColumnsComponent, { Column }, 'Columns');
1191
1191
 
1192
+ /**
1193
+ * Whether an `as` target is a custom element rather than a built-in tag.
1194
+ *
1195
+ * HTML requires a custom element's name to contain a hyphen, and no built-in
1196
+ * element name has one, so this is exact rather than a heuristic. It matters
1197
+ * because a custom element is an intrinsic STRING — `typeof as === 'string'` is
1198
+ * true — while its props are whatever a consumer declared through
1199
+ * `React.JSX.IntrinsicElements`, the way this package declares `<ion-icon>`.
1200
+ * A runtime backstop that filters built-in attributes must leave those alone,
1201
+ * or it strips props the derived type just promised to forward.
1202
+ */
1203
+ function isCustomElement(as) {
1204
+ return typeof as === 'string' && as.includes('-');
1205
+ }
1206
+
1192
1207
  const avatarColors = [
1193
1208
  'primary',
1194
1209
  'link',
@@ -1257,6 +1272,7 @@ function DefaultAvatarIcon() {
1257
1272
  *
1258
1273
  * @function
1259
1274
  * @param {AvatarProps} props - Props for the Avatar component.
1275
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
1260
1276
  * @returns {JSX.Element} The rendered avatar element.
1261
1277
  *
1262
1278
  * @example
@@ -1264,7 +1280,8 @@ function DefaultAvatarIcon() {
1264
1280
  * @example
1265
1281
  * <Avatar name="Grace Hopper" />
1266
1282
  */
1267
- const Avatar = ({ className, src, alt, name, initials, icon, size, shape = 'circle', color, as, href, target, rel, imageProps, style, ...props }) => {
1283
+ const Avatar = React.forwardRef(function Avatar(avatarProps, ref) {
1284
+ const { className, src, alt, name, initials, icon, size, shape = 'circle', color, as, href, target, rel, imageProps, style, ...props } = avatarProps;
1268
1285
  // Tracks the src that failed to load. A src change clears the latch during
1269
1286
  // render (React's "reset state when props change" pattern) so a previously
1270
1287
  // failed src is retried when switched back to. The img is additionally
@@ -1316,10 +1333,10 @@ const Avatar = ({ className, src, alt, name, initials, icon, size, shape = 'circ
1316
1333
  // decorative (aria-hidden) and it could render nameless.
1317
1334
  const isInteractive = Tag === 'a' ||
1318
1335
  Tag === 'button' ||
1319
- (typeof Tag !== 'string' && href != null);
1336
+ ((typeof Tag !== 'string' || isCustomElement(Tag)) && href != null);
1320
1337
  // Only forward link attributes when rendering an anchor or a custom (non-DOM)
1321
1338
  // component; a plain `as="div"` must not receive a stray `href`/`target`/`rel`.
1322
- const isLinkLike = Tag === 'a' || typeof Tag !== 'string';
1339
+ const isLinkLike = Tag === 'a' || typeof Tag !== 'string' || isCustomElement(Tag);
1323
1340
  const linkProps = isLinkLike ? { href, target, rel } : {};
1324
1341
  // alt coalesces with ?? (not ||) so an explicit alt="" survives as the
1325
1342
  // standard decorative marker instead of being overridden by name.
@@ -1342,11 +1359,11 @@ const Avatar = ({ className, src, alt, name, initials, icon, size, shape = 'circ
1342
1359
  // A clickable avatar inside a form must not submit it; default the native
1343
1360
  // button type (an explicit type passed through rest still wins).
1344
1361
  const buttonTypeProps = Tag === 'button' ? { type: 'button' } : {};
1345
- return (jsxRuntime.jsxs(Tag, { className: combinedClasses, style: { ...sizeStyle, ...style }, ...buttonTypeProps, ...linkProps, ...a11yProps, ...rest, children: [showImage && (jsxRuntime.jsx("img", { ...imageProps, ref: imgRef, src: src, alt: accessibleName ?? '', onError: e => {
1362
+ return (jsxRuntime.jsxs(Tag, { ref: ref, className: combinedClasses, style: { ...sizeStyle, ...style }, ...buttonTypeProps, ...linkProps, ...a11yProps, ...rest, children: [showImage && (jsxRuntime.jsx("img", { ...imageProps, ref: imgRef, src: src, alt: accessibleName ?? '', onError: e => {
1346
1363
  imageProps?.onError?.(e);
1347
1364
  setErroredSrc(src);
1348
1365
  } }, src)), showInitials && (jsxRuntime.jsx("span", { className: initialsClass, children: resolvedInitials })), showIcon && icon, showDefaultIcon && jsxRuntime.jsx(DefaultAvatarIcon, {})] }));
1349
- };
1366
+ });
1350
1367
  Avatar.displayName = 'Avatar';
1351
1368
 
1352
1369
  /**
@@ -2059,13 +2076,23 @@ const MenuList = ({ className, children, ...props }) => {
2059
2076
  *
2060
2077
  * @function
2061
2078
  * @param {MenuItemProps} props - Props for the MenuItem component.
2079
+ * @param {React.Ref} ref - Forwarded ref to the inner element `as` renders.
2062
2080
  * @returns {JSX.Element} The rendered menu item.
2063
2081
  */
2064
- const MenuItem = ({ className, children, active, href, as: Component = 'a', 'data-testid': testId, ...rest }) => {
2065
- const { bulmaHelperClasses, rest: bulmaRest } = useBulmaClasses(rest);
2082
+ const MenuItem = React.forwardRef(function MenuItem(itemProps, ref) {
2083
+ const { className, children, active, as: Component = 'a', 'data-testid': testId, style, id, title, role, tabIndex, ...rest } = itemProps;
2084
+ const { bulmaHelperClasses, rest: forwarded } = useBulmaClasses(rest);
2085
+ // `href` reaches an anchor or a custom component (which owns its own prop
2086
+ // contract), but not another intrinsic tag — `<span href>` is invalid HTML.
2087
+ // The same rule Avatar applies through `isLinkLike` and Button through its
2088
+ // intrinsic-only strip. Before #641 `href` was an own prop re-applied only
2089
+ // for `as="a"`; deriving it from `as` must not quietly widen that.
2090
+ const isLinkLike = Component === 'a' ||
2091
+ typeof Component !== 'string' ||
2092
+ isCustomElement(Component);
2093
+ const { href: _href, ...withoutHref } = forwarded;
2094
+ const linkProps = isLinkLike ? forwarded : withoutHref;
2066
2095
  const itemClass = classNames({ [usePrefixedClassNames('is-active')]: active }, bulmaHelperClasses);
2067
- // Standard <li> props
2068
- const { style, id, title, role, tabIndex, ...linkProps } = bulmaRest;
2069
2096
  // Split children into label and nested MenuList(s)
2070
2097
  const labelChildren = [];
2071
2098
  const nestedMenuLists = [];
@@ -2077,15 +2104,9 @@ const MenuItem = ({ className, children, active, href, as: Component = 'a', 'dat
2077
2104
  labelChildren.push(child);
2078
2105
  }
2079
2106
  });
2080
- // href/to should go to the link component
2081
- if (Component === 'a' && href) {
2082
- linkProps.href = href;
2083
- }
2084
- if (Object.prototype.hasOwnProperty.call(rest, 'to')) {
2085
- linkProps.to = rest.to;
2086
- }
2087
- return (jsxRuntime.jsxs("li", { className: className, "data-testid": testId, style: style, id: id, title: title, role: role, tabIndex: tabIndex, children: [jsxRuntime.jsx(Component, { className: itemClass, ...linkProps, children: labelChildren }), nestedMenuLists] }));
2088
- };
2107
+ return (jsxRuntime.jsxs("li", { className: className, "data-testid": testId, style: style, id: id, title: title, role: role, tabIndex: tabIndex, children: [jsxRuntime.jsx(Component, { ref: ref, className: itemClass, ...linkProps, children: labelChildren }), nestedMenuLists] }));
2108
+ });
2109
+ MenuItem.displayName = 'MenuItem';
2089
2110
  // Attach static subcomponents
2090
2111
  const Menu = withSubComponents(MenuComponent, {
2091
2112
  Label: MenuLabel,
@@ -2597,18 +2618,21 @@ const NavbarBrand = ({ className, children, textColor, ...props }) => {
2597
2618
  *
2598
2619
  * @function
2599
2620
  * @param {NavbarItemProps} props - Props for the NavbarItem component.
2621
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
2600
2622
  * @returns {JSX.Element} The rendered item.
2601
2623
  */
2602
- const NavbarItem = ({ className, as: Component = 'a', active, textColor, bgColor, children, ...props }) => {
2624
+ const NavbarItem = React.forwardRef(function NavbarItem(itemProps, ref) {
2625
+ const { className, as: Component = 'a', active, textColor, bgColor, children, ...props } = itemProps;
2603
2626
  const { bulmaHelperClasses, rest } = useBulmaClasses({
2604
2627
  color: textColor,
2605
2628
  backgroundColor: bgColor,
2606
2629
  ...props,
2607
2630
  });
2608
- return (jsxRuntime.jsx(Component, { className: classNames(usePrefixedClassNames('navbar-item', {
2631
+ return (jsxRuntime.jsx(Component, { ref: ref, className: classNames(usePrefixedClassNames('navbar-item', {
2609
2632
  'is-active': active,
2610
2633
  }), bulmaHelperClasses, className), ...rest, children: children }));
2611
- };
2634
+ });
2635
+ NavbarItem.displayName = 'NavbarItem';
2612
2636
  /**
2613
2637
  * Responsive menu toggle (mobile)
2614
2638
  *
@@ -2672,10 +2696,11 @@ const NavbarEnd = ({ className, children, ...props }) => {
2672
2696
  *
2673
2697
  * @function
2674
2698
  * @param {NavbarLinkProps} props - Props for the NavbarLink component.
2675
- * @param {React.Ref<HTMLAnchorElement | HTMLButtonElement>} ref - Forwarded ref to the rendered link or button element.
2699
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
2676
2700
  * @returns {JSX.Element} The rendered navbar link.
2677
2701
  */
2678
- const NavbarLink = React.forwardRef(function NavbarLink({ className, as: Component = 'a', arrowless, textColor, bgColor, children, ...props }, ref) {
2702
+ const NavbarLink = React.forwardRef(function NavbarLink(linkProps, ref) {
2703
+ const { className, as: Component = 'a', arrowless, textColor, bgColor, children, ...props } = linkProps;
2679
2704
  const { bulmaHelperClasses, rest } = useBulmaClasses({
2680
2705
  color: textColor,
2681
2706
  backgroundColor: bgColor,
@@ -2684,8 +2709,16 @@ const NavbarLink = React.forwardRef(function NavbarLink({ className, as: Compone
2684
2709
  const dropdownContext = React.useContext(NavbarDropdownContext);
2685
2710
  const hasHref = rest.href !== undefined;
2686
2711
  const isNativeInteractive = Component === 'button' || hasHref;
2712
+ // Guarded like Button's disabled blocker: these run on whatever `as` renders,
2713
+ // and a custom target's callback need not take a DOM event. One declaring
2714
+ // `onKeyDown: (k: {key: string}) => void` reaches `e.preventDefault()` and
2715
+ // throws. Composing the caller's handler is unconditional; acting on the
2716
+ // event is not ours to do when the payload is foreign.
2717
+ const isDomEvent = (e) => typeof e?.preventDefault === 'function';
2687
2718
  const handleKeyDown = (e) => {
2688
2719
  rest.onKeyDown?.(e);
2720
+ if (!isDomEvent(e))
2721
+ return;
2689
2722
  if (!dropdownContext || e.defaultPrevented)
2690
2723
  return;
2691
2724
  if (e.key === 'Enter' || e.key === ' ') {
@@ -2704,6 +2737,8 @@ const NavbarLink = React.forwardRef(function NavbarLink({ className, as: Compone
2704
2737
  // click semantics (navigation / the caller's handler).
2705
2738
  const handleClick = (e) => {
2706
2739
  rest.onClick?.(e);
2740
+ if (!isDomEvent(e))
2741
+ return;
2707
2742
  if (!dropdownContext || isNativeInteractive || e.defaultPrevented)
2708
2743
  return;
2709
2744
  dropdownContext.toggle();
@@ -4693,15 +4728,16 @@ const validButtonColors = [...validColors, 'text', 'ghost'];
4693
4728
  *
4694
4729
  * @function
4695
4730
  * @param {ButtonProps} props - Props for the Button component.
4696
- * @param {React.Ref<HTMLButtonElement | HTMLAnchorElement>} ref - Forwarded ref to the rendered button or anchor element.
4697
- * @returns {JSX.Element} The rendered button or anchor element.
4731
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
4732
+ * @returns {JSX.Element} The rendered button, anchor, or custom element.
4698
4733
  * @see {@link https://bulma.io/documentation/elements/button/ | Bulma Button documentation}
4699
4734
  */
4700
- const Button = React.forwardRef(function Button({ color, size, isLight, isRounded, isLoading, isStatic, isFullwidth, isFullWidth, isOutlined, isInverted, isFocused, isActive, isHovered, isDisabled, className, children, textColor, bgColor, as: Component = 'button', href, onClick, target, rel, ...props }, ref) {
4735
+ const Button = React.forwardRef(function Button(props, ref) {
4736
+ const { color, size, isLight, isRounded, isLoading, isStatic, isFullwidth, isFullWidth, isOutlined, isInverted, isFocused, isActive, isHovered, isDisabled, className, children, textColor, bgColor, as: Component = 'button', href, onClick, target, rel, ...bulmaProps } = props;
4701
4737
  const { bulmaHelperClasses, rest } = useBulmaClasses({
4702
4738
  color: textColor,
4703
4739
  backgroundColor: bgColor,
4704
- ...props,
4740
+ ...bulmaProps,
4705
4741
  });
4706
4742
  // Generate Bulma classes with prefix
4707
4743
  const bulmaClasses = usePrefixedClassNames('button', {
@@ -4723,13 +4759,93 @@ const Button = React.forwardRef(function Button({ color, size, isLight, isRounde
4723
4759
  // Combine prefixed Bulma classes with unprefixed user className and prefixed helper classes
4724
4760
  const buttonClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
4725
4761
  if (Component !== 'button') {
4726
- // Create anchor-specific props by excluding button-specific ones, so
4727
- // native/custom link-like elements (an <a>, a router Link, ...) don't
4728
- // receive button-only HTML attributes.
4729
- const { type: _type, disabled: _disabled, form: _form, formAction: _formAction, formEncType: _formEncType, formMethod: _formMethod, formNoValidate: _formNoValidate, formTarget: _formTarget, name: _name, value: _value, autoFocus: _autoFocus, ...anchorRest } = rest;
4762
+ // Strip the form-control attributes a link-like element cannot carry, so a
4763
+ // JavaScript consumer or a spread object doesn't put them on the DOM. The
4764
+ // types no longer allow them through; this is the runtime backstop.
4765
+ //
4766
+ // Only for INTRINSIC tags. A custom component (a router Link, ...) owns its
4767
+ // prop contract, and `ComponentPropsWithoutRef<T>` promises the caller that
4768
+ // its props reach it. Stripping names by their spelling alone broke that
4769
+ // promise silently: `<Button as={Custom} name="x" />` type-checked while
4770
+ // `Custom` never received the `name` it requires.
4771
+ //
4772
+ // `autoFocus` and `type` are deliberately NOT stripped: both are valid on
4773
+ // targets this list was filtering them from. `autoFocus` is a global
4774
+ // attribute (React decides per element whether to honour it, which is not
4775
+ // ours to pre-empt), and `type` on an anchor is the MIME hint that
4776
+ // `ButtonProps<'a'>` now types it as.
4777
+ //
4778
+ // The types already answer this for a TypeScript caller: `ButtonProps<T>`
4779
+ // derives from `ComponentPropsWithoutRef<T>`, so only what the target
4780
+ // accepts can be passed. What is left is a runtime backstop for JavaScript
4781
+ // consumers and spread objects.
4782
+ //
4783
+ // Keep it to the two cases where a stray attribute does something. The
4784
+ // submit-overrides belong to a submit control and never make sense on the
4785
+ // anchor path. `disabled` is the one that is VISIBLE: Bulma styles
4786
+ // `.button[disabled]` (background, border, shadow, opacity), so letting it
4787
+ // through to a `<span>` greys the element out — main stripped it, and not
4788
+ // stripping it would be a silent visual change on a types-only release.
4789
+ //
4790
+ // Everything else (`name`, `value`, `form`) is inert where it does not
4791
+ // belong, and enumerating which tags own it is what kept going wrong:
4792
+ // first all nine names on every non-button tag (so `<Button as="input"
4793
+ // name="query" value="Search">` submitted nothing), then a form-control
4794
+ // allowlist that still lost `formAction` on an input and `value` on an
4795
+ // option. Those now ride on the types instead.
4796
+ //
4797
+ // A custom component is exempt entirely — it owns its prop contract, and
4798
+ // `ComponentPropsWithoutRef<T>` promises the caller its props arrive.
4799
+ //
4800
+ // The elements that own `disabled`, per the HTML spec. A closed set, unlike
4801
+ // the open-ended question of which tag owns which attribute.
4802
+ const SUBMIT_OVERRIDES = [
4803
+ 'formAction',
4804
+ 'formEncType',
4805
+ 'formMethod',
4806
+ 'formNoValidate',
4807
+ 'formTarget',
4808
+ ];
4809
+ const OWNS_DISABLED = [
4810
+ 'button',
4811
+ 'fieldset',
4812
+ 'input',
4813
+ 'optgroup',
4814
+ 'option',
4815
+ 'select',
4816
+ 'textarea',
4817
+ ];
4818
+ // Two independent filters. They are not exclusive — an `<a>` owns neither
4819
+ // the submit-overrides nor `disabled`, so it takes both — and deriving them
4820
+ // from one destructure, or from one if/else, is what broke each of them in
4821
+ // turn: first the overrides came off every intrinsic (an `as="input"` lost
4822
+ // `formAction`), then scoping them to the anchor let `disabled` back onto
4823
+ // it.
4824
+ const forwardedRest = { ...rest };
4825
+ if (typeof Component === 'string' && !isCustomElement(Component)) {
4826
+ // Meaningless anywhere but a submit control, and an anchor is not one.
4827
+ if (Component === 'a') {
4828
+ for (const key of SUBMIT_OVERRIDES)
4829
+ delete forwardedRest[key];
4830
+ }
4831
+ // Visible via Bulma's `.button[disabled]`, so withheld from any element
4832
+ // that does not own it.
4833
+ if (!OWNS_DISABLED.includes(Component))
4834
+ delete forwardedRest.disabled;
4835
+ }
4730
4836
  return (jsxRuntime.jsx(Component, { ref: ref, className: buttonClasses, href: href, target: target, rel: rel, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : undefined, onClick: isDisabled
4731
- ? (e) => e.preventDefault()
4732
- : onClick, ...anchorRest, children: children }));
4837
+ ? // Guarded, because this handler is installed into whatever `as`
4838
+ // renders and a custom component's `onClick` need not be a DOM
4839
+ // event handler at all. One declaring `onClick: (v: string) =>
4840
+ // void` calls this with a string, and an unguarded
4841
+ // `e.preventDefault()` throws `is not a function`. Blocking the
4842
+ // real event is the point; a foreign payload is simply not ours
4843
+ // to act on.
4844
+ (e) => {
4845
+ if (typeof e?.preventDefault === 'function')
4846
+ e.preventDefault();
4847
+ }
4848
+ : onClick, ...forwardedRest, children: children }));
4733
4849
  }
4734
4850
  return (jsxRuntime.jsx("button", { ref: ref, className: buttonClasses, disabled: isDisabled, onClick: onClick, ...rest, children: children }));
4735
4851
  });
@@ -5118,7 +5234,8 @@ function usePrefersReducedMotion() {
5118
5234
  * ))}
5119
5235
  * </Reveal>
5120
5236
  */
5121
- const Reveal = ({ animation = 'fade-up', delay = 0, duration = 600, threshold = 0.15, once = true, as: Component = 'div', cascade = false, cascadeInterval = 80, className, style, children, ...props }) => {
5237
+ function RevealImpl(revealProps) {
5238
+ const { animation = 'fade-up', delay = 0, duration = 600, threshold = 0.15, once = true, as: Component = 'div', cascade = false, cascadeInterval = 80, className, style, children, ...props } = revealProps;
5122
5239
  const { bulmaHelperClasses, rest } = useBulmaClasses(props);
5123
5240
  const classPrefix = useClassPrefix();
5124
5241
  const prefersReducedMotion = usePrefersReducedMotion();
@@ -5195,12 +5312,16 @@ const Reveal = ({ animation = 'fade-up', delay = 0, duration = 600, threshold =
5195
5312
  return (jsxRuntime.jsx("span", { className: itemAnimationClasses, style: itemStyle, children: child }, index));
5196
5313
  })
5197
5314
  : children;
5198
- // Scroll observation needs a real DOM node. Intrinsic tags ('div',
5199
- // 'section', ...) always accept a ref directly. A custom component passed
5200
- // via `as` (Section, Card, ...) is rendered by this library as a plain
5201
- // React.FC with no ref forwarding, so the ref (and the animation classes
5202
- // that depend on it) go on a plain wrapper `div` instead, with `Component`
5203
- // rendered inside it.
5315
+ // Scroll observation needs a DOM node this component OWNS — the observer and
5316
+ // the animation classes both key off it. An intrinsic tag is that node, so
5317
+ // the ref goes straight on it. A component passed via `as` is not: whatever
5318
+ // it renders is its own business, and it may render several elements or
5319
+ // none. So it gets wrapped in an observed `div`.
5320
+ //
5321
+ // Not a statement about ref forwarding. Several components in this library
5322
+ // forward refs (#641 added four more), and that changes nothing here — a
5323
+ // forwarded ref would still point at the target's node rather than at one
5324
+ // this component controls.
5204
5325
  if (typeof Component === 'string') {
5205
5326
  // A plain createElement call sidesteps the combinatorial JSX prop types
5206
5327
  // for `ref` across every possible intrinsic tag `as` could be.
@@ -5212,7 +5333,9 @@ const Reveal = ({ animation = 'fade-up', delay = 0, duration = 600, threshold =
5212
5333
  }, content);
5213
5334
  }
5214
5335
  return (jsxRuntime.jsx("div", { ref: setNode, className: combinedClasses, style: wrapperStyle, children: jsxRuntime.jsx(Component, { ...rest, children: content }) }));
5215
- };
5336
+ }
5337
+ const Reveal = RevealImpl;
5338
+ Reveal.displayName = 'Reveal';
5216
5339
 
5217
5340
  /**
5218
5341
  * The `Block` component renders a simple container with Bulma's `.block` class, adding vertical margin between sections of content.
@@ -5265,7 +5388,7 @@ const Box = ({ className, textColor, color, bgColor, hasShadow = true, children,
5265
5388
  *
5266
5389
  * @function
5267
5390
  * @param {LinkButtonProps} props - Props for the LinkButton component.
5268
- * @param {React.Ref<HTMLButtonElement | HTMLAnchorElement>} ref - Forwarded ref to the rendered button or anchor element.
5391
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
5269
5392
  * @returns {JSX.Element} The rendered link-styled button element.
5270
5393
  *
5271
5394
  * @example
@@ -5279,7 +5402,13 @@ const Box = ({ className, textColor, color, bgColor, hasShadow = true, children,
5279
5402
  const LinkButton = React.forwardRef(function LinkButton({ variant = 'text', color, className, ...props }, ref) {
5280
5403
  const buttonColor = variant === 'underline' ? 'text' : variant;
5281
5404
  const prefixedClasses = usePrefixedClassNames('link-button', color && `link-button-${color}`, variant === 'underline' && 'link-button-underline');
5282
- return (jsxRuntime.jsx(Button, { ref: ref, color: buttonColor, className: classNames(prefixedClasses, className), ...props }));
5405
+ return (jsxRuntime.jsx(Button
5406
+ // LinkButton is polymorphic through to Button, which resolves the element
5407
+ // from `as`. TS cannot infer that through the spread below.
5408
+ , {
5409
+ // LinkButton is polymorphic through to Button, which resolves the element
5410
+ // from `as`. TS cannot infer that through the spread below.
5411
+ ref: ref, color: buttonColor, className: classNames(prefixedClasses, className), ...props }));
5283
5412
  });
5284
5413
  LinkButton.displayName = 'LinkButton';
5285
5414
 
@@ -5551,10 +5680,12 @@ const Image = ({ as, className, textColor, color, bgColor, size, isRounded, isRe
5551
5680
  *
5552
5681
  * @function
5553
5682
  * @param {LinkProps} props - Props for the Link component.
5554
- * @returns {JSX.Element} The rendered anchor element.
5683
+ * @param {React.Ref} ref - Forwarded ref to the element `as` renders.
5684
+ * @returns {JSX.Element} The rendered anchor, or whatever `as` names.
5555
5685
  * @see {@link https://bulma.io/documentation/elements/content/ | Bulma Content documentation}
5556
5686
  */
5557
- const Link = ({ className, textColor, bgColor, isActive, as: Component = 'a', children, ...props }) => {
5687
+ const Link = React.forwardRef(function Link(linkProps, ref) {
5688
+ const { className, textColor, bgColor, isActive, as: Component = 'a', children, ...props } = linkProps;
5558
5689
  /**
5559
5690
  * Generates Bulma helper classes and separates out remaining props.
5560
5691
  */
@@ -5567,8 +5698,9 @@ const Link = ({ className, textColor, bgColor, isActive, as: Component = 'a', ch
5567
5698
  'is-active': isActive,
5568
5699
  });
5569
5700
  const linkClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
5570
- return (jsxRuntime.jsx(Component, { className: linkClasses || undefined, ...rest, children: children }));
5571
- };
5701
+ return (jsxRuntime.jsx(Component, { ref: ref, className: linkClasses || undefined, ...rest, children: children }));
5702
+ });
5703
+ Link.displayName = 'Link';
5572
5704
 
5573
5705
  /**
5574
5706
  * The `ListItem` component renders a styled list item (`<li>`) element with Bulma helper class integration.