UNPKG

@brutalcomponent/react

Version:
1,119 lines (1,113 loc) 184 kB
'use strict'; var chunkR74LWSGE_js = require('./chunk-R74LWSGE.js'); var chunk7GZ4CFXP_js = require('./chunk-7GZ4CFXP.js'); var chunk7YHHVG7W_js = require('./chunk-7YHHVG7W.js'); var chunk7T4KDGYW_js = require('./chunk-7T4KDGYW.js'); var React35 = require('react'); var fa = require('react-icons/fa'); var clsx = require('clsx'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var React35__default = /*#__PURE__*/_interopDefault(React35); /** * @brutalcomponent/react * (c) David Heffler (https://dvh.sh) * Licensed under MIT */ var StatCard = ({ title, value, previousValue, format = "number", trend, icon: Icon2, color = "default", size = "md", brutal = true, className }) => { const sizeClasses = { sm: "p-4", md: "p-6", lg: "p-8" }; const valueSizes = { sm: "text-2xl", md: "text-3xl", lg: "text-4xl" }; const colorClasses = { default: "border-l-brutal-black", success: "border-l-brutal-mint", warning: "border-l-brutal-yellow", danger: "border-l-brutal-coral" }; const calculateChange = () => { if (!previousValue || typeof value !== "number" || typeof previousValue !== "number") { return null; } return (value - previousValue) / previousValue * 100; }; const change = calculateChange(); return /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( // Base brutal styling "bg-brutal-surface0 shadow-brutal", brutal && "border-4 border-brutal-black border-l-8", !brutal && "border border-brutal-gray-300", colorClasses[color], sizeClasses[size], "hover:shadow-brutal-md hover:-translate-y-0.5 transition-all duration-200", "transform hover:rotate-0", brutal && "-rotate-1", className ) }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex justify-between items-start mb-4" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-xs font-black uppercase text-brutal-gray-600 tracking-wider mb-2 transform skew-x-1" }, title), /* @__PURE__ */ React35__default.default.createElement( "p", { className: chunk7T4KDGYW_js.cn( "font-black text-brutal-black transform -skew-x-2", valueSizes[size] ) }, format === "currency" && "$", typeof value === "number" ? value.toLocaleString() : value, format === "percentage" && "%" )), Icon2 && /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( "p-2 transform rotate-3", brutal && "bg-brutal-gray-100 border-2 border-brutal-black shadow-brutal-sm", !brutal && "bg-brutal-gray-100 rounded" ) }, /* @__PURE__ */ React35__default.default.createElement(Icon2, { className: "w-6 h-6 text-brutal-gray-700" }) )), change !== null && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React35__default.default.createElement( "span", { className: chunk7T4KDGYW_js.cn( "text-sm font-black uppercase tracking-wider px-2 py-1", brutal && "border-2 border-brutal-black shadow-brutal-sm", change >= 0 ? "bg-brutal-mint text-brutal-black" : "bg-brutal-coral text-brutal-black" ) }, change >= 0 ? "+" : "", change.toFixed(1), "%" ), /* @__PURE__ */ React35__default.default.createElement("span", { className: "text-xs text-brutal-gray-500 font-mono" }, "from", " ", typeof previousValue === "number" ? previousValue.toLocaleString() : previousValue)) ); }; var ExperienceCard = ({ title, company, location, startDate, endDate, type, description, bullets, keywords = [], brutal = true, variant = "default", accentColor = "brutal-pink", className }) => { const duration = chunkR74LWSGE_js.formatDuration( chunkR74LWSGE_js.parseLooseDate(startDate), endDate ? chunkR74LWSGE_js.parseLooseDate(endDate) : null ); chunk7T4KDGYW_js.getAccentClasses(accentColor); const highlightedDescription = description ? chunkR74LWSGE_js.emphasizeText(description, keywords) : []; const highlightedBullets = bullets?.map( (bullet) => chunkR74LWSGE_js.emphasizeText(bullet, keywords) ); return /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( // Base styling - match original exactly "relative bg-brutal-surface0 p-6 shadow-brutal border-4 overflow-hidden", "border-accent", // Use CSS variable for theming "transition-all duration-300", className ) }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3 mb-4" }, /* @__PURE__ */ React35__default.default.createElement("div", null, /* @__PURE__ */ React35__default.default.createElement("h3", { className: "text-2xl font-black text-accent uppercase tracking-wider transform -skew-x-3" }, title), /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-lg text-brutal-gray-700 font-bold mt-1" }, company)), variant !== "compact" && /* @__PURE__ */ React35__default.default.createElement("div", { className: "text-right" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center gap-2 text-brutal-gray-600 text-sm" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaClock, size: "xs" }), /* @__PURE__ */ React35__default.default.createElement("span", { className: "font-mono" }, startDate, " - ", endDate || "Present")), /* @__PURE__ */ React35__default.default.createElement("span", { className: "inline-block text-xs font-black text-brutal-pink uppercase tracking-wider mt-1 px-2 py-1 bg-brutal-surface1" }, duration))), (type || location) && variant !== "compact" && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-wrap gap-4 text-xs text-brutal-gray-600 mb-4 font-mono" }, type && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaBriefcase, size: "xs" }), /* @__PURE__ */ React35__default.default.createElement("span", null, type)), location && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaMapMarkerAlt, size: "xs" }), /* @__PURE__ */ React35__default.default.createElement("span", null, location))), description && variant !== "compact" && /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-sm text-brutal-gray-700 mb-4 leading-relaxed" }, highlightedDescription.map( (segment, idx) => segment.bold ? /* @__PURE__ */ React35__default.default.createElement( "strong", { key: idx, className: "font-black text-brutal-pink inline-block" }, segment.text ) : /* @__PURE__ */ React35__default.default.createElement(React35.Fragment, { key: idx }, segment.text) )), bullets && bullets.length > 0 && variant === "detailed" && /* @__PURE__ */ React35__default.default.createElement("ul", { className: "space-y-2" }, highlightedBullets?.map((bulletSegments, idx) => /* @__PURE__ */ React35__default.default.createElement("li", { key: idx, className: "flex text-sm text-brutal-gray-700" }, /* @__PURE__ */ React35__default.default.createElement("span", { className: "text-brutal-pink font-black mr-2 flex-shrink-0" }, "\u2192"), /* @__PURE__ */ React35__default.default.createElement("span", null, bulletSegments.map( (segment, segIdx) => segment.bold ? /* @__PURE__ */ React35__default.default.createElement( "strong", { key: segIdx, className: "font-black text-brutal-pink inline-block" }, segment.text ) : /* @__PURE__ */ React35__default.default.createElement(React35.Fragment, { key: segIdx }, segment.text) ))))) ); }; var Badge = ({ variant = "default", size = "sm", brutal = true, icon: Icon2, iconPosition = "left", dot = false, removable = false, onRemove, className, children, ...props }) => { const variantClasses = { default: "bg-brutal-surface0 text-brutal-black border-brutal-black", primary: "bg-brutal-black text-brutal-white border-brutal-black", secondary: "bg-brutal-white text-brutal-black border-brutal-black", success: "bg-brutal-mint text-brutal-black border-brutal-black", warning: "bg-brutal-yellow text-brutal-black border-brutal-black", danger: "bg-brutal-coral text-brutal-black border-brutal-black", info: "bg-brutal-sky text-brutal-black border-brutal-black" }; const sizeClasses = { xs: "px-1.5 py-0.5 text-xs", sm: "px-2 py-1 text-xs", md: "px-3 py-1.5 text-sm", lg: "px-4 py-2 text-base" }; const iconSizes = { xs: "w-2.5 h-2.5", sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" }; return /* @__PURE__ */ React35__default.default.createElement( "span", { className: chunk7T4KDGYW_js.cn( "inline-flex items-center gap-1", "font-black uppercase tracking-wider", brutal ? "border-2 shadow-brutal-sm" : "border rounded", sizeClasses[size], variantClasses[variant], "transition-all duration-200", brutal && "hover:shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5", brutal && "transform hover:rotate-0", brutal && size !== "xs" && "rotate-1", className ), ...props }, dot && /* @__PURE__ */ React35__default.default.createElement( "span", { className: chunk7T4KDGYW_js.cn( "rounded-full bg-current", size === "xs" ? "w-1 h-1" : size === "sm" ? "w-1.5 h-1.5" : "w-2 h-2" ) } ), Icon2 && iconPosition === "left" && /* @__PURE__ */ React35__default.default.createElement(Icon2, { className: iconSizes[size] }), children, Icon2 && iconPosition === "right" && /* @__PURE__ */ React35__default.default.createElement(Icon2, { className: iconSizes[size] }), removable && /* @__PURE__ */ React35__default.default.createElement( "button", { onClick: (e) => { e.stopPropagation(); onRemove?.(); }, className: chunk7T4KDGYW_js.cn( "ml-1 -mr-1 hover:bg-brutal-black/20 transition-colors", size === "xs" || size === "sm" ? "p-0.5" : "p-1" ), "aria-label": "Remove" }, /* @__PURE__ */ React35__default.default.createElement( "svg", { className: iconSizes[size], fill: "none", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React35__default.default.createElement("path", { d: "M6 18L18 6M6 6l12 12" }) ) ) ); }; var BadgeGroup = ({ children, className }) => /* @__PURE__ */ React35__default.default.createElement("div", { className: clsx.clsx("flex flex-wrap gap-2", className) }, children); // src/components/core/Card/ProjectCard.tsx var ProjectCard = ({ title, description, technologies, demoLink, sourceLink, image, keywords = [], variant = "default", brutal = true, accentColor = "brutal-pink", className }) => { const highlightedDescription = chunkR74LWSGE_js.emphasizeText(description, keywords); return /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( // Base styling - match original exactly "relative bg-brutal-surface0 border-4 border-accent p-6 shadow-brutal", "overflow-hidden flex flex-col h-full", className ) }, /* @__PURE__ */ React35__default.default.createElement("h3", { className: "text-2xl font-black text-accent mb-3 uppercase tracking-wider transform -skew-x-6" }, title), /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-brutal-gray-700 mb-4 font-mono text-sm leading-relaxed flex-grow" }, highlightedDescription.map( (segment, idx) => segment.bold ? /* @__PURE__ */ React35__default.default.createElement( "strong", { key: idx, className: "font-black text-brutal-pink inline-block" }, segment.text ) : /* @__PURE__ */ React35__default.default.createElement(React35.Fragment, { key: idx }, segment.text) )), technologies.length > 0 && /* @__PURE__ */ React35__default.default.createElement("div", { className: "mb-5" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaCode, size: "xs", className: "text-brutal-gray-600" }), /* @__PURE__ */ React35__default.default.createElement("span", { className: "text-xs font-bold text-brutal-gray-600 uppercase tracking-wider" }, "Built with")), /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-wrap gap-2" }, technologies.map((tech, idx) => /* @__PURE__ */ React35__default.default.createElement(Badge, { key: idx, size: "xs", variant: "secondary", brutal }, tech)))), /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex gap-3 mt-auto" }, demoLink && /* @__PURE__ */ React35__default.default.createElement( "a", { href: demoLink, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-2 font-black uppercase tracking-wider px-3 py-2 border-2 transition-all duration-200 shadow-brutal border-accent bg-accent text-brutal-black hover:bg-transparent hover:text-accent" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaExternalLinkAlt, size: "sm" }), /* @__PURE__ */ React35__default.default.createElement("span", { className: "text-xs" }, "Demo") ), sourceLink && /* @__PURE__ */ React35__default.default.createElement( "a", { href: sourceLink, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-2 font-black uppercase tracking-wider px-3 py-2 border-2 transition-all duration-200 shadow-brutal border-accent text-accent hover:bg-accent hover:text-brutal-black" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaGithub, size: "sm" }), /* @__PURE__ */ React35__default.default.createElement("span", { className: "text-xs" }, "Code") )) ); }; var WorkCard = ({ title, shortDescription, technologies, link, date, client, testimonial, keywords = [], brutal = true, accentColor = "brutal-pink", className }) => { const highlightedDescription = chunkR74LWSGE_js.emphasizeText(shortDescription, keywords); const normalizedTechs = Array.isArray(technologies) ? technologies.map((tech) => tech.toLowerCase()) : []; const safeLink = link && typeof link === "string" && link.startsWith("http") ? link : `https://${String(link ?? "")}`; return /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( // Base styling - match original exactly "relative bg-brutal-surface0 border-4 border-accent p-6 shadow-brutal overflow-hidden", "transform rotate-1 hover:rotate-0 hover:scale-1.02 hover:translate-x-1.5", "transition-all duration-300", className ) }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3 mb-3" }, /* @__PURE__ */ React35__default.default.createElement("div", null, /* @__PURE__ */ React35__default.default.createElement("h3", { className: "text-2xl font-black text-accent uppercase tracking-wider transform -skew-x-6" }, title), client && /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-sm font-bold text-brutal-gray-600 mt-1" }, "for ", client)), /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center gap-2 text-brutal-gray-600" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaCalendar, size: "xs" }), /* @__PURE__ */ React35__default.default.createElement("span", { className: "font-mono text-xs font-bold" }, date))), /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-brutal-gray-700 mb-4 font-mono text-sm leading-relaxed" }, highlightedDescription.map( (segment, idx) => segment.bold ? /* @__PURE__ */ React35__default.default.createElement( "strong", { key: idx, className: "font-black text-brutal-pink inline-block" }, segment.text ) : /* @__PURE__ */ React35__default.default.createElement(React35.Fragment, { key: idx }, segment.text) )), testimonial && /* @__PURE__ */ React35__default.default.createElement("blockquote", { className: "mb-4 p-3 italic bg-brutal-gray-100 border-l-4 border-accent" }, /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-sm text-brutal-gray-700" }, '"', testimonial, '"')), normalizedTechs.length > 0 && /* @__PURE__ */ React35__default.default.createElement("div", { className: "mb-5" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaCode, size: "xs", className: "text-brutal-gray-600" }), /* @__PURE__ */ React35__default.default.createElement("span", { className: "text-xs font-bold text-brutal-gray-600 uppercase tracking-wider" }, "Built with")), /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-wrap gap-2" }, normalizedTechs.map((tech, idx) => /* @__PURE__ */ React35__default.default.createElement(Badge, { key: idx, size: "xs", variant: "secondary", brutal }, tech)))), link && /* @__PURE__ */ React35__default.default.createElement( "a", { href: safeLink, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-2 text-accent font-black uppercase tracking-wider px-3 py-2 border-2 border-accent bg-transparent shadow-brutal hover:bg-accent hover:text-brutal-black transition-colors" }, "Live Demo", /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaExternalLinkAlt, size: "sm" }) ), /* @__PURE__ */ React35__default.default.createElement("div", { className: "absolute top-0 right-0 w-16 h-16 bg-accent opacity-10 -mr-8 -mt-8" }) ); }; var SoftwareCard = ({ title, description, link, price, brewInstall, operatingSystem, features = [], variant = "default", brutal = true, accentColor = "brutal-pink", className }) => { const [copied, setCopied] = React35.useState(false); const copyToClipboard = React35.useCallback((text) => { try { navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 1400); } catch (e) { console.error("Clipboard write failed:", e); } }, []); const safeLink = typeof link === "string" && link ? link.startsWith("http") ? link : `https://${link}` : void 0; const osTags = operatingSystem ? operatingSystem.split(",").map((s) => s.trim()).filter(Boolean) : []; return /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( // Base styling - match original exactly "relative bg-brutal-surface0 border-4 border-accent p-6 shadow-brutal", "overflow-hidden flex flex-col h-full", "transform -rotate-1 hover:rotate-0 hover:scale-1.02 hover:translate-x-1.5", "transition-all duration-300", className ) }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-start justify-between gap-3 mb-3" }, /* @__PURE__ */ React35__default.default.createElement("h3", { className: "text-xl font-black text-accent uppercase tracking-wider transform -skew-x-6" }, title), price && /* @__PURE__ */ React35__default.default.createElement("span", { className: "inline-block bg-brutal-surface1 text-brutal-gray-600 px-3 py-1 text-xs font-black uppercase tracking-wider border-2 border-accent" }, price)), /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-brutal-gray-700 mb-4 flex-grow font-mono text-sm leading-relaxed" }, description), features.length > 0 && variant === "detailed" && /* @__PURE__ */ React35__default.default.createElement("ul", { className: "mb-4 space-y-1" }, features.map((feature, idx) => /* @__PURE__ */ React35__default.default.createElement( "li", { key: idx, className: "flex items-start text-xs text-brutal-gray-600" }, /* @__PURE__ */ React35__default.default.createElement("span", { className: "mr-2 text-accent" }, "\u2713"), feature ))), /* @__PURE__ */ React35__default.default.createElement("div", { className: "mt-auto flex items-center justify-between gap-3" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-wrap items-center gap-1 text-xs font-black uppercase tracking-wider text-brutal-gray-600" }, osTags.length ? osTags.map((os, idx) => /* @__PURE__ */ React35__default.default.createElement( "span", { key: idx, className: "px-2 py-0.5 border border-accent bg-brutal-surface1" }, os )) : /* @__PURE__ */ React35__default.default.createElement("span", { className: "px-2 py-0.5 border border-accent bg-brutal-surface1" }, "N/A")), /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center gap-3" }, brewInstall && /* @__PURE__ */ React35__default.default.createElement( "button", { onClick: () => copyToClipboard(brewInstall), className: "inline-flex items-center gap-2 text-brutal-gray-600 hover:text-accent transition-colors px-2 py-1 border-2 border-accent bg-brutal-surface1 font-black uppercase tracking-wider text-xs", "aria-label": "Copy Brew Install Command", title: "Copy Brew Install Command" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaCopy, size: "xs" }), "Copy" ), safeLink && /* @__PURE__ */ React35__default.default.createElement( "a", { href: safeLink, className: "inline-flex items-center gap-2 text-accent border-2 border-accent px-2 py-1 bg-transparent hover:bg-accent hover:text-brutal-black transition-colors font-black uppercase tracking-wider text-xs", target: "_blank", rel: "noopener noreferrer", "aria-label": "View software" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaExternalLinkAlt, size: "xs" }), "View" ))), copied && /* @__PURE__ */ React35__default.default.createElement("div", { className: "absolute bottom-3 right-3 bg-brutal-surface1 border-2 border-accent text-brutal-gray-700 px-3 py-1 font-mono text-xs shadow-brutal" }, "Copied!"), /* @__PURE__ */ React35__default.default.createElement("div", { className: "pointer-events-none absolute inset-1 border-2 border-accent opacity-30" }) ); }; var SoftwareCardSkeleton = () => /* @__PURE__ */ React35__default.default.createElement("div", { className: "bg-brutal-surface0 border-4 border-accent p-6 shadow-brutal h-[200px] flex flex-col animate-pulse" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "h-6 bg-brutal-gray-300 w-3/4 mb-3" }), /* @__PURE__ */ React35__default.default.createElement("div", { className: "h-4 bg-brutal-gray-300 w-full mb-2" }), /* @__PURE__ */ React35__default.default.createElement("div", { className: "h-4 bg-brutal-gray-300 w-5/6 mb-4" }), /* @__PURE__ */ React35__default.default.createElement("div", { className: "mt-auto flex items-center gap-2" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "h-7 w-20 bg-brutal-gray-300" }), /* @__PURE__ */ React35__default.default.createElement("div", { className: "h-7 w-16 bg-brutal-gray-300" }))); var UserCard = ({ name, avatar, titles = [], bio, links = [], rotationInterval = 2500, variant = "default", brutal = true, accentColor = "brutal-pink", className }) => { const [titleIndex, setTitleIndex] = React35.useState(0); const [isImageLoaded, setIsImageLoaded] = React35.useState(false); React35.useEffect(() => { if (titles.length <= 1) return; const interval = setInterval(() => { setTitleIndex((prev) => (prev + 1) % titles.length); }, rotationInterval); return () => clearInterval(interval); }, [titles.length, rotationInterval]); return /* @__PURE__ */ React35__default.default.createElement("div", { className: chunk7T4KDGYW_js.cn("text-center mb-8", className) }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "relative mx-auto mb-4 w-32 h-32 group" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "absolute inset-0 bg-accent opacity-30 rounded-full animate-pulse" }), /* @__PURE__ */ React35__default.default.createElement("div", { className: "relative rounded-full overflow-hidden border-4 border-accent shadow-brutal group-hover:shadow-brutal-md transition-all duration-300" }, !isImageLoaded && /* @__PURE__ */ React35__default.default.createElement("div", { className: "w-full h-full bg-brutal-gray-200 animate-pulse" }), /* @__PURE__ */ React35__default.default.createElement( "img", { src: avatar, alt: name, width: 128, height: 128, onLoad: () => setIsImageLoaded(true), className: chunk7T4KDGYW_js.cn( "w-full h-full object-cover", "group-hover:scale-110 transition-transform duration-300", !isImageLoaded && "invisible" ) } ))), /* @__PURE__ */ React35__default.default.createElement("h3", { className: "text-xl font-black mb-2 text-brutal-gray-700 uppercase tracking-widest transform hover:-skew-x-6 transition-transform duration-200" }, name), titles.length > 0 && /* @__PURE__ */ React35__default.default.createElement("div", { className: "h-6 relative overflow-hidden" }, /* @__PURE__ */ React35__default.default.createElement( "div", { className: "absolute inset-x-0 transition-transform duration-300", style: { transform: `translateY(-${titleIndex * 100}%)` } }, titles.map((title, index) => /* @__PURE__ */ React35__default.default.createElement( "p", { key: index, className: "text-sm text-brutal-gray-600 font-mono h-6 flex items-center justify-center" }, title )) )), bio && variant !== "compact" && /* @__PURE__ */ React35__default.default.createElement("p", { className: "mt-4 text-sm text-brutal-gray-700 font-mono max-w-xs mx-auto" }, bio), links.length > 0 && variant === "detailed" && /* @__PURE__ */ React35__default.default.createElement("div", { className: "mt-4 flex justify-center gap-3" }, links.map((link, idx) => /* @__PURE__ */ React35__default.default.createElement( "a", { key: idx, href: link.href, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1 px-3 py-1 text-xs font-bold uppercase tracking-wider border-2 border-brutal-black hover:bg-brutal-black hover:text-brutal-white transition-colors" }, link.icon, link.label )))); }; var PositionCard = ({ company, position, description, technologies, companyLink, dateRange, location, achievements = [], variant = "default", brutal = true, accentColor = "brutal-pink", className }) => { return /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( // Base styling - match original exactly "bg-brutal-surface0 p-6 shadow-md hover:shadow-lg transition-shadow duration-300", "transform -skew-x-2 border-l-4 border-accent", className ) }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-col mb-4" }, /* @__PURE__ */ React35__default.default.createElement("h3", { className: "text-3xl font-bold text-accent mb-1 uppercase tracking-wide" }, company), /* @__PURE__ */ React35__default.default.createElement("span", { className: "text-lg text-brutal-gray-600 font-mono" }, dateRange)), /* @__PURE__ */ React35__default.default.createElement("h4", { className: "text-2xl font-semibold text-brutal-gray-700 mb-3 transform skew-x-2" }, position), /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-brutal-gray-700 mb-4 text-base font-mono leading-relaxed" }, description), /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-wrap gap-2 mb-4" }, technologies.map((tech, idx) => /* @__PURE__ */ React35__default.default.createElement(Badge, { key: idx, size: "sm", variant: "secondary", brutal }, tech))), companyLink && /* @__PURE__ */ React35__default.default.createElement( "a", { href: companyLink, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center text-accent hover:underline text-lg font-bold" }, "Company Website", /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaExternalLinkAlt, size: "md", className: "ml-2" }) ) ); }; var BlogCard = ({ title, excerpt, date, href, views, readingTime, tags, origin, type, brutal = true, accentColor = "brutal-pink", className }) => { const isCooking = origin && type; return /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( // Base styling - match original exactly "bg-brutal-surface0 p-6 shadow-lg flex flex-col h-full relative overflow-hidden", "border-l-4 border-accent transition-all duration-300", "hover:scale-[1.03] hover:-rotate-1", className ) }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-col mb-4" }, /* @__PURE__ */ React35__default.default.createElement("h3", { className: "text-2xl font-bold text-accent mb-2 uppercase tracking-wide" }, title), /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center text-brutal-gray-600 space-x-4 text-sm flex-wrap" }, /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaCalendarAlt, size: "xs", className: "mr-1" }), /* @__PURE__ */ React35__default.default.createElement("span", null, new Date(date).toLocaleDateString())), readingTime && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaBook, size: "xs", className: "mr-1" }), /* @__PURE__ */ React35__default.default.createElement("span", null, "~", readingTime, " min")), views !== void 0 && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaEye, size: "xs", className: "mr-1" }), /* @__PURE__ */ React35__default.default.createElement("span", null, views, " views")), origin && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaGlobe, size: "xs", className: "mr-1" }), /* @__PURE__ */ React35__default.default.createElement("span", null, origin)), type && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaUtensils, size: "xs", className: "mr-1" }), /* @__PURE__ */ React35__default.default.createElement("span", null, type)))), /* @__PURE__ */ React35__default.default.createElement("p", { className: "text-brutal-gray-700 mb-4 flex-grow font-mono text-sm" }, excerpt), tags && tags.length > 0 && /* @__PURE__ */ React35__default.default.createElement("div", { className: "flex flex-wrap gap-2 mb-4" }, tags.map((tag, idx) => /* @__PURE__ */ React35__default.default.createElement(Badge, { key: idx, size: "xs", variant: "secondary", brutal }, tag))), /* @__PURE__ */ React35__default.default.createElement( "a", { href: isCooking ? `/cooking/${href}` : `/blog/${href}`, className: "text-brutal-sky hover:text-accent transition-colors duration-200 flex items-center group self-start" }, /* @__PURE__ */ React35__default.default.createElement("span", { className: "mr-2 uppercase tracking-wide font-bold" }, "Read more"), /* @__PURE__ */ React35__default.default.createElement( chunk7YHHVG7W_js.Icon, { icon: fa.FaArrowRight, size: "sm", className: "transition-transform duration-300 group-hover:translate-x-2" } ) ), /* @__PURE__ */ React35__default.default.createElement("div", { className: "absolute top-0 right-0 w-16 h-16 bg-accent opacity-10 rounded-full -mr-8 -mt-8" }) ); }; var Chip = ({ children, variant = "default", size = "sm", icon: IconComponent, iconPosition = "left", onRemove, onClick, brutal = true, selected = false, disabled = false, accentColor = "brutal-pink", className }) => { const Component = onClick ? "button" : "span"; const sizeClasses = chunk7T4KDGYW_js.getSizeClasses(size); const iconSizes = { xs: "xs", sm: "xs", md: "sm", lg: "sm" }; return /* @__PURE__ */ React35__default.default.createElement( Component, { className: chunk7T4KDGYW_js.cn( // Base styling "inline-flex items-center font-black uppercase tracking-wider", "transition-all duration-200", // Size classes sizeClasses.padding, sizeClasses.text, "gap-1.5", // Brutal styling brutal && [ sizeClasses.border, "border-brutal-black", sizeClasses.shadow ], !brutal && "border rounded-md", // Variant styling variant === "default" && "bg-brutal-gray-100 text-brutal-black", variant === "primary" && "bg-brutal-black text-brutal-white", variant === "secondary" && "bg-brutal-white text-brutal-black", variant === "success" && "bg-brutal-mint text-brutal-black", variant === "warning" && "bg-brutal-yellow text-brutal-black", variant === "danger" && "bg-brutal-coral text-brutal-black", variant === "ghost" && "bg-transparent text-brutal-black border-brutal-black", // Selected state selected && [ "bg-accent text-brutal-black", brutal && "shadow-brutal transform -rotate-1" ], // Interactive states onClick && !disabled && [ "cursor-pointer", brutal && "hover:shadow-brutal-md hover:transform hover:-rotate-0.5", !brutal && "hover:shadow-md hover:scale-105" ], // Disabled state disabled && "opacity-50 cursor-not-allowed", className ), onClick: !disabled ? onClick : void 0, disabled: Component === "button" ? disabled : void 0, style: { "--accent-color": accentColor.startsWith("#") ? accentColor : `var(--brutal-${accentColor.replace("brutal-", "")})` } }, IconComponent && iconPosition === "left" && /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: IconComponent, size: iconSizes[size] }), /* @__PURE__ */ React35__default.default.createElement("span", { className: "select-none" }, children), IconComponent && iconPosition === "right" && !onRemove && /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: IconComponent, size: iconSizes[size] }), onRemove && /* @__PURE__ */ React35__default.default.createElement( "button", { onClick: (e) => { e.stopPropagation(); onRemove(); }, className: chunk7T4KDGYW_js.cn( "ml-1 -mr-1 p-0.5 transition-colors duration-200", "hover:bg-brutal-black/10 rounded", brutal && "hover:bg-accent/20" ), "aria-label": "Remove chip" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaTimes, size: "xs" }) ) ); }; var ChipGroup = ({ children, maxItems, showMore = false, onShowMore, wrap = true, spacing = "normal", brutal = true, className }) => { const spacingClasses = { tight: "gap-1", normal: "gap-2", loose: "gap-3" }; return /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( // Base layout "flex items-center", wrap ? "flex-wrap" : "flex-nowrap overflow-x-auto", spacingClasses[spacing], // Brutal styling brutal && "relative", className ) }, children ); }; var ChipGroupSkeleton = ({ count = 3, brutal = true, className }) => /* @__PURE__ */ React35__default.default.createElement("div", { className: chunk7T4KDGYW_js.cn("flex flex-wrap gap-2 animate-pulse", className) }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React35__default.default.createElement( "div", { key: i, className: chunk7T4KDGYW_js.cn( "h-6 bg-brutal-gray-300 rounded", brutal && "border-2 border-brutal-gray-400", // Random widths for variety i % 3 === 0 && "w-16", i % 3 === 1 && "w-20", i % 3 === 2 && "w-12" ) } ))); // src/components/core/Chip/TechChip.tsx var TechChip = ({ name, icon, color, size = "sm", onClick, brutal = true, showIcon = true, accentColor = "brutal-pink", className }) => { const [rotation, setRotation] = React35.useState(0); const [skew, setSkew] = React35.useState(0); const [mounted, setMounted] = React35.useState(false); React35.useEffect(() => { if (brutal) { setRotation(Math.random() * 4 - 2); setSkew(Math.random() * 4 - 2); } setMounted(true); }, [brutal]); const normalizedName = chunkR74LWSGE_js.normalizeTechName(name); let IconComponent = null; if (showIcon) { if (typeof icon === "string") { IconComponent = chunkR74LWSGE_js.getTechIcon(icon); } else if (typeof icon === "function") { IconComponent = icon; } else { IconComponent = chunkR74LWSGE_js.getTechIcon( `Si${normalizedName.replace(/[^a-zA-Z]/g, "")}` ); } } const chipStyle = brutal && mounted ? { transform: `rotate(${rotation}deg) skewX(${skew}deg)`, transition: "transform 0.3s ease" } : void 0; const handleMouseEnter = (e) => { if (brutal && mounted && e.currentTarget instanceof HTMLElement) { e.currentTarget.style.transform = "rotate(0deg) skewX(0deg) scale(1.05)"; } }; const handleMouseLeave = (e) => { if (brutal && mounted && e.currentTarget instanceof HTMLElement) { e.currentTarget.style.transform = `rotate(${rotation}deg) skewX(${skew}deg) scale(1)`; } }; return /* @__PURE__ */ React35__default.default.createElement( "div", { style: chipStyle, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, className: chunk7T4KDGYW_js.cn("inline-block", brutal && "hover:z-10 relative", className) }, /* @__PURE__ */ React35__default.default.createElement( Chip, { variant: "secondary", size, icon: IconComponent || void 0, onClick, brutal, accentColor, className: chunk7T4KDGYW_js.cn( color, brutal && [ "hover:shadow-brutal-md cursor-default select-none", "transform-gpu will-change-transform" ], !brutal && "hover:scale-105" ) }, normalizedName ) ); }; var TechChipGroup = ({ technologies, size = "sm", maxItems, brutal = true, showIcons = true, accentColor = "brutal-pink", onChipClick, className }) => { const [showAll, setShowAll] = React35.useState(false); const visibleTechs = showAll || !maxItems ? technologies : technologies.slice(0, maxItems); const hasMore = !showAll && !!maxItems && technologies.length > maxItems; return /* @__PURE__ */ React35__default.default.createElement( ChipGroup, { maxItems: showAll ? void 0 : maxItems, showMore: hasMore, onShowMore: () => setShowAll(true), brutal, className }, visibleTechs.map((tech, index) => /* @__PURE__ */ React35__default.default.createElement( TechChip, { key: `${tech.name}-${index}`, name: tech.name, icon: tech.icon, color: tech.color, size, onClick: onChipClick ? () => onChipClick(tech.name) : void 0, brutal, showIcon: showIcons, accentColor } )), hasMore && /* @__PURE__ */ React35__default.default.createElement( Chip, { variant: "ghost", size, onClick: () => setShowAll(true), brutal, accentColor, className: "opacity-70 hover:opacity-100" }, "+", technologies.length - maxItems, " more" ) ); }; var LoadingSpinner = ({ size = "md", className }) => { const sizeClasses = { 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" }; return /* @__PURE__ */ React35__default.default.createElement( "svg", { className: clsx.clsx("animate-spin", sizeClasses[size], className), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ React35__default.default.createElement( "circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" } ), /* @__PURE__ */ React35__default.default.createElement( "path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" } ) ); }; var Modal = ({ isOpen, onClose, title, children, footer, size = "md", variant = "default", brutal = true, closeOnBackdrop = true, closeOnEscape = true, animated = true, accentColor = "brutal-pink", className, ...props }) => { const modalRef = React35.useRef(null); const previousActiveElement = React35.useRef(null); const handleEscape = React35.useCallback( (e) => { if (e.key === "Escape" && closeOnEscape && isOpen) { onClose(); } }, [closeOnEscape, isOpen, onClose] ); const handleBackdropClick = React35.useCallback( (e) => { if (closeOnBackdrop && e.target === e.currentTarget) { onClose(); } }, [closeOnBackdrop, onClose] ); React35.useEffect(() => { if (isOpen) { previousActiveElement.current = document.activeElement; setTimeout(() => { modalRef.current?.focus(); }, 100); document.body.style.overflow = "hidden"; document.addEventListener("keydown", handleEscape); } else { if (previousActiveElement.current) { previousActiveElement.current.focus(); } document.body.style.overflow = "unset"; document.removeEventListener("keydown", handleEscape); } return () => { document.removeEventListener("keydown", handleEscape); document.body.style.overflow = "unset"; }; }, [isOpen, handleEscape]); if (!isOpen) return null; const sizeClasses = { xs: "max-w-xs", sm: "max-w-sm", md: "max-w-md", lg: "max-w-2xl", xl: "max-w-4xl", "2xl": "max-w-6xl", full: "max-w-[95vw]" }; const getVariantClasses = () => { const variants = { default: "bg-brutal-white", success: "bg-brutal-mint/10 border-brutal-mint", warning: "bg-brutal-yellow/10 border-brutal-yellow", danger: "bg-brutal-coral/10 border-brutal-coral", info: "bg-brutal-sky/10 border-brutal-sky" }; return variants[variant]; }; return /* @__PURE__ */ React35__default.default.createElement(React35__default.default.Fragment, null, /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( "fixed inset-0 z-40 bg-brutal-black/50", animated && [ "transition-opacity duration-300", isOpen ? "opacity-100" : "opacity-0" ] ), onClick: handleBackdropClick, "aria-hidden": "true" } ), /* @__PURE__ */ React35__default.default.createElement( "div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 overflow-y-auto", role: "dialog", "aria-modal": "true", "aria-labelledby": "modal-title", "aria-describedby": "modal-description" }, /* @__PURE__ */ React35__default.default.createElement( "div", { ref: modalRef, className: chunk7T4KDGYW_js.cn( // Base styling "w-full max-h-[90vh] flex flex-col relative", sizeClasses[size], getVariantClasses(), // Brutal styling brutal && [ "border-4 border-brutal-black shadow-brutal-lg", animated && [ "transition-all duration-300 transform", "animate-scale-in", "hover:shadow-brutal-xl" ] ], !brutal && [ "rounded-lg shadow-2xl border", animated && "transition-all duration-300 transform animate-scale-in" ], // Focus styles "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2", className ), style: { "--accent-color": accentColor.startsWith("#") ? accentColor : `var(--brutal-${accentColor.replace("brutal-", "")})` }, tabIndex: -1, ...props }, /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( "flex items-center justify-between p-6 flex-shrink-0", brutal && [ "border-b-4 border-brutal-black bg-brutal-black text-brutal-white" ], !brutal && ["border-b bg-brutal-gray-50 rounded-t-lg"] ) }, /* @__PURE__ */ React35__default.default.createElement( "h2", { id: "modal-title", className: chunk7T4KDGYW_js.cn( "font-black uppercase tracking-wider flex-1 min-w-0 truncate", brutal ? "text-brutal-white" : "text-brutal-black", size === "xs" ? "text-lg" : size === "sm" ? "text-xl" : "text-2xl" ) }, title ), /* @__PURE__ */ React35__default.default.createElement( "button", { onClick: onClose, className: chunk7T4KDGYW_js.cn( "p-2 ml-4 flex-shrink-0 transition-all duration-200", brutal ? [ "hover:bg-brutal-white hover:text-brutal-black", "border-2 border-transparent hover:border-brutal-white" ] : [ "hover:bg-brutal-gray-200 rounded-md", "text-brutal-gray-500 hover:text-brutal-black" ], "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent" ), "aria-label": "Close modal", type: "button" }, /* @__PURE__ */ React35__default.default.createElement(chunk7YHHVG7W_js.Icon, { icon: fa.FaTimes, size: "md", brutal: brutal && animated }) ) ), /* @__PURE__ */ React35__default.default.createElement( "div", { id: "modal-description", className: chunk7T4KDGYW_js.cn( "flex-1 overflow-y-auto p-6", "scrollbar-thin scrollbar-track-transparent scrollbar-thumb-brutal-gray-300" ) }, children ), footer && /* @__PURE__ */ React35__default.default.createElement( "div", { className: chunk7T4KDGYW_js.cn( "p-4 flex-shrink-0", brutal && "border-t-4 border-brutal-black bg-brutal-gray-50", !brutal && "border-t bg-brutal-gray-50 rounded-b-lg" ) }, footer ), brutal && animated && /* @__PURE__ */ React35__default.default.createElement("div", { className: "absolute top-0 right-0 w-8 h-8 bg-accent opacity-20 -mr-4 -mt-4 rotate-45"