@allxsmith/bestax-bulma 5.16.7 → 5.16.9

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 CHANGED
@@ -1281,6 +1281,22 @@ const avatarSizes = [
1281
1281
  '96x96',
1282
1282
  '128x128',
1283
1283
  ];
1284
+ /**
1285
+ * The roles a caller can use to say "this avatar is not a control", and so claim
1286
+ * the non-interactive treatment for a custom `as` target we would otherwise have
1287
+ * to guess about.
1288
+ *
1289
+ * Read by VALUE, not by presence. Any role at all used to count, which let
1290
+ * `role="button"` — a claim of the opposite — route a real control into the
1291
+ * decorative branch and come out `aria-hidden` and nameless. `img` is what the
1292
+ * fallback itself applies; `presentation` and `none` are the standard ways to say
1293
+ * an element carries no semantics, which is what pairs with `alt=""`.
1294
+ */
1295
+ const NON_INTERACTIVE_ROLES = [
1296
+ 'img',
1297
+ 'presentation',
1298
+ 'none',
1299
+ ];
1284
1300
  /**
1285
1301
  * Derives a small set of initials from a name (e.g. "Ada Lovelace" -> "AL").
1286
1302
  */
@@ -1375,17 +1391,63 @@ const Avatar = React.forwardRef(function Avatar(avatarProps, ref) {
1375
1391
  const combinedClasses = classNames(avatarClasses, bulmaHelperClasses, className);
1376
1392
  const initialsClass = usePrefixedClassNames('avatar-initials');
1377
1393
  const Tag = as ?? (href ? 'a' : 'figure');
1378
- // A custom `as` component given an href is being used as a link — the same
1379
- // condition under which isLinkLike forwards href/target/rel below — so it
1380
- // counts as interactive too. Otherwise alt="" would mark a real link
1381
- // decorative (aria-hidden) and it could render nameless.
1394
+ // A custom component counts as interactive whether or not it was given OUR
1395
+ // href: a router link takes `to`, creates the anchor itself, and cannot be
1396
+ // classified from the props it arrives with (#668). Marking a real link as a
1397
+ // picture is the worse failure — and `alt=""` would go further and mark it
1398
+ // decorative (aria-hidden), leaving it nameless.
1399
+ //
1400
+ // A custom ELEMENT still needs the href. A hyphenated tag renders a real DOM
1401
+ // element of that name, so nothing is hidden from us: without a link to follow
1402
+ // it is still a picture. `Navbar.Link` draws the same line for `role="button"`.
1403
+ //
1404
+ // Where we are guessing, the caller settles it: an explicit `role` or
1405
+ // `aria-hidden` states the semantics, so a custom component that really is a
1406
+ // wrapper gets `role="img"` and its `alt=""` opt-out back. `role` alone would
1407
+ // be a half-override — interactivity also drives the decorative opt-out and the
1408
+ // name fallback, and overriding one of the three is worse than overriding none.
1409
+ //
1410
+ // An `href` ENDS the guess, so it outranks the signal. `as="a"`, `as="button"`
1411
+ // and a target we were handed an href for are known to be interactive, and there
1412
+ // the rule that an interactive element always carries an accessible name is not
1413
+ // the caller's to waive: without this, `as={RouterLink} href="/x" role="img"`
1414
+ // with `alt=""` rendered a real anchor as `aria-hidden` and nameless — the very
1415
+ // failure #668 is about. `Navbar.Link` orders the same two the same way.
1416
+ //
1417
+ // The signal has to MEAN what it is used for, so both halves read a value rather
1418
+ // than a presence — the way `Navbar.Link` reads `role === 'button'`. A role only
1419
+ // claims to be a picture if it says so: `role="button"` or `role="link"` is the
1420
+ // opposite claim, and taking any role as the signal handed an interactive-role
1421
+ // element `aria-hidden` and no name. Likewise `aria-hidden={false}` denies
1422
+ // hiding, so only a truthy one counts.
1423
+ const ariaHidden = rest['aria-hidden'];
1424
+ const statesItIsNotAControl = (rest.role !== undefined && NON_INTERACTIVE_ROLES.includes(rest.role)) ||
1425
+ ariaHidden === true ||
1426
+ ariaHidden === 'true';
1427
+ const customTargetStatesSemantics = typeof Tag !== 'string' && href == null && statesItIsNotAControl;
1382
1428
  const isInteractive = Tag === 'a' ||
1383
1429
  Tag === 'button' ||
1384
- ((typeof Tag !== 'string' || isCustomElement(Tag)) && href != null);
1430
+ (typeof Tag !== 'string' && !customTargetStatesSemantics) ||
1431
+ (isCustomElement(Tag) && href != null);
1385
1432
  // Only forward link attributes when rendering an anchor or a custom (non-DOM)
1386
1433
  // component; a plain `as="div"` must not receive a stray `href`/`target`/`rel`.
1387
1434
  const isLinkLike = Tag === 'a' || typeof Tag !== 'string' || isCustomElement(Tag);
1388
- const linkProps = isLinkLike ? { href, target, rel } : {};
1435
+ // Present-only, not `{ href, target, rel }`. An unconditional spread hands the
1436
+ // target these keys whatever the caller passed, and a key existing is not free:
1437
+ // a target that tests for one sees a link where there is none, and one that
1438
+ // spreads its own `{...rest}` onward passes the nothing along. It is NOT about
1439
+ // a destructuring default, which an explicit `undefined` triggers just as an
1440
+ // absent key does. What stops a target that REQUIRES one from being rendered
1441
+ // without it is the type (#665) — this is the smaller half, and the backstop for
1442
+ // the callers a type does not reach: a plain-JavaScript one and a loose spread,
1443
+ // the same pair `Button` and `Menu.Item` keep their own filters for.
1444
+ const linkProps = isLinkLike
1445
+ ? {
1446
+ ...(href !== undefined && { href }),
1447
+ ...(target !== undefined && { target }),
1448
+ ...(rel !== undefined && { rel }),
1449
+ }
1450
+ : {};
1389
1451
  // alt coalesces with ?? (not ||) so an explicit alt="" survives as the
1390
1452
  // standard decorative marker instead of being overridden by name.
1391
1453
  const accessibleName = alt ?? name;
@@ -2886,7 +2948,27 @@ const NavbarLink = React.forwardRef(function NavbarLink(linkProps, ref) {
2886
2948
  });
2887
2949
  const dropdownContext = React.useContext(NavbarDropdownContext);
2888
2950
  const hasHref = rest.href !== undefined;
2889
- const isNativeInteractive = Component === 'button' || hasHref;
2951
+ // What a custom component renders cannot be read off its input props, and the
2952
+ // prop that ends in an anchor belongs to the router, not to us — `to`, `state`,
2953
+ // `params` and a dozen further spellings all get there. Sniffing for more names
2954
+ // trades one wrong guess for another, so a non-string `as` counts as
2955
+ // interactive: announcing a real anchor as a button, and layering a synthetic
2956
+ // click over its navigation, is the worse of the two failures (#668).
2957
+ //
2958
+ // A custom ELEMENT stays out of it. A hyphenated tag is a real DOM element and
2959
+ // none of those is natively interactive, so `<x-trigger>` keeps the fallback
2960
+ // exactly like `as="span"` — the same line `Avatar` draws for `role="img"`.
2961
+ //
2962
+ // Where we are guessing, the caller settles it: a custom target that declares
2963
+ // `role="button"` is saying it is a button and not a link, so it takes the
2964
+ // whole fallback — including the click, which is the half it could not supply
2965
+ // itself. `Avatar` gives the same escape hatch to the same guess. An `href`
2966
+ // still wins: a target with somewhere to navigate is a link whatever role it
2967
+ // claims.
2968
+ const customTargetIsButton = typeof Component !== 'string' && rest.role === 'button';
2969
+ const isNativeInteractive = Component === 'button' ||
2970
+ (typeof Component !== 'string' && !customTargetIsButton) ||
2971
+ hasHref;
2890
2972
  // Guarded like Button's disabled blocker: these run on whatever `as` renders,
2891
2973
  // and a custom target's callback need not take a DOM event. One declaring
2892
2974
  // `onKeyDown: (k: {key: string}) => void` reaches `e.preventDefault()` and