Skip to content

Commit

Permalink
feat: created SVG document components
Browse files Browse the repository at this point in the history
  • Loading branch information
sametcodes committed Mar 2, 2023
1 parent 66f37a5 commit 12c4ee8
Show file tree
Hide file tree
Showing 17 changed files with 474 additions and 82 deletions.
21 changes: 0 additions & 21 deletions components/codewars/index.ts

This file was deleted.

25 changes: 0 additions & 25 deletions components/github/index.ts

This file was deleted.

83 changes: 83 additions & 0 deletions components/icons/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
export const IssueIcon = () => (
<svg
aria-hidden="true"
height="16"
viewBox="0 0 16 16"
version="1.1"
width="16"
className="icon"
>
<path d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path>
<path
fillRule="evenodd"
d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"
></path>
</svg>
);

export const PullRequestIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M12.7 10.1V5.3C12.7 4.3 12 2.7 10 2.7V1.3l-2.7 2 2.7 2V4c1.2 0 1.3 1 1.3 1.3v4.8c-1 0.3-1.7 1.2-1.6 2.2 0 1.3 1 2.3 2.3 2.4s2.3-1 2.3-2.4c0-1.1-0.7-1.9-1.6-2.2z m-0.7 3.2c-0.6 0-1-0.4-1-1s0.4-1 1-1 1 0.4 1 1-0.4 1-1 1zM6.3 3.7C6.3 2.4 5.3 1.3 4 1.3S1.7 2.4 1.7 3.7c0 1.1 0.7 1.9 1.6 2.2v4.2c-1 0.3-1.7 1.2-1.6 2.2C1.7 13.6 2.7 14.7 4 14.7s2.3-1 2.3-2.4c0-1.1-0.7-1.9-1.6-2.2V5.9C5.6 5.6 6.3 4.7 6.3 3.7z m-3.3 0C3 3.1 3.4 2.7 4 2.7s1 0.4 1 1S4.6 4.7 4 4.7s-1-0.4-1-1z m2 8.6c0 0.6-0.4 1-1 1s-1-0.4-1-1S3.4 11.3 4 11.3s1 0.4 1 1z" />
</svg>
);

export const MergeIcon = () => (
<svg
viewBox="0 0 16 16"
width="16"
height="16"
fill="currentColor"
className="icon"
>
<path d="M1.7 12.3C1.7 13.6 2.7 14.7 4 14.7s2.3-1 2.3-2.4c0-1.1-0.7-1.9-1.6-2.2v-2.3c0.2 0.2 0.3 0.4 0.5 0.5 0.8 0.6 1.7 0.7 2.6 0.7 0.6 0 1.2-0.1 1.7-0.2a2.3 2.3 0 0 0 2.2 1.5c1.3 0 2.3-1 2.3-2.3s-1-2.3-2.3-2.3a2.3 2.3 0 0 0-2.3 1.8c-0.9 0.2-2.4 0.4-3.4-0.3-0.4-0.3-0.7-0.8-0.9-1.5C5.8 5.3 6.3 4.5 6.3 3.7 6.3 2.4 5.3 1.3 4 1.3S1.7 2.4 1.7 3.7c0 1.1 0.7 1.9 1.6 2.2v4.2c-1 0.3-1.7 1.2-1.6 2.2z m10-5.3c0.6 0 1 0.4 1 1s-0.4 1-1 1S10.7 8.6 10.7 8s0.4-1 1-1z m-6.7 5.3c0 0.6-0.4 1-1 1s-1-0.4-1-1S3.4 11.3 4 11.3s1 0.4 1 1z m-2-8.6C3 3.1 3.4 2.7 4 2.7s1 0.4 1 1S4.6 4.7 4 4.7s-1-0.4-1-1z" />
</svg>
);

export const CommitIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M11.3 7.3a3.3 3.3 0 0 0-6.6 0H1.3v1.4h3.4a3.3 3.3 0 0 0 6.6 0H14.7v-1.4h-3.4zM8 10c-1.1 0-2-0.9-2-2s0.9-2 2-2 2 0.9 2 2-0.9 2-2 2z" />
</svg>
);

