aboutsummaryrefslogtreecommitdiff
path: root/apps/web/components
diff options
context:
space:
mode:
authorDhravya <[email protected]>2024-07-01 20:12:56 -0500
committerDhravya <[email protected]>2024-07-01 20:12:56 -0500
commit2c6a96e96f49439853f68ff18d1502cac04d618c (patch)
treec4b541c4ba21bf1b404722d714d5ab32a2644d90 /apps/web/components
parentfix link (diff)
downloadsupermemory-2c6a96e96f49439853f68ff18d1502cac04d618c.tar.xz
supermemory-2c6a96e96f49439853f68ff18d1502cac04d618c.zip
spaces function
Diffstat (limited to 'apps/web/components')
-rw-r--r--apps/web/components/twitter/icons/icons.module.css9
-rw-r--r--apps/web/components/twitter/icons/index.ts3
-rw-r--r--apps/web/components/twitter/icons/verified-business.tsx53
-rw-r--r--apps/web/components/twitter/icons/verified-government.tsx18
-rw-r--r--apps/web/components/twitter/icons/verified.tsx14
-rw-r--r--apps/web/components/twitter/render-tweet.tsx117
-rw-r--r--apps/web/components/twitter/tweet-header.module.css96
-rw-r--r--apps/web/components/twitter/verified-badge.module.css10
-rw-r--r--apps/web/components/twitter/verified-badge.tsx34
9 files changed, 354 insertions, 0 deletions
diff --git a/apps/web/components/twitter/icons/icons.module.css b/apps/web/components/twitter/icons/icons.module.css
new file mode 100644
index 00000000..aca493e6
--- /dev/null
+++ b/apps/web/components/twitter/icons/icons.module.css
@@ -0,0 +1,9 @@
+.verified {
+ margin-left: 0.125rem;
+ max-width: 20px;
+ max-height: 20px;
+ height: 1.25em;
+ fill: currentColor;
+ user-select: none;
+ vertical-align: text-bottom;
+}
diff --git a/apps/web/components/twitter/icons/index.ts b/apps/web/components/twitter/icons/index.ts
new file mode 100644
index 00000000..f90ec616
--- /dev/null
+++ b/apps/web/components/twitter/icons/index.ts
@@ -0,0 +1,3 @@
+export * from "./verified";
+export * from "./verified-business";
+export * from "./verified-government";
diff --git a/apps/web/components/twitter/icons/verified-business.tsx b/apps/web/components/twitter/icons/verified-business.tsx
new file mode 100644
index 00000000..06d574bd
--- /dev/null
+++ b/apps/web/components/twitter/icons/verified-business.tsx
@@ -0,0 +1,53 @@
+import s from "./icons.module.css";
+
+export const VerifiedBusiness = () => (
+ <svg
+ viewBox="0 0 22 22"
+ aria-label="Verified account"
+ role="img"
+ className={s.verified}
+ >
+ <g>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ id="0-a"
+ x1="4.411"
+ x2="18.083"
+ y1="2.495"
+ y2="21.508"
+ >
+ <stop offset="0" stopColor="#f4e72a"></stop>
+ <stop offset=".539" stopColor="#cd8105"></stop>
+ <stop offset=".68" stopColor="#cb7b00"></stop>
+ <stop offset="1" stopColor="#f4ec26"></stop>
+ <stop offset="1" stopColor="#f4e72a"></stop>
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ id="0-b"
+ x1="5.355"
+ x2="16.361"
+ y1="3.395"
+ y2="19.133"
+ >
+ <stop offset="0" stopColor="#f9e87f"></stop>
+ <stop offset=".406" stopColor="#e2b719"></stop>
+ <stop offset=".989" stopColor="#e2b719"></stop>
+ </linearGradient>
+ <g clipRule="evenodd" fillRule="evenodd">
+ <path
+ d="M13.324 3.848L11 1.6 8.676 3.848l-3.201-.453-.559 3.184L2.06 8.095 3.48 11l-1.42 2.904 2.856 1.516.559 3.184 3.201-.452L11 20.4l2.324-2.248 3.201.452.559-3.184 2.856-1.516L18.52 11l1.42-2.905-2.856-1.516-.559-3.184zm-7.09 7.575l3.428 3.428 5.683-6.206-1.347-1.247-4.4 4.795-2.072-2.072z"
+ fill="url(#0-a)"
+ ></path>
+ <path
+ d="M13.101 4.533L11 2.5 8.899 4.533l-2.895-.41-.505 2.88-2.583 1.37L4.2 11l-1.284 2.627 2.583 1.37.505 2.88 2.895-.41L11 19.5l2.101-2.033 2.895.41.505-2.88 2.583-1.37L17.8 11l1.284-2.627-2.583-1.37-.505-2.88zm-6.868 6.89l3.429 3.428 5.683-6.206-1.347-1.247-4.4 4.795-2.072-2.072z"
+ fill="url(#0-b)"
+ ></path>
+ <path
+ d="M6.233 11.423l3.429 3.428 5.65-6.17.038-.033-.005 1.398-5.683 6.206-3.429-3.429-.003-1.405.005.003z"
+ fill="#d18800"
+ ></path>
+ </g>
+ </g>
+ </svg>
+);
diff --git a/apps/web/components/twitter/icons/verified-government.tsx b/apps/web/components/twitter/icons/verified-government.tsx
new file mode 100644
index 00000000..601a6910
--- /dev/null
+++ b/apps/web/components/twitter/icons/verified-government.tsx
@@ -0,0 +1,18 @@
+import s from "./icons.module.css";
+
+export const VerifiedGovernment = () => (
+ <svg
+ viewBox="0 0 22 22"
+ aria-label="Verified account"
+ role="img"
+ className={s.verified}
+ >
+ <g>
+ <path
+ clipRule="evenodd"
+ d="M12.05 2.056c-.568-.608-1.532-.608-2.1 0l-1.393 1.49c-.284.303-.685.47-1.1.455L5.42 3.932c-.832-.028-1.514.654-1.486 1.486l.069 2.039c.014.415-.152.816-.456 1.1l-1.49 1.392c-.608.568-.608 1.533 0 2.101l1.49 1.393c.304.284.47.684.456 1.1l-.07 2.038c-.027.832.655 1.514 1.487 1.486l2.038-.069c.415-.014.816.152 1.1.455l1.392 1.49c.569.609 1.533.609 2.102 0l1.393-1.49c.283-.303.684-.47 1.099-.455l2.038.069c.832.028 1.515-.654 1.486-1.486L18 14.542c-.015-.415.152-.815.455-1.099l1.49-1.393c.608-.568.608-1.533 0-2.101l-1.49-1.393c-.303-.283-.47-.684-.455-1.1l.068-2.038c.029-.832-.654-1.514-1.486-1.486l-2.038.07c-.415.013-.816-.153-1.1-.456zm-5.817 9.367l3.429 3.428 5.683-6.206-1.347-1.247-4.4 4.795-2.072-2.072z"
+ fillRule="evenodd"
+ ></path>
+ </g>
+ </svg>
+);
diff --git a/apps/web/components/twitter/icons/verified.tsx b/apps/web/components/twitter/icons/verified.tsx
new file mode 100644
index 00000000..81c9fc25
--- /dev/null
+++ b/apps/web/components/twitter/icons/verified.tsx
@@ -0,0 +1,14 @@
+import s from "./icons.module.css";
+
+export const Verified = () => (
+ <svg
+ viewBox="0 0 24 24"
+ aria-label="Verified account"
+ role="img"
+ className={s.verified}
+ >
+ <g>
+ <path d="M22.25 12c0-1.43-.88-2.67-2.19-3.34.46-1.39.2-2.9-.81-3.91s-2.52-1.27-3.91-.81c-.66-1.31-1.91-2.19-3.34-2.19s-2.67.88-3.33 2.19c-1.4-.46-2.91-.2-3.92.81s-1.26 2.52-.8 3.91c-1.31.67-2.2 1.91-2.2 3.34s.89 2.67 2.2 3.34c-.46 1.39-.21 2.9.8 3.91s2.52 1.26 3.91.81c.67 1.31 1.91 2.19 3.34 2.19s2.68-.88 3.34-2.19c1.39.45 2.9.2 3.91-.81s1.27-2.52.81-3.91c1.31-.67 2.19-1.91 2.19-3.34zm-11.71 4.2L6.8 12.46l1.41-1.42 2.26 2.26 4.8-5.23 1.47 1.36-6.2 6.77z"></path>
+ </g>
+ </svg>
+);
diff --git a/apps/web/components/twitter/render-tweet.tsx b/apps/web/components/twitter/render-tweet.tsx
new file mode 100644
index 00000000..9d6d1a8a
--- /dev/null
+++ b/apps/web/components/twitter/render-tweet.tsx
@@ -0,0 +1,117 @@
+import type { Tweet } from "react-tweet/api";
+import {
+ type TwitterComponents,
+ TweetContainer,
+ TweetInReplyTo,
+ TweetBody,
+ TweetMedia,
+ TweetInfo,
+ QuotedTweet,
+ enrichTweet,
+ EnrichedTweet,
+} from "react-tweet";
+import clsx from "clsx";
+import s from "./tweet-header.module.css";
+import { VerifiedBadge } from "./verified-badge";
+
+type Props = {
+ tweet: Tweet;
+ components?: TwitterComponents;
+};
+
+type AvatarImgProps = {
+ src: string;
+ alt: string;
+ width: number;
+ height: number;
+};
+const AvatarImg = (props: AvatarImgProps) => <img {...props} />;
+
+const TweetHeader = ({
+ tweet,
+ components,
+}: {
+ tweet: EnrichedTweet;
+ components?: TwitterComponents;
+}) => {
+ const Img = components?.AvatarImg ?? AvatarImg;
+ const { user } = tweet;
+
+ return (
+ <div className={s.header}>
+ <a
+ href={tweet.url}
+ className={s.avatar}
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <div
+ className={clsx(
+ s.avatarOverflow,
+ user.profile_image_shape === "Square" && s.avatarSquare,
+ )}
+ >
+ <Img
+ src={user.profile_image_url_https}
+ alt={user.name}
+ width={48}
+ height={48}
+ />
+ </div>
+ <div className={s.avatarOverflow}>
+ <div className={s.avatarShadow}></div>
+ </div>
+ </a>
+ <div className={s.author}>
+ <a
+ href={tweet.url}
+ className={s.authorLink}
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <div className={s.authorLinkText}>
+ <span title={user.name}>{user.name}</span>
+ </div>
+ <VerifiedBadge user={user} className={s.authorVerified} />
+ </a>
+ <div className={s.authorMeta}>
+ <a
+ href={tweet.url}
+ className={s.username}
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <span title={`@${user.screen_name}`}>@{user.screen_name}</span>
+ </a>
+ <div className={s.authorFollow}>
+ <span className={s.separator}>ยท</span>
+ <a
+ href={user.follow_url}
+ className={s.follow}
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ Follow
+ </a>
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+};
+
+export const MyTweet = ({ tweet: t, components }: Props) => {
+ const tweet = enrichTweet(t);
+ return (
+ <TweetContainer className="bg-transparent !m-0 !p-0 !z-0">
+ <TweetHeader tweet={tweet} components={components} />
+ {tweet.in_reply_to_status_id_str && <TweetInReplyTo tweet={tweet} />}
+ <TweetBody tweet={tweet} />
+ {tweet.mediaDetails?.length ? (
+ <TweetMedia tweet={tweet} components={components} />
+ ) : null}
+ {tweet.quoted_tweet && <QuotedTweet tweet={tweet.quoted_tweet} />}
+ <TweetInfo tweet={tweet} />
+ </TweetContainer>
+ );
+};
diff --git a/apps/web/components/twitter/tweet-header.module.css b/apps/web/components/twitter/tweet-header.module.css
new file mode 100644
index 00000000..2ce994e2
--- /dev/null
+++ b/apps/web/components/twitter/tweet-header.module.css
@@ -0,0 +1,96 @@
+.header {
+ display: flex;
+ padding-bottom: 0.75rem;
+ line-height: var(--tweet-header-line-height);
+ font-size: var(--tweet-header-font-size);
+ white-space: nowrap;
+ overflow-wrap: break-word;
+ overflow: hidden;
+}
+
+.avatar {
+ position: relative;
+ height: 48px;
+ width: 48px;
+}
+.avatarOverflow {
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ overflow: hidden;
+ border-radius: 9999px;
+}
+.avatarSquare {
+ border-radius: 4px;
+}
+.avatarShadow {
+ height: 100%;
+ width: 100%;
+ transition-property: background-color;
+ transition-duration: 0.2s;
+ box-shadow: rgb(0 0 0 / 3%) 0px 0px 2px inset;
+}
+.avatarShadow:hover {
+ background-color: rgba(26, 26, 26, 0.15);
+}
+
+.author {
+ max-width: calc(100% - 84px);
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ margin: 0 0.5rem;
+}
+.authorLink {
+ text-decoration: none;
+ color: inherit;
+ display: flex;
+ align-items: center;
+}
+.authorLink:hover {
+ text-decoration-line: underline;
+}
+.authorVerified {
+ display: inline-flex;
+}
+.authorLinkText {
+ font-weight: 700;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+.authorMeta {
+ display: flex;
+}
+.authorFollow {
+ display: flex;
+}
+.username {
+ color: var(--tweet-font-color-secondary);
+ text-decoration: none;
+ text-overflow: ellipsis;
+}
+.follow {
+ color: var(--tweet-color-blue-secondary);
+ text-decoration: none;
+ font-weight: 700;
+}
+.follow:hover {
+ text-decoration-line: underline;
+}
+.separator {
+ padding: 0 0.25rem;
+}
+
+.brand {
+ margin-inline-start: auto;
+}
+
+.twitterIcon {
+ width: 23.75px;
+ height: 23.75px;
+ color: var(--tweet-twitter-icon-color);
+ fill: currentColor;
+ user-select: none;
+}
diff --git a/apps/web/components/twitter/verified-badge.module.css b/apps/web/components/twitter/verified-badge.module.css
new file mode 100644
index 00000000..c16e77ec
--- /dev/null
+++ b/apps/web/components/twitter/verified-badge.module.css
@@ -0,0 +1,10 @@
+.verifiedOld {
+ color: var(--tweet-verified-old-color);
+}
+.verifiedBlue {
+ color: var(--tweet-verified-blue-color);
+}
+.verifiedGovernment {
+ /* color: var(--tweet-verified-government-color); */
+ color: rgb(130, 154, 171);
+}
diff --git a/apps/web/components/twitter/verified-badge.tsx b/apps/web/components/twitter/verified-badge.tsx
new file mode 100644
index 00000000..daa11852
--- /dev/null
+++ b/apps/web/components/twitter/verified-badge.tsx
@@ -0,0 +1,34 @@
+import clsx from "clsx";
+import { Verified, VerifiedBusiness, VerifiedGovernment } from "./icons/index";
+import s from "./verified-badge.module.css";
+
+type Props = {
+ user: any;
+ className?: string;
+};
+
+export const VerifiedBadge = ({ user, className }: Props) => {
+ const verified = user.verified || user.is_blue_verified || user.verified_type;
+ let icon = <Verified />;
+ let iconClassName: string | null = s.verifiedBlue ?? null;
+
+ if (verified) {
+ if (!user.is_blue_verified) {
+ iconClassName = s.verifiedOld!;
+ }
+ switch (user.verified_type) {
+ case "Government":
+ icon = <VerifiedGovernment />;
+ iconClassName = s.verifiedGovernment!;
+ break;
+ case "Business":
+ icon = <VerifiedBusiness />;
+ iconClassName = null;
+ break;
+ }
+ }
+
+ return verified ? (
+ <div className={clsx(className, iconClassName)}>{icon}</div>
+ ) : null;
+};