@c-rex/templates 0.3.0-build.41 → 0.3.0-build.49

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c-rex/templates",
3
- "version": "0.3.0-build.41",
3
+ "version": "0.3.0-build.49",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src"
@@ -21,7 +21,12 @@
21
21
  },
22
22
  "scripts": {
23
23
  "lint": "eslint .",
24
- "lint:fix": "eslint . --fix"
24
+ "lint:fix": "eslint . --fix",
25
+ "check-types": "echo \u0027No types to check\u0027",
26
+ "test": "echo \u0027No tests\u0027",
27
+ "build": "echo \u0027No build script\u0027",
28
+ "format:check": "prettier --check .",
29
+ "validate": "npm run lint \u0026\u0026 npm run check-types \u0026\u0026 npm run test \u0026\u0026 npm run build"
25
30
  },
26
31
  "devDependencies": {
27
32
  "@c-rex/eslint-config": "*",
@@ -31,7 +36,7 @@
31
36
  "@types/react": "19.0.10",
32
37
  "@types/react-dom": "19.0.4",
33
38
  "eslint": "^9.23.0",
34
- "typescript": "latest"
39
+ "typescript": "~5.8.3"
35
40
  },
36
41
  "dependencies": {
37
42
  "@c-rex/components": "*",
@@ -45,7 +50,7 @@
45
50
  "@c-rex/utils": "*",
46
51
  "cheerio": "^1.1.0",
47
52
  "i18next": "^25.1.3",
48
- "next": "^14",
53
+ "next": "^15",
49
54
  "next-intl": "^4.1.0",
50
55
  "nuqs": "^2.4.3",
51
56
  "react": "^18.3.1",
@@ -6,58 +6,66 @@ import { informationUnitsResponse } from "@c-rex/interfaces";
6
6
  import { CrexSDK } from "@c-rex/core/sdk";
7
7
 
8
8
  interface HomeProps {
9
- searchParams: {
10
- search?: string;
11
- page: string;
12
- language: string;
13
- wildcard: string;
14
- operator: string;
15
- like: string;
16
- packages?: string;
17
- filter?: string;
18
- };
9
+ searchParams: {
10
+ search?: string;
11
+ page: string;
12
+ language: string;
13
+ wildcard: string;
14
+ operator: string;
15
+ like: string;
16
+ packages?: string;
17
+ filter?: string;
18
+ };
19
19
  }
20
20
 
21
21
  export const HomeLayout = async ({ searchParams }: HomeProps) => {
22
- const { search, page, language, wildcard, operator, like, packages, filter } = searchParams;
23
- const sdk = new CrexSDK();
24
- const config = sdk.getServerConfig();
22
+ const { search, page, language, wildcard, operator, like, packages, filter } =
23
+ searchParams;
24
+ const sdk = new CrexSDK();
25
+ const config = sdk.getServerConfig();
25
26
 
26
- let data = {
27
- items: [],
28
- pageInfo: {
29
- pageCount: 0,
30
- pageNumber: 0
31
- }
32
- } as unknown as informationUnitsResponse;
27
+ let data = {
28
+ items: [],
29
+ pageInfo: {
30
+ pageCount: 0,
31
+ pageNumber: 0,
32
+ },
33
+ } as unknown as informationUnitsResponse;
33
34
 
34
- if (search !== undefined) {
35
+ if (search !== undefined) {
36
+ const filters: string[] = filter?.split(",") || [];
37
+ const restrict: string[] = [];
35
38
 
36
- const filters: string[] = filter?.split(",") || []
37
- const restrict: string[] = []
38
-
39
- if (packages && packages.length > 0) {
40
- restrict.push(`packages.shortId=${packages}`)
41
- }
42
- const service = new InformationUnitsService();
43
-
44
- data = await service.getList({
45
- queries: search,
46
- page: Number(page),
47
- fields: ["renditions", "class", "languages", "labels", "versionOf", "revision"],
48
- languages: language.split(","),
49
- wildcard: wildcard as WildCardType,
50
- restrict: restrict,
51
- operator: operator as OperatorType,
52
- like: Boolean(like === "true"),
53
- filters: filters,
54
- tags: config.search.tags,
55
- });
39
+ if (packages && packages.length > 0) {
40
+ restrict.push(`packages.shortId=${packages}`);
56
41
  }
42
+ const service = new InformationUnitsService();
43
+
44
+ data = await service.getList({
45
+ queries: search,
46
+ page: Number(page),
47
+ fields: [
48
+ "renditions",
49
+ "class",
50
+ "languages",
51
+ "titles",
52
+ "labels",
53
+ "versionOf",
54
+ "revision",
55
+ ],
56
+ languages: language.split(","),
57
+ wildcard: wildcard as WildCardType,
58
+ restrict: restrict,
59
+ operator: operator as OperatorType,
60
+ like: Boolean(like === "true"),
61
+ filters: filters,
62
+ tags: config.search.tags,
63
+ });
64
+ }
57
65
 
58
- return (
59
- <PageWrapper>
60
- <HomePage data={data} />
61
- </PageWrapper>
62
- );
66
+ return (
67
+ <PageWrapper>
68
+ <HomePage data={data} />
69
+ </PageWrapper>
70
+ );
63
71
  };
package/src/layout.tsx CHANGED
@@ -1,91 +1,128 @@
1
1
  import React from "react";
2
- import { NextIntlClientProvider } from 'next-intl';
2
+ import { NextIntlClientProvider } from "next-intl";
3
3
  import { getLocale } from "next-intl/server";
4
- import { Toaster } from "@c-rex/ui/sonner"
4
+ import { Toaster } from "@c-rex/ui/sonner";
5
5
  import { AppConfigProvider } from "@c-rex/contexts/config-provider";
6
- import { NuqsAdapter } from 'nuqs/adapters/next/app'
6
+ import { NuqsAdapter } from "nuqs/adapters/next/app";
7
7
  import { cookies } from "next/headers";
8
8
  import { CrexSDK } from "@c-rex/core/sdk";
9
9
  import { getIssuerMetadata } from "@c-rex/core/OIDC";
10
10
  import { resolveUILanguage, resolveContentLanguage } from "./utils";
11
11
  import { informationUnitsLanguagesServer } from "@c-rex/services/server-requests";
12
- import { UI_LANG_KEY } from "@c-rex/constants";
12
+ import {
13
+ UI_LANG_KEY,
14
+ SEARCH_SETTINGS_COOKIE_NAME,
15
+ UI_PREFERENCES_COOKIE_NAME,
16
+ } from "@c-rex/constants";
13
17
  import { transformLanguageData } from "@c-rex/utils";
14
18
  import { getSearchSettingsFromCookie } from "@c-rex/components/search-settings-store";
15
19
  import { FavoritesProvider } from "@c-rex/components/favorites-context";
20
+ import { getUiPreferencesFromCookie } from "@c-rex/components/ui-preferences-store";
21
+ import { UiPreferencesRuntime } from "@c-rex/components/ui-preferences-runtime";
16
22
 
17
23
  interface DefaultRootLayoutProps {
18
- children: React.ReactNode;
24
+ children: React.ReactNode;
19
25
  }
20
26
 
21
- const getAvailableLanguagesSafe = async (): Promise<{ value: string; score: number }[]> => {
22
- try {
23
- const data = await informationUnitsLanguagesServer();
24
- return (data as { value: string; score: number }[]) || [];
25
- } catch (error) {
26
- // Some installations expose the Languages endpoint only intermittently
27
- // or behind infrastructure that can transiently return 503. The app
28
- // should still boot with the configured default language instead of
29
- // failing the entire root layout.
30
- console.warn("[DefaultRootLayout] Failed to load available content languages. Falling back to defaults.", error);
31
- return [];
32
- }
27
+ const getAvailableLanguagesSafe = async (): Promise<
28
+ { value: string; score: number }[]
29
+ > => {
30
+ try {
31
+ const data = await informationUnitsLanguagesServer();
32
+ return (data as { value: string; score: number }[]) || [];
33
+ } catch (error) {
34
+ // Some installations expose the Languages endpoint only intermittently
35
+ // or behind infrastructure that can transiently return 503. The app
36
+ // should still boot with the configured default language instead of
37
+ // failing the entire root layout.
38
+ console.warn(
39
+ "[DefaultRootLayout] Failed to load available content languages. Falling back to defaults.",
40
+ error,
41
+ );
42
+ return [];
43
+ }
33
44
  };
34
45
 
35
- export const DefaultRootLayout = async ({ children }: DefaultRootLayoutProps) => {
36
- const [locale, metadata, languageData] = await Promise.all([
37
- getLocale(),
38
- getIssuerMetadata(),
39
- getAvailableLanguagesSafe(),
40
- ])
46
+ export const DefaultRootLayout = async ({
47
+ children,
48
+ }: DefaultRootLayoutProps) => {
49
+ const [locale, metadata, languageData] = await Promise.all([
50
+ getLocale(),
51
+ getIssuerMetadata(),
52
+ getAvailableLanguagesSafe(),
53
+ ]);
41
54
 
42
- const sdk = new CrexSDK()
43
- const cookieStore = cookies();
44
- const uiLangCookie = cookieStore.get(UI_LANG_KEY)?.value ?? null;
45
- const clientConfigs = sdk.getClientConfig();
46
- const serverConfigs = sdk.getServerConfig();
47
- const searchSettings = getSearchSettingsFromCookie(cookieStore.get("c-rex-search-settings")?.value);
55
+ const sdk = new CrexSDK();
56
+ const cookieStore = await cookies();
57
+ const uiLangCookie = cookieStore.get(UI_LANG_KEY)?.value ?? null;
58
+ const clientConfigs = await sdk.getClientConfig();
59
+ const serverConfigs = sdk.getServerConfig();
60
+ const searchSettings = getSearchSettingsFromCookie(
61
+ cookieStore.get(SEARCH_SETTINGS_COOKIE_NAME)?.value,
62
+ );
63
+ const uiPreferences = getUiPreferencesFromCookie(
64
+ cookieStore.get(UI_PREFERENCES_COOKIE_NAME)?.value,
65
+ );
48
66
 
49
- sdk.updateConfigProp('OIDC', {
50
- ...serverConfigs.OIDC,
51
- issuerMetadata: metadata
52
- });
67
+ sdk.updateConfigProp("OIDC", {
68
+ ...serverConfigs.OIDC,
69
+ issuerMetadata: metadata,
70
+ });
53
71
 
54
- const availableLanguages = transformLanguageData(languageData);
72
+ const availableLanguages = transformLanguageData(languageData);
55
73
 
56
- const uiLang = resolveUILanguage({
57
- uiLangCookie,
58
- defaultLang: clientConfigs.languageSwitcher.default
59
- });
74
+ const uiLang = await resolveUILanguage({
75
+ uiLangCookie,
76
+ defaultLang: clientConfigs.languageSwitcher.default,
77
+ });
60
78
 
61
- const contentLang = resolveContentLanguage({
62
- contentLangCookie: searchSettings.language,
63
- availableLanguages,
64
- defaultLang: clientConfigs.languageSwitcher.default
65
- });
79
+ const contentLang = await resolveContentLanguage({
80
+ contentLangCookie: searchSettings.language,
81
+ availableLanguages,
82
+ defaultLang:
83
+ clientConfigs.defaultContentLanguage ??
84
+ clientConfigs.languageSwitcher.default,
85
+ });
66
86
 
67
- return (
68
- <html lang={locale}>
69
- <head>
70
- <link rel="icon" type="image/x-icon" href="/img/favicon.png" />
71
- </head>
72
- <body className="min-h-screen bg-background font-sans antialiased">
73
- <NextIntlClientProvider>
74
- <AppConfigProvider
75
- uiLang={uiLang}
76
- contentLang={contentLang}
77
- availableLanguages={availableLanguages}
78
- initialConfig={clientConfigs}
79
- >
80
- <FavoritesProvider>
81
- <Toaster />
82
- <NuqsAdapter>
83
- {children}
84
- </NuqsAdapter>
85
- </FavoritesProvider>
86
- </AppConfigProvider>
87
- </NextIntlClientProvider>
88
- </body>
89
- </html>
90
- );
87
+ return (
88
+ <html
89
+ lang={locale}
90
+ className={uiPreferences.theme === "dark" ? "dark" : undefined}
91
+ data-theme={uiPreferences.theme}
92
+ data-font-scale={uiPreferences.fontScale}
93
+ data-readonly-mode={clientConfigs.readOnlyMode ? "true" : "false"}
94
+ style={{
95
+ fontSize:
96
+ uiPreferences.fontScale === "small"
97
+ ? "93.75%"
98
+ : uiPreferences.fontScale === "large"
99
+ ? "112.5%"
100
+ : "100%",
101
+ }}
102
+ >
103
+ <head>
104
+ <link rel="icon" type="image/x-icon" href="/img/favicon.png" />
105
+ </head>
106
+ <body className="min-h-screen bg-background font-sans antialiased">
107
+ <NextIntlClientProvider>
108
+ <AppConfigProvider
109
+ uiLang={uiLang}
110
+ contentLang={contentLang}
111
+ availableLanguages={availableLanguages}
112
+ initialConfig={clientConfigs}
113
+ loginEnabled={Boolean(serverConfigs.OIDC.client.enabled)}
114
+ >
115
+ <FavoritesProvider>
116
+ <UiPreferencesRuntime
117
+ initialTheme={uiPreferences.theme}
118
+ initialFontScale={uiPreferences.fontScale}
119
+ />
120
+ <Toaster />
121
+ <NuqsAdapter>{children}</NuqsAdapter>
122
+ </FavoritesProvider>
123
+ </AppConfigProvider>
124
+ </NextIntlClientProvider>
125
+ </body>
126
+ </html>
127
+ );
91
128
  };
package/src/utils.ts CHANGED
@@ -2,8 +2,8 @@ import { UI_LANG_OPTIONS } from "@c-rex/constants";
2
2
  import { headers } from "next/headers";
3
3
  import { normalizeLanguageCode } from "@c-rex/utils";
4
4
 
5
- const getBrowserLangFromHeader = (): string => {
6
- const h = headers();
5
+ const getBrowserLangFromHeader = async (): Promise<string> => {
6
+ const h = await headers();
7
7
  const accept = h.get("accept-language"); // ex: "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7"
8
8
 
9
9
  if (!accept) return "";
@@ -12,14 +12,14 @@ const getBrowserLangFromHeader = (): string => {
12
12
  }
13
13
 
14
14
 
15
- export const resolveUILanguage = ({
15
+ export const resolveUILanguage = async ({
16
16
  uiLangCookie,
17
17
  defaultLang,
18
18
  }: {
19
19
  uiLangCookie?: string | null;
20
20
  defaultLang: string;
21
- }): string => {
22
- const browserLang = getBrowserLangFromHeader();
21
+ }): Promise<string> => {
22
+ const browserLang = await getBrowserLangFromHeader();
23
23
 
24
24
  if (uiLangCookie) return uiLangCookie;
25
25
  if (browserLang && UI_LANG_OPTIONS.includes(browserLang)) return browserLang;
@@ -27,7 +27,7 @@ export const resolveUILanguage = ({
27
27
  return defaultLang;
28
28
  }
29
29
 
30
- export const resolveContentLanguage = ({
30
+ export const resolveContentLanguage = async ({
31
31
  contentLangCookie,
32
32
  availableLanguages,
33
33
  defaultLang,
@@ -35,8 +35,8 @@ export const resolveContentLanguage = ({
35
35
  contentLangCookie?: string | null;
36
36
  availableLanguages: { value: string }[];
37
37
  defaultLang: string;
38
- }): string => {
39
- const browserLang = getBrowserLangFromHeader();
38
+ }): Promise<string> => {
39
+ const browserLang = await getBrowserLangFromHeader();
40
40
  const normalizedAvailableLanguages = availableLanguages.map((item) => normalizeLanguageCode(item.value));
41
41
  const normalizedDefaultLanguage = normalizeLanguageCode(defaultLang);
42
42
  const normalizedCookieLanguage = contentLangCookie ? normalizeLanguageCode(contentLangCookie) : "";