@next-library/theme 1.0.3 → 1.0.5

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 (39) hide show
  1. package/README.md +106 -76
  2. package/dist/client.d.ts +1 -0
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +2082 -287
  5. package/dist/client.js.map +1 -1
  6. package/dist/components/layout/doc-pager.d.ts +18 -0
  7. package/dist/components/layout/doc-pager.d.ts.map +1 -0
  8. package/dist/components/layout/documentation-layout.d.ts +2 -0
  9. package/dist/components/layout/documentation-layout.d.ts.map +1 -1
  10. package/dist/components/layout/footer.d.ts +1 -1
  11. package/dist/components/layout/footer.d.ts.map +1 -1
  12. package/dist/components/layout/navigation-bar.d.ts +3 -1
  13. package/dist/components/layout/navigation-bar.d.ts.map +1 -1
  14. package/dist/components/layout/reading-progress.d.ts +3 -0
  15. package/dist/components/layout/reading-progress.d.ts.map +1 -0
  16. package/dist/components/markdown/markdown-renderer.d.ts.map +1 -1
  17. package/dist/components/navigation/navbar/logo.d.ts.map +1 -1
  18. package/dist/components/navigation/navbar/mobile-menu.d.ts.map +1 -1
  19. package/dist/components/navigation/navbar/search-bar.d.ts.map +1 -1
  20. package/dist/components/navigation/sidebar-left/parent.d.ts.map +1 -1
  21. package/dist/components/navigation/sidebar-left/sidebar.d.ts +1 -1
  22. package/dist/components/navigation/sidebar-left/sidebar.d.ts.map +1 -1
  23. package/dist/components/navigation/sidebar-right/table-of-contents.d.ts +6 -0
  24. package/dist/components/navigation/sidebar-right/table-of-contents.d.ts.map +1 -1
  25. package/dist/components/ui/anchor-link-handler.d.ts.map +1 -1
  26. package/dist/index.js +2346 -320
  27. package/dist/index.js.map +1 -1
  28. package/dist/lib/translations/index.d.ts +3 -35
  29. package/dist/lib/translations/index.d.ts.map +1 -1
  30. package/dist/lib/translations/locale-names.d.ts +1 -1
  31. package/dist/lib/translations/locale-names.d.ts.map +1 -1
  32. package/dist/lib/translations/theme-translations-types.d.ts +35 -0
  33. package/dist/lib/translations/theme-translations-types.d.ts.map +1 -0
  34. package/dist/server.d.ts +1 -0
  35. package/dist/server.d.ts.map +1 -1
  36. package/dist/server.js +1895 -53
  37. package/dist/server.js.map +1 -1
  38. package/package.json +4 -4
  39. package/src/style.css +185 -0
package/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  Complete UI theme package for Next.js documentation framework. This package provides ready-made React components built on top of [`@next-library/core`](../core/README.md).
4
4
 
5
- > **Looking for core utilities only?** Check out [`@next-library/core`](../core/README.md) which provides content management, i18n, and SEO utilities without UI components.
5
+ > **Looking for core utilities only?** See [`@next-library/core`](../core/README.md).
6
+
7
+ > **Content tree:** Layout and nav expect the same **`PageData`** from **`extractPageData(contentTree, locale, slug)`**. Import **`contentTree`** from your generated **`lib/tree.ts`** and pass **`contentTree`** into **`NavigationBar`** (and derive **`getSupportedLocales(contentTree)`** for **`LanguageSwitcher`**). The canonical wiring is **[`example/app/`](../../example/app/)** and **[`docs/getting-started.md`](../../docs/getting-started.md)**.
6
8
 
7
9
  ## Features
8
10
 
@@ -35,6 +37,12 @@ yarn add @next-library/theme @next-library/core
35
37
  pnpm add next-themes @tailwindcss/typography
36
38
  ```
37
39
 
40
+ ### Module format (ESM vs `@next-library/core`)
41
+
42
+ `@next-library/theme` is published as **ESM-only** (`import` / `export` in `package.json` `exports`). Use it from **Next.js App Router** (or any bundler that resolves ESM) as in this repo’s [example app](../../example).
43
+
44
+ [`@next-library/core`](../core/README.md) ships **both ESM and CommonJS** (`import` and `require` via `exports`), which helps generic Node tooling and older setups. You do **not** need CJS to use the theme with Next.js; if you rely on `require('@next-library/theme')` in plain Node without a bundler, prefer importing `@next-library/core` for config/tree utilities and keep UI imports inside the Next.js bundle.
45
+
38
46
  ## Quick Start
39
47
 
40
48
  ### 1. Set Up Tailwind CSS v4
@@ -115,10 +123,18 @@ Import server components from `@next-library/theme/server`:
115
123
  ```typescript