export const RepositoryIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M12.3 2C13.3 2 14 2.7 14 3.7L14 12.3C14 13.3 13.3 14 12.3 14L3.7 14C2.7 14 2 13.3 2 12.3L2 3.7C2 2.8 2.7 2 3.6 2 3.6 2 6.5 2 12.3 2ZM3.7 2.7C3.1 2.7 2.7 3.1 2.7 3.7L2.7 12.3C2.7 12.9 3.1 13.3 3.7 13.3L12.3 13.3C12.9 13.3 13.3 12.9 13.3 12.3L13.3 3.7C13.3 3.1 12.9 2.7 12.3 2.7L3.7 2.7ZM6.6 9.5C6.7 9.6 6.7 9.8 6.5 9.9 6.4 10 6.2 10 6.1 9.9L4.7 8.2C4.6 8.1 4.6 7.9 4.7 7.8L6.1 6.1C6.2 6 6.4 6 6.5 6.1 6.7 6.2 6.7 6.4 6.6 6.5L5.4 8 6.6 9.5ZM9.4 6.5C9.3 6.4 9.3 6.2 9.5 6.1 9.6 6 9.8 6 9.9 6.1L11.3 7.8C11.4 7.9 11.4 8.1 11.3 8.2L9.9 9.9C9.8 10 9.6 10 9.5 9.9 9.3 9.8 9.3 9.6 9.4 9.5L10.6 8 9.4 6.5Z" />
</svg>
);

export const JavaScriptIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M2 2h12v12H2V2z m11 9.1c-0.1-0.5-0.4-1-1.5-1.4-0.4-0.2-0.8-0.3-0.9-0.6 0-0.2-0.1-0.3 0-0.3 0.1-0.3 0.5-0.4 0.8-0.4 0.2 0.1 0.4 0.2 0.4 0.5 0.5-0.3 0.5-0.3 0.9-0.6-0.1-0.2-0.2-0.3-0.3-0.4-0.3-0.4-0.7-0.5-1.4-0.5l-0.3 0.1c-0.3 0.1-0.7 0.3-0.9 0.5-0.6 0.6-0.4 1.8 0.3 2.2 0.7 0.5 1.7 0.6 1.8 1.1 0.1 0.6-0.4 0.8-1 0.7-0.4-0.1-0.6-0.3-0.9-0.6l-0.9 0.5c0.1 0.2 0.2 0.3 0.4 0.5 0.9 0.9 3 0.8 3.5-0.5 0 0 0.1-0.4 0-0.8l0 0z m-4.5-3.6h-1.1c0 1 0 1.9 0 2.9 0 0.6 0 1.2-0.1 1.4-0.2 0.3-0.6 0.3-0.8 0.2-0.2-0.1-0.3-0.2-0.4-0.4 0-0.1-0.1-0.1 0-0.1l-0.9 0.5c0.2 0.3 0.4 0.6 0.6 0.8 0.4 0.3 1 0.3 1.6 0.2 0.4-0.1 0.7-0.3 0.9-0.7 0.3-0.5 0.2-1 0.2-1.7 0-1 0-2.1 0-3.1l0 0z" />
</svg>
);

export const PythonIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M6.4 7.8h2.9s1.6 0 1.6-1.6V3.6S11.1 2 8 2C4.9 2 5.1 3.3 5.1 3.3l0 1.4h2.9v0.4H3.9s-2-0.2-1.9 2.9 1.7 3 1.7 2.9h1v-1.4s-0.1-1.7 1.7-1.7z m0-3.8a0.5 0.5 0 1 1 0-1.1 0.5 0.5 0 1 1 0 1.1z" />
<path d="M12.3 5h-1v1.4s0.1 1.7-1.7 1.8h-2.9s-1.6 0-1.6 1.5v2.7s-0.2 1.6 2.9 1.5c3 0 2.9-1.3 2.9-1.3l0-1.3h-2.9v-0.5h4.1s2 0.2 1.9-2.8-1.7-3-1.7-3z m-2.7 7a0.5 0.5 0 1 1 0 1 0.5 0.5 0 1 1 0-1z" />
</svg>
);

