@c-rex/components 0.1.37 → 0.1.39

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 (146) hide show
  1. package/README.md +73 -73
  2. package/package.json +250 -235
  3. package/src/article/article-action-bar.tsx +110 -110
  4. package/src/article/article-content.tsx +18 -46
  5. package/src/autocomplete.tsx +201 -201
  6. package/src/breadcrumb.tsx +124 -124
  7. package/src/carousel/carousel.tsx +353 -352
  8. package/src/check-article-lang.tsx +47 -43
  9. package/src/directoryNodes/directory-tree-context.tsx +388 -0
  10. package/src/directoryNodes/tree-of-content.tsx +68 -67
  11. package/src/documents/result-list.tsx +124 -127
  12. package/src/favorites/bookmark-button.tsx +97 -79
  13. package/src/favorites/favorite-button.tsx +137 -74
  14. package/src/footer/footer-shell.tsx +52 -0
  15. package/src/footer/footer.tsx +7 -0
  16. package/src/footer/legal-links-block.tsx +25 -0
  17. package/src/footer/organization-contact-block.tsx +94 -0
  18. package/src/footer/social-links-block.tsx +38 -0
  19. package/src/footer/types.ts +10 -0
  20. package/src/footer/vcard-footer.tsx +72 -0
  21. package/src/generated/client-components.tsx +1366 -1350
  22. package/src/generated/create-client-request.tsx +116 -113
  23. package/src/generated/create-server-request.tsx +70 -61
  24. package/src/generated/create-suggestions-request.tsx +55 -55
  25. package/src/generated/server-components.tsx +1056 -1056
  26. package/src/generated/suggestions.tsx +302 -299
  27. package/src/icons/file-icon.tsx +8 -8
  28. package/src/icons/flag-icon.tsx +15 -15
  29. package/src/icons/loading.tsx +11 -11
  30. package/src/icons/social-icon.tsx +24 -0
  31. package/src/info/info-card.tsx +43 -0
  32. package/src/info/{info-table.tsx → information-unit-metadata-grid.tsx} +157 -146
  33. package/src/info/shared.tsx +49 -25
  34. package/src/navbar/language-switcher/content-language-switch.tsx +92 -92
  35. package/src/navbar/language-switcher/shared.tsx +33 -33
  36. package/src/navbar/language-switcher/ui-language-switch.tsx +37 -38
  37. package/src/navbar/navbar.tsx +157 -148
  38. package/src/navbar/settings.tsx +62 -62
  39. package/src/navbar/sign-in-out-btns.tsx +35 -35
  40. package/src/navbar/user-menu.tsx +60 -60
  41. package/src/page-wrapper.tsx +54 -31
  42. package/src/render-article.module.css +155 -0
  43. package/src/render-article.tsx +75 -68
  44. package/src/renditions/file-download.tsx +83 -83
  45. package/src/renditions/html.tsx +64 -64
  46. package/src/renditions/image/container.tsx +54 -54
  47. package/src/renditions/image/rendition.tsx +55 -55
  48. package/src/restriction-menu/restriction-menu-container.tsx +117 -53
  49. package/src/restriction-menu/restriction-menu-item.tsx +155 -147
  50. package/src/restriction-menu/restriction-menu.tsx +341 -157
  51. package/src/results/dialog-filter.tsx +166 -166
  52. package/src/results/empty.tsx +15 -15
  53. package/src/results/filter-navbar.tsx +294 -261
  54. package/src/results/filter-sidebar/__tests__/utils.test.ts +129 -0
  55. package/src/results/filter-sidebar/index.tsx +270 -126
  56. package/src/results/filter-sidebar/utils.ts +196 -164
  57. package/src/results/generic/table-result-list.tsx +97 -99
  58. package/src/results/{table-with-images.tsx → information-unit-search-results-card-list.tsx} +125 -127
  59. package/src/results/{cards.tsx → information-unit-search-results-cards.tsx} +99 -99
  60. package/src/results/{table.tsx → information-unit-search-results-table.tsx} +104 -104
  61. package/src/results/pagination.tsx +81 -81
  62. package/src/results/summary.ts +30 -0
  63. package/src/results/utils.ts +54 -47
  64. package/src/search-input.tsx +70 -70
  65. package/src/share-button.tsx +49 -49
  66. package/src/stores/favorites-store.ts +88 -88
  67. package/src/stores/highlight-store.ts +15 -15
  68. package/src/stores/language-store.ts +14 -43
  69. package/src/stores/restriction-store.ts +11 -11
  70. package/src/stores/search-settings-store.ts +68 -64
  71. package/src/article/article-action-bar.analysis.md +0 -15
  72. package/src/article/article-action-bar.stories.tsx +0 -15
  73. package/src/article/article-content.analysis.md +0 -15
  74. package/src/article/article-content.stories.tsx +0 -21
  75. package/src/autocomplete.analysis.md +0 -17
  76. package/src/breadcrumb.analysis.md +0 -15
  77. package/src/carousel/carousel.analysis.md +0 -17
  78. package/src/check-article-lang.analysis.md +0 -15
  79. package/src/directoryNodes/tree-of-content.analysis.md +0 -14
  80. package/src/directoryNodes/tree-of-content.stories.tsx +0 -22
  81. package/src/documents/result-list.analysis.md +0 -14
  82. package/src/documents/result-list.stories.tsx +0 -19
  83. package/src/favorites/bookmark-button.analysis.md +0 -17
  84. package/src/favorites/bookmark-button.stories.tsx +0 -19
  85. package/src/favorites/favorite-button.analysis.md +0 -18
  86. package/src/favorites/favorite-button.stories.tsx +0 -22
  87. package/src/icons/file-icon.analysis.md +0 -14
  88. package/src/icons/file-icon.stories.tsx +0 -19
  89. package/src/icons/flag-icon.analysis.md +0 -14
  90. package/src/icons/flag-icon.stories.tsx +0 -25
  91. package/src/icons/loading.analysis.md +0 -14
  92. package/src/icons/loading.stories.tsx +0 -21
  93. package/src/info/info-table.analysis.md +0 -15
  94. package/src/info/shared.analysis.md +0 -14
  95. package/src/info/stories/info-table.stories.tsx +0 -31
  96. package/src/info/stories/shared.stories.tsx +0 -24
  97. package/src/navbar/language-switcher/content-language-switch.analysis.md +0 -15
  98. package/src/navbar/language-switcher/shared.analysis.md +0 -14
  99. package/src/navbar/language-switcher/ui-language-switch.analysis.md +0 -15
  100. package/src/navbar/navbar.analysis.md +0 -14
  101. package/src/navbar/settings.analysis.md +0 -14
  102. package/src/navbar/sign-in-out-btns.analysis.md +0 -14
  103. package/src/navbar/stories/navbar.stories.tsx +0 -31
  104. package/src/navbar/stories/settings.stories.tsx +0 -15
  105. package/src/navbar/stories/sign-in-out-btns.stories.tsx +0 -15
  106. package/src/navbar/stories/user-menu.stories.tsx +0 -20
  107. package/src/navbar/user-menu.analysis.md +0 -14
  108. package/src/page-wrapper.analysis.md +0 -14
  109. package/src/render-article.analysis.md +0 -15
  110. package/src/renditions/file-download.analysis.md +0 -14
  111. package/src/renditions/file-download.stories.tsx +0 -19
  112. package/src/renditions/html.analysis.md +0 -17
  113. package/src/renditions/html.stories.tsx +0 -19
  114. package/src/renditions/image/container.analysis.md +0 -15
  115. package/src/renditions/image/container.stories.tsx +0 -19
  116. package/src/renditions/image/rendition.analysis.md +0 -14
  117. package/src/renditions/image/rendition.stories.tsx +0 -19
  118. package/src/restriction-menu/restriction-menu-container.analysis.md +0 -14
  119. package/src/restriction-menu/restriction-menu-item.analysis.md +0 -14
  120. package/src/restriction-menu/restriction-menu.analysis.md +0 -17
  121. package/src/results/analysis/cards.analysis.md +0 -14
  122. package/src/results/analysis/dialog-filter.analysis.md +0 -17
  123. package/src/results/analysis/empty.analysis.md +0 -14
  124. package/src/results/analysis/filter-navbar.analysis.md +0 -16
  125. package/src/results/analysis/pagination.analysis.md +0 -14
  126. package/src/results/analysis/table-with-images.analysis.md +0 -15
  127. package/src/results/analysis/table.analysis.md +0 -15
  128. package/src/results/filter-sidebar/index.analysis.md +0 -14
  129. package/src/results/generic/table-result-list.analysis.md +0 -15
  130. package/src/results/generic/table-result-list.stories.tsx +0 -21
  131. package/src/results/stories/cards.stories.tsx +0 -66
  132. package/src/results/stories/dialog-filter.stories.tsx +0 -20
  133. package/src/results/stories/empty.stories.tsx +0 -25
  134. package/src/results/stories/filter-navbar.stories.tsx +0 -19
  135. package/src/results/stories/filter-sidebar.stories.tsx +0 -20
  136. package/src/results/stories/pagination.stories.tsx +0 -24
  137. package/src/results/stories/table-with-images.stories.tsx +0 -19
  138. package/src/results/stories/table.stories.tsx +0 -78
  139. package/src/search-input.analysis.md +0 -15
  140. package/src/share-button.analysis.md +0 -19
  141. package/src/stories/autocomplete.stories.tsx +0 -20
  142. package/src/stories/breadcrumb.stories.tsx +0 -93
  143. package/src/stories/check-article-lang.stories.tsx +0 -22
  144. package/src/stories/render-article.stories.tsx +0 -19
  145. package/src/stories/search-input.stories.tsx +0 -21
  146. package/src/stories/share-button.stories.tsx +0 -15
