@devwise/core
v1.8.0
Published
Shared library for DevWise website templates - components, logic, helpers, and utilities
Maintainers
Readme
DevWise Core
A comprehensive TypeScript library for React applications, providing components, utilities, and helpers for modern web development.
Features
- 🎯 TypeScript First - Full type safety and excellent IntelliSense
- 🌳 Tree Shakeable - Import only what you need
- ⚡ SSR Compatible - Works with Next.js, Remix, and other SSR frameworks
- 🎨 Tailwind Ready - Pre-styled components using Tailwind CSS
- 🧪 Well Tested - Comprehensive test coverage
- 📦 Modular - Separate client, server, and shared bundles
Installation
npm install @devwise/core
# or
yarn add @devwise/core
# or
pnpm add @devwise/corePeer Dependencies
npm install react react-domQuick Start
// Shared utilities (works everywhere)
import { formatCurrency, isEmail, chunk } from '@devwise/core';
// Client-only components and hooks (browser environment)
import { ImageUpload, useLocalStorage } from '@devwise/core/client';
// Server-only components (SSR environment)
import { MetaTags, JsonLd } from '@devwise/core/server';Components
Client Components
ImageUpload
A drag-and-drop file upload component with validation and preview capabilities.
import { ImageUpload } from '@devwise/core/client';
function MyForm() {
const handleImageSelect = (file: File) => {
console.log('Selected file:', file);
};
return (
<ImageUpload
onImageSelect={handleImageSelect}
maxSize={5 * 1024 * 1024} // 5MB
accept="image/*"
className="border-2 border-dashed border-gray-300 rounded-lg p-8"
>
<div className="text-center">
<p>Drag & drop an image here, or click to select</p>
</div>
</ImageUpload>
);
}GeolocationDisplay
Display and manage user's current location with accuracy information.
import { GeolocationDisplay } from '@devwise/core/client';
function LocationWidget() {
return (
<GeolocationDisplay
onLocationChange={(coords) => {
console.log('Location:', coords.latitude, coords.longitude);
}}
showAccuracy={true}
className="bg-blue-50 p-4 rounded-lg"
/>
);
}Server Components
MetaTags
SEO-friendly meta tags for your pages.
import { MetaTags } from '@devwise/core/server';
function BlogPost({ post }) {
return (
<>
<MetaTags
title={post.title}
description={post.excerpt}
keywords={post.tags.join(', ')}
ogTitle={post.title}
ogDescription={post.excerpt}
ogImage={post.featuredImage}
ogUrl={`https://example.com/blog/${post.slug}`}
twitterCard="summary_large_image"
canonicalUrl={`https://example.com/blog/${post.slug}`}
/>
{/* Your page content */}
</>
);
}JsonLd
Structured data for search engines.
import { JsonLd, createArticleSchema } from '@devwise/core/server';
function ArticlePage({ article }) {
const schema = createArticleSchema(
article.title,
article.author,
article.publishedAt,
article.updatedAt,
article.image,
article.description
);
return (
<>
<JsonLd data={schema} />
{/* Your article content */}
</>
);
}Shared Components
Button
A versatile button component with multiple variants and loading states.
import { Button } from '@devwise/core';
function ActionButtons() {
return (
<div className="space-x-4">
<Button variant="primary" size="lg">
Primary Action
</Button>
<Button variant="outline" loading={true}>
Loading...
</Button>
<Button variant="ghost" size="sm">
Ghost Button
</Button>
</div>
);
}Card
Flexible card components for content layout.
import { Card, CardHeader, CardFooter } from '@devwise/core';
function ProductCard({ product }) {
return (
<Card padding="lg" shadow="md" rounded="lg">
<CardHeader>
<h3 className="text-lg font-semibold">{product.name}</h3>
</CardHeader>
<div className="space-y-4">
<p>{product.description}</p>
<p className="text-xl font-bold">${product.price}</p>
</div>
<CardFooter>
<Button variant="primary" className="w-full">
Add to Cart
</Button>
</CardFooter>
</Card>
);
}Hooks
useLocalStorage
Persist state in localStorage with SSR safety.
import { useLocalStorage } from '@devwise/core/client';
function UserPreferences() {
const { value: theme, setValue: setTheme } = useLocalStorage('theme', 'light');
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current theme: {theme}
</button>
);
}useAsync
Manage async operations with loading and error states.
import { useAsync } from '@devwise/core/client';
function UserProfile({ userId }) {
const [state, { execute }] = useAsync(
() => fetch(`/api/users/${userId}`).then(res => res.json()),
{ immediate: true }
);
if (state.loading) return <div>Loading...</div>;
if (state.error) return <div>Error: {state.error.message}</div>;
return <div>Welcome, {state.data?.name}!</div>;
}useDebounce
Debounce rapidly changing values.
import { useDebounce } from '@devwise/core/client';
import { useState } from 'react';
function SearchInput() {
const [query, setQuery] = useState('');
const debouncedQuery = useDebounce(query, 300);
// Perform search when debouncedQuery changes
useEffect(() => {
if (debouncedQuery) {
performSearch(debouncedQuery);
}
}, [debouncedQuery]);
return (
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
);
}Utilities
String Utilities
import {
capitalize,
camelCase,
kebabCase,
truncate,
slugify,
isEmail,
isUrl
} from '@devwise/core';
// Text transformation
const title = capitalize('hello world'); // "Hello world"
const camelCased = camelCase('hello-world'); // "helloWorld"
const kebabCased = kebabCase('Hello World'); // "hello-world"
// Text manipulation
const short = truncate('This is a long text', 10); // "This is a..."
const slug = slugify('Hello World!'); // "hello-world"
// Validation
const validEmail = isEmail('[email protected]'); // true
const validUrl = isUrl('https://example.com'); // trueArray Utilities
import {
chunk,
shuffle,
unique,
groupBy,
sortBy,
partition
} from '@devwise/core';
// Array manipulation
const chunks = chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
const shuffled = shuffle([1, 2, 3, 4, 5]); // [3, 1, 5, 2, 4]
const uniqueItems = unique([1, 1, 2, 2, 3]); // [1, 2, 3]
// Advanced operations
const grouped = groupBy(users, user => user.role); // { admin: [...], user: [...] }
const sorted = sortBy(products, product => product.price);
const [active, inactive] = partition(users, user => user.isActive);Date Utilities
import {
formatDate,
formatTime,
getRelativeTime,
addDays,
isToday,
getDaysBetween
} from '@devwise/core';
const now = new Date();
// Formatting
const date = formatDate(now, 'medium'); // "Jan 15, 2024"
const time = formatTime(now, '12'); // "2:30 PM"
const relative = getRelativeTime(now); // "just now"
// Date manipulation
const tomorrow = addDays(now, 1);
const checkToday = isToday(now); // true
const daysDiff = getDaysBetween(now, tomorrow); // 1Format Utilities
import {
formatCurrency,
formatNumber,
formatPercentage,
formatFileSize,
formatPhoneNumber
} from '@devwise/core';
// Number formatting
const price = formatCurrency(1234.56); // "$1,234.56"
const number = formatNumber(1234567, { notation: 'compact' }); // "1.2M"
const percent = formatPercentage(0.1234, 2); // "12.34%"
// Other formats
const fileSize = formatFileSize(1024 * 1024); // "1.00 MB"
const phone = formatPhoneNumber('1234567890'); // "(123) 456-7890"Object Utilities
import {
deepClone,
deepMerge,
pick,
omit,
flattenObject,
getNestedValue
} from '@devwise/core';
const user = { id: 1, name: 'John', profile: { age: 30, city: 'NYC' } };
// Object manipulation
const cloned = deepClone(user);
const merged = deepMerge(user, { profile: { country: 'USA' } });
const subset = pick(user, ['id', 'name']); // { id: 1, name: 'John' }
const without = omit(user, ['profile']); // { id: 1, name: 'John' }
// Advanced operations
const flattened = flattenObject(user); // { id: 1, name: 'John', 'profile.age': 30, ... }
const age = getNestedValue(user, 'profile.age'); // 30Validation
Create robust form validation with chainable validators.
import { createValidator, commonValidators } from '@devwise/core';
// Email validation
const emailValidator = createValidator<string>()
.addRule(commonValidators.required('Email is required'))
.addRule(commonValidators.email('Please enter a valid email'));
// Password validation
const passwordValidator = createValidator<string>()
.addRule(commonValidators.required('Password is required'))
.addRule(commonValidators.minLength(8, 'Password must be at least 8 characters'))
.addRule(commonValidators.pattern(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
'Password must contain uppercase, lowercase, and number'
));
// Usage
const emailResult = emailValidator.validate('[email protected]');
if (!emailResult.isValid) {
console.log('Errors:', emailResult.errors);
}Browser Utilities
Client-side browser APIs and utilities.
import {
copyToClipboard,
downloadJSON,
scrollToTop,
detectBrowser,
isMobile,
fullscreen
} from '@devwise/core/client';
// Clipboard operations
await copyToClipboard('Hello, World!');
// File downloads
downloadJSON({ users: [...] }, 'users.json');
// Navigation and UI
scrollToTop(true); // smooth scroll
const browser = detectBrowser(); // "Chrome", "Firefox", etc.
const mobile = isMobile(); // true/false
// Fullscreen API
await fullscreen.enter();
await fullscreen.exit();TypeScript Support
All components and utilities are fully typed. Import types as needed:
import type { ButtonProps, ValidationResult } from '@devwise/core';
import type { AsyncState, LocalStorageHook } from '@devwise/core/client';Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes and add tests
- Run tests:
npm test - Submit a pull request
Development
# Install dependencies
npm install
# Run tests
npm test
# Build the library
npm run build
# Run linting
npm run lint
# Check types
npm run typescriptLicense
MIT © DevWise
Support
Made with ❤️ by the DevWise team