export const TypeScriptIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M0 0v16h16V0H0z m9.2 6.9H6.9v7.1h-1.2V6.9h-2.3v-1.1h5.8v1.1z m4.7 6.4c-0.8 1-3 1.1-4.3 0.3v-1.6c0.7 0.8 1.4 0.9 2 1 1.7 0.1 1.8-1.3 1.1-2-1-0.8-3.1-1.3-3.1-3.1 0-1.3 1-2.2 2.5-2.2 0.6 0 1.4 0 1.9 0.3v1.5c-1.2-1.1-3.7-0.8-3.1 0.8 0.5 1 2.4 1.1 3.3 2.7 0.3 0.9 0.1 1.7-0.3 2.3z" />
</svg>
);

export const ScoreIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M7.2 2.1a0.4 0.4 0 0 0-0.8-0.2l-0.7 3.7H2.8a0.4 0.4 0 1 0 0 0.8h2.7l-0.6 3.2H2a0.4 0.4 0 0 0 0 0.8h2.7l-0.7 3.5a0.4 0.4 0 1 0 0.8 0.2l0.7-3.7h4L8.8 13.9a0.4 0.4 0 0 0 0.8 0.2l0.7-3.7h2.9a0.4 0.4 0 0 0 0-0.8H10.5l0.7-3.2h2.8a0.4 0.4 0 1 0 0-0.8h-2.7l0.8-3.5a0.4 0.4 0 1 0-0.8-0.2l-0.8 3.7H6.5l0.7-3.5ZM6.3 6.4h4.1l-0.7 3.2H5.7l0.6-3.2Z" />
</svg>
);

export const StarIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M8 1l-2.3 4.6-5.1 0.7 3.7 3.6L3.5 15l4.5-2.4L12.6 15l-0.9-5.1 3.7-3.6-5.1-0.7Z" />
</svg>
);

export const CodeIcon = () => (
<svg viewBox="0 0 16 16" width="16" height="16" className="icon">
<path d="M5.1 12.4L0 8l5.1-4.4 0.8 1L2 8l3.9 3.4-0.8 1z m5.8 0l-0.8-1L14 8 10.1 4.6l0.8-1L16 8 10.9 12.4zM6.9 13.8L5.7 13.4 9.1 2.2 10.3 2.6 6.9 13.8z" />
</svg>
);
21 changes: 0 additions & 21 deletions components/stackoverflow/index.ts

This file was deleted.

39 changes: 39 additions & 0 deletions components/svgs/codewars/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as Icons from "@components/icons";
import {
Document,
DocumentTitle,
List,
ListItem,
} from "@components/svgs/document";
import { ObjectEntries } from "@utils";

export const getUser = (result: any, platform: any) => {
const langs = ObjectEntries(result.ranks.languages).map(([key, value]) => ({
lang: key,
...value,
}));

const langItems = langs.map((lang, index) => (
<ListItem
key={index}
icon={<Icons.CodeIcon />}
text={lang.lang as string}
value={lang.score}
/>
));

return (
<Document width={210} height={200}>
<DocumentTitle>Codewars</DocumentTitle>
<List>
<ListItem icon={<Icons.StarIcon />} text="Honor" value={result.honor} />
<ListItem
icon={<Icons.ScoreIcon />}
text="Overall Score"
value={result.ranks.overall.score}
/>
{langItems}
</List>
</Document>
);
};
194 changes: 194 additions & 0 deletions components/svgs/document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import { ReactElement } from "react";

export const getDocumentStyle = () => {
return `<style>
svg{ border: 1px solid #ccc; border-radius: 10px; }
.header { font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif; fill: #2f80ed; animation: fadeInAnimation 0.8s ease-in-out forwards; }
.stat { text-transform: capitalize; font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: #434d58; }
.stagger { opacity: 0; animation: fadeInAnimation 0.3s ease-in-out forwards; }
.rank-text { font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58; animation: scaleInAnimation 0.3s ease-in-out forwards; }
.not_bold { font-weight: 400 }
.bold { font-weight: 700 }
.icon { fill: #4c71f2; display: block; }
.rank-circle-rim { stroke: #2f80ed; fill: none; stroke-width: 6; opacity: 0.2; }
.rank-circle { stroke: #2f80ed; stroke-dasharray: 250; fill: none; stroke-width: 6; stroke-linecap: round; opacity: 0.8; transform-origin: -10px 8px; transform: rotate(-90deg); animation: rankAnimation 1s forwards ease-in-out; }
@supports(-moz-appearance: auto) { /* Selector detects Firefox */ .header { font-size: 15.5px; } }
@supports(-moz-appearance: auto) { /* Selector detects Firefox */ .stat { font-size:12px; } }
/* Animations */
@keyframes rankAnimation { from { stroke-dashoffset: 251.32741228718345; } to { stroke-dashoffset: 127.57536535528702; } }
@keyframes scaleInAnimation { from { transform: translate(-5px, 5px) scale(0); } to { transform: translate(-5px, 5px) scale(1); } }
@keyframes fadeInAnimation { from { opacity: 0; } to { opacity: 1; } }
</style>`;
};

