@c-rex/components 0.1.22 → 0.1.23
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/package.json +78 -62
- package/src/article/article-action-bar.tsx +89 -0
- package/src/article/article-content.tsx +55 -0
- package/src/autocomplete.tsx +55 -50
- package/src/breadcrumb.tsx +3 -1
- package/src/directoryNodes/tree-of-content.tsx +49 -0
- package/src/{bookmark-button.tsx → favorites/bookmark-button.tsx} +12 -3
- package/src/{favorite-button.tsx → favorites/favorite-button.tsx} +1 -1
- package/src/generated/client-components.tsx +1350 -0
- package/src/generated/create-client-request.tsx +105 -0
- package/src/generated/create-server-request.tsx +61 -0
- package/src/generated/create-suggestions-request.tsx +56 -0
- package/src/generated/server-components.tsx +1056 -0
- package/src/generated/suggestions.tsx +299 -0
- package/src/info/bookmark.tsx +51 -0
- package/src/info/info-table.tsx +127 -60
- package/src/info/shared.tsx +1 -1
- package/src/navbar/language-switcher/shared.tsx +1 -1
- package/src/navbar/navbar.tsx +1 -1
- package/src/{stories → navbar/stories}/navbar.stories.tsx +1 -1
- package/src/page-wrapper.tsx +1 -1
- package/src/renditions/file-download.tsx +84 -0
- package/src/renditions/html.tsx +55 -0
- package/src/renditions/image/container.tsx +52 -0
- package/src/renditions/image/rendition.tsx +61 -0
- package/src/{dialog-filter.tsx → results/dialog-filter.tsx} +22 -23
- package/src/results/filter-navbar.tsx +241 -0
- package/src/results/filter-sidebar/index.tsx +125 -0
- package/src/results/filter-sidebar/utils.ts +164 -0
- package/src/{pagination.tsx → results/pagination.tsx} +12 -10
- package/src/results/result-container.tsx +70 -0
- package/src/{stories/blog-view.stories.tsx → results/stories/cards.stories.tsx} +1 -1
- package/src/{stories/table-view.stories.tsx → results/stories/table.stories.tsx} +1 -1
- package/src/results/table-with-images.tsx +140 -0
- package/src/{result-view → results}/table.tsx +1 -2
- package/src/results/utils.ts +67 -0
- package/src/{navbar/search-input.tsx → search-input.tsx} +9 -6
- package/src/share-button.tsx +49 -0
- package/src/stores/search-settings-store.ts +1 -1
- package/src/blur-image.tsx +0 -23
- package/src/left-sidebar.tsx +0 -90
- package/src/result-list.tsx +0 -43
- package/src/result-view/table-with-images.tsx +0 -199
- package/src/right-sidebar.tsx +0 -70
- package/src/search-modal.tsx +0 -140
- package/src/stories/blur-image.stories.tsx +0 -51
- package/src/stories/sidebar.stories.tsx +0 -94
- /package/src/{file-icon.tsx → icons/file-icon.tsx} +0 -0
- /package/src/{flag.tsx → icons/flag-icon.tsx} +0 -0
- /package/src/{loading.tsx → icons/loading.tsx} +0 -0
- /package/src/{result-view/blog.tsx → results/cards.tsx} +0 -0
- /package/src/{empty.tsx → results/empty.tsx} +0 -0
- /package/src/{stories → results/stories}/empty.stories.tsx +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c-rex/components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"files": [
|
|
5
5
|
"src"
|
|
6
6
|
],
|
|
@@ -9,33 +9,45 @@
|
|
|
9
9
|
},
|
|
10
10
|
"sideEffects": false,
|
|
11
11
|
"exports": {
|
|
12
|
-
"./
|
|
13
|
-
"types": "./src/
|
|
14
|
-
"import": "./src/
|
|
12
|
+
"./server-components": {
|
|
13
|
+
"types": "./src/generated/server-components.tsx",
|
|
14
|
+
"import": "./src/generated/server-components.tsx"
|
|
15
15
|
},
|
|
16
|
-
"./
|
|
17
|
-
"types": "./src/
|
|
18
|
-
"import": "./src/
|
|
16
|
+
"./client-components": {
|
|
17
|
+
"types": "./src/generated/client-components.tsx",
|
|
18
|
+
"import": "./src/generated/client-components.tsx"
|
|
19
19
|
},
|
|
20
|
-
"./
|
|
21
|
-
"types": "./src/
|
|
22
|
-
"import": "./src/
|
|
20
|
+
"./suggestion-components": {
|
|
21
|
+
"types": "./src/generated/suggestions.tsx",
|
|
22
|
+
"import": "./src/generated/suggestions.tsx"
|
|
23
23
|
},
|
|
24
24
|
"./breadcrumb": {
|
|
25
25
|
"types": "./src/breadcrumb.tsx",
|
|
26
26
|
"import": "./src/breadcrumb.tsx"
|
|
27
27
|
},
|
|
28
|
+
"./navbar": {
|
|
29
|
+
"types": "./src/navbar/navbar.tsx",
|
|
30
|
+
"import": "./src/navbar/navbar.tsx"
|
|
31
|
+
},
|
|
32
|
+
"./page-wrapper": {
|
|
33
|
+
"types": "./src/page-wrapper.tsx",
|
|
34
|
+
"import": "./src/page-wrapper.tsx"
|
|
35
|
+
},
|
|
28
36
|
"./settings-menu": {
|
|
29
37
|
"types": "./src/navbar/settings.tsx",
|
|
30
38
|
"import": "./src/navbar/settings.tsx"
|
|
31
39
|
},
|
|
40
|
+
"./favorite-button": {
|
|
41
|
+
"types": "./src/favorites/favorite-button.tsx",
|
|
42
|
+
"import": "./src/favorites/favorite-button.tsx"
|
|
43
|
+
},
|
|
32
44
|
"./flag": {
|
|
33
45
|
"types": "./src/flag.tsx",
|
|
34
46
|
"import": "./src/flag.tsx"
|
|
35
47
|
},
|
|
36
|
-
"./
|
|
37
|
-
"types": "./src/
|
|
38
|
-
"import": "./src/
|
|
48
|
+
"./loading": {
|
|
49
|
+
"types": "./src/loading.tsx",
|
|
50
|
+
"import": "./src/loading.tsx"
|
|
39
51
|
},
|
|
40
52
|
"./info-table": {
|
|
41
53
|
"types": "./src/info/info-table.tsx",
|
|
@@ -45,69 +57,61 @@
|
|
|
45
57
|
"types": "./src/info/info-card.tsx",
|
|
46
58
|
"import": "./src/info/info-card.tsx"
|
|
47
59
|
},
|
|
48
|
-
"./
|
|
49
|
-
"types": "./src/
|
|
50
|
-
"import": "./src/
|
|
51
|
-
},
|
|
52
|
-
"./navbar": {
|
|
53
|
-
"types": "./src/navbar/navbar.tsx",
|
|
54
|
-
"import": "./src/navbar/navbar.tsx"
|
|
60
|
+
"./check-article-lang": {
|
|
61
|
+
"types": "./src/check-article-lang.tsx",
|
|
62
|
+
"import": "./src/check-article-lang.tsx"
|
|
55
63
|
},
|
|
56
|
-
"./
|
|
57
|
-
"types": "./src/
|
|
58
|
-
"import": "./src/
|
|
64
|
+
"./render-article": {
|
|
65
|
+
"types": "./src/render-article.tsx",
|
|
66
|
+
"import": "./src/render-article.tsx"
|
|
59
67
|
},
|
|
60
|
-
"./
|
|
61
|
-
"types": "./src/
|
|
62
|
-
"import": "./src/
|
|
68
|
+
"./html-rendition": {
|
|
69
|
+
"types": "./src/renditions/html.tsx",
|
|
70
|
+
"import": "./src/renditions/html.tsx"
|
|
63
71
|
},
|
|
64
|
-
"./
|
|
65
|
-
"types": "./src/
|
|
66
|
-
"import": "./src/
|
|
72
|
+
"./image-rendition-container": {
|
|
73
|
+
"types": "./src/renditions/container.ts",
|
|
74
|
+
"import": "./src/renditions/container.ts"
|
|
67
75
|
},
|
|
68
|
-
"./
|
|
69
|
-
"types": "./src/
|
|
70
|
-
"import": "./src/
|
|
76
|
+
"./autocomplete": {
|
|
77
|
+
"types": "./src/autocomplete.tsx",
|
|
78
|
+
"import": "./src/autocomplete.tsx"
|
|
71
79
|
},
|
|
72
|
-
"./
|
|
73
|
-
"types": "./src/result-
|
|
74
|
-
"import": "./src/result-
|
|
80
|
+
"./result-container": {
|
|
81
|
+
"types": "./src/result-container.tsx",
|
|
82
|
+
"import": "./src/result-container.tsx"
|
|
75
83
|
},
|
|
76
|
-
"./
|
|
77
|
-
"types": "./src/
|
|
78
|
-
"import": "./src/
|
|
84
|
+
"./table": {
|
|
85
|
+
"types": "./src/results/table.tsx",
|
|
86
|
+
"import": "./src/results/table.tsx"
|
|
79
87
|
},
|
|
80
|
-
"./
|
|
81
|
-
"types": "./src/
|
|
82
|
-
"import": "./src/
|
|
88
|
+
"./table-with-images": {
|
|
89
|
+
"types": "./src/results/table-with-images.tsx",
|
|
90
|
+
"import": "./src/results/table-with-images.tsx"
|
|
83
91
|
},
|
|
84
92
|
"./dialog-filter": {
|
|
85
|
-
"types": "./src/dialog-filter.tsx",
|
|
86
|
-
"import": "./src/dialog-filter.tsx"
|
|
93
|
+
"types": "./src/results/dialog-filter.tsx",
|
|
94
|
+
"import": "./src/results/dialog-filter.tsx"
|
|
87
95
|
},
|
|
88
|
-
"./
|
|
89
|
-
"types": "./src/
|
|
90
|
-
"import": "./src/
|
|
91
|
-
},
|
|
92
|
-
"./render-article": {
|
|
93
|
-
"types": "./src/render-article.tsx",
|
|
94
|
-
"import": "./src/render-article.tsx"
|
|
96
|
+
"./pagination": {
|
|
97
|
+
"types": "./src/results/pagination.tsx",
|
|
98
|
+
"import": "./src/results/pagination.tsx"
|
|
95
99
|
},
|
|
96
|
-
"./
|
|
97
|
-
"types": "./src/
|
|
98
|
-
"import": "./src/
|
|
100
|
+
"./cards": {
|
|
101
|
+
"types": "./src/results/cards.tsx",
|
|
102
|
+
"import": "./src/results/cards.tsx"
|
|
99
103
|
},
|
|
100
|
-
"./
|
|
101
|
-
"types": "./src/
|
|
102
|
-
"import": "./src/
|
|
104
|
+
"./empty": {
|
|
105
|
+
"types": "./src/results/empty.tsx",
|
|
106
|
+
"import": "./src/results/empty.tsx"
|
|
103
107
|
},
|
|
104
|
-
"./
|
|
105
|
-
"types": "./src/
|
|
106
|
-
"import": "./src/
|
|
108
|
+
"./filter-sidebar": {
|
|
109
|
+
"types": "./src/results/filter-sidebar/index.tsx",
|
|
110
|
+
"import": "./src/results/filter-sidebar/index.tsx"
|
|
107
111
|
},
|
|
108
|
-
"./
|
|
109
|
-
"types": "./src/
|
|
110
|
-
"import": "./src/
|
|
112
|
+
"./filter-navbar": {
|
|
113
|
+
"types": "./src/results/filter-navbar.tsx",
|
|
114
|
+
"import": "./src/results/filter-navbar.tsx"
|
|
111
115
|
},
|
|
112
116
|
"./language-store": {
|
|
113
117
|
"types": "./src/stores/language-store.ts",
|
|
@@ -120,6 +124,18 @@
|
|
|
120
124
|
"./favorites-store": {
|
|
121
125
|
"types": "./src/stores/favorites-store.ts",
|
|
122
126
|
"import": "./src/stores/favorites-store.ts"
|
|
127
|
+
},
|
|
128
|
+
"./article-content": {
|
|
129
|
+
"types": "./src/article/article-content.tsx",
|
|
130
|
+
"import": "./src/article/article-content.tsx"
|
|
131
|
+
},
|
|
132
|
+
"./tree-of-content": {
|
|
133
|
+
"types": "./src/directoryNodes/tree-of-content.tsx",
|
|
134
|
+
"import": "./src/directoryNodes/tree-of-content.tsx"
|
|
135
|
+
},
|
|
136
|
+
"./share-button": {
|
|
137
|
+
"types": "./src/share-button.tsx",
|
|
138
|
+
"import": "./src/share-button.tsx"
|
|
123
139
|
}
|
|
124
140
|
},
|
|
125
141
|
"scripts": {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { FC, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { useHighlightStore } from "../stores/highlight-store";
|
|
4
|
+
import { Button } from "@c-rex/ui/button";
|
|
5
|
+
import { ArrowBigLeft, ArrowBigRight, FileSearchIcon, PanelRight, Search, X } from "lucide-react";
|
|
6
|
+
import { useQueryState } from "nuqs";
|
|
7
|
+
import { useHighlight } from "@c-rex/contexts/highlight-provider";
|
|
8
|
+
import { useMultiSidebar } from "@c-rex/ui/sidebar";
|
|
9
|
+
import { cn } from "@c-rex/utils";
|
|
10
|
+
import { useTranslations } from "next-intl";
|
|
11
|
+
|
|
12
|
+
export const ArticleActionBar: FC = () => {
|
|
13
|
+
const t = useTranslations();
|
|
14
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
15
|
+
const { next, prev } = useHighlight();
|
|
16
|
+
const [open, setOpen] = useState(false);
|
|
17
|
+
const enableHighlight = useHighlightStore((state) => state.enable);
|
|
18
|
+
const toggleHighlight = useHighlightStore((state) => state.toggleHighlight);
|
|
19
|
+
const { rightSidebar } = useMultiSidebar()
|
|
20
|
+
const [query, setQuery] = useQueryState("q");
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (open && inputRef.current) {
|
|
24
|
+
inputRef.current.focus();
|
|
25
|
+
}
|
|
26
|
+
}, [open]);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<div className="w-full sm:w-auto justify-between bg-primary text-primary-foreground rounded-full shadow-lg flex sticky bottom-4 p-2 float-right gap-2 transition-all duration-300">
|
|
31
|
+
{enableHighlight && (
|
|
32
|
+
|
|
33
|
+
<>
|
|
34
|
+
<div className="flex items-center">
|
|
35
|
+
<input
|
|
36
|
+
type="text"
|
|
37
|
+
value={query as string || ""}
|
|
38
|
+
ref={inputRef}
|
|
39
|
+
onKeyDown={(e) => {
|
|
40
|
+
if (e.key === "Enter") {
|
|
41
|
+
next();
|
|
42
|
+
}
|
|
43
|
+
if (e.key === "Escape") {
|
|
44
|
+
setOpen(false);
|
|
45
|
+
}
|
|
46
|
+
}}
|
|
47
|
+
onChange={(e) => setQuery(e.target.value || null)}
|
|
48
|
+
placeholder={t("search")}
|
|
49
|
+
className={cn(
|
|
50
|
+
"border border-gray-300 left-12 transition-all duration-300 rounded-full h-9 bg-secondary text-secondary-foreground focus:outline-none focus:ring-2 focus:ring-blue-500",
|
|
51
|
+
open ? "w-48 opacity-100 px-2 mr-2" : "w-0 opacity-0 px-0"
|
|
52
|
+
)}
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<Button
|
|
56
|
+
variant="ghost" size="icon" rounded="full" onClick={() => setOpen(!open)}
|
|
57
|
+
>
|
|
58
|
+
{open ? <X className="w-5 h-5" /> : <Search className="w-5 h-5" />}
|
|
59
|
+
</Button>
|
|
60
|
+
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<Button variant="ghost" size="icon" rounded="full" onClick={prev}>
|
|
64
|
+
<ArrowBigLeft />
|
|
65
|
+
</Button>
|
|
66
|
+
<Button variant="ghost" size="icon" rounded="full" onClick={next}>
|
|
67
|
+
|
|
68
|
+
<ArrowBigRight />
|
|
69
|
+
</Button>
|
|
70
|
+
</>
|
|
71
|
+
)}
|
|
72
|
+
|
|
73
|
+
<Button variant="ghost" size="icon" rounded="full" onClick={() => toggleHighlight(!enableHighlight)} className="group">
|
|
74
|
+
{enableHighlight ?
|
|
75
|
+
<FileSearchIcon /> :
|
|
76
|
+
<div className="relative inline-block">
|
|
77
|
+
<FileSearchIcon />
|
|
78
|
+
<span className="absolute inset-0 w-[2px] bg-primary-foreground rotate-45 translate-x-2 group-hover:bg-accent-foreground" />
|
|
79
|
+
</div>
|
|
80
|
+
}
|
|
81
|
+
</Button>
|
|
82
|
+
|
|
83
|
+
<Button variant="ghost" size="icon" rounded="full" onClick={rightSidebar.toggleSidebar}>
|
|
84
|
+
<PanelRight />
|
|
85
|
+
</Button>
|
|
86
|
+
</div>
|
|
87
|
+
</>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { RenditionModel } from "@c-rex/interfaces";
|
|
3
|
+
import { RenderArticle } from "../render-article";
|
|
4
|
+
import { ArticleActionBar } from "./article-action-bar";
|
|
5
|
+
import * as cheerio from "cheerio"
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
renditions: RenditionModel[] | null | undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const ArticleContent: FC<Props> = async ({ renditions }) => {
|
|
12
|
+
const empty = (
|
|
13
|
+
<div>No HTML Rendition Available</div>
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if (renditions == null || renditions.length == 0) return empty;
|
|
17
|
+
|
|
18
|
+
const filteredRenditions = renditions.filter((item) => item.format == "application/xhtml+xml");
|
|
19
|
+
|
|
20
|
+
if (filteredRenditions.length == 0 || filteredRenditions[0] == undefined || filteredRenditions[0].links == undefined) return empty;
|
|
21
|
+
|
|
22
|
+
const filteredLinks = filteredRenditions[0].links.filter((item) => item.rel == "view");
|
|
23
|
+
|
|
24
|
+
if (filteredLinks.length == 0 || filteredLinks[0] == undefined || filteredLinks[0].href == undefined) return empty;
|
|
25
|
+
|
|
26
|
+
const url = filteredLinks[0].href;
|
|
27
|
+
const html = await fetch(url, {
|
|
28
|
+
method: "GET",
|
|
29
|
+
headers: {
|
|
30
|
+
Accept: "application/xhtml+xml",
|
|
31
|
+
},
|
|
32
|
+
}).then(res => res.text());
|
|
33
|
+
|
|
34
|
+
const $ = cheerio.load(html)
|
|
35
|
+
|
|
36
|
+
const metaTags = $("meta").map((_, el) => {
|
|
37
|
+
const name = $(el).attr("name")
|
|
38
|
+
const content = $(el).attr("content")
|
|
39
|
+
return name && content ? { name, content } : null
|
|
40
|
+
}).get().filter(Boolean)
|
|
41
|
+
|
|
42
|
+
const articleHtml = $("main").html() || ""
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<>
|
|
46
|
+
{metaTags.map((tag, index) => (
|
|
47
|
+
<meta key={index} name={tag.name} content={tag.content} />
|
|
48
|
+
))}
|
|
49
|
+
<div className="pr-4 relative">
|
|
50
|
+
<RenderArticle htmlContent={articleHtml} contentLang="" />
|
|
51
|
+
</div>
|
|
52
|
+
<ArticleActionBar />
|
|
53
|
+
</>
|
|
54
|
+
)
|
|
55
|
+
}
|
package/src/autocomplete.tsx
CHANGED
|
@@ -1,55 +1,68 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { Input } from "@c-rex/ui/input";
|
|
5
|
-
import { call, generateQueryParams } from "@c-rex/utils";
|
|
6
5
|
import { useTranslations } from "next-intl";
|
|
7
|
-
import {
|
|
8
|
-
|
|
6
|
+
import { SuggestionQueryParams } from "@c-rex/interfaces";
|
|
7
|
+
|
|
9
8
|
import { useSearchSettingsStore } from "./stores/search-settings-store";
|
|
10
9
|
import { useLanguageStore } from "./stores/language-store";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
import { useRouter } from 'next/navigation';
|
|
11
|
+
import { suggestionRequest } from "./generated/create-suggestions-request";
|
|
12
|
+
|
|
13
|
+
export type AutoCompleteProps = {
|
|
14
|
+
initialValue?: string;
|
|
15
|
+
embedded?: boolean;
|
|
16
|
+
endpoint: string;
|
|
17
|
+
queryParams?: SuggestionQueryParams
|
|
18
|
+
onSelectParams?: { key: string, value: string }[];
|
|
16
19
|
};
|
|
17
20
|
|
|
18
|
-
export const AutoComplete = ({
|
|
21
|
+
export const AutoComplete = ({
|
|
22
|
+
initialValue = "",
|
|
23
|
+
embedded = true,
|
|
24
|
+
endpoint,
|
|
25
|
+
queryParams,
|
|
26
|
+
onSelectParams,
|
|
27
|
+
}: AutoCompleteProps) => {
|
|
19
28
|
const t = useTranslations();
|
|
20
29
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
const { articleLang, packageID } = useAppConfig()
|
|
24
|
-
|
|
30
|
+
const router = useRouter();
|
|
25
31
|
const [open, setOpen] = useState(false);
|
|
26
32
|
const [query, setQuery] = useState(initialValue);
|
|
27
33
|
const [loading, setLoading] = useState(false);
|
|
28
34
|
const [suggestions, setSuggestions] = useState<string[]>([]);
|
|
29
35
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const onSelect = (value: string) => {
|
|
35
|
-
const params: QueryParams[] = [
|
|
36
|
-
{ key: "search", value: value },
|
|
37
|
-
{ key: "page", value: "1" },
|
|
38
|
-
{ key: "operator", value: useSearchSettingsStore.getState().operator },
|
|
36
|
+
const fetchSuggestions = useCallback(async (prefix: string): Promise<string[]> => {
|
|
37
|
+
const results = await suggestionRequest({ endpoint, prefix, queryParams });
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
return results.data;
|
|
40
|
+
}, [endpoint, queryParams]);
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
params.push({ key: "packages", value: packageID })
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const aux = generateQueryParams(params)
|
|
42
|
+
const handleSelect = (value: string) => {
|
|
43
|
+
setQuery(value);
|
|
44
|
+
setOpen(false);
|
|
45
|
+
onSelect(value);
|
|
46
|
+
};
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
const onSelect = (value: string) => {
|
|
49
|
+
const params = new URLSearchParams();
|
|
50
|
+
const searchSettings = useSearchSettingsStore.getState();
|
|
51
|
+
const languageSettings = useLanguageStore.getState();
|
|
52
|
+
|
|
53
|
+
params.set('search', value);
|
|
54
|
+
params.set("page", "1")
|
|
55
|
+
params.set("operator", searchSettings.operator)
|
|
56
|
+
params.set("language",
|
|
57
|
+
searchSettings.language.length > 0 ? searchSettings.language.join(",") : languageSettings.contentLang)
|
|
58
|
+
params.set("wildcard", searchSettings.wildcard)
|
|
59
|
+
params.set("like", searchSettings.like.toString())
|
|
60
|
+
|
|
61
|
+
onSelectParams?.forEach(param => {
|
|
62
|
+
params.set(param.key, param.value);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
router.push(`/?${params.toString()}`);
|
|
53
66
|
};
|
|
54
67
|
|
|
55
68
|
useEffect(() => {
|
|
@@ -73,18 +86,15 @@ export const AutoComplete = ({ initialValue, embedded, searchByPackage }: Props)
|
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
const debounceFetch = setTimeout(() => {
|
|
76
|
-
setLoading(true)
|
|
77
|
-
|
|
78
|
-
setSuggestions
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
setLoading(false)
|
|
82
|
-
setSuggestions([])
|
|
83
|
-
});
|
|
89
|
+
setLoading(true);
|
|
90
|
+
fetchSuggestions(query)
|
|
91
|
+
.then(setSuggestions)
|
|
92
|
+
.catch(() => setSuggestions([]))
|
|
93
|
+
.finally(() => setLoading(false));
|
|
84
94
|
}, 300);
|
|
85
95
|
|
|
86
96
|
return () => clearTimeout(debounceFetch);
|
|
87
|
-
}, [query]);
|
|
97
|
+
}, [query, fetchSuggestions]);
|
|
88
98
|
|
|
89
99
|
return (
|
|
90
100
|
<div className="relative flex-1" ref={containerRef}>
|
|
@@ -100,8 +110,7 @@ export const AutoComplete = ({ initialValue, embedded, searchByPackage }: Props)
|
|
|
100
110
|
onKeyDown={(e) => {
|
|
101
111
|
if (e.key === "Enter") {
|
|
102
112
|
e.preventDefault();
|
|
103
|
-
|
|
104
|
-
setOpen(false)
|
|
113
|
+
handleSelect(query);
|
|
105
114
|
}
|
|
106
115
|
}}
|
|
107
116
|
/>
|
|
@@ -122,11 +131,7 @@ export const AutoComplete = ({ initialValue, embedded, searchByPackage }: Props)
|
|
|
122
131
|
<li
|
|
123
132
|
key={index}
|
|
124
133
|
className="px-4 py-2 hover:bg-accent cursor-pointer text-sm"
|
|
125
|
-
onClick={() => {
|
|
126
|
-
setQuery(option);
|
|
127
|
-
setOpen(false);
|
|
128
|
-
onSelect(`"${option}"`);
|
|
129
|
-
}}
|
|
134
|
+
onClick={() => handleSelect(`"${option}"`)}
|
|
130
135
|
>
|
|
131
136
|
{option}
|
|
132
137
|
</li>
|
package/src/breadcrumb.tsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import React, { FC, Fragment, ReactNode } from "react";
|
|
2
4
|
import {
|
|
3
5
|
Breadcrumb as BreadcrumbComponent,
|
|
@@ -74,7 +76,7 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ items, loading, lang }) => {
|
|
|
74
76
|
{items.slice(0, -1).map((item, index) => (
|
|
75
77
|
<Link
|
|
76
78
|
key={index}
|
|
77
|
-
href={item.link}
|
|
79
|
+
href={item.link!}
|
|
78
80
|
className="py-1 text-sm"
|
|
79
81
|
>
|
|
80
82
|
{item.label}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SidebarMenu,
|
|
3
|
+
SidebarMenuButton,
|
|
4
|
+
SidebarMenuItem,
|
|
5
|
+
SidebarMenuSub,
|
|
6
|
+
SidebarMenuSubButton,
|
|
7
|
+
SidebarMenuSubItem,
|
|
8
|
+
} from "@c-rex/ui/sidebar";
|
|
9
|
+
import { DirectoryNodeModel } from "@c-rex/interfaces";
|
|
10
|
+
import { generateTreeOfContent } from "@c-rex/utils/directoryNodes";
|
|
11
|
+
|
|
12
|
+
interface SidebarProps {
|
|
13
|
+
directoryNodes: DirectoryNodeModel[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function TreeOfContent({ directoryNodes }: SidebarProps) {
|
|
17
|
+
const tree = await generateTreeOfContent(directoryNodes);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<SidebarMenu>
|
|
21
|
+
{tree.map((item) => (
|
|
22
|
+
<SidebarMenuItem key={item.id}>
|
|
23
|
+
<SidebarMenuButton asChild isActive={item.active}>
|
|
24
|
+
<a href={item.link} title={item.label}>
|
|
25
|
+
{item.label}
|
|
26
|
+
</a>
|
|
27
|
+
</SidebarMenuButton>
|
|
28
|
+
|
|
29
|
+
{item.children?.length ? (
|
|
30
|
+
<SidebarMenuSub>
|
|
31
|
+
{item.children.map((item) => (
|
|
32
|
+
<SidebarMenuSubItem key={item.label}>
|
|
33
|
+
<SidebarMenuSubButton
|
|
34
|
+
asChild
|
|
35
|
+
isActive={item.active}
|
|
36
|
+
>
|
|
37
|
+
<a href={item.link} title={item.label}>
|
|
38
|
+
{item.label}
|
|
39
|
+
</a>
|
|
40
|
+
</SidebarMenuSubButton>
|
|
41
|
+
</SidebarMenuSubItem>
|
|
42
|
+
))}
|
|
43
|
+
</SidebarMenuSub>
|
|
44
|
+
) : null}
|
|
45
|
+
</SidebarMenuItem>
|
|
46
|
+
))}
|
|
47
|
+
</SidebarMenu>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { FC, ReactNode } from "react";
|
|
3
|
+
import { FC, ReactNode, useEffect, useState } from "react";
|
|
4
4
|
import { Button } from "@c-rex/ui/button";
|
|
5
5
|
import { Trash } from "lucide-react";
|
|
6
6
|
import { cn } from "@c-rex/utils";
|
|
7
7
|
import Link from "next/link";
|
|
8
|
-
import {
|
|
8
|
+
import { useFavoritesStore } from "../stores/favorites-store";
|
|
9
9
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@c-rex/ui/dialog";
|
|
10
10
|
import {
|
|
11
11
|
Table,
|
|
@@ -15,7 +15,16 @@ import {
|
|
|
15
15
|
} from "@c-rex/ui/table"
|
|
16
16
|
import { FaRegBookmark } from "react-icons/fa6";
|
|
17
17
|
|
|
18
|
-
export const BookmarkButton: FC<{
|
|
18
|
+
export const BookmarkButton: FC<{ shortId: string, trigger?: ReactNode }> = ({ shortId, trigger }) => {
|
|
19
|
+
const [markersList, setMarkersList] = useState<Array<{ id: string; label: string; color: string }>>([]);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
setMarkersList(useFavoritesStore.getState().documents[shortId]?.topics || []);
|
|
23
|
+
}, [shortId]);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
console.log(shortId, markersList);
|
|
27
|
+
}, [markersList]);
|
|
19
28
|
|
|
20
29
|
return (
|
|
21
30
|
<Dialog>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { FC, useEffect, useState } from "react";
|
|
4
4
|
import { Button } from "@c-rex/ui/button";
|
|
5
5
|
import { FaStar, FaRegStar } from "react-icons/fa";
|
|
6
|
-
import { useFavoritesStore } from "
|
|
6
|
+
import { useFavoritesStore } from "../stores/favorites-store";
|
|
7
7
|
import { MARKER_COLORS, RESULT_TYPES } from "@c-rex/constants";
|
|
8
8
|
import { ResultTypes } from "@c-rex/types";
|
|
9
9
|
|