@okshaun/components 0.5.3 → 0.5.5

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;
@@ -1014,6 +1058,7 @@ export declare const Spinner: React.FC<SpinnerProps>;
1014
1058
  export declare type SpinnerProps = Omit<BoxProps, keyof SpinnerVariantProps> & SpinnerVariantProps & {
1015
1059
  size?: 'standard' | 'small' | 'large';
1016
1060
  className?: string;
1061
+ inverse?: boolean;
1017
1062
  };
1018
1063
 
1019
1064
  export declare const splitProps: (props: Record<string, any>) => [string, Record<string, any>];
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";
@@ -731,6 +731,9 @@ const spinnerVariantMap = {
731
731
  "standard",
732
732
  "small",
733
733
  "large"
734
+ ],
735
+ "inverse": [
736
+ "true"
734
737
  ]
735
738
  };
736
739
  const spinnerVariantKeys = Object.keys(spinnerVariantMap);
@@ -2267,6 +2270,7 @@ const Text = ({
2267
2270
  };
2268
2271
  const Spinner = ({
2269
2272
  size: size2,
2273
+ inverse,
2270
2274
  ...props
2271
2275
  }) => {
2272
2276
  const [className, otherProps] = splitProps(props);
@@ -2274,7 +2278,7 @@ const Spinner = ({
2274
2278
  Box,
2275
2279
  {
2276
2280
  as: "div",
2277
- className: cx(spinner({ size: size2 }), className),
2281
+ className: cx(spinner({ size: size2, inverse }), className),
2278
2282
  ...otherProps
2279
2283
  }
2280
2284
  );
@@ -2671,7 +2675,12 @@ const Button = React.forwardRef(
2671
2675
  right: "0",
2672
2676
  bottom: "0",
2673
2677
  placeItems: "center",
2674
- children: /* @__PURE__ */ jsx(Spinner, {})
2678
+ children: /* @__PURE__ */ jsx(
2679
+ Spinner,
2680
+ {
2681
+ ...appearance === "primary" ? { inverse: true } : {}
2682
+ }
2683
+ )
2675
2684
  }
2676
2685
  )
2677
2686
  ] })
@@ -2878,7 +2887,12 @@ const IconButton = React.forwardRef(
2878
2887
  right: "0",
2879
2888
  bottom: "0",
2880
2889
  placeItems: "center",
2881
- children: /* @__PURE__ */ jsx(Spinner, {})
2890
+ children: /* @__PURE__ */ jsx(
2891
+ Spinner,
2892
+ {
2893
+ ...appearance === "primary" ? { inverse: true } : {}
2894
+ }
2895
+ )
2882
2896
  }
2883
2897
  )
2884
2898
  ] })
@@ -8447,9 +8461,12 @@ const Menu = ({
8447
8461
  ) }) })
8448
8462
  ] });
8449
8463
  };
8450
- const highlightText = (text2, match) => {
8464
+ const highlightText$1 = (text2, match) => {
8451
8465
  if (!match || typeof text2 !== "string") return text2;
8452
- const regex = new RegExp(`(${match.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`, "gi");
8466
+ const regex = new RegExp(
8467
+ `(${match.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`,
8468
+ "gi"
8469
+ );
8453
8470
  const parts = text2.split(regex);
8454
8471
  return parts.map(
8455
8472
  (part, i) => regex.test(part) ? /* @__PURE__ */ jsx("mark", { children: part }, i) : part
@@ -8513,10 +8530,10 @@ const MenuItem = ({
8513
8530
  }
8514
8531
  ) });
8515
8532
  }
8516
- return /* @__PURE__ */ jsx(Box, { className: classes.menuItemIndicator, children: selected && /* @__PURE__ */ jsx(Icon, { name: "check", size: "20" }) });
8533
+ return /* @__PURE__ */ jsx(Box, { className: classes.menuItemIndicator, children: selected && /* @__PURE__ */ jsx(Icon, { name: "check", size: "24" }) });
8517
8534
  };
8518
8535
  const renderLabel = () => {
8519
- const labelContent = typeof label2 === "string" && highlightMatch ? highlightText(label2, highlightMatch) : label2;
8536
+ const labelContent = typeof label2 === "string" && highlightMatch ? highlightText$1(label2, highlightMatch) : label2;
8520
8537
  return /* @__PURE__ */ jsx(Box, { className: classes.menuItemLabel, children: labelContent });
8521
8538
  };
8522
8539
  return /* @__PURE__ */ jsxs(
@@ -8582,6 +8599,152 @@ const MenuGroup = ({
8582
8599
  }
8583
8600
  );
8584
8601
  };