type IDocument = {
(props: {
width: number;
height: number;
children: JSX.Element | JSX.Element[];
}): JSX.Element;
};

type IDocumentHeader = {
(props: { title: string; desc: string }): JSX.Element;
};

type IDocumentTitle = {
(props: { children: string }): JSX.Element;
};

type IList = {
(props: { children: any }): JSX.Element;
};

export type IListItem = {
(props: IItem): JSX.Element;
};

type IItem = {
icon: JSX.Element;
url?: string;
text: string;
value?: string;
index?: number;
gap?: number;
};

export const Document: IDocument = ({ width, height, children }) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
width={width}
height={height}
>
{getDocumentStyle()}

{/* <DocumentHeader title={title} desc={desc} /> */}
{/* <DocumentBackground /> */}
{children}
</svg>
);
};

export const DocumentTitle: IDocumentTitle = ({ children }) => {
return (
<g data-testid="card-title" transform="translate(25, 35)">
<g transform="translate(0, 0)">
<text x="0" y="0" className="header" data-testid="header">
{children}
</text>
</g>
</g>
);
};

export const DocumentHeader: IDocumentHeader = ({ title, desc }) => {
return (
<>
<title id="titleId">{title}</title>
<desc id="descId">{desc}</desc>
</>
);
};

export const DocumentBackground = () => {
return (
<rect
data-testid="card-bg"
x="0.5"
y="0.5"
rx="4.5"
width="500"
height="120"
stroke="#e4e2e2"
fill="#fffefe"
strokeOpacity="1"
/>
);
};

export const List: IList = ({ children }) => {
if (Array.isArray(children)) children = children.flat();

if (!Array.isArray(children)) children = [children];

const makeTitleShort = (
element: ReactElement<IItem, IListItem>
): JSX.Element => {
return {
...element,
props: {
...element.props,
value:
element.props?.value && String(element.props.value).length > 45
? String(element.props.value).slice(0, 45) + "..."
: String(element.props.value),
},
};
};

const calculateGap = (elements: ReactElement<IItem, IListItem>[]) => {
if (!children) {
return [];
}
const gap =
elements
.map((child) => child.props.text.length * 6.7)
.reduce((a, b) => Math.max(a, b), 0) + 45;
return elements.map((child, index) => ({
...child,
props: { ...child.props, index, gap: gap },
}));
};

children = calculateGap(children.map(makeTitleShort));

return (
<g data-testid="main-card-body" transform="translate(0, 55)">
<svg x="0" y="0">
{children}
</svg>
</g>
);
};

export const ListItem: IListItem = ({
index = 0,
gap = 0,
icon,
text,
value,
url,
}) => {
return (
<g transform={`translate(0, ${index * 25})`}>
<g
className="stagger"
style={{ animationDelay: `${450 + 150 * index}ms` }}
transform="translate(25, 0)"
>
<g className="item-info">
{icon}
<text className="stat bold" x="25" y="12.5">
{text}
</text>
</g>

{url ? (
<a href={url} target="_blank" rel="noopener noreferrer">
<text className="stat bold" x={gap} y="12.5">
{value}
</text>
</a>
) : (
<text className="stat bold" x={gap} y="12.5">
{value}
</text>
)}
</g>
</g>
);
};
Loading

1 comment on commit 12c4ee8

@vercel
Copy link

@vercel vercel bot commented on 12c4ee8 Mar 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.