@okshaun/components 0.5.2 → 0.5.4

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.d.ts CHANGED
@@ -801,6 +801,50 @@ export declare type MenuItemProps = Omit<BoxProps, 'children'> & {
801
801
 
802
802
  export declare type MenuItemType = 'action' | 'single-select' | 'multi-select';
803
803
 
804
+ export declare const MenuList: default_2.ForwardRefExoticComponent<Omit<MenuListProps, "ref"> & default_2.RefAttributes<HTMLDivElement>>;
805
+
806
+ export declare const MenuListDivider: default_2.FC<MenuListDividerProps>;
807
+
808
+ export declare type MenuListDividerProps = Omit<BoxProps, 'children' | keyof MenuVariantProps> & MenuVariantProps;
809
+
810
+ export declare const MenuListGroup: default_2.FC<MenuListGroupProps>;
811
+
812
+ export declare type MenuListGroupProps = Omit<BoxProps, 'title' | keyof MenuVariantProps> & MenuVariantProps & {
813
+ /** Group label */
814
+ label?: string;
815
+ /** Children (MenuListItem components) */
816
+ children: React.ReactNode;
817
+ };
818
+
819
+ export declare const MenuListItem: default_2.ForwardRefExoticComponent<Omit<MenuListItemProps, "ref"> & default_2.RefAttributes<HTMLDivElement>>;
820
+
821
+ export declare type MenuListItemProps = Omit<BoxProps, 'children' | 'onClick' | keyof MenuVariantProps> & MenuVariantProps & {
822
+ /** Item behavior type */
823
+ type?: MenuItemType;
824
+ /** Selected state (for single-select and multi-select) */
825
+ selected?: boolean;
826
+ /** Active highlight state (controlled externally) */
827
+ active?: boolean;
828
+ /** Click handler */
829
+ onClick?: React.MouseEventHandler<HTMLDivElement>;
830
+ /** Disable the item */
831
+ disabled?: boolean;
832
+ /** Primary label (required) */
833
+ label: string | React.ReactNode;
834
+ /** Secondary description text */
835
+ description?: string;
836
+ /** Icon on the left side */
837
+ iconLeft?: IconNamesList;
838
+ /** Icon on the right side */
839
+ iconRight?: IconNamesList;
840
+ /** Text to highlight (for autocomplete/search scenarios) */
841
+ highlightMatch?: string;
842
+ /** Selection indicator style (only for select types) */
843
+ selectionIndicator?: SelectionIndicator;
844
+ };
845
+
846
+ export declare type MenuListProps = Omit<BoxProps, keyof MenuVariantProps> & MenuVariantProps;
847
+
804
848
  export declare type MenuProps = Omit<BoxProps, keyof MenuVariantProps> & MenuVariantProps & {
805
849
  /** Controlled open state (REQUIRED) */
806
850
  open: boolean;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import React__default, { forwardRef, useMemo, createElement, useEffect, useState, useRef, createContext, useContext, useCallback, useLayoutEffect, useSyncExternalStore } from "react";
2
+ import React__default, { forwardRef, useMemo, createElement, useEffect, useState, useRef, createContext, useContext, useCallback, useLayoutEffect, useId as useId$1, useSyncExternalStore } from "react";
3
3
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
4
4
  import * as ReactDOM from "react-dom";
5
5
  import { b as breakpoints, c as containerSizes } from "./size.primitives-j2MFgtrT.js";
@@ -3520,7 +3520,7 @@ const Chip = ({
3520
3520
  after: hasAfter
3521
3521
  });
3522
3522
  const iconSize = chipSizeToIconSize[size2];
3523
- const handleClick = () => {
3523
+ const handleClick = (e) => {
3524
3524
  if (dismissable && onDismiss) {
3525
3525
  onDismiss();
3526
3526
  } else if (isSelectable && groupContext) {
@@ -3532,7 +3532,7 @@ const Chip = ({
3532
3532
  groupContext.onChange(newValues);
3533
3533
  }
3534
3534
  } else if (onClick) {
3535
- onClick();
3535
+ onClick(e);
3536
3536
  }
3537
3537
  };
3538
3538
  const handleKeyDown = (e) => {
@@ -8447,7 +8447,7 @@ const Menu = ({
8447
8447
  ) }) })
8448
8448
  ] });
