@allxsmith/bestax-bulma 5.15.1 → 5.15.2

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.esm.js CHANGED
@@ -2000,6 +2000,33 @@ const DropdownComponent = forwardRef(function DropdownComponent({ label, childre
2000
2000
  const dropdownClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
2001
2001
  return (jsxs("div", { className: dropdownClasses, ref: setRefs, id: id, "data-testid": "dropdown-root", ...rest, children: [jsx("div", { className: usePrefixedClassNames('dropdown-trigger'), children: 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: [jsx("span", { children: label }), jsx("span", { className: usePrefixedClassNames('icon', 'is-small'), "aria-hidden": "true", children: jsx("i", { className: "fas fa-angle-down" }) })] }) }), jsx("div", { className: classNames(usePrefixedClassNames('dropdown-menu'), menuClassName), id: id ? `${id}-menu` : undefined, role: "menu", "data-testid": "dropdown-menu", onKeyDown: handleMenuKeyDown, children: jsx("div", { className: usePrefixedClassNames('dropdown-content'), onClick: handleMenuClick, tabIndex: -1, children: children }) })] }));
2002
2002
  });
2003
+ /**
2004
+ * The anchor-only attributes, withheld from a `<div>` or a `<button>`.
2005
+ *
2006
+ * Mirrors `LINK_ATTRS` in `bestax-migrate/src/sources/_shared/polymorphic.ts`,
2007
+ * which drops the same set when a migration lands one on a non-anchor. `rel` is
2008
+ * absent from both on purpose: React declares it on `HTMLAttributes<T>` — every
2009
+ * element — so withholding it would diverge from React's own typing, the same
2010
+ * call #641 recorded for `Navbar.Link`.
2011
+ */
2012
+ const LINK_ONLY_ATTRS = [
2013
+ 'href',
2014
+ 'target',
2015
+ 'download',
2016
+ 'hrefLang',
2017
+ 'ping',
2018
+ 'referrerPolicy',
2019
+ 'media',
2020
+ ];
2021
+ /** `props` without any attribute only an anchor can carry. */
2022
+ function omitLinkAttrs(props) {
2023
+ const out = {};
2024
+ for (const [key, value] of Object.entries(props)) {
2025
+ if (!LINK_ONLY_ATTRS.includes(key))
2026
+ out[key] = value;
2027
+ }
2028
+ return out;
2029
+ }
2003
2030
  /**
2004
2031
  * Bulma Dropdown item.
2005
2032
  *
@@ -2007,12 +2034,34 @@ const DropdownComponent = forwardRef(function DropdownComponent({ label, childre
2007
2034
  * @param {DropdownItemProps} props - Props for the DropdownItem component.
2008
2035
  * @returns {JSX.Element} The rendered dropdown item.
2009
2036
  */
