@motor-hero/ui-kit 0.23.1 → 0.24.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/components/combobox.d.ts +18 -2
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/multi-combobox.d.ts +13 -1
- package/dist/components/multi-combobox.d.ts.map +1 -1
- package/dist/hooks/use-infinite-scroll-sentinel.d.ts +16 -0
- package/dist/hooks/use-infinite-scroll-sentinel.d.ts.map +1 -0
- package/dist/index.cjs +189 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +194 -97
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/combobox.tsx +66 -11
- package/src/components/multi-combobox.tsx +61 -8
- package/src/hooks/use-infinite-scroll-sentinel.ts +47 -0
package/dist/index.js
CHANGED
|
@@ -615,18 +615,52 @@ PasswordInput.displayName = "PasswordInput";
|
|
|
615
615
|
// src/components/combobox.tsx
|
|
616
616
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
617
617
|
import { Command as CommandPrimitive } from "cmdk";
|
|
618
|
-
import { Check, ChevronsUpDown, Search } from "lucide-react";
|
|
619
|
-
import * as
|
|
618
|
+
import { Check, ChevronsUpDown, Loader2, Search } from "lucide-react";
|
|
619
|
+
import * as React6 from "react";
|
|
620
620
|
import { Drawer as DrawerPrimitive } from "vaul";
|
|
621
621
|
|
|
622
|
-
// src/hooks/use-
|
|
622
|
+
// src/hooks/use-infinite-scroll-sentinel.ts
|
|
623
623
|
import * as React4 from "react";
|
|
624
|
+
function useInfiniteScrollSentinel({
|
|
625
|
+
enabled,
|
|
626
|
+
loading,
|
|
627
|
+
onLoadMore
|
|
628
|
+
}) {
|
|
629
|
+
const listRef = React4.useRef(null);
|
|
630
|
+
const sentinelRef = React4.useRef(null);
|
|
631
|
+
const loadingRef = React4.useRef(loading);
|
|
632
|
+
const onLoadMoreRef = React4.useRef(onLoadMore);
|
|
633
|
+
React4.useEffect(() => {
|
|
634
|
+
loadingRef.current = loading;
|
|
635
|
+
onLoadMoreRef.current = onLoadMore;
|
|
636
|
+
});
|
|
637
|
+
React4.useEffect(() => {
|
|
638
|
+
if (!enabled) return;
|
|
639
|
+
const root = listRef.current;
|
|
640
|
+
const sentinel = sentinelRef.current;
|
|
641
|
+
if (!root || !sentinel) return;
|
|
642
|
+
const observer = new IntersectionObserver(
|
|
643
|
+
(entries) => {
|
|
644
|
+
if (entries[0]?.isIntersecting && !loadingRef.current) {
|
|
645
|
+
onLoadMoreRef.current?.();
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
{ root, rootMargin: "0px 0px 100px 0px" }
|
|
649
|
+
);
|
|
650
|
+
observer.observe(sentinel);
|
|
651
|
+
return () => observer.disconnect();
|
|
652
|
+
}, [enabled]);
|
|
653
|
+
return { listRef, sentinelRef };
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// src/hooks/use-is-desktop.ts
|
|
657
|
+
import * as React5 from "react";
|
|
624
658
|
var DESKTOP_QUERY = "(min-width: 640px)";
|
|
625
659
|
function useIsDesktop() {
|
|
626
|
-
const [isDesktop, setIsDesktop] =
|
|
660
|
+
const [isDesktop, setIsDesktop] = React5.useState(
|
|
627
661
|
() => typeof window !== "undefined" ? window.matchMedia(DESKTOP_QUERY).matches : true
|
|
628
662
|
);
|
|
629
|
-
|
|
663
|
+
React5.useEffect(() => {
|
|
630
664
|
const mql = window.matchMedia(DESKTOP_QUERY);
|
|
631
665
|
const onChange = () => setIsDesktop(mql.matches);
|
|
632
666
|
onChange();
|
|
@@ -649,11 +683,22 @@ function Combobox({
|
|
|
649
683
|
id,
|
|
650
684
|
className,
|
|
651
685
|
"aria-invalid": ariaInvalid,
|
|
652
|
-
"aria-describedby": ariaDescribedby
|
|
686
|
+
"aria-describedby": ariaDescribedby,
|
|
687
|
+
onSearchChange,
|
|
688
|
+
onLoadMore,
|
|
689
|
+
loading,
|
|
690
|
+
hasMore,
|
|
691
|
+
selectedOption
|
|
653
692
|
}) {
|
|
654
|
-
const [open, setOpen] =
|
|
693
|
+
const [open, setOpen] = React6.useState(false);
|
|
655
694
|
const isDesktop = useIsDesktop();
|
|
656
|
-
const
|
|
695
|
+
const isServer = onSearchChange !== void 0;
|
|
696
|
+
const selected = selectedOption?.value === value ? selectedOption : options.find((option) => option.value === value);
|
|
697
|
+
const { listRef, sentinelRef } = useInfiniteScrollSentinel({
|
|
698
|
+
enabled: isServer && !!hasMore,
|
|
699
|
+
loading,
|
|
700
|
+
onLoadMore
|
|
701
|
+
});
|
|
657
702
|
const trigger = /* @__PURE__ */ jsxs14(
|
|
658
703
|
"button",
|
|
659
704
|
{
|
|
@@ -674,55 +719,73 @@ function Combobox({
|
|
|
674
719
|
]
|
|
675
720
|
}
|
|
676
721
|
);
|
|
677
|
-
const command = /* @__PURE__ */ jsxs14(
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
722
|
+
const command = /* @__PURE__ */ jsxs14(
|
|
723
|
+
CommandPrimitive,
|
|
724
|
+
{
|
|
725
|
+
shouldFilter: !isServer,
|
|
726
|
+
className: "flex h-full w-full flex-col overflow-hidden",
|
|
727
|
+
children: [
|
|
728
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center border-b px-3", children: [
|
|
729
|
+
/* @__PURE__ */ jsx16(Search, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
|
|
730
|
+
/* @__PURE__ */ jsx16(
|
|
731
|
+
CommandPrimitive.Input,
|
|
732
|
+
{
|
|
733
|
+
placeholder: searchPlaceholder,
|
|
734
|
+
onValueChange: isServer ? onSearchChange : void 0,
|
|
735
|
+
className: "flex h-11 w-full bg-transparent py-2 text-base outline-none placeholder:text-muted-foreground sm:h-9 sm:text-sm"
|
|
736
|
+
}
|
|
737
|
+
)
|
|
738
|
+
] }),
|
|
739
|
+
/* @__PURE__ */ jsxs14(
|
|
740
|
+
CommandPrimitive.List,
|
|
741
|
+
{
|
|
742
|
+
ref: listRef,
|
|
743
|
+
className: "max-h-[50vh] overflow-y-auto overflow-x-hidden p-1 sm:max-h-60",
|
|
744
|
+
children: [
|
|
745
|
+
!isServer && /* @__PURE__ */ jsx16(CommandPrimitive.Empty, { className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }),
|
|
746
|
+
options.map((option) => /* @__PURE__ */ jsxs14(
|
|
747
|
+
CommandPrimitive.Item,
|
|
748
|
+
{
|
|
749
|
+
value: isServer ? option.value : option.label,
|
|
750
|
+
disabled: option.disabled,
|
|
751
|
+
onSelect: () => {
|
|
752
|
+
onChange(option.value);
|
|
753
|
+
setOpen(false);
|
|
754
|
+
},
|
|
755
|
+
className: "relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-2.5 text-sm outline-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 sm:py-1.5",
|
|
756
|
+
children: [
|
|
757
|
+
/* @__PURE__ */ jsx16(
|
|
758
|
+
Check,
|
|
759
|
+
{
|
|
760
|
+
className: cn(
|
|
761
|
+
"h-4 w-4 shrink-0",
|
|
762
|
+
value === option.value ? "opacity-100" : "opacity-0"
|
|
763
|
+
)
|
|
764
|
+
}
|
|
765
|
+
),
|
|
766
|
+
/* @__PURE__ */ jsx16("span", { className: "truncate", children: option.label })
|
|
767
|
+
]
|
|
768
|
+
},
|
|
769
|
+
option.value
|
|
770
|
+
)),
|
|
771
|
+
isServer && !loading && options.length === 0 && /* @__PURE__ */ jsx16("div", { className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }),
|
|
772
|
+
isServer && loading && /* @__PURE__ */ jsx16("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx16(Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) }),
|
|
773
|
+
isServer && hasMore && /* @__PURE__ */ jsx16("div", { ref: sentinelRef, "aria-hidden": true, className: "h-1" })
|
|
774
|
+
]
|
|
775
|
+
}
|
|
776
|
+
)
|
|
777
|
+
]
|
|
778
|
+
}
|
|
779
|
+
);
|
|
717
780
|
if (isDesktop) {
|
|
718
|
-
return /* @__PURE__ */ jsxs14(PopoverPrimitive.Root, { open, onOpenChange: setOpen,
|
|
781
|
+
return /* @__PURE__ */ jsxs14(PopoverPrimitive.Root, { open, onOpenChange: setOpen, children: [
|
|
719
782
|
/* @__PURE__ */ jsx16(PopoverPrimitive.Trigger, { asChild: true, children: trigger }),
|
|
720
783
|
/* @__PURE__ */ jsx16(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx16(
|
|
721
784
|
PopoverPrimitive.Content,
|
|
722
785
|
{
|
|
723
786
|
align: "start",
|
|
724
787
|
sideOffset: 4,
|
|
725
|
-
className: "z-50 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-md",
|
|
788
|
+
className: "pointer-events-auto z-50 overflow-hidden rounded-md border bg-popover p-0 text-popover-foreground shadow-md",
|
|
726
789
|
style: { width: "var(--radix-popover-trigger-width)" },
|
|
727
790
|
children: command
|
|
728
791
|
}
|
|
@@ -745,8 +808,8 @@ function Combobox({
|
|
|
745
808
|
// src/components/multi-combobox.tsx
|
|
746
809
|
import * as PopoverPrimitive2 from "@radix-ui/react-popover";
|
|
747
810
|
import { Command as CommandPrimitive2 } from "cmdk";
|
|
748
|
-
import { Check as Check2, ChevronsUpDown as ChevronsUpDown2, Search as Search2, X as X2 } from "lucide-react";
|
|
749
|
-
import * as
|
|
811
|
+
import { Check as Check2, ChevronsUpDown as ChevronsUpDown2, Loader2 as Loader22, Search as Search2, X as X2 } from "lucide-react";
|
|
812
|
+
import * as React7 from "react";
|
|
750
813
|
import { Drawer as DrawerPrimitive2 } from "vaul";
|
|
751
814
|
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
752
815
|
function MultiCombobox({
|
|
@@ -760,11 +823,27 @@ function MultiCombobox({
|
|
|
760
823
|
id,
|
|
761
824
|
className,
|
|
762
825
|
"aria-invalid": ariaInvalid,
|
|
763
|
-
"aria-describedby": ariaDescribedby
|
|
826
|
+
"aria-describedby": ariaDescribedby,
|
|
827
|
+
onSearchChange,
|
|
828
|
+
onLoadMore,
|
|
829
|
+
loading,
|
|
830
|
+
hasMore,
|
|
831
|
+
selectedOptions
|
|
764
832
|
}) {
|
|
765
|
-
const [open, setOpen] =
|
|
833
|
+
const [open, setOpen] = React7.useState(false);
|
|
766
834
|
const isDesktop = useIsDesktop();
|
|
767
|
-
const
|
|
835
|
+
const isServer = onSearchChange !== void 0;
|
|
836
|
+
const seen = /* @__PURE__ */ new Set();
|
|
837
|
+
const selected = [...selectedOptions ?? [], ...options].filter((option) => {
|
|
838
|
+
if (!value.includes(option.value) || seen.has(option.value)) return false;
|
|
839
|
+
seen.add(option.value);
|
|
840
|
+
return true;
|
|
841
|
+
});
|
|
842
|
+
const { listRef, sentinelRef } = useInfiniteScrollSentinel({
|
|
843
|
+
enabled: isServer && !!hasMore,
|
|
844
|
+
loading,
|
|
845
|
+
onLoadMore
|
|
846
|
+
});
|
|
768
847
|
const toggleValue = (optionValue) => {
|
|
769
848
|
onChange(
|
|
770
849
|
value.includes(optionValue) ? value.filter((v) => v !== optionValue) : [...value, optionValue]
|
|
@@ -824,43 +903,61 @@ function MultiCombobox({
|
|
|
824
903
|
]
|
|
825
904
|
}
|
|
826
905
|
);
|
|
827
|
-
const command = /* @__PURE__ */ jsxs15(
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
{
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
906
|
+
const command = /* @__PURE__ */ jsxs15(
|
|
907
|
+
CommandPrimitive2,
|
|
908
|
+
{
|
|
909
|
+
shouldFilter: !isServer,
|
|
910
|
+
className: "flex h-full w-full flex-col overflow-hidden",
|
|
911
|
+
children: [
|
|
912
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center border-b px-3", children: [
|
|
913
|
+
/* @__PURE__ */ jsx17(Search2, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
|
|
914
|
+
/* @__PURE__ */ jsx17(
|
|
915
|
+
CommandPrimitive2.Input,
|
|
916
|
+
{
|
|
917
|
+
placeholder: searchPlaceholder,
|
|
918
|
+
onValueChange: isServer ? onSearchChange : void 0,
|
|
919
|
+
className: "flex h-11 w-full bg-transparent py-2 text-base outline-none placeholder:text-muted-foreground sm:h-9 sm:text-sm"
|
|
920
|
+
}
|
|
921
|
+
)
|
|
922
|
+
] }),
|
|
923
|
+
/* @__PURE__ */ jsxs15(
|
|
924
|
+
CommandPrimitive2.List,
|
|
925
|
+
{
|
|
926
|
+
ref: listRef,
|
|
927
|
+
className: "max-h-[50vh] overflow-y-auto overflow-x-hidden p-1 sm:max-h-60",
|
|
928
|
+
children: [
|
|
929
|
+
!isServer && /* @__PURE__ */ jsx17(CommandPrimitive2.Empty, { className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }),
|
|
930
|
+
options.map((option) => /* @__PURE__ */ jsxs15(
|
|
931
|
+
CommandPrimitive2.Item,
|
|
932
|
+
{
|
|
933
|
+
value: isServer ? option.value : option.label,
|
|
934
|
+
disabled: option.disabled,
|
|
935
|
+
onSelect: () => toggleValue(option.value),
|
|
936
|
+
className: "relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-2.5 text-sm outline-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 sm:py-1.5",
|
|
937
|
+
children: [
|
|
938
|
+
/* @__PURE__ */ jsx17(
|
|
939
|
+
Check2,
|
|
940
|
+
{
|
|
941
|
+
className: cn(
|
|
942
|
+
"h-4 w-4 shrink-0",
|
|
943
|
+
value.includes(option.value) ? "opacity-100" : "opacity-0"
|
|
944
|
+
)
|
|
945
|
+
}
|
|
946
|
+
),
|
|
947
|
+
/* @__PURE__ */ jsx17("span", { className: "truncate", children: option.label })
|
|
948
|
+
]
|
|
949
|
+
},
|
|
950
|
+
option.value
|
|
951
|
+
)),
|
|
952
|
+
isServer && !loading && options.length === 0 && /* @__PURE__ */ jsx17("div", { className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }),
|
|
953
|
+
isServer && loading && /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx17(Loader22, { className: "h-4 w-4 animate-spin text-muted-foreground" }) }),
|
|
954
|
+
isServer && hasMore && /* @__PURE__ */ jsx17("div", { ref: sentinelRef, "aria-hidden": true, className: "h-1" })
|
|
955
|
+
]
|
|
956
|
+
}
|
|
957
|
+
)
|
|
958
|
+
]
|
|
959
|
+
}
|
|
960
|
+
);
|
|
864
961
|
if (isDesktop) {
|
|
865
962
|
return /* @__PURE__ */ jsxs15(PopoverPrimitive2.Root, { open, onOpenChange: setOpen, children: [
|
|
866
963
|
/* @__PURE__ */ jsx17(PopoverPrimitive2.Trigger, { asChild: true, disabled, children: trigger }),
|
|
@@ -892,7 +989,7 @@ function MultiCombobox({
|
|
|
892
989
|
// src/components/color-picker.tsx
|
|
893
990
|
import * as PopoverPrimitive3 from "@radix-ui/react-popover";
|
|
894
991
|
import { ChevronsUpDown as ChevronsUpDown3 } from "lucide-react";
|
|
895
|
-
import * as
|
|
992
|
+
import * as React8 from "react";
|
|
896
993
|
import { HexColorInput, HexColorPicker } from "react-colorful";
|
|
897
994
|
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
898
995
|
function ColorPicker({
|
|
@@ -905,7 +1002,7 @@ function ColorPicker({
|
|
|
905
1002
|
"aria-invalid": ariaInvalid,
|
|
906
1003
|
"aria-describedby": ariaDescribedby
|
|
907
1004
|
}) {
|
|
908
|
-
const [open, setOpen] =
|
|
1005
|
+
const [open, setOpen] = React8.useState(false);
|
|
909
1006
|
const color = value || "";
|
|
910
1007
|
return /* @__PURE__ */ jsxs16(PopoverPrimitive3.Root, { open, onOpenChange: setOpen, modal: true, children: [
|
|
911
1008
|
/* @__PURE__ */ jsx18(PopoverPrimitive3.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs16(
|
|
@@ -1041,7 +1138,7 @@ function DataTableWrapper({
|
|
|
1041
1138
|
}
|
|
1042
1139
|
|
|
1043
1140
|
// src/components/mobile-card-list.tsx
|
|
1044
|
-
import { useRef } from "react";
|
|
1141
|
+
import { useRef as useRef2 } from "react";
|
|
1045
1142
|
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1046
1143
|
var SCROLL_THRESHOLD = 8;
|
|
1047
1144
|
function MobileCardList({
|
|
@@ -1052,8 +1149,8 @@ function MobileCardList({
|
|
|
1052
1149
|
loadingCount = 5,
|
|
1053
1150
|
className
|
|
1054
1151
|
}) {
|
|
1055
|
-
const start =
|
|
1056
|
-
const scrolled =
|
|
1152
|
+
const start = useRef2(null);
|
|
1153
|
+
const scrolled = useRef2(false);
|
|
1057
1154
|
const onTouchStart = (e) => {
|
|
1058
1155
|
const t = e.touches[0];
|
|
1059
1156
|
start.current = { x: t.clientX, y: t.clientY };
|