aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
160 lines (157 loc) • 5.1 kB
JavaScript
'use client';
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { cn } from '../../lib/utilsComprehensive.js';
import { forwardRef } from 'react';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
import '../../primitives/GlassCore.js';
import '../../primitives/glass/GlassAdvanced.js';
import { OptimizedGlassCore } from '../../primitives/OptimizedGlassCore.js';
import '../../primitives/glass/OptimizedGlassAdvanced.js';
import '../../primitives/MotionNative.js';
import '../../primitives/motion/MotionFramer.js';
const GlassTypingIndicator = /*#__PURE__*/forwardRef(({
isTyping = true,
users,
showUsers = true,
text,
size = "md",
elevation = "level1",
variant = "bounce",
dotColor = "primary",
dotCount = 3,
glass = true,
className,
...props
}, ref) => {
useReducedMotion();
if (!isTyping) return null;
const userList = Array.isArray(users) ? users : users ? [users] : [];
const hasUsers = userList.length > 0;
const getUserText = () => {
if (!hasUsers || !showUsers) return null;
if (userList.length === 1) {
return `${userList[0]} is`;
} else if (userList.length === 2) {
return `${userList[0]} and ${userList[1]} are`;
} else if (userList.length > 2) {
return `${userList[0]}, ${userList[1]} and ${userList.length - 2} other${userList.length - 2 > 1 ? "s" : ""} are`;
}
return null;
};
const displayText = text ? text.replace("{users}", userList.join(", ")).replace("{isAre}", userList.length === 1 ? "is" : "are") : null;
const sizeClasses = {
sm: {
dot: "w-1.5 h-1.5",
text: "glass-text-xs",
gap: "gap-1",
padding: "glass-px-2 glass-py-1"
},
md: {
dot: "w-2 h-2",
text: "glass-text-sm",
gap: "gap-1.5",
padding: "glass-px-3 glass-py-2"
},
lg: {
dot: "w-2.5 h-2.5",
text: "glass-text-base",
gap: "gap-2",
padding: "glass-px-4 glass-py-3"
}
};
const dotColorClasses = {
primary: "bg-blue-500",
secondary: "bg-purple-500",
success: "bg-green-500",
warning: "bg-yellow-500",
danger: "bg-red-500",
neutral: "glass-surface-subtle"
};
const getAnimationStyle = index => {
const delay = index * 150;
const styles = {
animationDelay: `${delay}ms`
};
if (variant === "wave") {
styles.animation = `wave 1.4s ease-in-out infinite`;
styles.animationDelay = `${delay}ms`;
}
return styles;
};
const dots = Array.from({
length: dotCount
}, (_, index) => jsx("div", {
className: cn(sizeClasses[size].dot, dotColorClasses[dotColor], "rounded-full", variant !== "wave" && animations[variant]),
style: getAnimationStyle(index),
"aria-hidden": "true"
}, index));
const content = jsxs("div", {
className: cn("inline-flex items-center", sizeClasses[size].gap, !glass && sizeClasses[size].padding),
children: [showUsers && hasUsers && jsx("span", {
className: cn(sizeClasses[size].text, "glass-text-secondary font-medium"),
children: displayText || jsxs(Fragment, {
children: [getUserText(), " typing", jsx("span", {
className: 'glass-inline-flex ml-1 glass-gap-0.5',
children: Array.from({
length: 3
}, (_, i) => jsx("span", {
className: 'animate-pulse',
style: {
animationDelay: `${i * 200}ms`
},
children: "."
}, i))
})]
})
}), (!showUsers || !hasUsers) && jsx("div", {
className: cn("flex items-center", sizeClasses[size].gap),
children: dots
})]
});
if (!glass) {
return jsx("div", {
"data-glass-component": true,
ref: ref,
className: cn("inline-flex", className),
role: "status",
"aria-live": "polite",
"aria-label": hasUsers && showUsers ? `${userList.join(", ")} ${userList.length === 1 ? "is" : "are"} typing` : "Someone is typing",
...props,
children: content
});
}
return jsx(OptimizedGlassCore, {
ref: ref,
elevation: elevation,
className: cn("inline-flex glass-radius-full", sizeClasses[size].padding, className),
role: "status",
"aria-live": "polite",
"aria-label": hasUsers && showUsers ? `${userList.join(", ")} ${userList.length === 1 ? "is" : "are"} typing` : "Someone is typing",
...props,
children: content
});
});
GlassTypingIndicator.displayName = "GlassTypingIndicator";
const animations = {
bounce: "animate-bounce",
pulse: "animate-pulse",
wave: "",
fade: "animate-pulse"
};
if (typeof document !== "undefined" && !document.getElementById("typing-indicator-keyframes")) {
const style = document.createElement("style");
style.id = "typing-indicator-keyframes";
style.textContent = `
@keyframes wave {
0%, 60%, 100% {
transform: translateY(0);
}
30% {
transform: translateY(-8px);
}
}
`;
document.head.appendChild(style);
}
export { GlassTypingIndicator, GlassTypingIndicator as default };
//# sourceMappingURL=GlassTypingIndicator.js.map