8449
8449
  };
8450
- const highlightText = (text2, match) => {
8450
+ const highlightText$1 = (text2, match) => {
8451
8451
  if (!match || typeof text2 !== "string") return text2;
8452
8452
  const regex = new RegExp(`(${match.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`, "gi");
8453
8453
  const parts = text2.split(regex);
@@ -8516,7 +8516,7 @@ const MenuItem = ({
8516
8516
  return /* @__PURE__ */ jsx(Box, { className: classes.menuItemIndicator, children: selected && /* @__PURE__ */ jsx(Icon, { name: "check", size: "20" }) });
8517
8517
  };
8518
8518
  const renderLabel = () => {
8519
- const labelContent = typeof label2 === "string" && highlightMatch ? highlightText(label2, highlightMatch) : label2;
8519
+ const labelContent = typeof label2 === "string" && highlightMatch ? highlightText$1(label2, highlightMatch) : label2;
8520
8520
  return /* @__PURE__ */ jsx(Box, { className: classes.menuItemLabel, children: labelContent });
8521
8521
  };
8522
8522
  return /* @__PURE__ */ jsxs(
@@ -8582,6 +8582,149 @@ const MenuGroup = ({
8582
8582
  }
8583
8583
  );
8584
8584
  };
8585
+ const MenuList = React__default.forwardRef(
8586
+ ({ size: size2, indicatorPosition, role = "listbox", className, ...props }, ref) => {
8587
+ const [cssClassName, otherProps] = splitProps(props);
8588
+ const classes = menu({ size: size2, indicatorPosition });
8589
+ return /* @__PURE__ */ jsx(
8590
+ Box,
8591
+ {
8592
+ ref,
8593
+ role,
8594
+ className: cx(classes.menu, cssClassName, className),
8595
+ ...otherProps
8596
+ }
8597
+ );
8598
+ }
8599
+ );
8600
+ MenuList.displayName = "MenuList";
8601
+ const highlightText = (text2, match) => {
8602
+ if (!match || typeof text2 !== "string") return text2;
8603
+ const regex = new RegExp(`(${match.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`, "gi");
8604
+ const parts = text2.split(regex);
8605
+ return parts.map(
8606
+ (part, i) => regex.test(part) ? /* @__PURE__ */ jsx("mark", { children: part }, i) : part
8607
+ );
8608
+ };
8609
+ const MenuListItem = React__default.forwardRef(
8610
+ ({
8611
+ type = "action",
8612
+ selected = false,
8613
+ active = false,
8614
+ onClick,
8615
+ disabled = false,
8616
+ label: label2,
8617
+ description,
8618
+ iconLeft,
8619
+ iconRight,
8620
+ highlightMatch,
8621
+ selectionIndicator = "checkmark",
8622
+ size: size2,
8623
+ indicatorPosition,
8624
+ role = "option",
8625
+ className,
8626
+ ...props
8627
+ }, ref) => {
8628
+ const [cssClassName, otherProps] = splitProps(props);
8629
+ const classes = menu({ size: size2, indicatorPosition });
8630
+ const checkboxId = useId$1();
8631
+ const isSelectable = type === "single-select" || type === "multi-select";
8632
+ const showIndicator = isSelectable;
8633
+ const handleClick = useCallback(
8634
+ (event) => {
8635
+ if (disabled) return;
8636
+ onClick == null ? void 0 : onClick(event);
8637
+ },
8638
+ [disabled, onClick]
8639
+ );
8640
+ const renderIndicator = () => {
8641
+ if (!showIndicator) return null;
8642
+ if (selectionIndicator === "checkbox") {
8643
+ return /* @__PURE__ */ jsx(Box, { className: classes.menuItemIndicator, children: /* @__PURE__ */ jsx(
8644
+ Checkbox,
8645
+ {
8646
+ name: `menu-list-item-checkbox-${checkboxId}`,
8647
+ checked: selected,
8648
+ onChange: () => {
8649
+ },
8650
+ tabIndex: -1,
8651
+ "aria-hidden": true
8652
+ }
8653
+ ) });
8654
+ }
8655
+ return /* @__PURE__ */ jsx(Box, { className: classes.menuItemIndicator, children: selected && /* @__PURE__ */ jsx(Icon, { name: "check", size: "20" }) });
8656
+ };
8657
+ const renderLabel = () => {
8658
+ const labelContent = typeof label2 === "string" && highlightMatch ? highlightText(label2, highlightMatch) : label2;
8659
+ return /* @__PURE__ */ jsx(Box, { className: classes.menuItemLabel, children: labelContent });
8660
+ };
8661
+ return /* @__PURE__ */ jsxs(
8662
+ Box,
8663
+ {
8664
+ ref,
8665
+ role,
8666
+ "aria-disabled": disabled,
8667
+ "aria-selected": selected,
8668
+ "data-selected": selected,
8669
+ "data-active": active,
8670
+ className: cx(classes.menuItem, cssClassName, className),
8671
+ onClick: handleClick,
8672
+ ...otherProps,
8673
+ children: [
8674
+ renderIndicator(),
8675
+ iconLeft && /* @__PURE__ */ jsx(Box, { className: classes.menuItemIconLeft, children: /* @__PURE__ */ jsx(Icon, { name: iconLeft, size: "24" }) }),
8676
+ /* @__PURE__ */ jsxs(Box, { className: classes.menuItemContent, children: [
8677
+ renderLabel(),
8678
+ description && /* @__PURE__ */ jsx(Box, { className: classes.menuItemDescription, children: description })
8679
+ ] }),
8680
+ iconRight && /* @__PURE__ */ jsx(Box, { className: classes.menuItemIconRight, children: /* @__PURE__ */ jsx(Icon, { name: iconRight, size: "24" }) })
8681
+ ]
8682
+ }
8683
+ );
8684
+ }
8685
+ );
8686
+ MenuListItem.displayName = "MenuListItem";
8687
+ const MenuListDivider = ({
8688
+ size: size2,
8689
+ indicatorPosition,
8690
+ className,
8691
+ ...props
8692
+ }) => {
8693
+ const [cssClassName, otherProps] = splitProps(props);
8694
+ const classes = menu({ size: size2, indicatorPosition });
8695
+ return /* @__PURE__ */ jsx(
8696
+ Box,
8697
+ {
8698
+ role: "separator",
8699
+ className: cx(classes.menuDivider, cssClassName, className),
8700
+ ...otherProps
8701
+ }
8702
+ );
8703
+ };
8704
+ const MenuListGroup = ({
8705
+ label: label2,
8706
+ size: size2,
8707
+ indicatorPosition,
8708
+ children,
8709
+ className,
8710
+ ...props
8711
+ }) => {
8712
+ const [cssClassName, otherProps] = splitProps(props);
8713
+ const classes = menu({ size: size2, indicatorPosition });
8714
+ return /* @__PURE__ */ jsxs(
8715
+ Box,
8716
+ {
8717
+ role: "group",
8718
+ "aria-label": label2,
8719
+ className: cx(classes.menuGroup, cssClassName, className),
8720
+ ...otherProps,
8721
+ children: [
8722
+ label2 && /* @__PURE__ */ jsx(Box, { className: classes.menuGroupLabel, children: label2 }),
8723
+ children
8724
+ ]
8725
+ }
8726
+ );
8727
+ };
8585
8728
  const caretStyles = css({
8586
8729
  transitionProperty: "transform",
8587
8730
  transitionDuration: "normal",
@@ -8654,7 +8797,6 @@ const Autocomplete = ({
8654
8797
  const [open, setOpen] = useState(false);
8655
8798
  const [activeIndex, setActiveIndex] = useState(null);
8656
8799
  const listRef = useRef([]);
8657
- const classes = menu({ size: size$12, indicatorPosition });
8658
8800
  const filteredOptions = useMemo(() => {
8659
8801
  if (!value) return options;
8660
8802
  return options.filter((option) => filterFn(option, value));
@@ -8755,47 +8897,42 @@ const Autocomplete = ({
8755
8897
  }
8756
8898
  ),
8757
8899
  open && /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(FloatingFocusManager, { context: context2, modal: false, initialFocus: -1, children: /* @__PURE__ */ jsx(
8758
- Box,
8900
+ MenuList,
8759
8901
  {
8760
8902
  ref: refs.setFloating,
8761
8903
  style: floatingStyles,
8762
- className: classes.menu,
8763
8904
  id: `${id ?? name}-listbox`,
8764
8905
  role: "listbox",
8906
+ size: size$12,
8907
+ indicatorPosition,
8765
8908
  ...getFloatingProps(),
8766
- children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx(Box, { className: classes.menuItem, "aria-disabled": "true", children: /* @__PURE__ */ jsx(Box, { className: classes.menuItemContent, children: /* @__PURE__ */ jsx(Box, { className: classes.menuItemLabel, children: noResultsMessage }) }) }) : filteredOptions.map((option, index2) => {
8909
+ children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx(
8910
+ MenuListItem,
8911
+ {
8912
+ label: noResultsMessage,
8913
+ disabled: true,
8914
+ size: size$12,
8915
+ indicatorPosition
8916
+ }
8917
+ ) : filteredOptions.map((option, index2) => {
8767
8918
  const isActive = activeIndex === index2;
8768
- const highlightLabel = () => {
8769
- if (!value) return option.label;
8770
- const regex = new RegExp(
8771
- `(${value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`,
8772
- "gi"
8773
- );
8774
- const parts = option.label.split(regex);
8775
- return parts.map(
8776
- (part, i) => regex.test(part) ? /* @__PURE__ */ jsx("mark", { children: part }, i) : part
8777
- );
8778
- };
8779
- return /* @__PURE__ */ jsxs(
8780
- Box,
8919
+ return /* @__PURE__ */ jsx(
8920
+ MenuListItem,
8781
8921
  {
8782
8922
  ref: (node) => {
8783
8923
  listRef.current[index2] = node;
8784
8924
  },
8785
- role: "option",
8925
+ active: isActive,
8786
8926
  "aria-selected": isActive,
8787
- "aria-disabled": option.disabled,
8788
- "data-active": isActive,
8789
- className: classes.menuItem,
8927
+ disabled: option.disabled,
8928
+ label: option.label,
8929
+ description: option.description,
8930
+ iconLeft: option.icon,
8931
+ highlightMatch: value || void 0,
8790
8932
  onClick: () => handleOptionClick(option),
8791
- ...getItemProps(),
8792
- children: [
8793
- option.icon && /* @__PURE__ */ jsx(Box, { className: classes.menuItemIconLeft, children: /* @__PURE__ */ jsx(Icon, { name: option.icon, size: "24" }) }),
8794
- /* @__PURE__ */ jsxs(Box, { className: classes.menuItemContent, children: [
8795
- /* @__PURE__ */ jsx(Box, { className: classes.menuItemLabel, children: highlightLabel() }),
8796
- option.description && /* @__PURE__ */ jsx(Box, { className: classes.menuItemDescription, children: option.description })
8797
- ] })
8798
- ]
8933
+ size: size$12,
8934
+ indicatorPosition,
8935
+ ...getItemProps()
8799
8936
  },
8800
8937
  option.id
8801
8938
  );
@@ -9016,6 +9153,10 @@ export {
9016
9153
  MenuDivider,
9017
9154
  MenuGroup,
9018
9155
  MenuItem,
9156
+ MenuList,
9157
+ MenuListDivider,
9158
+ MenuListGroup,
9159
+ MenuListItem,
9019
9160
  MenuTrigger,
9020
9161
  Pre,
9021
9162
  Radio,