@jsarc/core
v0.0.1-beta.1.2
Published
CORE est un ensemble de hooks et utilitaires de routage avancés pour les applications React avec TypeScript/JavaScript. Il fournit des fonctionnalités de navigation avancées, une gestion automatique des langues et des utilitaires pour simplifier le dévelo
Readme
@jsarc/core
@jsarc/core est un ensemble de hooks et utilitaires de routage avancés pour les applications React avec TypeScript/JavaScript. Il fournit des fonctionnalités de navigation avancées, une gestion automatique des langues et des utilitaires pour simplifier le développement d'applications React Router.
✨ Fonctionnalités Principales
🧭 Navigation Avancée
- Navigation type-safe avec validation des paramètres
- Gestion automatique des query strings avec support multi-langue
- Résolution de routes avec paramètres dynamiques
- Navigation avec rechargement pour les mises à jour critiques
- Analyse d'URL complète avec extraction des données
🌍 Support Multi-Langue
- Gestion automatique du paramètre de langue
lang - Support intégré pour français et anglais
- Fallback sécurisé vers le français par défaut
- Codes de langue standardisés (fr_FR, en_US)
⚡ Utilitaires de Routage
- Validation de route actuelle avec correspondance de chemin
- Extraction des paramètres de query string
- Génération d'URL avec paramètres et queries
- Navigation externe vers des URL spécifiques
🛡️ Gestion d'Erreurs
- Fallback sécurisé pour les routes invalides
- Validation stricte des paramètres d'entrée
- Logs détaillés en mode développement
- Types TypeScript complets pour une meilleure autocomplétion
📦 Installation
Via npm/yarn/pnpm
npm install @jsarc/core react-router-dom @jsarc/qust react
# ou
yarn add @jsarc/core react-router-dom @jsarc/qust react
# ou
pnpm add @jsarc/core react-router-dom @jsarc/qust reactDépendances requises
- React 18+
- React Router DOM 6+
- TypeScript 5.0+ (recommandé)
- @jsarc/qust 1.0.0+ (pour la manipulation de query strings)
🚀 Démarrage Rapide
Configuration de base
// main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);Utilisation du hook principal
// App.tsx
import { useRootingActions } from '@jsarc/core';
const App = () => {
const {
params,
queries,
resolveRoute,
goToRoute,
checkIfIsCurrentRoute
} = useRootingActions();
// Navigation vers une page avec paramètres
const navigateToUser = (userId: string) => {
goToRoute({
path: '/users/:id',
params: { id: userId },
queries: { lang: 'fr', view: 'profile' }
});
};
// Vérifier si on est sur la page d'accueil
const isHome = checkIfIsCurrentRoute('/');
return (
<div>
<h1>Mon Application</h1>
{isHome && <p>Vous êtes sur la page d'accueil</p>}
<button onClick={() => navigateToUser('123')}>
Voir l'utilisateur 123
</button>
</div>
);
};
export default App;📚 Documentation API
Hook useRootingActions
import { useRootingActions } from '@jsarc/core';
const MyComponent = () => {
const {
// Paramètres de l'URL actuelle
params, // { id: "123", slug: "article" }
queries, // { lang: "fr", page: "1" }
pathName, // "/users/123/profile"
urlSearch, // "?lang=fr&page=1"
// Fonctions de navigation
navigate, // navigate() de react-router-dom
resolveRoute, // Générer une URL complète
goToRoute, // Naviguer vers une route
goAndReloadRoute, // Naviguer avec rechargement
goToUrl, // Naviguer vers une URL externe
// Utilitaires
getParams, // Obtenir les paramètres d'URL
getUrlData, // Analyser une URL
checkIfIsCurrentRoute // Vérifier la route actuelle
} = useRootingActions();
return (
<div>
<p>ID Utilisateur: {params.id}</p>
<p>Langue: {queries.lang || 'fr'}</p>
</div>
);
};Interfaces principales
// Configuration de navigation
interface ConfigGoToRoute {
path?: string; // Chemin de la route (ex: "/users/:id")
params?: any; // Paramètres de route (ex: { id: "123" })
queries?: any; // Query parameters (ex: { lang: "fr" })
refreshPage?: boolean; // Forcer le rechargement
replace?: boolean; // Remplacer l'historique
enableLoader?: boolean; // Afficher un loader
}
// Configuration de résolution
interface ConfigResolveRoute {
path?: string;
params?: any;
queries?: any;
}
// Configuration de navigation externe
interface ConfigGoToSpecificUrl {
path?: string;
queries?: any;
refreshPage?: boolean;
replace?: boolean;
enableLoader?: boolean;
}
// Valeur de retour du hook
interface RootingActionReturns {
params: Readonly<Params<string>>;
queries: any;
getParams: () => URLSearchParams;
navigate: NavigateFunction;
resolveRoute: (config: ConfigResolveRoute) => string;
goToRoute: (config: ConfigGoToRoute) => void;
goAndReloadRoute: (config: ConfigGoAndReloadRoute) => void;
pathName: string;
urlSearch: string;
getUrlData: (url: string | URL) => {
host: string;
hostname: string;
pathname: string;
search: string;
queries: any;
} | undefined;
goToUrl: (config: ConfigGoToSpecificUrl) => string;
checkIfIsCurrentRoute: (path?: string, exact?: boolean, strict?: boolean) => boolean;
}Fonctions utilitaires
import { nativeResolveRoute, getLang, getLangCode } from '@jsarc/core';
// Générer une URL sans utiliser le hook
const userProfileUrl = nativeResolveRoute({
path: '/users/:id/profile',
params: { id: '456' },
queries: { lang: 'en', tab: 'settings' }
});
// Résultat: "/users/456/profile?lang=en&tab=settings"
// Gestion des langues
const currentLang = getLang('fr'); // "fr" (valide)
const fallbackLang = getLang('es'); // "fr" (fallback)
const langCode = getLangCode('en'); // "en_US"🔧 Utilisation Avancée
Navigation avec gestion de langue
const LanguageAwareNavigation = () => {
const { goToRoute, queries } = useRootingActions();
const currentLang = queries.lang || 'fr';
const navigateWithLang = (path: string, params?: any, additionalQueries?: any) => {
goToRoute({
path,
params,
queries: {
...additionalQueries,
lang: currentLang
}
});
};
return (
<div>
<button onClick={() => navigateWithLang('/about', null, { section: 'team' })}>
Voir l'équipe
</button>
</div>
);
};Analyse d'URL externe
const UrlAnalyzer = () => {
const { getUrlData } = useRootingActions();
const analyzeUrl = () => {
const urlData = getUrlData('https://example.com/products/123?color=red&size=L');
if (urlData) {
console.log('Host:', urlData.host); // "example.com"
console.log('Path:', urlData.pathname); // "/products/123"
console.log('Queries:', urlData.queries); // { color: "red", size: "L" }
}
};
return (
<button onClick={analyzeUrl}>
Analyser l'URL
</button>
);
};Navigation conditionnelle
const SmartNavigation = () => {
const { goToRoute, checkIfIsCurrentRoute } = useRootingActions();
const navigateSmartly = (path: string) => {
// Si déjà sur la page, ne rien faire
if (checkIfIsCurrentRoute(path)) {
return;
}
// Sinon, naviguer
goToRoute({ path });
};
return (
<nav>
<button onClick={() => navigateSmartly('/')}>
Accueil
</button>
<button onClick={() => navigateSmartly('/about')}>
À propos
</button>
</nav>
);
};🎯 Exemples Complets
Exemple 1 : Formulaire avec redirection
import { useState } from 'react';
import { useRootingActions } from '@jsarc/core';
const ContactForm = () => {
const { goToRoute, goAndReloadRoute } = useRootingActions();
const [formData, setFormData] = useState({ name: '', email: '', message: '' });
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
// Envoyer les données
const response = await fetch('/api/contact', {
method: 'POST',
body: JSON.stringify(formData)
});
if (response.ok) {
// Redirection simple vers la page de confirmation
goToRoute({
path: '/contact/success',
queries: { ref: 'contact-form' }
});
} else {
// Redirection avec rechargement pour nettoyer les erreurs
goAndReloadRoute({
path: '/contact',
queries: { error: 'submission_failed' }
});
}
} catch (error) {
goToRoute({
path: '/contact',
queries: { error: 'network_error' }
});
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={formData.name}
onChange={e => setFormData({...formData, name: e.target.value})}
placeholder="Votre nom"
/>
<input
type="email"
value={formData.email}
onChange={e => setFormData({...formData, email: e.target.value})}
placeholder="Votre email"
/>
<textarea
value={formData.message}
onChange={e => setFormData({...formData, message: e.target.value})}
placeholder="Votre message"
rows={4}
/>
<button type="submit">
Envoyer
</button>
</form>
);
};Exemple 2 : Système de pagination
import { useRootingActions } from '@jsarc/core';
const PaginatedList = ({ items, currentPage, totalPages }) => {
const { goToRoute, queries } = useRootingActions();
const goToPage = (page: number) => {
goToRoute({
path: '/items',
queries: {
...queries,
page: page.toString()
}
});
};
return (
<div>
<h2>Liste des éléments</h2>
{/* Liste des éléments */}
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
{/* Pagination */}
<div className="pagination">
<button
disabled={currentPage <= 1}
onClick={() => goToPage(currentPage - 1)}
>
Précédent
</button>
<span>Page {currentPage} sur {totalPages}</span>
<button
disabled={currentPage >= totalPages}
onClick={() => goToPage(currentPage + 1)}
>
Suivant
</button>
</div>
</div>
);
};Exemple 3 : Menu de navigation intelligent
import { useRootingActions } from '@jsarc/core';
const NavigationMenu = () => {
const { goToRoute, checkIfIsCurrentRoute } = useRootingActions();
const menuItems = [
{ path: '/', label: 'Accueil' },
{ path: '/products', label: 'Produits' },
{ path: '/about', label: 'À propos' },
{ path: '/contact', label: 'Contact' }
];
return (
<nav className="navigation">
{menuItems.map(item => {
const isActive = checkIfIsCurrentRoute(item.path);
return (
<button
key={item.path}
className={`nav-item \${isActive ? 'active' : ''}`}
onClick={() => goToRoute({ path: item.path })}
>
{item.label}
</button>
);
})}
</nav>
);
};Exemple 4 : Sélecteur de langue
import { useRootingActions } from '@jsarc/core';
const LanguageSelector = () => {
const { goToRoute, queries } = useRootingActions();
const currentLang = queries.lang || 'fr';
const languages = [
{ code: 'fr', name: 'Français', flag: '🇫🇷' },
{ code: 'en', name: 'English', flag: '🇬🇧' },
{ code: 'es', name: 'Español', flag: '🇪🇸' }
];
const changeLanguage = (langCode: string) => {
goToRoute({
path: (window as any).location.pathname,
queries: {
...queries,
lang: langCode
}
});
};
return (
<div className="language-selector">
{languages.map(lang => (
<button
key={lang.code}
className={`lang-btn \${currentLang === lang.code ? 'active' : ''}`}
onClick={() => changeLanguage(lang.code)}
title={lang.name}
>
{lang.flag} {lang.name}
</button>
))}
</div>
);
};🔧 Configuration
Configuration des langues
// Configuration par défaut dans @jsarc/core
export const langs = ['en', 'fr']; // Langues supportées
export const langCodes = {
'fr': 'fr_FR',
'en': 'en_US',
};Variables d'environnement
# .env
NODE_ENV=development # development | debug | production🛡️ Gestion des Erreurs
Fallback sécurisé
const SafeNavigation = () => {
const { resolveRoute, goToRoute } = useRootingActions();
const safeGoToRoute = (config: ConfigGoToRoute) => {
try {
goToRoute(config);
} catch (error) {
console.error('Navigation error:', error);
// Fallback vers la page d'accueil
goToRoute({ path: '/' });
}
};
return (
<button onClick={() => safeGoToRoute({ path: '/invalid-route' })}>
Naviguer en sécurité
</button>
);
};📋 Table des Conventions
Paramètres de query string
| Paramètre | Type | Description | Valeur par défaut |
|-----------|------|-------------|-------------------|
| lang | fr | en | Langue de l'application | fr |
| page | number | Numéro de page | 1 |
| sort | string | Tri des résultats | date |
| filter | string | Filtre appliqué | all |
Codes de langue
| Code court | Code long | Description |
|------------|-----------|-------------|
| fr | fr_FR | Français (France) |
| en | en_US | Anglais (États-Unis) |
🔧 Build et Développement
Scripts recommandés
{
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"type-check": "tsc --noEmit"
}
}Configuration TypeScript
{
"compilerOptions": {
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ES2020"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"types": ["vite/client"]
},
"include": ["src", "node_modules/@jsarc/core/**/*"]
}📄 Licence
MIT License - Voir le fichier LICENSE pour plus de détails.
🐛 Signaler un Bug
Envoyez nous un mail à l'adresse [email protected] pour :
- Signaler un bug
- Proposer une amélioration
- Poser une question
@jsarc/core - Les hooks et utilitaires de routage avancés pour React et TypeScript.
Développé par l'équipe INICODE
