@lumx/react 4.17.0-next.1 → 4.17.0-next.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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { HorizontalAlignment as HorizontalAlignment$1, Orientation as Orientation$1, Alignment as Alignment$1, Size as Size$1, AspectRatio as AspectRatio$1, ColorPalette as ColorPalette$1, Kind as Kind$1, Emphasis as Emphasis$1, Theme as Theme$1 } from '@lumx/core/js/constants';
2
2
  export * from '@lumx/core/js/constants';
3
3
  import * as _lumx_core_js_types from '@lumx/core/js/types';
4
- import { ValueOf as ValueOf$1, GenericProps as GenericProps$1, HasTheme as HasTheme$1, PropsToOverride, HasAriaDisabled as HasAriaDisabled$1, HasRequiredLinkHref as HasRequiredLinkHref$1, HasClassName as HasClassName$1, HasCloseMode as HasCloseMode$1, JSXElement as JSXElement$1, CommonRef as CommonRef$1, Falsy, HeadingElement as HeadingElement$1, NamedProps, HasAriaLabelOrLabelledBy as HasAriaLabelOrLabelledBy$1 } from '@lumx/core/js/types';
4
+ import { ValueOf as ValueOf$1, GenericProps as GenericProps$1, HasTheme as HasTheme$1, PropsToOverride, HasAriaDisabled as HasAriaDisabled$1, HasRequiredLinkHref as HasRequiredLinkHref$1, HasClassName as HasClassName$1, HasCloseMode as HasCloseMode$1, JSXElement as JSXElement$1, CommonRef as CommonRef$1, Falsy, HeadingElement as HeadingElement$1, HasAriaLabelOrLabelledBy as HasAriaLabelOrLabelledBy$1, NamedProps } from '@lumx/core/js/types';
5
5
  export * from '@lumx/core/js/types';
6
6
  import * as React$1 from 'react';
7
7
  import React__default, { Ref, ReactElement, ReactNode, SyntheticEvent, MouseEventHandler, KeyboardEventHandler, RefObject, SetStateAction, Key, CSSProperties, ElementType as ElementType$1, HTMLInputTypeAttribute, ComponentProps, ImgHTMLAttributes } from 'react';
@@ -3472,7 +3472,26 @@ interface LinkPreviewProps extends GenericProps$1, ReactToJSX<LinkPreviewProps$1
3472
3472
  */
3473
3473
  declare const LinkPreview: Comp<LinkPreviewProps, HTMLDivElement>;
3474
3474
 
