@trackunit/react-components 0.4.33 → 0.4.34

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.cjs.js CHANGED
@@ -3739,7 +3739,7 @@ const PopoverContent = React.forwardRef(function PopoverContent({ className, dat
3739
3739
  var _a;
3740
3740
  const { context: floatingContext, customProps, ...context } = usePopoverContext();
3741
3741
  const ref = react.useMergeRefs([context.refs.setFloating, propRef]);
3742
- return (jsxRuntime.jsx(react.FloatingPortal, { id: portalId !== null && portalId !== void 0 ? portalId : "tu-floating-ui", children: context.isOpen ? (jsxRuntime.jsx(react.FloatingFocusManager, { closeOnFocusOut: false, context: floatingContext, guards: false, modal: context.isModal, order: ["reference", "content"], returnFocus: false, children: jsxRuntime.jsx("div", { "aria-describedby": context.descriptionId, "aria-labelledby": context.labelId, className: cvaPopoverContainer({ className: className !== null && className !== void 0 ? className : customProps.className }), "data-testid": (_a = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _a !== void 0 ? _a : "popover-content", ref: ref, style: {
3742
+ return (jsxRuntime.jsx(react.FloatingPortal, { id: portalId !== null && portalId !== void 0 ? portalId : "tu-floating-ui", children: context.isOpen ? (jsxRuntime.jsx(react.FloatingFocusManager, { closeOnFocusOut: false, context: floatingContext, guards: true, modal: context.isModal, order: ["reference", "content"], returnFocus: true, children: jsxRuntime.jsx("div", { "aria-describedby": context.descriptionId, "aria-labelledby": context.labelId, className: cvaPopoverContainer({ className: className !== null && className !== void 0 ? className : customProps.className }), "data-testid": (_a = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _a !== void 0 ? _a : "popover-content", ref: ref, style: {
3743
3743
  position: context.strategy,
3744
3744
  top: context.y,
3745
3745
  left: context.x,
@@ -4036,6 +4036,36 @@ const KPICard = ({ asChild = false, title, value, loading, unit, iconName, iconB
4036
4036
  return (jsxRuntime.jsxs(Comp, { className: cvaKPICardContainer({ className, isClickable: Boolean(asChild || onClick) }), "data-testid": `${dataTestId}-comp`, onClick: onClick, ...rest, children: [tooltipLabel ? (jsxRuntime.jsx(Tooltip, { className: "w-full", label: tooltipLabel, placement: "bottom", children: jsxRuntime.jsx(CardContent, {}) })) : (jsxRuntime.jsx(CardContent, {})), !loading && jsxRuntime.jsx(reactSlot.Slottable, { children: rest.children })] }));
4037
4037
  };
4038
4038
 
4039
+ const cvaMenuList = cssClassVarianceUtilities.cvaMerge([
4040
+ "shadow",
4041
+ "rounded-lg",
4042
+ "z-popover",
4043
+ "bg-white",
4044
+ "border",
4045
+ "border-slate-300",
4046
+ "grid",
4047
+ "min-w-[200px]",
4048
+ "max-w-[300px]",
4049
+ "p-1",
4050
+ ], {
4051
+ variants: {
4052
+ stickyHeader: {
4053
+ true: "grid-rows-min-fr grid overflow-y-hidden",
4054
+ false: "",
4055
+ },
4056
+ },
4057
+ });
4058
+ const cvaMenuListDivider = cssClassVarianceUtilities.cvaMerge(["mx-[-4px]", "my-1", "min-h-px", "bg-slate-300"]);
4059
+ const cvaMenuListMultiSelect = cssClassVarianceUtilities.cvaMerge("hover:!bg-blue-200");
4060
+ const cvaMenuListItem = cssClassVarianceUtilities.cvaMerge("max-w-[290px]");
4061
+
4062
+ /**
4063
+ * The MenuDivider component is used to separate items in a menu list.
4064
+ */
4065
+ const MenuDivider = () => {
4066
+ return jsxRuntime.jsx("div", { className: cvaMenuListDivider(), "data-testid": "menu-divider" });
4067
+ };
4068
+
4039
4069
  /**
4040
4070
  * Applies standardized interaction-related styles to an element.
4041
4071
  *
@@ -4088,45 +4118,108 @@ const cvaInteractableItem = cssClassVarianceUtilities.cvaMerge("", {
4088
4118
  },
4089
4119
  });
4090
4120
 
4091
- const cvaMenuItemStyle = cssClassVarianceUtilities.cvaMerge(["py-2", "px-2", "w-full", "h-auto", "flex", "flex-row", "items-center", "gap-x-2", "select-none", "rounded"], {
4121
+ /**
4122
+ * Extends the cvaInteractableItem variant in order to set the padding, width, height, cursor, and other styles particular to the MenuItem component.
4123
+ * The cvaInteractableItem variant is used to set the standardized styles that change through interaction with the element (background color, hover, focus, and disabled).
4124
+ */
4125
+ const cvaMenuItem = (props) => {
4126
+ const { size, selected, disabled, focused, className, variant } = props !== null && props !== void 0 ? props : {};
4127
+ return tailwindMerge.twMerge(cvaMenuItemStyle({ size, variant, selected, disabled }), cvaInteractableItem({ selected, disabled, cursor: "pointer", focused }), className);
4128
+ };
4129
+ const cvaMenuItemStyle = cssClassVarianceUtilities.cvaMerge(["py-2", "px-2", "h-auto", "flex", "flex-row", "items-center", "gap-x-2", "select-none", "rounded", "text-sm"], {
4092
4130
  variants: {
4093
4131
  size: {
4094
4132
  small: "py-1",
4095
4133
  medium: "py-2",
4096
4134
  },
4135
+ variant: {
4136
+ primary: [],
4137
+ danger: [
4138
+ "text-danger-600",
4139
+ "hover:!bg-danger-100",
4140
+ "focus:!bg-danger-200",
4141
+ "hover:!text-danger-700",
4142
+ "focus:!text-danger-800",
4143
+ ],
4144
+ },
4145
+ selected: {
4146
+ true: "",
4147
+ false: "",
4148
+ },
4149
+ disabled: {
4150
+ true: "text-black opacity-50",
4151
+ false: "",
4152
+ },
4153
+ },
4154
+ compoundVariants: [
4155
+ {
4156
+ /* danger not multi-select enabled */
4157
+ selected: true,
4158
+ variant: "danger",
4159
+ className: ["!bg-white"],
4160
+ },
4161
+ ],
4162
+ defaultVariants: {
4163
+ variant: "primary",
4164
+ selected: false,
4165
+ disabled: false,
4097
4166
  },
4098
4167
  });
4099
- /**
4100
- * Extends the cvaInteractableItem variant in order to set the padding, width, height, cursor, and other styles particular to the MenuItem component.
4101
- * The cvaInteractableItem variant is used to set the standardized styles that change through interaction with the element (background color, hover, focus, and disabled).
4102
- */
4103
- const cvaMenuItem = (props) => {
4104
- const { size, selected, disabled, focused, className } = props !== null && props !== void 0 ? props : {};
4105
- return tailwindMerge.twMerge(cvaMenuItemStyle({ size }), cvaInteractableItem({ selected, disabled, cursor: "pointer", focused }), className);
4106
- };
4107
- const cvaMenuItemLabel = cssClassVarianceUtilities.cvaMerge([
4108
- "flex-grow",
4109
- "text-gray-700",
4110
- "text-ellipsis",
4111
- "truncate",
4112
- "group-hover:text-gray-900",
4113
- "group-active:text-gray-700",
4114
- ]);
4115
- const cvaMenuItemSuffix = cssClassVarianceUtilities.cvaMerge(["self-center", "flex-grow-0", "text-slate-400", "text-sm"], {
4168
+ const cvaMenuItemLabel = cssClassVarianceUtilities.cvaMerge(["flex-grow", "truncate", "text-black", "font-normal"], {
4169
+ variants: {
4170
+ variant: {
4171
+ primary: [],
4172
+ danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
4173
+ },
4174
+ disabled: {
4175
+ true: "text-black opacity-50",
4176
+ false: "",
4177
+ },
4178
+ },
4179
+ defaultVariants: {
4180
+ variant: "primary",
4181
+ disabled: false,
4182
+ },
4183
+ });
4184
+ const cvaMenuItemPrefix = cssClassVarianceUtilities.cvaMerge(["text-secondary-400", "hover:text-secondary-500", "focus:text-secondary-500", "h-min", "leading-[0]"], {
4116
4185
  variants: {
4117
4186
  selected: {
4118
- true: "text-primary-600 hover:text-primary-700",
4187
+ true: "text-secondary-600",
4188
+ false: "",
4189
+ },
4190
+ variant: {
4191
+ primary: [],
4192
+ danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
4193
+ },
4194
+ disabled: {
4195
+ true: "text-secondary opacity-50",
4119
4196
  false: "",
4120
4197
  },
4121
4198
  },
4199
+ defaultVariants: {
4200
+ variant: "primary",
4201
+ disabled: false,
4202
+ },
4122
4203
  });
4123
- const cvaMenuItemPrefix = cssClassVarianceUtilities.cvaMerge(["self-center", "flex-grow-0", "text-slate-400", "group-hover:text-slate-600", "h-min", "leading-[0]", "text-sm"], {
4204
+ const cvaMenuItemSuffix = cssClassVarianceUtilities.cvaMerge(["text-secondary-400", "text-sm"], {
4124
4205
  variants: {
4125
4206
  selected: {
4126
- true: "text-primary-600 hover:text-primary-700",
4207
+ true: "text-secondary-600",
4208
+ false: "",
4209
+ },
4210
+ variant: {
4211
+ primary: [],
4212
+ danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
4213
+ },
4214
+ disabled: {
4215
+ true: "text-secondary opacity-50",
4127
4216
  false: "",
4128
4217
  },
4129
4218
  },
4219
+ defaultVariants: {
4220
+ variant: "primary",
4221
+ disabled: false,
4222
+ },
4130
4223
  });
4131
4224
 
4132
4225
  /**
@@ -4135,46 +4228,81 @@ const cvaMenuItemPrefix = cssClassVarianceUtilities.cvaMerge(["self-center", "fl
4135
4228
  * @param {MenuItemProps} props - The props for the MenuItem component
4136
4229
  * @returns {JSX.Element} MenuItem component
4137
4230
  */
4138
- const MenuItem = ({ className, dataTestId, label, size, children, selected, prefix, suffix, disabled, onClick, stopPropagation = true, id, tabIndex, }) => {
4139
- return (jsxRuntime.jsxs("div", { className: cvaMenuItem({
4231
+ const MenuItem = ({ className, dataTestId, label, size, children, selected, prefix, suffix, disabled, onClick, stopPropagation = true, id, tabIndex, variant = "primary", }) => {
4232
+ /* Handle tab navigation */
4233
+ const handleKeyDown = (e) => {
4234
+ if (e.key === "Enter" && onClick && !disabled) {
4235
+ stopPropagation && e.stopPropagation();
4236
+ // eslint-disable-next-line local-rules/no-typescript-assertion
4237
+ onClick(e);
4238
+ }
4239
+ };
4240
+ return (jsxRuntime.jsxs("div", { "aria-disabled": disabled, className: cvaMenuItem({
4140
4241
  selected,
4141
4242
  disabled,
4142
4243
  size,
4143
4244
  className,
4144
- }), "data-testid": dataTestId !== null && dataTestId !== void 0 ? dataTestId : "menu-item", id: id, onClick: e => {
4245
+ variant,
4246
+ }), "data-testid": dataTestId ? `${dataTestId}-menu-item` : "menu-item", id: id, onClick: e => {
4145
4247
  stopPropagation && e.stopPropagation();
4146
4248
  onClick === null || onClick === void 0 ? void 0 : onClick(e);
4147
- }, role: "menuitem", tabIndex: tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0, children: [prefix ? (jsxRuntime.jsx("div", { className: cvaMenuItemPrefix({ selected }), "data-testid": dataTestId ? `${dataTestId}-prefix` : null, children: prefix })) : null, children && typeof children !== "string" ? (children) : (jsxRuntime.jsx("div", { className: cvaMenuItemLabel(), "data-testid": dataTestId ? `${dataTestId}-label` : null, children: children !== null && children !== void 0 ? children : label })), suffix ? (jsxRuntime.jsx("div", { className: cvaMenuItemSuffix({ selected }), "data-testid": dataTestId ? `${dataTestId}-suffix` : null, children: suffix })) : null] }));
4249
+ }, onKeyDown: handleKeyDown, role: "menuitem", tabIndex: disabled ? -1 : tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0, children: [prefix ? (jsxRuntime.jsx("div", { className: cvaMenuItemPrefix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-prefix` : "menu-item-prefix", children: prefix })) : null, children && typeof children !== "string" ? (children) : (jsxRuntime.jsx("div", { className: cvaMenuItemLabel({ variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-label` : "menu-item-label", children: children !== null && children !== void 0 ? children : label })), suffix ? (jsxRuntime.jsx("div", { className: cvaMenuItemSuffix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-suffix` : "menu-item-suffix", children: suffix })) : null] }));
4148
4250
  };
4149
4251
 
4150
- const cvaMenuList = cssClassVarianceUtilities.cvaMerge(["shadow-md", "rounded-lg", "z-popover", "bg-white", "border", "border-slate-300", "grid"], {
4151
- variants: {
4152
- stickyHeader: {
4153
- true: "grid-rows-min-fr grid overflow-y-hidden",
4154
- false: "",
4155
- },
4156
- },
4157
- });
4158
- const cvaMenuListDivider = cssClassVarianceUtilities.cvaMerge([
4159
- "file:w-full",
4160
- "selection:col-span-full",
4161
- "selection:h-px",
4162
- "selection:bg-slate-200",
4163
- ]);
4164
-
4165
4252
  /**
4166
- * The MenuList component is used for menus and selects.
4167
-
4253
+ * The MenuList is a popover menu that appears above all other content on the page. The menu offers a list of actions or functions that a user can access by clicking on a trigger.
4254
+ *
4255
+ * **When to use**
4256
+ * - Use the MenuList if you have limited space and need to display overflow actions in a list.
4257
+ * - Use the MenuList for actions that are not essential to completing workflows.
4258
+ * - Don’t use the MenuList to display single or multi-select items within form components. For dropdowns within select components, use SelectDropdown (component not available yet).
4259
+ *
4168
4260
  * @param {MenuListProps} props - The props for the MenuList component
4169
4261
  * @returns {JSX.Element} MenuList component
4170
4262
  */
4171
- const MenuList = ({ dataTestId, className, children, withStickyHeader = false, showDivider = false, ...args }) => {
4263
+ const MenuList = ({ dataTestId, className, children, withStickyHeader = false, isMulti = false, selectedItems: controlledSelectedItems, onSelectionChange, ...args }) => {
4172
4264
  const childrenArr = React.Children.toArray(children);
4173
- const isLastItem = (index) => index === childrenArr.length - 1;
4174
- return (jsxRuntime.jsx("div", { className: cvaMenuList({ stickyHeader: withStickyHeader, className }), "data-testid": dataTestId, onClick: args.onClick, role: "list", tabIndex: 0, children: React.Children.map(childrenArr, (menuItem, index) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [menuItem, showDivider && !isLastItem(index) ? jsxRuntime.jsx("hr", { className: cvaMenuListDivider() }) : null] }))) }));
4265
+ const [internalSelectedItems, setInternalSelectedItems] = React.useState(controlledSelectedItems !== null && controlledSelectedItems !== void 0 ? controlledSelectedItems : []);
4266
+ const selectedItems = controlledSelectedItems !== null && controlledSelectedItems !== void 0 ? controlledSelectedItems : internalSelectedItems;
4267
+ const handleItemClick = React.useCallback((id, disabled) => {
4268
+ if (disabled) {
4269
+ return;
4270
+ }
4271
+ const newSelectedItems = isMulti
4272
+ ? selectedItems.includes(id)
4273
+ ? selectedItems.filter(item => item !== id)
4274
+ : [...selectedItems, id]
4275
+ : [id];
4276
+ if (onSelectionChange) {
4277
+ onSelectionChange(newSelectedItems);
4278
+ }
4279
+ else {
4280
+ setInternalSelectedItems(newSelectedItems);
4281
+ }
4282
+ }, [isMulti, selectedItems, onSelectionChange]);
4283
+ return (jsxRuntime.jsx("div", { className: cvaMenuList({ stickyHeader: withStickyHeader, className }), "data-testid": dataTestId ? `${dataTestId}-menu-list` : "menu-list", onClick: args.onClick, role: "list", tabIndex: 0, children: childrenArr.map((menuItem, index) => {
4284
+ var _a;
4285
+ if (React.isValidElement(menuItem)) {
4286
+ const isSelected = selectedItems.includes((_a = menuItem.props.id) !== null && _a !== void 0 ? _a : `${index}`) || menuItem.props.selected;
4287
+ return (jsxRuntime.jsx("div", { children: React.cloneElement(menuItem, {
4288
+ ...menuItem.props,
4289
+ onClick: (event) => {
4290
+ var _a, _b, _c;
4291
+ (_b = (_a = menuItem.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, event);
4292
+ handleItemClick((_c = menuItem.props.id) !== null && _c !== void 0 ? _c : `${index}`, menuItem.props.disabled);
4293
+ },
4294
+ className: isMulti && isSelected
4295
+ ? cvaMenuListMultiSelect({ className: menuItem.props.className })
4296
+ : cvaMenuListItem({ className: menuItem.props.className }),
4297
+ selected: isSelected,
4298
+ suffix: isMulti && isSelected ? (jsxRuntime.jsx(Icon, { className: "h-5 text-blue-600", name: "Check", size: "medium", type: "solid" })) : null,
4299
+ }) }, index));
4300
+ }
4301
+ return null;
4302
+ }) }));
4175
4303
  };
4176
4304
 
4177
- const cvaMoreMenu = cssClassVarianceUtilities.cvaMerge(["p-4"]);
4305
+ const cvaMoreMenu = cssClassVarianceUtilities.cvaMerge(["p-0"]);
4178
4306
 
4179
4307
  /**
4180
4308
  * A kebab menu component.
@@ -4192,7 +4320,7 @@ const MoreMenu = ({ className, dataTestId, popoverProps, iconProps = {
4192
4320
  variant: "secondary",
4193
4321
  }, customButton, customPortalId, children, }) => {
4194
4322
  const actionMenuRef = React.useRef(null);
4195
- return (jsxRuntime.jsx("div", { className: cvaMoreMenu({ className }), "data-testid": dataTestId, ref: actionMenuRef, children: jsxRuntime.jsxs(Popover, { ...popoverProps, children: [jsxRuntime.jsx(PopoverTrigger, { children: customButton !== null && customButton !== void 0 ? customButton : jsxRuntime.jsx(IconButton, { ...iconButtonProps, icon: jsxRuntime.jsx(Icon, { name: "EllipsisHorizontal", ...iconProps }) }) }), jsxRuntime.jsx(PopoverContent, { portalId: customPortalId, children: close => (typeof children === "function" ? children(close) : children) })] }) }));
4323
+ return (jsxRuntime.jsx("div", { className: cvaMoreMenu({ className }), "data-testid": dataTestId, ref: actionMenuRef, children: jsxRuntime.jsxs(Popover, { placement: "bottom-end", ...popoverProps, children: [jsxRuntime.jsx(PopoverTrigger, { children: customButton !== null && customButton !== void 0 ? customButton : (jsxRuntime.jsx(IconButton, { dataTestId: "more-menu-icon", ...iconButtonProps, icon: jsxRuntime.jsx(Icon, { name: "EllipsisHorizontal", ...iconProps }) })) }), jsxRuntime.jsx(PopoverContent, { portalId: customPortalId, children: close => (typeof children === "function" ? children(close) : children) })] }) }));
4196
4324
  };
4197
4325
 
4198
4326
  const cvaNotice = cssClassVarianceUtilities.cvaMerge(["flex", "items-center"]);
@@ -4608,7 +4736,7 @@ const Sidebar = ({ childContainerClassName, children, breakpoint = "lg", classNa
4608
4736
  }) }), overflowItemCount > 0 ? (jsxRuntime.jsx(MoreMenu, { iconButtonProps: {
4609
4737
  circular: false,
4610
4738
  variant: "ghost-neutral",
4611
- }, popoverProps: { placement: "bottom-end" }, ...moreMenuProps, className: tailwindMerge.twMerge(moreMenuProps === null || moreMenuProps === void 0 ? void 0 : moreMenuProps.className, "!p-0"), dataTestId: dataTestId ? `${dataTestId}-more-menu` : undefined, children: close => (jsxRuntime.jsx(MenuList, { ...menuListProps, dataTestId: dataTestId ? `${dataTestId}-menu-list` : undefined, children: React.Children.map(children, child => {
4739
+ }, ...moreMenuProps, className: moreMenuProps === null || moreMenuProps === void 0 ? void 0 : moreMenuProps.className, dataTestId: dataTestId ? `${dataTestId}-more-menu` : undefined, children: close => (jsxRuntime.jsx(MenuList, { ...menuListProps, dataTestId: dataTestId, children: React.Children.map(children, child => {
4612
4740
  return itemOverflowMap[child.props.id]
4613
4741
  ? React.cloneElement(child, {
4614
4742
  onClick: () => {
@@ -4616,6 +4744,7 @@ const Sidebar = ({ childContainerClassName, children, breakpoint = "lg", classNa
4616
4744
  (_b = (_a = child.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
4617
4745
  close();
4618
4746
  },
4747
+ className: "w-full",
4619
4748
  })
4620
4749
  : null;
4621
4750
  }) })) })) : null] }));
@@ -5044,6 +5173,7 @@ exports.Icon = Icon;
5044
5173
  exports.IconButton = IconButton;
5045
5174
  exports.Indicator = Indicator;
5046
5175
  exports.KPICard = KPICard;
5176
+ exports.MenuDivider = MenuDivider;
5047
5177
  exports.MenuItem = MenuItem;
5048
5178
  exports.MenuList = MenuList;
5049
5179
  exports.MoreMenu = MoreMenu;
package/index.esm.js CHANGED
@@ -3719,7 +3719,7 @@ const PopoverContent = React__default.forwardRef(function PopoverContent({ class
3719
3719
  var _a;
3720
3720
  const { context: floatingContext, customProps, ...context } = usePopoverContext();
3721
3721
  const ref = useMergeRefs([context.refs.setFloating, propRef]);
3722
- return (jsx(FloatingPortal, { id: portalId !== null && portalId !== void 0 ? portalId : "tu-floating-ui", children: context.isOpen ? (jsx(FloatingFocusManager, { closeOnFocusOut: false, context: floatingContext, guards: false, modal: context.isModal, order: ["reference", "content"], returnFocus: false, children: jsx("div", { "aria-describedby": context.descriptionId, "aria-labelledby": context.labelId, className: cvaPopoverContainer({ className: className !== null && className !== void 0 ? className : customProps.className }), "data-testid": (_a = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _a !== void 0 ? _a : "popover-content", ref: ref, style: {
3722
+ return (jsx(FloatingPortal, { id: portalId !== null && portalId !== void 0 ? portalId : "tu-floating-ui", children: context.isOpen ? (jsx(FloatingFocusManager, { closeOnFocusOut: false, context: floatingContext, guards: true, modal: context.isModal, order: ["reference", "content"], returnFocus: true, children: jsx("div", { "aria-describedby": context.descriptionId, "aria-labelledby": context.labelId, className: cvaPopoverContainer({ className: className !== null && className !== void 0 ? className : customProps.className }), "data-testid": (_a = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _a !== void 0 ? _a : "popover-content", ref: ref, style: {
3723
3723
  position: context.strategy,
3724
3724
  top: context.y,
3725
3725
  left: context.x,
@@ -4016,6 +4016,36 @@ const KPICard = ({ asChild = false, title, value, loading, unit, iconName, iconB
4016
4016
  return (jsxs(Comp, { className: cvaKPICardContainer({ className, isClickable: Boolean(asChild || onClick) }), "data-testid": `${dataTestId}-comp`, onClick: onClick, ...rest, children: [tooltipLabel ? (jsx(Tooltip, { className: "w-full", label: tooltipLabel, placement: "bottom", children: jsx(CardContent, {}) })) : (jsx(CardContent, {})), !loading && jsx(Slottable, { children: rest.children })] }));
4017
4017
  };
4018
4018
 
4019
+ const cvaMenuList = cvaMerge([
4020
+ "shadow",
4021
+ "rounded-lg",
4022
+ "z-popover",
4023
+ "bg-white",
4024
+ "border",
4025
+ "border-slate-300",
4026
+ "grid",
4027
+ "min-w-[200px]",
4028
+ "max-w-[300px]",
4029
+ "p-1",
4030
+ ], {
4031
+ variants: {
4032
+ stickyHeader: {
4033
+ true: "grid-rows-min-fr grid overflow-y-hidden",
4034
+ false: "",
4035
+ },
4036
+ },
4037
+ });
4038
+ const cvaMenuListDivider = cvaMerge(["mx-[-4px]", "my-1", "min-h-px", "bg-slate-300"]);
4039
+ const cvaMenuListMultiSelect = cvaMerge("hover:!bg-blue-200");
4040
+ const cvaMenuListItem = cvaMerge("max-w-[290px]");
4041
+
4042
+ /**
4043
+ * The MenuDivider component is used to separate items in a menu list.
4044
+ */
4045
+ const MenuDivider = () => {
4046
+ return jsx("div", { className: cvaMenuListDivider(), "data-testid": "menu-divider" });
4047
+ };
4048
+
4019
4049
  /**
4020
4050
  * Applies standardized interaction-related styles to an element.
4021
4051
  *
@@ -4068,45 +4098,108 @@ const cvaInteractableItem = cvaMerge("", {
4068
4098
  },
4069
4099
  });
4070
4100
 
4071
- const cvaMenuItemStyle = cvaMerge(["py-2", "px-2", "w-full", "h-auto", "flex", "flex-row", "items-center", "gap-x-2", "select-none", "rounded"], {
4101
+ /**
4102
+ * Extends the cvaInteractableItem variant in order to set the padding, width, height, cursor, and other styles particular to the MenuItem component.
4103
+ * The cvaInteractableItem variant is used to set the standardized styles that change through interaction with the element (background color, hover, focus, and disabled).
4104
+ */
4105
+ const cvaMenuItem = (props) => {
4106
+ const { size, selected, disabled, focused, className, variant } = props !== null && props !== void 0 ? props : {};
4107
+ return twMerge(cvaMenuItemStyle({ size, variant, selected, disabled }), cvaInteractableItem({ selected, disabled, cursor: "pointer", focused }), className);
4108
+ };
4109
+ const cvaMenuItemStyle = cvaMerge(["py-2", "px-2", "h-auto", "flex", "flex-row", "items-center", "gap-x-2", "select-none", "rounded", "text-sm"], {
4072
4110
  variants: {
4073
4111
  size: {
4074
4112
  small: "py-1",
4075
4113
  medium: "py-2",
4076
4114
  },
4115
+ variant: {
4116
+ primary: [],
4117
+ danger: [
4118
+ "text-danger-600",
4119
+ "hover:!bg-danger-100",
4120
+ "focus:!bg-danger-200",
4121
+ "hover:!text-danger-700",
4122
+ "focus:!text-danger-800",
4123
+ ],
4124
+ },
4125
+ selected: {
4126
+ true: "",
4127
+ false: "",
4128
+ },
4129
+ disabled: {
4130
+ true: "text-black opacity-50",
4131
+ false: "",
4132
+ },
4133
+ },
4134
+ compoundVariants: [
4135
+ {
4136
+ /* danger not multi-select enabled */
4137
+ selected: true,
4138
+ variant: "danger",
4139
+ className: ["!bg-white"],
4140
+ },
4141
+ ],
4142
+ defaultVariants: {
4143
+ variant: "primary",
4144
+ selected: false,
4145
+ disabled: false,
4077
4146
  },
4078
4147
  });
4079
- /**
4080
- * Extends the cvaInteractableItem variant in order to set the padding, width, height, cursor, and other styles particular to the MenuItem component.
4081
- * The cvaInteractableItem variant is used to set the standardized styles that change through interaction with the element (background color, hover, focus, and disabled).
4082
- */
4083
- const cvaMenuItem = (props) => {
4084
- const { size, selected, disabled, focused, className } = props !== null && props !== void 0 ? props : {};
4085
- return twMerge(cvaMenuItemStyle({ size }), cvaInteractableItem({ selected, disabled, cursor: "pointer", focused }), className);
4086
- };
4087
- const cvaMenuItemLabel = cvaMerge([
4088
- "flex-grow",
4089
- "text-gray-700",
4090
- "text-ellipsis",
4091
- "truncate",
4092
- "group-hover:text-gray-900",
4093
- "group-active:text-gray-700",
4094
- ]);
4095
- const cvaMenuItemSuffix = cvaMerge(["self-center", "flex-grow-0", "text-slate-400", "text-sm"], {
4148
+ const cvaMenuItemLabel = cvaMerge(["flex-grow", "truncate", "text-black", "font-normal"], {
4149
+ variants: {
4150
+ variant: {
4151
+ primary: [],
4152
+ danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
4153
+ },
4154
+ disabled: {
4155
+ true: "text-black opacity-50",
4156
+ false: "",
4157
+ },
4158
+ },
4159
+ defaultVariants: {
4160
+ variant: "primary",
4161
+ disabled: false,
4162
+ },
4163
+ });
4164
+ const cvaMenuItemPrefix = cvaMerge(["text-secondary-400", "hover:text-secondary-500", "focus:text-secondary-500", "h-min", "leading-[0]"], {
4096
4165
  variants: {
4097
4166
  selected: {
4098
- true: "text-primary-600 hover:text-primary-700",
4167
+ true: "text-secondary-600",
4168
+ false: "",
4169
+ },
4170
+ variant: {
4171
+ primary: [],
4172
+ danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
4173
+ },
4174
+ disabled: {
4175
+ true: "text-secondary opacity-50",
4099
4176
  false: "",
4100
4177
  },
4101
4178
  },
4179
+ defaultVariants: {
4180
+ variant: "primary",
4181
+ disabled: false,
4182
+ },
4102
4183
  });
4103
- const cvaMenuItemPrefix = cvaMerge(["self-center", "flex-grow-0", "text-slate-400", "group-hover:text-slate-600", "h-min", "leading-[0]", "text-sm"], {
4184
+ const cvaMenuItemSuffix = cvaMerge(["text-secondary-400", "text-sm"], {
4104
4185
  variants: {
4105
4186
  selected: {
4106
- true: "text-primary-600 hover:text-primary-700",
4187
+ true: "text-secondary-600",
4188
+ false: "",
4189
+ },
4190
+ variant: {
4191
+ primary: [],
4192
+ danger: ["text-danger-600", "hover:text-danger-700", "focus:bg-danger-200", "focus:text-danger-800"],
4193
+ },
4194
+ disabled: {
4195
+ true: "text-secondary opacity-50",
4107
4196
  false: "",
4108
4197
  },
4109
4198
  },
4199
+ defaultVariants: {
4200
+ variant: "primary",
4201
+ disabled: false,
4202
+ },
4110
4203
  });
4111
4204
 
4112
4205
  /**
@@ -4115,46 +4208,81 @@ const cvaMenuItemPrefix = cvaMerge(["self-center", "flex-grow-0", "text-slate-40
4115
4208
  * @param {MenuItemProps} props - The props for the MenuItem component
4116
4209
  * @returns {JSX.Element} MenuItem component
4117
4210
  */
4118
- const MenuItem = ({ className, dataTestId, label, size, children, selected, prefix, suffix, disabled, onClick, stopPropagation = true, id, tabIndex, }) => {
4119
- return (jsxs("div", { className: cvaMenuItem({
4211
+ const MenuItem = ({ className, dataTestId, label, size, children, selected, prefix, suffix, disabled, onClick, stopPropagation = true, id, tabIndex, variant = "primary", }) => {
4212
+ /* Handle tab navigation */
4213
+ const handleKeyDown = (e) => {
4214
+ if (e.key === "Enter" && onClick && !disabled) {
4215
+ stopPropagation && e.stopPropagation();
4216
+ // eslint-disable-next-line local-rules/no-typescript-assertion
4217
+ onClick(e);
4218
+ }
4219
+ };
4220
+ return (jsxs("div", { "aria-disabled": disabled, className: cvaMenuItem({
4120
4221
  selected,
4121
4222
  disabled,
4122
4223
  size,
4123
4224
  className,
4124
- }), "data-testid": dataTestId !== null && dataTestId !== void 0 ? dataTestId : "menu-item", id: id, onClick: e => {
4225
+ variant,
4226
+ }), "data-testid": dataTestId ? `${dataTestId}-menu-item` : "menu-item", id: id, onClick: e => {
4125
4227
  stopPropagation && e.stopPropagation();
4126
4228
  onClick === null || onClick === void 0 ? void 0 : onClick(e);
4127
- }, role: "menuitem", tabIndex: tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0, children: [prefix ? (jsx("div", { className: cvaMenuItemPrefix({ selected }), "data-testid": dataTestId ? `${dataTestId}-prefix` : null, children: prefix })) : null, children && typeof children !== "string" ? (children) : (jsx("div", { className: cvaMenuItemLabel(), "data-testid": dataTestId ? `${dataTestId}-label` : null, children: children !== null && children !== void 0 ? children : label })), suffix ? (jsx("div", { className: cvaMenuItemSuffix({ selected }), "data-testid": dataTestId ? `${dataTestId}-suffix` : null, children: suffix })) : null] }));
4229
+ }, onKeyDown: handleKeyDown, role: "menuitem", tabIndex: disabled ? -1 : tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0, children: [prefix ? (jsx("div", { className: cvaMenuItemPrefix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-prefix` : "menu-item-prefix", children: prefix })) : null, children && typeof children !== "string" ? (children) : (jsx("div", { className: cvaMenuItemLabel({ variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-label` : "menu-item-label", children: children !== null && children !== void 0 ? children : label })), suffix ? (jsx("div", { className: cvaMenuItemSuffix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-suffix` : "menu-item-suffix", children: suffix })) : null] }));
4128
4230
  };
4129
4231
 
4130
- const cvaMenuList = cvaMerge(["shadow-md", "rounded-lg", "z-popover", "bg-white", "border", "border-slate-300", "grid"], {
4131
- variants: {
4132
- stickyHeader: {
4133
- true: "grid-rows-min-fr grid overflow-y-hidden",
4134
- false: "",
4135
- },
4136
- },
4137
- });
4138
- const cvaMenuListDivider = cvaMerge([
4139
- "file:w-full",
4140
- "selection:col-span-full",
4141
- "selection:h-px",
4142
- "selection:bg-slate-200",
4143
- ]);
4144
-
4145
4232
  /**
4146
- * The MenuList component is used for menus and selects.
4147
-
4233
+ * The MenuList is a popover menu that appears above all other content on the page. The menu offers a list of actions or functions that a user can access by clicking on a trigger.
4234
+ *
4235
+ * **When to use**
4236
+ * - Use the MenuList if you have limited space and need to display overflow actions in a list.
4237
+ * - Use the MenuList for actions that are not essential to completing workflows.
4238
+ * - Don’t use the MenuList to display single or multi-select items within form components. For dropdowns within select components, use SelectDropdown (component not available yet).
4239
+ *
4148
4240
  * @param {MenuListProps} props - The props for the MenuList component
4149
4241
  * @returns {JSX.Element} MenuList component
4150
4242
  */
4151
- const MenuList = ({ dataTestId, className, children, withStickyHeader = false, showDivider = false, ...args }) => {
4243
+ const MenuList = ({ dataTestId, className, children, withStickyHeader = false, isMulti = false, selectedItems: controlledSelectedItems, onSelectionChange, ...args }) => {
4152
4244
  const childrenArr = Children.toArray(children);
4153
- const isLastItem = (index) => index === childrenArr.length - 1;
4154
- return (jsx("div", { className: cvaMenuList({ stickyHeader: withStickyHeader, className }), "data-testid": dataTestId, onClick: args.onClick, role: "list", tabIndex: 0, children: Children.map(childrenArr, (menuItem, index) => (jsxs(Fragment, { children: [menuItem, showDivider && !isLastItem(index) ? jsx("hr", { className: cvaMenuListDivider() }) : null] }))) }));
4245
+ const [internalSelectedItems, setInternalSelectedItems] = useState(controlledSelectedItems !== null && controlledSelectedItems !== void 0 ? controlledSelectedItems : []);
4246
+ const selectedItems = controlledSelectedItems !== null && controlledSelectedItems !== void 0 ? controlledSelectedItems : internalSelectedItems;
4247
+ const handleItemClick = useCallback((id, disabled) => {
4248
+ if (disabled) {
4249
+ return;
4250
+ }
4251
+ const newSelectedItems = isMulti
4252
+ ? selectedItems.includes(id)
4253
+ ? selectedItems.filter(item => item !== id)
4254
+ : [...selectedItems, id]
4255
+ : [id];
4256
+ if (onSelectionChange) {
4257
+ onSelectionChange(newSelectedItems);
4258
+ }
4259
+ else {
4260
+ setInternalSelectedItems(newSelectedItems);
4261
+ }
4262
+ }, [isMulti, selectedItems, onSelectionChange]);
4263
+ return (jsx("div", { className: cvaMenuList({ stickyHeader: withStickyHeader, className }), "data-testid": dataTestId ? `${dataTestId}-menu-list` : "menu-list", onClick: args.onClick, role: "list", tabIndex: 0, children: childrenArr.map((menuItem, index) => {
4264
+ var _a;
4265
+ if (isValidElement(menuItem)) {
4266
+ const isSelected = selectedItems.includes((_a = menuItem.props.id) !== null && _a !== void 0 ? _a : `${index}`) || menuItem.props.selected;
4267
+ return (jsx("div", { children: cloneElement(menuItem, {
4268
+ ...menuItem.props,
4269
+ onClick: (event) => {
4270
+ var _a, _b, _c;
4271
+ (_b = (_a = menuItem.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, event);
4272
+ handleItemClick((_c = menuItem.props.id) !== null && _c !== void 0 ? _c : `${index}`, menuItem.props.disabled);
4273
+ },
4274
+ className: isMulti && isSelected
4275
+ ? cvaMenuListMultiSelect({ className: menuItem.props.className })
4276
+ : cvaMenuListItem({ className: menuItem.props.className }),
4277
+ selected: isSelected,
4278
+ suffix: isMulti && isSelected ? (jsx(Icon, { className: "h-5 text-blue-600", name: "Check", size: "medium", type: "solid" })) : null,
4279
+ }) }, index));
4280
+ }
4281
+ return null;
4282
+ }) }));
4155
4283
  };
4156
4284
 
4157
- const cvaMoreMenu = cvaMerge(["p-4"]);
4285
+ const cvaMoreMenu = cvaMerge(["p-0"]);
4158
4286
 
4159
4287
  /**
4160
4288
  * A kebab menu component.
@@ -4172,7 +4300,7 @@ const MoreMenu = ({ className, dataTestId, popoverProps, iconProps = {
4172
4300
  variant: "secondary",
4173
4301
  }, customButton, customPortalId, children, }) => {
4174
4302
  const actionMenuRef = useRef(null);
4175
- return (jsx("div", { className: cvaMoreMenu({ className }), "data-testid": dataTestId, ref: actionMenuRef, children: jsxs(Popover, { ...popoverProps, children: [jsx(PopoverTrigger, { children: customButton !== null && customButton !== void 0 ? customButton : jsx(IconButton, { ...iconButtonProps, icon: jsx(Icon, { name: "EllipsisHorizontal", ...iconProps }) }) }), jsx(PopoverContent, { portalId: customPortalId, children: close => (typeof children === "function" ? children(close) : children) })] }) }));
4303
+ return (jsx("div", { className: cvaMoreMenu({ className }), "data-testid": dataTestId, ref: actionMenuRef, children: jsxs(Popover, { placement: "bottom-end", ...popoverProps, children: [jsx(PopoverTrigger, { children: customButton !== null && customButton !== void 0 ? customButton : (jsx(IconButton, { dataTestId: "more-menu-icon", ...iconButtonProps, icon: jsx(Icon, { name: "EllipsisHorizontal", ...iconProps }) })) }), jsx(PopoverContent, { portalId: customPortalId, children: close => (typeof children === "function" ? children(close) : children) })] }) }));
4176
4304
  };
4177
4305
 
4178
4306
  const cvaNotice = cvaMerge(["flex", "items-center"]);
@@ -4588,7 +4716,7 @@ const Sidebar = ({ childContainerClassName, children, breakpoint = "lg", classNa
4588
4716
  }) }), overflowItemCount > 0 ? (jsx(MoreMenu, { iconButtonProps: {
4589
4717
  circular: false,
4590
4718
  variant: "ghost-neutral",
4591
- }, popoverProps: { placement: "bottom-end" }, ...moreMenuProps, className: twMerge(moreMenuProps === null || moreMenuProps === void 0 ? void 0 : moreMenuProps.className, "!p-0"), dataTestId: dataTestId ? `${dataTestId}-more-menu` : undefined, children: close => (jsx(MenuList, { ...menuListProps, dataTestId: dataTestId ? `${dataTestId}-menu-list` : undefined, children: React__default.Children.map(children, child => {
4719
+ }, ...moreMenuProps, className: moreMenuProps === null || moreMenuProps === void 0 ? void 0 : moreMenuProps.className, dataTestId: dataTestId ? `${dataTestId}-more-menu` : undefined, children: close => (jsx(MenuList, { ...menuListProps, dataTestId: dataTestId, children: React__default.Children.map(children, child => {
4592
4720
  return itemOverflowMap[child.props.id]
4593
4721
  ? React__default.cloneElement(child, {
4594
4722
  onClick: () => {
@@ -4596,6 +4724,7 @@ const Sidebar = ({ childContainerClassName, children, breakpoint = "lg", classNa
4596
4724
  (_b = (_a = child.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
4597
4725
  close();
4598
4726
  },
4727
+ className: "w-full",
4599
4728
  })
4600
4729
  : null;
4601
4730
  }) })) })) : null] }));
@@ -5003,4 +5132,4 @@ const cvaClickable = cvaMerge([
5003
5132
  },
5004
5133
  });
5005
5134
 
5006
- export { Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, Drawer, EmptyState, EmptyValue, ExternalLink, Heading, Icon, IconButton, Indicator, KPICard, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, Timeline, TimelineElement, ToggleGroup, ToggleItem, Tooltip, ValueBar, VirtualizedList, WidgetBody, cvaButton, cvaButtonPrefixSuffix, cvaButtonSpinner, cvaButtonSpinnerContainer, cvaClickable, cvaIconButton, cvaIndicator, cvaIndicatorIcon, cvaIndicatorIconBackground, cvaIndicatorLabel, cvaIndicatorPing, cvaInteractableItem, cvaMenuItem, cvaMenuItemLabel, cvaMenuItemPrefix, cvaMenuItemStyle, cvaMenuItemSuffix, docs, getDevicePixelRatio, getValueBarColorByValue, iconColorNames, iconPalette, setLocalStorage, useClickOutside, useContinuousTimeout, useDebounce, useDevicePixelRatio, useGeometry, useHover, useIsFirstRender, useIsFullscreen, useIsTextCutOff, useLocalStorage, useLocalStorageReducer, useOptionallyElevatedState, useOverflowItems, usePopoverContext, usePrevious, usePrompt, useResize, useSelfUpdatingRef, useTimeout, useViewportSize, useWindowActivity };
5135
+ export { Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, Drawer, EmptyState, EmptyValue, ExternalLink, Heading, Icon, IconButton, Indicator, KPICard, MenuDivider, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, Timeline, TimelineElement, ToggleGroup, ToggleItem, Tooltip, ValueBar, VirtualizedList, WidgetBody, cvaButton, cvaButtonPrefixSuffix, cvaButtonSpinner, cvaButtonSpinnerContainer, cvaClickable, cvaIconButton, cvaIndicator, cvaIndicatorIcon, cvaIndicatorIconBackground, cvaIndicatorLabel, cvaIndicatorPing, cvaInteractableItem, cvaMenuItem, cvaMenuItemLabel, cvaMenuItemPrefix, cvaMenuItemStyle, cvaMenuItemSuffix, docs, getDevicePixelRatio, getValueBarColorByValue, iconColorNames, iconPalette, setLocalStorage, useClickOutside, useContinuousTimeout, useDebounce, useDevicePixelRatio, useGeometry, useHover, useIsFirstRender, useIsFullscreen, useIsTextCutOff, useLocalStorage, useLocalStorageReducer, useOptionallyElevatedState, useOverflowItems, usePopoverContext, usePrevious, usePrompt, useResize, useSelfUpdatingRef, useTimeout, useViewportSize, useWindowActivity };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "0.4.33",
3
+ "version": "0.4.34",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -0,0 +1,4 @@
1
+ /**
2
+ * The MenuDivider component is used to separate items in a menu list.
3
+ */
4
+ export declare const MenuDivider: () => import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,10 @@
1
- import * as React from "react";
2
1
  import { CommonProps, Size } from "../../../common";
3
2
  type MenuItemSize = Extract<Size, "small" | "medium">;
3
+ export type MenuItemVariant = "primary" | "danger";
4
4
  export interface MenuItemProps extends CommonProps {
5
+ /**
6
+ * The unique id for the menu item
7
+ */
5
8
  id?: string;
6
9
  /**
7
10
  * Label of the menu item
@@ -51,7 +54,14 @@ export interface MenuItemProps extends CommonProps {
51
54
  * used in Menu and Select components
52
55
  */
53
56
  stopPropagation?: boolean;
57
+ /**
58
+ * The tab index of the menu item.
59
+ */
54
60
  tabIndex?: number;
61
+ /**
62
+ * The button's variant. Values are primary and danger.
63
+ */
64
+ variant?: MenuItemVariant;
55
65
  }
56
66
  /**
57
67
  * The MenuItem component is used to display a menu, primarily meant to be used in a list form.
@@ -59,5 +69,5 @@ export interface MenuItemProps extends CommonProps {
59
69
  * @param {MenuItemProps} props - The props for the MenuItem component
60
70
  * @returns {JSX.Element} MenuItem component
61
71
  */
62
- export declare const MenuItem: ({ className, dataTestId, label, size, children, selected, prefix, suffix, disabled, onClick, stopPropagation, id, tabIndex, }: MenuItemProps) => import("react/jsx-runtime").JSX.Element;
72
+ export declare const MenuItem: ({ className, dataTestId, label, size, children, selected, prefix, suffix, disabled, onClick, stopPropagation, id, tabIndex, variant, }: MenuItemProps) => import("react/jsx-runtime").JSX.Element;
63
73
  export {};
@@ -1,22 +1,35 @@
1
1
  import { type VariantProps } from "@trackunit/css-class-variance-utilities";
2
2
  import { MappedOmit } from "@trackunit/shared-utils";
3
3
  import { cvaInteractableItem } from "../../InteractableItem/InteractableItem.variants";
4
- export declare const cvaMenuItemStyle: (props?: ({
5
- size?: "small" | "medium" | null | undefined;
6
- } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
4
+ import { MenuItemVariant } from "./MenuItem";
7
5
  type CvaMenuItemProps = Partial<MappedOmit<VariantProps<typeof cvaInteractableItem>, "cursor">> & {
8
6
  size?: "small" | "medium";
7
+ variant?: MenuItemVariant;
8
+ selected?: boolean | null | undefined;
9
9
  };
10
10
  /**
11
11
  * Extends the cvaInteractableItem variant in order to set the padding, width, height, cursor, and other styles particular to the MenuItem component.
12
12
  * The cvaInteractableItem variant is used to set the standardized styles that change through interaction with the element (background color, hover, focus, and disabled).
13
13
  */
14
14
  export declare const cvaMenuItem: (props?: CvaMenuItemProps) => string;
15
- export declare const cvaMenuItemLabel: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
16
- export declare const cvaMenuItemSuffix: (props?: ({
15
+ export declare const cvaMenuItemStyle: (props?: ({
16
+ size?: "small" | "medium" | null | undefined;
17
+ variant?: "primary" | "danger" | null | undefined;
17
18
  selected?: boolean | null | undefined;
19
+ disabled?: boolean | null | undefined;
20
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
21
+ export declare const cvaMenuItemLabel: (props?: ({
22
+ variant?: "primary" | "danger" | null | undefined;
23
+ disabled?: boolean | null | undefined;
18
24
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
19
25
  export declare const cvaMenuItemPrefix: (props?: ({
20
26
  selected?: boolean | null | undefined;
27
+ variant?: "primary" | "danger" | null | undefined;
28
+ disabled?: boolean | null | undefined;
29
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
30
+ export declare const cvaMenuItemSuffix: (props?: ({
31
+ selected?: boolean | null | undefined;
32
+ variant?: "primary" | "danger" | null | undefined;
33
+ disabled?: boolean | null | undefined;
21
34
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
22
35
  export {};
@@ -1,17 +1,9 @@
1
1
  import { CommonProps } from "../../../common";
2
- import { MenuItemProps } from "../MenuItem/MenuItem";
3
- export interface MenuListItemProps extends MenuItemProps {
4
- showDivider?: boolean;
5
- }
6
2
  export interface MenuListProps extends CommonProps {
7
3
  /**
8
4
  * List of menu items to be rendered.
9
5
  */
10
6
  children: React.ReactNode;
11
- /**
12
- * List of menu items to be rendered.
13
- */
14
- showDivider?: boolean;
15
7
  /**
16
8
  * When enabled the menu list padding will be removed, and a grid will be applied to keep the first column "sticky".
17
9
  *
@@ -20,11 +12,30 @@ export interface MenuListProps extends CommonProps {
20
12
  withStickyHeader?: boolean;
21
13
  /** Click handler - typically used to trigger close action. when propagation is NOT prevented on menuItem */
22
14
  onClick?: () => void;
15
+ /**
16
+ * Enable multi-selection in the menu list.
17
+ *
18
+ * @default false
19
+ */
20
+ isMulti?: boolean;
21
+ /**
22
+ * Array of IDs representing the currently selected items.
23
+ */
24
+ selectedItems?: string[];
25
+ /**
26
+ * Callback triggered when selected items change.
27
+ */
28
+ onSelectionChange?: (selected: string[]) => void;
23
29
  }
24
30
  /**
25
- * The MenuList component is used for menus and selects.
26
-
31
+ * The MenuList is a popover menu that appears above all other content on the page. The menu offers a list of actions or functions that a user can access by clicking on a trigger.
32
+ *
33
+ * **When to use**
34
+ * - Use the MenuList if you have limited space and need to display overflow actions in a list.
35
+ * - Use the MenuList for actions that are not essential to completing workflows.
36
+ * - Don’t use the MenuList to display single or multi-select items within form components. For dropdowns within select components, use SelectDropdown (component not available yet).
37
+ *
27
38
  * @param {MenuListProps} props - The props for the MenuList component
28
39
  * @returns {JSX.Element} MenuList component
29
40
  */
30
- export declare const MenuList: ({ dataTestId, className, children, withStickyHeader, showDivider, ...args }: MenuListProps) => JSX.Element;
41
+ export declare const MenuList: ({ dataTestId, className, children, withStickyHeader, isMulti, selectedItems: controlledSelectedItems, onSelectionChange, ...args }: MenuListProps) => JSX.Element;
@@ -2,3 +2,5 @@ export declare const cvaMenuList: (props?: ({
2
2
  stickyHeader?: boolean | null | undefined;
3
3
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
4
4
  export declare const cvaMenuListDivider: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
5
+ export declare const cvaMenuListMultiSelect: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
6
+ export declare const cvaMenuListItem: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
@@ -1,3 +1,4 @@
1
+ export * from "./MenuDivider/MenuDivider";
1
2
  export * from "./MenuItem/MenuItem";
2
3
  export * from "./MenuList/MenuList";
3
4
  export * from "./MoreMenu/MoreMenu";