@@ -1,92 +1,92 @@
1
- "use client";
2
-
3
- import { startTransition } from "react";
4
- import { SharedLanguageSwitch } from "./shared";
5
- import { BLOG_TYPE_AND_LINK, DOCUMENTS_TYPE_AND_LINK, TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
6
- import { useQueryState } from "nuqs"
7
- import { useAppConfig } from "@c-rex/contexts/config-provider";
8
- import { useTranslations } from "next-intl";
9
- import { toast } from "sonner"
10
- import { useLanguageStore } from "../../stores/language-store";
11
- import { useSearchSettingsStore } from "../../stores/search-settings-store";
12
-
13
- type Props = {
14
- contentLangDefault: string;
15
- };
16
-
17
- export const ContentLanguageSwitch = ({ contentLangDefault }: Props) => {
18
- const t = useTranslations();
19
- const contentLang = useSearchSettingsStore.getState().language || contentLangDefault;
20
- const updatePreferences = useSearchSettingsStore.getState().updatePreferences;
21
-
22
- const { availableVersions } = useAppConfig()
23
-
24
- const availableLanguagesAndCountries = () => {
25
- const aux = useLanguageStore.getState().availableLanguages;
26
- let result = aux.map(item => ({ ...item, link: "#" }))
27
- if (availableVersions == null) return result
28
-
29
- result = aux.map(item => {
30
- const availableVersion = availableVersions.find(version => version.lang === item.value)
31
- return {
32
- ...item,
33
- link: availableVersion?.link ?? "#"
34
- }
35
- })
36
-
37
- return result;
38
- }
39
- const [queryLanguage, setContentLanguage] = useQueryState('language', {
40
- history: 'push',
41
- shallow: false,
42
- })
43
-
44
- const changeContentLanguage = (locale: string) => {
45
- startTransition(() => {
46
- updatePreferences({ language: locale })
47
-
48
- if (queryLanguage != null) {
49
- setContentLanguage(locale)
50
- }
51
-
52
- //TODO en: needs to be fixed as it's not working
53
-
54
- const currentPath = window.location.pathname;
55
- const isTopicOrBlogOrDocument = (
56
- currentPath.includes(TOPICS_TYPE_AND_LINK) ||
57
- currentPath.includes(BLOG_TYPE_AND_LINK) ||
58
- currentPath.includes(DOCUMENTS_TYPE_AND_LINK)
59
- )
60
-
61
- if (!isTopicOrBlogOrDocument) {
62
- setTimeout(() => window.location.reload(), 5);
63
- return;
64
- }
65
-
66
- if (availableVersions !== null) {
67
- const filteredList = availableVersions.filter((item) => item.lang === locale)
68
-
69
- if (filteredList.length > 0 && filteredList[0]) {
70
- window.location.href = filteredList[0].link as string;
71
- } else {
72
- articleNotAvailableToast()
73
- }
74
- }
75
- });
76
- };
77
-
78
- const articleNotAvailableToast = () => {
79
- toast(t('sorry'), {
80
- description: t('toast.articleNotAvailable'),
81
- duration: 10000,
82
- })
83
- }
84
-
85
- return (
86
- <SharedLanguageSwitch
87
- availableLanguagesAndCountries={availableLanguagesAndCountries()}
88
- changeLanguage={changeContentLanguage}
89
- selected={contentLang}
90
- />
91
- );
92
- };
1
+ "use client";
2
+
3
+ import { startTransition, useCallback, useMemo } from "react";
4
+ import { SharedLanguageSwitch } from "./shared";
5
+ import { useQueryState } from "nuqs"
6
+ import { useAppConfig } from "@c-rex/contexts/config-provider";
7
+ import { useTranslations } from "next-intl";
8
+ import { toast } from "sonner"
9
+ import { useLanguageStore } from "../../stores/language-store";
10
+ import { useSearchSettingsStore } from "../../stores/search-settings-store";
11
+
12
+ type Props = {
13
+ contentLangDefault: string;
14
+ };
15
+
16
+ export const ContentLanguageSwitch = ({ contentLangDefault }: Props) => {
17
+ const t = useTranslations();
18
+ const contentLang = useSearchSettingsStore((state) => state.language) || contentLangDefault;
19
+ const updatePreferences = useSearchSettingsStore((state) => state.updatePreferences);
20
+ const availableLanguages = useLanguageStore((state) => state.availableLanguages);
21
+ const { availableVersions } = useAppConfig()
22
+
23
+
24
+ const normalizeLang = (lang: string) => lang.trim().toLowerCase();
25
+
26
+ const findVersionByLocale = useCallback((locale: string) => {
27
+ if (!availableVersions || availableVersions.length === 0) return undefined;
28
+ const normalizedLocale = normalizeLang(locale);
29
+
30
+ return availableVersions.find((item) => normalizeLang(item.lang) === normalizedLocale)
31
+ ?? availableVersions.find((item) => {
32
+ const langCode = normalizeLang(item.lang).split("-")[0];
33
+ const localeCode = normalizedLocale.split("-")[0];
34
+ return langCode === localeCode;
35
+ });
36
+ }, [availableVersions]);
37
+
38
+ const availableLanguagesAndCountries = useMemo(() => {
39
+ return availableLanguages.map((item) => {
40
+ const availableVersion = findVersionByLocale(item.value);
41
+ return {
42
+ ...item,
43
+ link: availableVersion?.link ?? "#",
44
+ };
45
+ });
46
+ }, [availableLanguages, availableVersions]);
47
+
48
+ const [queryLanguage, setContentLanguage] = useQueryState('language', {
49
+ history: 'push',
50
+ shallow: false,
51
+ })
52
+
53
+ const changeContentLanguage = (locale: string) => {
54
+ startTransition(() => {
55
+ updatePreferences({ language: locale })
56
+ if (queryLanguage != null) {
57
+ setContentLanguage(locale)
58
+ return;
59
+ }
60
+
61
+ const currentPath = window.location.pathname;
62
+ const isArticlePage = currentPath.includes("/pages");
63
+ if (!isArticlePage) {
64
+ window.location.reload();
65
+ return;
66
+ };
67
+
68
+ const targetVersion = findVersionByLocale(locale);
69
+ if (targetVersion?.link) {
70
+ window.location.href = targetVersion.link;
71
+ return;
72
+ }
73
+
74
+ articleNotAvailableToast()
75
+ });
76
+ };
77
+
78
+ const articleNotAvailableToast = () => {
79
+ toast(t('sorry'), {
80
+ description: t('toast.articleNotAvailable'),
81
+ duration: 10000,
82
+ })
83
+ }
84
+
85
+ return (
86
+ <SharedLanguageSwitch
87
+ availableLanguagesAndCountries={availableLanguagesAndCountries}
88
+ changeLanguage={changeContentLanguage}
89
+ selected={contentLang}
90
+ />
91
+ );
92
+ };
@@ -1,33 +1,33 @@
1
- import React, { FC } from "react";
2
- import { LanguageAndCountries } from "@c-rex/interfaces";
3
- import { DropdownMenuRadioGroup, DropdownMenuRadioItem } from "@c-rex/ui/dropdown-menu";
4
- import { Flag } from "../../icons/flag-icon";
5
-
6
- interface SharedLanguageSwitchProps {
7
- availableLanguagesAndCountries: (LanguageAndCountries & { link?: string })[];
8
- selected: string;
9
- changeLanguage: (locale: string) => void;
10
- }
11
- export const SharedLanguageSwitch: FC<SharedLanguageSwitchProps> = ({ availableLanguagesAndCountries, changeLanguage, selected }) => {
12
-
13
- return (
14
- <DropdownMenuRadioGroup value={selected}>
15
- {availableLanguagesAndCountries.map(item => {
16
- return (
17
- <DropdownMenuRadioItem
18
- key={item.value}
19
- value={item.value}
20
- link={item?.link}
21
- onClick={(e) => {
22
- e.preventDefault();
23
- changeLanguage(item.value)
24
- }}
25
- >
26
- <Flag countryCode={item.country} />
27
- <span>{item.lang.toUpperCase()}</span>
28
- </DropdownMenuRadioItem>
29
- )
30
- })}
31
- </DropdownMenuRadioGroup>
32
- );
33
- };
1
+ import React, { FC } from "react";
2
+ import { LanguageAndCountries } from "@c-rex/interfaces";
3
+ import { DropdownMenuRadioGroup, DropdownMenuRadioItem } from "@c-rex/ui/dropdown-menu";
4
+ import { Flag } from "../../icons/flag-icon";
5
+
6
+ interface SharedLanguageSwitchProps {
7
+ availableLanguagesAndCountries: (LanguageAndCountries & { link?: string })[];
8
+ selected: string;
9
+ changeLanguage: (locale: string) => void;
10
+ }
11
+ export const SharedLanguageSwitch: FC<SharedLanguageSwitchProps> = ({ availableLanguagesAndCountries, changeLanguage, selected }) => {
12
+
13
+ return (
14
+ <DropdownMenuRadioGroup value={selected}>
15
+ {availableLanguagesAndCountries.map(item => {
16
+ return (
17
+ <DropdownMenuRadioItem
18
+ key={item.value}
19
+ value={item.value}
20
+ link={item?.link}
21
+ onClick={(e) => {
22
+ e.preventDefault();
23
+ changeLanguage(item.value)
24
+ }}
25
+ >
26
+ <Flag countryCode={item.country} />
27
+ <span>{item.lang.toUpperCase()}</span>
28
+ </DropdownMenuRadioItem>
29
+ )
30
+ })}
31
+ </DropdownMenuRadioGroup>
32
+ );
33
+ };
@@ -1,38 +1,37 @@
1
- "use client"
2
-
3
- import React, { FC, startTransition } from "react";
4
- import { SharedLanguageSwitch } from "./shared";
5
- import { UI_LANG_KEY, UI_LANG_OPTIONS } from "@c-rex/constants";
6
- import { getCountryCodeByLang, } from "@c-rex/utils";
7
- import { setCookie } from "@c-rex/utils/cookies";
8
- import { useLanguageStore } from "../../stores/language-store";
9
-
10
- export const UILanguageSwitch: FC = () => {
11
- const uiLang = useLanguageStore((state) => state.uiLang);
12
- const setUiLang = useLanguageStore.getState().setUiLang;
13
- const UILanguages = UI_LANG_OPTIONS.map((lang) => {
14
- const langCode = lang.split("-")[0] as string;
15
- return {
16
- value: lang,
17
- lang: langCode,
18
- country: getCountryCodeByLang(langCode)
19
- };
20
- })
21
-
22
- const setUILanguage = (locale: string) => {
23
- startTransition(() => {
24
- setUiLang(locale)
25
- setCookie(UI_LANG_KEY, locale, { httpOnly: false });
26
-
27
- //window.location.reload()
28
- });
29
- }
30
-
31
- return (
32
- <SharedLanguageSwitch
33
- availableLanguagesAndCountries={UILanguages}
34
- changeLanguage={setUILanguage}
35
- selected={uiLang}
36
- />
37
- );
38
- };
1
+ "use client"
2
+
3
+ import React, { FC, startTransition } from "react";
4
+ import { SharedLanguageSwitch } from "./shared";
5
+ import { UI_LANG_KEY, UI_LANG_OPTIONS } from "@c-rex/constants";
6
+ import { getCountryCodeByLang, } from "@c-rex/utils";
7
+ import { setCookie } from "@c-rex/utils/cookies";
8
+ import { useLocale } from "next-intl";
9
+ import { useRouter } from "next/navigation";
10
+
11
+ export const UILanguageSwitch: FC = () => {
12
+ const uiLang = useLocale().toLowerCase();
13
+ const router = useRouter();
14
+ const UILanguages = UI_LANG_OPTIONS.map((lang) => {
15
+ const langCode = lang.split("-")[0] as string;
16
+ return {
17
+ value: lang,
18
+ lang: langCode,
19
+ country: getCountryCodeByLang(langCode)
20
+ };
21
+ })
22
+
23
+ const setUILanguage = (locale: string) => {
24
+ startTransition(() => {
25
+ setCookie(UI_LANG_KEY, locale, { httpOnly: false });
26
+ router.refresh();
27
+ });
28
+ }
29
+
30
+ return (
31
+ <SharedLanguageSwitch
32
+ availableLanguagesAndCountries={UILanguages}
33
+ changeLanguage={setUILanguage}
34
+ selected={uiLang}
35
+ />
36
+ );
37
+ };
@@ -1,148 +1,157 @@
1
- import { ComponentProps, FC } from "react";
2
- import Link from "next/link";
3
- import { SignInBtn } from "./sign-in-out-btns";
4
- import { getServerSession } from "next-auth";
5
- import { SettingsMenu } from "./settings";
6
- import { UserMenu } from "./user-menu";
7
- import { SearchInput } from "../search-input";
8
- import { CrexSDK } from "@c-rex/core/sdk";
9
- import * as AutocompleteOptions from "../generated/suggestions";
10
- import { cn } from "@c-rex/utils";
11
- import { getTranslations } from "next-intl/server";
12
- import { Button } from "@c-rex/ui/button";
13
- import { DropdownHoverItem } from "@c-rex/ui/dropdown-hover-item";
14
- import { Menu } from "lucide-react";
15
-
16
- type NavBarProps = {
17
- title?: string;
18
- showInput: boolean;
19
- showPkgFilter: boolean;
20
- onSelectPath?: string;
21
- autocompleteType?: keyof typeof AutocompleteOptions;
22
- //these two props are only used when showPkgFilter is false and has some values to override the default behavior
23
- alternativeAutocompleteType?: keyof typeof AutocompleteOptions;
24
- alternativeOnSelectPath?: string;
25
- showMenu?: boolean;
26
- }
27
-
28
- export const NavBar: FC<NavBarProps> = async ({
29
- title,
30
- showInput,
31
- autocompleteType,
32
- onSelectPath,
33
- showMenu = true,
34
- ...props
35
- }) => {
36
- const t = await getTranslations();
37
- const sdk = new CrexSDK();
38
- const clientConfigs = sdk.getClientConfig();
39
- const serverConfigs = sdk.getServerConfig();
40
-
41
- const willShowInput = showInput && autocompleteType && onSelectPath;
42
- if (!willShowInput && showInput) {
43
- throw new Error("NavBar: autocompleteType and onSelectPath are required when showInput is true");
44
- }
45
-
46
- let session: any;
47
- if (clientConfigs.OIDC.userEnabled) {
48
- session = await getServerSession();
49
- }
50
-
51
- return (
52
- <header className="sticky flex flex-col top-0 z-40 w-full p-4 backdrop-blur-xl transition-all bg-transparent border-b gap-2">
53
- <div className="w-full flex items-center justify-between gap-2">
54
- <div
55
- className={cn(
56
- "flex items-center gap-4",
57
- title && "lg:w-[calc(16rem-16px)]"
58
- )}
59
- >
60
-
61
- <Link href="/"
62
- >
63
- <img
64
- src="/img/logo.png"
65
- alt="C-rex Logo"
66
- className="h-14"
67
- />
68
- </Link>
69
-
70
- {showMenu && (
71
- <DropdownHoverItem
72
- label={
73
- <Button variant="outline" rounded="full" size="icon">
74
- <Menu className="size-4" />
75
- </Button>
76
- }
77
- >
78
- <Button asChild variant="link" className="flex justify-start">
79
- <Link href="/">
80
- {t('navigation.home')}
81
- </Link>
82
- </Button>
83
- <Button asChild variant="link" className="flex justify-start">
84
- <Link href="/documents">
85
- {t('navigation.documents')}
86
- </Link>
87
- </Button>
88
- <Button asChild variant="link" className="flex justify-start">
89
- <Link href="/topics">
90
- {t('navigation.topics')}
91
- </Link>
92
- </Button>
93
- <Button asChild variant="link" className="flex justify-start">
94
- <Link href="/fragments">
95
- {t('navigation.fragments')}
96
- </Link>
97
- </Button>
98
- <Button asChild variant="link" className="flex justify-start">
99
- <Link href="/packages">
100
- {t('navigation.packages')}
101
- </Link>
102
- </Button>
103
- <Button asChild variant="link" className="flex justify-start">
104
- <Link href="/information-units">
105
- {t('navigation.informationUnits')}
106
- </Link>
107
- </Button>
108
- </DropdownHoverItem>
109
- )}
110
- </div>
111
-
112
- {title && (
113
- <div className="flex-1 hidden md:flex md:justify-center lg:justify-start">
114
- <h1 className="md:text-2xl lg:text-3xl font-bold tracking-tight text-balance">{title}</h1>
115
- </div>
116
- )}
117
-
118
- <div className="flex gap-2">
119
- {willShowInput &&
120
- <div className="hidden sm:flex flex-1 items-center px-3 border rounded-full h-8 c-rex-search-bar">
121
- <SearchInput autocompleteType={autocompleteType} onSelectPath={onSelectPath} {...props} />
122
- </div>
123
- }
124
-
125
- {clientConfigs.OIDC.userEnabled && (
126
- <>
127
- {session ? (
128
- <UserMenu session={session} OIDCEndPoint={serverConfigs.OIDC.user.issuer} />
129
- ) : (
130
- <SignInBtn />
131
- )}
132
- </>
133
- )}
134
-
135
- {clientConfigs.languageSwitcher.enabled && (
136
- <SettingsMenu />
137
- )}
138
- </div>
139
- </div>
140
-
141
- {title && (
142
- <div className="flex-1 flex justify-center md:hidden">
143
- <h1 className="text-2xl font-bold tracking-tight text-balance">{title}</h1>
144
- </div>
145
- )}
146
- </header>
147
- );
148
- };
1
+ import { FC } from "react";
2
+ import Link from "next/link";
3
+ import { SignInBtn } from "./sign-in-out-btns";
4
+ import { getServerSession } from "next-auth";
5
+ import { SettingsMenu } from "./settings";
6
+ import { UserMenu } from "./user-menu";
7
+ import { SearchInput } from "../search-input";
8
+ import { CrexSDK } from "@c-rex/core/sdk";
9
+ import * as AutocompleteOptions from "../generated/suggestions";
10
+ import { cn } from "@c-rex/utils";
11
+ import { getTranslations } from "next-intl/server";
12
+ import { Button } from "@c-rex/ui/button";
13
+ import { DropdownHoverItem } from "@c-rex/ui/dropdown-hover-item";
14
+ import { Menu } from "lucide-react";
15
+ import { getOrganizationBranding } from "@c-rex/services/vcard";
16
+
17
+ type NavBarProps = {
18
+ title?: string;
19
+ showInput: boolean;
20
+ showPkgFilter: boolean;
21
+ showOrganizationLogo?: boolean;
22
+ onSelectPath?: string;
23
+ autocompleteType?: keyof typeof AutocompleteOptions;
24
+ //these two props are only used when showPkgFilter is false and has some values to override the default behavior
25
+ alternativeAutocompleteType?: keyof typeof AutocompleteOptions;
26
+ alternativeOnSelectPath?: string;
27
+ showMenu?: boolean;
28
+ }
29
+
30
+ export const NavBar: FC<NavBarProps> = async ({
31
+ title,
32
+ showInput,
33
+ showOrganizationLogo = true,
34
+ autocompleteType,
35
+ onSelectPath,
36
+ showMenu = true,
37
+ ...props
38
+ }) => {
39
+ const t = await getTranslations();
40
+ const sdk = new CrexSDK();
41
+ const clientConfigs = sdk.getClientConfig();
42
+ const serverConfigs = sdk.getServerConfig();
43
+ const organizationBranding = showOrganizationLogo ? await getOrganizationBranding() : undefined;
44
+
45
+ const willShowInput = showInput && autocompleteType && onSelectPath;
46
+ if (!willShowInput && showInput) {
47
+ throw new Error("NavBar: autocompleteType and onSelectPath are required when showInput is true");
48
+ }
49
+
50
+ let session: any;
51
+ if (clientConfigs.OIDC.userEnabled) {
52
+ session = await getServerSession();
53
+ }
54
+
55
+ return (
56
+ <header className="sticky flex flex-col top-0 z-40 w-full p-4 backdrop-blur-xl transition-all bg-transparent border-b gap-2">
57
+ <div className="w-full flex items-center justify-between gap-2">
58
+ <div
59
+ className={cn(
60
+ "flex items-center gap-4",
61
+ title && "lg:w-[calc(16rem-16px)]"
62
+ )}
63
+ >
64
+
65
+ {showOrganizationLogo && organizationBranding && (
66
+ <Link href="/">
67
+ <img
68
+ src={organizationBranding.logoSrc}
69
+ alt={`${organizationBranding.organizationName} logo`}
70
+ className="h-14"
71
+ />
72
+ </Link>
73
+ )}
74
+
75
+ {showMenu && (
76
+ <DropdownHoverItem
77
+ label={
78
+ <Button variant="outline" rounded="full" size="icon">
79
+ <Menu className="size-4" />
80
+ </Button>
81
+ }
82
+ >
83
+ <Button asChild variant="link" className="flex justify-start">
84
+ <Link href="/">
85
+ {t('navigation.home')}
86
+ </Link>
87
+ </Button>
88
+ <Button asChild variant="link" className="flex justify-start">
89
+ <Link href="/documents">
90
+ {t('navigation.documents')}
91
+ </Link>
92
+ </Button>
93
+ <Button asChild variant="link" className="flex justify-start">
94
+ <Link href="/topics">
95
+ {t('navigation.topics')}
96
+ </Link>
97
+ </Button>
98
+ <Button asChild variant="link" className="flex justify-start">
99
+ <Link href="/fragments">
100
+ {t('navigation.fragments')}
101
+ </Link>
102
+ </Button>
103
+ <Button asChild variant="link" className="flex justify-start">
104
+ <Link href="/packages">
105
+ {t('navigation.packages')}
106
+ </Link>
107
+ </Button>
108
+ <Button asChild variant="link" className="flex justify-start">
109
+ <Link href="/information-units">
110
+ {t('navigation.informationUnits')}
111
+ </Link>
112
+ </Button>
113
+ </DropdownHoverItem>
114
+ )}
115
+ </div>
116
+
117
+ {title && (
118
+ <div className="flex-1 hidden md:flex md:justify-center lg:justify-start">
119
+ <h1 className="md:text-2xl lg:text-3xl font-bold tracking-tight text-balance">{title}</h1>
120
+ </div>
121
+ )}
122
+
123
+ <div className="flex gap-2">
124
+ {willShowInput &&
125
+ <div className="hidden sm:flex flex-1 items-center px-3 border rounded-full h-8 c-rex-search-bar">
126
+ <SearchInput
127
+ autocompleteType={autocompleteType}
128
+ onSelectPath={onSelectPath}
129
+ {...props}
130
+ />
131
+ </div>
132
+ }
133
+
134
+ {clientConfigs.OIDC.userEnabled && (
135
+ <>
136
+ {session ? (
137
+ <UserMenu session={session} OIDCEndPoint={serverConfigs.OIDC.user.issuer} />
138
+ ) : (
139
+ <SignInBtn />
140
+ )}
141
+ </>
142
+ )}
143
+
144
+ {clientConfigs.languageSwitcher.enabled && (
145
+ <SettingsMenu />
146
+ )}
147
+ </div>
148
+ </div>
149
+
150
+ {title && (
151
+ <div className="flex-1 flex justify-center md:hidden">
152
+ <h1 className="text-2xl font-bold tracking-tight text-balance">{title}</h1>
153
+ </div>
154
+ )}
155
+ </header>
156
+ );
157
+ };