Profile page UI and functionality implemented
This commit is contained in:
@@ -1,19 +1,56 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import ContentCopyIcon from "./icon/content_copy.svg";
|
||||
import EditIcon from "./icon/edit.svg";
|
||||
import ExclamationIcon from "./icon/exclamation.svg";
|
||||
import ChevronRightIcon from "./icon/chevron_right.svg";
|
||||
import LogOutIcon from "./icon/log_out.svg";
|
||||
import MailIcon from "./icon/mail.svg";
|
||||
import WarningIcon from "./icon/warning.svg";
|
||||
|
||||
export type IconName = "exclamation";
|
||||
export const ICON_NAME_OPTIONS = [
|
||||
"chevron_right",
|
||||
"content_copy",
|
||||
"edit",
|
||||
"exclamation",
|
||||
"log_out",
|
||||
"mail",
|
||||
"warning",
|
||||
] as const;
|
||||
|
||||
export type IconName = (typeof ICON_NAME_OPTIONS)[number];
|
||||
|
||||
type SvgComponent =
|
||||
| React.ComponentType<React.SVGProps<SVGSVGElement>>
|
||||
| { default: React.ComponentType<React.SVGProps<SVGSVGElement>> };
|
||||
|
||||
/** SVG import may be a React component or a module object { default: Component } (e.g. with Turbopack) */
|
||||
const iconMap: Record<
|
||||
IconName,
|
||||
| React.ComponentType<React.SVGProps<SVGSVGElement>>
|
||||
| { default: React.ComponentType<React.SVGProps<SVGSVGElement>> }
|
||||
> = {
|
||||
const iconMap: Record<IconName, SvgComponent> = {
|
||||
chevron_right: ChevronRightIcon,
|
||||
content_copy: ContentCopyIcon,
|
||||
edit: EditIcon,
|
||||
exclamation: ExclamationIcon,
|
||||
log_out: LogOutIcon,
|
||||
mail: MailIcon,
|
||||
warning: WarningIcon,
|
||||
};
|
||||
|
||||
function resolveSvgComponent(module: SvgComponent) {
|
||||
if (
|
||||
typeof module === "object" &&
|
||||
module !== null &&
|
||||
"default" in module
|
||||
) {
|
||||
return (
|
||||
module as {
|
||||
default: React.ComponentType<React.SVGProps<SVGSVGElement>>;
|
||||
}
|
||||
).default;
|
||||
}
|
||||
return module as React.ComponentType<React.SVGProps<SVGSVGElement>>;
|
||||
}
|
||||
|
||||
export interface IconProps {
|
||||
name: IconName;
|
||||
className?: string;
|
||||
@@ -30,18 +67,26 @@ function IconComponent({
|
||||
}: IconProps) {
|
||||
const SvgModule = iconMap[name];
|
||||
if (!SvgModule) return null;
|
||||
// Turbopack/bundler may expose SVG as { default: Component } instead of the component directly
|
||||
const Svg =
|
||||
typeof SvgModule === "object" &&
|
||||
SvgModule !== null &&
|
||||
"default" in SvgModule
|
||||
? (
|
||||
SvgModule as {
|
||||
default: React.ComponentType<React.SVGProps<SVGSVGElement>>;
|
||||
}
|
||||
).default
|
||||
: (SvgModule as React.ComponentType<React.SVGProps<SVGSVGElement>>);
|
||||
if (typeof Svg !== "function") return null;
|
||||
const resolved = resolveSvgComponent(SvgModule);
|
||||
|
||||
// Turbopack/webpack mismatch: `.svg` may be a URL string instead of SVGR output.
|
||||
if (typeof resolved === "string") {
|
||||
return (
|
||||
<img
|
||||
src={resolved}
|
||||
width={size}
|
||||
height={size}
|
||||
className={className}
|
||||
alt=""
|
||||
aria-hidden={ariaHidden}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (resolved == null) return null;
|
||||
|
||||
const Svg = resolved as React.ComponentType<React.SVGProps<SVGSVGElement>>;
|
||||
|
||||
return (
|
||||
<Svg
|
||||
width={size}
|
||||
|
||||
Reference in New Issue
Block a user