2010
- const DropdownItem = ({ children, active, className, as: Component = 'a', ...props }) => {
2037
+ const DropdownItem = ((itemProps) => {
2038
+ const { children, active, className, as: Component = 'a', ...props } = itemProps;
2011
2039
  const { bulmaHelperClasses, rest } = useBulmaClasses(props);
2040
+ // The anchor's attributes reach an anchor and nothing else — `<div href>` and
2041
+ // `<button target>` are invalid HTML. The same rule Menu applies, for the same
2042
+ // reason: the type now derives these from `as`, and deriving them must not
2043
+ // quietly widen where they land. The type stops a direct caller; this stops a
2044
+ // plain-JS one, a loose `{...props}` spread, and the genericity a wrapping HOC
2045
+ // erases.
2046
+ //
2047
+ // The whole link set, not `href` alone. Menu strips only `href` because its
2048
+ // props never gained the rest; here they all arrive together under `as="a"`,
2049
+ // and `bestax-migrate` already removes exactly this set (`LINK_ATTRS`) when it
2050
+ // migrates onto a non-anchor — so stripping less would leave the codemod
2051
+ // stricter than the component it migrates to.
2052
+ //
2053
+ // Menu's condition also admits a custom component and a custom element, which
2054
+ // own their prop contracts. `as` is closed to three intrinsic tags here, so
2055
+ // neither can arrive and the anchor test is the whole rule.
2056
+ const forwarded = Component === 'a' ? rest : omitLinkAttrs(rest);
2012
2057
  return (jsx(Component, { className: classNames(usePrefixedClassNames('dropdown-item', {
2013
2058
  'is-active': active,
2014
- }), bulmaHelperClasses, className), tabIndex: 0, role: "menuitem", "data-testid": "dropdown-item", ...rest, children: children }));
2015
- };
2059
+ }), bulmaHelperClasses, className), tabIndex: 0, role: "menuitem", "data-testid": "dropdown-item", ...forwarded, ...(Component === 'button'
2060
+ ? {
2061
+ type: forwarded.type ?? 'button',
2062
+ }
2063
+ : {}), children: children }));
2064
+ });
2016
2065
  /**
2017
2066
  * Bulma Dropdown divider.
2018
2067
  *
@@ -3128,10 +3177,11 @@ containerClassName, children, ...restProps }) => {
3128
3177
  // component, …) in place of a class-based glyph. Library/variant/features don't apply.
3129
3178
  return (jsx("span", { className: iconContainerClasses, "aria-label": ariaLabel, style: style, ...rest, children: children }));
3130
3179
  }
3131
- // `name` is guaranteed once `children` is absent (`IconProps` is a discriminated union of
3132
- // the two, and `IconChildrenProps['children']` excludes `undefined` so `children={undefined}`
3133
- // can't slip past into this branch) — the cast only matters for legacy callers that bypass
3134
- // the type and rely solely on the deprecated `icon` prop below.
3180
+ // `name` is guaranteed once `children` is absent UNLESS the caller is on the deprecated
3181
+ // `icon` path, which `IconDeprecatedProps` declares with `name?: undefined`.
3182
+ // (`IconChildrenProps['children']` excludes `undefined`, so `children={undefined}` can't
3183
+ // slip past into this branch.) The cast covers that third member, and the `!name && icon`
3184
+ // fallback below is what fills it in.
3135
3185
  let finalName = name;
3136
3186
  if (!name && icon) {
3137
3187
  // If icon prop is provided instead of name, try to parse it
@@ -3155,9 +3205,10 @@ containerClassName, children, ...restProps }) => {
3155
3205
  // library is 'fa'), so `name` behaves identically with or without the prefix.
3156
3206
  finalName = stripRedundantLibraryPrefix(finalName, finalLibrary);
3157
3207
  if (!finalName) {
3158
- // No glyph to name. Unreachable through the public type, but a plain-JS caller (or one
3159
- // that casts) can land here, and building a class off an absent name produced a bogus
3160
- // `fa-undefined` glyph. Render the bare container instead, matching the `children` branch.
3208
+ // No glyph to name. Reachable through the public type only as `icon=""`, and otherwise
3209
+ // by a plain-JS caller (or one that casts). Building a class off an absent name produced
3210
+ // a bogus `fa-undefined` glyph; render the bare container instead, matching the
3211
+ // `children` branch.
3161
3212
  return (jsx("span", { className: iconContainerClasses, "aria-label": ariaLabel, style: style, ...rest }));
3162
3213
  }
3163
3214
  // Backward compatibility: if libraryFeatures is provided, parse it for variant and features
@@ -5600,15 +5651,49 @@ const Figure = withSubComponents(FigureComponent, {
5600
5651
  }, 'Figure');
5601
5652
 
5602
5653
  /**
5603
- * Distinguishes an `IconProps` object from a plain custom node (an inline SVG, a `react-icons`
5604
- * component, …) passed to a slot that accepts either.
5654
+ * Distinguishes an `IconProps` object from a plain custom node (an inline SVG, a
5655
+ * `react-icons` component, …) in a slot that accepts either — `Control`'s
5656
+ * `iconLeft`/`iconRight`, `IconText`'s `iconProps`.
5657
+ *
5658
+ * One copy, imported by both consumers: two hand-maintained copies, one per
5659
+ * consumer, is how the deprecated `icon` path came to crash both (#663).
5660
+ *
5661
+ * Its own module rather than `Icon.tsx` because `src/index.ts` wildcard-exports
5662
+ * that file, and everything published there is public forever. `polymorphic.ts`
5663
+ * makes the same call for `isCustomElement`: an internal discriminator is not
5664
+ * something to support for the life of the package.
5665
+ *
5666
+ * It tests each member's VALUE, not merely its key, and only after everything
5667
+ * React owns is out of the way. `'icon' in value` was enough
5668
+ * to claim a Font Awesome `IconDefinition` — `{ prefix, iconName, icon: [w, h, …,
5669
+ * path] }` — whose `icon` is a path array rather than a class string. That object
5670
+ * is not a renderable node either, so the honest outcome is the one this slot has
5671
+ * always had for it: the node branch, and React's own "Objects are not valid as a
5672
+ * React child". Claiming it here instead rendered a blank container that still
5673
+ * reserved layout.
5674
+ *
5675
+ * A member added to `IconProps` needs a line here, and a missed one is a crash
5676
+ * rather than a fallthrough. That is the cost of a slot taking either a props
5677
+ * object or a node; keeping the guard in one place is what keeps the cost to a
5678
+ * single line.
5605
5679
  */