3475
+ type MenuButtonVariant = 'button' | 'icon-button' | 'chip' | 'link';
3476
+ /** ARIA keys set by MenuButton on the trigger — omitted from variant component props. */
3477
+ type MenuButtonAriaKeys = 'aria-haspopup' | 'aria-controls' | 'aria-expanded';
3478
+ /** Per-variant keys internally managed by MenuButton — omitted from variant component props. */
3479
+ type MenuButtonVariantsInternalKeys = {
3480
+ button: MenuButtonAriaKeys;
3481
+ 'icon-button': MenuButtonAriaKeys;
3482
+ chip: MenuButtonAriaKeys | 'isClickable';
3483
+ link: MenuButtonAriaKeys | 'href' | 'linkAs';
3484
+ };
3485
+ /** Discriminated union of MenuButton props across all trigger variants. */
3486
+ type MenuButtonVariantsProps<TBase, TVariantProps extends Record<MenuButtonVariant, any>> = {
3487
+ [V in MenuButtonVariant]: TBase & (V extends 'button' ? {
3488
+ variant?: V;
3489
+ } : {
3490
+ variant: V;
3491
+ }) & Omit<TVariantProps[V], MenuButtonVariantsInternalKeys[V] | keyof TBase>;
3492
+ }[MenuButtonVariant];
3475
3493
  interface MenuButtonProps$1 {
3494
+ variant?: MenuButtonVariant;
3476
3495
  label?: JSXElement;
3477
3496
  children?: JSXElement;
3478
3497
  triggerProps?: Record<string, any>;
@@ -3481,25 +3500,9 @@ interface MenuButtonProps$1 {
3481
3500
  }
3482
3501
 
3483
3502
  /** MenuPopover props. */
3484
- interface MenuPopoverProps$1 extends HasClassName {
3503
+ interface MenuPopoverProps$1 extends HasClassName, Pick<PopoverProps$1, 'placement' | 'anchorRef' | 'isOpen' | 'handleClose'> {
3485
3504
  /** Popover content (a `Menu`). */
3486
3505
  children?: JSXElement;
3487
- /** Whether the popover is open. */
3488
- isOpen?: boolean;
3489
- /** Placement relative to the anchor. Defaults to `'bottom-start'`. */
3490
- placement?: Placement;
3491
- /** Reference to the anchor element. */
3492
- anchorRef?: CommonRef;
3493
- /** Callback invoked when the popover requests to close (click away, escape). */
3494
- handleClose?(): void;
3495
- /** Whether the popover should close when clicking outside. Default: true. */
3496
- closeOnClickAway?: boolean;
3497
- /** Whether the popover should close on Escape. Default: true. */
3498
- closeOnEscape?: boolean;
3499
- /** Whether to render in a portal. Default: false (avoid stacking-context surprises). */
3500
- usePortal?: boolean;
3501
- /** Whether to focus the anchor on close. Default: true. */
3502
- focusAnchorOnClose?: boolean;
3503
3506
  }
3504
3507
 
3505
3508
  /** Popover props forwarded to the inner Popover (minus managed props). */
@@ -3509,35 +3512,27 @@ interface MenuPopoverProps extends ReactToJSX<MenuPopoverProps$1, 'isOpen' | 'an
3509
3512
  children: ReactNode;
3510
3513
  }
3511
3514
 
3512
- /** Keys managed by MenuButton omitted from the polymorphic trigger props. */
3513
- type OmittedTriggerKeys = 'aria-haspopup' | 'aria-controls' | 'aria-expanded' | 'label' | 'children' | 'ref';
3514
- /** Polymorphic trigger props with index signature stripped and managed keys removed. */
3515
- type TriggerProps$1<E extends ElementType$1> = Omit<NamedProps<React__default.ComponentProps<E>>, OmittedTriggerKeys>;
3516
- /** Menu button props */
3517
- type MenuButtonProps<E extends ElementType$1 = typeof Button> = TriggerProps$1<E> & ReactToJSX<MenuButtonProps$1, 'triggerProps'> & {
3518
- /** Customize the rendered trigger component. */
3519
- as?: E;
3515
+ /** Props that MenuButton explicitly declares. */
3516
+ type MenuButtonBase = ReactToJSX<MenuButtonProps$1, 'triggerProps' | 'variant'> & {
3520
3517
  children?: React__default.ReactNode;
3521
3518
  popoverProps?: MenuPopoverProps;
3522
3519
  onOpen?: (isOpen: boolean) => void;
3520
+ label: string;
3523
3521
  };
3522
+ /** MenuButton props — discriminated union over the variant to inherit the target component's props. */
3523
+ type MenuButtonProps = MenuButtonVariantsProps<MenuButtonBase, {
3524
+ button: ButtonProps;
3525
+ 'icon-button': IconButtonProps;
3526
+ chip: ChipProps;
3527
+ link: LinkProps;
3528
+ }>;
3524
3529
  /**
3525
3530
  * MenuButton component.
3526
3531
  *
3527
3532
  * @param props Component props.
3528
3533
  * @return React element.
3529
3534
  */
3530
- declare const MenuButton: (<E extends ElementType$1 = Comp<ButtonProps, HTMLButtonElement | HTMLAnchorElement>>(props: TriggerProps$1<E> & ReactToJSX<MenuButtonProps$1, "triggerProps"> & {
3531
- /** Customize the rendered trigger component. */
3532
- as?: E | undefined;
3533
- children?: React__default.ReactNode;
3534
- popoverProps?: MenuPopoverProps;
3535
- onOpen?: (isOpen: boolean) => void;
3536
- } & React__default.ComponentProps<E> & {
3537
- ref?: ComponentRef<E> | undefined;
3538
- }) => React__default.JSX.Element) & {
3539
- displayName: string;
3540
- };
3535
+ declare const MenuButton: Comp<MenuButtonProps, HTMLElement>;
3541
3536
 
3542
3537
  /** MenuItem props. */
3543
3538
  interface MenuItemProps$1 extends HasClassName {
@@ -3573,6 +3568,8 @@ interface MenuItemProps<E extends ElementType$1 = 'button'> extends GenericProps
3573
3568
  onClick?(event: SyntheticEvent): void;
3574
3569
  /** MDI icon rendered as `<Icon size="xs" />` prepended to the `before` slot. */
3575
3570
  icon?: string;
3571
+ /** MDI icon rendered as `<Icon size="xs" />` appended to the `after` slot. */
3572
+ afterIcon?: string;
3576
3573
  /** Foreground color applied to the icon and label text. */
3577
3574
  color?: ColorPalette$1;
3578
3575
  /** Content rendered before the label (rendered AFTER `icon` if both are provided). */
package/index.js CHANGED
@@ -46,6 +46,7 @@ import range from 'lodash/range.js';
46
46
  import { mdiPlayCircleOutline } from '@lumx/icons/esm/play-circle-outline.js';
47
47
  import { mdiPauseCircleOutline } from '@lumx/icons/esm/pause-circle-outline.js';
48
48
  import chunk from 'lodash/chunk.js';
49
+ import { mdiDotsVertical } from '@lumx/icons/esm/dots-vertical.js';
49
50
  import take from 'lodash/take.js';
50
51
  import { mdiRadioboxBlank } from '@lumx/icons/esm/radiobox-blank.js';
51
52
  import { mdiRadioboxMarked } from '@lumx/icons/esm/radiobox-marked.js';
@@ -14709,23 +14710,45 @@ const COMPONENT_NAME$J = 'MenuButton';
14709
14710
 
14710
14711
  /** Menu button core template (composition of menu provider, trigger, popover and list) */
14711
14712
  const MenuButton$1 = (props, {
14712
- Menu
14713
+ MenuProvider,
14714
+ MenuTrigger,
14715
+ MenuPopover,
14716
+ MenuList
14713
14717
  }) => {
14714
14718
  const {
14715
14719
  label,
14716
14720
  children,
14717
14721
  triggerProps,
14718
14722
  popoverProps,
14719
- onOpen
14723
+ onOpen,
14724
+ variant
14720
14725
  } = props;
14721
- return /*#__PURE__*/jsxs(Menu.Provider, {
14726
+ const extraTriggerProps = {};
14727
+ if (variant === 'chip') {
14728
+ // Chip render as clickable (since the component cannot detect this automatically)
14729
+ extraTriggerProps.isClickable = true;
14730
+ }
14731
+ let triggerChildren;
14732
+ if (variant === 'icon-button') {
14733
+ // Label as prop (renders as tooltip label)
14734
+ extraTriggerProps.label = label;
14735
+ // Default icon
14736
+ if (!triggerProps?.icon) {
14737
+ extraTriggerProps.icon = mdiDotsVertical;
14738
+ }
14739
+ } else {
14740
+ // Only set the label as children when we are not displaying an icon-button
14741
+ triggerChildren = label;
14742
+ }
14743
+ return /*#__PURE__*/jsxs(MenuProvider, {
14722
14744
  onOpen: onOpen,
14723
- children: [/*#__PURE__*/jsx(Menu.Trigger, {
14745
+ children: [/*#__PURE__*/jsx(MenuTrigger, {
14724
14746
  ...triggerProps,
14725
- children: label
14726
- }), /*#__PURE__*/jsx(Menu.Popover, {
14747
+ ...extraTriggerProps,
14748
+ children: triggerChildren
14749
+ }), /*#__PURE__*/jsx(MenuPopover, {
14727
14750
  ...popoverProps,
14728
- children: /*#__PURE__*/jsx(Menu.List, {
14751
+ children: /*#__PURE__*/jsx(MenuList, {
14729
14752
  children: children
14730
14753
  })
14731
14754
  })]
@@ -15060,11 +15083,11 @@ function setupMenu(options = {}) {
15060
15083
 
15061
15084
  const MenuContext = /*#__PURE__*/createContext(undefined);
15062
15085
 
15063
- /** Use Menu context. @throws if used outside `Menu.Provider`. */
15086
+ /** Use Menu context. @throws if used outside `MenuProvider`. */
15064
15087
  function useMenuContext() {
15065
15088
  const context = useContext(MenuContext);
15066
15089
  if (!context) {
15067
- throw new Error('Menu sub-components must be used within a Menu.Provider');
15090
+ throw new Error('Menu sub-components must be used within a MenuProvider');
15068
15091
  }
15069
15092
  return context;
15070
15093
  }
@@ -15235,10 +15258,6 @@ const MenuPopover$1 = (props, {
15235
15258
  placement = 'bottom-start',
15236
15259
  anchorRef,
15237
15260
  handleClose,
15238
- closeOnClickAway = true,
15239
- closeOnEscape = true,
15240
- usePortal = false,
15241
- focusAnchorOnClose = true,
15242
15261
  ...forwardedProps
15243
15262
  } = props;
15244
15263
  return /*#__PURE__*/jsx(Popover, {
@@ -15247,10 +15266,10 @@ const MenuPopover$1 = (props, {
15247
15266
  anchorRef: anchorRef,
15248
15267
  isOpen: isOpen,
15249
15268
  onClose: handleClose,
15250
- closeOnClickAway: closeOnClickAway,
15251
- closeOnEscape: closeOnEscape,
15252
- usePortal: usePortal,
15253
- focusAnchorOnClose: focusAnchorOnClose,
15269
+ closeOnClickAway: true,
15270
+ closeOnEscape: true,
15271
+ usePortal: false,
15272
+ focusAnchorOnClose: true,
15254
15273
  withFocusTrap: false,
15255
15274
  closeMode: "hide",
15256
15275
  fitToAnchorWidth: false,
@@ -15364,18 +15383,17 @@ const MenuList = forwardRef((props, ref) => {
15364
15383
  MenuList.displayName = COMPONENT_NAME$G;
15365
15384
  MenuList.className = CLASSNAME$H;
15366
15385
 
15367
- const Menu = {
15368
- Provider: MenuProvider,
15369
- Trigger: MenuTrigger,
15370
- Popover: MenuPopover,
15371
- List: MenuList
15372
- };
15373
-
15374
- /** Keys managed by MenuButton — omitted from the polymorphic trigger props. */
15386
+ /** Props that MenuButton explicitly declares. */
15375
15387
 
15376
- /** Polymorphic trigger props with index signature stripped and managed keys removed. */
15388
+ /** MenuButton props discriminated union over the variant to inherit the target component's props. */
15377
15389
 
15378
- /** Menu button props */
15390
+ /** Menu trigger button component by variant */
15391
+ const TRIGGER_COMPONENTS = {
15392
+ button: Button,
15393
+ 'icon-button': IconButton,
15394
+ chip: Chip,
15395
+ link: Link
15396
+ };
15379
15397
 
15380
15398
  /**
15381
15399
  * MenuButton component.
@@ -15383,37 +15401,34 @@ const Menu = {
15383
15401
  * @param props Component props.
15384
15402
  * @return React element.
15385
15403
  */
15386
- const MenuButton = Object.assign(forwardRefPolymorphic((props, ref) => {
15404
+ const MenuButton = forwardRef((props, ref) => {
15387
15405
  const {
15388
15406
  label,
15389
15407
  children,
15390
15408
  popoverProps,
15391
15409
  onOpen,
15392
- as,
15410
+ variant = 'button',
15393
15411
  ...triggerProps
15394
15412
  } = props;
15395
- const isIconButton = as === IconButton;
15396
- const triggerLabel = isIconButton ? undefined : label;
15397
- const extraTriggerProps = isIconButton ? {
15398
- label
15399
- } : {};
15400
15413
  return MenuButton$1({
15401
- label: triggerLabel,
15414
+ label,
15402
15415
  children,
15403
15416
  popoverProps,
15404
15417
  onOpen,
15418
+ variant,
15405
15419
  triggerProps: {
15406
15420
  ...triggerProps,
15407
- ...extraTriggerProps,
15408
- as,
15421
+ as: TRIGGER_COMPONENTS[variant],
15409
15422
  ref
15410
15423
  }
15411
15424
  }, {
15412
- Menu
15425
+ MenuProvider,
15426
+ MenuTrigger,
15427
+ MenuPopover,
15428
+ MenuList
15413
15429
  });
15414
- }), {
15415
- displayName: COMPONENT_NAME$J
15416
15430
  });
15431
+ MenuButton.displayName = COMPONENT_NAME$J;
15417
15432
 
15418
15433
  /** MenuItem props. */
15419
15434
 
@@ -15475,6 +15490,7 @@ const MenuItem = forwardRef((props, ref) => {
15475
15490
  const {
15476
15491
  children,
15477
15492
  icon,
15493
+ afterIcon,
15478
15494
  color,
15479
15495
  before,
15480
15496
  after,
@@ -15509,12 +15525,21 @@ const MenuItem = forwardRef((props, ref) => {
15509
15525
  color: color
15510
15526
  }), before]
15511
15527
  }) : before;
15528
+
15529
+ // Append the optional `afterIcon` to the `after` slot.
15530
+ const mergedAfter = afterIcon ? /*#__PURE__*/jsxs(Fragment, {
15531
+ children: [after, /*#__PURE__*/jsx(Icon, {
15532
+ icon: afterIcon,
15533
+ size: "xs",
15534
+ color: color
15535
+ })]
15536
+ }) : after;
15512
15537
  return MenuItem$1({
15513
15538
  ...rest,
15514
15539
  ref: mergedRef,
15515
15540
  actionRef,
15516
15541
  before: mergedBefore,
15517
- after,
15542
+ after: mergedAfter,
15518
15543
  children: /*#__PURE__*/jsx(Text, {
15519
15544
  as: "span",
15520
15545
  color: color,