nnews-react 0.0.3

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 NAuth Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,575 @@
1
+ # nnews-react
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.
4
+
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)
7
+
8
+ ## Features
9
+
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
16
+
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
24
+
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
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ npm install nnews-react react react-dom react-router-dom
35
+
36
+ # If you don't have Tailwind CSS
37
+ npm install -D tailwindcss postcss autoprefixer tailwindcss-animate
38
+ npx tailwindcss init -p
39
+ ```
40
+
41
+ ### Configure Tailwind
42
+
43
+ ```javascript
44
+ // tailwind.config.js
45
+ export default {
46
+ darkMode: ['class'],
47
+ 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
65
+ ],
66
+ };
67
+ ```
68
+
69
+ ```css
70
+ /* src/index.css */
71
+ @tailwind base;
72
+ @tailwind components;
73
+ @tailwind utilities;
74
+ ```
75
+
76
+ ## Quick Start
77
+
78
+ ### 1. Setup Providers
79
+
80
+ ```tsx
81
+ import { BrowserRouter } from 'react-router-dom';
82
+ import { NAuthProvider, NNewsProvider, ThemeProvider } from 'nnews-react';
83
+ import 'nnews-react/styles';
84
+ import './index.css';
85
+
86
+ function App() {
87
+ 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');
164
+ }}
165
+ onCancel={() => navigate('/users')}
166
+ />
167
+ );
168
+ }
169
+ ```
170
+
171
+ ### 3. Use Content Management Components
172
+
173
+ ```tsx
174
+ import {
175
+ ArticleList,
176
+ ArticleViewer,
177
+ ArticleEditor,
178
+ CategoryList,
179
+ CategoryModal,
180
+ TagList,
181
+ TagModal,
182
+ useArticles,
183
+ useCategories,
184
+ useTags,
185
+ } from 'nnews-react';
186
+
187
+ // Articles List Page
188
+ function ArticlesPage() {
189
+ const { articles, loading, fetchArticles, deleteArticle } = useArticles();
190
+
191
+ useEffect(() => {
192
+ fetchArticles({ page: 1, pageSize: 20 });
193
+ }, []);
194
+
195
+ 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`)}
226
+ showActions
227
+ />
228
+ );
229
+ }
230
+
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
+ }
265
+
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);
271
+
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
+ );
299
+ }
300
+ ```
301
+
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
310
+
311
+ ### User Management
312
+ - `UserEditForm` - Create and edit users with full profile management (dual mode)
313
+ - `SearchForm` - Search and browse users with pagination
314
+
315
+ ### Role Management
316
+ - `RoleList` - List and manage roles with CRUD operations
317
+ - `RoleForm` - Create and edit roles
318
+
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
328
+
329
+ ### UI Components
330
+ `Button`, `Input`, `Label`, `Card`, `Avatar`, `DropdownMenu`, `Toaster`
331
+
332
+ ## Hooks
333
+
334
+ ### Authentication Hooks
335
+ ```tsx
336
+ // Authentication state
337
+ const { user, isAuthenticated, login, logout, isLoading } = useAuth();
338
+
339
+ // User management
340
+ 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();
358
+ ```
359
+
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();
374
+
375
+ // Category management
376
+ const {
377
+ categories,
378
+ loading,
379
+ error,
380
+ fetchCategories,
381
+ getCategoryById,
382
+ createCategory,
383
+ updateCategory,
384
+ deleteCategory,
385
+ refresh,
386
+ } = useCategories();
387
+
388
+ // Tag management
389
+ const {
390
+ tags,
391
+ loading,
392
+ error,
393
+ fetchTags,
394
+ getTagById,
395
+ createTag,
396
+ updateTag,
397
+ deleteTag,
398
+ mergeTags,
399
+ refresh,
400
+ } = useTags();
401
+ ```
402
+
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';
440
+
441
+ const authApi = createNAuthClient({ apiUrl: 'https://your-api.com' });
442
+
443
+ await authApi.login({ email, password });
444
+ await authApi.getMe();
445
+ await authApi.updateUser({ name: 'New Name' });
446
+ await authApi.uploadImage(file);
447
+ ```
448
+
449
+ ### NNews API Services
450
+ ```tsx
451
+ import { ArticleAPI, CategoryAPI, TagAPI } from 'nnews-react';
452
+ import axios from 'axios';
453
+
454
+ const apiClient = axios.create({ baseURL: 'https://your-api.com' });
455
+
456
+ // Article API
457
+ const articleApi = new ArticleAPI(apiClient);
458
+ await articleApi.listArticles();
459
+ await articleApi.getArticleById(id);
460
+ await articleApi.createArticle(data);
461
+ await articleApi.updateArticle(data);
462
+ await articleApi.deleteArticle(id);
463
+
464
+ // Category API
465
+ const categoryApi = new CategoryAPI(apiClient);
466
+ await categoryApi.listCategories();
467
+ await categoryApi.createCategory(data);
468
+
469
+ // Tag API
470
+ const tagApi = new TagAPI(apiClient);
471
+ await tagApi.listTags();
472
+ await tagApi.mergeTags(sourceId, targetId);
473
+ ```
474
+
475
+ ## Customization
476
+
477
+ ```tsx
478
+ <LoginForm
479
+ className="shadow-2xl"
480
+ styles={{
481
+ container: 'bg-white',
482
+ button: 'bg-purple-600',
483
+ }}
484
+ />
485
+ ```
486
+
487
+ ## Utilities
488
+
489
+ ```tsx
490
+ import {
491
+ validateCPF,
492
+ validateCNPJ,
493
+ validateEmail,
494
+ formatPhone,
495
+ validatePasswordStrength,
496
+ cn, // Utility for merging Tailwind classes
497
+ } from 'nnews-react';
498
+ ```
499
+
500
+ ## Markdown Support
501
+
502
+ The Markdown editor supports:
503
+
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
513
+
514
+ ## TypeScript
515
+
516
+ ```tsx
517
+ 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,
534
+ } from 'nnews-react';
535
+ ```
536
+
537
+ ## Project Structure
538
+
539
+ ```
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
548
+ ```
549
+
550
+ ## Development
551
+
552
+ ```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
558
+ ```
559
+
560
+ ## Publishing
561
+
562
+ ```bash
563
+ npm run build
564
+ npm publish --access public
565
+ ```
566
+
567
+ ## License
568
+
569
+ MIT © [Rodrigo Landim](https://github.com/landim32)
570
+
571
+ ## Links
572
+
573
+ - [GitHub](https://github.com/landim32/NNews/tree/main/nnews-react)
574
+ - [NPM](https://www.npmjs.com/package/nnews-react)
575
+ - [Documentation](https://github.com/landim32/NNews/tree/main/nnews-react#readme)