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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/dist/chunk-24NYFO7H.js +31 -0
  4. package/dist/chunk-2ZR5Z6B2.js +105 -0
  5. package/dist/chunk-36MVEJ25.js +39 -0
  6. package/dist/chunk-5EZE3X7G.js +31 -0
  7. package/dist/chunk-5KW7ATCP.js +23 -0
  8. package/dist/chunk-6C3VEZWH.js +9 -0
  9. package/dist/chunk-CBOHU2VN.js +28 -0
  10. package/dist/chunk-EDUYFB4P.js +43 -0
  11. package/dist/chunk-F62NYOL5.js +44 -0
  12. package/dist/chunk-GZQICERS.js +31 -0
  13. package/dist/chunk-IXYX64FW.js +243 -0
  14. package/dist/chunk-KCGRUOMD.js +13 -0
  15. package/dist/chunk-OG3QOLYP.js +43 -0
  16. package/dist/chunk-PLXR6QNH.js +21 -0
  17. package/dist/chunk-UIZNMCLD.js +49 -0
  18. package/dist/chunk-YAHHY62W.js +20 -0
  19. package/dist/components/accordion.d.mts +11 -0
  20. package/dist/components/accordion.js +128 -0
  21. package/dist/components/api.d.mts +20 -0
  22. package/dist/components/api.js +136 -0
  23. package/dist/components/callout.d.mts +13 -0
  24. package/dist/components/callout.js +39 -0
  25. package/dist/components/card.d.mts +12 -0
  26. package/dist/components/card.js +10 -0
  27. package/dist/components/codeblock.d.mts +12 -0
  28. package/dist/components/codeblock.js +14 -0
  29. package/dist/components/dialog/search-algolia.d.mts +15 -0
  30. package/dist/components/dialog/search-algolia.js +39 -0
  31. package/dist/components/dialog/search-default.d.mts +15 -0
  32. package/dist/components/dialog/search-default.js +39 -0
  33. package/dist/components/dialog/search.d.mts +25 -0
  34. package/dist/components/dialog/search.js +13 -0
  35. package/dist/components/files.d.mts +20 -0
  36. package/dist/components/files.js +56 -0
  37. package/dist/components/heading.d.mts +9 -0
  38. package/dist/components/heading.js +8 -0
  39. package/dist/components/image-zoom.d.mts +12 -0
  40. package/dist/components/image-zoom.js +39 -0
  41. package/dist/components/inline-toc.d.mts +11 -0
  42. package/dist/components/inline-toc.js +53 -0
  43. package/dist/components/roll-button.d.mts +14 -0
  44. package/dist/components/roll-button.js +54 -0
  45. package/dist/components/steps.d.mts +10 -0
  46. package/dist/components/steps.js +14 -0
  47. package/dist/components/tabs.d.mts +37 -0
  48. package/dist/components/tabs.js +141 -0
  49. package/dist/components/type-table.d.mts +23 -0
  50. package/dist/components/type-table.js +52 -0
  51. package/dist/i18n-dw7ODAws.d.mts +22 -0
  52. package/dist/i18n.d.mts +21 -0
  53. package/dist/i18n.js +146 -0
  54. package/dist/layout-YB7EFpgW.d.mts +79 -0
  55. package/dist/layout.client.d.mts +4 -0
  56. package/dist/layout.client.js +458 -0
  57. package/dist/layout.d.mts +3 -0
  58. package/dist/layout.js +97 -0
  59. package/dist/mdx.client.d.mts +7 -0
  60. package/dist/mdx.client.js +23 -0
  61. package/dist/mdx.d.mts +36 -0
  62. package/dist/mdx.js +51 -0
  63. package/dist/page.client.d.mts +29 -0
  64. package/dist/page.client.js +168 -0
  65. package/dist/page.d.mts +49 -0
  66. package/dist/page.js +56 -0
  67. package/dist/provider.d.mts +50 -0
  68. package/dist/provider.js +51 -0
  69. package/dist/style.css +1 -0
  70. package/dist/tailwind-plugin.d.ts +36 -0
  71. package/dist/tailwind-plugin.js +481 -0
  72. package/dist/tree-Zwtp9xPv.d.mts +15 -0
  73. 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,5 @@
1
+ # Fumadocs UI
2
+
3
+ The Next.js framework for building documentation website.
4
+
5
+ [Read Documentation](https://fumadocs.vercel.app/docs/ui)
@@ -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,9 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ export {
8
+ __export
9
+ };
@@ -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
+ };
@@ -0,0 +1,13 @@
1
+ // src/utils/cn.ts
2
+ import { extendTailwindMerge } from "tailwind-merge";
3
+ var cn = extendTailwindMerge({
4
+ extend: {
5
+ classGroups: {
6
+ "font-size": [{ text: ["medium"] }]
7
+ }
8
+ }
9
+ });
10
+
11
+ export {
12
+ cn
13
+ };