fumadocs-ui 8.0.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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/chunk-24NYFO7H.js +31 -0
- package/dist/chunk-2ZR5Z6B2.js +105 -0
- package/dist/chunk-36MVEJ25.js +39 -0
- package/dist/chunk-5EZE3X7G.js +31 -0
- package/dist/chunk-5KW7ATCP.js +23 -0
- package/dist/chunk-6C3VEZWH.js +9 -0
- package/dist/chunk-CBOHU2VN.js +28 -0
- package/dist/chunk-EDUYFB4P.js +43 -0
- package/dist/chunk-F62NYOL5.js +44 -0
- package/dist/chunk-GZQICERS.js +31 -0
- package/dist/chunk-IXYX64FW.js +243 -0
- package/dist/chunk-KCGRUOMD.js +13 -0
- package/dist/chunk-OG3QOLYP.js +43 -0
- package/dist/chunk-PLXR6QNH.js +21 -0
- package/dist/chunk-UIZNMCLD.js +49 -0
- package/dist/chunk-YAHHY62W.js +20 -0
- package/dist/components/accordion.d.mts +11 -0
- package/dist/components/accordion.js +128 -0
- package/dist/components/api.d.mts +20 -0
- package/dist/components/api.js +136 -0
- package/dist/components/callout.d.mts +13 -0
- package/dist/components/callout.js +39 -0
- package/dist/components/card.d.mts +12 -0
- package/dist/components/card.js +10 -0
- package/dist/components/codeblock.d.mts +12 -0
- package/dist/components/codeblock.js +14 -0
- package/dist/components/dialog/search-algolia.d.mts +15 -0
- package/dist/components/dialog/search-algolia.js +39 -0
- package/dist/components/dialog/search-default.d.mts +15 -0
- package/dist/components/dialog/search-default.js +39 -0
- package/dist/components/dialog/search.d.mts +25 -0
- package/dist/components/dialog/search.js +13 -0
- package/dist/components/files.d.mts +20 -0
- package/dist/components/files.js +56 -0
- package/dist/components/heading.d.mts +9 -0
- package/dist/components/heading.js +8 -0
- package/dist/components/image-zoom.d.mts +12 -0
- package/dist/components/image-zoom.js +39 -0
- package/dist/components/inline-toc.d.mts +11 -0
- package/dist/components/inline-toc.js +53 -0
- package/dist/components/roll-button.d.mts +14 -0
- package/dist/components/roll-button.js +54 -0
- package/dist/components/steps.d.mts +10 -0
- package/dist/components/steps.js +14 -0
- package/dist/components/tabs.d.mts +37 -0
- package/dist/components/tabs.js +141 -0
- package/dist/components/type-table.d.mts +23 -0
- package/dist/components/type-table.js +52 -0
- package/dist/i18n-dw7ODAws.d.mts +22 -0
- package/dist/i18n.d.mts +21 -0
- package/dist/i18n.js +146 -0
- package/dist/layout-YB7EFpgW.d.mts +79 -0
- package/dist/layout.client.d.mts +4 -0
- package/dist/layout.client.js +458 -0
- package/dist/layout.d.mts +3 -0
- package/dist/layout.js +97 -0
- package/dist/mdx.client.d.mts +7 -0
- package/dist/mdx.client.js +23 -0
- package/dist/mdx.d.mts +36 -0
- package/dist/mdx.js +51 -0
- package/dist/page.client.d.mts +29 -0
- package/dist/page.client.js +168 -0
- package/dist/page.d.mts +49 -0
- package/dist/page.js +56 -0
- package/dist/provider.d.mts +50 -0
- package/dist/provider.js +51 -0
- package/dist/style.css +1 -0
- package/dist/tailwind-plugin.d.ts +36 -0
- package/dist/tailwind-plugin.js +481 -0
- package/dist/tree-Zwtp9xPv.d.mts +15 -0
- package/package.json +97 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Fuma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/utils/use-copy-button.ts
|
|
2
|
+
import {
|
|
3
|
+
useState,
|
|
4
|
+
useRef,
|
|
5
|
+
useEffect,
|
|
6
|
+
useCallback
|
|
7
|
+
} from "react";
|
|
8
|
+
function useCopyButton(onCopy) {
|
|
9
|
+
const [checked, setChecked] = useState(false);
|
|
10
|
+
const timeoutRef = useRef(null);
|
|
11
|
+
const onClick = useCallback(() => {
|
|
12
|
+
if (timeoutRef.current)
|
|
13
|
+
window.clearTimeout(timeoutRef.current);
|
|
14
|
+
timeoutRef.current = window.setTimeout(() => {
|
|
15
|
+
setChecked(false);
|
|
16
|
+
}, 1500);
|
|
17
|
+
onCopy();
|
|
18
|
+
setChecked(true);
|
|
19
|
+
}, [onCopy]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
return () => {
|
|
22
|
+
if (timeoutRef.current)
|
|
23
|
+
window.clearTimeout(timeoutRef.current);
|
|
24
|
+
};
|
|
25
|
+
}, []);
|
|
26
|
+
return [checked, onClick];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
useCopyButton
|
|
31
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ScrollArea
|
|
3
|
+
} from "./chunk-OG3QOLYP.js";
|
|
4
|
+
import {
|
|
5
|
+
useCopyButton
|
|
6
|
+
} from "./chunk-24NYFO7H.js";
|
|
7
|
+
import {
|
|
8
|
+
buttonVariants
|
|
9
|
+
} from "./chunk-5KW7ATCP.js";
|
|
10
|
+
import {
|
|
11
|
+
cn
|
|
12
|
+
} from "./chunk-KCGRUOMD.js";
|
|
13
|
+
|
|
14
|
+
// src/components/codeblock.tsx
|
|
15
|
+
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
16
|
+
import { forwardRef, useCallback, useRef } from "react";
|
|
17
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
+
var Pre = forwardRef(
|
|
19
|
+
({ className, ...props }, ref) => {
|
|
20
|
+
return /* @__PURE__ */ jsx("pre", { ref, className: cn("nd-codeblock py-4", className), ...props, children: props.children });
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
Pre.displayName = "Pre";
|
|
24
|
+
var CodeBlock = forwardRef(
|
|
25
|
+
({ title, allowCopy = true, className, ...props }, ref) => {
|
|
26
|
+
const areaRef = useRef(null);
|
|
27
|
+
const onCopy = useCallback(() => {
|
|
28
|
+
const pre = areaRef.current?.getElementsByTagName("pre").item(0);
|
|
29
|
+
if (!pre?.textContent)
|
|
30
|
+
return;
|
|
31
|
+
void navigator.clipboard.writeText(pre.textContent);
|
|
32
|
+
}, []);
|
|
33
|
+
return /* @__PURE__ */ jsxs(
|
|
34
|
+
"figure",
|
|
35
|
+
{
|
|
36
|
+
ref,
|
|
37
|
+
className: cn(
|
|
38
|
+
"not-prose group relative my-6 overflow-hidden rounded-lg border bg-secondary/50 text-sm",
|
|
39
|
+
className
|
|
40
|
+
),
|
|
41
|
+
...props,
|
|
42
|
+
children: [
|
|
43
|
+
title ? /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center border-b bg-muted py-1.5 pl-4 pr-2 text-muted-foreground", children: [
|
|
44
|
+
/* @__PURE__ */ jsx("figcaption", { className: "flex-1", children: title }),
|
|
45
|
+
allowCopy ? /* @__PURE__ */ jsx(CopyButton, { onCopy }) : null
|
|
46
|
+
] }) : allowCopy && /* @__PURE__ */ jsx(
|
|
47
|
+
CopyButton,
|
|
48
|
+
{
|
|
49
|
+
className: "absolute right-2 top-2 z-[2]",
|
|
50
|
+
onCopy
|
|
51
|
+
}
|
|
52
|
+
),
|
|
53
|
+
/* @__PURE__ */ jsx(ScrollArea, { ref: areaRef, children: props.children })
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
CodeBlock.displayName = "CodeBlock";
|
|
60
|
+
function CopyButton({
|
|
61
|
+
className,
|
|
62
|
+
onCopy,
|
|
63
|
+
...props
|
|
64
|
+
}) {
|
|
65
|
+
const [checked, onClick] = useCopyButton(onCopy);
|
|
66
|
+
return /* @__PURE__ */ jsxs(
|
|
67
|
+
"button",
|
|
68
|
+
{
|
|
69
|
+
type: "button",
|
|
70
|
+
className: cn(
|
|
71
|
+
buttonVariants({
|
|
72
|
+
color: "muted",
|
|
73
|
+
className: "transition-all group-hover:opacity-100"
|
|
74
|
+
}),
|
|
75
|
+
!checked && "opacity-0",
|
|
76
|
+
className
|
|
77
|
+
),
|
|
78
|
+
"aria-label": "Copy Text",
|
|
79
|
+
onClick,
|
|
80
|
+
...props,
|
|
81
|
+
children: [
|
|
82
|
+
/* @__PURE__ */ jsx(
|
|
83
|
+
CheckIcon,
|
|
84
|
+
{
|
|
85
|
+
className: cn("size-3.5 transition-transform", !checked && "scale-0")
|
|
86
|
+
}
|
|
87
|
+
),
|
|
88
|
+
/* @__PURE__ */ jsx(
|
|
89
|
+
CopyIcon,
|
|
90
|
+
{
|
|
91
|
+
className: cn(
|
|
92
|
+
"absolute size-3.5 transition-transform",
|
|
93
|
+
checked && "scale-0"
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
Pre,
|
|
104
|
+
CodeBlock
|
|
105
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/contexts/search.tsx
|
|
2
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var SearchContext = createContext(void 0);
|
|
5
|
+
function useSearchContext() {
|
|
6
|
+
const ctx = useContext(SearchContext);
|
|
7
|
+
if (!ctx)
|
|
8
|
+
throw new Error("Missing root provider");
|
|
9
|
+
return ctx;
|
|
10
|
+
}
|
|
11
|
+
function SearchProvider({
|
|
12
|
+
SearchDialog,
|
|
13
|
+
children,
|
|
14
|
+
preload = true,
|
|
15
|
+
links = []
|
|
16
|
+
}) {
|
|
17
|
+
const [isOpen, setIsOpen] = useState(preload ? false : void 0);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const handler = (e) => {
|
|
20
|
+
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
|
21
|
+
setIsOpen(true);
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
window.addEventListener("keydown", handler);
|
|
26
|
+
return () => {
|
|
27
|
+
window.removeEventListener("keydown", handler);
|
|
28
|
+
};
|
|
29
|
+
}, []);
|
|
30
|
+
return /* @__PURE__ */ jsxs(SearchContext.Provider, { value: { links, setOpenSearch: setIsOpen }, children: [
|
|
31
|
+
isOpen !== void 0 && /* @__PURE__ */ jsx(SearchDialog, { open: isOpen, onOpenChange: setIsOpen }),
|
|
32
|
+
children
|
|
33
|
+
] });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
useSearchContext,
|
|
38
|
+
SearchProvider
|
|
39
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-KCGRUOMD.js";
|
|
4
|
+
|
|
5
|
+
// src/components/ui/collapsible.tsx
|
|
6
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
7
|
+
import { forwardRef } from "react";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
var Collapsible = CollapsiblePrimitive.Root;
|
|
10
|
+
var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
|
|
11
|
+
var CollapsibleContent2 = forwardRef(({ className, children, ...props }, ref) => {
|
|
12
|
+
return /* @__PURE__ */ jsx(
|
|
13
|
+
CollapsiblePrimitive.CollapsibleContent,
|
|
14
|
+
{
|
|
15
|
+
ref,
|
|
16
|
+
className: cn(
|
|
17
|
+
"overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
|
|
18
|
+
className
|
|
19
|
+
),
|
|
20
|
+
...props,
|
|
21
|
+
children
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
CollapsibleContent2.displayName = CollapsiblePrimitive.CollapsibleContent.displayName;
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
Collapsible,
|
|
29
|
+
CollapsibleTrigger2 as CollapsibleTrigger,
|
|
30
|
+
CollapsibleContent2 as CollapsibleContent
|
|
31
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/theme/variants.ts
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
var buttonVariants = cva(
|
|
4
|
+
"inline-flex items-center justify-center rounded-md p-2 text-sm font-medium transition-colors duration-100",
|
|
5
|
+
{
|
|
6
|
+
variants: {
|
|
7
|
+
color: {
|
|
8
|
+
outline: "border hover:bg-accent hover:text-accent-foreground",
|
|
9
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
10
|
+
secondary: "border bg-secondary text-secondary-foreground hover:bg-accent hover:text-accent-foreground",
|
|
11
|
+
muted: "bg-muted text-secondary-foreground hover:bg-accent hover:text-accent-foreground"
|
|
12
|
+
},
|
|
13
|
+
size: {
|
|
14
|
+
lg: "px-4 py-2 text-medium",
|
|
15
|
+
icon: "p-1.5 [&_svg]:size-5"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
buttonVariants
|
|
23
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-KCGRUOMD.js";
|
|
4
|
+
|
|
5
|
+
// src/components/heading.tsx
|
|
6
|
+
import { LinkIcon } from "lucide-react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
function Heading({
|
|
9
|
+
as,
|
|
10
|
+
className,
|
|
11
|
+
...props
|
|
12
|
+
}) {
|
|
13
|
+
const As = as ?? "h1";
|
|
14
|
+
return /* @__PURE__ */ jsx(As, { className: cn("scroll-m-20", className), ...props, children: props.id ? /* @__PURE__ */ jsxs("a", { href: `#${props.id}`, className: "not-prose group", children: [
|
|
15
|
+
props.children,
|
|
16
|
+
/* @__PURE__ */ jsx(
|
|
17
|
+
LinkIcon,
|
|
18
|
+
{
|
|
19
|
+
"aria-label": "Link to section",
|
|
20
|
+
className: "ml-2 inline size-4 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100"
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
] }) : props.children });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
Heading
|
|
28
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/utils/shared.ts
|
|
2
|
+
var defaultImageSizes = "(max-width: 768px) 100vw, (max-width: 1200px) 70vw, 800px";
|
|
3
|
+
function isActive(url, pathname, nested = true) {
|
|
4
|
+
return url === pathname || nested && pathname.startsWith(`${url}/`);
|
|
5
|
+
}
|
|
6
|
+
function replaceOrDefault(obj, def) {
|
|
7
|
+
if (obj?.enabled === false)
|
|
8
|
+
return;
|
|
9
|
+
if (obj?.component !== void 0)
|
|
10
|
+
return obj.component;
|
|
11
|
+
return def;
|
|
12
|
+
}
|
|
13
|
+
function hasActive(items, url) {
|
|
14
|
+
return items.some((item) => {
|
|
15
|
+
if (item.type === "page") {
|
|
16
|
+
return item.url === url;
|
|
17
|
+
}
|
|
18
|
+
if (item.type === "folder")
|
|
19
|
+
return item.index?.url === url || hasActive(item.children, url);
|
|
20
|
+
return false;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function flattenTree(tree) {
|
|
24
|
+
return tree.flatMap((node) => {
|
|
25
|
+
if (node.type === "separator")
|
|
26
|
+
return [];
|
|
27
|
+
if (node.type === "folder") {
|
|
28
|
+
const children = flattenTree(node.children);
|
|
29
|
+
if (!node.root && node.index)
|
|
30
|
+
return [node.index, ...children];
|
|
31
|
+
return children;
|
|
32
|
+
}
|
|
33
|
+
return [node];
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
defaultImageSizes,
|
|
39
|
+
isActive,
|
|
40
|
+
replaceOrDefault,
|
|
41
|
+
hasActive,
|
|
42
|
+
flattenTree
|
|
43
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-KCGRUOMD.js";
|
|
4
|
+
|
|
5
|
+
// src/components/card.tsx
|
|
6
|
+
import Link from "fumadocs-core/link";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
function Cards(props) {
|
|
9
|
+
return /* @__PURE__ */ jsx(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
...props,
|
|
13
|
+
className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2", props.className),
|
|
14
|
+
children: props.children
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
function Card({
|
|
19
|
+
icon,
|
|
20
|
+
title,
|
|
21
|
+
description,
|
|
22
|
+
...props
|
|
23
|
+
}) {
|
|
24
|
+
return /* @__PURE__ */ jsxs(
|
|
25
|
+
Link,
|
|
26
|
+
{
|
|
27
|
+
...props,
|
|
28
|
+
className: cn(
|
|
29
|
+
"not-prose block rounded-lg border bg-card p-4 text-sm text-card-foreground shadow-md transition-colors hover:bg-muted/80",
|
|
30
|
+
props.className
|
|
31
|
+
),
|
|
32
|
+
children: [
|
|
33
|
+
icon ? /* @__PURE__ */ jsx("div", { className: "mb-2 w-fit rounded-md border bg-muted p-2 text-muted-foreground [&_svg]:size-4", children: icon }) : null,
|
|
34
|
+
/* @__PURE__ */ jsx("h3", { className: "mb-1 font-medium", children: title }),
|
|
35
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: description })
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
Cards,
|
|
43
|
+
Card
|
|
44
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-KCGRUOMD.js";
|
|
4
|
+
|
|
5
|
+
// src/components/ui/popover.tsx
|
|
6
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
var Popover = PopoverPrimitive.Root;
|
|
10
|
+
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
11
|
+
var PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
12
|
+
PopoverPrimitive.Content,
|
|
13
|
+
{
|
|
14
|
+
ref,
|
|
15
|
+
align,
|
|
16
|
+
sideOffset,
|
|
17
|
+
side: "bottom",
|
|
18
|
+
className: cn(
|
|
19
|
+
"z-50 max-w-[90vw] rounded-md border bg-popover p-2 text-popover-foreground shadow-md outline-none data-[state=closed]:animate-popover-out data-[state=open]:animate-popover-in",
|
|
20
|
+
className
|
|
21
|
+
),
|
|
22
|
+
...props
|
|
23
|
+
}
|
|
24
|
+
) }));
|
|
25
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
Popover,
|
|
29
|
+
PopoverTrigger,
|
|
30
|
+
PopoverContent
|
|
31
|
+
};
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useSearchContext
|
|
3
|
+
} from "./chunk-36MVEJ25.js";
|
|
4
|
+
import {
|
|
5
|
+
useI18n
|
|
6
|
+
} from "./chunk-YAHHY62W.js";
|
|
7
|
+
import {
|
|
8
|
+
buttonVariants
|
|
9
|
+
} from "./chunk-5KW7ATCP.js";
|
|
10
|
+
import {
|
|
11
|
+
cn
|
|
12
|
+
} from "./chunk-KCGRUOMD.js";
|
|
13
|
+
|
|
14
|
+
// src/components/dialog/search.tsx
|
|
15
|
+
import { FileTextIcon, HashIcon, TextIcon } from "lucide-react";
|
|
16
|
+
import { useRouter } from "next/navigation";
|
|
17
|
+
import { useMemo } from "react";
|
|
18
|
+
|
|
19
|
+
// src/components/ui/command.tsx
|
|
20
|
+
import { Command as CommandPrimitive } from "cmdk";
|
|
21
|
+
import { Search } from "lucide-react";
|
|
22
|
+
import * as React2 from "react";
|
|
23
|
+
|
|
24
|
+
// src/components/ui/dialog.tsx
|
|
25
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
26
|
+
import * as React from "react";
|
|
27
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
28
|
+
var Dialog = DialogPrimitive.Root;
|
|
29
|
+
var DialogContent = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
|
|
30
|
+
/* @__PURE__ */ jsx(DialogPrimitive.DialogOverlay, { className: "fixed inset-0 z-50 bg-background/50 backdrop-blur-sm data-[state=closed]:animate-fade-out data-[state=open]:animate-fade-in" }),
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
DialogPrimitive.Content,
|
|
33
|
+
{
|
|
34
|
+
ref,
|
|
35
|
+
className: cn(
|
|
36
|
+
"fixed left-[50%] top-[10vh] z-50 w-[98vw] max-w-[640px] origin-left translate-x-[-50%] rounded-lg border bg-popover p-6 text-popover-foreground shadow-lg data-[state=closed]:animate-dialog-out data-[state=open]:animate-dialog-in",
|
|
37
|
+
className
|
|
38
|
+
),
|
|
39
|
+
...props,
|
|
40
|
+
children
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
] }));
|
|
44
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
45
|
+
function DialogHeader({
|
|
46
|
+
className,
|
|
47
|
+
...props
|
|
48
|
+
}) {
|
|
49
|
+
return /* @__PURE__ */ jsx(
|
|
50
|
+
"div",
|
|
51
|
+
{
|
|
52
|
+
className: cn(
|
|
53
|
+
"flex flex-col space-y-1.5 text-center sm:text-left",
|
|
54
|
+
className
|
|
55
|
+
),
|
|
56
|
+
...props
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
DialogHeader.displayName = "DialogHeader";
|
|
61
|
+
function DialogFooter({
|
|
62
|
+
className,
|
|
63
|
+
...props
|
|
64
|
+
}) {
|
|
65
|
+
return /* @__PURE__ */ jsx("div", { className: cn("mt-auto flex flex-col p-3", className), ...props });
|
|
66
|
+
}
|
|
67
|
+
DialogFooter.displayName = "DialogFooter";
|
|
68
|
+
var DialogClose = DialogPrimitive.Close;
|
|
69
|
+
|
|
70
|
+
// src/components/ui/command.tsx
|
|
71
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
72
|
+
var Command = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
|
|
73
|
+
CommandPrimitive,
|
|
74
|
+
{
|
|
75
|
+
ref,
|
|
76
|
+
className: cn("flex max-h-[80vh] flex-col", className),
|
|
77
|
+
shouldFilter: false,
|
|
78
|
+
loop: true,
|
|
79
|
+
...props
|
|
80
|
+
}
|
|
81
|
+
));
|
|
82
|
+
Command.displayName = CommandPrimitive.displayName;
|
|
83
|
+
var CommandInput = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 px-3", children: [
|
|
84
|
+
/* @__PURE__ */ jsx2(Search, { className: "size-4 shrink-0 text-muted-foreground" }),
|
|
85
|
+
/* @__PURE__ */ jsx2(
|
|
86
|
+
CommandPrimitive.Input,
|
|
87
|
+
{
|
|
88
|
+
ref,
|
|
89
|
+
className: cn(
|
|
90
|
+
"w-full bg-transparent py-3 text-base outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed",
|
|
91
|
+
className
|
|
92
|
+
),
|
|
93
|
+
...props
|
|
94
|
+
}
|
|
95
|
+
),
|
|
96
|
+
/* @__PURE__ */ jsx2(
|
|
97
|
+
DialogClose,
|
|
98
|
+
{
|
|
99
|
+
className: cn(
|
|
100
|
+
buttonVariants({
|
|
101
|
+
color: "outline",
|
|
102
|
+
size: "icon",
|
|
103
|
+
className: "text-xs"
|
|
104
|
+
})
|
|
105
|
+
),
|
|
106
|
+
children: "Esc"
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
] }));
|
|
110
|
+
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
|
111
|
+
var CommandList = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
|
|
112
|
+
CommandPrimitive.List,
|
|
113
|
+
{
|
|
114
|
+
ref,
|
|
115
|
+
className: cn("max-h-[460px] overflow-y-auto border-t p-2", className),
|
|
116
|
+
...props
|
|
117
|
+
}
|
|
118
|
+
));
|
|
119
|
+
CommandList.displayName = CommandPrimitive.List.displayName;
|
|
120
|
+
var CommandEmpty = React2.forwardRef((props, ref) => /* @__PURE__ */ jsx2(
|
|
121
|
+
CommandPrimitive.Empty,
|
|
122
|
+
{
|
|
123
|
+
ref,
|
|
124
|
+
className: "py-12 text-center text-sm",
|
|
125
|
+
...props
|
|
126
|
+
}
|
|
127
|
+
));
|
|
128
|
+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
|
129
|
+
var CommandGroup = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
|
|
130
|
+
CommandPrimitive.Group,
|
|
131
|
+
{
|
|
132
|
+
ref,
|
|
133
|
+
className: cn(
|
|
134
|
+
"overflow-hidden [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
|
|
135
|
+
className
|
|
136
|
+
),
|
|
137
|
+
...props
|
|
138
|
+
}
|
|
139
|
+
));
|
|
140
|
+
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
|
141
|
+
var CommandSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
|
|
142
|
+
CommandPrimitive.Separator,
|
|
143
|
+
{
|
|
144
|
+
ref,
|
|
145
|
+
className: cn("h-px bg-border", className),
|
|
146
|
+
...props
|
|
147
|
+
}
|
|
148
|
+
));
|
|
149
|
+
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
|
150
|
+
var CommandItem = React2.forwardRef(({ className, icon, nested = false, children, ...props }, ref) => /* @__PURE__ */ jsx2(
|
|
151
|
+
CommandPrimitive.Item,
|
|
152
|
+
{
|
|
153
|
+
ref,
|
|
154
|
+
className: cn(
|
|
155
|
+
"select-none rounded-lg px-2 text-sm aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
156
|
+
className
|
|
157
|
+
),
|
|
158
|
+
...props,
|
|
159
|
+
children: /* @__PURE__ */ jsxs2(
|
|
160
|
+
"div",
|
|
161
|
+
{
|
|
162
|
+
className: cn(
|
|
163
|
+
"flex min-h-10 items-center gap-3",
|
|
164
|
+
nested && "ml-2 gap-2 border-l pl-4"
|
|
165
|
+
),
|
|
166
|
+
children: [
|
|
167
|
+
/* @__PURE__ */ jsx2("div", { className: "text-muted-foreground [&_svg]:size-4", children: icon }),
|
|
168
|
+
/* @__PURE__ */ jsx2("p", { className: "w-0 flex-1 truncate", children })
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
));
|
|
174
|
+
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
|
175
|
+
|
|
176
|
+
// src/components/dialog/search.tsx
|
|
177
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
178
|
+
function SearchDialog(props) {
|
|
179
|
+
return /* @__PURE__ */ jsx3(Dialog, { ...props, children: props.children });
|
|
180
|
+
}
|
|
181
|
+
function SearchDialogContent({
|
|
182
|
+
footer,
|
|
183
|
+
...props
|
|
184
|
+
}) {
|
|
185
|
+
return /* @__PURE__ */ jsxs3(DialogContent, { className: "p-0", children: [
|
|
186
|
+
/* @__PURE__ */ jsx3(Search2, { ...props }),
|
|
187
|
+
footer ? /* @__PURE__ */ jsx3(DialogFooter, { className: "border-t", children: footer }) : null
|
|
188
|
+
] });
|
|
189
|
+
}
|
|
190
|
+
function Search2({ search, onSearchChange, results }) {
|
|
191
|
+
const { text } = useI18n();
|
|
192
|
+
const router = useRouter();
|
|
193
|
+
const { links, setOpenSearch } = useSearchContext();
|
|
194
|
+
const defaultItems = useMemo(() => {
|
|
195
|
+
return links.map(([name, link]) => ({
|
|
196
|
+
type: "page",
|
|
197
|
+
id: name,
|
|
198
|
+
content: name,
|
|
199
|
+
url: link
|
|
200
|
+
}));
|
|
201
|
+
}, [links]);
|
|
202
|
+
const items = results === "empty" ? defaultItems : results;
|
|
203
|
+
const hideList = results === "empty" && defaultItems.length === 0;
|
|
204
|
+
const onOpen = (url) => {
|
|
205
|
+
router.push(url);
|
|
206
|
+
setOpenSearch(false);
|
|
207
|
+
};
|
|
208
|
+
return /* @__PURE__ */ jsxs3(Command, { children: [
|
|
209
|
+
/* @__PURE__ */ jsx3(
|
|
210
|
+
CommandInput,
|
|
211
|
+
{
|
|
212
|
+
value: search,
|
|
213
|
+
onValueChange: onSearchChange,
|
|
214
|
+
placeholder: text.search
|
|
215
|
+
}
|
|
216
|
+
),
|
|
217
|
+
/* @__PURE__ */ jsxs3(CommandList, { className: cn(hideList && "hidden"), children: [
|
|
218
|
+
/* @__PURE__ */ jsx3(CommandEmpty, { children: text.searchNoResult }),
|
|
219
|
+
/* @__PURE__ */ jsx3(CommandGroup, { value: "result", children: items.map((item) => /* @__PURE__ */ jsx3(
|
|
220
|
+
CommandItem,
|
|
221
|
+
{
|
|
222
|
+
value: item.id,
|
|
223
|
+
onSelect: () => {
|
|
224
|
+
onOpen(item.url);
|
|
225
|
+
},
|
|
226
|
+
icon: {
|
|
227
|
+
text: /* @__PURE__ */ jsx3(TextIcon, {}),
|
|
228
|
+
heading: /* @__PURE__ */ jsx3(HashIcon, {}),
|
|
229
|
+
page: /* @__PURE__ */ jsx3(FileTextIcon, {})
|
|
230
|
+
}[item.type],
|
|
231
|
+
nested: item.type !== "page",
|
|
232
|
+
children: item.content
|
|
233
|
+
},
|
|
234
|
+
item.id
|
|
235
|
+
)) })
|
|
236
|
+
] })
|
|
237
|
+
] });
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export {
|
|
241
|
+
SearchDialog,
|
|
242
|
+
SearchDialogContent
|
|
243
|
+
};
|