@alankrit2/ui 0.4.1 → 0.5.0

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.mts CHANGED
@@ -210,6 +210,39 @@ interface ToggleProps {
210
210
 
211
211
  declare const Toggle: React__default.ForwardRefExoticComponent<ToggleProps & React__default.RefAttributes<HTMLButtonElement>>;
212
212
 
213
+ declare const ComboboxRoot: any;
214
+
215
+ interface ComboboxProps {
216
+ value?: string;
217
+ defaultValue?: string;
218
+ onValueChange?: (value: string) => void;
219
+ open?: boolean;
220
+ defaultOpen?: boolean;
221
+ onOpenChange?: (open: boolean) => void;
222
+ inputValue?: string;
223
+ defaultInputValue?: string;
224
+ onInputChange?: (value: string) => void;
225
+ children?: ReactNode;
226
+ className?: string;
227
+ }
228
+ interface ComboboxInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange"> {
229
+ asChild?: boolean;
230
+ onChange?: (value: string) => void;
231
+ }
232
+ interface ComboboxTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
233
+ asChild?: boolean;
234
+ }
235
+ interface ComboboxContentProps extends React.HTMLAttributes<HTMLDivElement> {
236
+ asChild?: boolean;
237
+ portal?: boolean;
238
+ }
239
+ interface ComboboxItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSelect"> {
240
+ value: string;
241
+ asChild?: boolean;
242
+ disabled?: boolean;
243
+ onSelect?: (value: string) => void;
244
+ }
245
+
213
246
  interface UseControlledOptions<T> {
214
247
  /** Controlled value */
215
248
  value?: T;
@@ -277,4 +310,4 @@ declare const Slot: React$1.ForwardRefExoticComponent<SlotProps & React$1.RefAtt
277
310
  */
278
311
  declare function composeRefs<T>(...refs: Array<React.Ref<T> | undefined>): (node: T | null) => void;
279
312
 
280
- export { Button, type ButtonProps, _default as Dialog, type DialogCloseProps, type DialogContentProps, type DialogDescriptionProps, type DialogOverlayProps, type DialogPortalProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, DropdownRoot as Dropdown, type DropdownContentProps, type DropdownItemProps, type DropdownProps, type DropdownTriggerProps, Slot, Tabs, type TabsContentProps, type TabsListProps, type TabsProps, type TabsTriggerProps, Toggle, type ToggleProps, composeRefs, useBodyScrollLock, useClickOutside, useControlled, useEscapeKeydown, useFocusTrap, useStableId };
313
+ export { Button, type ButtonProps, ComboboxRoot as Combobox, type ComboboxContentProps, type ComboboxInputProps, type ComboboxItemProps, type ComboboxProps, type ComboboxTriggerProps, _default as Dialog, type DialogCloseProps, type DialogContentProps, type DialogDescriptionProps, type DialogOverlayProps, type DialogPortalProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, DropdownRoot as Dropdown, type DropdownContentProps, type DropdownItemProps, type DropdownProps, type DropdownTriggerProps, Slot, Tabs, type TabsContentProps, type TabsListProps, type TabsProps, type TabsTriggerProps, Toggle, type ToggleProps, composeRefs, useBodyScrollLock, useClickOutside, useControlled, useEscapeKeydown, useFocusTrap, useStableId };
package/dist/index.d.ts CHANGED
@@ -210,6 +210,39 @@ interface ToggleProps {
210
210
 
211
211
  declare const Toggle: React__default.ForwardRefExoticComponent<ToggleProps & React__default.RefAttributes<HTMLButtonElement>>;
212
212
 
213
+ declare const ComboboxRoot: any;
214
+
215
+ interface ComboboxProps {
216
+ value?: string;
217
+ defaultValue?: string;
218
+ onValueChange?: (value: string) => void;
219
+ open?: boolean;
220
+ defaultOpen?: boolean;
221
+ onOpenChange?: (open: boolean) => void;
222
+ inputValue?: string;
223
+ defaultInputValue?: string;
224
+ onInputChange?: (value: string) => void;
225
+ children?: ReactNode;
226
+ className?: string;
227
+ }
228
+ interface ComboboxInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange"> {
229
+ asChild?: boolean;
230
+ onChange?: (value: string) => void;
231
+ }
232
+ interface ComboboxTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
233
+ asChild?: boolean;
234
+ }
235
+ interface ComboboxContentProps extends React.HTMLAttributes<HTMLDivElement> {
236
+ asChild?: boolean;
237
+ portal?: boolean;
238
+ }
239
+ interface ComboboxItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSelect"> {
240
+ value: string;
241
+ asChild?: boolean;
242
+ disabled?: boolean;
243
+ onSelect?: (value: string) => void;
244
+ }
245
+
213
246
  interface UseControlledOptions<T> {
214
247
  /** Controlled value */
215
248
  value?: T;
@@ -277,4 +310,4 @@ declare const Slot: React$1.ForwardRefExoticComponent<SlotProps & React$1.RefAtt
277
310
  */
278
311
  declare function composeRefs<T>(...refs: Array<React.Ref<T> | undefined>): (node: T | null) => void;
279
312
 
280
- export { Button, type ButtonProps, _default as Dialog, type DialogCloseProps, type DialogContentProps, type DialogDescriptionProps, type DialogOverlayProps, type DialogPortalProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, DropdownRoot as Dropdown, type DropdownContentProps, type DropdownItemProps, type DropdownProps, type DropdownTriggerProps, Slot, Tabs, type TabsContentProps, type TabsListProps, type TabsProps, type TabsTriggerProps, Toggle, type ToggleProps, composeRefs, useBodyScrollLock, useClickOutside, useControlled, useEscapeKeydown, useFocusTrap, useStableId };
313
+ export { Button, type ButtonProps, ComboboxRoot as Combobox, type ComboboxContentProps, type ComboboxInputProps, type ComboboxItemProps, type ComboboxProps, type ComboboxTriggerProps, _default as Dialog, type DialogCloseProps, type DialogContentProps, type DialogDescriptionProps, type DialogOverlayProps, type DialogPortalProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, DropdownRoot as Dropdown, type DropdownContentProps, type DropdownItemProps, type DropdownProps, type DropdownTriggerProps, Slot, Tabs, type TabsContentProps, type TabsListProps, type TabsProps, type TabsTriggerProps, Toggle, type ToggleProps, composeRefs, useBodyScrollLock, useClickOutside, useControlled, useEscapeKeydown, useFocusTrap, useStableId };
package/dist/index.js CHANGED
@@ -655,8 +655,310 @@ var Toggle = React8__namespace.default.forwardRef(
655
655
  }
656
656
  );
