nnews-react 0.4.4 โ†’ 0.4.9

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
@@ -1,68 +1,135 @@
1
- # nnews-react
1
+ # nnews-react - React Component Library for NNews CMS
2
2
 
3
- Complete React component library for NAuth authentication and NNews content management system. Built with TypeScript, Tailwind CSS, and designed as a distributable NPM package.
3
+ ![React](https://img.shields.io/badge/React-18+-61DAFB?logo=react&logoColor=white)
4
+ ![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6?logo=typescript&logoColor=white)
5
+ ![npm version](https://img.shields.io/npm/v/nnews-react.svg)
6
+ ![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)
4
7
 
5
- [![npm version](https://img.shields.io/npm/v/nnews-react.svg)](https://www.npmjs.com/package/nnews-react)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+ ## Overview
7
9
 
8
- ## Features
10
+ **nnews-react** is a React component library (npm package) for the NNews content management system. It provides ready-made components, hooks, API services, context providers, and a theming system that consuming applications integrate via `NNewsProvider`. Includes AI-powered article generation with ChatGPT and DALL-E 3.
9
11
 
10
- ### Authentication (NAuth)
11
- โœจ **Complete Auth Suite** - Login, Register, Password Recovery, Change Password
12
- ๐Ÿ‘ค **User Management** - Full CRUD with profile editing
13
- ๐ŸŽญ **Role Management** - Role-based access control
14
- ๐ŸŽฏ **Security** - Device fingerprinting with FingerprintJS
15
- ๐Ÿ”’ **Type-Safe** - Full TypeScript support
12
+ Built with **TypeScript**, **Tailwind CSS**, **Radix UI**, and **i18next** for internationalization (English and Portuguese).
16
13
 
17
- ### Content Management (NNews)
18
- ๐Ÿ“ **Article Management** - Full CRUD with Markdown editor
19
- ๐Ÿ“‚ **Category System** - Hierarchical categories with parent-child relationships
20
- ๐Ÿท๏ธ **Tag Management** - Flexible tagging with merge functionality
21
- โœ๏ธ **Markdown Editor** - Live preview with syntax highlighting
22
- ๐Ÿ‘๏ธ **Article Viewer** - Beautiful article display with GitHub-flavored Markdown
23
- ๐Ÿ” **Access Control** - Role-based content visibility
14
+ The `example-app/` directory contains a full working application demonstrating library usage in dark mode.
24
15
 
25
- ### General
26
- ๐ŸŽจ **Theme Support** - Light/Dark mode with system detection
27
- ๐Ÿ“ฆ **Tree-shakeable** - Import only what you need
28
- โ™ฟ **Accessible** - WCAG compliant
29
- ๐Ÿ“ฑ **Responsive** - Mobile-first design
16
+ ---
30
17
 
31
- ## Installation
18
+ ## ๐Ÿš€ Features
19
+
20
+ ### Content Management
21
+ - ๐Ÿ“ **Article Management** โ€” Full CRUD with rich text (Quill), Markdown, and plain text editors
22
+ - ๐Ÿค– **AI-Powered Content** โ€” Create and update articles with ChatGPT, generate images with DALL-E 3
23
+ - ๐Ÿ“‚ **Hierarchical Categories** โ€” Parent-child category system with full CRUD
24
+ - ๐Ÿท๏ธ **Tag System** โ€” Flexible tagging with merge functionality
25
+ - ๐Ÿ” **Search & Filters** โ€” Search articles by keyword, filter by category, status, tag, or roles
26
+ - ๐Ÿ“„ **Pagination** โ€” Built-in `PagedResult<T>` pattern with `hasNext`/`hasPrevious`
27
+ - ๐Ÿ–ผ๏ธ **Image Upload** โ€” Featured image upload with preview and placeholder fallback
28
+
29
+ ### Architecture
30
+ - ๐ŸŽจ **Theme System** โ€” Configurable `light`/`dark`/`system` mode via `NNewsConfig.theme`
31
+ - ๐ŸŒ **Internationalization** โ€” i18next with `nnews` namespace, EN/PT built-in, extensible
32
+ - ๐Ÿข **Multi-tenancy** โ€” `X-Tenant-Id` header injection via Axios interceptor
33
+ - ๐Ÿ” **Role-based Access** โ€” Content visibility control per role
34
+ - ๐Ÿ“ฆ **Tree-shakeable** โ€” ESM + CJS dual output, import only what you need
35
+ - โ™ฟ **Accessible** โ€” Radix UI primitives with focus trapping, keyboard navigation, ARIA
36
+ - ๐Ÿ“ฑ **Responsive** โ€” Mobile-first Tailwind CSS design
37
+
38
+ ### UI System
39
+ - ๐ŸชŸ **Normalized Modals** โ€” All modals use a single Radix-based `Modal` component
40
+ - โœ… **ConfirmModal** โ€” Reusable confirmation dialog with danger/warning/default variants
41
+ - ๐Ÿงฉ **UI Primitives** โ€” Button, Input, Label, Avatar, Modal components
42
+
43
+ ---
44
+
45
+ ## ๐Ÿ› ๏ธ Technologies Used
46
+
47
+ ### Core
48
+ - **React 18+** โ€” UI framework (peer dependency)
49
+ - **TypeScript 5** โ€” Type safety
50
+ - **Vite** โ€” Build tooling with SWC plugin
51
+
52
+ ### Styling & UI
53
+ - **Tailwind CSS** โ€” Utility-first CSS with class-based dark mode
54
+ - **Radix UI** โ€” Accessible Dialog, Dropdown, Select, Tabs, Toast primitives
55
+ - **class-variance-authority** โ€” Component variant system
56
+ - **lucide-react** โ€” Icon library
57
+
58
+ ### Editors
59
+ - **react-quill-new** โ€” WYSIWYG rich text editor (HTML)
60
+ - **react-markdown** + **remark-gfm** + **rehype-highlight** โ€” Markdown rendering with syntax highlighting
61
+
62
+ ### State & Data
63
+ - **Axios** โ€” HTTP client with interceptors
64
+ - **react-hook-form** + **Zod** โ€” Form handling and validation
65
+ - **i18next** + **react-i18next** โ€” Internationalization
66
+
67
+ ### Testing
68
+ - **Vitest** โ€” Unit test runner with coverage
69
+
70
+ ---
71
+
72
+ ## ๐Ÿ“ Project Structure
73
+
74
+ ```
75
+ nnews-react/
76
+ โ”œโ”€โ”€ src/
77
+ โ”‚ โ”œโ”€โ”€ components/ # React components
78
+ โ”‚ โ”‚ โ”œโ”€โ”€ ui/ # Primitives (Button, Input, Modal, ConfirmModal, etc.)
79
+ โ”‚ โ”‚ โ”œโ”€โ”€ ArticleList.tsx # Article grid with image placeholders
80
+ โ”‚ โ”‚ โ”œโ”€โ”€ ArticleEditor.tsx # Multi-format article editor
81
+ โ”‚ โ”‚ โ”œโ”€โ”€ ArticleViewer.tsx # Article display (Markdown/HTML/Plain)
82
+ โ”‚ โ”‚ โ”œโ”€โ”€ AIArticleGenerator.tsx # AI content generation modal
83
+ โ”‚ โ”‚ โ”œโ”€โ”€ CategoryList.tsx # Category table
84
+ โ”‚ โ”‚ โ”œโ”€โ”€ CategoryModal.tsx # Category create/edit modal
85
+ โ”‚ โ”‚ โ”œโ”€โ”€ TagList.tsx # Tag chips with actions
86
+ โ”‚ โ”‚ โ”œโ”€โ”€ TagModal.tsx # Tag create/edit modal
87
+ โ”‚ โ”‚ โ”œโ”€โ”€ TagMerge.tsx # Tag merge modal
88
+ โ”‚ โ”‚ โ”œโ”€โ”€ RichTextEditor.tsx # Quill WYSIWYG editor
89
+ โ”‚ โ”‚ โ””โ”€โ”€ MarkdownEditor.tsx # Markdown editor with preview
90
+ โ”‚ โ”œโ”€โ”€ contexts/ # NNewsContext (provider, config, Axios setup)
91
+ โ”‚ โ”œโ”€โ”€ hooks/ # useArticles, useCategories, useTags
92
+ โ”‚ โ”œโ”€โ”€ services/ # ArticleAPI, CategoryAPI, TagAPI
93
+ โ”‚ โ”œโ”€โ”€ types/ # TypeScript types, enums, theme config
94
+ โ”‚ โ”œโ”€โ”€ i18n/ # i18next setup, EN/PT translations
95
+ โ”‚ โ”œโ”€โ”€ utils/ # cn(), validators
96
+ โ”‚ โ”œโ”€โ”€ styles/ # Tailwind CSS base styles
97
+ โ”‚ โ””โ”€โ”€ index.ts # Public API exports
98
+ โ”œโ”€โ”€ example-app/ # Full demo application (dark mode)
99
+ โ”œโ”€โ”€ docs/ # Additional documentation
100
+ โ”œโ”€โ”€ dist/ # Build output (ESM + CJS + types + CSS)
101
+ โ””โ”€โ”€ package.json
102
+ ```
103
+
104
+ ---
105
+
106
+ ## โš™๏ธ Installation
32
107
 
33
108
  ```bash
34
- npm install nnews-react react react-dom react-router-dom
109
+ npm install nnews-react
110
+ ```
35
111
 
36
- # If you don't have Tailwind CSS
37
- npm install -D tailwindcss postcss autoprefixer tailwindcss-animate
38
- npx tailwindcss init -p
112
+ **Peer dependencies:**
113
+
114
+ ```bash
115
+ npm install react react-dom react-router-dom nauth-react
39
116
  ```
40
117
 
41
- ### Configure Tailwind
118
+ **Tailwind CSS setup:**
119
+
120
+ ```bash
121
+ npm install -D tailwindcss postcss autoprefixer tailwindcss-animate
122
+ ```
42
123
 
43
124
  ```javascript
44
125
  // tailwind.config.js
45
126
  export default {
46
127
  darkMode: ['class'],
47
128
  content: [
48
- './src/**/*.{js,ts,jsx,tsx}',
49
- './node_modules/nnews-react/dist/**/*.{js,ts,jsx,tsx}',
50
- ],
51
- theme: {
52
- extend: {
53
- typography: {
54
- DEFAULT: {
55
- css: {
56
- maxWidth: 'none',
57
- },
58
- },
59
- },
60
- },
61
- },
62
- plugins: [
63
- require('tailwindcss-animate'),
64
- require('@tailwindcss/typography'), // For Markdown rendering
129
+ './src/**/*.{ts,tsx}',
130
+ './node_modules/nnews-react/dist/**/*.{js,mjs}',
65
131
  ],
132
+ plugins: [require('tailwindcss-animate')],
66
133
  };
67
134
  ```
68
135
 
@@ -73,321 +140,152 @@ export default {
73
140
  @tailwind utilities;
74
141
  ```
75
142
 
76
- ## Quick Start
143
+ ---
77
144
 
78
- ### 1. Setup Providers
145
+ ## ๐Ÿ“– Quick Start
146
+
147
+ ### 1. Setup Provider
79
148
 
80
149
  ```tsx
81
- import { BrowserRouter } from 'react-router-dom';
82
- import { NAuthProvider, NNewsProvider, ThemeProvider } from 'nnews-react';
150
+ import { NNewsProvider } from 'nnews-react';
83
151
  import 'nnews-react/styles';
84
- import './index.css';
85
152
 
86
153
  function App() {
87
154
  return (
88
- <BrowserRouter>
89
- <ThemeProvider defaultTheme="system">
90
- <NAuthProvider
91
- config={{
92
- apiUrl: import.meta.env.VITE_API_URL,
93
- enableFingerprinting: true,
94
- }}
95
- >
96
- <NNewsProvider
97
- config={{
98
- apiUrl: import.meta.env.VITE_API_URL,
99
- }}
100
- >
101
- <YourApp />
102
- </NNewsProvider>
103
- </NAuthProvider>
104
- </ThemeProvider>
105
- </BrowserRouter>
106
- );
107
- }
108
- ```
109
-
110
- ```env
111
- # .env
112
- VITE_API_URL=https://your-nauth-api.com
113
- ```
114
-
115
- ### 2. Use Authentication Components
116
-
117
- ```tsx
118
- import {
119
- LoginForm,
120
- RegisterForm,
121
- UserEditForm,
122
- RoleList,
123
- SearchForm,
124
- useAuth,
125
- useProtectedRoute,
126
- } from 'nnews-react';
127
- import { useNavigate } from 'react-router-dom';
128
-
129
- // Login Page
130
- function LoginPage() {
131
- const navigate = useNavigate();
132
- return (
133
- <div className="min-h-screen flex items-center justify-center">
134
- <LoginForm
135
- onSuccess={() => navigate('/dashboard')}
136
- showRememberMe
137
- showForgotPassword
138
- />
139
- </div>
140
- );
141
- }
142
-
143
- // Protected Dashboard
144
- function Dashboard() {
145
- const { user, logout } = useAuth();
146
- useProtectedRoute({ redirectTo: '/login' });
147
-
148
- return (
149
- <div>
150
- <h1>Welcome, {user?.name}</h1>
151
- <button onClick={logout}>Logout</button>
152
- </div>
153
- );
154
- }
155
-
156
- // User Management
157
- function CreateUserPage() {
158
- const navigate = useNavigate();
159
- return (
160
- <UserEditForm
161
- onSuccess={(user) => {
162
- console.log('User created:', user);
163
- navigate('/users');
155
+ <NNewsProvider
156
+ config={{
157
+ apiUrl: import.meta.env.VITE_NNEWS_API_URL,
158
+ tenantId: import.meta.env.VITE_TENANT_ID,
159
+ headers: {
160
+ Authorization: `Bearer ${token}`,
161
+ },
162
+ language: 'en', // 'en' | 'pt'
163
+ theme: {
164
+ mode: 'dark', // 'light' | 'dark' | 'system'
165
+ },
164
166
  }}
165
- onCancel={() => navigate('/users')}
166
- />
167
+ >
168
+ <YourApp />
169
+ </NNewsProvider>
167
170
  );
168
171
  }
169
172
  ```
170
173
 
171
- ### 3. Use Content Management Components
174
+ ### 2. Use Components
172
175
 
173
176
  ```tsx
174
177
  import {
175
178
  ArticleList,
176
- ArticleViewer,
177
179
  ArticleEditor,
180
+ ArticleViewer,
181
+ AIArticleGenerator,
178
182
  CategoryList,
179
183
  CategoryModal,
180
184
  TagList,
181
185
  TagModal,
186
+ TagMerge,
187
+ ConfirmModal,
182
188
  useArticles,
183
189
  useCategories,
184
190
  useTags,
185
191
  } from 'nnews-react';
192
+ ```
193
+
194
+ ### 3. Fetch and Display Articles
186
195
 
187
- // Articles List Page
196
+ ```tsx
188
197
  function ArticlesPage() {
189
198
  const { articles, loading, fetchArticles, deleteArticle } = useArticles();
190
199
 
191
200
  useEffect(() => {
192
- fetchArticles({ page: 1, pageSize: 20 });
201
+ fetchArticles({ page: 1, pageSize: 10, status: 1 }); // Published only
193
202
  }, []);
194
203
 
195
204
  return (
196
- <div className="container mx-auto p-6">
197
- <h1 className="text-3xl font-bold mb-6">Articles</h1>
198
- <ArticleList
199
- articles={articles}
200
- loading={loading}
201
- onArticleClick={(article) => navigate(`/articles/${article.id}`)}
202
- onEditClick={(article) => navigate(`/articles/${article.id}/edit`)}
203
- onDeleteClick={deleteArticle}
204
- showActions
205
- />
206
- </div>
207
- );
208
- }
209
-
210
- // Article Viewer Page
211
- function ArticleViewPage({ articleId }: { articleId: number }) {
212
- const { getArticleById } = useArticles();
213
- const [article, setArticle] = useState(null);
214
-
215
- useEffect(() => {
216
- getArticleById(articleId).then(setArticle);
217
- }, [articleId]);
218
-
219
- if (!article) return <div>Loading...</div>;
220
-
221
- return (
222
- <ArticleViewer
223
- article={article}
224
- onBack={() => navigate('/articles')}
225
- onEdit={(article) => navigate(`/articles/${article.id}/edit`)}
205
+ <ArticleList
206
+ articles={articles}
207
+ loading={loading}
208
+ onArticleClick={(article) => navigate(`/articles/${article.articleId}`)}
209
+ onEditClick={(article) => navigate(`/articles/edit/${article.articleId}`)}
210
+ onDeleteClick={(article) => setArticleToDelete(article)}
226
211
  showActions
227
212
  />
228
213
  );
229
214
  }
215
+ ```
230
216
 
231
- // Article Editor Page
232
- function ArticleEditorPage({ articleId }: { articleId?: number }) {
233
- const { createArticle, updateArticle, getArticleById } = useArticles();
234
- const { categories } = useCategories();
235
- const { tags } = useTags();
236
- const [article, setArticle] = useState(null);
237
-
238
- useEffect(() => {
239
- if (articleId) {
240
- getArticleById(articleId).then(setArticle);
241
- }
242
- fetchCategories();
243
- fetchTags();
244
- }, [articleId]);
245
-
246
- const handleSave = async (data) => {
247
- if (article) {
248
- await updateArticle({ ...data, id: article.id });
249
- } else {
250
- await createArticle(data);
251
- }
252
- navigate('/articles');
253
- };
254
-
255
- return (
256
- <ArticleEditor
257
- article={article}
258
- categories={categories}
259
- tags={tags}
260
- onSave={handleSave}
261
- onCancel={() => navigate('/articles')}
262
- />
263
- );
264
- }
217
+ ---
265
218
 
266
- // Category Management
267
- function CategoriesPage() {
268
- const { categories, createCategory, updateCategory, deleteCategory } = useCategories();
269
- const [modalOpen, setModalOpen] = useState(false);
270
- const [selectedCategory, setSelectedCategory] = useState(null);
219
+ ## ๐Ÿ”ง NNewsProvider Configuration
271
220
 
272
- return (
273
- <div className="container mx-auto p-6">
274
- <div className="flex justify-between mb-6">
275
- <h1 className="text-3xl font-bold">Categories</h1>
276
- <button onClick={() => setModalOpen(true)}>New Category</button>
277
- </div>
278
- <CategoryList
279
- categories={categories}
280
- onEditClick={(cat) => {
281
- setSelectedCategory(cat);
282
- setModalOpen(true);
283
- }}
284
- onDeleteClick={deleteCategory}
285
- showActions
286
- />
287
- <CategoryModal
288
- isOpen={modalOpen}
289
- onClose={() => {
290
- setModalOpen(false);
291
- setSelectedCategory(null);
292
- }}
293
- category={selectedCategory}
294
- categories={categories}
295
- onSave={selectedCategory ? updateCategory : createCategory}
296
- />
297
- </div>
298
- );
221
+ ```tsx
222
+ interface NNewsConfig {
223
+ apiUrl: string; // Required โ€” NNews API base URL
224
+ tenantId?: string; // Multi-tenant ID (X-Tenant-Id header)
225
+ apiClient?: AxiosInstance; // Custom Axios instance
226
+ headers?: Record<string, string>; // Dynamic headers (e.g., Authorization)
227
+ language?: string; // 'en' | 'pt' (default: 'en')
228
+ translations?: Record<string, Record<string, unknown>>; // Custom translations
229
+ theme?: {
230
+ mode?: 'light' | 'dark' | 'system'; // Theme mode (default: 'system')
231
+ classNames?: { // CSS class overrides
232
+ root?: string;
233
+ card?: string;
234
+ table?: string;
235
+ modal?: string;
236
+ button?: string;
237
+ input?: string;
238
+ };
239
+ };
299
240
  }
300
241
  ```
301
242
 
302
- ## Components
303
-
304
- ### Authentication Components
305
- - `LoginForm` - Email/password login with validation
306
- - `RegisterForm` - Multi-step registration with password strength
307
- - `ForgotPasswordForm` - Password recovery request
308
- - `ResetPasswordForm` - Password reset with token
309
- - `ChangePasswordForm` - Change password for authenticated users
243
+ The provider creates an Axios instance with request interceptors that inject `Authorization` and `X-Tenant-Id` headers dynamically. It also wraps children in a themed container with the `dark` class when appropriate.
310
244
 
311
- ### User Management
312
- - `UserEditForm` - Create and edit users with full profile management (dual mode)
313
- - `SearchForm` - Search and browse users with pagination
245
+ ---
314
246
 
315
- ### Role Management
316
- - `RoleList` - List and manage roles with CRUD operations
317
- - `RoleForm` - Create and edit roles
247
+ ## ๐Ÿ“š Hooks API
318
248
 
319
- ### Content Management (News)
320
- - `ArticleList` - Display paginated list of articles with actions
321
- - `ArticleViewer` - Beautiful article display with Markdown rendering
322
- - `ArticleEditor` - Full-featured article editor with Markdown support
323
- - `MarkdownEditor` - Standalone Markdown editor with live preview
324
- - `CategoryList` - Display and manage categories
325
- - `CategoryModal` - Modal for creating/editing categories
326
- - `TagList` - Display and manage tags
327
- - `TagModal` - Modal for creating/editing tags
249
+ ### useArticles
328
250
 
329
- ### UI Components
330
- `Button`, `Input`, `Label`, `Card`, `Avatar`, `DropdownMenu`, `Toaster`
331
-
332
- ## Hooks
333
-
334
- ### Authentication Hooks
335
251
  ```tsx
336
- // Authentication state
337
- const { user, isAuthenticated, login, logout, isLoading } = useAuth();
338
-
339
- // User management
340
252
  const {
341
- user,
342
- updateUser,
343
- createUser,
344
- getUserById,
345
- changePassword,
346
- uploadImage,
347
- searchUsers,
348
- } = useUser();
349
-
350
- // Role management
351
- const { fetchRoles, getRoleById, createRole, updateRole, deleteRole } = useNAuth();
352
-
353
- // Route protection
354
- useProtectedRoute({ redirectTo: '/login', requireAdmin: false });
355
-
356
- // Theme management
357
- const { theme, setTheme } = useTheme();
253
+ articles, // PagedResult<Article> | null
254
+ loading, // boolean
255
+ error, // Error | null
256
+ fetchArticles, // (params?: ArticleSearchParams) => Promise<void>
257
+ getArticleById, // (id: number) => Promise<Article>
258
+ createArticle, // (article: ArticleInput) => Promise<Article>
259
+ updateArticle, // (article: ArticleUpdate) => Promise<Article>
260
+ deleteArticle, // (id: number) => Promise<void>
261
+ refresh, // () => Promise<void>
262
+ } = useArticles();
263
+
264
+ // ArticleSearchParams supports:
265
+ // categoryId, status, roles, tags, searchTerm, page, pageSize
358
266
  ```
359
267
 
360
- ### Content Management Hooks
361
- ```tsx
362
- // Article management
363
- const {
364
- articles,
365
- loading,
366
- error,
367
- fetchArticles,
368
- getArticleById,
369
- createArticle,
370
- updateArticle,
371
- deleteArticle,
372
- refresh,
373
- } = useArticles();
268
+ ### useCategories
374
269
 
375
- // Category management
270
+ ```tsx
376
271
  const {
377
- categories,
272
+ categories, // Category[]
378
273
  loading,
379
274
  error,
380
- fetchCategories,
275
+ fetchCategories, // (params?: CategoryFilterParams) => Promise<void>
381
276
  getCategoryById,
382
277
  createCategory,
383
278
  updateCategory,
384
279
  deleteCategory,
385
280
  refresh,
386
281
  } = useCategories();
282
+ ```
387
283
 
388
- // Tag management
284
+ ### useTags
285
+
286
+ ```tsx
389
287
  const {
390
- tags,
288
+ tags, // Tag[]
391
289
  loading,
392
290
  error,
393
291
  fetchTags,
@@ -395,181 +293,258 @@ const {
395
293
  createTag,
396
294
  updateTag,
397
295
  deleteTag,
398
- mergeTags,
296
+ mergeTags, // (sourceId: number, targetId: number) => Promise<void>
399
297
  refresh,
400
298
  } = useTags();
401
299
  ```
402
300
 
403
- ## Configuration
404
-
405
- ### NAuth Configuration
406
- ```tsx
407
- <NAuthProvider
408
- config={{
409
- apiUrl: 'https://your-api.com', // Required
410
- timeout: 30000, // Optional
411
- enableFingerprinting: true, // Optional
412
- storageType: 'localStorage', // Optional
413
- redirectOnUnauthorized: '/login', // Optional
414
- onAuthChange: (user) => {}, // Optional
415
- onLogin: (user) => {}, // Optional
416
- onLogout: () => {}, // Optional
417
- }}
418
- >
419
- <App />
420
- </NAuthProvider>
421
- ```
422
-
423
- ### NNews Configuration
424
- ```tsx
425
- <NNewsProvider
426
- config={{
427
- apiUrl: 'https://your-api.com', // Required
428
- timeout: 30000, // Optional
429
- }}
430
- >
431
- <App />
432
- </NNewsProvider>
433
- ```
434
-
435
- ## API Clients
436
-
437
- ### NAuth API Client
438
- ```tsx
439
- import { createNAuthClient } from 'nnews-react';
301
+ ---
440
302
 
441
- const authApi = createNAuthClient({ apiUrl: 'https://your-api.com' });
303
+ ## ๐Ÿ”Œ API Services
442
304
 
443
- await authApi.login({ email, password });
444
- await authApi.getMe();
445
- await authApi.updateUser({ name: 'New Name' });
446
- await authApi.uploadImage(file);
447
- ```
305
+ The library exposes class-based API clients that can be used directly:
448
306
 
449
- ### NNews API Services
450
307
  ```tsx
451
308
  import { ArticleAPI, CategoryAPI, TagAPI } from 'nnews-react';
452
309
  import axios from 'axios';
453
310
 
454
- const apiClient = axios.create({ baseURL: 'https://your-api.com' });
311
+ const client = axios.create({ baseURL: 'https://your-api.com' });
312
+ const articleApi = new ArticleAPI(client);
455
313
 
456
- // Article API
457
- const articleApi = new ArticleAPI(apiClient);
458
- await articleApi.listArticles();
314
+ // Article endpoints
315
+ await articleApi.listArticles(categoryId?, status?, page, pageSize);
316
+ await articleApi.listByCategory(categoryId, page, pageSize);
317
+ await articleApi.listByRoles(page, pageSize);
318
+ await articleApi.listByTag(tagSlug, page, pageSize);
319
+ await articleApi.search(keyword, page, pageSize);
459
320
  await articleApi.getArticleById(id);
460
321
  await articleApi.createArticle(data);
461
322
  await articleApi.updateArticle(data);
462
323
  await articleApi.deleteArticle(id);
324
+ await articleApi.uploadImage(file);
325
+ await articleApi.createArticleWithAI(request);
326
+ await articleApi.updateArticleWithAI(request);
463
327
 
464
- // Category API
465
- const categoryApi = new CategoryAPI(apiClient);
328
+ // Category endpoints
329
+ const categoryApi = new CategoryAPI(client);
466
330
  await categoryApi.listCategories();
331
+ await categoryApi.listByParent(roles?, parentId?);
332
+ await categoryApi.getCategoryById(id);
467
333
  await categoryApi.createCategory(data);
334
+ await categoryApi.updateCategory(data);
335
+ await categoryApi.deleteCategory(id);
468
336
 
469
- // Tag API
470
- const tagApi = new TagAPI(apiClient);
337
+ // Tag endpoints
338
+ const tagApi = new TagAPI(client);
471
339
  await tagApi.listTags();
340
+ await tagApi.listByRoles();
341
+ await tagApi.getTagById(id);
342
+ await tagApi.createTag(data);
343
+ await tagApi.updateTag(data);
344
+ await tagApi.deleteTag(id);
472
345
  await tagApi.mergeTags(sourceId, targetId);
473
346
  ```
474
347
 
475
- ## Customization
348
+ ---
476
349
 
477
- ```tsx
478
- <LoginForm
479
- className="shadow-2xl"
480
- styles={{
481
- container: 'bg-white',
482
- button: 'bg-purple-600',
483
- }}
484
- />
485
- ```
350
+ ## ๐ŸชŸ Modal System
486
351
 
487
- ## Utilities
352
+ All modals use a single normalized `Modal` component built on Radix UI Dialog:
488
353
 
489
354
  ```tsx
490
355
  import {
491
- validateCPF,
492
- validateCNPJ,
493
- validateEmail,
494
- formatPhone,
495
- validatePasswordStrength,
496
- cn, // Utility for merging Tailwind classes
356
+ Modal, ModalContent, ModalHeader, ModalBody, ModalFooter,
357
+ ModalTitle, ModalDescription, ModalClose,
358
+ ConfirmModal,
497
359
  } from 'nnews-react';
360
+
361
+ // Confirmation dialog
362
+ <ConfirmModal
363
+ open={isOpen}
364
+ onOpenChange={setIsOpen}
365
+ onConfirm={handleDelete}
366
+ title="Delete Article"
367
+ description="This action cannot be undone."
368
+ confirmLabel="Delete"
369
+ variant="danger" // 'danger' | 'warning' | 'default'
370
+ loading={isDeleting}
371
+ />
372
+
373
+ // Custom modal
374
+ <Modal open={isOpen} onOpenChange={setIsOpen}>
375
+ <ModalContent className="max-w-2xl">
376
+ <ModalHeader>
377
+ <ModalTitle>Edit Item</ModalTitle>
378
+ <ModalDescription>Fill in the details below.</ModalDescription>
379
+ </ModalHeader>
380
+ <ModalBody>
381
+ {/* Your form content */}
382
+ </ModalBody>
383
+ <ModalFooter>
384
+ <ModalClose asChild>
385
+ <button>Cancel</button>
386
+ </ModalClose>
387
+ <button onClick={handleSave}>Save</button>
388
+ </ModalFooter>
389
+ </ModalContent>
390
+ </Modal>
498
391
  ```
499
392
 
500
- ## Markdown Support
393
+ ---
394
+
395
+ ## ๐ŸŒ Internationalization
501
396
 
502
- The Markdown editor supports:
397
+ Built-in translations for English and Portuguese. Extend with custom translations:
503
398
 
504
- - **Basic Formatting**: Bold, italic, strikethrough
505
- - **Headers**: H1-H6
506
- - **Lists**: Ordered and unordered
507
- - **Links**: Inline and reference-style
508
- - **Images**: Inline images
509
- - **Code**: Inline code and fenced code blocks with syntax highlighting
510
- - **Tables**: GitHub-flavored tables
511
- - **Task Lists**: GitHub-style checkboxes
512
- - **Blockquotes**: Quote blocks
399
+ ```tsx
400
+ <NNewsProvider
401
+ config={{
402
+ apiUrl: '...',
403
+ language: 'pt',
404
+ translations: {
405
+ en: { custom_key: 'Custom value' },
406
+ pt: { custom_key: 'Valor customizado' },
407
+ },
408
+ }}
409
+ >
410
+ ```
411
+
412
+ ---
513
413
 
514
- ## TypeScript
414
+ ## ๐Ÿ”’ TypeScript Types
515
415
 
516
416
  ```tsx
517
417
  import type {
518
- // Auth types
519
- UserInfo,
520
- LoginCredentials,
521
- NAuthConfig,
522
- Theme,
523
- // News types
524
- Article,
525
- Category,
526
- Tag,
527
- ArticleStatus,
528
- ArticleInput,
529
- ArticleUpdate,
530
- CategoryInput,
531
- CategoryUpdate,
532
- TagInput,
533
- TagUpdate,
418
+ Article, ArticleInput, ArticleUpdate, AIArticleRequest,
419
+ Category, CategoryInput, CategoryUpdate,
420
+ Tag, TagInput, TagUpdate,
421
+ PagedResult, Role,
422
+ NNewsConfig, NNewsTheme, NNewsThemeMode,
423
+ ArticleSearchParams, CategoryFilterParams, TagSearchParams,
534
424
  } from 'nnews-react';
425
+
426
+ import { ArticleStatus, ContentType } from 'nnews-react';
427
+ // ArticleStatus: Draft(0), Published(1), Archived(2), Scheduled(3), Review(4)
428
+ // ContentType: PlainText(1), Html(2), MarkDown(3)
535
429
  ```
536
430
 
537
- ## Project Structure
431
+ ---
432
+
433
+ ## โš™๏ธ Environment Variables (Example App)
538
434
 
435
+ ```bash
436
+ cp example-app/.env.example example-app/.env
539
437
  ```
540
- src/
541
- โ”œโ”€โ”€ components/ # Auth forms + News components + UI components
542
- โ”œโ”€โ”€ contexts/ # NAuthContext, NNewsContext, ThemeContext
543
- โ”œโ”€โ”€ hooks/ # useAuth, useUser, useArticles, useCategories, useTags, etc.
544
- โ”œโ”€โ”€ services/ # NAuth API client + News API services
545
- โ”œโ”€โ”€ types/ # TypeScript definitions (auth + news)
546
- โ”œโ”€โ”€ utils/ # Validators, formatters, utilities
547
- โ””โ”€โ”€ styles/ # Tailwind CSS
438
+
439
+ ```bash
440
+ VITE_API_URL=http://localhost:5007 # NAuth backend URL
441
+ VITE_NNEWS_API_URL=http://localhost:5008 # NNews backend URL
442
+ VITE_TENANT_ID=my-tenant # Tenant identifier
443
+ ```
444
+
445
+ ---
446
+
447
+ ## ๐Ÿงช Testing
448
+
449
+ ```bash
450
+ npm test # Run tests once
451
+ npm run test:watch # Watch mode
452
+ npm run test:coverage # Coverage report (text, JSON, HTML)
548
453
  ```
549
454
 
550
- ## Development
455
+ ---
456
+
457
+ ## ๐Ÿ”ง Development
551
458
 
552
459
  ```bash
553
- npm install # Install dependencies
554
- npm run dev # Development mode
555
- npm run build # Build library
556
- npm test # Run tests
557
- npm run lint # Run ESLint
460
+ # Library (root)
461
+ npm install # Install dependencies
462
+ npm run dev # Vite dev server
463
+ npm run build # Type-check + Vite build (outputs to dist/)
464
+ npm run lint # ESLint
465
+ npm run type-check # tsc --noEmit
466
+
467
+ # Example App (example-app/)
468
+ cd example-app
469
+ npm install
470
+ npm run dev # Start dev server
471
+ npm run build # Production build
558
472
  ```
559
473
 
560
- ## Publishing
474
+ ### Build Output
475
+
476
+ The library outputs both ESM and CJS with TypeScript declarations:
477
+
478
+ | File | Description |
479
+ |------|-------------|
480
+ | `dist/index.js` | ES Module bundle |
481
+ | `dist/index.cjs` | CommonJS bundle |
482
+ | `dist/index.d.ts` | TypeScript declarations |
483
+ | `dist/style.css` | Bundled CSS styles |
484
+
485
+ ---
486
+
487
+ ## ๐Ÿ”„ CI/CD
488
+
489
+ ### GitHub Actions
490
+
491
+ - **version-tag.yml** โ€” Semantic versioning with GitVersion on push to `main`
492
+ - **npm-publish.yml** โ€” Publishes to NPM on tag creation
493
+ - **create-release.yml** โ€” GitHub release creation
494
+
495
+ ---
496
+
497
+ ## ๐Ÿ“– Additional Documentation
498
+
499
+ | Document | Description |
500
+ |----------|-------------|
501
+ | [AI Features Guide](docs/AI_FEATURES_GUIDE.md) | ChatGPT and DALL-E 3 integration details |
502
+ | [Changelog](docs/CHANGELOG.md) | Version history and changes |
503
+ | [Role API Documentation](docs/ROLE_API_DOCUMENTATION.md) | Role management API reference |
504
+ | [Testing Guide](docs/TESTING_GUIDE.md) | Testing patterns and conventions |
505
+ | [Update Summary](docs/UPDATE_SUMMARY.md) | Recent update summary |
506
+ | [User API Documentation](docs/USER_API_DOCUMENTATION.md) | User management API reference |
507
+
508
+ ---
509
+
510
+ ## ๐Ÿ“ฆ Publishing
561
511
 
562
512
  ```bash
563
513
  npm run build
564
514
  npm publish --access public
565
515
  ```
566
516
 
567
- ## License
517
+ ---
518
+
519
+ ## ๐Ÿค Contributing
520
+
521
+ 1. Fork the repository
522
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
523
+ 3. Make your changes
524
+ 4. Run tests (`npm test`)
525
+ 5. Commit your changes (`git commit -m 'feat: add amazing feature'`)
526
+ 6. Push to the branch (`git push origin feature/amazing-feature`)
527
+ 7. Open a Pull Request
528
+
529
+ ---
530
+
531
+ ## ๐Ÿ‘จโ€๐Ÿ’ป Author
532
+
533
+ Developed by **[Rodrigo Landim](https://github.com/landim32)**
534
+
535
+ ---
536
+
537
+ ## ๐Ÿ“„ License
538
+
539
+ This project is licensed under the **MIT License** โ€” see the [LICENSE](LICENSE) file for details.
540
+
541
+ ---
542
+
543
+ ## ๐Ÿ“ž Support
568
544
 
569
- MIT ยฉ [Rodrigo Landim](https://github.com/landim32)
545
+ - **Issues**: [GitHub Issues](https://github.com/landim32/NNews.React/issues)
546
+ - **NPM**: [nnews-react](https://www.npmjs.com/package/nnews-react)
570
547
 
571
- ## Links
548
+ ---
572
549
 
573
- - [GitHub](https://github.com/landim32/NNews.React)
574
- - [NPM](https://www.npmjs.com/package/nnews-react)
575
- - [Documentation](https://github.com/landim32/NNews.React#readme)
550
+ **โญ If you find this project useful, please consider giving it a star!**