@djangocfg/ui-nextjs 2.1.178 → 2.1.180
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 +58 -24
- package/package.json +7 -5
- package/src/blocks/ArticleCard.tsx +3 -1
- package/src/blocks/Hero.tsx +2 -1
- package/src/blocks/SplitHero/SplitHeroContent.tsx +2 -1
- package/src/blocks/SuperHero.tsx +3 -1
- package/src/components/breadcrumb-navigation.tsx +1 -1
- package/src/components/breadcrumb.tsx +1 -1
- package/src/components/dropdown-menu.tsx +1 -1
- package/src/components/next-link.tsx +12 -8
- package/src/components/pagination.tsx +1 -1
- package/src/components/sidebar.tsx +1 -1
- package/src/components/ssr-pagination.tsx +1 -1
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useNavigation.ts +20 -0
- package/src/lib/navigation.ts +17 -0
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Next.js UI library extending `@djangocfg/ui-core` with 69+ components built on Radix UI + Tailwind CSS v4.
|
|
4
4
|
|
|
5
|
+
All navigation components are **locale-aware** via `next-intl` — links automatically include the locale prefix (e.g. `/ru/dashboard`).
|
|
6
|
+
|
|
5
7
|
**Part of [DjangoCFG](https://djangocfg.com)** — modern Django framework for production-ready SaaS applications.
|
|
6
8
|
|
|
7
9
|
**[Live Demo & Props](https://djangocfg.com/demo/)**
|
|
@@ -12,12 +14,15 @@ Next.js UI library extending `@djangocfg/ui-core` with 69+ components built on R
|
|
|
12
14
|
pnpm add @djangocfg/ui-nextjs
|
|
13
15
|
```
|
|
14
16
|
|
|
17
|
+
Peer dependencies: `next`, `next-intl`, `react`, `tailwindcss`.
|
|
18
|
+
|
|
15
19
|
## Architecture
|
|
16
20
|
|
|
17
21
|
```
|
|
18
22
|
@djangocfg/ui-nextjs
|
|
19
23
|
├── Re-exports everything from @djangocfg/ui-core (60 components, 13 hooks)
|
|
20
|
-
├── + Next.js
|
|
24
|
+
├── + Next.js locale-aware components (11)
|
|
25
|
+
├── + Navigation hooks (useNavigation, useRouter, usePathname)
|
|
21
26
|
├── + Browser storage hooks (2)
|
|
22
27
|
├── + Blocks, Theme, Animations
|
|
23
28
|
```
|
|
@@ -25,7 +30,7 @@ pnpm add @djangocfg/ui-nextjs
|
|
|
25
30
|
| Package | Use Case |
|
|
26
31
|
|---------|----------|
|
|
27
32
|
| `@djangocfg/ui-core` | Electron, Vite, CRA, any React app |
|
|
28
|
-
| `@djangocfg/ui-nextjs` | Next.js apps (includes ui-core +
|
|
33
|
+
| `@djangocfg/ui-nextjs` | Next.js apps (includes ui-core + locale-aware navigation) |
|
|
29
34
|
|
|
30
35
|
## Components
|
|
31
36
|
|
|
@@ -34,25 +39,27 @@ All components from `@djangocfg/ui-core` are re-exported.
|
|
|
34
39
|
|
|
35
40
|
### Next.js Specific (11)
|
|
36
41
|
|
|
37
|
-
| Component |
|
|
42
|
+
| Component | Description |
|
|
38
43
|
|-----------|-------------|
|
|
39
|
-
| `NextLink` |
|
|
40
|
-
| `NextButtonLink` | Button-styled
|
|
41
|
-
| `Sidebar` |
|
|
42
|
-
| `Breadcrumb` |
|
|
43
|
-
| `BreadcrumbNavigation` |
|
|
44
|
-
| `NavigationMenu` |
|
|
45
|
-
| `Menubar` |
|
|
46
|
-
| `DropdownMenu` |
|
|
47
|
-
| `Pagination` |
|
|
48
|
-
| `SSRPagination` |
|
|
44
|
+
| `NextLink` | Locale-aware link wrapper |
|
|
45
|
+
| `NextButtonLink` | Button-styled locale-aware link with variants |
|
|
46
|
+
| `Sidebar` | Locale-aware navigation sidebar |
|
|
47
|
+
| `Breadcrumb` | Locale-aware breadcrumbs |
|
|
48
|
+
| `BreadcrumbNavigation` | High-level breadcrumb component |
|
|
49
|
+
| `NavigationMenu` | Locale-aware navigation menu |
|
|
50
|
+
| `Menubar` | Locale-aware menubar |
|
|
51
|
+
| `DropdownMenu` | Menu with locale-aware link items |
|
|
52
|
+
| `Pagination` | Locale-aware page links |
|
|
53
|
+
| `SSRPagination` | Server-compatible pagination |
|
|
49
54
|
| `DownloadButton` | Uses `localStorage` for auth |
|
|
50
55
|
|
|
56
|
+
All link-based components use `next-intl` internally — no configuration needed.
|
|
57
|
+
|
|
51
58
|
### MultiSelect Pro
|
|
52
59
|
`MultiSelectPro` `MultiSelectProAsync` — Advanced multi-select with async loading
|
|
53
60
|
|
|
54
61
|
### Blocks (7)
|
|
55
|
-
`Hero` `SuperHero` `
|
|
62
|
+
`Hero` `SuperHero` `SplitHero` `ArticleCard` `FeatureSection` `CTASection` `StatsSection`
|
|
56
63
|
|
|
57
64
|
```tsx
|
|
58
65
|
import { Hero } from '@djangocfg/ui-nextjs/blocks';
|
|
@@ -60,6 +67,24 @@ import { Hero } from '@djangocfg/ui-nextjs/blocks';
|
|
|
60
67
|
|
|
61
68
|
## Hooks
|
|
62
69
|
|
|
70
|
+
### Navigation (locale-aware)
|
|
71
|
+
|
|
72
|
+
| Hook | Description |
|
|
73
|
+
|------|-------------|
|
|
74
|
+
| `useNavigation` | Returns `{ router, pathname, redirect }` — all locale-aware |
|
|
75
|
+
| `useRouter` | Locale-aware router (`router.push('/page')` → `/ru/page`) |
|
|
76
|
+
| `usePathname` | Current pathname without locale prefix |
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { useNavigation } from '@djangocfg/ui-nextjs/hooks';
|
|
80
|
+
|
|
81
|
+
function MyComponent() {
|
|
82
|
+
const { router, pathname } = useNavigation();
|
|
83
|
+
// pathname: "/dashboard" (not "/ru/dashboard")
|
|
84
|
+
// router.push('/settings') → navigates to /ru/settings
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
63
88
|
### From ui-core (13)
|
|
64
89
|
|
|
65
90
|
| Hook | Description |
|
|
@@ -78,14 +103,13 @@ import { Hero } from '@djangocfg/ui-nextjs/blocks';
|
|
|
78
103
|
| `useBrowserDetect` | Browser detection |
|
|
79
104
|
| `useDeviceDetect` | Device detection |
|
|
80
105
|
|
|
81
|
-
### Next.js Specific (
|
|
106
|
+
### Next.js Specific (3)
|
|
82
107
|
|
|
83
108
|
| Hook | Description |
|
|
84
109
|
|------|-------------|
|
|
85
110
|
| `useResolvedTheme` | Light/dark theme resolution (next-themes) |
|
|
86
111
|
| `useLocalStorage` | Persistent state in localStorage |
|
|
87
|
-
|
|
88
|
-
Note: `useSessionStorage` is also available in ui-core.
|
|
112
|
+
| `useSessionStorage` | Persistent state in sessionStorage |
|
|
89
113
|
|
|
90
114
|
## Dialog Service
|
|
91
115
|
|
|
@@ -102,20 +126,23 @@ See ui-core README for full documentation.
|
|
|
102
126
|
```tsx
|
|
103
127
|
import {
|
|
104
128
|
Button, Card, Input, // from ui-core
|
|
105
|
-
NextButtonLink, Sidebar // Next.js
|
|
129
|
+
NextButtonLink, Sidebar // Next.js locale-aware
|
|
106
130
|
} from '@djangocfg/ui-nextjs';
|
|
107
|
-
import { useLocalStorage } from '@djangocfg/ui-nextjs/hooks';
|
|
131
|
+
import { useNavigation, useLocalStorage } from '@djangocfg/ui-nextjs/hooks';
|
|
108
132
|
|
|
109
133
|
function Example() {
|
|
134
|
+
const { router, pathname } = useNavigation();
|
|
110
135
|
const [saved, setSaved] = useLocalStorage('form', null);
|
|
111
136
|
|
|
112
137
|
return (
|
|
113
138
|
<Sidebar>
|
|
114
139
|
<Card>
|
|
115
140
|
<Input placeholder="Email" />
|
|
116
|
-
<Button>
|
|
117
|
-
|
|
118
|
-
|
|
141
|
+
<Button onClick={() => router.push('/dashboard')}>
|
|
142
|
+
Submit
|
|
143
|
+
</Button>
|
|
144
|
+
<NextButtonLink href="/docs" variant="outline">
|
|
145
|
+
Documentation
|
|
119
146
|
</NextButtonLink>
|
|
120
147
|
</Card>
|
|
121
148
|
</Sidebar>
|
|
@@ -129,7 +156,7 @@ function Example() {
|
|
|
129
156
|
import { NextButtonLink } from '@djangocfg/ui-nextjs';
|
|
130
157
|
import { ArrowLeft, Settings } from 'lucide-react';
|
|
131
158
|
|
|
132
|
-
// Basic
|
|
159
|
+
// Basic — automatically gets locale prefix
|
|
133
160
|
<NextButtonLink href="/dashboard">Dashboard</NextButtonLink>
|
|
134
161
|
|
|
135
162
|
// With variants
|
|
@@ -147,6 +174,11 @@ import { ArrowLeft, Settings } from 'lucide-react';
|
|
|
147
174
|
<NextButtonLink href="/page" prefetch={false} replace scroll={false}>
|
|
148
175
|
Navigate
|
|
149
176
|
</NextButtonLink>
|
|
177
|
+
|
|
178
|
+
// With locale override
|
|
179
|
+
<NextButtonLink href="/docs" locale="en">
|
|
180
|
+
English Docs
|
|
181
|
+
</NextButtonLink>
|
|
150
182
|
```
|
|
151
183
|
|
|
152
184
|
## Styling
|
|
@@ -185,6 +217,7 @@ mediaLog.buffer(buffered, duration);
|
|
|
185
217
|
| `@djangocfg/ui-nextjs/blocks` | Landing page blocks |
|
|
186
218
|
| `@djangocfg/ui-nextjs/lib` | Logger, utilities |
|
|
187
219
|
| `@djangocfg/ui-nextjs/theme` | ThemeProvider, ThemeToggle |
|
|
220
|
+
| `@djangocfg/ui-nextjs/animations` | Background animations |
|
|
188
221
|
| `@djangocfg/ui-nextjs/styles` | CSS |
|
|
189
222
|
|
|
190
223
|
## Theme
|
|
@@ -210,9 +243,10 @@ function App({ children }) {
|
|
|
210
243
|
|
|
211
244
|
## Requirements
|
|
212
245
|
|
|
213
|
-
- Next.js >=
|
|
246
|
+
- Next.js >= 16
|
|
214
247
|
- React >= 19
|
|
215
248
|
- Tailwind CSS >= 4
|
|
249
|
+
- next-intl >= 4
|
|
216
250
|
|
|
217
251
|
---
|
|
218
252
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-nextjs",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.180",
|
|
4
4
|
"description": "Next.js UI component library with Radix UI primitives, Tailwind CSS styling, charts, and form components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-components",
|
|
@@ -80,15 +80,16 @@
|
|
|
80
80
|
"check": "tsc --noEmit"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
|
-
"@djangocfg/api": "^2.1.
|
|
84
|
-
"@djangocfg/ui-core": "^2.1.
|
|
85
|
-
"@djangocfg/ui-tools": "^2.1.
|
|
83
|
+
"@djangocfg/api": "^2.1.180",
|
|
84
|
+
"@djangocfg/ui-core": "^2.1.180",
|
|
85
|
+
"@djangocfg/ui-tools": "^2.1.180",
|
|
86
86
|
"@types/react": "^19.1.0",
|
|
87
87
|
"@types/react-dom": "^19.1.0",
|
|
88
88
|
"consola": "^3.4.2",
|
|
89
89
|
"lucide-react": "^0.545.0",
|
|
90
90
|
"moment": "^2.30.1",
|
|
91
91
|
"next": "^16.0.10",
|
|
92
|
+
"next-intl": "^4.8.3",
|
|
92
93
|
"react": "^19.1.0",
|
|
93
94
|
"react-dom": "^19.1.0",
|
|
94
95
|
"react-hook-form": "^7.69.0",
|
|
@@ -104,13 +105,14 @@
|
|
|
104
105
|
"react-chartjs-2": "^5.3.0"
|
|
105
106
|
},
|
|
106
107
|
"devDependencies": {
|
|
107
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
108
|
+
"@djangocfg/typescript-config": "^2.1.180",
|
|
108
109
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
109
110
|
"@radix-ui/react-slot": "^1.2.4",
|
|
110
111
|
"@types/node": "^24.7.2",
|
|
111
112
|
"class-variance-authority": "^0.7.1",
|
|
112
113
|
"eslint": "^9.37.0",
|
|
113
114
|
"tailwindcss-animate": "1.0.7",
|
|
115
|
+
"next-intl": "^4.8.3",
|
|
114
116
|
"typescript": "^5.9.3",
|
|
115
117
|
"zustand": "^5.0.9"
|
|
116
118
|
},
|
|
@@ -2,8 +2,10 @@ import React from 'react';
|
|
|
2
2
|
import moment from 'moment';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
Badge,
|
|
5
|
+
Badge, Card, CardContent, CardDescription, CardHeader, CardTitle
|
|
6
6
|
} from '@djangocfg/ui-core/components';
|
|
7
|
+
|
|
8
|
+
import { NextButtonLink as ButtonLink } from '../components/next-link';
|
|
7
9
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
8
10
|
|
|
9
11
|
export type ArticleType = 'security' | 'release' | 'announcement' | 'feature';
|
package/src/blocks/Hero.tsx
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import { ButtonLink } from '@djangocfg/ui-core/components';
|
|
4
3
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
5
4
|
|
|
5
|
+
import { NextButtonLink as ButtonLink } from '../components/next-link';
|
|
6
|
+
|
|
6
7
|
interface HeroProps {
|
|
7
8
|
title: string;
|
|
8
9
|
subtitle?: string;
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { ArrowRight, Sparkles } from 'lucide-react';
|
|
5
|
-
import { ButtonLink } from '@djangocfg/ui-core/components';
|
|
6
5
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
6
|
+
|
|
7
|
+
import { NextButtonLink as ButtonLink } from '../../components/next-link';
|
|
7
8
|
import type { SplitHeroBadge, SplitHeroAction, SplitHeroFeature } from './types';
|
|
8
9
|
|
|
9
10
|
interface SplitHeroContentProps {
|
package/src/blocks/SuperHero.tsx
CHANGED
|
@@ -4,8 +4,10 @@ import { ArrowRight, Sparkles, Wand2 } from 'lucide-react';
|
|
|
4
4
|
import React from 'react';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
Button,
|
|
7
|
+
Button, CopyButton, Sticky, Tooltip, TooltipContent, TooltipTrigger
|
|
8
8
|
} from '@djangocfg/ui-core/components';
|
|
9
|
+
|
|
10
|
+
import { NextButtonLink as ButtonLink } from '../components/next-link';
|
|
9
11
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
10
12
|
|
|
11
13
|
import { AnimatedBackground, BackgroundVariant} from '../animations';
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import type { LinkProps as NextLinkBaseProps } from 'next/link';
|
|
5
|
+
import { Link } from '../lib/navigation';
|
|
6
6
|
import { buttonVariants } from '@djangocfg/ui-core/components';
|
|
7
7
|
import type { VariantProps } from 'class-variance-authority';
|
|
8
8
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
9
9
|
|
|
10
|
+
type IntlLinkProps = React.ComponentProps<typeof Link>;
|
|
11
|
+
|
|
10
12
|
// ============================================================================
|
|
11
13
|
// NextLink - Styled Next.js Link (text link style)
|
|
12
14
|
// ============================================================================
|
|
13
15
|
|
|
14
16
|
export interface NextLinkProps
|
|
15
|
-
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof
|
|
16
|
-
|
|
17
|
+
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof NextLinkBaseProps>,
|
|
18
|
+
NextLinkBaseProps {
|
|
19
|
+
locale?: string;
|
|
17
20
|
children?: React.ReactNode;
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -29,7 +32,7 @@ export interface NextLinkProps
|
|
|
29
32
|
const NextLink = React.forwardRef<HTMLAnchorElement, NextLinkProps>(
|
|
30
33
|
({ children, ...props }, ref) => {
|
|
31
34
|
return (
|
|
32
|
-
<Link ref={ref} {...props}>
|
|
35
|
+
<Link ref={ref} {...props as IntlLinkProps}>
|
|
33
36
|
{children}
|
|
34
37
|
</Link>
|
|
35
38
|
);
|
|
@@ -42,9 +45,10 @@ NextLink.displayName = 'NextLink';
|
|
|
42
45
|
// ============================================================================
|
|
43
46
|
|
|
44
47
|
export interface NextButtonLinkProps
|
|
45
|
-
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof
|
|
46
|
-
|
|
48
|
+
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof NextLinkBaseProps>,
|
|
49
|
+
NextLinkBaseProps,
|
|
47
50
|
VariantProps<typeof buttonVariants> {
|
|
51
|
+
locale?: string;
|
|
48
52
|
children?: React.ReactNode;
|
|
49
53
|
}
|
|
50
54
|
|
|
@@ -75,7 +79,7 @@ const NextButtonLink = React.forwardRef<HTMLAnchorElement, NextButtonLinkProps>(
|
|
|
75
79
|
<Link
|
|
76
80
|
className={cn(buttonVariants({ variant, size, className }))}
|
|
77
81
|
ref={ref}
|
|
78
|
-
{...props}
|
|
82
|
+
{...props as IntlLinkProps}
|
|
79
83
|
>
|
|
80
84
|
{children}
|
|
81
85
|
</Link>
|
package/src/hooks/index.ts
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
'use client';
|
|
7
7
|
|
|
8
|
+
// Locale-aware navigation hooks (next-intl)
|
|
9
|
+
export { useRouter, usePathname } from '../lib/navigation';
|
|
10
|
+
export { useNavigation } from './useNavigation';
|
|
11
|
+
|
|
8
12
|
// Theme hook (standalone, no provider required)
|
|
9
13
|
export { useResolvedTheme } from './useResolvedTheme';
|
|
10
14
|
export type { ResolvedTheme } from './useResolvedTheme';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useRouter, usePathname, redirect } from '../lib/navigation';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Locale-aware navigation hook.
|
|
7
|
+
*
|
|
8
|
+
* Returns router, pathname (without locale prefix), and redirect —
|
|
9
|
+
* all automatically scoped to the current locale.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const { router, pathname } = useNavigation();
|
|
13
|
+
* router.push('/dashboard'); // → /ru/dashboard when locale is "ru"
|
|
14
|
+
*/
|
|
15
|
+
export function useNavigation() {
|
|
16
|
+
const router = useRouter();
|
|
17
|
+
const pathname = usePathname();
|
|
18
|
+
|
|
19
|
+
return { router, pathname, redirect };
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal navigation utilities for ui-nextjs
|
|
3
|
+
*
|
|
4
|
+
* Uses next-intl's createNavigation() to produce locale-aware
|
|
5
|
+
* Link, usePathname, useRouter, etc.
|
|
6
|
+
*
|
|
7
|
+
* These are used internally by ui-nextjs components (breadcrumb, pagination, sidebar, etc.)
|
|
8
|
+
* so that all links automatically include the locale prefix.
|
|
9
|
+
*/
|
|
10
|
+
import { createNavigation } from 'next-intl/navigation';
|
|
11
|
+
|
|
12
|
+
export const {
|
|
13
|
+
Link,
|
|
14
|
+
usePathname,
|
|
15
|
+
useRouter,
|
|
16
|
+
redirect,
|
|
17
|
+
} = createNavigation();
|