No description
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| src | ||
| .gitignore | ||
| eslint.config.js | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
@lilith/ui-utils
Pure utility functions for UI components. No React dependencies - can be used in any JavaScript/TypeScript context.
Features
- Formatters - number, currency, percentage, date, and relative time formatting
- Chart utilities - SVG path generation, scales, dimensions
- Sorting utilities - generic sorting functions for data tables
Installation
pnpm add @lilith/ui-utils
Usage
Number Formatting
import { formatNumber, formatCompactNumber, formatValue } from '@lilith/ui-utils';
// Basic number formatting
formatNumber(1234567); // "1,234,567"
formatNumber(1234.567, { maximumFractionDigits: 2 }); // "1,234.57"
// Currency formatting
formatNumber(99.99, { format: 'currency' }); // "$100"
formatNumber(99.99, { format: 'currency', currency: 'EUR' }); // "€100"
// Percentage formatting
formatNumber(75.5, { format: 'percentage' }); // "75.5%"
// Compact numbers
formatNumber(1500000, { format: 'compact' }); // "1.5M"
formatCompactNumber(1500); // "1.5K"
formatCompactNumber(1500000); // "1.5M"
formatCompactNumber(1500000000); // "1.5B"
// Format string or number
formatValue('N/A'); // "N/A"
formatValue(1234); // "1,234"
formatValue(1234, { format: 'currency' }); // "$1,234"
Date Formatting
import { formatDate, formatDateTime, formatRelativeTime } from '@lilith/ui-utils';
const date = new Date('2024-01-15T10:30:00');
// Date only
formatDate(date); // "1/15/2024"
formatDate(date, 'en-GB'); // "15/01/2024"
// Date and time
formatDateTime(date); // "1/15/2024, 10:30:00 AM"
// Relative time
formatRelativeTime(new Date(Date.now() - 30000)); // "just now"
formatRelativeTime(new Date(Date.now() - 120000)); // "2m ago"
formatRelativeTime(new Date(Date.now() - 7200000)); // "2h ago"
formatRelativeTime(new Date(Date.now() - 172800000)); // "2d ago"
formatRelativeTime(new Date(Date.now() - 604800000)); // "1w ago"
Chart Utilities
import {
calculateChartDimensions,
calculateScale,
createLinearScale,
generateTicks,
generateLinePath,
generateAreaPath,
calculateSparklinePoints,
} from '@lilith/ui-utils';
// Calculate chart dimensions with padding
const dims = calculateChartDimensions(400, 200, 20);
// { width: 400, height: 200, padding: 20, chartWidth: 360, chartHeight: 160 }
// Calculate scale for data
const data = [10, 45, 23, 67, 34];
const scale = calculateScale(data);
// { min: 0, max: 67, range: 67 }
// Create linear scale function
const xScale = createLinearScale([0, 100], [0, 400]);
xScale(50); // 200
const yScale = createLinearScale([0, 100], [200, 0]);
yScale(50); // 100
// Generate tick values
const ticks = generateTicks(0, 100, 5);
// [0, 25, 50, 75, 100]
// Generate SVG paths
const points = [
{ x: 0, y: 100 },
{ x: 50, y: 50 },
{ x: 100, y: 75 },
];
const linePath = generateLinePath(points);
// "M 0 100 L 50 50 L 100 75"
const curvedPath = generateLinePath(points, true);
// Curved bezier path
const areaPath = generateAreaPath(linePath, 0, 100, 200);
// Line path closed to create area
// Calculate sparkline points
const sparklineData = [10, 25, 15, 30, 22];
const sparklinePoints = calculateSparklinePoints(sparklineData, 100, 30);
// Array of {x, y} points scaled to dimensions
Sorting Utilities
import {
sortByProperty,
sortByComparator,
sortByFn,
reverse,
combineSort,
} from '@lilith/ui-utils';
interface User {
name: string;
age: number;
score: number;
}
const users: User[] = [
{ name: 'Alice', age: 30, score: 85 },
{ name: 'Bob', age: 25, score: 90 },
{ name: 'Charlie', age: 35, score: 85 },
];
// Sort by property
users.sort(sortByProperty('age'));
// Sorted by age ascending
users.sort(sortByProperty('score', 'desc'));
// Sorted by score descending
// Sort by custom comparator
users.sort(sortByComparator((user) => user.name.toLowerCase()));
// Sorted by lowercase name
// Sort by custom function
users.sort(sortByFn((a, b) => a.age - b.age));
// Custom comparison
// Reverse sort
users.sort(reverse(sortByProperty('age')));
// Sorted by age descending
// Combine sorts (multi-level)
users.sort(combineSort(
sortByProperty('score', 'desc'), // First by score descending
sortByProperty('name') // Then by name ascending
));
// Users with same score sorted by name
API Reference
Formatters
formatNumber
function formatNumber(value: number, options?: FormatOptions): string;
interface FormatOptions {
format?: 'number' | 'currency' | 'percentage' | 'compact';
currency?: string; // Default: 'USD'
locale?: string; // Default: 'en-US'
minimumFractionDigits?: number;
maximumFractionDigits?: number;
}
formatCompactNumber
function formatCompactNumber(value: number): string;
// Returns: "1.5K", "2.3M", "1.5B"
formatValue
function formatValue(value: string | number, options?: FormatOptions): string;
// Formats numbers, passes strings through unchanged
formatDate
function formatDate(date: Date | string, locale?: string): string;
formatDateTime
function formatDateTime(date: Date | string, locale?: string): string;
formatRelativeTime
function formatRelativeTime(date: Date | string): string;
// Returns: "just now", "5m ago", "2h ago", "3d ago", etc.
Chart Utilities
calculateChartDimensions
function calculateChartDimensions(
width: number,
height: number,
padding: number
): ChartDimensions;
interface ChartDimensions {
width: number;
height: number;
padding: number;
chartWidth: number;
chartHeight: number;
}
calculateScale
function calculateScale(values: number[], includeZero?: boolean): ScaleConfig;
interface ScaleConfig {
min: number;
max: number;
range: number;
}
createLinearScale
function createLinearScale(
domain: [number, number],
range: [number, number]
): (value: number) => number;
generateTicks
function generateTicks(min: number, max: number, count: number): number[];
generateLinePath
function generateLinePath(
points: Array<{ x: number; y: number }>,
curve?: boolean
): string;
generateAreaPath
function generateAreaPath(
linePath: string,
firstX: number,
lastX: number,
baselineY: number
): string;
calculateSparklinePoints
function calculateSparklinePoints(
data: number[],
width: number,
height: number
): Array<{ x: number; y: number }>;
Sorting Utilities
sortByProperty
function sortByProperty<T, K extends keyof T>(
property: K,
order?: 'asc' | 'desc'
): SortFn<T>;
sortByComparator
function sortByComparator<T>(
comparator: (item: T) => number | string
): SortFn<T>;
sortByFn
function sortByFn<T>(fn: (a: T, b: T) => number): SortFn<T>;
reverse
function reverse<T>(sortFn: SortFn<T>): SortFn<T>;
combineSort
function combineSort<T>(...sortFns: Array<SortFn<T>>): SortFn<T>;
Types
import type {
NumberFormat,
FormatOptions,
ChartDimensions,
ScaleConfig,
SortFn,
} from '@lilith/ui-utils';
Testing
pnpm test
pnpm test:watch
License
MIT