116
124
  // app/[locale]/layout.tsx
117
125
  import { DocumentationLayout } from '@next-library/theme/server';
126
+ import { isValidLocale, type Locale } from '@next-library/core';
127
+
128
+ export default async function LocaleLayout({
129
+ children,
130
+ params,
131
+ }: {
132
+ children: React.ReactNode;
133
+ params: Promise<{ locale: string }>;
134
+ }) {
135
+ const { locale: raw } = await params;
136
+ const locale = (isValidLocale(raw) ? raw : 'en') as Locale;
118
137
 
119
- export default function LocaleLayout({ children, params }) {
120
- const { locale } = await params;
121
-
122
138
  return (
123
139
  <DocumentationLayout language={locale}>
124
140
  {children}
@@ -131,22 +147,38 @@ export default function LocaleLayout({ children, params }) {
131
147
 
132
148
  Import client components from `@next-library/theme/client`:
133
149
 
150
+ Server parent (derive locales from the generated tree):
151
+
152
+ ```typescript
153
+ import { getSupportedLocales } from '@next-library/core';
154
+ import contentTree from '@/lib/tree';
155
+ import { LocaleTools } from './locale-tools';
156
+
157
+ const availableLocales = getSupportedLocales(contentTree);
158
+ // …
159
+ <LocaleTools availableLocales={availableLocales} />;
160
+ ```
161
+
162
+ Client component:
163
+
134
164
  ```typescript
135
- // components/my-component.tsx
165
+ // app/locale-tools.tsx
136
166
  'use client';
137
167
 
138
168
  import { LanguageSwitcher, ThemeSwitcher } from '@next-library/theme/client';
139
169
 
140
- export function MyComponent() {
170
+ export function LocaleTools({ availableLocales }: { availableLocales: string[] }) {
141
171
  return (
142
172
  <div>
143
- <LanguageSwitcher availableLocales={['en', 'fr', 'de']} />
173
+ <LanguageSwitcher availableLocales={availableLocales} />
144
174
  <ThemeSwitcher />
145
175
  </div>
146
176
  );
147
177
  }
148
178
  ```
149
179
 
180
+ `NavigationBar` computes locales from **`contentTree`** when you pass **`contentTree`** (see complete example below).
181
+
150
182
  ## Component Exports
151
183
 
152
184
  ### Server Components (`@next-library/theme/server`)
@@ -204,16 +236,18 @@ export function MyComponent() {
204
236
  ```typescript
205
237
  // app/[locale]/layout.tsx
206
238
  import { DocumentationLayout } from '@next-library/theme/server';
239
+ import { isValidLocale, type Locale } from '@next-library/core';
207
240
 
208
- export default async function LocaleLayout({
209
- children,
210
- params
211
- }: {
241
+ export default async function LocaleLayout({
242
+ children,
243
+ params,
244
+ }: {
212
245
  children: React.ReactNode;
213
246
  params: Promise<{ locale: string }>;
214
247
  }) {
215
- const { locale } = await params;
216
-
248
+ const { locale: rawLocale } = await params;
249
+ const locale = (isValidLocale(rawLocale) ? rawLocale : 'en') as Locale;
250
+
217
251
  return (
218
252
  <DocumentationLayout language={locale}>
219
253
  {children}
@@ -228,52 +262,50 @@ export default async function LocaleLayout({
228
262
  // app/[locale]/docs/[[...slug]]/layout.tsx
229
263
  import { NavigationBar, LeftSidebar, RightSidebar } from '@next-library/theme/server';
230
264
  import { Breadcrumbs, AnchorLinkHandler } from '@next-library/theme/client';
231
- import { extractPageData, getSupportedLocales, type Locale } from '@next-library/core';
232
-
233
- export default async function DocsLayout({
234
- children,
235
- params
236
- }: {
265
+ import { extractPageData, isValidLocale, createConfig, type Locale } from '@next-library/core';
266
+ import { libraryConfig } from '@/library.config';
267
+ import contentTree from '@/lib/tree';
268
+
269
+ export default async function DocsLayout({
270
+ children,
271
+ params,
272
+ }: {
237
273
  children: React.ReactNode;
238
274
  params: Promise<{ locale: string; slug?: string[] }>;
239
275
  }) {
240
276
  const { locale: rawLocale, slug } = await params;
241
- const supportedLocales = getSupportedLocales();
242
- const locale = (supportedLocales.includes(rawLocale) ? rawLocale : 'en') as Locale;
277
+ const locale = (isValidLocale(rawLocale) ? rawLocale : 'en') as Locale;
243
278
  const safeSlug = Array.isArray(slug) ? slug : [];
244
-
245
- const pageData = extractPageData(locale, safeSlug);
279
+ const fullConfig = createConfig(libraryConfig);
280
+ const pageData = extractPageData(contentTree, locale, safeSlug);
281
+ const repoUrl =
282
+ fullConfig.github?.user && fullConfig.github?.repo
283
+ ? `https://github.com/${fullConfig.github.user}/${fullConfig.github.repo}`
284
+ : undefined;
246
285
 
247
286
  return (
248
287
  <div>
249
- {/* Mobile Navigation */}
250
288
  <NavigationBar
251
289
  language={locale}
252
290
  className="block lg:hidden"
253
291
  pageData={pageData}
292
+ websiteTitle={fullConfig.website?.title || 'Documentation'}
293
+ contentTree={contentTree}
294
+ repoUrl={repoUrl}
254
295
  />
255
-
256
- {/* Main Content Layout */}
257
296
  <div className="flex flex-row gap-12 w-full lg:w-[95vw] mx-auto pt-10">
258
- {/* Left Sidebar */}
259
297
  <LeftSidebar
260
298
  data={pageData}
261
299
  className="sticky top-28 hidden lg:flex lg:flex-[2] max-w-xs"
262
300
  />
263
-
264
- {/* Main Content */}
265
301
  <main className="flex flex-col lg:gap-8 gap-4 flex-1 w-full lg:flex-[6] px-4 lg:px-0">
266
302
  <Breadcrumbs data={pageData} locale={locale} />
267
303
  {children}
268
304
  </main>
269
-
270
- {/* Right Sidebar */}
271
305
  <RightSidebar
272
306
  data={pageData}
273
307
  className="sticky top-28 hidden lg:flex lg:flex-[1.5] max-w-xs"
274
308
  />
275
-
276
- {/* Anchor Link Handler */}
277
309
  <AnchorLinkHandler locale={locale} />
278
310
  </div>
279
311
  </div>
@@ -284,73 +316,69 @@ export default async function DocsLayout({
284
316
  ### Documentation Page
285
317
 
286
318
  ```typescript
287
- // app/[locale]/docs/[[...slug]]/page.tsx
288
- import { PageHeader, MarkdownRenderer, FallbackLocaleWarning } from '@next-library/theme';
289
- import { extractPageData, generateArticleSchema, generateBreadcrumbSchema, generateCollectionPageSchema, getSupportedLocales, fetchRawFileContent } from '@next-library/core';
290
- import { StructuredData } from '@next-library/theme/server';
319
+ // app/[locale]/docs/[[...slug]]/page.tsx (leaf page — folder views need FolderCards; see example app)
320
+ import {
321
+ extractPageData,
322
+ isValidLocale,
323
+ createConfig,
324
+ type Locale,
325
+ } from '@next-library/core';
326
+ import { loadDocumentationMarkdown } from '@next-library/core/server';
327
+ import { PageHeader, FallbackLocaleWarning } from '@next-library/theme/server';
328
+ import { MarkdownRenderer } from '@next-library/theme/client';
329
+ import { libraryConfig } from '@/library.config';
330
+ import contentTree from '@/lib/tree';
291
331
  import { notFound } from 'next/navigation';
292
332
 
293
- export default async function DocPage({
294
- params
295
- }: {
333
+ export default async function DocPage({
334
+ params,
335
+ }: {
296
336
  params: Promise<{ locale: string; slug?: string[] }>;
297
337
  }) {
298
338
  const { locale: rawLocale, slug } = await params;
299
- const supportedLocales = getSupportedLocales();
300
- const locale = supportedLocales.includes(rawLocale) ? rawLocale : 'en';
339
+ const locale = (isValidLocale(rawLocale) ? rawLocale : 'en') as Locale;
301
340
  const safeSlug = Array.isArray(slug) ? slug : [];
302
-
303
- const pageData = extractPageData(locale, safeSlug);
341
+ const fullConfig = createConfig(libraryConfig);
342
+ const pageData = extractPageData(contentTree, locale, safeSlug);
304
343
  const { node } = pageData;
305
344
 
306
- if (!node) {
345
+ if (!node?.githubPath || !fullConfig.github?.user || !fullConfig.github?.repo) {
307
346
  notFound();
308
347
  }
309
348
 
310
- // Fetch markdown content from GitHub
311
- const rawMarkdown = await fetchRawFileContent(node.githubPath!);
312
-
313
- // Generate structured data
314
- const articleSchema = generateArticleSchema({ /* ... */ });
315
- const breadcrumbSchema = generateBreadcrumbSchema(pageData.navigation.breadcrumbs);
316
- const collectionPageSchema = generateCollectionPageSchema({ /* ... */ });
317
-
318
- const schemas = [articleSchema, breadcrumbSchema, collectionPageSchema]
319
- .filter(Boolean)
320
- .map(schema => JSON.stringify(schema, null, 0).replace(/</g, '\\u003c'))
321
- .join('\n');
349
+ const githubConfig = {
350
+ user: fullConfig.github.user,
351
+ repo: fullConfig.github.repo,
352
+ branch: fullConfig.github.branch || 'main',
353
+ token: fullConfig.github.token,
354
+ app: fullConfig.github.app,
355
+ };
356
+ const rawMarkdown = await loadDocumentationMarkdown(node.githubPath, {
357
+ contentDir: fullConfig.tree?.contentBodiesDir,
358
+ github: githubConfig,
359
+ });
360
+ const baseUrl = fullConfig.website?.siteUrl || 'http://localhost:3000';
361
+ const pageUrl = `${baseUrl.replace(/\/$/, '')}/${locale}/docs/${safeSlug.join('/')}`;
362
+ const websiteTitle = fullConfig.website?.title || fullConfig.website?.organizationName || 'Documentation';
322
363
 
323
364
  return (
324
365
  <div>
325
- {/* Structured Data */}
326
- {schemas && (
327
- <script
328
- type="application/ld+json"
329
- dangerouslySetInnerHTML={{ __html: schemas }}
330
- />
331
- )}
332
-
333
- {/* Page Header with Copy Button */}
334
366
  <PageHeader
335
367
  title={node.title}
336
368
  markdown={rawMarkdown}
337
- pageUrl={`https://example.com/${locale}/docs/${safeSlug.join('/')}`}
338
- websiteTitle="My Documentation"
369
+ pageUrl={pageUrl}
370
+ websiteTitle={websiteTitle}
339
371
  locale={locale}
340
372
  />
341
-
342
- {/* Fallback Warning */}
343
- {node.fallback && (
344
- <FallbackLocaleWarning locale={locale} />
345
- )}
346
-
347
- {/* Markdown Content */}
373
+ {node.fallback && <FallbackLocaleWarning locale={locale} />}
348
374
  <MarkdownRenderer markdown={rawMarkdown} />
349
375
  </div>
350
376
  );
351
377
  }
352
378
  ```
353
379
 
380
+ For **JSON-LD**, **`generateMetadata`**, **folder `index` views** (`FolderCards`), and error handling, copy from **`example/app/[locale]/docs/[[...slug]]/page.tsx`** in the monorepo.
381
+
354
382
  ## Internationalization
355
383
 
356
384
  The theme package includes translations for 20+ languages. Components automatically use translations based on the `locale` prop:
@@ -467,10 +495,12 @@ interface DocumentationLayoutProps {
467
495
 
468
496
  ```typescript
469
497
  interface NavigationBarProps {
470
- language: Locale;
498
+ language?: Locale;
471
499
  className?: string;
472
500
  pageData?: PageData;
473
501
  websiteTitle?: string;
502
+ contentTree?: ContentTree;
503
+ repoUrl?: string;
474
504
  }
475
505
  ```
476
506
 
package/dist/client.d.ts CHANGED
@@ -41,4 +41,5 @@ export { BreadcrumbToggle } from './components/ui/breadcrumb-toggle';
41
41
  export * from './components/ui/sidebar';
42
42
  export { useMediaQuery } from './hooks/use-media-query';
43
43
  export { useIsMobile } from './hooks/use-mobile';
44
+ export { ReadingProgress } from './components/layout/reading-progress';
44
45
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAGH,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,qCAAqC,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,MAAM,2CAA2C,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AAGxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,yDAAyD,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2DAA2D,CAAC;AAG/F,OAAO,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AAGxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAYxE,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAKnE,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAGH,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,qCAAqC,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,MAAM,2CAA2C,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AAGxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,qDAAqD,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,yDAAyD,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2DAA2D,CAAC;AAG/F,OAAO,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AAGxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAYxE,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAKnE,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIjD,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC"}