@majapisoftwares/ui 4.1.9 → 4.1.11
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export default function Spotlight<T extends object>({ recentSearchesId, open, setOpen, setQuery, query, onClickItem, results, loading, getItemId, getItemLabel, getItemPicture, getItemHref,
|
|
1
|
+
export default function Spotlight<T extends object>({ recentSearchesId, open, setOpen, setQuery, query, onClickItem, results, loading, getItemId, getItemLabel, getItemPicture, getItemHref, onSeeMoreClick, seeMoreHref, overlayClassName, dialogContentClassName, className, contentClassName, iconClassName, inputClassName, buttonClassName, noResultsClassName, recentSearchClassName, seeMoreLabel, noRecentSearchLabel, recentlySearchedLabel, noResultsLabel, onSubmit, }: {
|
|
2
2
|
recentSearchesId: string;
|
|
3
3
|
open: boolean;
|
|
4
4
|
setOpen: (open: boolean) => void;
|
|
@@ -11,7 +11,6 @@ export default function Spotlight<T extends object>({ recentSearchesId, open, se
|
|
|
11
11
|
getItemPicture?: (item: T) => string;
|
|
12
12
|
getItemHref?: (item: T) => string;
|
|
13
13
|
onClickItem?: (item: T) => void;
|
|
14
|
-
showSeeMoreButton?: boolean;
|
|
15
14
|
onSeeMoreClick?: () => void;
|
|
16
15
|
seeMoreHref?: string;
|
|
17
16
|
overlayClassName?: string;
|
|
@@ -23,8 +22,9 @@ export default function Spotlight<T extends object>({ recentSearchesId, open, se
|
|
|
23
22
|
buttonClassName?: string;
|
|
24
23
|
noResultsClassName?: string;
|
|
25
24
|
recentSearchClassName?: string;
|
|
26
|
-
|
|
25
|
+
seeMoreLabel?: string;
|
|
27
26
|
noRecentSearchLabel?: string;
|
|
28
27
|
recentlySearchedLabel?: string;
|
|
29
28
|
noResultsLabel?: string;
|
|
29
|
+
onSubmit?: () => void;
|
|
30
30
|
}): import("react").JSX.Element;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as Dialog from "@radix-ui/react-dialog";
|
|
2
2
|
import { VisuallyHidden } from "radix-ui";
|
|
3
|
-
import { useCallback } from "react";
|
|
4
|
-
import { ChevronRightIcon
|
|
3
|
+
import { Fragment, useCallback } from "react";
|
|
4
|
+
import { ChevronRightIcon } from "@heroicons/react/20/solid";
|
|
5
|
+
import { MagnifyingGlassIcon } from "@heroicons/react/24/solid";
|
|
5
6
|
import { useLocalStorage } from "react-use";
|
|
6
7
|
import { take, uniqBy } from "lodash-es";
|
|
7
8
|
import Image from "next/image";
|
|
@@ -10,7 +11,7 @@ import Skeleton from "../Skeleton";
|
|
|
10
11
|
import UnstyledButton from "../Button/UnstyledButton";
|
|
11
12
|
import Button from "../Button";
|
|
12
13
|
import clsx from "../../utils/clsx";
|
|
13
|
-
export default function Spotlight({ recentSearchesId, open, setOpen, setQuery, query, onClickItem, results, loading, getItemId = (item) => item._id, getItemLabel = (item) => item.name, getItemPicture, getItemHref,
|
|
14
|
+
export default function Spotlight({ recentSearchesId, open, setOpen, setQuery, query, onClickItem, results, loading, getItemId = (item) => item._id, getItemLabel = (item) => item.name, getItemPicture, getItemHref, onSeeMoreClick, seeMoreHref, overlayClassName, dialogContentClassName, className, contentClassName, iconClassName, inputClassName, buttonClassName, noResultsClassName, recentSearchClassName, seeMoreLabel = "See more", noRecentSearchLabel = "No recent search", recentlySearchedLabel = "Recently searched", noResultsLabel = "No result found", onSubmit, }) {
|
|
14
15
|
const [recentQueries, setRecentQueries] = useLocalStorage(`spotlight-recent-queries-${recentSearchesId}`, []);
|
|
15
16
|
const handleClose = useCallback((item) => {
|
|
16
17
|
setRecentQueries(take(uniqBy([item, ...(recentQueries || [])], getItemId), 5));
|
|
@@ -21,57 +22,65 @@ export default function Spotlight({ recentSearchesId, open, setOpen, setQuery, q
|
|
|
21
22
|
onClickItem?.(item);
|
|
22
23
|
handleClose(item);
|
|
23
24
|
}, [handleClose, onClickItem]);
|
|
24
|
-
return (<Dialog.Root open={open} onOpenChange={setOpen}>
|
|
25
|
-
<Dialog.Portal>
|
|
26
|
-
<Dialog.Overlay className={clsx("fixed inset-0 z-20 flex justify-center bg-
|
|
27
|
-
<Dialog.Content className={clsx("fixed mx-auto w-full max-w-(--breakpoint-md) px-4 py-4 focus:outline-hidden md:py-8", "data-[state=closed]:animate-fade-out data-[state=open]:animate-elastic-slide-up-and-fade will-change-[transform,opacity]", dialogContentClassName)}>
|
|
28
|
-
<VisuallyHidden.Root>
|
|
29
|
-
<Dialog.Title />
|
|
30
|
-
<Dialog.Description />
|
|
31
|
-
</VisuallyHidden.Root>
|
|
32
|
-
<div className={clsx("flex w-full flex-col justify-center rounded-sm border border-zinc-800 bg-zinc-900", className)}>
|
|
33
|
-
<div className="px-4 py-4">
|
|
34
|
-
<Input className={clsx("w-full
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
</
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
25
|
+
return (<Dialog.Root open={open} onOpenChange={setOpen}>
|
|
26
|
+
<Dialog.Portal>
|
|
27
|
+
<Dialog.Overlay className={clsx("fixed inset-0 z-20 flex justify-center bg-white/30 backdrop-blur-xs dark:bg-black/30", "data-[state=closed]:animate-fade-out data-[state=open]:animate-slide-up-and-fade will-change-[opacity,transform]", overlayClassName)}>
|
|
28
|
+
<Dialog.Content className={clsx("fixed mx-auto w-full max-w-(--breakpoint-md) px-4 py-4 focus:outline-hidden md:py-8", "data-[state=closed]:animate-fade-out data-[state=open]:animate-elastic-slide-up-and-fade will-change-[transform,opacity]", dialogContentClassName)}>
|
|
29
|
+
<VisuallyHidden.Root>
|
|
30
|
+
<Dialog.Title />
|
|
31
|
+
<Dialog.Description />
|
|
32
|
+
</VisuallyHidden.Root>
|
|
33
|
+
<div className={clsx("flex w-full flex-col justify-center rounded-sm border border-zinc-200 bg-zinc-100 dark:border-zinc-800 dark:bg-zinc-900", className)}>
|
|
34
|
+
<div className="px-4 py-4">
|
|
35
|
+
<Input className={clsx("w-full", contentClassName)} inputClassName={clsx("border-none rounded-none shadow-none rounded-b-none dark:bg-zinc-900 dark:focus:ring-0 focus:ring-0 bg-transparent", inputClassName)} autoFocus={true} leading={<MagnifyingGlassIcon className={clsx("h-5 w-5 text-black dark:text-white", iconClassName)}/>} value={query} onChange={(e) => setQuery(e.target.value)} onKeyDown={(e) => {
|
|
36
|
+
if (e.key === "Enter") {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
onSubmit?.();
|
|
39
|
+
}
|
|
40
|
+
}}/>
|
|
41
|
+
</div>
|
|
42
|
+
<div className="w-full border-t border-zinc-200 p-4 dark:border-zinc-800">
|
|
43
|
+
<div className="flex flex-col gap-2">
|
|
44
|
+
{query ? (<>
|
|
45
|
+
{loading && (<div className="flex items-center gap-4">
|
|
46
|
+
{getItemPicture && <Skeleton className="h-16 w-28"/>}
|
|
47
|
+
<Skeleton className="h-6 w-32"/>
|
|
48
|
+
</div>)}
|
|
49
|
+
{!loading && !results?.length && (<div className={clsx("flex justify-center py-5 text-zinc-400 dark:text-zinc-600", noResultsClassName)}>
|
|
50
|
+
{noResultsLabel}
|
|
51
|
+
</div>)}
|
|
52
|
+
{!loading && !!results?.length && (<>
|
|
53
|
+
{results.map((item, i) => (<Fragment key={getItemId(item)}>
|
|
54
|
+
{i > 0 && (<div className="h-px bg-zinc-200 dark:bg-zinc-800"/>)}
|
|
55
|
+
<UnstyledButton key={getItemId(item)} href={getItemHref?.(item)} className="flex w-full items-center gap-4 rounded-sm hover:bg-zinc-200/90 dark:hover:bg-zinc-800/90" onClick={handleItemClick(item)}>
|
|
56
|
+
{getItemPicture && (<Image src={getItemPicture(item)} alt={getItemLabel(item)} width={200} height={378} className="h-16 w-28 rounded-sm object-cover"/>)}
|
|
57
|
+
<div className="text-black dark:text-white">
|
|
58
|
+
{getItemLabel(item)}
|
|
59
|
+
</div>
|
|
60
|
+
</UnstyledButton>
|
|
61
|
+
</Fragment>))}
|
|
62
|
+
{(onSeeMoreClick || seeMoreHref) && (<Button variant="filled" type="submit" className={clsx("mt-2 w-full dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700", buttonClassName)} trailing={<ChevronRightIcon />} onClick={onSeeMoreClick} href={seeMoreHref}>
|
|
63
|
+
{seeMoreLabel}
|
|
64
|
+
</Button>)}
|
|
65
|
+
</>)}
|
|
66
|
+
</>) : (<>
|
|
67
|
+
{recentQueries?.length ? (<div className={clsx("mb-2 text-zinc-600 dark:text-zinc-400", recentSearchClassName)}>
|
|
68
|
+
{recentlySearchedLabel}
|
|
69
|
+
</div>) : (<div className={clsx("flex justify-center py-5 text-zinc-400 dark:text-zinc-600", noResultsClassName)}>
|
|
70
|
+
{noRecentSearchLabel}
|
|
71
|
+
</div>)}
|
|
72
|
+
{recentQueries?.map((item) => (<UnstyledButton key={getItemId(item)} href={getItemHref?.(item)} className="flex w-full items-center gap-4 hover:bg-zinc-200/90 dark:hover:bg-zinc-800/90" onClick={handleItemClick(item)}>
|
|
73
|
+
{getItemPicture && (<Image src={getItemPicture(item)} alt={getItemLabel(item)} width={200} height={378} className="max-h-16 max-w-28 rounded-sm object-cover"/>)}
|
|
74
|
+
<div className="text-black dark:text-white">
|
|
75
|
+
{getItemLabel(item)}
|
|
76
|
+
</div>
|
|
77
|
+
</UnstyledButton>))}
|
|
78
|
+
</>)}
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</Dialog.Content>
|
|
83
|
+
</Dialog.Overlay>
|
|
84
|
+
</Dialog.Portal>
|
|
76
85
|
</Dialog.Root>);
|
|
77
86
|
}
|