@pawells/react-shared
v1.0.5
Published
Shared React utilities library for hooks, components, context, and HOCs
Maintainers
Readme
@pawells/react-shared
Shared React UI components, hooks, and notification context for @pawells applications. Built on MUI (Material UI).
Installation
yarn add @pawells/react-sharedMUI and React must be present as peer dependencies in your project.
Components
VoronoiBackground
Animated SVG canvas background using Voronoi/Delaunay triangulation. Renders an array of colored triangles that fill the viewport, derived from a seeded or random point distribution.
import { VoronoiBackground } from '@pawells/react-shared';
<VoronoiBackground primaryColor="#1a73e8" />
// With explicit gradient endpoints
<VoronoiBackground primaryColor="#1a73e8" secondaryColor="#e8f0fe" seed={42} />| Prop | Type | Default | Description |
|---|---|---|---|
| primaryColor | { r, g, b } \| string | — | Required. Primary gradient color (RGB object or hex string). When secondaryColor is omitted, a monochromatic gradient is derived from this color via HSV interpolation |
| secondaryColor | { r, g, b } \| string | derived | Secondary/end color. When omitted, the hue and saturation of primaryColor are preserved while brightness is set to 90% (bright) vs 10% (dark) |
| seed | number | Date.now() | Seed for deterministic random generation. Only read on initial mount; changes after mount are ignored |
| zIndex | number | -1 | CSS z-index for layering |
| opacity | number | 1 | Opacity of the entire background |
| overlay | string | — | CSS color with alpha for a darkening/lightening overlay, e.g. 'rgba(0,0,0,0.3)' |
| blur | number | 0 | Blur in pixels applied to the triangles |
| className | string | — | CSS class for the container div |
| style | React.CSSProperties | — | Inline styles for the container div |
| pointerEventsNone | boolean | true | Disables pointer events so clicks pass through to content below |
| pointCount | number | 98 | Number of internal seed points; higher values produce more polygons |
| edgePointCount | number | 20 | Points placed along each viewport edge to ensure full coverage |
| minAreaDivisor | number | 750 | Controls small-triangle pruning aggressiveness |
| maxPruningIterations | number | 10 | Maximum pruning iterations |
InactivityWarningDialog
Controlled dialog that warns the user about an upcoming session timeout. Displays a formatted countdown timer and "Stay Logged In" / "Logout Now" buttons. The parent component manages open state and callbacks.
import { InactivityWarningDialog } from '@pawells/react-shared';
<InactivityWarningDialog
open={isWarningActive}
countdownSeconds={countdownSeconds}
onStayLoggedIn={extendSession}
onLogout={async () => {
await auth.logout();
navigate('/login');
}}
/>| Prop | Type | Required | Description |
|---|---|---|---|
| open | boolean | Yes | Whether the dialog is visible |
| countdownSeconds | number | Yes | Remaining seconds before session timeout |
| onStayLoggedIn | () => void | Yes | Called when the user clicks "Stay Logged In" |
| onLogout | () => void \| Promise<void> | Yes | Called when the user clicks "Logout Now" or the countdown expires |
Pair with useInactivityWarning to manage state automatically.
LoadingState
Centered MUI spinner with an optional message. Suitable as a Suspense fallback or a data-loading placeholder.
import { LoadingState } from '@pawells/react-shared';
<LoadingState />
<LoadingState size="large" message="Fetching data..." />| Prop | Type | Default | Description |
|---|---|---|---|
| size | 'small' \| 'medium' \| 'large' | 'medium' | Spinner size |
| message | string | — | Text displayed below the spinner |
PageHeader
Page-level header with a title, optional subtitle, and optional action slot. Stacks vertically on mobile, displays as a row on desktop.
import { PageHeader } from '@pawells/react-shared';
<PageHeader
title="Dashboard"
subtitle="Welcome back"
actions={<Button variant="contained">Add User</Button>}
/>| Prop | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Main heading text (rendered as h1 / h4 variant) |
| subtitle | string | No | Subdued subtitle displayed below the title |
| actions | React.ReactNode | No | Action elements displayed on the right side |
StatCard
MUI Card that displays a metric with an icon and optional trending indicator. Includes a hover lift animation.
import { StatCard } from '@pawells/react-shared';
import PeopleIcon from '@mui/icons-material/People';
<StatCard
title="Total Users"
value="1,234"
icon={<PeopleIcon />}
color="success"
change={12}
/>| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | — | Required. Card title |
| value | string \| number | — | Required. Prominent metric value |
| icon | React.ReactNode | — | Required. Icon element displayed in the card |
| color | 'primary' \| 'success' \| 'warning' \| 'error' | 'primary' | MUI color theme applied to the value and icon |
| change | number | — | Percentage change; renders a trending chip with ↑/↓ indicator |
Hooks
useNotification / NotificationProvider
Global notification queue backed by MUI Snackbar + Alert. Supports up to 3 simultaneously visible notifications with auto-dismiss and manual dismiss.
import { NotificationProvider, useNotification } from '@pawells/react-shared';
// 1. Wrap your app (once, near the root)
<NotificationProvider>
<App />
</NotificationProvider>
// 2. Show notifications from any component
function SaveButton() {
const { showNotification } = useNotification();
const handleSave = async () => {
try {
await api.save();
showNotification('Saved successfully', 'success');
} catch {
showNotification('Failed to save', 'error');
}
};
return <button onClick={handleSave}>Save</button>;
}showNotification(message, severity, options?)
| Parameter | Type | Description |
|---|---|---|
| message | string | Notification text |
| severity | 'success' \| 'error' \| 'warning' \| 'info' | Alert severity level |
| options.duration | number | Auto-dismiss duration in ms. Defaults to 6000 |
Features: queue management (max 3 visible), responsive positioning (bottom-left on desktop, bottom-center on mobile), manual dismiss via close button.
useInactivityWarning
Tracks user inactivity via DOM events (mousedown, keydown, scroll, touchstart, click) and triggers a countdown warning before the session expires.
import {
useInactivityWarning,
InactivityWarningDialog,
} from '@pawells/react-shared';
function App() {
const { isAuthenticated, logout } = useAuth();
const { isWarningActive, countdownSeconds, extendSession } = useInactivityWarning({
timeoutMinutes: 30,
warningSeconds: 60,
onTimeout: async () => {
await logout();
navigate('/login');
},
});
return (
<>
<Routes />
{isAuthenticated && (
<InactivityWarningDialog
open={isWarningActive}
countdownSeconds={countdownSeconds}
onStayLoggedIn={extendSession}
onLogout={logout}
/>
)}
</>
);
}Config
| Option | Type | Default | Description |
|---|---|---|---|
| timeoutMinutes | number | 60 | Total inactivity timeout before onTimeout is called |
| warningSeconds | number | 300 | How many seconds before timeout to show the warning |
| onTimeout | () => void \| Promise<void> | — | Required. Called when the countdown reaches zero |
Return value
| Field | Type | Description |
|---|---|---|
| isWarningActive | boolean | Whether the warning dialog should be shown |
| countdownSeconds | number | Remaining seconds shown in the countdown |
| extendSession | () => void | Resets the inactivity timer and hides the warning |
| dismissWarning | () => void | Hides the warning without resetting the timer |
