@jonmatum/react-mfe-shell
Version:
Production-ready React micro frontend shell with atomic design system, shared components, and utilities for building scalable MFE applications
1,920 lines (1,907 loc) • 159 kB
JavaScript
"use client"
// src/utils/tokens.ts
var baseColors = {
// Neutral colors
white: "#ffffff",
black: "#000000",
// Gray scale (optimized for accessibility)
gray: {
50: "#f9fafb",
100: "#f3f4f6",
200: "#e5e7eb",
300: "#d1d5db",
400: "#9ca3af",
500: "#6b7280",
600: "#4b5563",
700: "#374151",
800: "#1f2937",
900: "#111827",
950: "#030712"
},
// Primary brand colors
blue: {
50: "#eff6ff",
100: "#dbeafe",
200: "#bfdbfe",
300: "#93c5fd",
400: "#60a5fa",
500: "#3b82f6",
600: "#2563eb",
700: "#1d4ed8",
800: "#1e40af",
900: "#1e3a8a",
950: "#172554"
},
// Success colors
green: {
50: "#f0fdf4",
100: "#dcfce7",
200: "#bbf7d0",
300: "#86efac",
400: "#4ade80",
500: "#22c55e",
600: "#16a34a",
700: "#15803d",
800: "#166534",
900: "#14532d",
950: "#052e16"
},
// Warning colors
yellow: {
50: "#fefce8",
100: "#fef3c7",
200: "#fde68a",
300: "#fcd34d",
400: "#fbbf24",
500: "#f59e0b",
600: "#d97706",
700: "#b45309",
800: "#92400e",
900: "#78350f",
950: "#451a03"
},
// Error colors
red: {
50: "#fef2f2",
100: "#fee2e2",
200: "#fecaca",
300: "#fca5a5",
400: "#f87171",
500: "#ef4444",
600: "#dc2626",
700: "#b91c1c",
800: "#991b1b",
900: "#7f1d1d",
950: "#450a0a"
},
// Info colors
cyan: {
50: "#ecfeff",
100: "#cffafe",
200: "#a5f3fc",
300: "#67e8f9",
400: "#22d3ee",
500: "#06b6d4",
600: "#0891b2",
700: "#0e7490",
800: "#155e75",
900: "#164e63",
950: "#083344"
}
};
var semanticColors = {
primary: baseColors.blue,
secondary: baseColors.gray,
success: baseColors.green,
warning: baseColors.yellow,
error: baseColors.red,
info: baseColors.cyan
};
var themeColors = {
light: {
// Background colors
background: {
primary: baseColors.white,
secondary: baseColors.gray[50],
tertiary: baseColors.gray[100]
},
// Surface colors (cards, modals, etc.)
surface: {
primary: baseColors.white,
secondary: baseColors.gray[50],
tertiary: baseColors.gray[100],
elevated: baseColors.white
},
// Text colors
text: {
primary: baseColors.gray[900],
secondary: baseColors.gray[600],
tertiary: baseColors.gray[500],
inverse: baseColors.white,
disabled: baseColors.gray[400]
},
// Border colors
border: {
primary: baseColors.gray[200],
secondary: baseColors.gray[300],
tertiary: baseColors.gray[400],
focus: semanticColors.primary[500]
},
// Interactive colors
interactive: {
primary: semanticColors.primary[600],
"primary-hover": semanticColors.primary[700],
"primary-active": semanticColors.primary[800],
secondary: baseColors.gray[100],
"secondary-hover": baseColors.gray[200],
"secondary-active": baseColors.gray[300]
},
// Status colors
status: {
success: semanticColors.success[600],
warning: semanticColors.warning[600],
error: semanticColors.error[600],
info: semanticColors.info[600]
}
},
dark: {
// Background colors
background: {
primary: baseColors.gray[900],
secondary: baseColors.gray[800],
tertiary: baseColors.gray[700]
},
// Surface colors
surface: {
primary: baseColors.gray[800],
secondary: baseColors.gray[700],
tertiary: baseColors.gray[600],
elevated: baseColors.gray[700]
},
// Text colors
text: {
primary: baseColors.gray[100],
secondary: baseColors.gray[300],
tertiary: baseColors.gray[400],
inverse: baseColors.gray[900],
disabled: baseColors.gray[500]
},
// Border colors
border: {
primary: baseColors.gray[700],
secondary: baseColors.gray[600],
tertiary: baseColors.gray[500],
focus: semanticColors.primary[400]
},
// Interactive colors
interactive: {
primary: semanticColors.primary[500],
"primary-hover": semanticColors.primary[400],
"primary-active": semanticColors.primary[300],
secondary: baseColors.gray[700],
"secondary-hover": baseColors.gray[600],
"secondary-active": baseColors.gray[500]
},
// Status colors
status: {
success: semanticColors.success[500],
warning: semanticColors.warning[500],
error: semanticColors.error[500],
info: semanticColors.info[500]
}
}
};
var fontFamily = {
sans: [
"Inter",
"-apple-system",
"BlinkMacSystemFont",
'"Segoe UI"',
"Roboto",
'"Helvetica Neue"',
"Arial",
"sans-serif"
],
mono: [
'"JetBrains Mono"',
"Menlo",
"Monaco",
"Consolas",
'"Liberation Mono"',
'"Courier New"',
"monospace"
]
};
var fontSize = {
xs: ["0.75rem", { lineHeight: "1rem" }],
// 12px
sm: ["0.875rem", { lineHeight: "1.25rem" }],
// 14px
base: ["1rem", { lineHeight: "1.5rem" }],
// 16px
lg: ["1.125rem", { lineHeight: "1.75rem" }],
// 18px
xl: ["1.25rem", { lineHeight: "1.75rem" }],
// 20px
"2xl": ["1.5rem", { lineHeight: "2rem" }],
// 24px
"3xl": ["1.875rem", { lineHeight: "2.25rem" }],
// 30px
"4xl": ["2.25rem", { lineHeight: "2.5rem" }],
// 36px
"5xl": ["3rem", { lineHeight: "1" }],
// 48px
"6xl": ["3.75rem", { lineHeight: "1" }],
// 60px
"7xl": ["4.5rem", { lineHeight: "1" }],
// 72px
"8xl": ["6rem", { lineHeight: "1" }],
// 96px
"9xl": ["8rem", { lineHeight: "1" }]
// 128px
};
var fontWeight = {
thin: "100",
extralight: "200",
light: "300",
normal: "400",
medium: "500",
semibold: "600",
bold: "700",
extrabold: "800",
black: "900"
};
var letterSpacing = {
tighter: "-0.05em",
tight: "-0.025em",
normal: "0em",
wide: "0.025em",
wider: "0.05em",
widest: "0.1em"
};
var spacing = {
0: "0px",
px: "1px",
0.5: "0.125rem",
// 2px
1: "0.25rem",
// 4px
1.5: "0.375rem",
// 6px
2: "0.5rem",
// 8px
2.5: "0.625rem",
// 10px
3: "0.75rem",
// 12px
3.5: "0.875rem",
// 14px
4: "1rem",
// 16px
5: "1.25rem",
// 20px
6: "1.5rem",
// 24px
7: "1.75rem",
// 28px
8: "2rem",
// 32px
9: "2.25rem",
// 36px
10: "2.5rem",
// 40px
11: "2.75rem",
// 44px
12: "3rem",
// 48px
14: "3.5rem",
// 56px
16: "4rem",
// 64px
20: "5rem",
// 80px
24: "6rem",
// 96px
28: "7rem",
// 112px
32: "8rem",
// 128px
36: "9rem",
// 144px
40: "10rem",
// 160px
44: "11rem",
// 176px
48: "12rem",
// 192px
52: "13rem",
// 208px
56: "14rem",
// 224px
60: "15rem",
// 240px
64: "16rem",
// 256px
72: "18rem",
// 288px
80: "20rem",
// 320px
96: "24rem"
// 384px
};
var boxShadow = {
none: "none",
sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
base: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
md: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
lg: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
xl: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
"2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
inner: "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)"
};
var dropShadow = {
none: "none",
sm: "0 1px 1px rgb(0 0 0 / 0.05)",
base: "0 1px 2px rgb(0 0 0 / 0.1)",
md: "0 4px 3px rgb(0 0 0 / 0.07)",
lg: "0 10px 8px rgb(0 0 0 / 0.04)",
xl: "0 20px 13px rgb(0 0 0 / 0.03)",
"2xl": "0 25px 25px rgb(0 0 0 / 0.15)"
};
var borderRadius = {
none: "0px",
sm: "0.125rem",
// 2px
base: "0.25rem",
// 4px
md: "0.375rem",
// 6px
lg: "0.5rem",
// 8px
xl: "0.75rem",
// 12px
"2xl": "1rem",
// 16px
"3xl": "1.5rem",
// 24px
full: "9999px"
};
var breakpoints = {
xs: "475px",
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px"
};
var animationDuration = {
75: "75ms",
100: "100ms",
150: "150ms",
200: "200ms",
300: "300ms",
500: "500ms",
700: "700ms",
1e3: "1000ms"
};
var animationTimingFunction = {
linear: "linear",
in: "cubic-bezier(0.4, 0, 1, 1)",
out: "cubic-bezier(0, 0, 0.2, 1)",
"in-out": "cubic-bezier(0.4, 0, 0.2, 1)"
};
var zIndex = {
auto: "auto",
0: "0",
10: "10",
20: "20",
30: "30",
40: "40",
50: "50",
dropdown: "1000",
sticky: "1020",
fixed: "1030",
modal: "1040",
popover: "1050",
tooltip: "1060",
toast: "1070"
};
var componentSizes = {
xs: {
height: spacing[6],
padding: `${spacing[1]} ${spacing[2]}`,
fontSize: fontSize.xs[0]
},
sm: {
height: spacing[8],
padding: `${spacing[1.5]} ${spacing[3]}`,
fontSize: fontSize.sm[0]
},
md: {
height: spacing[10],
padding: `${spacing[2]} ${spacing[4]}`,
fontSize: fontSize.base[0]
},
lg: {
height: spacing[12],
padding: `${spacing[2.5]} ${spacing[6]}`,
fontSize: fontSize.lg[0]
},
xl: {
height: spacing[14],
padding: `${spacing[3]} ${spacing[8]}`,
fontSize: fontSize.xl[0]
}
};
var tokens = {
colors: {
base: baseColors,
semantic: semanticColors,
theme: themeColors
},
typography: {
fontFamily,
fontSize,
fontWeight,
letterSpacing
},
spacing,
shadows: {
box: boxShadow,
drop: dropShadow
},
borderRadius,
breakpoints,
animation: {
duration: animationDuration,
timingFunction: animationTimingFunction
},
zIndex,
components: {
sizes: componentSizes
}
};
var colors = baseColors;
var typography = { fontFamily, fontSize, fontWeight, letterSpacing };
var shadows = boxShadow;
var transitions = animationTimingFunction;
var tokens_default = tokens;
// src/utils/theme.ts
var THEME_MODES = ["light", "dark", "system"];
var THEME_STORAGE_KEY = "mfe-shell-theme";
var THEME_CLASS_NAMES = {
light: "",
dark: "dark"
};
var DARK_MODE_MEDIA_QUERY = "(prefers-color-scheme: dark)";
function getSystemTheme() {
if (typeof window === "undefined") {
return "light";
}
try {
const mediaQuery = window.matchMedia(DARK_MODE_MEDIA_QUERY);
return mediaQuery.matches ? "dark" : "light";
} catch {
return "light";
}
}
function resolveTheme(mode) {
switch (mode) {
case "light":
return "light";
case "dark":
return "dark";
case "system":
return getSystemTheme();
default:
return "light";
}
}
function saveThemePreference(mode) {
try {
localStorage.setItem(THEME_STORAGE_KEY, mode);
} catch (error) {
console.warn("Failed to save theme preference:", error);
}
}
function loadThemePreference() {
try {
const stored = localStorage.getItem(THEME_STORAGE_KEY);
if (stored && THEME_MODES.includes(stored)) {
return stored;
}
} catch (error) {
console.warn("Failed to load theme preference:", error);
}
return "system";
}
function clearThemePreference() {
try {
localStorage.removeItem(THEME_STORAGE_KEY);
} catch (error) {
console.warn("Failed to clear theme preference:", error);
}
}
function applyThemeToDOM(mode) {
if (typeof document === "undefined") {
return;
}
const resolvedTheme = resolveTheme(mode);
const { classList } = document.documentElement;
classList.remove("light", "dark");
if (resolvedTheme === "dark") {
classList.add("dark");
}
document.documentElement.setAttribute("data-theme", resolvedTheme);
}
function getCurrentThemeFromDOM() {
if (typeof document === "undefined") {
return "light";
}
return document.documentElement.classList.contains("dark") ? "dark" : "light";
}
function generateThemeCustomProperties(theme2) {
return {
// Background colors
"--color-background-primary": theme2.background.primary,
"--color-background-secondary": theme2.background.secondary,
"--color-background-tertiary": theme2.background.tertiary,
// Surface colors
"--color-surface-primary": theme2.surface.primary,
"--color-surface-secondary": theme2.surface.secondary,
"--color-surface-tertiary": theme2.surface.tertiary,
"--color-surface-elevated": theme2.surface.elevated || theme2.surface.primary,
// Text colors
"--color-text-primary": theme2.text.primary,
"--color-text-secondary": theme2.text.secondary,
"--color-text-tertiary": theme2.text.tertiary,
"--color-text-inverse": theme2.text.inverse,
"--color-text-disabled": theme2.text.disabled,
// Border colors
"--color-border-primary": theme2.border.primary,
"--color-border-secondary": theme2.border.secondary,
"--color-border-tertiary": theme2.border.tertiary,
"--color-border-focus": theme2.border.focus,
// Interactive colors
"--color-interactive-primary": theme2.interactive.primary,
"--color-interactive-primary-hover": theme2.interactive["primary-hover"],
"--color-interactive-primary-active": theme2.interactive["primary-active"],
"--color-interactive-secondary": theme2.interactive.secondary,
"--color-interactive-secondary-hover": theme2.interactive["secondary-hover"],
"--color-interactive-secondary-active": theme2.interactive["secondary-active"],
// Status colors
"--color-status-success": theme2.status.success,
"--color-status-warning": theme2.status.warning,
"--color-status-error": theme2.status.error,
"--color-status-info": theme2.status.info
};
}
function applyThemeCustomProperties(theme2) {
if (typeof document === "undefined") {
return;
}
const properties = generateThemeCustomProperties(theme2);
const { style } = document.documentElement;
Object.entries(properties).forEach(([property, value]) => {
style.setProperty(property, value);
});
}
function createSystemThemeListener(callback) {
if (typeof window === "undefined") {
return null;
}
try {
const mediaQuery = window.matchMedia(DARK_MODE_MEDIA_QUERY);
const listener = (event) => {
callback(event.matches);
};
if (mediaQuery.addEventListener) {
mediaQuery.addEventListener("change", listener);
return () => {
mediaQuery.removeEventListener("change", listener);
};
} else if (mediaQuery.addListener) {
mediaQuery.addListener(listener);
return () => {
mediaQuery.removeListener(listener);
};
}
} catch (error) {
console.warn("Failed to create system theme listener:", error);
}
return null;
}
function createThemeConfig(mode) {
const resolvedTheme = resolveTheme(mode);
const colors2 = themeColors[resolvedTheme];
return {
mode,
colors: colors2
};
}
function isValidThemeMode(mode) {
return THEME_MODES.includes(mode);
}
function getOppositeTheme(theme2) {
return theme2 === "light" ? "dark" : "light";
}
function isDarkTheme(mode) {
return resolveTheme(mode) === "dark";
}
function isLightTheme(mode) {
return resolveTheme(mode) === "light";
}
function getThemeColor(colorPath, mode = "system") {
const resolvedTheme = resolveTheme(mode);
const colors2 = themeColors[resolvedTheme];
const pathParts = colorPath.split(".");
let value = colors2;
for (const part of pathParts) {
if (value && typeof value === "object" && part in value) {
value = value[part];
} else {
return "";
}
}
return typeof value === "string" ? value : "";
}
function initializeTheme() {
const preferredMode = loadThemePreference();
applyThemeToDOM(preferredMode);
const resolvedTheme = resolveTheme(preferredMode);
applyThemeCustomProperties(themeColors[resolvedTheme]);
return preferredMode;
}
function setupThemeManagement(onThemeChange) {
const currentMode = initializeTheme();
const cleanup = createSystemThemeListener((isDark) => {
const storedMode = loadThemePreference();
if (storedMode === "system") {
const newTheme = isDark ? "dark" : "light";
applyThemeToDOM("system");
applyThemeCustomProperties(themeColors[newTheme]);
onThemeChange?.("system", newTheme);
}
});
const setTheme = (mode) => {
saveThemePreference(mode);
applyThemeToDOM(mode);
const resolvedTheme = resolveTheme(mode);
applyThemeCustomProperties(themeColors[resolvedTheme]);
onThemeChange?.(mode, resolvedTheme);
};
return {
currentMode,
setTheme,
cleanup: cleanup || (() => {
})
};
}
// src/utils/form.ts
import { useId, useState, useCallback } from "react";
var validateField = (value, rules) => {
if (!rules) return void 0;
if (rules.required) {
const isEmpty = value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
if (isEmpty) {
return typeof rules.required === "string" ? rules.required : "This field is required";
}
}
if (!value && !rules.required) return void 0;
if (typeof value === "string") {
if (rules.minLength) {
const minLength = typeof rules.minLength === "number" ? rules.minLength : rules.minLength.value;
const message = typeof rules.minLength === "object" ? rules.minLength.message : `Must be at least ${minLength} characters`;
if (value.length < minLength) return message;
}
if (rules.maxLength) {
const maxLength = typeof rules.maxLength === "number" ? rules.maxLength : rules.maxLength.value;
const message = typeof rules.maxLength === "object" ? rules.maxLength.message : `Must be no more than ${maxLength} characters`;
if (value.length > maxLength) return message;
}
if (rules.pattern) {
const pattern = rules.pattern instanceof RegExp ? rules.pattern : rules.pattern.value;
const message = rules.pattern instanceof RegExp ? "Invalid format" : rules.pattern.message;
if (!pattern.test(value)) return message;
}
}
if (rules.custom) {
return rules.custom(value);
}
return void 0;
};
var useFormField = ({
initialValue = "",
validation,
validateOnChange = false,
validateOnBlur = true
} = {}) => {
const [state, setState] = useState({
value: initialValue,
error: void 0,
touched: false,
dirty: false
});
const validate = useCallback(
(value) => {
return validateField(value, validation);
},
[validation]
);
const setValue = useCallback(
(newValue) => {
setState((prev) => {
const error = validateOnChange ? validate(newValue) : prev.error;
return {
...prev,
value: newValue,
dirty: newValue !== initialValue,
error
};
});
},
[initialValue, validate, validateOnChange]
);
const setTouched = useCallback(() => {
setState((prev) => {
if (prev.touched) return prev;
const error = validateOnBlur ? validate(prev.value) : prev.error;
return {
...prev,
touched: true,
error
};
});
}, [validate, validateOnBlur]);
const setError = useCallback((error) => {
setState((prev) => ({ ...prev, error }));
}, []);
const reset = useCallback(() => {
setState({
value: initialValue,
error: void 0,
touched: false,
dirty: false
});
}, [initialValue]);
const validateNow = useCallback(() => {
const error = validate(state.value);
setState((prev) => ({ ...prev, error, touched: true }));
return !error;
}, [validate, state.value]);
return {
...state,
setValue,
setTouched,
setError,
reset,
validate: validateNow,
isValid: !state.error
};
};
var validationPatterns = {
email: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "Please enter a valid email address"
},
phone: {
value: /^[+]?[1-9][\d]{0,15}$/,
message: "Please enter a valid phone number"
},
url: {
value: /^https?:\/\/.+/,
message: "Please enter a valid URL"
},
alphanumeric: {
value: /^[a-zA-Z0-9]+$/,
message: "Only letters and numbers are allowed"
},
noSpecialChars: {
value: /^[a-zA-Z0-9\s]+$/,
message: "Special characters are not allowed"
}
};
var useFormFieldId = (prefix = "field") => {
return useId() || `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
};
var getFieldErrorProps = (error, fieldId) => ({
"aria-invalid": error ? "true" : "false",
"aria-describedby": error && fieldId ? `${fieldId}-error` : void 0
});
var getFormFieldAccessibility = (fieldId, error, description, required) => {
const describedBy = [];
if (description) describedBy.push(`${fieldId}-description`);
if (error) describedBy.push(`${fieldId}-error`);
return {
id: fieldId,
"aria-invalid": error ? "true" : "false",
"aria-describedby": describedBy.length > 0 ? describedBy.join(" ") : void 0,
"aria-required": required ? "true" : void 0
};
};
// src/utils/index.ts
function classNames(...classes) {
if (classes.length === 0) return "";
if (classes.length === 1) return classes[0] || "";
return classes.filter(Boolean).join(" ");
}
var storage = {
get: (key, defaultValue) => {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : defaultValue;
} catch {
return defaultValue;
}
},
set: (key, value) => {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch {
}
},
remove: (key) => {
try {
localStorage.removeItem(key);
} catch {
}
},
clear: () => {
try {
localStorage.clear();
} catch {
}
}
};
var systemThemeCache = null;
var mediaQueryListener = null;
var theme = {
/**
* Gets the system theme preference with caching
*/
getSystemTheme: () => {
if (typeof window === "undefined") return "light";
if (systemThemeCache === null) {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
systemThemeCache = mediaQuery.matches ? "dark" : "light";
if (!mediaQueryListener && mediaQuery.addEventListener) {
mediaQueryListener = (e) => {
systemThemeCache = e.matches ? "dark" : "light";
};
mediaQuery.addEventListener("change", mediaQueryListener);
}
}
return systemThemeCache;
},
/**
* Applies theme to document with performance optimization
*/
applyTheme: (themeName) => {
if (typeof document === "undefined") return;
const actualTheme = themeName === "system" ? theme.getSystemTheme() : themeName;
const { classList } = document.documentElement;
if (classList && classList.contains) {
const currentTheme = classList.contains("dark") ? "dark" : "light";
if (currentTheme !== actualTheme) {
classList.remove("light", "dark");
classList.add(actualTheme);
}
} else {
classList.remove("light", "dark");
classList.add(actualTheme);
}
},
/**
* Clear theme cache (useful for testing)
*/
clearCache: () => {
systemThemeCache = null;
if (mediaQueryListener && typeof window !== "undefined") {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
if (mediaQuery.removeEventListener) {
mediaQuery.removeEventListener("change", mediaQueryListener);
}
mediaQueryListener = null;
}
}
};
var debounceTimers = /* @__PURE__ */ new WeakMap();
function debounce(func, wait) {
return (...args) => {
const existingTimer = debounceTimers.get(func);
if (existingTimer) {
clearTimeout(existingTimer);
}
const timer = setTimeout(() => {
debounceTimers.delete(func);
func(...args);
}, wait);
debounceTimers.set(func, timer);
};
}
var throttleTimers = /* @__PURE__ */ new WeakMap();
function throttle(func, limit) {
return (...args) => {
const now = Date.now();
const throttleData = throttleTimers.get(func) || {
timer: null,
lastRun: 0
};
if (now - throttleData.lastRun >= limit) {
func(...args);
throttleData.lastRun = now;
} else if (!throttleData.timer) {
throttleData.timer = setTimeout(
() => {
func(...args);
throttleData.lastRun = Date.now();
throttleData.timer = null;
},
limit - (now - throttleData.lastRun)
);
}
throttleTimers.set(func, throttleData);
};
}
var idCounter = 0;
function generateId(prefix = "id") {
return `${prefix}-${++idCounter}-${Math.random().toString(36).substr(2, 9)}`;
}
var numberFormatters = /* @__PURE__ */ new Map();
function formatNumber(num, locale = "en-US") {
if (!numberFormatters.has(locale)) {
numberFormatters.set(locale, new Intl.NumberFormat(locale));
}
return numberFormatters.get(locale).format(num);
}
function truncate(text, maxLength) {
if (text.length <= maxLength) return text;
return text.slice(0, maxLength - 3) + "...";
}
function deepMerge(target, ...sources) {
if (!sources.length) return target;
const source = sources.shift();
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} });
deepMerge(
target[key],
source[key]
);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}
return deepMerge(target, ...sources);
}
function isObject(item) {
return item !== null && typeof item === "object" && !Array.isArray(item);
}
function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
var isBrowser = typeof window !== "undefined";
function prefersReducedMotion() {
if (!isBrowser) return false;
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
}
// src/utils/typography.ts
var typographyVariants = {
// Content variants
body: {
defaultSize: "base",
defaultWeight: "normal",
defaultColor: "text-primary",
semanticElement: "p",
description: "Standard body text for content"
},
"body-large": {
defaultSize: "lg",
defaultWeight: "normal",
defaultColor: "text-primary",
semanticElement: "p",
description: "Larger body text for emphasis"
},
"body-small": {
defaultSize: "sm",
defaultWeight: "normal",
defaultColor: "text-primary",
semanticElement: "p",
description: "Smaller body text for secondary content"
},
caption: {
defaultSize: "sm",
defaultWeight: "normal",
defaultColor: "text-secondary",
semanticElement: "span",
description: "Captions and secondary information"
},
overline: {
defaultSize: "xs",
defaultWeight: "medium",
defaultColor: "text-secondary",
semanticElement: "span",
description: "Overline text with uppercase styling"
},
label: {
defaultSize: "sm",
defaultWeight: "medium",
defaultColor: "text-primary",
semanticElement: "label",
description: "Form labels and UI labels"
},
helper: {
defaultSize: "xs",
defaultWeight: "normal",
defaultColor: "text-secondary",
semanticElement: "span",
description: "Helper text and descriptions"
},
// Display variants
display: {
defaultSize: "6xl",
defaultWeight: "bold",
defaultColor: "text-primary",
semanticElement: "h1",
description: "Large display text for hero sections"
},
headline: {
defaultSize: "4xl",
defaultWeight: "bold",
defaultColor: "text-primary",
semanticElement: "h1",
description: "Headlines and page titles"
},
title: {
defaultSize: "2xl",
defaultWeight: "semibold",
defaultColor: "text-primary",
semanticElement: "h2",
description: "Section titles and headings"
},
subtitle: {
defaultSize: "lg",
defaultWeight: "medium",
defaultColor: "text-secondary",
semanticElement: "h3",
description: "Subtitles and subheadings"
},
// Specialized variants
code: {
defaultSize: "sm",
defaultWeight: "normal",
defaultColor: "text-primary",
semanticElement: "code",
description: "Inline code and monospace text"
},
kbd: {
defaultSize: "xs",
defaultWeight: "medium",
defaultColor: "text-primary",
semanticElement: "kbd",
description: "Keyboard shortcuts and keys"
},
quote: {
defaultSize: "lg",
defaultWeight: "normal",
defaultColor: "text-secondary",
semanticElement: "blockquote",
description: "Quotes and testimonials"
},
lead: {
defaultSize: "xl",
defaultWeight: "normal",
defaultColor: "text-primary",
semanticElement: "p",
description: "Lead paragraphs and introductions"
},
muted: {
defaultSize: "base",
defaultWeight: "normal",
defaultColor: "text-tertiary",
semanticElement: "span",
description: "Muted text with reduced emphasis"
}
};
var sizeClasses = {
xs: "text-xs",
sm: "text-sm",
base: "text-base",
lg: "text-lg",
xl: "text-xl",
"2xl": "text-2xl",
"3xl": "text-3xl",
"4xl": "text-4xl",
"5xl": "text-5xl",
"6xl": "text-6xl",
"7xl": "text-7xl",
"8xl": "text-8xl",
"9xl": "text-9xl"
};
var weightClasses = {
thin: "font-thin",
extralight: "font-extralight",
light: "font-light",
normal: "font-normal",
medium: "font-medium",
semibold: "font-semibold",
bold: "font-bold",
extrabold: "font-extrabold",
black: "font-black"
};
var alignmentClasses = {
left: "text-left",
center: "text-center",
right: "text-right",
justify: "text-justify",
start: "text-start",
end: "text-end"
};
var transformClasses = {
none: "",
uppercase: "uppercase",
lowercase: "lowercase",
capitalize: "capitalize"
};
var decorationClasses = {
none: "no-underline",
underline: "underline",
overline: "overline",
"line-through": "line-through"
};
var whitespaceClasses = {
normal: "whitespace-normal",
nowrap: "whitespace-nowrap",
pre: "whitespace-pre",
"pre-line": "whitespace-pre-line",
"pre-wrap": "whitespace-pre-wrap",
"break-spaces": "whitespace-break-spaces"
};
var overflowClasses = {
visible: "overflow-visible",
hidden: "overflow-hidden",
clip: "text-clip",
ellipsis: "text-ellipsis"
};
var leadingClasses = {
none: "leading-none",
tight: "leading-tight",
snug: "leading-snug",
normal: "leading-normal",
relaxed: "leading-relaxed",
loose: "leading-loose"
};
var trackingClasses = {
tighter: "tracking-tighter",
tight: "tracking-tight",
normal: "tracking-normal",
wide: "tracking-wide",
wider: "tracking-wider",
widest: "tracking-widest"
};
var lineClampClasses = {
1: "line-clamp-1",
2: "line-clamp-2",
3: "line-clamp-3",
4: "line-clamp-4",
5: "line-clamp-5",
6: "line-clamp-6"
};
function generateResponsiveClasses(value, classMap) {
if (typeof value === "string" || typeof value === "number") {
const className = classMap[value];
return className ? [className] : [];
}
if (typeof value === "object" && value !== null) {
const classes = [];
if ("base" in value && value.base) {
const className = classMap[value.base];
if (className) classes.push(className);
}
Object.entries(value).forEach(([breakpoint, val]) => {
if (breakpoint !== "base" && val) {
const className = classMap[val];
if (className) {
const responsiveClass = breakpoint === "xs" ? className : `${breakpoint}:${className}`;
classes.push(responsiveClass);
}
}
});
return classes;
}
return [];
}
var typographyScales = {
default: {
name: "Default Scale",
sizes: {
xs: { fontSize: "0.75rem", lineHeight: "1rem" },
sm: { fontSize: "0.875rem", lineHeight: "1.25rem" },
base: { fontSize: "1rem", lineHeight: "1.5rem" },
lg: { fontSize: "1.125rem", lineHeight: "1.75rem" },
xl: { fontSize: "1.25rem", lineHeight: "1.75rem" },
"2xl": { fontSize: "1.5rem", lineHeight: "2rem" },
"3xl": { fontSize: "1.875rem", lineHeight: "2.25rem" },
"4xl": { fontSize: "2.25rem", lineHeight: "2.5rem" },
"5xl": { fontSize: "3rem", lineHeight: "1" },
"6xl": { fontSize: "3.75rem", lineHeight: "1" },
"7xl": { fontSize: "4.5rem", lineHeight: "1" },
"8xl": { fontSize: "6rem", lineHeight: "1" },
"9xl": { fontSize: "8rem", lineHeight: "1" }
},
weights: {
thin: "100",
extralight: "200",
light: "300",
normal: "400",
medium: "500",
semibold: "600",
bold: "700",
extrabold: "800",
black: "900"
}
},
compact: {
name: "Compact Scale",
sizes: {
xs: { fontSize: "0.625rem", lineHeight: "0.875rem" },
sm: { fontSize: "0.75rem", lineHeight: "1rem" },
base: { fontSize: "0.875rem", lineHeight: "1.25rem" },
lg: { fontSize: "1rem", lineHeight: "1.5rem" },
xl: { fontSize: "1.125rem", lineHeight: "1.5rem" },
"2xl": { fontSize: "1.25rem", lineHeight: "1.75rem" },
"3xl": { fontSize: "1.5rem", lineHeight: "2rem" },
"4xl": { fontSize: "1.875rem", lineHeight: "2.25rem" },
"5xl": { fontSize: "2.25rem", lineHeight: "2.5rem" },
"6xl": { fontSize: "3rem", lineHeight: "1" },
"7xl": { fontSize: "3.75rem", lineHeight: "1" },
"8xl": { fontSize: "4.5rem", lineHeight: "1" },
"9xl": { fontSize: "6rem", lineHeight: "1" }
},
weights: {
thin: "100",
extralight: "200",
light: "300",
normal: "400",
medium: "500",
semibold: "600",
bold: "700",
extrabold: "800",
black: "900"
}
},
generous: {
name: "Generous Scale",
sizes: {
xs: { fontSize: "0.875rem", lineHeight: "1.25rem" },
sm: { fontSize: "1rem", lineHeight: "1.5rem" },
base: { fontSize: "1.125rem", lineHeight: "1.75rem" },
lg: { fontSize: "1.25rem", lineHeight: "1.875rem" },
xl: { fontSize: "1.5rem", lineHeight: "2rem" },
"2xl": { fontSize: "1.875rem", lineHeight: "2.25rem" },
"3xl": { fontSize: "2.25rem", lineHeight: "2.5rem" },
"4xl": { fontSize: "3rem", lineHeight: "1.2" },
"5xl": { fontSize: "3.75rem", lineHeight: "1.1" },
"6xl": { fontSize: "4.5rem", lineHeight: "1" },
"7xl": { fontSize: "6rem", lineHeight: "1" },
"8xl": { fontSize: "8rem", lineHeight: "1" },
"9xl": { fontSize: "10rem", lineHeight: "1" }
},
weights: {
thin: "100",
extralight: "200",
light: "300",
normal: "400",
medium: "500",
semibold: "600",
bold: "700",
extrabold: "800",
black: "900"
}
}
};
function getVariantConfig(variant) {
const config = typographyVariants[variant];
if (!config && process.env.NODE_ENV === "development") {
console.warn(
`Invalid typography variant: ${variant}. Falling back to 'body' variant.`
);
return typographyVariants.body;
}
return config || typographyVariants.body;
}
function getSemanticElement(variant, as) {
if (as) return as;
const variantConfig = typographyVariants[variant];
if (!variantConfig) return "span";
const semanticElement = variantConfig.semanticElement;
return semanticElement || "span";
}
function generateTypographyClasses({
variant = "body",
size,
weight,
align,
transform,
decoration,
whitespace,
overflow,
leading,
tracking,
lineClamp,
truncate: truncate2,
color,
gradient,
selectable
}) {
const variantConfig = getVariantConfig(variant);
const classes = [];
if (variant === "overline") {
classes.push("uppercase", "tracking-wide");
}
if (variant === "code") {
classes.push("font-mono");
}
if (variant === "kbd") {
classes.push(
"font-mono",
"px-1.5",
"py-0.5",
"text-xs",
"bg-surface-secondary",
"border",
"border-border-primary",
"rounded"
);
}
if (variant === "quote") {
classes.push("italic", "border-l-4", "border-border-primary", "pl-4");
}
if (size) {
classes.push(...generateResponsiveClasses(size, sizeClasses));
} else {
classes.push(sizeClasses[variantConfig.defaultSize]);
}
if (weight) {
classes.push(...generateResponsiveClasses(weight, weightClasses));
} else {
classes.push(weightClasses[variantConfig.defaultWeight]);
}
if (align) {
classes.push(...generateResponsiveClasses(align, alignmentClasses));
}
if (transform && transform !== "none") {
classes.push(transformClasses[transform]);
}
if (decoration && decoration !== "none") {
classes.push(decorationClasses[decoration]);
}
if (whitespace && whitespace !== "normal") {
classes.push(whitespaceClasses[whitespace]);
}
if (overflow && overflow !== "visible") {
classes.push(overflowClasses[overflow]);
}
if (leading && leading !== "normal") {
classes.push(leadingClasses[leading]);
}
if (tracking && tracking !== "normal") {
classes.push(trackingClasses[tracking]);
}
if (lineClamp) {
classes.push(lineClampClasses[lineClamp]);
}
if (truncate2) {
classes.push("truncate");
}
if (color && (color.startsWith("text-") || color.startsWith("bg-"))) {
classes.push(color);
} else {
classes.push(variantConfig.defaultColor);
}
if (gradient) {
classes.push("bg-gradient-to-r", "bg-clip-text", "text-transparent");
}
if (selectable === false) {
classes.push("select-none");
} else if (selectable === true) {
classes.push("select-text");
}
return classNames(...classes);
}
function generateHeadingClasses(level) {
const headingMap = {
1: { defaultSize: "4xl", defaultWeight: "bold" },
2: { defaultSize: "3xl", defaultWeight: "bold" },
3: {
defaultSize: "2xl",
defaultWeight: "semibold"
},
4: {
defaultSize: "xl",
defaultWeight: "semibold"
},
5: { defaultSize: "lg", defaultWeight: "medium" },
6: {
defaultSize: "base",
defaultWeight: "medium"
}
};
return headingMap[level];
}
function validateTypographyProps(props) {
const errors = [];
if (props.variant && typeof props.variant === "string" && !(props.variant in typographyVariants)) {
errors.push(`Invalid variant: ${props.variant}`);
}
if (props.size && typeof props.size === "string" && !(props.size in sizeClasses)) {
errors.push(`Invalid size: ${props.size}`);
}
if (props.weight && typeof props.weight === "string" && !(props.weight in weightClasses)) {
errors.push(`Invalid weight: ${props.weight}`);
}
return errors;
}
// src/types/form.ts
var FORM_FIELD_SIZES = ["sm", "md", "lg"];
var FORM_FIELD_VARIANTS = ["default", "error", "success"];
// src/types/index.ts
var BUTTON_VARIANTS = [
"primary",
"secondary",
"ghost",
"danger",
"success",
"warning"
];
var BUTTON_SIZES = ["xs", "sm", "md", "lg", "xl"];
var INPUT_VARIANTS = ["default", "error", "success"];
var INPUT_SIZES = ["sm", "md", "lg"];
var LABEL_SIZES = ["sm", "md", "lg"];
var ICON_SIZES = ["xs", "sm", "md", "lg", "xl", "2xl"];
var BADGE_VARIANTS = [
"default",
"primary",
"secondary",
"success",
"warning",
"danger"
];
var BADGE_SIZES = ["sm", "md", "lg"];
var FEATURE_CHIP_VARIANTS = [
"default",
"primary",
"secondary",
"success",
"warning",
"danger"
];
var FEATURE_CHIP_SIZES = ["sm", "md", "lg"];
var AVATAR_SIZES = ["xs", "sm", "md", "lg", "xl", "2xl"];
var TEXT_VARIANTS = [
// Content variants
"body",
"body-large",
"body-small",
"caption",
"overline",
"label",
"helper",
// Display variants
"display",
"headline",
"title",
"subtitle",
// Specialized variants
"code",
"kbd",
"quote",
"lead",
"muted"
];
var TEXT_SIZES = [
"xs",
// 12px
"sm",
// 14px
"base",
// 16px (renamed from 'md' for clarity)
"lg",
// 18px
"xl",
// 20px
"2xl",
// 24px
"3xl",
// 30px
"4xl",
// 36px
"5xl",
// 48px
"6xl",
// 60px
"7xl",
// 72px
"8xl",
// 96px
"9xl"
// 128px
];
var TEXT_WEIGHTS = [
"thin",
// 100
"extralight",
// 200
"light",
// 300
"normal",
// 400
"medium",
// 500
"semibold",
// 600
"bold",
// 700
"extrabold",
// 800
"black"
// 900
];
var TEXT_ALIGNMENTS = [
"left",
"center",
"right",
"justify",
"start",
"end"
];
var TEXT_TRANSFORMS = [
"none",
"uppercase",
"lowercase",
"capitalize"
];
var TEXT_DECORATIONS = [
"none",
"underline",
"overline",
"line-through"
];
var TEXT_WHITESPACE = [
"normal",
"nowrap",
"pre",
"pre-line",
"pre-wrap",
"break-spaces"
];
var TEXT_OVERFLOW = ["visible", "hidden", "clip", "ellipsis"];
var LINE_CLAMP_OPTIONS = [1, 2, 3, 4, 5, 6];
var TYPOGRAPHY_BREAKPOINTS = [
"xs",
"sm",
"md",
"lg",
"xl",
"2xl"
];
// src/contexts/SettingsContext.tsx
import {
createContext,
useContext,
useEffect,
useState as useState2
} from "react";
import { jsx } from "react/jsx-runtime";
var defaultSettings = {
theme: "system",
layout: "stacked",
containerWidth: "boxed"
};
var SettingsContext = createContext(
void 0
);
var SettingsProvider = ({
children,
initialSettings = {},
storageKey = "mfe-settings"
}) => {
const [settings, setSettings] = useState2(() => {
const savedSettings = storage.get(storageKey, {});
return {
...defaultSettings,
...initialSettings,
...savedSettings
};
});
useEffect(() => {
theme.applyTheme(settings.theme);
}, [settings.theme]);
useEffect(() => {
if (settings.theme !== "system") return;
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = () => {
theme.applyTheme("system");
};
mediaQuery.addEventListener("change", handleChange);
return () => mediaQuery.removeEventListener("change", handleChange);
}, [settings.theme]);
const updateSettings = (newSettings) => {
setSettings((prev) => {
const updated = { ...prev, ...newSettings };
storage.set(storageKey, updated);
return updated;
});
};
const resetSettings = () => {
const reset = { ...defaultSettings, ...initialSettings };
setSettings(reset);
storage.set(storageKey, reset);
};
const value = {
settings,
updateSettings,
resetSettings
};
return /* @__PURE__ */ jsx(SettingsContext.Provider, { value, children });
};
var useSettings = () => {
const context = useContext(SettingsContext);
if (context === void 0) {
throw new Error("useSettings must be used within a SettingsProvider");
}
return context;
};
// src/contexts/TypographyContext.tsx
import { createContext as createContext2, useContext as useContext2, useMemo } from "react";
import { jsx as jsx2 } from "react/jsx-runtime";
var TypographyContext = createContext2(null);
function TypographyProvider({
children,
baseSize = "base",
baseWeight = "normal",
baseColor = "text-text-primary",
scale = 1,
lineHeight = 1.5
}) {
const contextValue = useMemo(
() => ({
baseSize,
baseWeight,
baseColor,
scale,
lineHeight
}),
[baseSize, baseWeight, baseColor, scale, lineHeight]
);
return /* @__PURE__ */ jsx2(TypographyContext.Provider, { value: contextValue, children });
}
function useTypography() {
const context = useContext2(TypographyContext);
if (!context) {
return {
baseSize: "base",
baseWeight: "normal",
baseColor: "text-text-primary",
scale: 1,
lineHeight: 1.5
};
}
return context;
}
function useScaledTypography() {
const { scale, baseSize, baseWeight, baseColor } = useTypography();
return useMemo(() => {
const sizeMap = {
xs: scale > 1.2 ? "sm" : "xs",
sm: scale > 1.2 ? "base" : "sm",
base: scale > 1.2 ? "lg" : scale < 0.8 ? "sm" : "base",
lg: scale > 1.2 ? "xl" : scale < 0.8 ? "base" : "lg",
xl: scale > 1.2 ? "2xl" : scale < 0.8 ? "lg" : "xl",
"2xl": scale > 1.2 ? "3xl" : scale < 0.8 ? "xl" : "2xl",
"3xl": scale > 1.2 ? "4xl" : scale < 0.8 ? "2xl" : "3xl",
"4xl": scale > 1.2 ? "5xl" : scale < 0.8 ? "3xl" : "4xl",
"5xl": scale > 1.2 ? "6xl" : scale < 0.8 ? "4xl" : "5xl",
"6xl": scale > 1.2 ? "7xl" : scale < 0.8 ? "5xl" : "6xl",
"7xl": scale > 1.2 ? "8xl" : scale < 0.8 ? "6xl" : "7xl",
"8xl": scale > 1.2 ? "9xl" : scale < 0.8 ? "7xl" : "8xl",
"9xl": scale < 0.8 ? "8xl" : "9xl"
};
return {
getScaledSize: (size) => sizeMap[size] || size,
baseSize,
baseWeight,
baseColor,
scale
};
}, [scale, baseSize, baseWeight, baseColor]);
}
// src/components/atoms/Button.tsx
import { forwardRef, useCallback as useCallback2 } from "react";
// src/utils/componentUtils.ts
var BASE_INTERACTIVE_CLASSES = "inline-flex items-center justify-center transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2";
var createSemanticColorVariant = (colorName, type = "soft") => {
const baseColor = colorName === "danger" ? "error" : colorName;
const variants = {
solid: `bg-${baseColor}-600 text-white hover:bg-${baseColor}-700 dark:bg-${baseColor}-500 dark:hover:bg-${baseColor}-600`,
soft: `bg-${baseColor}-50 text-${baseColor}-700 border border-${baseColor}-200 dark:bg-${baseColor}-900/30 dark:text-${baseColor}-300 dark:border-${baseColor}-700/50`,
outline: `border border-${baseColor}-300 text-${baseColor}-700 hover:bg-${baseColor}-50 dark:border-${baseColor}-600 dark:text-${baseColor}-300 dark:hover:bg-${baseColor}-900/20`,
ghost: `text-${baseColor}-700 hover:bg-${baseColor}-50 dark:text-${baseColor}-300 dark:hover:bg-${baseColor}-900/20`
};
return variants[type];
};
var createSemanticFocusRing = (colorName) => {
const baseColor = colorName === "danger" ? "error" : colorName;
return `focus:ring-${baseColor}-500 dark:focus:ring-${baseColor}-400`;
};
var SIZE_MAPPINGS = {
padding: {
xs: "px-2 py-1",
sm: "px-2.5 py-1.5",
md: "px-3 py-2",
lg: "px-4 py-2.5",
xl: "px-6 py-3"
},
text: {
xs: "text-xs",
sm: "text-sm",
md: "text-sm",
lg: "text-base",
xl: "text-lg"
},
gap: {
xs: "gap-1",
sm: "gap-1.5",
md: "gap-2",
lg: "gap-2.5",
xl: "gap-3"
},
icon: {
xs: "w-3 h-3",
sm: "w-4 h-4",
md: "w-5 h-5",
lg: "w-6 h-6",
xl: "w-8 h-8"
}
};
var createSizeClasses = (size, options = {}) => {
const {
includePadding = true,
includeText = true,
includeGap = true,
customPadding,
customText
} = options;
const classes = [];
if (includePadding) {
const paddingMap = customPadding || SIZE_MAPPINGS.padding;
classes.push(paddingMap[size] || paddingMap.md);
}
if (includeText) {
const textMap = customText || SIZE_MAPPINGS.text;
classes.push(textMap[size] || textMap.md);
}
if (includeGap) {
classes.push(
SIZE_MAPPINGS.gap[size] || SIZE_MAPPINGS.gap.md
);
}
return classes.join(" ");
};
var createAriaAttributes = (props) => {
const attributes = {};
if (props.disabled) attributes["aria-disabled"] = true;
if (props.loading) attributes["aria-busy"] = true;
if (props.expanded !== void 0)
attributes["aria-expanded"] = props.expanded;
if (props.selected !== void 0)
attributes["aria-selected"] = props.selected;
if (props.label) attributes["aria-label"] = props.label;
if (props.describedBy) attributes["aria-describedby"] = props.describedBy;
return attributes;
};
var SURFACE_VARIANTS = {
primary: "bg-surface-primary text-text-primary border-border-primary",
secondary: "bg-surface-secondary text-text-primary border-border-primary",
tertiary: "bg-surface-tertiary text-text-secondary border-border-secondary",
elevated: "bg-surface-elevated text-text-primary border-border-primary shadow-sm"
};
var INTERACTIVE_STATES = {
hover: "hover:bg-surface-secondary",
active: "active:bg-surface-tertiary",
focus: "focus:ring-border-focus",
disabled: "disabled:opacity-50 disabled:cursor-not-allowed"
};
// src/components/atoms/LoadingSpinner.tsx
import { memo } from "react";
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
var LoadingSpinner = memo(
({
className,
size = "md",
color = "primary",
text,
"aria-label": ariaLabel = "Loading",
...props
}) => {
const sizeClasses3 = {
xs: "h-3 w-3",
sm: "h-4 w-4",
md: "h-8 w-8",
lg: "h-12 w-12",
xl: "h-16 w-16"
};
const colorClasses = {
primary: "border-surface-secondary border-t-primary-600",
secondary: "border-surface-secondary border-t-text-secondary",
success: "border-surface-secondary border-t-success-600",
warning: "border-surface-secondary border-t-warning-600",
danger: "border-surface-secondary border-t-danger-600",
white: "border-white/30 border-t-white",
current: "border-current/30 border-t-current"
};
const textSizeClasses = {
xs: "text-xs",
sm: "text-xs",
md: "text-sm",
lg: "text-base",
xl: "text-lg"
};
return /* @__PURE__ */ jsxs(
"div",
{
className: classNames(
"flex flex-col items-center justify-center",
className
),
...props,
children: [
/* @__PURE__ */ jsx3(
"div",
{
className: classNames(
"animate-spin rounded-full border-2",
sizeClasses3[size],
colorClasses[color]
),
role: "status",
"aria-label": ariaLabel,
children: /* @__PURE__ */ jsx3("span", { className: "sr-only", children: ariaLabel })
}
),
text && /* @__PURE__ */ jsx3(
"p",
{
className: classNames(
"mt-2 text-text-secondary",
textSizeClasses[size]
),
children: text
}
)
]
}
);
}
);
LoadingSpinner.displayName = "LoadingSpinner";
var LoadingSpinner_default = LoadingSpinner;
// src/components/atoms/Button.tsx
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
var ButtonComponent = forwardRef(
({
children,
className,
variant = "primary",
size = "md",
disabled = false,
loading = false,
leftIcon,
rightIcon,
fullWidth = false,
as: Component = "button",
...props
}, ref) => {
const bas