feat: implement Figlet, Pastel, and Unit tools with a unified layout
- Add Figlet text converter with font selection and history - Add Pastel color palette generator and manipulation suite - Add comprehensive Units converter with category-based logic - Introduce AppShell with Sidebar and Header for navigation - Modernize theme system with CSS variables and new animations - Update project configuration and dependencies
This commit is contained in:
38
lib/utils/animations.ts
Normal file
38
lib/utils/animations.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
// Animation utility classes and keyframes
|
||||
|
||||
export const fadeIn = {
|
||||
initial: { opacity: 0 },
|
||||
animate: { opacity: 1 },
|
||||
exit: { opacity: 0 },
|
||||
};
|
||||
|
||||
export const slideUp = {
|
||||
initial: { opacity: 0, y: 20 },
|
||||
animate: { opacity: 1, y: 0 },
|
||||
exit: { opacity: 0, y: -20 },
|
||||
};
|
||||
|
||||
export const slideDown = {
|
||||
initial: { opacity: 0, y: -20 },
|
||||
animate: { opacity: 1, y: 0 },
|
||||
exit: { opacity: 0, y: 20 },
|
||||
};
|
||||
|
||||
export const scaleIn = {
|
||||
initial: { opacity: 0, scale: 0.95 },
|
||||
animate: { opacity: 1, scale: 1 },
|
||||
exit: { opacity: 0, scale: 0.95 },
|
||||
};
|
||||
|
||||
export const staggerChildren = {
|
||||
animate: {
|
||||
transition: {
|
||||
staggerChildren: 0.05,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const staggerItem = {
|
||||
initial: { opacity: 0, y: 10 },
|
||||
animate: { opacity: 1, y: 0 },
|
||||
};
|
||||
6
lib/utils/cn.ts
Normal file
6
lib/utils/cn.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
18
lib/utils/debounce.ts
Normal file
18
lib/utils/debounce.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export function debounce<T extends (...args: any[]) => any>(
|
||||
func: T,
|
||||
wait: number
|
||||
): (...args: Parameters<T>) => void {
|
||||
let timeout: NodeJS.Timeout | null = null;
|
||||
|
||||
return function executedFunction(...args: Parameters<T>) {
|
||||
const later = () => {
|
||||
timeout = null;
|
||||
func(...args);
|
||||
};
|
||||
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
}
|
||||
4
lib/utils/index.ts
Normal file
4
lib/utils/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './cn';
|
||||
export * from './debounce';
|
||||
export * from './urlSharing';
|
||||
export * from './animations';
|
||||
64
lib/utils/urlSharing.ts
Normal file
64
lib/utils/urlSharing.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
'use client';
|
||||
|
||||
export interface ShareableState {
|
||||
text: string;
|
||||
font: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text and font to URL parameters
|
||||
*/
|
||||
export function encodeToUrl(text: string, font: string): string {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (text) {
|
||||
params.set('text', text);
|
||||
}
|
||||
|
||||
if (font && font !== 'Standard') {
|
||||
params.set('font', font);
|
||||
}
|
||||
|
||||
const queryString = params.toString();
|
||||
return queryString ? `?${queryString}` : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode URL parameters to get text and font
|
||||
*/
|
||||
export function decodeFromUrl(): ShareableState | null {
|
||||
if (typeof window === 'undefined') return null;
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const text = params.get('text');
|
||||
const font = params.get('font');
|
||||
|
||||
if (!text && !font) return null;
|
||||
|
||||
return {
|
||||
text: text || '',
|
||||
font: font || 'Standard',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the URL without reloading the page
|
||||
*/
|
||||
export function updateUrl(text: string, font: string): void {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const url = encodeToUrl(text, font);
|
||||
const newUrl = url ? `${window.location.pathname}${url}` : window.location.pathname;
|
||||
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shareable URL
|
||||
*/
|
||||
export function getShareableUrl(text: string, font: string): string {
|
||||
if (typeof window === 'undefined') return '';
|
||||
|
||||
const query = encodeToUrl(text, font);
|
||||
return `${window.location.origin}${window.location.pathname}${query}`;
|
||||
}
|
||||
Reference in New Issue
Block a user