@jmruthers/pace-core
v0.6.2
Published
Clean, modern React component library with Tailwind v4 styling and native utilities
Maintainers
Readme
@jmruthers/pace-core
Clean, modern React component library with Tailwind v4 styling and native utilities.
⚠️ Breaking Changes
Version 0.5.65+ - Mandatory Inactivity Timeouts
The UnifiedAuthProvider now requires mandatory inactivity timeout configuration for security:
// ❌ Before (will cause TypeScript errors)
<UnifiedAuthProvider supabaseClient={supabase} appName="my-app">
<AppContent />
</UnifiedAuthProvider>
// ✅ After (required configuration)
<UnifiedAuthProvider
supabaseClient={supabase}
appName="my-app"
idleTimeoutMs={30 * 60 * 1000} // Required
warnBeforeMs={5 * 60 * 1000} // Required
onIdleLogout={() => navigate('/login')} // Required
>
<AppContent />
</UnifiedAuthProvider>🚀 PaceAppLayout Usage
PaceAppLayout uses React Router's nested routing pattern for optimal performance and scalability.
// ✅ Correct usage with React Router
<Router>
<Routes>
<Route path="/" element={<PaceAppLayout appName="My App" />}>
<Route path="dashboard" element={<Dashboard />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
</Router>📦 Type System
PACE Core uses a domain-driven type organization for better maintainability and discoverability:
// Import from domain-specific modules
import type { Event } from '@jmruthers/pace-core/types/event';
import type { Organisation } from '@jmruthers/pace-core/types/organisation';
import type { User, Session } from '@jmruthers/pace-core/types/auth';
import type { UserId, AppId, PageId } from '@jmruthers/pace-core/types/core';
import type { RBACPermissionCheckParams } from '@jmruthers/pace-core/rbac/types/functions';See the Types API Reference for complete type documentation.
🚀 Complete Installation Guide
1. Install Dependencies
# Install pace-core and required peer dependencies
npm install @jmruthers/pace-core @tanstack/react-table @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-slot lucide-react class-variance-authority clsx tailwind-merge
# Install Tailwind CSS v4 and Vite plugin
npm install -D @tailwindcss/vite tailwindcss@^4.0.02. Import Core Styles
// src/main.tsx (or your app's entry point)
import '@jmruthers/pace-core/src/styles/core.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
// React 19+ with createRoot
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);3. Configure Vite with Tailwind v4
⚠️ CRITICAL: This configuration is required for:
- Tailwind CSS scanning - Ensures components are styled
- React context consistency - Prevents "useUnifiedAuth must be used within a UnifiedAuthProvider" errors
- Router context availability - Prevents "useNavigate() may be used only in the context of a " errors
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import path from 'path'
export default defineConfig({
plugins: [
react({
// React Compiler for automatic optimizations (React 19+)
babel: {
plugins: ['babel-plugin-react-compiler'],
},
}),
tailwindcss({
// Only need to scan your app's source files
// pace-core source files are automatically scanned via @source directives
content: [
'./src/**/*.{js,ts,jsx,tsx}'
]
})
],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
// CRITICAL: Dedupe React and React Router to ensure single instances
// This prevents Router context issues when pace-core uses react-router-dom
dedupe: ['react', 'react-dom', 'react-router-dom']
},
// CRITICAL: Exclude pace-core from pre-bundling to prevent React context mismatches
// Pre-bundling creates separate React instances, causing context errors
optimizeDeps: {
include: [
'react',
'react-dom',
'react/jsx-runtime',
'@radix-ui/react-slot'
],
// CRITICAL: Exclude pace-core from pre-bundling
// This ensures pace-core uses the same React instance as your app
// NOTE: react-router-dom should be INCLUDED, not excluded (excluding causes "module is not defined" errors)
exclude: ['@jmruthers/pace-core']
},
server: {
port: 3000,
open: true,
},
build: {
outDir: 'dist',
sourcemap: true,
},
})Fallback Configuration: If the CSS-first approach doesn't work, you can explicitly include pace-core source files:
// vite.config.ts - Fallback configuration
export default defineConfig({
plugins: [
react(),
tailwindcss({
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/@jmruthers/pace-core/src/**/*.{js,ts,jsx,tsx}'
]
})
],
// ... rest of config
})4. Verify Installation
Create a test component to ensure everything works:
// src/App.tsx
import { Button, Card, Input } from '@jmruthers/pace-core';
function App() {
return (
<div className="p-8 space-y-4">
<h1 className="text-2xl font-bold text-main-900">PACE Core Test</h1>
<Card className="p-4">
<h2 className="text-lg font-semibold text-sec-800 mb-2">Components Test</h2>
<div className="space-y-2">
<Button variant="primary" className="bg-main-600 text-main-50">
Primary Button
</Button>
<Button variant="secondary" className="bg-sec-500 text-main-50">
Secondary Button
</Button>
<Input placeholder="Test input field" className="border-main-300" />
</div>
</Card>
</div>
);
}
export default App;Expected Result: You should see properly styled components with PACE Core's design system colors and typography.
⚠️ Critical Configuration Notes
Why Source File Scanning is Required
Pace-core v0.4.15+ includes source files in the published package because:
- Tailwind v4 needs to scan original TypeScript/JSX files to detect utility classes
- Compiled JavaScript files don't contain the class names Tailwind needs
- Without proper scanning, only ~292 CSS rules are generated instead of 800+ needed
Alternative Configuration (if source files don't work)
If you're still having issues with component scanning:
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
react(),
tailwindcss({
content: [
'./src/**/*.{js,ts,jsx,tsx}',
// Try source files first
'./node_modules/@jmruthers/pace-core/src/**/*.{js,ts,jsx,tsx}',
// Fallback: also scan dist files
'./node_modules/@jmruthers/pace-core/dist/**/*.{js,ts,jsx,tsx}'
]
})
],
})Legacy Configuration (v0.4.14 and below)
For older versions, use this configuration:
// vite.config.ts
export default defineConfig({
plugins: [
react(),
tailwindcss({
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/@jmruthers/pace-core/**/*.{js,ts,jsx,tsx}'
]
})
],
})🔍 Troubleshooting
Issue: "useUnifiedAuth must be used within a UnifiedAuthProvider"
Cause: Vite is pre-bundling @jmruthers/pace-core, creating separate React instances
Solution:
- Add to
vite.config.ts:optimizeDeps: { exclude: ['@jmruthers/pace-core', 'react-router-dom'] } - Clear Vite cache:
rm -rf node_modules/.vite - Restart dev server
Issue: "useNavigate() may be used only in the context of a component"
Cause: Incorrect provider nesting - BrowserRouter should wrap UnifiedAuthProvider
Solution:
- Ensure correct nesting order in
main.tsx:<QueryClientProvider> <BrowserRouter> <UnifiedAuthProvider> <OrganisationProvider> <App /> </OrganisationProvider> </UnifiedAuthProvider> </BrowserRouter> </QueryClientProvider> - Do NOT put BrowserRouter inside UnifiedAuthProvider
- Add to
vite.config.ts:resolve: { dedupe: ['react', 'react-dom', 'react-router-dom'] }
Issue: Only 292 CSS rules instead of 800+
Solution:
- Update to pace-core v0.4.15+
- Use source file paths:
./node_modules/@jmruthers/pace-core/src/**/*.{js,ts,jsx,tsx} - Clear build cache:
rm -rf dist .vite node_modules && npm install
Issue: Components appear unstyled
Solution:
- Check your Vite configuration includes pace-core source files
- Ensure CSS file is imported:
import '@jmruthers/pace-core/src/styles/core.css' - Restart dev server after configuration changes
Issue: Build errors with source files
Solution: Add TypeScript configuration for node_modules:
// tsconfig.json
{
"compilerOptions": {
"skipLibCheck": true
}
}Issue: "Access Denied" errors with valid permissions
Problem: Users with valid permissions see "Access Denied" when loading pages with DataTable components.
Root Cause: Race condition in permission checking - useCan hook was being called with invalid scopes before scope resolution completed.
Solution: Fixed in v0.5.7+ - the useCan hook now properly handles invalid scopes and shows loading state until valid scope is available.
What was fixed:
useCanhook skips API calls whenorganisationIdis emptyPagePermissionGuardshows loading state during scope resolution- Eliminates race condition between scope resolution and permission checking
No action needed - this is automatically fixed in v0.5.7+
Features
- 🎨 Complete Design System - Colors, typography, spacing, shadows
- 🧩 React Components - Buttons, inputs, cards, data tables, and more
- 🔐 RBAC System - Role-based access control with Supabase
- 🎨 Tailwind v4 - CSS-first approach with design tokens
- 📱 Responsive - Mobile-first design patterns
- ♿ Accessible - WCAG compliant components
- 🚀 Performance - Tree-shakeable, optimized bundle
Documentation
- Quick Start Guide - Complete step-by-step tutorial
- Installation Guide - Detailed setup instructions
- Vite Configuration - CRITICAL Tailwind scanning setup
- Component API - All available components and hooks
- Styling Guide - Understanding the design system
- Troubleshooting - Fix common styling problems
- Tailwind Content Scanning - NEW Comprehensive scanning solutions
Import Strategy
PACE Core provides two import paths to optimize for different use cases:
Main Export (Recommended for Common Components)
Use the main export for frequently used components and utilities:
import {
Button,
Card,
Input,
DropdownMenu,
Select,
Dialog,
useUnifiedAuth
} from '@jmruthers/pace-core';Available from main export:
- Basic UI: Button, Card, Input, Textarea, Label, Alert, Avatar, Checkbox, Progress
- Advanced UI: Dialog (with HTML content), DropdownMenu, Select, Toast, Tooltip, Tabs, Calendar
- Data Display: DataTable (with hierarchical actions & expand/collapse all), Table
- Forms: Form, LoginForm
- Layout: PaceAppLayout, Header, Footer, NavigationMenu
- Providers: UnifiedAuthProvider, OrganisationProvider, EventProvider
- Hooks: useUnifiedAuth, useOrganisations, useEvents
Component Documentation
- DataTable Component - Enterprise-grade data table with hierarchical rows, expand/collapse all, actions, sorting, filtering, and performance optimization
- Hierarchical DataTable Guide - Complete guide for implementing parent/child rows with expand/collapse all and smart sorting
- Dialog Component - Comprehensive dialog system with smart height management, scrolling, HTML content rendering, and accessibility features
- Storage System - File storage utilities with organization-scoped access control
Complete Components Export (For Specialized Components)
Use the complete export for specialized or advanced components:
import {
DataTable,
NavigationMenu,
FormField
} from '@jmruthers/pace-core/components';License
MIT License - see LICENSE for details.