8602
+ const MenuList = React__default.forwardRef(
8603
+ ({ size: size2, indicatorPosition, role = "listbox", className, ...props }, ref) => {
8604
+ const [cssClassName, otherProps] = splitProps(props);
8605
+ const classes = menu({ size: size2, indicatorPosition });
8606
+ return /* @__PURE__ */ jsx(
8607
+ Box,
8608
+ {
8609
+ ref,
8610
+ role,
8611
+ className: cx(classes.menu, cssClassName, className),
8612
+ ...otherProps
8613
+ }
8614
+ );
8615
+ }
8616
+ );
8617
+ MenuList.displayName = "MenuList";
8618
+ const highlightText = (text2, match) => {
8619
+ if (!match || typeof text2 !== "string") return text2;
8620
+ const regex = new RegExp(
8621
+ `(${match.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`,
8622
+ "gi"
8623
+ );
8624
+ const parts = text2.split(regex);
8625
+ return parts.map(
8626
+ (part, i) => regex.test(part) ? /* @__PURE__ */ jsx("mark", { children: part }, i) : part
8627
+ );
8628
+ };
8629
+ const MenuListItem = React__default.forwardRef(
8630
+ ({
8631
+ type = "action",
8632
+ selected = false,
8633
+ active = false,
8634
+ onClick,
8635
+ disabled = false,
8636
+ label: label2,
8637
+ description,
8638
+ iconLeft,
8639
+ iconRight,
8640
+ highlightMatch,
8641
+ selectionIndicator = "checkmark",
8642
+ size: size2,
8643
+ indicatorPosition,
8644
+ role = "option",
8645
+ className,
8646
+ ...props
8647
+ }, ref) => {
8648
+ const [cssClassName, otherProps] = splitProps(props);
8649
+ const classes = menu({ size: size2, indicatorPosition });
8650
+ const checkboxId = useId$1();
8651
+ const isSelectable = type === "single-select" || type === "multi-select";
8652
+ const showIndicator = isSelectable;
8653
+ const handleClick = useCallback(
8654
+ (event) => {
8655
+ if (disabled) return;
8656
+ onClick == null ? void 0 : onClick(event);
8657
+ },
8658
+ [disabled, onClick]
8659
+ );
8660
+ const renderIndicator = () => {
8661
+ if (!showIndicator) return null;
8662
+ if (selectionIndicator === "checkbox") {
8663
+ return /* @__PURE__ */ jsx(Box, { className: classes.menuItemIndicator, children: /* @__PURE__ */ jsx(
8664
+ Checkbox,
8665
+ {
8666
+ name: `menu-list-item-checkbox-${checkboxId}`,
8667
+ checked: selected,
8668
+ onChange: () => {
8669
+ },
8670
+ tabIndex: -1,
8671
+ "aria-hidden": true
8672
+ }
8673
+ ) });
8674
+ }
8675
+ return /* @__PURE__ */ jsx(Box, { className: classes.menuItemIndicator, children: selected && /* @__PURE__ */ jsx(Icon, { name: "check", size: "24" }) });
8676
+ };
8677
+ const renderLabel = () => {
8678
+ const labelContent = typeof label2 === "string" && highlightMatch ? highlightText(label2, highlightMatch) : label2;
8679
+ return /* @__PURE__ */ jsx(Box, { className: classes.menuItemLabel, children: labelContent });
8680
+ };
8681
+ return /* @__PURE__ */ jsxs(
8682
+ Box,
8683
+ {
8684
+ ref,
8685
+ role,
8686
+ "aria-disabled": disabled,
8687
+ "aria-selected": selected,
8688
+ "data-selected": selected,
8689
+ "data-active": active,
8690
+ className: cx(classes.menuItem, cssClassName, className),
8691
+ onClick: handleClick,
8692
+ ...otherProps,
8693
+ children: [
8694
+ renderIndicator(),
8695
+ iconLeft && /* @__PURE__ */ jsx(Box, { className: classes.menuItemIconLeft, children: /* @__PURE__ */ jsx(Icon, { name: iconLeft, size: "24" }) }),
8696
+ /* @__PURE__ */ jsxs(Box, { className: classes.menuItemContent, children: [
8697
+ renderLabel(),
8698
+ description && /* @__PURE__ */ jsx(Box, { className: classes.menuItemDescription, children: description })
8699
+ ] }),
8700
+ iconRight && /* @__PURE__ */ jsx(Box, { className: classes.menuItemIconRight, children: /* @__PURE__ */ jsx(Icon, { name: iconRight, size: "24" }) })
8701
+ ]
8702
+ }
8703
+ );
8704
+ }
8705
+ );
8706
+ MenuListItem.displayName = "MenuListItem";
8707
+ const MenuListDivider = ({
8708
+ size: size2,
8709
+ indicatorPosition,
8710
+ className,
8711
+ ...props
8712
+ }) => {
8713
+ const [cssClassName, otherProps] = splitProps(props);
8714
+ const classes = menu({ size: size2, indicatorPosition });
8715
+ return /* @__PURE__ */ jsx(
8716
+ Box,
8717
+ {
8718
+ role: "separator",
8719
+ className: cx(classes.menuDivider, cssClassName, className),
8720
+ ...otherProps
8721
+ }
8722
+ );
8723
+ };
8724
+ const MenuListGroup = ({
8725
+ label: label2,
8726
+ size: size2,
8727
+ indicatorPosition,
8728
+ children,
8729
+ className,
8730
+ ...props
8731
+ }) => {
8732
+ const [cssClassName, otherProps] = splitProps(props);
8733
+ const classes = menu({ size: size2, indicatorPosition });
8734
+ return /* @__PURE__ */ jsxs(
8735
+ Box,
8736
+ {
8737
+ role: "group",
8738
+ "aria-label": label2,
8739
+ className: cx(classes.menuGroup, cssClassName, className),
8740
+ ...otherProps,
8741
+ children: [
8742
+ label2 && /* @__PURE__ */ jsx(Box, { className: classes.menuGroupLabel, children: label2 }),
8743
+ children
8744
+ ]
8745
+ }
8746
+ );
8747
+ };
8585
8748
  const caretStyles = css({
8586
8749
  transitionProperty: "transform",
8587
8750
  transitionDuration: "normal",
@@ -8654,7 +8817,6 @@ const Autocomplete = ({
8654
8817
  const [open, setOpen] = useState(false);
8655
8818
  const [activeIndex, setActiveIndex] = useState(null);
8656
8819
  const listRef = useRef([]);
8657
- const classes = menu({ size: size$12, indicatorPosition });
8658
8820
  const filteredOptions = useMemo(() => {
8659
8821
  if (!value) return options;
8660
8822
  return options.filter((option) => filterFn(option, value));
@@ -8755,47 +8917,42 @@ const Autocomplete = ({
8755
8917
  }
8756
8918
  ),
8757
8919
  open && /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(FloatingFocusManager, { context: context2, modal: false, initialFocus: -1, children: /* @__PURE__ */ jsx(
8758
- Box,
8920
+ MenuList,
8759
8921
  {
8760
8922
  ref: refs.setFloating,
8761
8923
  style: floatingStyles,
8762
- className: classes.menu,
8763
8924
  id: `${id ?? name}-listbox`,
8764
8925
  role: "listbox",
8926
+ size: size$12,
8927
+ indicatorPosition,
8765
8928
  ...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) => {
8929
+ children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx(
8930
+ MenuListItem,
8931
+ {
8932
+ label: noResultsMessage,
8933
+ disabled: true,
8934
+ size: size$12,
8935
+ indicatorPosition
8936
+ }
8937
+ ) : filteredOptions.map((option, index2) => {
8767
8938
  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,
8939
+ return /* @__PURE__ */ jsx(
8940
+ MenuListItem,
8781
8941
  {
8782
8942
  ref: (node) => {
8783
8943
  listRef.current[index2] = node;
8784
8944
  },
8785
- role: "option",
8945
+ active: isActive,
8786
8946
  "aria-selected": isActive,
8787
- "aria-disabled": option.disabled,
8788
- "data-active": isActive,
8789
- className: classes.menuItem,
8947
+ disabled: option.disabled,
8948
+ label: option.label,
8949
+ description: option.description,
8950
+ iconLeft: option.icon,
8951
+ highlightMatch: value || void 0,
8790
8952
  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
- ]
8953
+ size: size$12,
8954
+ indicatorPosition,
8955
+ ...getItemProps()
8799
8956
  },
8800
8957
  option.id
8801
8958
  );
@@ -9016,6 +9173,10 @@ export {
9016
9173
  MenuDivider,
9017
9174
  MenuGroup,
9018
9175
  MenuItem,
9176
+ MenuList,
9177
+ MenuListDivider,
9178
+ MenuListGroup,
9179
+ MenuListItem,
9019
9180
  MenuTrigger,
9020
9181
  Pre,
9021
9182
  Radio,