657
657
  Toggle.displayName = "Toggle";
658
+ var ComboboxContext = React8.createContext(
659
+ void 0
660
+ );
661
+ var useCombobox = () => {
662
+ const context = React8.useContext(ComboboxContext);
663
+ if (!context) {
664
+ throw new Error("useCombobox must be used within a Combobox");
665
+ }
666
+ return context;
667
+ };
668
+ var Combobox = ({
669
+ children,
670
+ value: valueProp,
671
+ defaultValue,
672
+ onValueChange,
673
+ open: openProp,
674
+ defaultOpen = false,
675
+ onOpenChange,
676
+ inputValue: inputValueProp,
677
+ defaultInputValue = "",
678
+ onInputChange,
679
+ className
680
+ }) => {
681
+ const [value, setValue] = useControlled({
682
+ value: valueProp,
683
+ defaultValue,
684
+ onChange: onValueChange
685
+ });
686
+ const [open, setOpen] = useControlled({
687
+ value: openProp,
688
+ defaultValue: defaultOpen,
689
+ onChange: onOpenChange
690
+ });
691
+ const [inputValue, setInputValue] = useControlled({
692
+ value: inputValueProp,
693
+ defaultValue: defaultInputValue,
694
+ onChange: onInputChange
695
+ });
696
+ const [activeIndex, setActiveIndex] = React8.useState(-1);
697
+ const [items, setItems] = React8.useState([]);
698
+ const inputRef = React8.useRef(null);
699
+ const triggerRef = React8.useRef(null);
700
+ const listId = useStableId();
701
+ const registerItem = React8.useCallback(
702
+ (item) => {
703
+ setItems((prev) => {
704
+ if (prev.find((i) => i.id === item.id)) return prev;
705
+ return [...prev, item];
706
+ });
707
+ },
708
+ []
709
+ );
710
+ const unregisterItem = React8.useCallback((id) => {
711
+ setItems((prev) => prev.filter((item) => item.id !== id));
712
+ }, []);
713
+ const contextValue = React8.useMemo(
714
+ () => ({
715
+ value: value || "",
716
+ onValueChange: setValue,
717
+ inputValue: inputValue || "",
718
+ onInputChange: setInputValue,
719
+ open: !!open,
720
+ onOpenChange: setOpen,
721
+ activeIndex,
722
+ setActiveIndex,
723
+ items,
724
+ registerItem,
725
+ unregisterItem,
726
+ listId,
727
+ inputRef,
728
+ triggerRef
729
+ }),
730
+ [
731
+ value,
732
+ setValue,
733
+ inputValue,
734
+ setInputValue,
735
+ open,
736
+ setOpen,
737
+ activeIndex,
738
+ items,
739
+ registerItem,
740
+ unregisterItem,
741
+ listId
742
+ ]
743
+ );
744
+ return /* @__PURE__ */ jsxRuntime.jsx(ComboboxContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { position: "relative" }, children }) });
745
+ };
746
+ var ComboboxInput = React8__namespace.default.forwardRef(
747
+ ({ asChild, onChange, onKeyDown, ...props }, ref) => {
748
+ const {
749
+ inputValue,
750
+ onInputChange,
751
+ open,
752
+ onOpenChange,
753
+ items,
754
+ activeIndex,
755
+ setActiveIndex,
756
+ onValueChange,
757
+ listId,
758
+ inputRef: contextInputRef
759
+ } = useCombobox();
760
+ const composedRef = composeRefs(ref, contextInputRef);
761
+ const Comp = asChild ? Slot : "input";
762
+ const handleKeyDown = (e) => {
763
+ onKeyDown?.(e);
764
+ switch (e.key) {
765
+ case "ArrowDown":
766
+ e.preventDefault();
767
+ if (!open) {
768
+ onOpenChange(true);
769
+ setActiveIndex(0);
770
+ } else {
771
+ setActiveIndex(
772
+ (prev) => prev < items.length - 1 ? prev + 1 : 0
773
+ );
774
+ }
775
+ break;
776
+ case "ArrowUp":
777
+ e.preventDefault();
778
+ if (!open) {
779
+ onOpenChange(true);
780
+ setActiveIndex(items.length - 1);
781
+ } else {
782
+ setActiveIndex((prev) => {
783
+ return prev > 0 ? prev - 1 : items.length - 1;
784
+ });
785
+ }
786
+ break;
787
+ case "Enter":
788
+ if (open && activeIndex >= 0 && items[activeIndex]) {
789
+ e.preventDefault();
790
+ const item = items[activeIndex];
791
+ if (!item.disabled) {
792
+ onValueChange(item.value);
793
+ onInputChange(item.value);
794
+ onOpenChange(false);
795
+ setActiveIndex(-1);
796
+ }
797
+ }
798
+ break;
799
+ case "Escape":
800
+ if (open) {
801
+ e.preventDefault();
802
+ onOpenChange(false);
803
+ setActiveIndex(-1);
804
+ }
805
+ break;
806
+ case "Tab":
807
+ if (open) {
808
+ onOpenChange(false);
809
+ }
810
+ break;
811
+ }
812
+ };
813
+ const handleChange = (e) => {
814
+ onChange?.(e.target.value);
815
+ onInputChange(e.target.value);
816
+ if (!open) {
817
+ onOpenChange(true);
818
+ }
819
+ };
820
+ const handleClick = (e) => {
821
+ props.onClick?.(e);
822
+ if (!open) {
823
+ onOpenChange(true);
824
+ }
825
+ };
826
+ return /* @__PURE__ */ jsxRuntime.jsx(
827
+ Comp,
828
+ {
829
+ ref: composedRef,
830
+ role: "combobox",
831
+ "aria-autocomplete": "list",
832
+ "aria-expanded": open,
833
+ "aria-controls": listId,
834
+ "aria-activedescendant": activeIndex >= 0 && items[activeIndex] ? items[activeIndex].id : void 0,
835
+ value: inputValue,
836
+ onChange: handleChange,
837
+ onKeyDown: handleKeyDown,
838
+ onClick: handleClick,
839
+ ...props
840
+ }
841
+ );
842
+ }
843
+ );
844
+ ComboboxInput.displayName = "Combobox.Input";
845
+ var ComboboxTrigger = React8__namespace.default.forwardRef(
846
+ ({ asChild, onClick, ...props }, ref) => {
847
+ const { open, onOpenChange, inputRef, triggerRef } = useCombobox();
848
+ const composedRef = composeRefs(ref, triggerRef);
849
+ const Comp = asChild ? Slot : "button";
850
+ return /* @__PURE__ */ jsxRuntime.jsx(
851
+ Comp,
852
+ {
853
+ ref: composedRef,
854
+ "aria-expanded": open,
855
+ type: "button",
856
+ onClick: (e) => {
857
+ onClick?.(e);
858
+ const nextOpen = !open;
859
+ onOpenChange(nextOpen);
860
+ if (nextOpen) {
861
+ requestAnimationFrame(() => {
862
+ inputRef.current?.focus();
863
+ });
864
+ }
865
+ },
866
+ ...props
867
+ }
868
+ );
869
+ }
870
+ );
871
+ ComboboxTrigger.displayName = "Combobox.Trigger";
872
+ var ComboboxContent = React8__namespace.default.forwardRef(
873
+ ({ asChild, children, portal = false, className, ...props }, ref) => {
874
+ const { open, onOpenChange, listId, inputRef, triggerRef } = useCombobox();
875
+ const contentRef = React8.useRef(null);
876
+ const composedRef = composeRefs(ref, contentRef);
877
+ useClickOutside(contentRef, (e) => {
878
+ const target = e.target;
879
+ if (inputRef.current?.contains(target)) return;
880
+ if (triggerRef.current?.contains(target)) return;
881
+ onOpenChange(false);
882
+ }, open);
883
+ if (!open) return null;
884
+ if (!open) return null;
885
+ const Comp = asChild ? Slot : "div";
886
+ const content = /* @__PURE__ */ jsxRuntime.jsx(
887
+ Comp,
888
+ {
889
+ ref: composedRef,
890
+ id: listId,
891
+ role: "listbox",
892
+ className,
893
+ ...props,
894
+ children
895
+ }
896
+ );
897
+ if (portal && typeof document !== "undefined") {
898
+ return ReactDOM.createPortal(content, document.body);
899
+ }
900
+ return content;
901
+ }
902
+ );
903
+ ComboboxContent.displayName = "Combobox.Content";
904
+ var ComboboxItem = React8__namespace.default.forwardRef(
905
+ ({ asChild, value, onClick, onSelect, disabled = false, ...props }, ref) => {
906
+ const {
907
+ onValueChange,
908
+ onInputChange,
909
+ onOpenChange,
910
+ registerItem,
911
+ unregisterItem,
912
+ items,
913
+ activeIndex,
914
+ setActiveIndex
915
+ } = useCombobox();
916
+ const id = useStableId();
917
+ const itemRef = React8.useRef(null);
918
+ const composedRef = composeRefs(ref, itemRef);
919
+ React8.useEffect(() => {
920
+ registerItem({ value, id, disabled });
921
+ return () => unregisterItem(id);
922
+ }, [value, id, disabled, registerItem, unregisterItem]);
923
+ const index = items.findIndex((i) => i.id === id);
924
+ const isActive = index === activeIndex;
925
+ const Comp = asChild ? Slot : "div";
926
+ return /* @__PURE__ */ jsxRuntime.jsx(
927
+ Comp,
928
+ {
929
+ ref: composedRef,
930
+ id,
931
+ role: "option",
932
+ "aria-selected": isActive,
933
+ "aria-disabled": disabled,
934
+ "data-disabled": disabled ? "" : void 0,
935
+ "data-highlighted": isActive ? "" : void 0,
936
+ onClick: (e) => {
937
+ if (disabled) return;
938
+ onClick?.(e);
939
+ onSelect?.(value);
940
+ onValueChange(value);
941
+ onInputChange(value);
942
+ onOpenChange(false);
943
+ setActiveIndex(-1);
944
+ },
945
+ onMouseEnter: () => {
946
+ if (!disabled) setActiveIndex(index);
947
+ },
948
+ ...props
949
+ }
950
+ );
951
+ }
952
+ );
953
+ ComboboxItem.displayName = "Combobox.Item";
954
+ var ComboboxRoot = Combobox;
955
+ ComboboxRoot.Input = ComboboxInput;
956
+ ComboboxRoot.Trigger = ComboboxTrigger;
957
+ ComboboxRoot.Content = ComboboxContent;
958
+ ComboboxRoot.Item = ComboboxItem;
658
959
 
659
960
  exports.Button = button_default;
961
+ exports.Combobox = ComboboxRoot;
660
962
  exports.Dialog = dialog_default;
661
963
  exports.Dropdown = dropdown_default;
662
964
  exports.Slot = Slot;