@lexibase/rdx-next 5.1.2 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,8 +50,8 @@ through `@lexibase/rdx-ui`: logo, navbar, Base UI version dropdown, mobile/deskt
50
50
  sidebar, landing page, MDX styles and theme provider. The adapter owns content
51
51
  and route data; it does not implement a parallel UI theme.
52
52
 
53
- Use `homepage: { enabled: true }` in `rdx.config.ts` for the centered-logo
54
- homepage, or import a project-owned React component with `homepage.component`.
53
+ Use `homepage: { enabled: true }` in `rdx.config.ts` for the built-in landing
54
+ page, or import a project-owned React component with `homepage.component`.
55
55
  Without the option, `/` redirects to `/docs`. Additional content sources from
56
56
  explicitly configured plugins enable the shared navbar dropdown.
57
57
 
@@ -11,6 +11,7 @@ const generated = [
11
11
  ...defaultFiles.map((file) => `app/(rdx-default)/${file}`),
12
12
  'app/(rdx-default)/[...notFound]/page.tsx',
13
13
  'app/(rdx-locales)/[locale]/layout.tsx',
14
+ 'app/(rdx-locales)/[locale]/page.tsx',
14
15
  'app/(rdx-locales)/[locale]/not-found.tsx',
15
16
  'app/(rdx-locales)/[locale]/docs/[[...slug]]/page.tsx',
16
17
  'app/(rdx-locales)/[locale]/rdx-search/[source]/route.ts',
@@ -107,6 +108,61 @@ export async function generateMetadata({ params }: { params: Promise<{ locale: s
107
108
  export default async function Layout({ children, params }: { children: React.ReactNode, params: Promise<{ locale: string }> }) {
108
109
  return <RdxLayout config={await configuration(params)} bodyClassName="antialiased">{children}</RdxLayout>
109
110
  }
111
+ `
112
+ )
113
+ const homeRoute = 'app/(rdx-locales)/[locale]/page.tsx'
114
+ const localizedHomes = []
115
+ if (project.config.homepage?.enabled) {
116
+ for (const locale of project.localization.locales) {
117
+ if (!locale.folder || locale.code === project.localization.defaultLocale)
118
+ continue
119
+
120
+ const file = path.join(
121
+ project.rootDir,
122
+ 'locale',
123
+ locale.folder,
124
+ 'home.tsx'
125
+ )
126
+ const exists = await stat(file).then(
127
+ (entry) => entry.isFile(),
128
+ (error) => {
129
+ if (error.code === 'ENOENT' || error.code === 'ENOTDIR') return false
130
+ throw error
131
+ }
132
+ )
133
+ if (!exists) continue
134
+
135
+ // Literal imports let Next compile and trace project-owned components.
136
+ const specifier = path
137
+ .relative(path.dirname(path.join(runtime, homeRoute)), file)
138
+ .split(path.sep)
139
+ .join('/')
140
+ .slice(0, -'.tsx'.length)
141
+ localizedHomes.push(
142
+ ` case ${JSON.stringify(locale.path)}: return (await import(${JSON.stringify(specifier)})).default`
143
+ )
144
+ }
145
+ }
146
+ await emit(
147
+ homeRoute,
148
+ `import { HomePage, getLocalizedProject } from '${provider}'
149
+ import { notFound, permanentRedirect } from 'next/navigation'
150
+ import { getProject } from '../../../rdx-project'
151
+ async function getLocalizedHome(locale: string) {
152
+ switch (locale) {
153
+ ${localizedHomes.join('\n')}
154
+ default: return undefined
155
+ }
156
+ }
157
+ export default async function Page({ params }: { params: Promise<{ locale: string }> }) {
158
+ const project = await getProject()
159
+ const { locale } = await params
160
+ const selected = project.localization?.locales.find(entry => entry.path === locale)
161
+ if (!project.config.homepage?.enabled || !selected) notFound()
162
+ if (selected.code === project.localization!.defaultLocale) permanentRedirect('/')
163
+ const component = await getLocalizedHome(locale)
164
+ return <HomePage project={getLocalizedProject(project, locale)} component={component} />
165
+ }
110
166
  `
111
167
  )
112
168
  await emit(
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export { defineConfig } from '@lexibase/rdx-core/config';
2
- export { RDXConfig, RdxHomepage, RdxMetadata, RdxPlugin, RdxPluginContext, RdxRuntimeConfig } from '@lexibase/rdx-types';
2
+ export { RDXConfig, RdxHomepage, RdxHomepageProps, RdxMetadata, RdxPlugin, RdxPluginContext, RdxRuntimeConfig } from '@lexibase/rdx-types';
@@ -47,8 +47,9 @@ declare function RdxLayout({ children, config, bodyClassName, }: {
47
47
  config: RDXConfig;
48
48
  bodyClassName?: string;
49
49
  }): react.JSX.Element;
50
- declare function HomePage({ project }: {
50
+ declare function HomePage({ project, component, }: {
51
51
  project: RdxProject;
52
+ component?: NonNullable<RDXConfig['homepage']>['component'];
52
53
  }): react.JSX.Element;
53
54
  declare function NotFoundPage({ project }: {
54
55
  project: RdxProject;
@@ -1,6 +1,7 @@
1
1
  // src/runtime/index.tsx
2
2
  import {
3
3
  getDocument as getDocument4,
4
+ getDocsIndex as getDocsIndex4,
4
5
  getDocsPaths,
5
6
  getSourceOptions as getSourceOptions5,
6
7
  resolveDocsRoute as resolveDocsRoute2,
@@ -17,7 +18,7 @@ import { DocsSidebar } from "@lexibase/rdx-ui/components/docs-sidebar";
17
18
  import { DocsToc } from "@lexibase/rdx-ui/components/docs-toc";
18
19
  import { DocsPageTransition } from "@lexibase/rdx-ui/components/docs-page-transition";
19
20
  import { DocsSearch } from "@lexibase/rdx-ui/components/docs-search";
20
- import { Home } from "@lexibase/rdx-ui/components/home";
21
+ import { Home, HomeSection } from "@lexibase/rdx-ui/components/home";
21
22
  import { SkipLink } from "@lexibase/rdx-ui/components/skip-link";
22
23
  import { FooterCredit } from "@lexibase/rdx-ui/components/footer-credit";
23
24
  import { EditPageLink } from "@lexibase/rdx-ui/components/edit-page-link";
@@ -429,9 +430,13 @@ function RdxLayout({
429
430
  }
430
431
  ) }) });
431
432
  }
433
+ function homepageHref(project, locale) {
434
+ return locale && locale.code !== project.localization?.defaultLocale ? `/${locale.path}` : "/";
435
+ }
432
436
  function RdxHeader({
433
437
  project,
434
- slug
438
+ slug,
439
+ onHomepage = false
435
440
  }) {
436
441
  const { config } = project;
437
442
  const messages = getMessages(config.lang);
@@ -460,14 +465,18 @@ function RdxHeader({
460
465
  ) : void 0,
461
466
  siteTitle: config.metadata.applicationName,
462
467
  logo: /* @__PURE__ */ jsx(BrandLogo, { source: config.navbar?.logo, className: "size-5" }),
463
- homeHref: config.homepage?.enabled ? "/" : getDocsHref4(project),
468
+ homeHref: config.homepage?.enabled ? homepageHref(project, project.locale) : getDocsHref4(project),
464
469
  docsHref: getDocsHref4(project, source),
465
470
  languageMenu: project.localization ? /* @__PURE__ */ jsx(
466
471
  LanguageDropdown,
467
472
  {
468
473
  lang: config.lang,
469
474
  current: project.locale?.code ?? project.localization.defaultLocale,
470
- options: getLanguageLinks(project, source, currentSlug),
475
+ options: onHomepage ? project.localization.locales.map((locale) => ({
476
+ code: locale.code,
477
+ label: locale.label,
478
+ href: homepageHref(project, locale)
479
+ })) : getLanguageLinks(project, source, currentSlug),
471
480
  contributionUrl: project.localization.contributionUrl
472
481
  }
473
482
  ) : void 0,
@@ -477,32 +486,68 @@ function RdxHeader({
477
486
  }
478
487
  );
479
488
  }
480
- function HomePage({ project }) {
489
+ function HomePage({
490
+ project,
491
+ component
492
+ }) {
481
493
  const { config } = project;
482
- if (!config.homepage?.enabled) redirect(getDocsHref4(project));
494
+ const docsHref = getDocsHref4(project);
495
+ if (!config.homepage?.enabled) redirect(docsHref);
483
496
  const homepage = config.homepage;
484
- const CustomHome = homepage.component;
497
+ const CustomHome = component ?? homepage.component;
498
+ const docsLabel = getMessages(config.lang).docs;
499
+ const source = project.sources[0];
500
+ const categories = CustomHome ? [] : getDocsIndex4(getSourceOptions5(project, source));
501
+ const firstPage = categories[0]?.pages[0];
485
502
  return /* @__PURE__ */ jsxs(Fragment, { children: [
486
- /* @__PURE__ */ jsx(RdxHeader, { project }),
503
+ /* @__PURE__ */ jsx(RdxHeader, { project, onHomepage: true }),
487
504
  /* @__PURE__ */ jsx(
488
505
  "main",
489
506
  {
490
507
  id: "rdx-main",
491
508
  tabIndex: -1,
492
- className: "flex-1 min-h-0 overflow-y-auto",
493
- children: CustomHome ? /* @__PURE__ */ jsx(CustomHome, {}) : /* @__PURE__ */ jsx(
509
+ className: "relative flex-1 min-h-0 overflow-y-auto",
510
+ children: CustomHome ? /* @__PURE__ */ jsx(CustomHome, { lang: config.lang, docsHref }) : /* @__PURE__ */ jsx(
494
511
  Home,
495
512
  {
496
513
  title: homepage.title ?? config.metadata.applicationName,
497
- logo: /* @__PURE__ */ jsx(
498
- BrandLogo,
514
+ logo: /* @__PURE__ */ jsx(BrandLogo, { source: config.navbar?.logo, className: "size-5" }),
515
+ description: homepage.description ?? config.description,
516
+ buttons: homepage.buttons?.map((button) => ({
517
+ ...button,
518
+ href: project.locale && /^\/docs(?:[/?#]|$)/.test(button.href) ? `/${project.locale.path}${button.href}` : button.href
519
+ })) ?? [{ label: docsLabel, href: docsHref }],
520
+ previewTitle: firstPage?.title,
521
+ previewDescription: firstPage?.description,
522
+ children: categories.length > 0 && /* @__PURE__ */ jsx(
523
+ HomeSection,
499
524
  {
500
- source: config.navbar?.logo,
501
- className: "size-52 hover:scale-105 hover:rotate-1 transition-[scale,rotation] duration-1000"
525
+ "aria-labelledby": "home-docs-title",
526
+ className: "border-t bg-muted/20",
527
+ children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-6xl", children: [
528
+ /* @__PURE__ */ jsx(
529
+ "h2",
530
+ {
531
+ id: "home-docs-title",
532
+ className: "text-3xl font-semibold tracking-tight sm:text-4xl",
533
+ children: docsLabel
534
+ }
535
+ ),
536
+ /* @__PURE__ */ jsx("ul", { className: "mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3", children: categories.map((category) => {
537
+ const page = category.pages[0];
538
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
539
+ Button,
540
+ {
541
+ href: getDocsHref4(project, source, page.slug),
542
+ variant: "link",
543
+ className: "h-auto whitespace-normal p-0 text-left",
544
+ children: category.title
545
+ }
546
+ ) }, category.id);
547
+ }) })
548
+ ] })
502
549
  }
503
- ),
504
- description: homepage.description,
505
- buttons: homepage.buttons
550
+ )
506
551
  }
507
552
  )
508
553
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lexibase/rdx-next",
3
- "version": "5.1.2",
3
+ "version": "5.2.0",
4
4
  "description": "The Next.js runtime for RDX documentation projects.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -52,8 +52,8 @@
52
52
  "next-mdx-remote": "^6.0.0",
53
53
  "remark-gfm": "^4",
54
54
  "typescript": "6.0.3",
55
- "@lexibase/rdx-core": "3.1.0",
56
- "@lexibase/rdx-types": "2.4.0"
55
+ "@lexibase/rdx-core": "3.1.1",
56
+ "@lexibase/rdx-types": "2.5.0"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "@lexibase/rdx-ui": "^3.5.0",
@@ -81,9 +81,9 @@
81
81
  "next": "^16.4.2",
82
82
  "react": "19.3.1",
83
83
  "react-dom": "19.3.1",
84
- "@lexibase/rdx-ui": "3.5.3",
85
- "@rdx/typescript-config": "1.0.0",
86
- "@rdx/eslint-config": "1.0.0"
84
+ "@lexibase/rdx-ui": "3.5.4",
85
+ "@rdx/eslint-config": "1.0.0",
86
+ "@rdx/typescript-config": "1.0.0"
87
87
  },
88
88
  "scripts": {
89
89
  "dev": "tsup src/index.ts src/runtime/index.tsx --format esm --dts --watch --external @lexibase/rdx-core --external @lexibase/rdx-types --external @lexibase/rdx-ui --external next --external react --external react-dom --external next-mdx-remote",
@@ -5,3 +5,4 @@
5
5
  @source '../../components/**/*.{ts,tsx}';
6
6
  @source '../../docs/**/*.mdx';
7
7
  @source '../../locale/*/docs/**/*.mdx';
8
+ @source '../../locale/*/home.tsx';