@c-rex/components 0.1.30 → 0.1.32
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 +13 -1
- package/src/article/article-action-bar.analysis.md +15 -0
- package/src/article/article-action-bar.tsx +31 -9
- package/src/article/article-content.analysis.md +15 -0
- package/src/article/article-content.tsx +3 -3
- package/src/autocomplete.analysis.md +17 -0
- package/src/autocomplete.tsx +7 -4
- package/src/breadcrumb.analysis.md +15 -0
- package/src/breadcrumb.tsx +4 -4
- package/src/carousel/carousel.analysis.md +17 -0
- package/src/carousel/carousel.tsx +18 -10
- package/src/check-article-lang.analysis.md +15 -0
- package/src/directoryNodes/tree-of-content.analysis.md +14 -0
- package/src/documents/result-list.analysis.md +14 -0
- package/src/documents/result-list.tsx +2 -2
- package/src/favorites/bookmark-button.analysis.md +17 -0
- package/src/favorites/favorite-button.analysis.md +18 -0
- package/src/generated/create-client-request.tsx +15 -6
- package/src/icons/file-icon.analysis.md +14 -0
- package/src/icons/flag-icon.analysis.md +14 -0
- package/src/icons/loading.analysis.md +14 -0
- package/src/info/info-table.analysis.md +15 -0
- package/src/info/info-table.tsx +9 -9
- package/src/info/shared.analysis.md +14 -0
- package/src/info/shared.tsx +1 -2
- package/src/navbar/language-switcher/content-language-switch.analysis.md +15 -0
- package/src/navbar/language-switcher/content-language-switch.tsx +9 -3
- package/src/navbar/language-switcher/shared.analysis.md +14 -0
- package/src/navbar/language-switcher/ui-language-switch.analysis.md +15 -0
- package/src/navbar/language-switcher/ui-language-switch.tsx +1 -1
- package/src/navbar/navbar.analysis.md +14 -0
- package/src/navbar/navbar.tsx +83 -50
- package/src/navbar/settings.analysis.md +14 -0
- package/src/navbar/settings.tsx +6 -1
- package/src/navbar/sign-in-out-btns.analysis.md +14 -0
- package/src/navbar/user-menu.analysis.md +14 -0
- package/src/page-wrapper.analysis.md +14 -0
- package/src/page-wrapper.tsx +11 -1
- package/src/render-article.analysis.md +15 -0
- package/src/renditions/file-download.analysis.md +14 -0
- package/src/renditions/html.analysis.md +17 -0
- package/src/renditions/image/container.analysis.md +15 -0
- package/src/renditions/image/rendition.analysis.md +14 -0
- package/src/restriction-menu/restriction-menu-container.analysis.md +14 -0
- package/src/restriction-menu/restriction-menu-container.tsx +53 -0
- package/src/restriction-menu/restriction-menu-item.analysis.md +14 -0
- package/src/restriction-menu/restriction-menu-item.tsx +103 -48
- package/src/restriction-menu/restriction-menu.analysis.md +17 -0
- package/src/restriction-menu/restriction-menu.tsx +128 -130
- package/src/results/cards.analysis.md +14 -0
- package/src/results/dialog-filter.analysis.md +17 -0
- package/src/results/dialog-filter.tsx +32 -26
- package/src/results/empty.analysis.md +14 -0
- package/src/results/filter-navbar.analysis.md +16 -0
- package/src/results/filter-navbar.tsx +25 -2
- package/src/results/filter-sidebar/index.analysis.md +14 -0
- package/src/results/filter-sidebar/index.tsx +1 -0
- package/src/results/generic/table-result-list.analysis.md +15 -0
- package/src/results/generic/table-result-list.tsx +3 -3
- package/src/results/pagination.analysis.md +14 -0
- package/src/results/table-with-images.analysis.md +15 -0
- package/src/results/table-with-images.tsx +2 -2
- package/src/results/table.analysis.md +15 -0
- package/src/results/table.tsx +4 -4
- package/src/results/utils.ts +1 -21
- package/src/search-input.analysis.md +15 -0
- package/src/search-input.tsx +4 -12
- package/src/share-button.analysis.md +19 -0
- package/src/stores/restriction-store.ts +11 -0
- package/src/stores/search-settings-store.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c-rex/components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"files": [
|
|
5
5
|
"src"
|
|
6
6
|
],
|
|
@@ -164,6 +164,18 @@
|
|
|
164
164
|
"./carousel": {
|
|
165
165
|
"types": "./src/carousel/carousel.tsx",
|
|
166
166
|
"import": "./src/carousel/carousel.tsx"
|
|
167
|
+
},
|
|
168
|
+
"./restriction-menu": {
|
|
169
|
+
"types": "./src/restriction-menu/restriction-menu.tsx",
|
|
170
|
+
"import": "./src/restriction-menu/restriction-menu.tsx"
|
|
171
|
+
},
|
|
172
|
+
"./restriction-menu-item": {
|
|
173
|
+
"types": "./src/restriction-menu/restriction-menu-item.tsx",
|
|
174
|
+
"import": "./src/restriction-menu/restriction-menu-item.tsx"
|
|
175
|
+
},
|
|
176
|
+
"./search-input": {
|
|
177
|
+
"types": "./src/search-input.tsx",
|
|
178
|
+
"import": "./src/search-input.tsx"
|
|
167
179
|
}
|
|
168
180
|
},
|
|
169
181
|
"scripts": {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Analysis: article-action-bar
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/article/article-action-bar.tsx
|
|
4
|
+
- Type: Client component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=yes, window/document=no, effects=yes, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- Store subscriptions can re-render this component whenever the selected slice changes.
|
|
9
|
+
- Effects that update state can add extra renders on mount and dependency changes.
|
|
10
|
+
|
|
11
|
+
## Possible bugs/risks
|
|
12
|
+
- No critical bug is evident in this quick static pass; keep tests for error and loading paths.
|
|
13
|
+
|
|
14
|
+
## Recommended improvements
|
|
15
|
+
- Standardize loading/error handling and add regression tests to prevent divergent behavior across consuming apps.
|
|
@@ -27,7 +27,7 @@ export const ArticleActionBar: FC = () => {
|
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
29
|
<>
|
|
30
|
-
<div className="w-
|
|
30
|
+
<div className="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
31
|
{enableHighlight && (
|
|
32
32
|
|
|
33
33
|
<>
|
|
@@ -48,29 +48,45 @@ export const ArticleActionBar: FC = () => {
|
|
|
48
48
|
placeholder={t("search")}
|
|
49
49
|
className={cn(
|
|
50
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 ? "
|
|
51
|
+
open ? "flex flex-1 opacity-100 px-2 mr-2" : "w-0 opacity-0 px-0"
|
|
52
52
|
)}
|
|
53
53
|
/>
|
|
54
54
|
|
|
55
|
-
<Button
|
|
56
|
-
variant="ghost" size="icon" rounded="full" onClick={() => setOpen(!open)}
|
|
57
|
-
>
|
|
55
|
+
<Button variant="ghost" size="icon" rounded="full" onClick={() => setOpen(!open)}>
|
|
58
56
|
{open ? <X className="w-5 h-5" /> : <Search className="w-5 h-5" />}
|
|
59
57
|
</Button>
|
|
60
58
|
|
|
61
59
|
</div>
|
|
62
60
|
|
|
63
|
-
<Button
|
|
61
|
+
<Button
|
|
62
|
+
variant="ghost"
|
|
63
|
+
size="icon"
|
|
64
|
+
rounded="full"
|
|
65
|
+
onClick={prev}
|
|
66
|
+
className={cn(open && "hidden sm:inline-flex")}
|
|
67
|
+
>
|
|
64
68
|
<ArrowBigLeft />
|
|
65
69
|
</Button>
|
|
66
|
-
<Button variant="ghost" size="icon" rounded="full" onClick={next}>
|
|
67
70
|
|
|
71
|
+
<Button
|
|
72
|
+
variant="ghost"
|
|
73
|
+
size="icon"
|
|
74
|
+
rounded="full"
|
|
75
|
+
onClick={next}
|
|
76
|
+
className={cn(open && "hidden sm:inline-flex")}
|
|
77
|
+
>
|
|
68
78
|
<ArrowBigRight />
|
|
69
79
|
</Button>
|
|
70
80
|
</>
|
|
71
81
|
)}
|
|
72
82
|
|
|
73
|
-
<Button
|
|
83
|
+
<Button
|
|
84
|
+
variant="ghost"
|
|
85
|
+
size="icon"
|
|
86
|
+
rounded="full"
|
|
87
|
+
onClick={() => toggleHighlight(!enableHighlight)}
|
|
88
|
+
className={cn("group", open && "hidden sm:inline-flex")}
|
|
89
|
+
>
|
|
74
90
|
{enableHighlight ?
|
|
75
91
|
<FileSearchIcon /> :
|
|
76
92
|
<div className="relative inline-block">
|
|
@@ -80,7 +96,13 @@ export const ArticleActionBar: FC = () => {
|
|
|
80
96
|
}
|
|
81
97
|
</Button>
|
|
82
98
|
|
|
83
|
-
<Button
|
|
99
|
+
<Button
|
|
100
|
+
variant="ghost"
|
|
101
|
+
size="icon"
|
|
102
|
+
rounded="full"
|
|
103
|
+
onClick={rightSidebar.toggleSidebar}
|
|
104
|
+
className={cn(open && "hidden sm:inline-flex")}
|
|
105
|
+
>
|
|
84
106
|
<PanelRight />
|
|
85
107
|
</Button>
|
|
86
108
|
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Analysis: article-content
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/article/article-content.tsx
|
|
4
|
+
- Type: Server component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=yes
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- Async flows can hit race conditions during fast param/route changes.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Consider cancellation guards (isMounted or AbortController) and standardized error handling.
|
|
15
|
+
|
|
@@ -43,8 +43,8 @@ export const ArticleContent: FC<Props> = async ({ renditions }) => {
|
|
|
43
43
|
|
|
44
44
|
return (
|
|
45
45
|
<>
|
|
46
|
-
{metaTags.map((tag
|
|
47
|
-
<meta key={
|
|
46
|
+
{metaTags.map((tag) => (
|
|
47
|
+
<meta key={`${tag.name}-${tag.content}`} name={tag.name} content={tag.content} />
|
|
48
48
|
))}
|
|
49
49
|
<div className="pr-4 relative">
|
|
50
50
|
<RenderArticle htmlContent={articleHtml} contentLang="" />
|
|
@@ -52,4 +52,4 @@ export const ArticleContent: FC<Props> = async ({ renditions }) => {
|
|
|
52
52
|
<ArticleActionBar />
|
|
53
53
|
</>
|
|
54
54
|
)
|
|
55
|
-
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Analysis: autocomplete
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/autocomplete.tsx
|
|
4
|
+
- Type: Client component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=yes, effects=yes, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- Effects that update state can add extra renders on mount and dependency changes.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- Access to window/document needs care to avoid hydration mismatch and non-browser runtime issues.
|
|
12
|
+
- The component renders list-heavy UI; key stability and memoization strongly affect perceived performance.
|
|
13
|
+
|
|
14
|
+
## Recommended improvements
|
|
15
|
+
- Keep browser-only access inside event handlers or useEffect, not in initial render paths.
|
|
16
|
+
- Review key strategy and extract memoized subcomponents for large-list rendering.
|
|
17
|
+
|
package/src/autocomplete.tsx
CHANGED
|
@@ -17,6 +17,7 @@ export type AutoCompleteProps = {
|
|
|
17
17
|
queryParams?: SuggestionQueryParams
|
|
18
18
|
onSelectParams?: { key: string, value: string }[];
|
|
19
19
|
onSelectPath: string
|
|
20
|
+
inputClass?: string
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
export const AutoComplete = ({
|
|
@@ -25,7 +26,8 @@ export const AutoComplete = ({
|
|
|
25
26
|
endpoint,
|
|
26
27
|
queryParams,
|
|
27
28
|
onSelectParams,
|
|
28
|
-
onSelectPath = "/"
|
|
29
|
+
onSelectPath = "/",
|
|
30
|
+
inputClass = "",
|
|
29
31
|
}: AutoCompleteProps) => {
|
|
30
32
|
const t = useTranslations();
|
|
31
33
|
const [pkg] = useQueryState("package");
|
|
@@ -59,7 +61,7 @@ export const AutoComplete = ({
|
|
|
59
61
|
params.set('search', value);
|
|
60
62
|
params.set("page", "1")
|
|
61
63
|
params.set("operator", searchSettings.operator)
|
|
62
|
-
params.set("language", searchSettings.language)
|
|
64
|
+
if (searchSettings.language) params.set("language", searchSettings.language)
|
|
63
65
|
params.set("wildcard", searchSettings.wildcard)
|
|
64
66
|
params.set("like", searchSettings.like.toString())
|
|
65
67
|
|
|
@@ -105,6 +107,7 @@ export const AutoComplete = ({
|
|
|
105
107
|
<div className="relative flex-1" ref={containerRef}>
|
|
106
108
|
<Input
|
|
107
109
|
variant={embedded ? "embedded" : undefined}
|
|
110
|
+
className={inputClass}
|
|
108
111
|
type="text"
|
|
109
112
|
placeholder={t("search")}
|
|
110
113
|
value={query}
|
|
@@ -132,9 +135,9 @@ export const AutoComplete = ({
|
|
|
132
135
|
<>
|
|
133
136
|
{suggestions.length > 0 ? (
|
|
134
137
|
<>
|
|
135
|
-
{suggestions.map((option
|
|
138
|
+
{suggestions.map((option) => (
|
|
136
139
|
<li
|
|
137
|
-
key={
|
|
140
|
+
key={option}
|
|
138
141
|
className="px-4 py-2 hover:bg-accent cursor-pointer text-sm"
|
|
139
142
|
onClick={() => handleSelect(`"${option}"`)}
|
|
140
143
|
>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Analysis: breadcrumb
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/breadcrumb.tsx
|
|
4
|
+
- Type: Client component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- The component renders list-heavy UI; key stability and memoization strongly affect perceived performance.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Review key strategy and extract memoized subcomponents for large-list rendering.
|
|
15
|
+
|
package/src/breadcrumb.tsx
CHANGED
|
@@ -53,9 +53,9 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ tree, lang }) => {
|
|
|
53
53
|
</DrawerHeader>
|
|
54
54
|
|
|
55
55
|
<div className="grid gap-1 px-4">
|
|
56
|
-
{items.slice(0, -1).map((item
|
|
56
|
+
{items.slice(0, -1).map((item) => (
|
|
57
57
|
<Link
|
|
58
|
-
key={
|
|
58
|
+
key={item.linkId}
|
|
59
59
|
href={`/topics/${item.linkId}/content`}
|
|
60
60
|
className="py-1 text-sm"
|
|
61
61
|
>
|
|
@@ -103,7 +103,7 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ tree, lang }) => {
|
|
|
103
103
|
|
|
104
104
|
return (
|
|
105
105
|
<Fragment key={`${item.label}-fragment`}>
|
|
106
|
-
<BreadcrumbItem key={`${item.label}-item`}
|
|
106
|
+
<BreadcrumbItem key={`${item.label}-item`}>
|
|
107
107
|
{renderLink(!isLast, item)}
|
|
108
108
|
</BreadcrumbItem>
|
|
109
109
|
{!isLast && (
|
|
@@ -121,4 +121,4 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ tree, lang }) => {
|
|
|
121
121
|
</BreadcrumbList>
|
|
122
122
|
</BreadcrumbComponent>
|
|
123
123
|
);
|
|
124
|
-
};
|
|
124
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Analysis: carousel
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/carousel/carousel.tsx
|
|
4
|
+
- Type: Client component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=yes, effects=yes, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- Effects that update state can add extra renders on mount and dependency changes.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- Access to window/document needs care to avoid hydration mismatch and non-browser runtime issues.
|
|
12
|
+
- The component renders list-heavy UI; key stability and memoization strongly affect perceived performance.
|
|
13
|
+
|
|
14
|
+
## Recommended improvements
|
|
15
|
+
- Keep browser-only access inside event handlers or useEffect, not in initial render paths.
|
|
16
|
+
- Review key strategy and extract memoized subcomponents for large-list rendering.
|
|
17
|
+
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
createContext,
|
|
10
10
|
useContext,
|
|
11
11
|
} from "react";
|
|
12
|
-
import { cn, getLanguage, getTitle, getType } from "@c-rex/utils";
|
|
12
|
+
import { cn, formatDateToLocale, getLanguage, getTitle, getType } from "@c-rex/utils";
|
|
13
13
|
import { Button } from "@c-rex/ui/button";
|
|
14
14
|
import { ArrowLeft, ArrowRight } from "lucide-react";
|
|
15
15
|
import { Skeleton } from "@c-rex/ui/skeleton";
|
|
@@ -21,6 +21,7 @@ import { Card } from "@c-rex/ui/card";
|
|
|
21
21
|
import { Badge } from "@c-rex/ui/badge";
|
|
22
22
|
import { Flag } from "../icons/flag-icon"
|
|
23
23
|
import { Empty } from "../results/empty";
|
|
24
|
+
import { useLocale, useTranslations } from "next-intl";
|
|
24
25
|
|
|
25
26
|
// Types
|
|
26
27
|
|
|
@@ -66,7 +67,7 @@ type Props = {
|
|
|
66
67
|
responsive?: ResponsiveSetting[];
|
|
67
68
|
indicators?: boolean;
|
|
68
69
|
showImages?: boolean;
|
|
69
|
-
|
|
70
|
+
carouselItemComponent?: FC<{ item: CommonItemsModel; showImages: boolean }>;
|
|
70
71
|
serviceType: keyof typeof ServiceOptions;
|
|
71
72
|
queryParams?: Record<string, any>;
|
|
72
73
|
loadByPages?: boolean;
|
|
@@ -80,13 +81,13 @@ export const Carousel: FC<Props> = ({
|
|
|
80
81
|
indicators = false,
|
|
81
82
|
autoplaySpeed = 3000,
|
|
82
83
|
showImages = false,
|
|
83
|
-
|
|
84
|
+
carouselItemComponent,
|
|
84
85
|
serviceType,
|
|
85
86
|
queryParams = {},
|
|
86
87
|
loadByPages = false,
|
|
87
88
|
}) => {
|
|
88
89
|
const service = ServiceOptions[serviceType] as typeof documentsGetAllClientService;
|
|
89
|
-
const
|
|
90
|
+
const RenderComponent = carouselItemComponent || DefaultRenderCarouselItem;
|
|
90
91
|
|
|
91
92
|
// Responsive
|
|
92
93
|
const [slidesToShow, setSlidesToShow] = useState(responsive[0]?.slidesToShow || 1);
|
|
@@ -239,7 +240,7 @@ export const Carousel: FC<Props> = ({
|
|
|
239
240
|
className={`flex-shrink-0 flex-grow-0 flex justify-center`}
|
|
240
241
|
style={{ width: `${100 / slidesToShow}%` }}
|
|
241
242
|
>
|
|
242
|
-
{
|
|
243
|
+
<RenderComponent item={item} showImages={showImages} />
|
|
243
244
|
</div>
|
|
244
245
|
))
|
|
245
246
|
) : null}
|
|
@@ -282,7 +283,7 @@ const CarouselIndicators: FC<{ className?: string }> = ({ className }) => {
|
|
|
282
283
|
return (
|
|
283
284
|
<ol className={cn("flex gap-2 z-20 list-none p-0 m-0", className)}>
|
|
284
285
|
{Array.from({ length: totalOfIndicators }).map((_, index) => (
|
|
285
|
-
<li key={index}>
|
|
286
|
+
<li key={`indicator-${index}`}>
|
|
286
287
|
<Button
|
|
287
288
|
className={`w-3 h-3 rounded-full border-0 cursor-pointer transition-colors ${index === current ? "bg-gray-800" : "bg-gray-300"}`}
|
|
288
289
|
size="xs"
|
|
@@ -314,14 +315,21 @@ const CarouselIndicators: FC<{ className?: string }> = ({ className }) => {
|
|
|
314
315
|
);
|
|
315
316
|
};
|
|
316
317
|
|
|
317
|
-
const
|
|
318
|
+
const DefaultRenderCarouselItem: FC<{ item: CommonItemsModel; showImages: boolean }> = ({ item, showImages }) => {
|
|
319
|
+
const locale = useLocale();
|
|
320
|
+
const t = useTranslations("itemTypes");
|
|
321
|
+
|
|
322
|
+
const date = formatDateToLocale(item.created!, locale);
|
|
318
323
|
const title = getTitle(item.titles, item.labels);
|
|
319
324
|
const itemType = getType(item.class);
|
|
320
325
|
const language = getLanguage(item.languages)
|
|
321
326
|
const countryCode = language.split("-")[1] || "";
|
|
327
|
+
|
|
322
328
|
return (
|
|
323
329
|
<div className="p-2 flex flex-1">
|
|
324
|
-
<Card className="p-4 flex-1 justify-between">
|
|
330
|
+
<Card className="p-4 flex-1 justify-between relative">
|
|
331
|
+
<Badge className="absolute -top-2 -right-2">{t(itemType.toLowerCase())}</Badge>
|
|
332
|
+
|
|
325
333
|
{showImages && (
|
|
326
334
|
<ImageRenditionContainer
|
|
327
335
|
itemShortId={item.shortId!}
|
|
@@ -333,12 +341,12 @@ const defaultRenderCarouselItem = (item: CommonItemsModel, showImages: boolean)
|
|
|
333
341
|
<span className="text-lg font-semibold">{title}</span>
|
|
334
342
|
|
|
335
343
|
<div className="flex justify-between w-full">
|
|
336
|
-
<Badge>{itemType}</Badge>
|
|
337
344
|
<span className="w-8 block border">
|
|
338
345
|
<Flag countryCode={countryCode} />
|
|
339
346
|
</span>
|
|
347
|
+
<span className="text-gray-400">{date || item.revision}</span>
|
|
340
348
|
</div>
|
|
341
349
|
</Card>
|
|
342
350
|
</div>
|
|
343
351
|
);
|
|
344
|
-
}
|
|
352
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Analysis: check-article-lang
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/check-article-lang.tsx
|
|
4
|
+
- Type: Client component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=yes, effects=yes, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- Effects that update state can add extra renders on mount and dependency changes.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- Access to window/document needs care to avoid hydration mismatch and non-browser runtime issues.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Keep browser-only access inside event handlers or useEffect, not in initial render paths.
|
|
15
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Analysis: tree-of-content
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/directoryNodes/tree-of-content.tsx
|
|
4
|
+
- Type: Server component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- No critical bug is evident in this quick static pass; keep tests for error and loading paths.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Standardize loading/error handling and add regression tests to prevent divergent behavior across consuming apps.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Analysis: result-list
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/documents/result-list.tsx
|
|
4
|
+
- Type: Server component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- No critical bug is evident in this quick static pass; keep tests for error and loading paths.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Standardize loading/error handling and add regression tests to prevent divergent behavior across consuming apps.
|
|
@@ -56,7 +56,7 @@ export const DocumentsResultList: FC<Props> = ({
|
|
|
56
56
|
|
|
57
57
|
return (
|
|
58
58
|
<div
|
|
59
|
-
key={
|
|
59
|
+
key={item.shortId}
|
|
60
60
|
className={cn(
|
|
61
61
|
"min-h-12 flex flex-wrap items-center border px-4 py-2 gap-2 rounded",
|
|
62
62
|
index == items.length - 1 ? "" : "mb-4",
|
|
@@ -124,4 +124,4 @@ export const DocumentsResultList: FC<Props> = ({
|
|
|
124
124
|
})}
|
|
125
125
|
</div>
|
|
126
126
|
);
|
|
127
|
-
};
|
|
127
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Analysis: bookmark-button
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/favorites/bookmark-button.tsx
|
|
4
|
+
- Type: Client component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=yes, effects=yes, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- Effects that update state can add extra renders on mount and dependency changes.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- Access to window/document needs care to avoid hydration mismatch and non-browser runtime issues.
|
|
12
|
+
- markersList is loaded only on mount/shortId change; later store updates may not refresh the badge.
|
|
13
|
+
|
|
14
|
+
## Recommended improvements
|
|
15
|
+
- Keep browser-only access inside event handlers or useEffect, not in initial render paths.
|
|
16
|
+
- Read documents[shortId]?.topics directly through a Zustand selector to keep UI reactive.
|
|
17
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Analysis: favorite-button
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/favorites/favorite-button.tsx
|
|
4
|
+
- Type: Client component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=yes, window/document=no, effects=yes, fetch/call=yes
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- Store subscriptions can re-render this component whenever the selected slice changes.
|
|
9
|
+
- Effects that update state can add extra renders on mount and dependency changes.
|
|
10
|
+
|
|
11
|
+
## Possible bugs/risks
|
|
12
|
+
- Async flows can hit race conditions during fast param/route changes.
|
|
13
|
+
- useEffect with empty deps calls getTopicDocumentData(id) and does not react if id/type changes.
|
|
14
|
+
|
|
15
|
+
## Recommended improvements
|
|
16
|
+
- Consider cancellation guards (isMounted or AbortController) and standardized error handling.
|
|
17
|
+
- Include id and type in effect dependencies and handle fetch cancellation on unmount.
|
|
18
|
+
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
"use client";
|
|
9
9
|
|
|
10
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
10
|
+
import { useState, useEffect, useCallback, useMemo } from 'react';
|
|
11
11
|
import { replacePathParams, call } from "@c-rex/utils"
|
|
12
12
|
|
|
13
13
|
type SerializedError = {
|
|
@@ -40,11 +40,21 @@ export function createClientDataRequest<T, PathParams, QueryParams>(
|
|
|
40
40
|
isLoading: true,
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
+
const pathParamsKey = useMemo(
|
|
44
|
+
() => JSON.stringify(pathParams ?? {}),
|
|
45
|
+
[pathParams]
|
|
46
|
+
);
|
|
47
|
+
const queryParamsKey = useMemo(
|
|
48
|
+
() => JSON.stringify(queryParams ?? {}),
|
|
49
|
+
[queryParams]
|
|
50
|
+
);
|
|
51
|
+
|
|
43
52
|
const fetchData = useCallback(async () => {
|
|
44
|
-
setState({
|
|
45
|
-
...
|
|
53
|
+
setState((prev) => ({
|
|
54
|
+
...prev,
|
|
46
55
|
error: null,
|
|
47
|
-
|
|
56
|
+
isLoading: true,
|
|
57
|
+
}));
|
|
48
58
|
|
|
49
59
|
try {
|
|
50
60
|
const url = replacePathParams(endpointTemplate, pathParams as Record<string, string>);
|
|
@@ -66,8 +76,7 @@ export function createClientDataRequest<T, PathParams, QueryParams>(
|
|
|
66
76
|
isLoading: false,
|
|
67
77
|
});
|
|
68
78
|
}
|
|
69
|
-
|
|
70
|
-
}, [endpointTemplate, pathParams]);
|
|
79
|
+
}, [endpointTemplate, pathParamsKey, queryParamsKey]);
|
|
71
80
|
|
|
72
81
|
|
|
73
82
|
// Initial fetch
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Analysis: file-icon
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/icons/file-icon.tsx
|
|
4
|
+
- Type: Server component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- No critical bug is evident in this quick static pass; keep tests for error and loading paths.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Standardize loading/error handling and add regression tests to prevent divergent behavior across consuming apps.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Analysis: flag-icon
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/icons/flag-icon.tsx
|
|
4
|
+
- Type: Server component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- No critical bug is evident in this quick static pass; keep tests for error and loading paths.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Standardize loading/error handling and add regression tests to prevent divergent behavior across consuming apps.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Analysis: loading
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/icons/loading.tsx
|
|
4
|
+
- Type: Server component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- No critical bug is evident in this quick static pass; keep tests for error and loading paths.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Standardize loading/error handling and add regression tests to prevent divergent behavior across consuming apps.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Analysis: info-table
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/info/info-table.tsx
|
|
4
|
+
- Type: Server component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- The component renders list-heavy UI; key stability and memoization strongly affect perceived performance.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Review key strategy and extract memoized subcomponents for large-list rendering.
|
|
15
|
+
|
package/src/info/info-table.tsx
CHANGED
|
@@ -56,10 +56,10 @@ export const InfoTable: FC<Props> = async ({
|
|
|
56
56
|
<CardContent className="space-y-3 !p-0">
|
|
57
57
|
<Table>
|
|
58
58
|
<TableBody>
|
|
59
|
-
{processDataToLabelValuePairs(data).map((item
|
|
60
|
-
<TableRow key={
|
|
59
|
+
{processDataToLabelValuePairs(data).map((item) => (
|
|
60
|
+
<TableRow key={item.label} className="min-h-12">
|
|
61
61
|
<TableCell className="font-medium w-28 pl-4">
|
|
62
|
-
<h4 className="text-sm font-medium">{t(item.label)}</h4>
|
|
62
|
+
<h4 className="text-sm font-medium capitalize">{t(item.label)}</h4>
|
|
63
63
|
</TableCell>
|
|
64
64
|
<TableCell className="text-xs text-muted-foreground flex items-center gap-2 min-h-12">
|
|
65
65
|
{renderValue(item, EN_LANG)}
|
|
@@ -108,24 +108,24 @@ export const InfoTable: FC<Props> = async ({
|
|
|
108
108
|
</TableCell>
|
|
109
109
|
<TableCell className="text-xs text-muted-foreground flex items-center gap-2 min-h-12">
|
|
110
110
|
|
|
111
|
-
{Object.keys(files).map((
|
|
112
|
-
if (!files[
|
|
111
|
+
{Object.keys(files).map((fileKey) => {
|
|
112
|
+
if (!files[fileKey]) return null
|
|
113
113
|
|
|
114
114
|
return (
|
|
115
|
-
<DropdownMenu key={
|
|
115
|
+
<DropdownMenu key={fileKey}>
|
|
116
116
|
<DropdownMenuTrigger className="mr-2" asChild >
|
|
117
117
|
<Button variant="outline" size="icon" >
|
|
118
|
-
<FileIcon extension={
|
|
118
|
+
<FileIcon extension={fileKey} />
|
|
119
119
|
</Button>
|
|
120
120
|
</DropdownMenuTrigger>
|
|
121
121
|
<DropdownMenuContent>
|
|
122
122
|
<DropdownMenuItem>
|
|
123
|
-
<a href={files[
|
|
123
|
+
<a href={files[fileKey].view} target="_blank" rel="noreferrer" className="flex items-center">
|
|
124
124
|
<Eye className="mr-2" /> Open
|
|
125
125
|
</a>
|
|
126
126
|
</DropdownMenuItem>
|
|
127
127
|
<DropdownMenuItem>
|
|
128
|
-
<a href={files[
|
|
128
|
+
<a href={files[fileKey].download} target="_blank" rel="noreferrer" className="flex items-center">
|
|
129
129
|
<CloudDownload className="mr-2" /> Download
|
|
130
130
|
</a>
|
|
131
131
|
</DropdownMenuItem>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Analysis: shared
|
|
2
|
+
|
|
3
|
+
- Component: packages/components/src/info/shared.tsx
|
|
4
|
+
- Type: Server component
|
|
5
|
+
- Detected signals: useQueryStates=no, stores=no, window/document=no, effects=no, fetch/call=no
|
|
6
|
+
|
|
7
|
+
## Possible re-render causes
|
|
8
|
+
- No obvious excessive re-render trigger beyond normal prop/context updates.
|
|
9
|
+
|
|
10
|
+
## Possible bugs/risks
|
|
11
|
+
- No critical bug is evident in this quick static pass; keep tests for error and loading paths.
|
|
12
|
+
|
|
13
|
+
## Recommended improvements
|
|
14
|
+
- Standardize loading/error handling and add regression tests to prevent divergent behavior across consuming apps.
|