vue-tweet-pure
Version:
A Vue 3 component for embedding tweets in your Vue.js applications.
812 lines (811 loc) • 31 kB
JavaScript
import { TwitterApiError as e } from "./api.es.js";
import { Fragment as t, computed as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createStaticVNode as s, createTextVNode as c, createVNode as l, defineComponent as u, mergeProps as ee, normalizeClass as d, normalizeStyle as f, onBeforeUnmount as p, onMounted as te, openBlock as m, ref as h, renderList as g, renderSlot as _, resolveDynamicComponent as v, toDisplayString as y, unref as b, useAttrs as ne, useCssModule as re, watch as ie, withCtx as x, withModifiers as ae } from "vue";
//#region src/twitter-theme/tweet-container.vue?vue&type=script&setup=true&lang.ts
var oe = /* @__PURE__ */ u({
__name: "tweet-container",
setup(e) {
let t = ne();
return (e, n) => (m(), a("div", { class: d([
"vue-tweet-theme",
e.$style.root,
b(t).class
]) }, [o("article", { class: d(e.$style.article) }, [_(e.$slots, "default")], 2)], 2));
}
}), se = {
article: "JrPdna_article",
root: "JrPdna_root"
}, S = (e, t) => {
let n = e.__vccOpts || e;
for (let [e, r] of t) n[e] = r;
return n;
}, C = /* @__PURE__ */ S(oe, [["__cssModules", { $style: se }]]), ce = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-not-found",
props: { error: {} },
setup(e) {
return (e, t) => (m(), r(C, null, {
default: x(() => [o("div", { class: d(e.$style.root) }, [...t[0] ||= [o("h3", null, "Tweet not found", -1), o("p", null, "The embedded tweet could not be found…", -1)]], 2)]),
_: 1
}));
}
}), [["__cssModules", { $style: { root: "nN86_W_root" } }]]), le = [
"src",
"alt",
"width",
"height"
], w = /* @__PURE__ */ u({
__name: "avatar-img",
props: {
src: {},
alt: {},
width: {},
height: {}
},
setup(e) {
return (t, n) => (m(), a("img", {
src: e.src,
alt: e.alt,
width: e.width,
height: e.height
}, null, 8, le));
}
}), ue = [
"src",
"alt",
"draggable"
], T = /* @__PURE__ */ u({
__name: "media-img",
props: {
src: {},
alt: {},
draggable: { type: Boolean }
},
setup(e) {
return (t, n) => (m(), a("img", ee(t.$attrs, {
src: e.src,
alt: e.alt,
draggable: e.draggable
}), null, 16, ue));
}
}), E = {
TweetNotFound: ce,
AvatarImg: w,
MediaImg: T
}, D = { verified: "_81i5Cq_verified" }, O = /* @__PURE__ */ u({
__name: "verified",
setup(e) {
return (e, t) => (m(), a("svg", {
viewBox: "0 0 24 24",
"aria-label": "Verified account",
role: "img",
class: d(b(D).verified)
}, [...t[0] ||= [o("g", null, [o("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" })], -1)]], 2));
}
}), k = /* @__PURE__ */ u({
__name: "verified-business",
setup(e) {
return (e, t) => (m(), a("svg", {
viewBox: "0 0 22 22",
"aria-label": "Verified account",
role: "img",
class: d(b(D).verified)
}, [...t[0] ||= [s("<g><linearGradient id=\"0-a\" gradientUnits=\"userSpaceOnUse\" x1=\"4.411\" x2=\"18.083\" y1=\"2.495\" y2=\"21.508\"><stop offset=\"0\" stop-color=\"#f4e72a\"></stop><stop offset=\".539\" stop-color=\"#cd8105\"></stop><stop offset=\".68\" stop-color=\"#cb7b00\"></stop><stop offset=\"1\" stop-color=\"#f4ec26\"></stop><stop offset=\"1\" stop-color=\"#f4e72a\"></stop></linearGradient><linearGradient id=\"0-b\" gradientUnits=\"userSpaceOnUse\" x1=\"5.355\" x2=\"16.361\" y1=\"3.395\" y2=\"19.133\"><stop offset=\"0\" stop-color=\"#f9e87f\"></stop><stop offset=\".406\" stop-color=\"#e2b719\"></stop><stop offset=\".989\" stop-color=\"#e2b719\"></stop></linearGradient><g clip-rule=\"evenodd\" fill-rule=\"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>", 1)]], 2));
}
}), A = /* @__PURE__ */ u({
__name: "verified-government",
setup(e) {
return (e, t) => (m(), a("svg", {
viewBox: "0 0 22 22",
"aria-label": "Verified account",
role: "img",
class: d(b(D).verified)
}, [...t[0] ||= [o("g", null, [o("path", {
"clip-rule": "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",
"fill-rule": "evenodd"
})], -1)]], 2));
}
}), j = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "quoted-tweet-container",
props: { tweet: {} },
setup(e) {
let t = (e) => {
window.open(e, "_blank");
};
return (n, r) => (m(), a("div", {
class: d(n.$style.root),
onClick: r[0] ||= ae((n) => t(e.tweet.url), ["prevent"])
}, [o("article", { class: d(n.$style.article) }, [_(n.$slots, "default")], 2)], 2));
}
}), [["__cssModules", { $style: {
article: "RsfEUq_article",
root: "RsfEUq_root"
} }]]), M = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "verified-badge",
props: { user: {} },
setup(e) {
let t = re(), o = ne(), s = e, c = n(() => s.user.verified || s.user.is_blue_verified || s.user.verified_type), l = n(() => c.value ? s.user.verified_type === "Government" ? A : s.user.verified_type === "Business" ? k : O : null), u = n(() => c.value ? s.user.verified_type === "Government" ? t.verifiedGovernment : s.user.verified_type === "Business" ? null : s.user.is_blue_verified ? t.verifiedBlue : t.verifiedOld : null);
return (e, t) => c.value ? (m(), a("div", {
key: 0,
class: d([b(o).class, u.value])
}, [(m(), r(v(l.value)))], 2)) : i("", !0);
}
}), [["__cssModules", { $style: {
verifiedBlue: "dT-upq_verifiedBlue",
verifiedGovernment: "dT-upq_verifiedGovernment",
verifiedOld: "dT-upq_verifiedOld"
} }]]), de = ["href"], fe = ["title"], pe = ["title"], N = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "quoted-tweet-header",
props: { tweet: {} },
setup(e) {
let { user: t } = e.tweet;
return (n, r) => (m(), a("div", { class: d(n.$style.header) }, [o("a", {
href: e.tweet.url,
class: d(n.$style.avatar),
target: "_blank",
rel: "noopener noreferrer"
}, [o("div", { class: d([n.$style.avatarOverflow, { [n.$style.avatarSquare]: b(t).profile_image_shape === "Square" }]) }, [l(w, {
src: b(t).profile_image_url_https,
alt: b(t).name,
width: 20,
height: 20
}, null, 8, ["src", "alt"])], 2)], 10, de), o("div", { class: d(n.$style.author) }, [
o("div", { class: d(n.$style.authorText) }, [o("span", { title: b(t).name }, y(b(t).name), 9, fe)], 2),
l(M, { user: b(t) }, null, 8, ["user"]),
o("div", { class: d(n.$style.username) }, [o("span", { title: `@${b(t).screen_name}` }, "@" + y(b(t).screen_name), 9, pe)], 2)
], 2)], 2));
}
}), [["__cssModules", { $style: {
author: "_2tBG3G_author",
authorText: "_2tBG3G_authorText",
avatar: "_2tBG3G_avatar",
avatarSquare: "_2tBG3G_avatarSquare",
header: "_2tBG3G_header",
username: "_2tBG3G_username"
} }]]), me = ["lang"], he = ["innerHTML"], P = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "quoted-tweet-body",
props: { tweet: {} },
setup(e) {
return (n, r) => (m(), a("p", {
class: d(n.$style.root),
lang: e.tweet.lang,
dir: "auto"
}, [(m(!0), a(t, null, g(e.tweet.entities, (e, t) => (m(), a("span", {
key: t,
innerHTML: e.text
}, null, 8, he))), 128))], 10, me));
}
}), [["__cssModules", { $style: { root: "_3hXyqa_root" } }]]), F = (e) => `https://x.com/${e.user.screen_name}/status/${e.id_str}`, I = (e) => `https://x.com/${typeof e == "string" ? e : e.user.screen_name}`, ge = (e) => `https://x.com/intent/like?tweet_id=${e.id_str}`, _e = (e) => `https://x.com/intent/tweet?in_reply_to=${e.id_str}`, ve = (e) => `https://x.com/intent/follow?screen_name=${e.user.screen_name}`, ye = (e) => `https://x.com/hashtag/${e.text}`, be = (e) => `https://x.com/search?q=%24${e.text}`, xe = (e) => `https://x.com/${e.in_reply_to_screen_name}/status/${e.in_reply_to_status_id_str}`, L = (e, t) => {
let n = new URL(e.media_url_https), r = n.pathname.split(".").pop();
return r ? (n.pathname = n.pathname.replace(`.${r}`, ""), n.searchParams.set("format", r), n.searchParams.set("name", t), n.toString()) : e.media_url_https;
}, R = (e) => {
let { variants: t } = e.video_info;
return t.filter((e) => e.content_type === "video/mp4").sort((e, t) => (t.bitrate ?? 0) - (e.bitrate ?? 0));
}, z = (e) => {
let t = R(e);
return t.length > 1 ? t[1] : t[0];
}, B = (e) => e > 999999 ? `${(e / 1e6).toFixed(1)}M` : e > 999 ? `${(e / 1e3).toFixed(1)}K` : e.toString();
function V(e) {
let t = Array.from(e.text), n = [{
indices: e.display_text_range,
type: "text"
}];
return H(n, "hashtag", e.entities.hashtags), H(n, "mention", e.entities.user_mentions), H(n, "url", e.entities.urls), H(n, "symbol", e.entities.symbols), e.entities.media && H(n, "media", e.entities.media), Se(e, n), n.map((e) => {
let n = t.slice(e.indices[0], e.indices[1]).join("");
switch (e.type) {
case "hashtag": return Object.assign(e, {
href: ye(e),
text: n
});
case "mention": return Object.assign(e, {
href: I(e.screen_name),
text: n
});
case "url":
case "media": return Object.assign(e, {
href: e.expanded_url,
text: e.display_url
});
case "symbol": return Object.assign(e, {
href: be(e),
text: n
});
default: return Object.assign(e, { text: n });
}
});
}
function H(e, t, n) {
for (let r of n) for (let [n, i] of e.entries()) {
if (i.indices[0] > r.indices[0] || i.indices[1] < r.indices[1]) continue;
let a = [{
...r,
type: t
}];
i.indices[0] < r.indices[0] && a.unshift({
indices: [i.indices[0], r.indices[0]],
type: "text"
}), i.indices[1] > r.indices[1] && a.push({
indices: [r.indices[1], i.indices[1]],
type: "text"
}), e.splice(n, 1, ...a);
break;
}
}
function Se(e, t) {
let n = e.entities.media?.[0];
n && n.indices[0] < e.display_text_range[1] && (e.display_text_range[1] = n.indices[0]);
let r = t.at(-1);
r && r.indices[1] > e.display_text_range[1] && (r.indices[1] = e.display_text_range[1]);
}
var U = (e) => ({
...e,
url: F(e),
user: {
...e.user,
url: I(e),
follow_url: ve(e)
},
like_url: ge(e),
reply_url: _e(e),
in_reply_to_url: e.in_reply_to_screen_name ? xe(e) : void 0,
entities: V(e),
quoted_tweet: e.quoted_tweet ? {
...e.quoted_tweet,
url: F(e.quoted_tweet),
entities: V(e.quoted_tweet)
} : void 0
}), W = {
grid2Columns: "nYjDHW_grid2Columns",
grid2x2: "nYjDHW_grid2x2",
grid3: "nYjDHW_grid3",
image: "nYjDHW_image",
mediaContainer: "nYjDHW_mediaContainer",
mediaLink: "nYjDHW_mediaLink",
mediaWrapper: "nYjDHW_mediaWrapper",
root: "nYjDHW_root",
rounded: "nYjDHW_rounded",
skeleton: "nYjDHW_skeleton"
}, Ce = [
"poster",
"controls",
"tabindex"
], we = ["src", "type"], Te = ["href"], Ee = ["href"], G = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-media-video",
props: {
tweet: {},
media: {}
},
setup(e) {
let n = e, r = h(!0), s = h(!1), c = h(!1), l = z(n.media), u = 0, ee = () => {
u && window.clearTimeout(u), s.value ||= !0, c.value &&= !1;
}, f = () => {
u && window.clearTimeout(u), u = window.setTimeout(() => {
s.value &&= !1, u = 0;
}, 100);
}, p = (e) => {
let t = e.currentTarget.previousElementSibling;
e.preventDefault(), r.value = !1, s.value = !0, t.play(), t.focus();
};
return (n, u) => b(l) ? (m(), a(t, { key: 0 }, [
o("video", {
class: d(b(W).image),
poster: b(L)(e.media, "small"),
controls: !r.value,
muted: "",
preload: "none",
tabindex: r.value ? -1 : 0,
onPlay: ee,
onPause: f,
onEnded: u[0] ||= (e) => c.value = !0
}, [o("source", {
src: b(l).url,
type: b(l).content_type
}, null, 8, we)], 42, Ce),
r.value ? (m(), a("button", {
key: 0,
type: "button",
class: d(n.$style.videoButton),
"aria-label": "View video on X",
onClick: p
}, [(m(), a("svg", {
viewBox: "0 0 24 24",
class: d(n.$style.videoButtonIcon),
"aria-hidden": "true"
}, [...u[1] ||= [o("g", null, [o("path", { d: "M21 12L4 2v20l17-10z" })], -1)]], 2))], 2)) : i("", !0),
!s.value && !c.value ? (m(), a("div", {
key: 1,
class: d(n.$style.watchOnTwitter)
}, [o("a", {
href: e.tweet.url,
class: d(n.$style.anchor),
target: "_blank",
rel: "noopener noreferrer"
}, y(r.value ? "Watch on X" : "Continue watching on X"), 11, Te)], 2)) : i("", !0),
c.value ? (m(), a("a", {
key: 2,
href: e.tweet.url,
class: d([n.$style.anchor, n.$style.viewReplies]),
target: "_blank",
rel: "noopener noreferrer"
}, " View replies ", 10, Ee)) : i("", !0)
], 64)) : i("", !0);
}
}), [["__cssModules", { $style: {
anchor: "rnM63W_anchor",
videoButton: "rnM63W_videoButton",
videoButtonIcon: "rnM63W_videoButtonIcon",
viewReplies: "rnM63W_viewReplies",
watchOnTwitter: "rnM63W_watchOnTwitter"
} }]]), De = ["href"], K = /* @__PURE__ */ u({
__name: "tweet-media",
props: {
tweet: {},
components: {},
quoted: { type: Boolean }
},
setup(e) {
let i = e, s = (e, t) => {
let n = 56.25;
return t === 1 && (n = 100 / e.original_info.width * e.original_info.height), t === 2 && (n *= 2), {
width: e.type === "photo" ? void 0 : "unset",
paddingBottom: `${n}%`
};
}, c = n(() => i.tweet.mediaDetails?.length ?? 0), u = n(() => i.components?.MediaImg ?? T);
return (n, i) => (m(), a("div", { class: d([b(W).root, !e.quoted && b(W).rounded]) }, [o("div", { class: d([
b(W).mediaWrapper,
c.value > 1 && b(W).grid2Columns,
c.value === 3 && b(W).grid3,
c.value > 4 && b(W).grid2x2
]) }, [(m(!0), a(t, null, g(e.tweet.mediaDetails, (n) => (m(), a(t, { key: n.media_url_https }, [n.type === "photo" ? (m(), a("a", {
key: 0,
href: e.tweet.url,
class: d([b(W).mediaContainer, b(W).mediaLink]),
target: "_blank",
rel: "noopener noreferrer"
}, [o("div", {
class: d(b(W).skeleton),
style: f(s(n, c.value))
}, null, 6), (m(), r(v(u.value), {
src: b(L)(n, "small"),
alt: n.ext_alt_text || "Image",
class: d(b(W).image),
draggable: ""
}, null, 8, [
"src",
"alt",
"class"
]))], 10, De)) : (m(), a("div", {
key: 1,
class: d(b(W).mediaContainer)
}, [o("div", {
class: d(b(W).skeleton),
style: f(s(n, c.value))
}, null, 6), l(G, {
tweet: e.tweet,
media: n
}, null, 8, ["tweet", "media"])], 2))], 64))), 128))], 2)], 2));
}
}), q = /* @__PURE__ */ u({
__name: "quoted-tweet",
props: { tweet: {} },
setup(e) {
return (t, n) => (m(), r(j, { tweet: e.tweet }, {
default: x(() => [
l(N, { tweet: e.tweet }, null, 8, ["tweet"]),
l(P, { tweet: e.tweet }, null, 8, ["tweet"]),
e.tweet.mediaDetails?.length ? (m(), r(K, {
key: 0,
tweet: e.tweet,
quoted: ""
}, null, 8, ["tweet"])) : i("", !0)
]),
_: 1
}, 8, ["tweet"]));
}
}), Oe = ["href"], ke = ["href"], Ae = ["title"], je = ["href"], Me = ["title"], Ne = ["href"], Pe = ["href"], J = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-header",
props: {
tweet: {},
components: {}
},
setup(e) {
let t = e, n = t.components?.AvatarImg ?? w, { user: i } = t.tweet;
return (t, s) => (m(), a("div", { class: d(t.$style.header) }, [
o("a", {
href: e.tweet.url,
class: d(t.$style.avatar),
target: "_blank",
rel: "noopener noreferrer"
}, [o("div", { class: d([t.$style.avatarOverflow, { [t.$style.avatarSquare]: b(i).profile_image_shape === "Square" }]) }, [(m(), r(v(b(n)), {
src: b(i).profile_image_url_https,
alt: b(i).name,
width: 48,
height: 48
}, null, 8, ["src", "alt"]))], 2), o("div", { class: d(t.$style.avatarOverflow) }, [o("div", { class: d(t.$style.avatarShadow) }, null, 2)], 2)], 10, Oe),
o("div", { class: d(t.$style.author) }, [o("a", {
href: e.tweet.url,
class: d(t.$style.authorLink),
target: "_blank",
rel: "noopener noreferrer"
}, [o("div", { class: d(t.$style.authorLinkText) }, [o("span", { title: b(i).name }, y(b(i).name), 9, Ae)], 2), l(M, {
user: b(i),
class: d(t.$style.authorVerified)
}, null, 8, ["user", "class"])], 10, ke), o("div", { class: d(t.$style.authorMeta) }, [o("a", {
href: e.tweet.url,
class: d(t.$style.username),
target: "_blank",
rel: "noopener noreferrer"
}, [o("span", { title: `@${b(i).screen_name}` }, "@" + y(b(i).screen_name), 9, Me)], 10, je), o("div", { class: d(t.$style.authorFollow) }, [o("span", { class: d(t.$style.separator) }, "·", 2), o("a", {
href: b(i).follow_url,
class: d(t.$style.follow),
target: "_blank",
rel: "noopener noreferrer"
}, " Follow ", 10, Ne)], 2)], 2)], 2),
o("a", {
href: e.tweet.url,
class: d(t.$style.brand),
target: "_blank",
rel: "noopener noreferrer",
"aria-label": "View on Twitter"
}, [(m(), a("svg", {
viewBox: "0 0 24 24",
"aria-hidden": "true",
class: d(t.$style.twitterIcon)
}, [...s[0] ||= [o("g", null, [o("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" })], -1)]], 2))], 10, Pe)
], 2));
}
}), [["__cssModules", { $style: {
author: "ZbIw1a_author",
authorFollow: "ZbIw1a_authorFollow",
authorLink: "ZbIw1a_authorLink",
authorLinkText: "ZbIw1a_authorLinkText",
authorMeta: "ZbIw1a_authorMeta",
authorVerified: "ZbIw1a_authorVerified",
avatar: "ZbIw1a_avatar",
avatarOverflow: "ZbIw1a_avatarOverflow",
avatarShadow: "ZbIw1a_avatarShadow",
avatarSquare: "ZbIw1a_avatarSquare",
brand: "ZbIw1a_brand",
follow: "ZbIw1a_follow",
header: "ZbIw1a_header",
separator: "ZbIw1a_separator",
twitterIcon: "ZbIw1a_twitterIcon",
username: "ZbIw1a_username"
} }]]), Fe = ["href"], Ie = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-in-reply-to",
props: { tweet: {} },
setup(e) {
return (t, n) => (m(), a("a", {
href: e.tweet.in_reply_to_url,
class: d(t.$style.root),
target: "_blank",
rel: "noopener noreferrer"
}, " Replying to @" + y(e.tweet.in_reply_to_screen_name), 11, Fe));
}
}), [["__cssModules", { $style: { root: "_5nZaGq_root" } }]]), Le = ["href"], Re = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-link",
props: { href: {} },
setup(e) {
return (t, n) => (m(), a("a", {
href: e.href,
class: d(t.$style.root),
target: "_blank",
rel: "noopener noreferrer nofollow"
}, [_(t.$slots, "default")], 10, Le));
}
}), [["__cssModules", { $style: { root: "KevUKq_root" } }]]), ze = ["lang"], Be = ["innerHTML"], Ve = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-body",
props: { tweet: {} },
setup(e) {
let n = (e) => [
"hashtag",
"mention",
"url",
"symbol"
].includes(e.type);
return (o, s) => (m(), a("p", {
class: d(o.$style.root),
lang: e.tweet.lang,
dir: "auto"
}, [(m(!0), a(t, null, g(e.tweet.entities, (e, o) => (m(), a(t, { key: o }, [n(e) ? (m(), r(Re, {
key: 0,
href: e.href
}, {
default: x(() => [c(y(e.text), 1)]),
_: 2
}, 1032, ["href"])) : e.type === "text" ? (m(), a("span", {
key: 1,
innerHTML: e.text
}, null, 8, Be)) : i("", !0)], 64))), 128))], 10, ze));
}
}), [["__cssModules", { $style: { root: "b5eIca_root" } }]]), He = new Intl.DateTimeFormat(navigator.language, {
hour: "numeric",
minute: "2-digit",
hour12: !0,
weekday: "short",
month: "short",
day: "numeric",
year: "numeric"
}), Ue = (e) => {
let t = {};
for (let n of e) t[n.type] = n.value;
return t;
}, We = (e) => {
let t = Ue(He.formatToParts(e));
return `${`${t.hour}:${t.minute} ${t.dayPeriod}`} · ${`${t.month} ${t.day}, ${t.year}`}`;
}, Ge = ["href", "aria-label"], Ke = ["datetime"], qe = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-info-created-at",
props: { tweet: {} },
setup(e) {
let t = new Date(e.tweet.created_at), n = We(t);
return (r, i) => (m(), a("a", {
class: d(r.$style.root),
href: e.tweet.url,
target: "_blank",
rel: "noopener noreferrer",
"aria-label": b(n)
}, [o("time", { datetime: b(t).toISOString() }, y(b(n)), 9, Ke)], 10, Ge));
}
}), [["__cssModules", { $style: { root: "Oh6FCq_root" } }]]), Je = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-info",
props: { tweet: {} },
setup(e) {
return (t, n) => (m(), a("div", { class: d(t.$style.info) }, [l(qe, { tweet: e.tweet }, null, 8, ["tweet"]), o("a", {
class: d(t.$style.infoLink),
href: "https://help.x.com/en/x-for-websites-ads-info-and-privacy",
target: "_blank",
rel: "noopener noreferrer",
"aria-label": "Twitter for Websites, Ads Information and Privacy"
}, [(m(), a("svg", {
viewBox: "0 0 24 24",
"aria-hidden": "true",
class: d(t.$style.infoIcon)
}, [...n[0] ||= [o("g", null, [o("path", { d: "M13.5 8.5c0 .83-.67 1.5-1.5 1.5s-1.5-.67-1.5-1.5S11.17 7 12 7s1.5.67 1.5 1.5zM13 17v-5h-2v5h2zm-1 5.25c5.66 0 10.25-4.59 10.25-10.25S17.66 1.75 12 1.75 1.75 6.34 1.75 12 6.34 22.25 12 22.25zM20.25 12c0 4.56-3.69 8.25-8.25 8.25S3.75 16.56 3.75 12 7.44 3.75 12 3.75s8.25 3.69 8.25 8.25z" })], -1)]], 2))], 2)], 2));
}
}), [["__cssModules", { $style: {
info: "Mff3nG_info",
infoIcon: "Mff3nG_infoIcon",
infoLink: "Mff3nG_infoLink"
} }]]), Y = {
actions: "aX6RRG_actions",
copy: "aX6RRG_copy",
copyIcon: "aX6RRG_copyIcon",
copyIconWrapper: "aX6RRG_copyIconWrapper",
copyText: "aX6RRG_copyText",
like: "aX6RRG_like",
likeCount: "aX6RRG_likeCount",
likeIcon: "aX6RRG_likeIcon",
likeIconWrapper: "aX6RRG_likeIconWrapper",
reply: "aX6RRG_reply",
replyIcon: "aX6RRG_replyIcon",
replyIconWrapper: "aX6RRG_replyIconWrapper",
replyText: "aX6RRG_replyText"
}, Ye = /* @__PURE__ */ u({
__name: "tweet-actions-copy",
props: { tweet: {} },
setup(e) {
let t = e, n = h(!1), r = () => {
navigator.clipboard.writeText(t.tweet.url), n.value = !0;
}, i;
return ie(n, (e) => {
e && (clearTimeout(i), i = setTimeout(() => {
n.value = !1;
}, 6e3));
}), p(() => clearTimeout(i)), (e, t) => (m(), a("button", {
type: "button",
class: d(b(Y).copy),
"aria-label": "Copy link",
onClick: r
}, [o("div", { class: d(b(Y).copyIconWrapper) }, [n.value ? (m(), a("svg", {
key: 0,
viewBox: "0 0 24 24",
class: d(b(Y).copyIcon),
"aria-hidden": "true"
}, [...t[0] ||= [o("g", null, [o("path", { d: "M9.64 18.952l-5.55-4.861 1.317-1.504 3.951 3.459 8.459-10.948L19.4 6.32 9.64 18.952z" })], -1)]], 2)) : (m(), a("svg", {
key: 1,
viewBox: "0 0 24 24",
class: d(b(Y).copyIcon),
"aria-hidden": "true"
}, [...t[1] ||= [o("g", null, [o("path", { d: "M18.36 5.64c-1.95-1.96-5.11-1.96-7.07 0L9.88 7.05 8.46 5.64l1.42-1.42c2.73-2.73 7.16-2.73 9.9 0 2.73 2.74 2.73 7.17 0 9.9l-1.42 1.42-1.41-1.42 1.41-1.41c1.96-1.96 1.96-5.12 0-7.07zm-2.12 3.53l-7.07 7.07-1.41-1.41 7.07-7.07 1.41 1.41zm-12.02.71l1.42-1.42 1.41 1.42-1.41 1.41c-1.96 1.96-1.96 5.12 0 7.07 1.95 1.96 5.11 1.96 7.07 0l1.41-1.41 1.42 1.41-1.42 1.42c-2.73 2.73-7.16 2.73-9.9 0-2.73-2.74-2.73-7.17 0-9.9z" })], -1)]], 2))], 2), o("span", { class: d(b(Y).copyText) }, y(n.value ? "Copied!" : "Copy link"), 3)], 2));
}
}), Xe = ["href", "aria-label"], Ze = ["href"], Qe = /* @__PURE__ */ u({
__name: "tweet-actions",
props: { tweet: {} },
setup(e) {
let t = B(e.tweet.favorite_count);
return (n, r) => (m(), a("div", { class: d(b(Y).actions) }, [
o("a", {
class: d(b(Y).like),
href: e.tweet.like_url,
target: "_blank",
rel: "noopener noreferrer",
"aria-label": `Like. This Tweet has ${b(t)} likes`
}, [o("div", { class: d(b(Y).likeIconWrapper) }, [(m(), a("svg", {
viewBox: "0 0 24 24",
class: d(b(Y).likeIcon),
"aria-hidden": "true"
}, [...r[0] ||= [o("g", null, [o("path", { d: "M20.884 13.19c-1.351 2.48-4.001 5.12-8.379 7.67l-.503.3-.504-.3c-4.379-2.55-7.029-5.19-8.382-7.67-1.36-2.5-1.41-4.86-.514-6.67.887-1.79 2.647-2.91 4.601-3.01 1.651-.09 3.368.56 4.798 2.01 1.429-1.45 3.146-2.1 4.796-2.01 1.954.1 3.714 1.22 4.601 3.01.896 1.81.846 4.17-.514 6.67z" })], -1)]], 2))], 2), o("span", { class: d(b(Y).likeCount) }, y(b(t)), 3)], 10, Xe),
o("a", {
class: d(b(Y).reply),
href: e.tweet.reply_url,
target: "_blank",
rel: "noopener noreferrer",
"aria-label": "Reply to this Tweet on Twitter"
}, [o("div", { class: d(b(Y).replyIconWrapper) }, [(m(), a("svg", {
viewBox: "0 0 24 24",
class: d(b(Y).replyIcon),
"aria-hidden": "true"
}, [...r[1] ||= [o("g", null, [o("path", { d: "M1.751 10c0-4.42 3.584-8 8.005-8h4.366c4.49 0 8.129 3.64 8.129 8.13 0 2.96-1.607 5.68-4.196 7.11l-8.054 4.46v-3.69h-.067c-4.49.1-8.183-3.51-8.183-8.01z" })], -1)]], 2))], 2), o("span", { class: d(b(Y).replyText) }, "Reply", 2)], 10, Ze),
l(Ye, { tweet: e.tweet }, null, 8, ["tweet"])
], 2));
}
}), $e = ["href"], et = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-replies",
props: { tweet: {} },
setup(e) {
let t = e, r = n(() => t.tweet.conversation_count === 0 ? "Read more on X" : t.tweet.conversation_count === 1 ? `Read ${B(t.tweet.conversation_count)} reply` : `Read ${B(t.tweet.conversation_count)} replies`);
return (t, n) => (m(), a("div", { class: d(t.$style.replies) }, [o("a", {
class: d(t.$style.link),
href: e.tweet.url,
target: "_blank",
rel: "noopener noreferrer"
}, [o("span", { class: d(t.$style.text) }, y(r.value), 3)], 10, $e)], 2));
}
}), [["__cssModules", { $style: {
link: "ykg4nq_link",
replies: "ykg4nq_replies",
text: "ykg4nq_text"
} }]]), X = /* @__PURE__ */ u({
__name: "embedded-tweet",
props: {
tweet: {},
components: {}
},
setup(e) {
let t = e, a = n(() => U(t.tweet));
return (t, n) => (m(), r(C, null, {
default: x(() => [
l(J, {
tweet: a.value,
components: e.components
}, null, 8, ["tweet", "components"]),
a.value.in_reply_to_status_id_str ? (m(), r(Ie, {
key: 0,
tweet: a.value
}, null, 8, ["tweet"])) : i("", !0),
l(Ve, { tweet: a.value }, null, 8, ["tweet"]),
a.value.mediaDetails?.length ? (m(), r(K, {
key: 1,
tweet: a.value,
components: e.components
}, null, 8, ["tweet", "components"])) : i("", !0),
a.value.quoted_tweet ? (m(), r(b(q), {
key: 2,
tweet: a.value.quoted_tweet
}, null, 8, ["tweet"])) : i("", !0),
l(Je, { tweet: a.value }, null, 8, ["tweet"]),
l(Qe, { tweet: a.value }, null, 8, ["tweet"]),
l(et, { tweet: a.value }, null, 8, ["tweet"])
]),
_: 1
}));
}
}), Z = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "skeleton",
props: { style: {} },
setup(e) {
return (t, n) => (m(), a("span", {
class: d(t.$style.skeleton),
style: f(e.style)
}, null, 6));
}
}), [["__cssModules", { $style: {
loading: "l4VFjW_loading",
skeleton: "l4VFjW_skeleton"
} }]]), tt = /* @__PURE__ */ S(/* @__PURE__ */ u({
__name: "tweet-skeleton",
setup(e) {
return (e, t) => (m(), r(C, { class: d(e.$style.root) }, {
default: x(() => [
l(Z, { style: {
height: "3rem",
marginBottom: "0.75rem"
} }),
l(Z, { style: {
height: "6rem",
margin: "0.5rem 0"
} }),
t[0] ||= o("div", { style: {
borderTop: "var(--tweet-border)",
margin: "0.5rem 0"
} }, null, -1),
l(Z, { style: { height: "2rem" } }),
l(Z, { style: {
height: "2rem",
borderRadius: "9999px",
marginTop: "0.5rem"
} })
]),
_: 1
}, 8, ["class"]));
}
}), [["__cssModules", { $style: { root: "Wi8Y9q_root" } }]]);
//#endregion
//#region src/composables/useTweet.ts
async function nt(t, n) {
let r = await fetch(t, n), i = await r.json();
if (r.ok) return i.data || null;
throw new e({
message: `Failed to fetch tweet at "${t}" with "${r.status}".`,
data: i,
status: r.status
});
}
var Q = /* @__PURE__ */ new Map();
function rt() {
Q.clear();
}
function it(e, t) {
let n = Q.get(e);
if (n) return n;
let r = nt(e, t).catch((t) => {
throw Q.delete(e), t;
});
return Q.set(e, r), r;
}
function $(e, t, n) {
let r = h(!0), i = h(), a = h(null), o = async () => {
if (!t && !e) {
r.value = !1;
return;
}
try {
i.value = await it(`${t}/${e}`, n);
} catch (e) {
a.value = e;
} finally {
r.value = !1;
}
};
return te(() => {
o();
}), {
isLoading: r,
data: i,
error: a
};
}
function at() {
let e = h(!1);
return te(() => {
e.value = !0;
}), e;
}
//#endregion
//#region src/tweet.vue
var ot = /* @__PURE__ */ u({
__name: "tweet",
props: {
id: {},
apiUrl: { default: "https://react-tweet.vercel.app/api/tweet" },
fallback: { default: tt },
components: { default: () => E },
fetchOptions: { default: () => ({}) },
onError: {
type: Function,
default: (e) => e
}
},
setup(e) {
let n = e, { isLoading: i, data: o, error: s } = $(n.id, n.apiUrl, n.fetchOptions);
return (n, c) => b(i) ? (m(), r(b(e.fallback), { key: 0 })) : (m(), a(t, { key: 1 }, [b(s) || !b(o) ? (m(), r(v(e.components.TweetNotFound), {
key: 0,
error: e.onError(b(s))
}, null, 8, ["error"])) : (m(), r(b(X), {
key: 1,
tweet: b(o),
components: e.components
}, null, 8, ["tweet", "components"]))], 64));
}
});
//#endregion
export { X as EmbeddedTweet, q as QuotedTweet, P as QuotedTweetBody, j as QuotedTweetContainer, N as QuotedTweetHeader, ot as Tweet, Qe as TweetActions, Ye as TweetActionsCopy, Ve as TweetBody, C as TweetContainer, J as TweetHeader, Ie as TweetInReplyTo, Je as TweetInfo, qe as TweetInfoCreatedAt, Re as TweetLink, K as TweetMedia, G as TweetMediaVideo, ce as TweetNotFound, et as TweetReplies, tt as TweetSkeleton, O as Verified, k as VerifiedBusiness, A as VerifiedGovernment, it as cachedFetcher, rt as clearCache, E as defaultTwitterComponents, U as enrichTweet, B as formatNumber, L as getMediaUrl, z as getMp4Video, R as getMp4Videos, at as useMounted, $ as useTweet };