@websolutespa/bom-mixer-hooks
v1.9.2
Published
Mixer Hooks module of the BOM Repository
Readme
@websolutespa/bom-mixer-hooks
Mixer Hooks module of the BOM Repository by websolute.
this library is for internal usage and not production ready
@websolutespa/bom-mixer-hooks Documentation
A collection of React hooks for building modern web applications.
Table of Contents
- Installation
- API and Networking
- UI and Layout
- Form and Input
- Internationalization
- Scroll and Viewport
- State Management
- Performance
- Event Handling
Installation
npm install @websolutespa/bom-mixer-hooksAPI and Networking
useApi
Hook for making RESTful API calls.
import { useApi } from '@websolutespa/bom-mixer-hooks';
function MyComponent() {
const api = useApi();
const fetchData = async () => {
try {
// GET request
const data = await api.get('/endpoint');
// POST request with payload
const response = await api.post('/endpoint', {
name: 'John',
});
// PUT request
await api.put('/endpoint/1', {
updated: true,
});
// DELETE request
await api.delete('/endpoint/1');
} catch (error) {
console.error('API error:', error);
}
};
}useCollectionApi
Specialized version of useApi for data collections.
import { useCollectionApi, useCollectionApiGet } from '@websolutespa/bom-mixer-hooks';
function MyCollection() {
const [data, loading, error] = useCollectionApiGet('/collection', {
where: { status: 'active' }
});
if (loading) return <Loading />;
if (error) return <Error message={error.message} />;
return (
<div>
{data.map(item => (
<Item key={item.id} {...item} />
))}
</div>
);
}UI and Layout
useLayout
Manages the global application layout.
import { useLayout } from '@websolutespa/bom-mixer-hooks';
function Header() {
const layout = useLayout();
return (
<header>
<nav>
{layout.menu.main.items.map(item => (
<MenuItem key={item.id} {...item} />
))}
</nav>
</header>
);
}useDrawer
Manages drawer/sidebar state.
import { useDrawer } from '@websolutespa/bom-mixer-hooks';
function Sidebar() {
const [drawer, openDrawer, closeDrawer] = useDrawer();
return (
<>
<button onClick={() => openDrawer('main')}>Open Menu</button>
<div className={`drawer ${drawer === 'main' ? 'open' : ''}`}>
<button onClick={closeDrawer}>Close</button>
{/* Drawer content */}
</div>
</>
);
}useBreakpoint
Handles responsive breakpoints.
import { useBreakpoint } from '@websolutespa/bom-mixer-hooks';
function ResponsiveComponent() {
const breakpoint = useBreakpoint();
return (
<div>
{breakpoint.key === 'xs' && <MobileView />}
{breakpoint.key === 'md' && <TabletView />}
{breakpoint.key === 'lg' && <DesktopView />}
</div>
);
}Form and Input
useAutosizeTextArea
Automatically adjusts textarea height.
import { useAutosizeTextArea } from '@websolutespa/bom-mixer-hooks';
function AutoResizingTextarea() {
const [value, setValue] = useState('');
const textAreaRef = useRef<HTMLTextAreaElement>(null);
useAutosizeTextArea(textAreaRef.current, value);
return (
<textarea
ref={textAreaRef}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}useFocusTrap
Keeps focus within an element (useful for modals).
import { useFocusTrap } from '@websolutespa/bom-mixer-hooks';
function Modal() {
const modalRef = useRef(null);
const [isTrapped, setIsTrapped] = useFocusTrap(modalRef);
useEffect(() => {
setIsTrapped(true);
return () => setIsTrapped(false);
}, []);
return (
<div ref={modalRef}>
<input type="text" />
<button>Action</button>
<button>Close</button>
</div>
);
}Internationalization
useLabel
Manages translations.
import { useLabel } from '@websolutespa/bom-mixer-hooks';
function Translated() {
const label = useLabel();
return (
<div>
<h1>{label('welcome.title')}</h1>
<p>{label('welcome.description', { name: 'John' })}</p>
</div>
);
}useCurrency
Formats monetary values.
import { useCurrency } from '@websolutespa/bom-mixer-hooks';
function PriceDisplay() {
const formatCurrency = useCurrency('EUR', 'en-US');
return (
<div>
<p>Price: {formatCurrency(29.99)}</p> {/* Outputs: €29.99 */}
</div>
);
}Scroll and Viewport
useIntersectionObserver
Observes when elements enter the viewport.
import { useIntersectionObserver } from '@websolutespa/bom-mixer-hooks';
function LazyImage() {
const ref = useRef(null);
const isVisible = useIntersectionObserver(ref, {
threshold: 0.1
});
return (
<div ref={ref}>
{isVisible && <img src="heavy-image.jpg" alt="Lazy loaded" />}
</div>
);
}useScrollTo
Manages smooth scrolling to elements.
import { useScrollTo } from '@websolutespa/bom-mixer-hooks';
function ScrollableContent() {
const scrollTo = useScrollTo(80); // 80px offset
return (
<nav>
<a href="#section1" onClick={scrollTo}>Go to Section 1</a>
<div id="section1">
{/* Content */}
</div>
</nav>
);
}State Management
useCurrentState
Manages state with current reference.
import { useCurrentState } from '@websolutespa/bom-mixer-hooks';
function StateManager() {
const [value, setValue, valueRef] = useCurrentState(0);
useEffect(() => {
// valueRef.current is always up to date
const interval = setInterval(() => {
console.log('Current value:', valueRef.current);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<button onClick={() => setValue(v => v + 1)}>
Count: {value}
</button>
);
}Performance
useDebounce
Delays function execution.
import { useDebounce } from '@websolutespa/bom-mixer-hooks';
function SearchInput() {
const [value, setValue] = useState('');
const debouncedValue = useDebounce(value, 500);
useEffect(() => {
// API call only after 500ms from last input
searchAPI(debouncedValue);
}, [debouncedValue]);
return (
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}Event Handling
useEventListener
Safely manages event listeners.
import { useEventListener } from '@websolutespa/bom-mixer-hooks';
function EventHandler() {
const handleKeyPress = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
// Handle escape key
}
};
useEventListener('keydown', handleKeyPress);
return <div>Press ESC to trigger action</div>;
}Best Practices
- Hook Composition
function ComplexComponent() {
const layout = useLayout();
const breakpoint = useBreakpoint();
const [drawer] = useDrawer();
// Combine hooks for advanced functionality
const isMobileMenuOpen = breakpoint.key === 'xs' && drawer === 'menu';
return (
<div className={isMobileMenuOpen ? 'mobile-menu' : ''}>
{/* Component content */}
</div>
);
}- Error Handling
function DataFetcher() {
const [data, loading, error] = useCollectionApiGet('/api/data');
if (error) {
return <ErrorBoundary error={error} />;
}
if (loading) {
return <LoadingSpinner />;
}
return <DataDisplay data={data} />;
}- Performance Optimization
function OptimizedComponent() {
const debouncedSearch = useDebounceCallback((term: string) => {
searchAPI(term);
}, 300);
const intersectionRef = useRef(null);
const isVisible = useIntersectionObserver(intersectionRef);
// Load heavy content only when visible
return (
<div ref={intersectionRef}>
{isVisible && <HeavyContent />}
</div>
);
}Contributing
Please read our Contributing Guide before submitting a Pull Request to the project.
License
This project is licensed under the MIT License - see the LICENSE file for details.