5606
- function isIconProps$1(value) {
5607
- return (typeof value === 'object' &&
5608
- value !== null &&
5609
- !React.isValidElement(value) &&
5610
- ('name' in value || 'children' in value));
5680
+ function isIconProps(value) {
5681
+ if (typeof value !== 'object' || value === null)
5682
+ return false;
5683
+ // Anything React owns. `isValidElement` covers elements only; a PORTAL is a
5684
+ // valid `ReactNode` that fails it and carries a `children` key, so the member
5685
+ // test below claimed it and `Control` spread it into `<Icon>` as props —
5686
+ // rendering the portal's child locally instead of in its container. Every
5687
+ // React internal carries `$$typeof`, so testing for it covers lazy, context
5688
+ // and whatever React adds next, rather than portals alone.
5689
+ if (React.isValidElement(value) || '$$typeof' in value)
5690
+ return false;
5691
+ const candidate = value;
5692
+ return (typeof candidate.name === 'string' ||
5693
+ typeof candidate.icon === 'string' ||
5694
+ 'children' in candidate);
5611
5695
  }
5696
+
5612
5697
  /**
5613
5698
  * The `IconText` component provides a Bulma-styled horizontal arrangement of one or more `Icon` components and optional text.
5614
5699
  *
@@ -5629,8 +5714,8 @@ const IconTextComponent = ({ className, textColor, color, bgColor, iconProps, ch
5629
5714
  const bulmaClasses = usePrefixedClassNames('icon-text');
5630
5715
  const iconTextClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
5631
5716
  return (jsx("span", { className: iconTextClasses, ...rest, children: items ? (items.map((item, index) => (jsxs(React.Fragment, { children: [item.iconProps &&
5632
- (isIconProps$1(item.iconProps) ? (jsx(Icon, { ...item.iconProps })) : (jsx(Icon, { children: item.iconProps }))), item.text && jsx("span", { children: item.text })] }, index)))) : (jsxs(Fragment, { children: [iconProps &&
5633
- (isIconProps$1(iconProps) ? (jsx(Icon, { ...iconProps })) : (jsx(Icon, { children: iconProps }))), children && jsx("span", { children: children })] })) }));
5717
+ (isIconProps(item.iconProps) ? (jsx(Icon, { ...item.iconProps })) : (jsx(Icon, { children: item.iconProps }))), item.text && jsx("span", { children: item.text })] }, index)))) : (jsxs(Fragment, { children: [iconProps &&
5718
+ (isIconProps(iconProps) ? (jsx(Icon, { ...iconProps })) : (jsx(Icon, { children: iconProps }))), children && jsx("span", { children: children })] })) }));
5634
5719
  };
5635
5720
  const IconText = withSubComponents(IconTextComponent, { Icon }, 'IconText');
5636
5721
 
@@ -6544,16 +6629,6 @@ const Checkbox = forwardRef(({ color, size, className, children, textColor, disa
6544
6629
  });
6545
6630
  Checkbox.displayName = 'Checkbox';
6546
6631
 
6547
- /**
6548
- * Distinguishes an `IconProps` object from a plain custom node (an inline SVG, a `react-icons`
6549
- * component, …) passed to a slot that accepts either.
6550
- */
6551
- function isIconProps(value) {
6552
- return (typeof value === 'object' &&
6553
- value !== null &&
6554
- !React.isValidElement(value) &&
6555
- ('name' in value || 'children' in value));
6556
- }
6557
6632
  const allowedColors = [...validColors, 'inherit', 'current'];
6558
6633
  /**
6559
6634
  * The `Control` component is a Bulma-styled wrapper for form controls (`Input`, `Select`, `TextArea`, etc.), supporting icons (left/right), loading state, expansion, size, and Bulma helper props for layout and color.