@abpjs/theme-basic 0.7.6
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/LICENSE +165 -0
- package/README.md +680 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/block.d.ts +1 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/index.d.ts +10 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/language-selector.d.ts +8 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/logo.d.ts +15 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/nav-links.d.ts +12 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/navbar.d.ts +7 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/search-context.d.ts +20 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/search-field.d.ts +1 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/sidebar-link.d.ts +16 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/sidebar.d.ts +26 -0
- package/dist/components/blocks/sidebars/sidebar-with-collapsible/user-profile.d.ts +8 -0
- package/dist/components/change-password/ChangePassword.d.ts +26 -0
- package/dist/components/change-password/index.d.ts +1 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/components/layout/Layout.d.ts +30 -0
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/layout-account/LayoutAccount.d.ts +45 -0
- package/dist/components/layout-account/index.d.ts +1 -0
- package/dist/components/layout-application/LayoutApplication.d.ts +60 -0
- package/dist/components/layout-application/index.d.ts +1 -0
- package/dist/components/layout-empty/LayoutEmpty.d.ts +23 -0
- package/dist/components/layout-empty/index.d.ts +1 -0
- package/dist/components/profile/Profile.d.ts +28 -0
- package/dist/components/profile/index.d.ts +1 -0
- package/dist/contexts/branding.context.d.ts +67 -0
- package/dist/contexts/index.d.ts +2 -0
- package/dist/contexts/layout.context.d.ts +60 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +1466 -0
- package/dist/index.mjs +1435 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/layout.d.ts +26 -0
- package/dist/providers/ThemeBasicProvider.d.ts +92 -0
- package/dist/providers/index.d.ts +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
# @abpjs/theme-basic
|
|
2
|
+
|
|
3
|
+
> Basic layout components for ABP Framework in React
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@abpjs/theme-basic)
|
|
6
|
+
[](https://docs.abpjs.io/docs/packages/theme-basic/overview)
|
|
7
|
+
[](https://www.gnu.org/licenses/lgpl-3.0)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`@abpjs/theme-basic` provides the foundational layout system for ABP-based React applications. It includes multiple pre-built layouts for different sections of your application - from full application layouts with navigation to minimal account page layouts.
|
|
12
|
+
|
|
13
|
+
This package is a React translation of the original `@abp/ng.theme.basic` Angular package, bringing the same flexible layout system to React developers.
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- **Multiple Layouts** - Application, Account, and Empty layouts
|
|
18
|
+
- **Dynamic Layout System** - Switch layouts based on routes
|
|
19
|
+
- **Navigation Management** - Configurable navigation elements with icons and badges
|
|
20
|
+
- **User Profile** - Built-in profile and password change components
|
|
21
|
+
- **Responsive Design** - Mobile-friendly layouts with sidebar and drawer navigation
|
|
22
|
+
- **RTL Support** - Full right-to-left support for Arabic, Hebrew, Persian, and other RTL languages
|
|
23
|
+
- **Search** - Built-in navigation search to filter menu items
|
|
24
|
+
- **Logo Customization** - Customize logo via props without modifying source code
|
|
25
|
+
- **Chakra UI v3** - Beautiful, accessible components with modern patterns
|
|
26
|
+
- **Color Mode** - Built-in light/dark theme support (opt-in)
|
|
27
|
+
- **TypeScript** - Full type safety with comprehensive definitions
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Using npm
|
|
33
|
+
npm install @abpjs/theme-basic
|
|
34
|
+
|
|
35
|
+
# Using yarn
|
|
36
|
+
yarn add @abpjs/theme-basic
|
|
37
|
+
|
|
38
|
+
# Using pnpm
|
|
39
|
+
pnpm add @abpjs/theme-basic
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Required Dependencies
|
|
43
|
+
|
|
44
|
+
This package requires the following peer dependencies:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install @abpjs/core @abpjs/theme-shared @chakra-ui/react @emotion/react lucide-react react-router-dom react-hook-form
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> **Note:** Chakra UI v3 no longer requires `@chakra-ui/icons`, `@emotion/styled`, or `framer-motion` as peer dependencies.
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
### 1. Setup the Theme Provider
|
|
55
|
+
|
|
56
|
+
Wrap your application with the ThemeBasicProvider:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { ThemeBasicProvider } from '@abpjs/theme-basic';
|
|
60
|
+
import { CoreProvider } from '@abpjs/core';
|
|
61
|
+
|
|
62
|
+
function App() {
|
|
63
|
+
return (
|
|
64
|
+
<CoreProvider environment={environment}>
|
|
65
|
+
<ThemeBasicProvider>
|
|
66
|
+
<Router>
|
|
67
|
+
<AppRoutes />
|
|
68
|
+
</Router>
|
|
69
|
+
</ThemeBasicProvider>
|
|
70
|
+
</CoreProvider>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> **Note:** `ThemeBasicProvider` includes Chakra's provider internally (via `ThemeSharedProvider`), so you don't need to wrap with `ChakraProvider` separately.
|
|
76
|
+
|
|
77
|
+
### 2. Use Layouts in Routes
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
import {
|
|
81
|
+
LayoutApplication,
|
|
82
|
+
LayoutAccount,
|
|
83
|
+
LayoutEmpty
|
|
84
|
+
} from '@abpjs/theme-basic';
|
|
85
|
+
import { Routes, Route, Outlet } from 'react-router-dom';
|
|
86
|
+
|
|
87
|
+
function AppRoutes() {
|
|
88
|
+
return (
|
|
89
|
+
<Routes>
|
|
90
|
+
{/* Application layout for main pages */}
|
|
91
|
+
<Route element={<LayoutApplication><Outlet /></LayoutApplication>}>
|
|
92
|
+
<Route path="/" element={<HomePage />} />
|
|
93
|
+
<Route path="/dashboard" element={<DashboardPage />} />
|
|
94
|
+
<Route path="/users" element={<UsersPage />} />
|
|
95
|
+
</Route>
|
|
96
|
+
|
|
97
|
+
{/* Account layout for auth pages */}
|
|
98
|
+
<Route element={<LayoutAccount><Outlet /></LayoutAccount>}>
|
|
99
|
+
<Route path="/login" element={<LoginPage />} />
|
|
100
|
+
<Route path="/register" element={<RegisterPage />} />
|
|
101
|
+
</Route>
|
|
102
|
+
|
|
103
|
+
{/* Empty layout for minimal pages */}
|
|
104
|
+
<Route element={<LayoutEmpty><Outlet /></LayoutEmpty>}>
|
|
105
|
+
<Route path="/print/:id" element={<PrintPage />} />
|
|
106
|
+
</Route>
|
|
107
|
+
</Routes>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3. Dynamic Layout Selection
|
|
113
|
+
|
|
114
|
+
Use the LAYOUTS constant for dynamic layout selection:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { LAYOUTS, Layout } from '@abpjs/theme-basic';
|
|
118
|
+
|
|
119
|
+
function DynamicLayoutWrapper() {
|
|
120
|
+
const { pathname } = useLocation();
|
|
121
|
+
|
|
122
|
+
// Determine layout based on route
|
|
123
|
+
const getLayout = () => {
|
|
124
|
+
if (pathname.startsWith('/account')) return 'account';
|
|
125
|
+
if (pathname.startsWith('/print')) return 'empty';
|
|
126
|
+
return 'application';
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const SelectedLayout = LAYOUTS.find(l => l.key === getLayout())?.component || Layout;
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<SelectedLayout>
|
|
133
|
+
<Outlet />
|
|
134
|
+
</SelectedLayout>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Layouts
|
|
140
|
+
|
|
141
|
+
### LayoutApplication
|
|
142
|
+
|
|
143
|
+
The main application layout with navigation, header, and footer.
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
import { LayoutApplication } from '@abpjs/theme-basic';
|
|
147
|
+
|
|
148
|
+
function MainApp() {
|
|
149
|
+
return (
|
|
150
|
+
<LayoutApplication>
|
|
151
|
+
<YourContent />
|
|
152
|
+
</LayoutApplication>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Features:**
|
|
158
|
+
- Side navigation menu
|
|
159
|
+
- Top header with user menu
|
|
160
|
+
- Breadcrumbs
|
|
161
|
+
- Footer
|
|
162
|
+
- Responsive sidebar (collapsible on mobile)
|
|
163
|
+
|
|
164
|
+
### LayoutAccount
|
|
165
|
+
|
|
166
|
+
Centered layout for authentication pages.
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
import { LayoutAccount } from '@abpjs/theme-basic';
|
|
170
|
+
|
|
171
|
+
function AuthPages() {
|
|
172
|
+
return (
|
|
173
|
+
<LayoutAccount>
|
|
174
|
+
<LoginForm />
|
|
175
|
+
</LayoutAccount>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Features:**
|
|
181
|
+
- Centered content
|
|
182
|
+
- Clean, minimal design
|
|
183
|
+
- Logo display
|
|
184
|
+
- Language selector
|
|
185
|
+
|
|
186
|
+
### LayoutEmpty
|
|
187
|
+
|
|
188
|
+
Minimal layout with no chrome.
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
import { LayoutEmpty } from '@abpjs/theme-basic';
|
|
192
|
+
|
|
193
|
+
function PrintablePage() {
|
|
194
|
+
return (
|
|
195
|
+
<LayoutEmpty>
|
|
196
|
+
<PrintableContent />
|
|
197
|
+
</LayoutEmpty>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Features:**
|
|
203
|
+
- No header or footer
|
|
204
|
+
- Full-width content
|
|
205
|
+
- Ideal for printing or embedded views
|
|
206
|
+
|
|
207
|
+
## Components
|
|
208
|
+
|
|
209
|
+
### Profile
|
|
210
|
+
|
|
211
|
+
User profile management component (modal-based).
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { Profile } from '@abpjs/theme-basic';
|
|
215
|
+
import { useState } from 'react';
|
|
216
|
+
|
|
217
|
+
function ProfileButton() {
|
|
218
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
219
|
+
|
|
220
|
+
return (
|
|
221
|
+
<>
|
|
222
|
+
<button onClick={() => setIsOpen(true)}>My Profile</button>
|
|
223
|
+
<Profile visible={isOpen} onVisibleChange={setIsOpen} />
|
|
224
|
+
</>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### ChangePassword
|
|
230
|
+
|
|
231
|
+
Password change form component (modal-based).
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
import { ChangePassword } from '@abpjs/theme-basic';
|
|
235
|
+
import { useState } from 'react';
|
|
236
|
+
|
|
237
|
+
function SecurityButton() {
|
|
238
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<>
|
|
242
|
+
<button onClick={() => setIsOpen(true)}>Change Password</button>
|
|
243
|
+
<ChangePassword visible={isOpen} onVisibleChange={setIsOpen} />
|
|
244
|
+
</>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Hooks
|
|
250
|
+
|
|
251
|
+
### useLayoutContext
|
|
252
|
+
|
|
253
|
+
Access and modify layout state.
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
import { useLayoutContext } from '@abpjs/theme-basic';
|
|
257
|
+
|
|
258
|
+
function SidebarToggle() {
|
|
259
|
+
const { isSidebarOpen, toggleSidebar } = useLayoutContext();
|
|
260
|
+
|
|
261
|
+
return (
|
|
262
|
+
<button onClick={toggleSidebar}>
|
|
263
|
+
{isSidebarOpen ? 'Close' : 'Open'} Sidebar
|
|
264
|
+
</button>
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### useLayoutService
|
|
270
|
+
|
|
271
|
+
Access layout service for programmatic control.
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
import { useLayoutService } from '@abpjs/theme-basic';
|
|
275
|
+
|
|
276
|
+
function LayoutController() {
|
|
277
|
+
const layoutService = useLayoutService();
|
|
278
|
+
|
|
279
|
+
const handleCollapse = () => {
|
|
280
|
+
layoutService.collapseSidebar();
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
return <button onClick={handleCollapse}>Collapse</button>;
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### useNavigationElements
|
|
288
|
+
|
|
289
|
+
Access and manage navigation items.
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
import { useNavigationElements } from '@abpjs/theme-basic';
|
|
293
|
+
|
|
294
|
+
function NavigationMenu() {
|
|
295
|
+
const elements = useNavigationElements();
|
|
296
|
+
|
|
297
|
+
return (
|
|
298
|
+
<nav>
|
|
299
|
+
{elements.map(item => (
|
|
300
|
+
<NavLink key={item.name} to={item.path}>
|
|
301
|
+
{item.name}
|
|
302
|
+
</NavLink>
|
|
303
|
+
))}
|
|
304
|
+
</nav>
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Navigation Configuration
|
|
310
|
+
|
|
311
|
+
### Adding Navigation Items
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
import { useLayoutService } from '@abpjs/theme-basic';
|
|
315
|
+
|
|
316
|
+
function ConfigureNavigation() {
|
|
317
|
+
const layoutService = useLayoutService();
|
|
318
|
+
|
|
319
|
+
useEffect(() => {
|
|
320
|
+
layoutService.addNavigationElement({
|
|
321
|
+
name: 'Dashboard',
|
|
322
|
+
element: <DashboardLink />,
|
|
323
|
+
order: 1,
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
layoutService.addNavigationElement({
|
|
327
|
+
name: 'Users',
|
|
328
|
+
element: <UsersLink />,
|
|
329
|
+
order: 2,
|
|
330
|
+
});
|
|
331
|
+
}, []);
|
|
332
|
+
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Navigation Element Structure
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
interface NavigationElement {
|
|
341
|
+
name: string;
|
|
342
|
+
element: ReactNode;
|
|
343
|
+
order?: number;
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## LAYOUTS Constant
|
|
348
|
+
|
|
349
|
+
The package exports a `LAYOUTS` constant for dynamic layout selection:
|
|
350
|
+
|
|
351
|
+
```tsx
|
|
352
|
+
import { LAYOUTS } from '@abpjs/theme-basic';
|
|
353
|
+
|
|
354
|
+
// LAYOUTS structure:
|
|
355
|
+
// [
|
|
356
|
+
// { key: 'application', component: LayoutApplication },
|
|
357
|
+
// { key: 'account', component: LayoutAccount },
|
|
358
|
+
// { key: 'empty', component: LayoutEmpty },
|
|
359
|
+
// ]
|
|
360
|
+
|
|
361
|
+
function getLayoutByKey(key: string) {
|
|
362
|
+
return LAYOUTS.find(l => l.key === key)?.component;
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Customization
|
|
367
|
+
|
|
368
|
+
### Theme Customization with Chakra v3
|
|
369
|
+
|
|
370
|
+
Customize layouts using `defineConfig`:
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
import { ThemeBasicProvider, defineConfig } from '@abpjs/theme-basic';
|
|
374
|
+
|
|
375
|
+
const customTheme = defineConfig({
|
|
376
|
+
theme: {
|
|
377
|
+
tokens: {
|
|
378
|
+
colors: {
|
|
379
|
+
brand: {
|
|
380
|
+
50: { value: '#e3f2fd' },
|
|
381
|
+
100: { value: '#bbdefb' },
|
|
382
|
+
500: { value: '#2196f3' },
|
|
383
|
+
600: { value: '#1e88e5' },
|
|
384
|
+
// ... more shades
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
semanticTokens: {
|
|
389
|
+
colors: {
|
|
390
|
+
brand: {
|
|
391
|
+
solid: { value: '{colors.brand.500}' },
|
|
392
|
+
contrast: { value: 'white' },
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
function App() {
|
|
400
|
+
return (
|
|
401
|
+
<ThemeBasicProvider themeOverrides={customTheme}>
|
|
402
|
+
{/* Your app */}
|
|
403
|
+
</ThemeBasicProvider>
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Color Mode (Dark/Light Theme)
|
|
409
|
+
|
|
410
|
+
Enable color mode support:
|
|
411
|
+
|
|
412
|
+
```tsx
|
|
413
|
+
import { ThemeBasicProvider } from '@abpjs/theme-basic';
|
|
414
|
+
|
|
415
|
+
function App() {
|
|
416
|
+
return (
|
|
417
|
+
<ThemeBasicProvider
|
|
418
|
+
enableColorMode={true}
|
|
419
|
+
defaultColorMode="light" // 'light' | 'dark' | 'system'
|
|
420
|
+
>
|
|
421
|
+
{/* Your app */}
|
|
422
|
+
</ThemeBasicProvider>
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Custom Layout Components
|
|
428
|
+
|
|
429
|
+
Create your own layouts extending the base:
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
import { LayoutBase } from '@abpjs/theme-basic';
|
|
433
|
+
import { Box, Flex } from '@chakra-ui/react';
|
|
434
|
+
|
|
435
|
+
function CustomLayout({ children }) {
|
|
436
|
+
return (
|
|
437
|
+
<LayoutBase>
|
|
438
|
+
<Flex direction="column" minH="100vh">
|
|
439
|
+
<CustomHeader />
|
|
440
|
+
<Box flex="1" p={4}>
|
|
441
|
+
{children}
|
|
442
|
+
</Box>
|
|
443
|
+
<CustomFooter />
|
|
444
|
+
</Flex>
|
|
445
|
+
</LayoutBase>
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## ThemeBasicProvider Props
|
|
451
|
+
|
|
452
|
+
| Prop | Type | Default | Description |
|
|
453
|
+
|------|------|---------|-------------|
|
|
454
|
+
| `children` | `ReactNode` | - | Child components |
|
|
455
|
+
| `renderToasts` | `boolean` | `true` | Render ToastContainer |
|
|
456
|
+
| `renderConfirmation` | `boolean` | `true` | Render ConfirmationDialog |
|
|
457
|
+
| `themeOverrides` | `ThemeOverride` | - | Custom theme configuration |
|
|
458
|
+
| `toastPosition` | `string` | `'bottom-right'` | Toast position |
|
|
459
|
+
| `enableColorMode` | `boolean` | `false` | Enable dark/light mode |
|
|
460
|
+
| `defaultColorMode` | `'light' \| 'dark' \| 'system'` | `'light'` | Default color mode |
|
|
461
|
+
| `logo` | `ReactNode` | - | Custom logo component |
|
|
462
|
+
| `logoIcon` | `ReactNode` | - | Custom logo icon (for collapsed states) |
|
|
463
|
+
| `appName` | `string` | - | Application name for logo text |
|
|
464
|
+
| `logoLink` | `string` | `'/'` | Link destination when clicking logo |
|
|
465
|
+
|
|
466
|
+
## Logo Customization
|
|
467
|
+
|
|
468
|
+
Customize the application logo via ThemeBasicProvider props:
|
|
469
|
+
|
|
470
|
+
```tsx
|
|
471
|
+
import { ThemeBasicProvider } from '@abpjs/theme-basic';
|
|
472
|
+
|
|
473
|
+
function App() {
|
|
474
|
+
return (
|
|
475
|
+
<ThemeBasicProvider
|
|
476
|
+
logo={<img src="/my-logo.svg" alt="My App" />}
|
|
477
|
+
logoIcon={<img src="/my-icon.svg" alt="Icon" />}
|
|
478
|
+
appName="My Application"
|
|
479
|
+
logoLink="/"
|
|
480
|
+
>
|
|
481
|
+
{/* Your app */}
|
|
482
|
+
</ThemeBasicProvider>
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
## Route Icons and Badges
|
|
488
|
+
|
|
489
|
+
Define icons and badges directly on your routes:
|
|
490
|
+
|
|
491
|
+
```tsx
|
|
492
|
+
import { LuHome, LuUsers, LuSettings, LuListTodo } from 'react-icons/lu';
|
|
493
|
+
|
|
494
|
+
const routes = [
|
|
495
|
+
{
|
|
496
|
+
name: 'Home',
|
|
497
|
+
path: '/',
|
|
498
|
+
icon: <LuHome />,
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
name: 'Tasks',
|
|
502
|
+
path: '/tasks',
|
|
503
|
+
icon: <LuListTodo />,
|
|
504
|
+
badge: 5, // Shows "5" badge
|
|
505
|
+
badgeColorPalette: 'red', // Badge color (default: 'gray')
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
name: 'Messages',
|
|
509
|
+
path: '/messages',
|
|
510
|
+
badge: '50+', // Can be string or number
|
|
511
|
+
badgeColorPalette: 'blue',
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
name: 'Admin',
|
|
515
|
+
path: '/admin',
|
|
516
|
+
icon: <LuSettings />,
|
|
517
|
+
children: [
|
|
518
|
+
{
|
|
519
|
+
name: 'Users',
|
|
520
|
+
path: '/admin/users',
|
|
521
|
+
icon: <LuUsers />,
|
|
522
|
+
badge: 'New',
|
|
523
|
+
},
|
|
524
|
+
],
|
|
525
|
+
},
|
|
526
|
+
];
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## RTL (Right-to-Left) Support
|
|
530
|
+
|
|
531
|
+
The layout automatically supports RTL languages. When a user switches to Arabic, Hebrew, Persian, or other RTL languages:
|
|
532
|
+
|
|
533
|
+
- Sidebar moves to the right side
|
|
534
|
+
- Text alignment flips
|
|
535
|
+
- Icons and navigation elements reposition correctly
|
|
536
|
+
- Menus open in the appropriate direction
|
|
537
|
+
|
|
538
|
+
No additional configuration needed - RTL is detected automatically from the selected language.
|
|
539
|
+
|
|
540
|
+
## Complete Example
|
|
541
|
+
|
|
542
|
+
Full application setup:
|
|
543
|
+
|
|
544
|
+
```tsx
|
|
545
|
+
import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';
|
|
546
|
+
import { CoreProvider } from '@abpjs/core';
|
|
547
|
+
import {
|
|
548
|
+
ThemeBasicProvider,
|
|
549
|
+
LayoutApplication,
|
|
550
|
+
LayoutAccount,
|
|
551
|
+
Profile,
|
|
552
|
+
ChangePassword,
|
|
553
|
+
defineConfig,
|
|
554
|
+
} from '@abpjs/theme-basic';
|
|
555
|
+
import { LoginPage, RegisterPage } from '@abpjs/account';
|
|
556
|
+
|
|
557
|
+
const environment = {
|
|
558
|
+
// Your ABP configuration
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// Optional: Custom theme
|
|
562
|
+
const customTheme = defineConfig({
|
|
563
|
+
theme: {
|
|
564
|
+
tokens: {
|
|
565
|
+
colors: {
|
|
566
|
+
brand: {
|
|
567
|
+
500: { value: '#6366f1' },
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
function App() {
|
|
575
|
+
return (
|
|
576
|
+
<CoreProvider environment={environment}>
|
|
577
|
+
<ThemeBasicProvider
|
|
578
|
+
themeOverrides={customTheme}
|
|
579
|
+
enableColorMode={true}
|
|
580
|
+
>
|
|
581
|
+
<BrowserRouter>
|
|
582
|
+
<Routes>
|
|
583
|
+
{/* Main application routes */}
|
|
584
|
+
<Route element={<LayoutApplication><Outlet /></LayoutApplication>}>
|
|
585
|
+
<Route path="/" element={<HomePage />} />
|
|
586
|
+
<Route path="/dashboard" element={<DashboardPage />} />
|
|
587
|
+
</Route>
|
|
588
|
+
|
|
589
|
+
{/* Auth routes */}
|
|
590
|
+
<Route element={<LayoutAccount><Outlet /></LayoutAccount>}>
|
|
591
|
+
<Route path="/login" element={<LoginPage />} />
|
|
592
|
+
<Route path="/register" element={<RegisterPage />} />
|
|
593
|
+
</Route>
|
|
594
|
+
</Routes>
|
|
595
|
+
</BrowserRouter>
|
|
596
|
+
</ThemeBasicProvider>
|
|
597
|
+
</CoreProvider>
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export default App;
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
## Migration from Chakra UI v2
|
|
605
|
+
|
|
606
|
+
If you're upgrading from a previous version that used Chakra UI v2:
|
|
607
|
+
|
|
608
|
+
### Key Changes
|
|
609
|
+
|
|
610
|
+
1. **No separate ChakraProvider** - `ThemeBasicProvider` now includes it
|
|
611
|
+
2. **Theme configuration** - Use `defineConfig()` instead of `extendTheme()`
|
|
612
|
+
3. **Dependencies** - Remove `@chakra-ui/icons`, `@emotion/styled`, `framer-motion`; add `lucide-react`
|
|
613
|
+
4. **Color tokens** - Use `{ value: '#color' }` format in theme tokens
|
|
614
|
+
5. **Boolean props** - `isDisabled` → `disabled`, `isLoading` → `loading`
|
|
615
|
+
6. **Color scheme** - `colorScheme` → `colorPalette`
|
|
616
|
+
7. **Icons** - Use `lucide-react` instead of `@chakra-ui/icons`
|
|
617
|
+
|
|
618
|
+
### Example Migration
|
|
619
|
+
|
|
620
|
+
```tsx
|
|
621
|
+
// Before (Chakra v2)
|
|
622
|
+
import { ChakraProvider, extendTheme } from '@chakra-ui/react';
|
|
623
|
+
import { ThemeBasicProvider } from '@abpjs/theme-basic';
|
|
624
|
+
|
|
625
|
+
const theme = extendTheme({
|
|
626
|
+
colors: { brand: { 500: '#2196f3' } },
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
<ChakraProvider theme={theme}>
|
|
630
|
+
<ThemeBasicProvider>
|
|
631
|
+
<App />
|
|
632
|
+
</ThemeBasicProvider>
|
|
633
|
+
</ChakraProvider>
|
|
634
|
+
|
|
635
|
+
// After (Chakra v3)
|
|
636
|
+
import { ThemeBasicProvider, defineConfig } from '@abpjs/theme-basic';
|
|
637
|
+
|
|
638
|
+
const customTheme = defineConfig({
|
|
639
|
+
theme: {
|
|
640
|
+
tokens: {
|
|
641
|
+
colors: { brand: { 500: { value: '#2196f3' } } },
|
|
642
|
+
},
|
|
643
|
+
},
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
<ThemeBasicProvider themeOverrides={customTheme}>
|
|
647
|
+
<App />
|
|
648
|
+
</ThemeBasicProvider>
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
## Documentation
|
|
652
|
+
|
|
653
|
+
For comprehensive documentation, visit [docs.abpjs.io](https://docs.abpjs.io):
|
|
654
|
+
|
|
655
|
+
- **[Package Documentation](https://docs.abpjs.io/docs/packages/theme-basic/overview)** - Full API reference and examples
|
|
656
|
+
- **[Layouts](https://docs.abpjs.io/docs/packages/theme-basic/layouts)** - Layout components guide
|
|
657
|
+
- **[Navigation](https://docs.abpjs.io/docs/packages/theme-basic/navigation)** - Navigation configuration
|
|
658
|
+
- **[Profile](https://docs.abpjs.io/docs/packages/theme-basic/profile)** - Profile and password components
|
|
659
|
+
- **[Getting Started](https://docs.abpjs.io/docs/getting-started/installation)** - Installation and setup guide
|
|
660
|
+
- **[All Packages](https://docs.abpjs.io/docs/)** - Browse all ABP React packages
|
|
661
|
+
|
|
662
|
+
## Related Packages
|
|
663
|
+
|
|
664
|
+
- [@abpjs/core](https://www.npmjs.com/package/@abpjs/core) - Core infrastructure (required)
|
|
665
|
+
- [@abpjs/theme-shared](https://www.npmjs.com/package/@abpjs/theme-shared) - Shared UI components (required)
|
|
666
|
+
- [@abpjs/account](https://www.npmjs.com/package/@abpjs/account) - Account management
|
|
667
|
+
- [@abpjs/permission-management](https://www.npmjs.com/package/@abpjs/permission-management) - Permission management
|
|
668
|
+
- [@abpjs/tenant-management](https://www.npmjs.com/package/@abpjs/tenant-management) - Tenant administration
|
|
669
|
+
|
|
670
|
+
## Contributing
|
|
671
|
+
|
|
672
|
+
This package is part of the [ABP React](https://github.com/abpjs/abp-react) monorepo. Contributions are welcome!
|
|
673
|
+
|
|
674
|
+
## License
|
|
675
|
+
|
|
676
|
+
LGPL-3.0 - See [LICENSE](https://github.com/abpjs/abp-react/blob/main/LICENSE) for details.
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
**[View Full Documentation](https://docs.abpjs.io/docs/packages/theme-basic/overview)** | **[Report Issues](https://github.com/abpjs/abp-react/issues)** | **[View Source](https://github.com/abpjs/abp-react/tree/main/packages/theme-basic)**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const Block: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { Sidebar, type SidebarProps } from './sidebar';
|
|
2
|
+
export { Navbar, type NavbarProps } from './navbar';
|
|
3
|
+
export { Logo, DefaultLogo, LogoText, LogoIcon } from './logo';
|
|
4
|
+
export { SidebarLink } from './sidebar-link';
|
|
5
|
+
export { SearchField } from './search-field';
|
|
6
|
+
export { SearchProvider, useSearch } from './search-context';
|
|
7
|
+
export { NavLinks } from './nav-links';
|
|
8
|
+
export { LanguageSelector, type LanguageSelectorProps } from './language-selector';
|
|
9
|
+
export { UserProfile, type UserProfileProps } from './user-profile';
|
|
10
|
+
export { Block } from './block';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface LanguageSelectorProps {
|
|
2
|
+
/** Whether to show in compact mode (icon only when collapsed) */
|
|
3
|
+
compact?: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Language selector dropdown for the sidebar
|
|
7
|
+
*/
|
|
8
|
+
export declare const LanguageSelector: ({ compact }: LanguageSelectorProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default ABP logo SVG component
|
|
3
|
+
*/
|
|
4
|
+
export declare const DefaultLogo: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
interface LogoProps {
|
|
6
|
+
style?: React.CSSProperties;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Logo component that uses branding context.
|
|
10
|
+
* Falls back to default ABP logo if no custom logo is provided.
|
|
11
|
+
*/
|
|
12
|
+
export declare const Logo: ({ style }: LogoProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare const LogoText: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export declare const LogoIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|